Class UnusedLocalVariableCheck
java.lang.Object
com.puppycrawl.tools.checkstyle.AbstractAutomaticBean
com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter
com.puppycrawl.tools.checkstyle.api.AbstractCheck
com.puppycrawl.tools.checkstyle.checks.coding.UnusedLocalVariableCheck
- All Implemented Interfaces:
Configurable,Contextualizable
Checks that a local variable is declared and/or assigned, but not used.
Doesn't support
pattern variables yet.
Doesn't check
array components as array
components are classified as different kind of variables by
JLS.
- Since:
- 9.3
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final classMaintains information about the type declaration.private static final classMaintains information about the variable.Nested classes/interfaces inherited from class com.puppycrawl.tools.checkstyle.AbstractAutomaticBean
AbstractAutomaticBean.OutputStreamOptions -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate booleanAllow variables named with a single underscore (known as unnamed variables in Java 21+).private final Map<DetailAST,UnusedLocalVariableCheck.TypeDeclDesc> Maps local anonymous inner class to the TypeDeclDesc object containing it.Set of tokens of typeANONYMOUS_CLASS_PARENT_TOKENSandTokenTypes.LAMBDAin some cases.private static final int[]An array of blocks in which local anon inner classes can exist.private intDepth at which a type declaration is nested, 0 for top level type declarations.private static final int[]An array of increment and decrement tokens.private static final int[]An array of token types that indicate a variable is being used within an expression involving increment or decrement operators, or within a switch statement.static final StringA key is pointing to the warning message text in "messages.properties" file.static final StringA key is pointing to the warning message text in "messages.properties" file.private static final StringPackage separator.private StringName of the package.private static final int[]An array of scope tokens.private final Deque<UnusedLocalVariableCheck.TypeDeclDesc>Keeps track of all the type declarations present in the file.private final Map<DetailAST,UnusedLocalVariableCheck.TypeDeclDesc> Maps type declaration ast to their respective TypeDeclDesc objects.private static final int[]An array of unacceptable children of ast of typeTokenTypes.DOT.private static final int[]An array of unacceptable parent of ast of typeTokenTypes.IDENT.private final Deque<UnusedLocalVariableCheck.VariableDesc>Keeps tracks of the variables declared in file. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate voidaddInstanceOrClassVar(DetailAST varDefAst) Add instance variables and class variables to theUnusedLocalVariableCheck.TypeDeclDesc.instanceAndClassVarStack.private static voidaddLocalVariables(DetailAST varDefAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Add local variables to thevariablesStackstack.voidCalled before the starting to process a tree.private static intcalculateTypeDeclarationDistance(String outerTypeName, UnusedLocalVariableCheck.TypeDeclDesc firstType, UnusedLocalVariableCheck.TypeDeclDesc secondType) Get the difference between type declaration name matching count.private static voidcheckIdentifierAst(DetailAST identAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Checks the identifier ast.private static intcountMatchingQualifierChars(String pattern, String candidate) Calculates the type declaration matching count for the superclass of an anonymous inner class.private voidcustomLeaveToken(DetailAST ast, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Leave all ast nodes underanonInnerClassHoldersonce again.private voidcustomVisitToken(DetailAST ast, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Visit all ast nodes underanonInnerClassHoldersonce again.private static DetailASTfindScopeOfVariable(DetailAST variableDef) Find the scope of variable.int[]The configurable token set.private static DetailASTgetBlockContainingLocalAnonInnerClass(DetailAST literalNewAst) Get the block containing local anon inner class.private static UnusedLocalVariableCheck.TypeDeclDescgetClosestMatchingTypeDeclaration(String outerTypeDeclName, List<UnusedLocalVariableCheck.TypeDeclDesc> typeDeclWithSameName) For all type declarations with the same name as the superclass, gets the nearest type declaration.int[]Returns the default token a check is interested in.private StringgetQualifiedTypeDeclarationName(DetailAST typeDeclAst) Get qualified type declaration name from type ast.int[]The tokens that this check must be registered for.getSuperClassOfAnonInnerClass(DetailAST literalNewAst) Get theUnusedLocalVariableCheck.TypeDeclDescof the super class of anonymous inner class.private booleanhasSameNameAsSuperClass(String superClassName, UnusedLocalVariableCheck.TypeDeclDesc typeDeclDesc) Whether the qualified name oftypeDeclDescmatches the super class name.private static booleanA variable with increment or decrement operator is considered used if it is used as an argument or as an array index or for assigning value to a variable.private static booleanisInsideLocalAnonInnerClass(DetailAST literalNewAst) Whether ast node of typeTokenTypes.LITERAL_NEWis a part of a local anonymous inner class.private static booleanisLeftHandSideValue(DetailAST identAst) Checks whether the ast of typeTokenTypes.IDENTis used as left-hand side value.private static booleanisNonLocalTypeDeclaration(DetailAST typeDeclAst) Whether a type declaration is non-local.private static booleanisPrivateInstanceVariable(DetailAST varDefAst) Whether instance variable or class variable have private access modifier.private static booleanisStandAloneIncrementOrDecrement(DetailAST identAst) Checks whether the ast of typeTokenTypes.IDENTis used as an operand of a stand-alone increment or decrement.private voiditerateOverBlockContainingLocalAnonInnerClass(DetailAST ast, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Iterate over all the ast nodes present underast.private voidWe process all the blocks containing local anonymous inner classes separately after processing all the other nodes.voidleaveToken(DetailAST ast) Called after all the child nodes have been process.private voidlogViolations(DetailAST scopeAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) TraversevariablesStackstack and log the violations.private voidmodifyVariablesStack(UnusedLocalVariableCheck.TypeDeclDesc obtainedClass, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack, DetailAST literalNewAst) Add non-private instance and class variables of the super class of the anonymous class to the variables stack.voidsetAllowUnnamedVariables(boolean allowUnnamedVariables) Setter to allow variables named with a single underscore (known as unnamed variables in Java 21+).private static booleanWhether to check identifier token nested under dotAst.private booleanskipUnnamedVariables(DetailAST varDefAst) Check for skip currentTokenTypes.VARIABLE_DEFdue to allowUnnamedVariable option.typeDeclWithSameName(String superClassName) Checks if there is a type declaration with same name as the super class.private static voidvisitDotToken(DetailAST dotAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Visit ast of typeTokenTypes.DOT.private static voidvisitIdentToken(DetailAST identAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Visit ast of typeTokenTypes.IDENT.private voidvisitLocalAnonInnerClass(DetailAST literalNewAst) Visit the local anon inner class.private voidvisitNonLocalTypeDeclarationToken(DetailAST typeDeclAst) Visit the non-local type declaration token.voidvisitToken(DetailAST ast) Called to process a token.private voidvisitVariableDefToken(DetailAST varDefAst) Visit ast of typeTokenTypes.VARIABLE_DEF.Methods inherited from class com.puppycrawl.tools.checkstyle.api.AbstractCheck
clearViolations, destroy, finishTree, getFileContents, getFilePath, getLine, getLineCodePoints, getLines, getTabWidth, getTokenNames, getViolations, init, isCommentNodesRequired, log, log, log, setFileContents, setTabWidth, setTokensMethods inherited from class com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter
finishLocalSetup, getCustomMessages, getId, getMessageBundle, getSeverity, getSeverityLevel, setId, setSeverityMethods inherited from class com.puppycrawl.tools.checkstyle.AbstractAutomaticBean
configure, contextualize, getConfiguration, setupChild
-
Field Details
-
MSG_UNUSED_LOCAL_VARIABLE
A key is pointing to the warning message text in "messages.properties" file.- See Also:
-
MSG_UNUSED_NAMED_LOCAL_VARIABLE
A key is pointing to the warning message text in "messages.properties" file.- See Also:
-
INCREMENT_AND_DECREMENT_TOKENS
An array of increment and decrement tokens. -
SCOPES
An array of scope tokens. -
UNACCEPTABLE_CHILD_OF_DOT
An array of unacceptable children of ast of typeTokenTypes.DOT. -
UNACCEPTABLE_PARENT_OF_IDENT
An array of unacceptable parent of ast of typeTokenTypes.IDENT. -
ANONYMOUS_CLASS_PARENT_TOKENS
An array of blocks in which local anon inner classes can exist. -
INCREMENT_DECREMENT_VARIABLE_USAGE_TYPES
An array of token types that indicate a variable is being used within an expression involving increment or decrement operators, or within a switch statement. When a token of one of these types is the parent of an expression, it indicates that the variable associated with the increment or decrement operation is being used. Ex:- TokenTypes.LITERAL_SWITCH: Indicates a switch statement. Variables used within the switch expression are considered to be used -
PACKAGE_SEPARATOR
Package separator.- See Also:
-
variables
Keeps tracks of the variables declared in file. -
typeDeclarations
Keeps track of all the type declarations present in the file. Pops the type out of the stack while leaving the type in visitor pattern. -
typeDeclAstToTypeDeclDesc
Maps type declaration ast to their respective TypeDeclDesc objects. -
anonInnerAstToTypeDeclDesc
Maps local anonymous inner class to the TypeDeclDesc object containing it. -
anonInnerClassHolders
Set of tokens of typeANONYMOUS_CLASS_PARENT_TOKENSandTokenTypes.LAMBDAin some cases. -
allowUnnamedVariables
Allow variables named with a single underscore (known as unnamed variables in Java 21+). -
packageName
Name of the package. -
depth
Depth at which a type declaration is nested, 0 for top level type declarations.
-
-
Constructor Details
-
UnusedLocalVariableCheck
public UnusedLocalVariableCheck()
-
-
Method Details
-
setAllowUnnamedVariables
Setter to allow variables named with a single underscore (known as unnamed variables in Java 21+).- Parameters:
allowUnnamedVariables- true or false.- Since:
- 10.18.0
-
getDefaultTokens
Description copied from class:AbstractCheckReturns the default token a check is interested in. Only used if the configuration for a check does not define the tokens.- Specified by:
getDefaultTokensin classAbstractCheck- Returns:
- the default tokens
- See Also:
-
getAcceptableTokens
Description copied from class:AbstractCheckThe configurable token set. Used to protect Checks against malicious users who specify an unacceptable token set in the configuration file. The default implementation returns the check's default tokens.- Specified by:
getAcceptableTokensin classAbstractCheck- Returns:
- the token set this check is designed for.
- See Also:
-
getRequiredTokens
Description copied from class:AbstractCheckThe tokens that this check must be registered for.- Specified by:
getRequiredTokensin classAbstractCheck- Returns:
- the token set this must be registered for.
- See Also:
-
beginTree
Description copied from class:AbstractCheckCalled before the starting to process a tree. Ideal place to initialize information that is to be collected whilst processing a tree.- Overrides:
beginTreein classAbstractCheck- Parameters:
root- the root of the tree
-
visitToken
Description copied from class:AbstractCheckCalled to process a token.- Overrides:
visitTokenin classAbstractCheck- Parameters:
ast- the token to process
-
leaveToken
Description copied from class:AbstractCheckCalled after all the child nodes have been process.- Overrides:
leaveTokenin classAbstractCheck- Parameters:
ast- the token leaving
-
visitDotToken
private static void visitDotToken(DetailAST dotAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Visit ast of typeTokenTypes.DOT.- Parameters:
dotAst- dotAstvariablesStack- stack of all the relevant variables in the scope
-
visitVariableDefToken
Visit ast of typeTokenTypes.VARIABLE_DEF.- Parameters:
varDefAst- varDefAst
-
visitIdentToken
private static void visitIdentToken(DetailAST identAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Visit ast of typeTokenTypes.IDENT.- Parameters:
identAst- identAstvariablesStack- stack of all the relevant variables in the scope
-
visitNonLocalTypeDeclarationToken
Visit the non-local type declaration token.- Parameters:
typeDeclAst- type declaration ast
-
visitLocalAnonInnerClass
Visit the local anon inner class.- Parameters:
literalNewAst- literalNewAst
-
skipUnnamedVariables
Check for skip currentTokenTypes.VARIABLE_DEFdue to allowUnnamedVariable option.- Parameters:
varDefAst- varDefAst variable to check- Returns:
- true if the current variable should be skipped.
-
isInsideLocalAnonInnerClass
Whether ast node of typeTokenTypes.LITERAL_NEWis a part of a local anonymous inner class.- Parameters:
literalNewAst- ast node of typeTokenTypes.LITERAL_NEW- Returns:
- true if variableDefAst is an instance variable in local anonymous inner class
-
logViolations
private void logViolations(DetailAST scopeAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) TraversevariablesStackstack and log the violations.- Parameters:
scopeAst- ast node of typeSCOPESvariablesStack- stack of all the relevant variables in the scope
-
leaveCompilationUnit
We process all the blocks containing local anonymous inner classes separately after processing all the other nodes. This is being done due to the fact the instance variables of local anon inner classes can cast a shadow on local variables. -
isNonLocalTypeDeclaration
Whether a type declaration is non-local. Annotated interfaces are always non-local.- Parameters:
typeDeclAst- type declaration ast- Returns:
- true if type declaration is non-local
-
getBlockContainingLocalAnonInnerClass
Get the block containing local anon inner class.- Parameters:
literalNewAst- ast node of typeTokenTypes.LITERAL_NEW- Returns:
- the block containing local anon inner class
-
addLocalVariables
private static void addLocalVariables(DetailAST varDefAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Add local variables to thevariablesStackstack. Also adds the instance variables defined in a local anonymous inner class.- Parameters:
varDefAst- ast node of typeTokenTypes.VARIABLE_DEFvariablesStack- stack of all the relevant variables in the scope
-
addInstanceOrClassVar
Add instance variables and class variables to theUnusedLocalVariableCheck.TypeDeclDesc.instanceAndClassVarStack.- Parameters:
varDefAst- ast node of typeTokenTypes.VARIABLE_DEF
-
isPrivateInstanceVariable
Whether instance variable or class variable have private access modifier.- Parameters:
varDefAst- ast node of typeTokenTypes.VARIABLE_DEF- Returns:
- true if instance variable or class variable have private access modifier
-
getSuperClassOfAnonInnerClass
private UnusedLocalVariableCheck.TypeDeclDesc getSuperClassOfAnonInnerClass(DetailAST literalNewAst) Get theUnusedLocalVariableCheck.TypeDeclDescof the super class of anonymous inner class.- Parameters:
literalNewAst- ast node of typeTokenTypes.LITERAL_NEW- Returns:
UnusedLocalVariableCheck.TypeDeclDescof the super class of anonymous inner class
-
modifyVariablesStack
private void modifyVariablesStack(UnusedLocalVariableCheck.TypeDeclDesc obtainedClass, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack, DetailAST literalNewAst) Add non-private instance and class variables of the super class of the anonymous class to the variables stack.- Parameters:
obtainedClass- super class of the anon inner classvariablesStack- stack of all the relevant variables in the scopeliteralNewAst- ast node of typeTokenTypes.LITERAL_NEW
-
typeDeclWithSameName
Checks if there is a type declaration with same name as the super class.- Parameters:
superClassName- name of the super class- Returns:
- list if there is another type declaration with same name.
-
hasSameNameAsSuperClass
private boolean hasSameNameAsSuperClass(String superClassName, UnusedLocalVariableCheck.TypeDeclDesc typeDeclDesc) Whether the qualified name oftypeDeclDescmatches the super class name.- Parameters:
superClassName- name of the super classtypeDeclDesc- type declaration description- Returns:
trueif the qualified name oftypeDeclDescmatches the super class name
-
getClosestMatchingTypeDeclaration
private static UnusedLocalVariableCheck.TypeDeclDesc getClosestMatchingTypeDeclaration(String outerTypeDeclName, List<UnusedLocalVariableCheck.TypeDeclDesc> typeDeclWithSameName) For all type declarations with the same name as the superclass, gets the nearest type declaration.- Parameters:
outerTypeDeclName- outer type declaration of anonymous inner classtypeDeclWithSameName- typeDeclarations which have the same name as the super class- Returns:
- the nearest class
-
calculateTypeDeclarationDistance
private static int calculateTypeDeclarationDistance(String outerTypeName, UnusedLocalVariableCheck.TypeDeclDesc firstType, UnusedLocalVariableCheck.TypeDeclDesc secondType) Get the difference between type declaration name matching count. If the difference between them is zero, then their depth is compared to obtain the result.- Parameters:
outerTypeName- outer type declaration of anonymous inner classfirstType- first input type declarationsecondType- second input type declaration- Returns:
- difference between type declaration name matching count
-
countMatchingQualifierChars
Calculates the type declaration matching count for the superclass of an anonymous inner class.For example, if the pattern class is
Main.ClassOneand the class to be matched isMain.ClassOne.ClassTwo.ClassThree, then the matching count would be calculated by comparing the characters at each position, and updating the count whenever a '.' is encountered. This is necessary because pattern class can include anonymous inner classes, unlike regular inheritance where nested classes cannot be extended.- Parameters:
pattern- type declaration to match againstcandidate- type declaration to be matched- Returns:
- the type declaration matching count
-
getQualifiedTypeDeclarationName
Get qualified type declaration name from type ast.- Parameters:
typeDeclAst- type declaration ast- Returns:
- qualified name of type declaration
-
iterateOverBlockContainingLocalAnonInnerClass
private void iterateOverBlockContainingLocalAnonInnerClass(DetailAST ast, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Iterate over all the ast nodes present underast.- Parameters:
ast- astvariablesStack- stack of all the relevant variables in the scope
-
customVisitToken
private void customVisitToken(DetailAST ast, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Visit all ast nodes underanonInnerClassHoldersonce again.- Parameters:
ast- astvariablesStack- stack of all the relevant variables in the scope
-
customLeaveToken
private void customLeaveToken(DetailAST ast, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Leave all ast nodes underanonInnerClassHoldersonce again.- Parameters:
ast- astvariablesStack- stack of all the relevant variables in the scope
-
shouldCheckIdentTokenNestedUnderDot
Whether to check identifier token nested under dotAst.- Parameters:
dotAst- dotAst- Returns:
- true if ident nested under dotAst should be checked
-
checkIdentifierAst
private static void checkIdentifierAst(DetailAST identAst, Deque<UnusedLocalVariableCheck.VariableDesc> variablesStack) Checks the identifier ast.- Parameters:
identAst- ast of typeTokenTypes.IDENTvariablesStack- stack of all the relevant variables in the scope
-
findScopeOfVariable
Find the scope of variable.- Parameters:
variableDef- ast of typeTokenTypes.VARIABLE_DEF- Returns:
- scope of variableDef
-
isLeftHandSideValue
Checks whether the ast of typeTokenTypes.IDENTis used as left-hand side value. An identifier is being used as a left-hand side value if it is used as the left operand of an assignment or as an operand of a stand-alone increment or decrement.- Parameters:
identAst- ast of typeTokenTypes.IDENT- Returns:
- true if identAst is used as a left-hand side value
-
isStandAloneIncrementOrDecrement
Checks whether the ast of typeTokenTypes.IDENTis used as an operand of a stand-alone increment or decrement.- Parameters:
identAst- ast of typeTokenTypes.IDENT- Returns:
- true if identAst is used as an operand of stand-alone increment or decrement
-
isIncrementOrDecrementVariableUsed
A variable with increment or decrement operator is considered used if it is used as an argument or as an array index or for assigning value to a variable.- Parameters:
exprAst- ast of typeTokenTypes.EXPR- Returns:
- true if variable nested in exprAst is used
-