Class InnerAssignmentCheck
- 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.InnerAssignmentCheck
-
- All Implemented Interfaces:
Configurable
,Contextualizable
public class InnerAssignmentCheck extends AbstractCheck
Checks for assignments in subexpressions, such as in
String s = Integer.toString(i = 2);
.Rationale: Except for the loop idioms, all assignments should occur in their own top-level statement to increase readability. With inner assignments like the one given above, it is difficult to see all places where a variable is set.
Note: Check allows usage of the popular assignments in loops:
String line; while ((line = bufferedReader.readLine()) != null) { // OK // process the line } for (;(line = bufferedReader.readLine()) != null;) { // OK // process the line } do { // process the line } while ((line = bufferedReader.readLine()) != null); // OK
Assignment inside a condition is not a problem here, as the assignment is surrounded by an extra pair of parentheses. The comparison is
!= null
and there is no chance that intention was to writeline == reader.readLine()
.Parent is
com.puppycrawl.tools.checkstyle.TreeWalker
Violation Message Keys:
-
assignment.inner.avoid
- Since:
- 3.0
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from class com.puppycrawl.tools.checkstyle.AbstractAutomaticBean
AbstractAutomaticBean.OutputStreamOptions
-
-
Field Summary
Fields Modifier and Type Field Description private static int[][]
ALLOWED_ASSIGNMENT_CONTEXT
Allowed AST types from an assignment AST node towards the root.private static int[][]
ALLOWED_ASSIGNMENT_IN_COMPARISON_CONTEXT
Allowed AST types from a comparison node (above an assignment) towards the root.private static BitSet
COMPARISON_TYPES
The token types that identify comparison operators.private static int[][]
CONTROL_CONTEXT
Allowed AST types from an assignment AST node towards the root.private static BitSet
LOOP_IDIOM_IGNORED_PARENTS
The token types that are ignored while checking "loop-idiom".static String
MSG_KEY
A key is pointing to the warning message text in "messages.properties" file.
-
Constructor Summary
Constructors Constructor Description InnerAssignmentCheck()
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description int[]
getAcceptableTokens()
The configurable token set.int[]
getDefaultTokens()
Returns the default token a check is interested in.private static DetailAST
getParent(DetailAST ast, BitSet skipTokens)
Get ast parent, ignoring token types fromskipTokens
.int[]
getRequiredTokens()
The tokens that this check must be registered for.private static boolean
isComparison(DetailAST ast)
Checks if an AST is a comparison operator.private static boolean
isInContext(DetailAST ast, int[][] contextSet, BitSet skipTokens)
Tests whether the provided AST is in one of the given contexts.private static boolean
isInLoopIdiom(DetailAST ast)
Tests whether the given AST is used in the "assignment in loop" idiom.private static boolean
isInNoBraceControlStatement(DetailAST ast)
Determines if ast is in the body of a flow control statement without braces.void
visitToken(DetailAST ast)
Called to process a token.-
Methods inherited from class com.puppycrawl.tools.checkstyle.api.AbstractCheck
beginTree, clearViolations, destroy, finishTree, getFileContents, getFilePath, getLine, getLineCodePoints, getLines, getTabWidth, getTokenNames, getViolations, init, isCommentNodesRequired, leaveToken, log, log, log, setFileContents, setTabWidth, setTokens
-
Methods inherited from class com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter
finishLocalSetup, getCustomMessages, getId, getMessageBundle, getSeverity, getSeverityLevel, setId, setSeverity
-
Methods inherited from class com.puppycrawl.tools.checkstyle.AbstractAutomaticBean
configure, contextualize, getConfiguration, setupChild
-
-
-
-
Field Detail
-
MSG_KEY
public static final String MSG_KEY
A key is pointing to the warning message text in "messages.properties" file.- See Also:
- Constant Field Values
-
ALLOWED_ASSIGNMENT_CONTEXT
private static final int[][] ALLOWED_ASSIGNMENT_CONTEXT
Allowed AST types from an assignment AST node towards the root.
-
CONTROL_CONTEXT
private static final int[][] CONTROL_CONTEXT
Allowed AST types from an assignment AST node towards the root.
-
ALLOWED_ASSIGNMENT_IN_COMPARISON_CONTEXT
private static final int[][] ALLOWED_ASSIGNMENT_IN_COMPARISON_CONTEXT
Allowed AST types from a comparison node (above an assignment) towards the root.
-
COMPARISON_TYPES
private static final BitSet COMPARISON_TYPES
The token types that identify comparison operators.
-
LOOP_IDIOM_IGNORED_PARENTS
private static final BitSet LOOP_IDIOM_IGNORED_PARENTS
The token types that are ignored while checking "loop-idiom".
-
-
Constructor Detail
-
InnerAssignmentCheck
public InnerAssignmentCheck()
-
-
Method Detail
-
getDefaultTokens
public int[] getDefaultTokens()
Description copied from class:AbstractCheck
Returns the default token a check is interested in. Only used if the configuration for a check does not define the tokens.- Specified by:
getDefaultTokens
in classAbstractCheck
- Returns:
- the default tokens
- See Also:
TokenTypes
-
getAcceptableTokens
public int[] getAcceptableTokens()
Description copied from class:AbstractCheck
The 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:
getAcceptableTokens
in classAbstractCheck
- Returns:
- the token set this check is designed for.
- See Also:
TokenTypes
-
getRequiredTokens
public int[] getRequiredTokens()
Description copied from class:AbstractCheck
The tokens that this check must be registered for.- Specified by:
getRequiredTokens
in classAbstractCheck
- Returns:
- the token set this must be registered for.
- See Also:
TokenTypes
-
visitToken
public void visitToken(DetailAST ast)
Description copied from class:AbstractCheck
Called to process a token.- Overrides:
visitToken
in classAbstractCheck
- Parameters:
ast
- the token to process
-
isInNoBraceControlStatement
private static boolean isInNoBraceControlStatement(DetailAST ast)
Determines if ast is in the body of a flow control statement without braces. An example of such a statement would beif (y < 0) x = y;
This leads to the following AST structure:
LITERAL_IF LPAREN EXPR // test RPAREN EXPR // body SEMI
We need to ensure that ast is in the body and not in the test.
- Parameters:
ast
- an assignment operator AST- Returns:
- whether ast is in the body of a flow control statement
-
isInLoopIdiom
private static boolean isInLoopIdiom(DetailAST ast)
Tests whether the given AST is used in the "assignment in loop" idiom.String line; while ((line = bufferedReader.readLine()) != null) { // process the line } for (;(line = bufferedReader.readLine()) != null;) { // process the line } do { // process the line } while ((line = bufferedReader.readLine()) != null);
Assignment inside a condition is not a problem here, as the assignment is surrounded by an extra pair of parentheses. The comparison is!= null
and there is no chance that intention was to writeline == reader.readLine()
.- Parameters:
ast
- assignment AST- Returns:
- whether the context of the assignment AST indicates the idiom
-
isComparison
private static boolean isComparison(DetailAST ast)
Checks if an AST is a comparison operator.- Parameters:
ast
- the AST to check- Returns:
- true iff ast is a comparison operator.
-
isInContext
private static boolean isInContext(DetailAST ast, int[][] contextSet, BitSet skipTokens)
Tests whether the provided AST is in one of the given contexts.- Parameters:
ast
- the AST from which to start walking towards rootcontextSet
- the contexts to test against.skipTokens
- parent token types to ignore- Returns:
- whether the parents nodes of ast match one of the allowed type paths.
-
-