Class DescendantTokenCheck
- 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.DescendantTokenCheck
-
- All Implemented Interfaces:
Configurable
,Contextualizable
public class DescendantTokenCheck extends AbstractCheck
Checks for restricted tokens beneath other tokens.
WARNING: This is a very powerful and flexible check, but, at the same time, it is low-level and very implementation-dependent because its results depend on the grammar we use to build abstract syntax trees. Thus, we recommend using other checks when they provide the desired functionality. Essentially, this check just works on the level of an abstract syntax tree and knows nothing about language structures.
-
Property
limitedTokens
- Specify set of tokens with limited occurrences as descendants. Type isjava.lang.String[]
. Validation type istokenTypesSet
. Default value is""
. -
Property
minimumDepth
- Specify the minimum depth for descendant counts. Type isint
. Default value is0
. -
Property
maximumDepth
- Specify the maximum depth for descendant counts. Type isint
. Default value is2147483647
. -
Property
minimumNumber
- Specify a minimum count for descendants. Type isint
. Default value is0
. -
Property
maximumNumber
- Specify a maximum count for descendants. Type isint
. Default value is2147483647
. -
Property
sumTokenCounts
- Control whether the number of tokens found should be calculated from the sum of the individual token counts. Type isboolean
. Default value isfalse
. -
Property
minimumMessage
- Define the violation message when the minimum count is not reached. Type isjava.lang.String
. Default value isnull
. -
Property
maximumMessage
- Define the violation message when the maximum count is exceeded. Type isjava.lang.String
. Default value isnull
. -
Property
tokens
- tokens to check Type isanyTokenTypesSet
. Default value is""
.
To configure the check to produce a violation on a switch statement with no default case:
<module name="DescendantToken"> <property name="tokens" value="LITERAL_SWITCH"/> <property name="maximumDepth" value="2"/> <property name="limitedTokens" value="LITERAL_DEFAULT"/> <property name="minimumNumber" value="1"/> </module>
Example:
class Test { public static void main(String[] args) { int x = 1; switch (x) { // ok case 1: System.out.println("hi"); break; default: System.out.println("Default"); break; } int y = 1; switch (y) { // violation case 1: System.out.println("hi"); break; } } }
To configure the check to produce a violation on a switch with too many cases:
<module name="DescendantToken"> <property name="tokens" value="LITERAL_SWITCH"/> <property name="limitedTokens" value="LITERAL_CASE"/> <property name="maximumDepth" value="2"/> <property name="maximumNumber" value="1"/> </module>
Example:
class Test { public void foo() { int x = 1; switch (x) { // ok case 1: // Some code break; default: // Some code break; } switch (x) { // violation case 1: // Some code break; case 2: // Some code break; default: // Some code break; } } }
To configure the check to produce a violation on a switch that is nested in another switch:
<module name="DescendantToken"> <property name="tokens" value="LITERAL_SWITCH"/> <property name="limitedTokens" value="LITERAL_SWITCH"/> <property name="maximumNumber" value="0"/> <property name="minimumDepth" value="1"/> </module>
Example:
class Test { public void foo() { int x = 1; int y = 2; switch (x) { // ok case 1: System.out.println("xyz"); break; } switch (y) { // violation case 1: switch (y) { case 2: System.out.println("xyz"); break; } break; } } }
To configure the check to produce a violation on a condition in
for
which performs no check:<module name="DescendantToken"> <property name="tokens" value="FOR_CONDITION"/> <property name="limitedTokens" value="EXPR"/> <property name="minimumNumber" value="1"/> </module>
Example:
class Test { public static void main(String[] args) { for (int i = 0; i != 10; i++) { // ok System.out.println(i); } int k = 0; for (; ; ) { // violation System.out.println(k); } } }
To configure the check to produce a violation on an initializer in
for
performs no setup (where awhile
statement could be used instead):<module name="DescendantToken"> <property name="tokens" value="FOR_INIT"/> <property name="limitedTokens" value="EXPR"/> <property name="minimumNumber" value="1"/> </module>
Example:
class Test { public void foo() { int[] array = new int[] {1, 2, 3, 4, 5}; for (int i = 0; i != array.length; i++) { // ok System.out.println(i); } int j = 0; for (; j != array.length;) { // violation System.out.println(j); j++; } } }
To configure the check to produce a violation on a return statement from within a catch or finally block:
<module name="DescendantToken"> <property name="tokens" value="LITERAL_FINALLY,LITERAL_CATCH"/> <property name="limitedTokens" value="LITERAL_RETURN"/> <property name="maximumNumber" value="0"/> </module>
Example:
class Test { public void foo() { try { // Some code } catch (Exception e) { System.out.println("xyz"); return; // violation } finally { System.out.println("xyz"); } } }
To configure the check to produce a violation on a try statement within a catch or finally block:
<module name="DescendantToken"> <property name="tokens" value="LITERAL_CATCH,LITERAL_FINALLY"/> <property name="limitedTokens" value="LITERAL_TRY"/> <property name="maximumNumber" value="0"/> </module>
Example:
class Test { public void foo() { try { // Some code } catch (Exception e) { // ok System.out.println("xyz"); return; } finally { // ok System.out.println("xyz"); } try { // Some code } catch (Exception e) { try { // violation // Some code } catch (Exception ex) { // handle exception } } finally { try { // violation // Some code } catch (Exception e) { // handle exception } } } }
To configure the check to produce a violation on a method with too many local variables:
<module name="DescendantToken"> <property name="tokens" value="METHOD_DEF"/> <property name="limitedTokens" value="VARIABLE_DEF"/> <property name="maximumDepth" value="2"/> <property name="maximumNumber" value="1"/> </module>
Example:
class Test { public void foo() { // ok int var1 = 1; } public void boo() { // violation int var1 = 1; int var2 = 2; } }
To configure the check to produce a violation on a method with too many returns:
<module name="DescendantToken"> <property name="tokens" value="METHOD_DEF"/> <property name="limitedTokens" value="LITERAL_RETURN"/> <property name="maximumNumber" value="2"/> </module>
Example:
class Test { public int foo(int x) { // ok if (x == -1) { return -1; } else if (x == 0) { return 0; } } public int boo(int x) { // violation if (x == -1) { return -1; } else if (x == 0) { return 0; } else { return x; } } }
To configure the check to produce a violation on a method which throws too many exceptions:
<module name="DescendantToken"> <property name="tokens" value="LITERAL_THROWS"/> <property name="limitedTokens" value="IDENT"/> <property name="maximumNumber" value="1"/> </module>
Example:
class Foo { public void foo() throws ArithmeticException { // ok // ... } } class Boo { public void boo() throws ArithmeticException, ArithmeticException { // violation // ... } }
To configure the check to produce a violation on a method with too many expressions:
<module name="DescendantToken"> <property name="tokens" value="METHOD_DEF"/> <property name="limitedTokens" value="EXPR"/> <property name="maximumNumber" value="2"/> </module>
Example:
class Foo { public void foo() { // ok int x = 1; int z = x + 2; } } class Boo { public void boo() { // violation int x = 1; int y = 2; int z = x + y; } }
To configure the check to produce a violation on an empty statement:
<module name="DescendantToken"> <property name="tokens" value="EMPTY_STAT"/> <property name="limitedTokens" value="EMPTY_STAT"/> <property name="maximumNumber" value="0"/> <property name="maximumDepth" value="0"/> <property name="maximumMessage" value="Empty statement is not allowed."/> </module>
Example:
class Test { public void foo() { // ok System.out.println("Hello"); } public void boo() { ; // violation } }
To configure the check to produce a violation on a class or interface with too many fields:
<module name="DescendantToken"> <property name="tokens" value="CLASS_DEF,INTERFACE_DEF"/> <property name="limitedTokens" value="VARIABLE_DEF"/> <property name="maximumDepth" value="2"/> <property name="maximumNumber" value="1"/> </module>
Example:
class A { // ok private int field1; // Some code } class B { // violation private int field1; private int field2; // Some code } interface C { // ok int FIELD_1 = 1; } interface D { // violation int FIELD_1 = 1; int FIELD_2 = 2; }
To configure the check to produce a violation on comparing
this
withnull
:<module name="DescendantToken"> <property name="tokens" value="EQUAL,NOT_EQUAL"/> <property name="limitedTokens" value="LITERAL_THIS,LITERAL_NULL"/> <property name="maximumNumber" value="1"/> <property name="maximumDepth" value="1"/> <property name="sumTokenCounts" value="true"/> </module>
Example:
class Test { public void foo() { if (this == null) { // violation System.out.println("xyz"); } if (this != null) { // violation System.out.println("xyz"); } Object obj = new Object(); if (obj == null) { // ok System.out.println("xyz"); } if (obj != null) { // ok System.out.println("xyz"); } } }
To configure the check to produce a violation on a
String
literal equality check:<module name="DescendantToken"> <property name="tokens" value="EQUAL,NOT_EQUAL"/> <property name="limitedTokens" value="STRING_LITERAL"/> <property name="maximumNumber" value="0"/> <property name="maximumDepth" value="1"/> </module>
Example:
class Test { public void foo() { String str = "abc"; if (str.equals("abc")) { // ok System.out.println("equal."); } if (str == "abc") { // violation System.out.println("equal."); } } }
To configure the check to produce a violation on an assert statement that may have side effects:
<module name="DescendantToken"> <property name="tokens" value="LITERAL_ASSERT"/> <property name="limitedTokens" value="ASSIGN,DEC,INC,POST_DEC, POST_INC,PLUS_ASSIGN,MINUS_ASSIGN,STAR_ASSIGN,DIV_ASSIGN,MOD_ASSIGN, BSR_ASSIGN,SR_ASSIGN,SL_ASSIGN,BAND_ASSIGN,BXOR_ASSIGN,BOR_ASSIGN, METHOD_CALL"/> <property name="maximumNumber" value="0"/> </module>
Example:
class Test { public void foo() { int a = 5; assert a++ == 0 : "is not"; // violation System.out.println(a); assert a == 0 : "is not"; // ok } }
Parent is
com.puppycrawl.tools.checkstyle.TreeWalker
Violation Message Keys:
-
descendant.token.max
-
descendant.token.min
-
descendant.token.sum.max
-
descendant.token.sum.min
- Since:
- 3.2
-
-
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 int[]
counts
Counts of descendant tokens.private int[]
limitedTokens
Specify set of tokens with limited occurrences as descendants.private int
maximumDepth
Specify the maximum depth for descendant counts.private java.lang.String
maximumMessage
Define the violation message when the maximum count is exceeded.private int
maximumNumber
Specify a maximum count for descendants.private int
minimumDepth
Specify the minimum depth for descendant counts.private java.lang.String
minimumMessage
Define the violation message when the minimum count is not reached.private int
minimumNumber
Specify a minimum count for descendants.static java.lang.String
MSG_KEY_MAX
A key is pointing to the warning message text in "messages.properties" file.static java.lang.String
MSG_KEY_MIN
A key is pointing to the warning message text in "messages.properties" file.static java.lang.String
MSG_KEY_SUM_MAX
A key is pointing to the warning message text in "messages.properties" file.static java.lang.String
MSG_KEY_SUM_MIN
A key is pointing to the warning message text in "messages.properties" file.private boolean
sumTokenCounts
Control whether the number of tokens found should be calculated from the sum of the individual token counts.
-
Constructor Summary
Constructors Constructor Description DescendantTokenCheck()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description private void
countTokens(DetailAST ast, int depth)
Counts the number of occurrences of descendant tokens.int[]
getAcceptableTokens()
The configurable token set.int[]
getDefaultTokens()
Returns the default token a check is interested in.int[]
getRequiredTokens()
The tokens that this check must be registered for.private void
logAsSeparated(DetailAST ast)
Log violations for each Token.private void
logAsTotal(DetailAST ast)
Log validation as one violation.void
setLimitedTokens(java.lang.String... limitedTokensParam)
Setter to specify set of tokens with limited occurrences as descendants.void
setMaximumDepth(int maximumDepth)
Setter to specify the maximum depth for descendant counts.void
setMaximumMessage(java.lang.String message)
Setter to define the violation message when the maximum count is exceeded.void
setMaximumNumber(int maximumNumber)
Setter to specify a maximum count for descendants.void
setMinimumDepth(int minimumDepth)
Setter to specify the minimum depth for descendant counts.void
setMinimumMessage(java.lang.String message)
Setter to define the violation message when the minimum count is not reached.void
setMinimumNumber(int minimumNumber)
Setter to specify a minimum count for descendants.void
setSumTokenCounts(boolean sum)
Setter to control whether the number of tokens found should be calculated from the sum of the individual token counts.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_MIN
public static final java.lang.String MSG_KEY_MIN
A key is pointing to the warning message text in "messages.properties" file.- See Also:
- Constant Field Values
-
MSG_KEY_MAX
public static final java.lang.String MSG_KEY_MAX
A key is pointing to the warning message text in "messages.properties" file.- See Also:
- Constant Field Values
-
MSG_KEY_SUM_MIN
public static final java.lang.String MSG_KEY_SUM_MIN
A key is pointing to the warning message text in "messages.properties" file.- See Also:
- Constant Field Values
-
MSG_KEY_SUM_MAX
public static final java.lang.String MSG_KEY_SUM_MAX
A key is pointing to the warning message text in "messages.properties" file.- See Also:
- Constant Field Values
-
minimumDepth
private int minimumDepth
Specify the minimum depth for descendant counts.
-
maximumDepth
private int maximumDepth
Specify the maximum depth for descendant counts.
-
minimumNumber
private int minimumNumber
Specify a minimum count for descendants.
-
maximumNumber
private int maximumNumber
Specify a maximum count for descendants.
-
sumTokenCounts
private boolean sumTokenCounts
Control whether the number of tokens found should be calculated from the sum of the individual token counts.
-
limitedTokens
private int[] limitedTokens
Specify set of tokens with limited occurrences as descendants.
-
minimumMessage
private java.lang.String minimumMessage
Define the violation message when the minimum count is not reached.
-
maximumMessage
private java.lang.String maximumMessage
Define the violation message when the maximum count is exceeded.
-
counts
private int[] counts
Counts of descendant tokens. Indexed by (token ID - 1) for performance.
-
-
Constructor Detail
-
DescendantTokenCheck
public DescendantTokenCheck()
-
-
Method Detail
-
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
-
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
-
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
-
logAsSeparated
private void logAsSeparated(DetailAST ast)
Log violations for each Token.- Parameters:
ast
- token
-
logAsTotal
private void logAsTotal(DetailAST ast)
Log validation as one violation.- Parameters:
ast
- current token
-
countTokens
private void countTokens(DetailAST ast, int depth)
Counts the number of occurrences of descendant tokens.- Parameters:
ast
- the root token for descendants.depth
- the maximum depth of the counted descendants.
-
setLimitedTokens
public void setLimitedTokens(java.lang.String... limitedTokensParam)
Setter to specify set of tokens with limited occurrences as descendants.- Parameters:
limitedTokensParam
- tokens to ignore.
-
setMinimumDepth
public void setMinimumDepth(int minimumDepth)
Setter to specify the minimum depth for descendant counts.- Parameters:
minimumDepth
- the minimum depth for descendant counts.
-
setMaximumDepth
public void setMaximumDepth(int maximumDepth)
Setter to specify the maximum depth for descendant counts.- Parameters:
maximumDepth
- the maximum depth for descendant counts.
-
setMinimumNumber
public void setMinimumNumber(int minimumNumber)
Setter to specify a minimum count for descendants.- Parameters:
minimumNumber
- the minimum count for descendants.
-
setMaximumNumber
public void setMaximumNumber(int maximumNumber)
Setter to specify a maximum count for descendants.- Parameters:
maximumNumber
- the maximum count for descendants.
-
setMinimumMessage
public void setMinimumMessage(java.lang.String message)
Setter to define the violation message when the minimum count is not reached.- Parameters:
message
- the violation message for minimum count not reached. Used as aMessageFormat
pattern with arguments- {0} - token count
- {1} - minimum number
- {2} - name of token
- {3} - name of limited token
-
setMaximumMessage
public void setMaximumMessage(java.lang.String message)
Setter to define the violation message when the maximum count is exceeded.- Parameters:
message
- the violation message for maximum count exceeded. Used as aMessageFormat
pattern with arguments- {0} - token count
- {1} - maximum number
- {2} - name of token
- {3} - name of limited token
-
setSumTokenCounts
public void setSumTokenCounts(boolean sum)
Setter to control whether the number of tokens found should be calculated from the sum of the individual token counts.- Parameters:
sum
- whether to use the sum.
-
-