public class VariableDeclarationUsageDistanceCheck extends AbstractCheck
Checks the distance between declaration of variable and its first usage.
Example #1:
int count;
a = a + b;
b = a + a;
count = b; // DECLARATION OF VARIABLE 'count'
// SHOULD BE HERE (distance = 3)
Example #2:
int count;
{
a = a + b;
count = b; // DECLARATION OF VARIABLE 'count'
// SHOULD BE HERE (distance = 2)
}
Check can detect a block of initialization methods. If a variable is used in such a block and there is no other statements after this variable then distance=1.
Case #1:
int minutes = 5; Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(timeNow); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.HOUR_OF_DAY, hh); cal.set(Calendar.MINUTE, minutes); The distance for the variable minutes is 1 even though this variable is used in the fifth method's call.
Case #2:
int minutes = 5; Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(timeNow); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); System.out.println(cal); cal.set(Calendar.HOUR_OF_DAY, hh); cal.set(Calendar.MINUTE, minutes); The distance for the variable minutes is 6 because there is one more expression (except the initialization block) between the declaration of this variable and its usage.
There are several additional options to configure the check:
1. allowedDistance - allows to set a distance between declaration of variable and its first usage. 2. ignoreVariablePattern - allows to set a RegEx pattern for ignoring the distance calculation for variables listed in this pattern. 3. validateBetweenScopes - allows to calculate the distance between declaration of variable and its first usage in the different scopes. 4. ignoreFinal - allows to ignore variables with a 'final' modifier.ATTENTION!! (Not supported cases)
Case #1:
{
int c;
int a = 3;
int b = 2;
{
a = a + b;
c = b;
}
}
Distance for variable 'a' = 1;
Distance for variable 'b' = 1;
Distance for variable 'c' = 2.
As distance by default is 1 the Check doesn't raise warning for variables 'a'
and 'b' to move them into the block.
Case #2:
int sum = 0;
for (int i = 0; i < 20; i++) {
a++;
b--;
sum++;
if (sum > 10) {
res = true;
}
}
Distance for variable 'sum' = 3.
As the distance is more then the default one, the Check raises warning for variable 'sum' to move it into the 'for(...)' block. But there is situation when variable 'sum' hasn't to be 0 within each iteration. So, to avoid such warnings you can use Suppression Filter, provided by Checkstyle, for the whole class.
An example how to configure this Check:
<module name="VariableDeclarationUsageDistance"/>
An example of how to configure this Check: - to set the allowed distance to 4; - to ignore variables with prefix '^temp'; - to force the validation between scopes; - to check the final variables;
<module name="VariableDeclarationUsageDistance"> <property name="allowedDistance" value="4"/> <property name="ignoreVariablePattern" value="^temp.*"/> <property name="validateBetweenScopes" value="true"/> <property name="ignoreFinal" value="false"/> </module>
Modifier and Type | Field and Description |
---|---|
private int |
allowedDistance
Allowed distance between declaration of variable and its first usage.
|
private static int |
DEFAULT_DISTANCE
Default value of distance between declaration of variable and its first
usage.
|
private boolean |
ignoreFinal
Allows to ignore variables with 'final' modifier.
|
private java.util.regex.Pattern |
ignoreVariablePattern
RegExp pattern to ignore distance calculation for variables listed in
this pattern.
|
static java.lang.String |
MSG_KEY
Warning message key.
|
static java.lang.String |
MSG_KEY_EXT
Warning message key.
|
private boolean |
validateBetweenScopes
Allows to calculate distance between declaration of variable and its
first usage in different scopes.
|
Constructor and Description |
---|
VariableDeclarationUsageDistanceCheck() |
Modifier and Type | Method and Description |
---|---|
private static java.util.Map.Entry<DetailAST,java.lang.Integer> |
calculateDistanceBetweenScopes(DetailAST ast,
DetailAST variable)
Calculates distance between declaration of variable and its first usage
in multiple scopes.
|
private static java.util.Map.Entry<DetailAST,java.lang.Integer> |
calculateDistanceInSingleScope(DetailAST semicolonAst,
DetailAST variableIdentAst)
Calculates distance between declaration of variable and its first usage
in single scope.
|
int[] |
getAcceptableTokens()
The configurable token set.
|
int[] |
getDefaultTokens()
Returns the default token a check is interested in.
|
private static int |
getDistToVariableUsageInChildNode(DetailAST childNode,
DetailAST varIdent,
int currentDistToVarUsage)
Returns the distance to variable usage for in the child node.
|
private static DetailAST |
getFirstNodeInsideForWhileDoWhileBlocks(DetailAST block,
DetailAST variable)
Gets first Ast node inside FOR, WHILE or DO-WHILE blocks if variable
usage is met only inside the block (not in its declaration!).
|
private static DetailAST |
getFirstNodeInsideIfBlock(DetailAST block,
DetailAST variable)
Gets first Ast node inside IF block if variable usage is met
only inside the block (not in its declaration!).
|
private static DetailAST |
getFirstNodeInsideSwitchBlock(DetailAST block,
DetailAST variable)
Gets first Ast node inside SWITCH block if variable usage is met
only inside the block (not in its declaration!).
|
private static DetailAST |
getFirstNodeInsideTryCatchFinallyBlocks(DetailAST block,
DetailAST variable)
Gets first Ast node inside TRY-CATCH-FINALLY blocks if variable usage is
met only inside the block (not in its declaration!).
|
private static java.lang.String |
getInstanceName(DetailAST methodCallAst)
Get name of instance whose method is called.
|
int[] |
getRequiredTokens()
The tokens that this check must be registered for.
|
private static boolean |
isChild(DetailAST parent,
DetailAST ast)
Checks if Ast node contains given element.
|
private static boolean |
isInitializationSequence(DetailAST variableUsageAst,
java.lang.String variableName)
Processes statements until usage of variable to detect sequence of
initialization methods.
|
private static boolean |
isVariableInOperatorExpr(DetailAST operator,
DetailAST variable)
Checks if variable is in operator declaration.
|
private boolean |
isVariableMatchesIgnorePattern(java.lang.String variable)
Checks if entrance variable is contained in ignored pattern.
|
private static java.util.Map.Entry<java.util.List<DetailAST>,java.lang.Integer> |
searchVariableUsageExpressions(DetailAST variableAst,
DetailAST statementAst)
Searches variable usages starting from specified statement.
|
void |
setAllowedDistance(int allowedDistance)
Sets an allowed distance between declaration of variable and its first
usage.
|
void |
setIgnoreFinal(boolean ignoreFinal)
Sets ignore option for variables with 'final' modifier.
|
void |
setIgnoreVariablePattern(java.util.regex.Pattern pattern)
Sets RegExp pattern to ignore distance calculation for variables listed in this pattern.
|
void |
setValidateBetweenScopes(boolean validateBetweenScopes)
Sets option which allows to calculate distance between declaration of
variable and its first usage in different scopes.
|
void |
visitToken(DetailAST ast)
Called to process a token.
|
beginTree, destroy, finishTree, getClassLoader, getFileContents, getLine, getLines, getTabWidth, getTokenNames, init, isCommentNodesRequired, leaveToken, log, log, setClassLoader, setFileContents, setMessages, setTabWidth, setTokens
getCustomMessages, getId, getMessageBundle, getSeverity, getSeverityLevel, log, setId, setSeverity
configure, contextualize, finishLocalSetup, getConfiguration, setupChild
public static final java.lang.String MSG_KEY
public static final java.lang.String MSG_KEY_EXT
private static final int DEFAULT_DISTANCE
private int allowedDistance
private java.util.regex.Pattern ignoreVariablePattern
private boolean validateBetweenScopes
private boolean ignoreFinal
public VariableDeclarationUsageDistanceCheck()
public void setAllowedDistance(int allowedDistance)
allowedDistance
- Allowed distance between declaration of variable and its first
usage.public void setIgnoreVariablePattern(java.util.regex.Pattern pattern)
pattern
- a pattern.public void setValidateBetweenScopes(boolean validateBetweenScopes)
validateBetweenScopes
- Defines if allow to calculate distance between declaration of
variable and its first usage in different scopes or not.public void setIgnoreFinal(boolean ignoreFinal)
ignoreFinal
- Defines if ignore variables with 'final' modifier or not.public int[] getDefaultTokens()
AbstractCheck
getDefaultTokens
in class AbstractCheck
TokenTypes
public int[] getAcceptableTokens()
AbstractCheck
getAcceptableTokens
in class AbstractCheck
TokenTypes
public int[] getRequiredTokens()
AbstractCheck
getRequiredTokens
in class AbstractCheck
TokenTypes
public void visitToken(DetailAST ast)
AbstractCheck
visitToken
in class AbstractCheck
ast
- the token to processprivate static java.lang.String getInstanceName(DetailAST methodCallAst)
methodCallAst
- DetailAST of METHOD_CALL.private static boolean isInitializationSequence(DetailAST variableUsageAst, java.lang.String variableName)
variableUsageAst
- DetailAST of expression that uses variable named variableName.variableName
- name of considered variable.private static java.util.Map.Entry<DetailAST,java.lang.Integer> calculateDistanceInSingleScope(DetailAST semicolonAst, DetailAST variableIdentAst)
semicolonAst
- Regular node of Ast which is checked for content of checking
variable.variableIdentAst
- Variable which distance is calculated for.private static int getDistToVariableUsageInChildNode(DetailAST childNode, DetailAST varIdent, int currentDistToVarUsage)
childNode
- child node.varIdent
- variable variable identifier.currentDistToVarUsage
- current distance to the variable usage.private static java.util.Map.Entry<DetailAST,java.lang.Integer> calculateDistanceBetweenScopes(DetailAST ast, DetailAST variable)
ast
- Regular node of Ast which is checked for content of checking
variable.variable
- Variable which distance is calculated for.private static java.util.Map.Entry<java.util.List<DetailAST>,java.lang.Integer> searchVariableUsageExpressions(DetailAST variableAst, DetailAST statementAst)
variableAst
- Variable that is used.statementAst
- DetailAST to start searching from.private static DetailAST getFirstNodeInsideForWhileDoWhileBlocks(DetailAST block, DetailAST variable)
block
- Ast node represents FOR, WHILE or DO-WHILE block.variable
- Variable which is checked for content in block.private static DetailAST getFirstNodeInsideIfBlock(DetailAST block, DetailAST variable)
block
- Ast node represents IF block.variable
- Variable which is checked for content in block.private static DetailAST getFirstNodeInsideSwitchBlock(DetailAST block, DetailAST variable)
block
- Ast node represents SWITCH block.variable
- Variable which is checked for content in block.private static DetailAST getFirstNodeInsideTryCatchFinallyBlocks(DetailAST block, DetailAST variable)
block
- Ast node represents TRY-CATCH-FINALLY block.variable
- Variable which is checked for content in block.private static boolean isVariableInOperatorExpr(DetailAST operator, DetailAST variable)
boolean b = true; if (b) {...}Variable 'b' is in declaration of operator IF.
operator
- Ast node which represents operator.variable
- Variable which is checked for content in operator.private static boolean isChild(DetailAST parent, DetailAST ast)
parent
- Node of AST.ast
- Ast element which is checked for content in Ast node.private boolean isVariableMatchesIgnorePattern(java.lang.String variable)
variable
- Variable which is checked for content in ignored pattern.