DescendantToken

Since Checkstyle 3.2

Description

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.

Properties

name description type default value since
limitedTokens Specify set of tokens with limited occurrences as descendants. subset of tokens TokenTypes {} 3.2
maximumDepth Specify the maximum depth for descendant counts. int 2147483647 3.2
maximumMessage Define the violation message when the maximum count is exceeded. String null 3.2
maximumNumber Specify a maximum count for descendants. int 2147483647 3.2
minimumDepth Specify the minimum depth for descendant counts. int 0 3.2
minimumMessage Define the violation message when the minimum count is not reached. String null 3.2
minimumNumber Specify a minimum count for descendants. int 0 3.2
sumTokenCounts Control whether the number of tokens found should be calculated from the sum of the individual token counts. boolean false 5.0
tokens tokens to check set of any supported tokens empty 3.2

Examples

To configure the check to produce a violation on a switch statement with no default case:

<module name="Checker">
  <module name="TreeWalker">
    <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>
  </module>
</module>
        

Example:

class Example1 {
  void testMethod1() {
    int x = 1;
    switch (x) {
      case 1:
        System.out.println("hi");
        break;
      default:
        System.out.println("Default");
        break;
    }

    int y = 1;
    switch (y) { // violation, 'Count of 0 for 'LITERAL_SWITCH' descendant'
      case 1:
        System.out.println("hi");
        break;
    }
  }

  void testMethod2() {
    int x = 1;
    switch (x) {
      case 1:
        // Some code
        break;
      default:
        // Some code
        break;
    }

    switch (x) {
      case 1:
        // Some code
        break;
      case 2:
        // Some code
        break;
      default:
        // Some code
        break;
    }
  }

  void testMethod3() {
    int x = 1;
    int y = 2;
    switch (x) { // violation, 'Count of 0 for 'LITERAL_SWITCH' descendant'
      case 1:
        System.out.println("xyz");
        break;
    }
    switch (y) { // violation, 'Count of 0 for 'LITERAL_SWITCH' descendant'
      case 1:
        switch (y) { // violation, 'Count of 0 for 'LITERAL_SWITCH' descendant'
          case 2:
            System.out.println("xyz");
            break;
        }
        break;
    }
  }
}
        

To configure the check to produce a violation on a switch with too many cases:

<module name="Checker">
  <module name="TreeWalker">
    <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>
  </module>
</module>
        

Example:

class Example2 {
  void testMethod1() {
    int x = 1;
    switch (x) {
      case 1:
        System.out.println("hi");
        break;
      default:
        System.out.println("Default");
        break;
    }

    int y = 1;
    switch (y) {
      case 1:
        System.out.println("hi");
        break;
    }
  }

  void testMethod2() {
    int x = 1;
    switch (x) {
      case 1:
        // Some code
        break;
      default:
        // Some code
        break;
    }

    switch (x) { // violation, 'Count of 2 for 'LITERAL_SWITCH' descendant'
      case 1:
        // Some code
        break;
      case 2:
        // Some code
        break;
      default:
        // Some code
        break;
    }
  }

  void testMethod3() {
    int x = 1;
    int y = 2;
    switch (x) {
      case 1:
        System.out.println("xyz");
        break;
    }
    switch (y) {
      case 1:
        switch (y) {
          case 2:
            System.out.println("xyz");
            break;
        }
        break;
    }
  }
}
        

To configure the check to produce a violation on a switch that is nested in another switch:

<module name="Checker">
  <module name="TreeWalker">
    <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>
  </module>
</module>
        

Example:

class Example3 {
  void testMethod1() {
    int x = 1;
    switch (x) {
      case 1:
        System.out.println("hi");
        break;
      default:
        System.out.println("Default");
        break;
    }

    int y = 1;
    switch (y) {
      case 1:
        System.out.println("hi");
        break;
    }
  }

  void testMethod2() {
    int x = 1;
    switch (x) {
      case 1:
        // Some code
        break;
      default:
        // Some code
        break;
    }

    switch (x) {
      case 1:
        // Some code
        break;
      case 2:
        // Some code
        break;
      default:
        // Some code
        break;
    }
  }

  void testMethod3() {
    int x = 1;
    int y = 2;
    switch (x) {
      case 1:
        System.out.println("xyz");
        break;
    }
    switch (y) { // violation, 'Count of 1 for 'LITERAL_SWITCH' descendant'
      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="Checker">
  <module name="TreeWalker">
    <module name="DescendantToken">
      <property name="tokens" value="FOR_CONDITION"/>
      <property name="limitedTokens" value="EXPR"/>
      <property name="minimumNumber" value="1"/>
    </module>
  </module>
</module>
        

Example:

class Example4 {
  void testMethod1() {
    for (int i = 0; i != 10; i++) {
      System.out.println(i);
    }
    int k = 0;
    for (; ; ) { // violation, 'Count of 0 for 'FOR_CONDITION' descendant'
      System.out.println(k);
    }
  }

  void testMethod2() {
    int[] array = new int[] {1, 2, 3, 4, 5};
    for (int i = 0; i != array.length; i++) {
      System.out.println(i);
    }
    int j = 0;

    for (; j != array.length;) {
      System.out.println(j);
      j++;
    }
  }
}
        

To configure the check to produce a violation on an initializer in for performs no setup (where a while statement could be used instead):

<module name="Checker">
  <module name="TreeWalker">
    <module name="DescendantToken">
      <property name="tokens" value="FOR_INIT"/>
      <property name="limitedTokens" value="EXPR"/>
      <property name="minimumNumber" value="1"/>
    </module>
  </module>
</module>
        

Example:

class Example5 {
  void testMethod1() {
    for (int i = 0; i != 10; i++) {
      System.out.println(i);
    }
    int k = 0;
    for (; ; ) { // violation, 'Count of 0 for 'FOR_INIT' descendant'
      System.out.println(k);
    }
  }

  void testMethod2() {
    int[] array = new int[] {1, 2, 3, 4, 5};
    for (int i = 0; i != array.length; i++) {
      System.out.println(i);
    }
    int j = 0;
    // violation below, 'Count of 0 for 'FOR_INIT' descendant'
    for (; j != array.length;) {
      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="Checker">
  <module name="TreeWalker">
    <module name="DescendantToken">
      <property name="tokens" value="LITERAL_FINALLY,LITERAL_CATCH"/>
      <property name="limitedTokens" value="LITERAL_RETURN"/>
      <property name="maximumNumber" value="0"/>
    </module>
  </module>
</module>
        

Example:

class Example6 {
  void testMethod1() {
    try {}
    catch (Exception e) { // violation, 'Count of 1 for 'LITERAL_CATCH' descendant'
      System.out.println("xyz");
      return;
    }
    finally {
      System.out.println("xyz");
    }
  }

  void testMethod2() {
    try {}
    catch (Exception e) { // violation, 'Count of 1 for 'LITERAL_CATCH' descendant'
      System.out.println("xyz");
      return;
    }
    finally {
      System.out.println("xyz");
    }
    try {}
    catch (Exception e) {
      try {}
      catch (Exception ex) {
        // handle exception
      }
    }
    finally {
      try {}
      catch (Exception e) {
        // handle exception
      }
    }
  }
}
        

To configure the check to produce a violation on a try statement within a catch or finally block:

<module name="Checker">
  <module name="TreeWalker">
    <module name="DescendantToken">
      <property name="tokens" value="LITERAL_CATCH,LITERAL_FINALLY"/>
      <property name="limitedTokens" value="LITERAL_TRY"/>
      <property name="maximumNumber" value="0"/>
    </module>
  </module>
</module>
        

Example:

class Example7 {
  void testMethod1() {
    try {}
    catch (Exception e) {
      System.out.println("xyz");
      return;
    }
    finally {
      System.out.println("xyz");
    }
  }

  void testMethod2() {
    try {}
    catch (Exception e) {
      System.out.println("xyz");
      return;
    }
    finally {
      System.out.println("xyz");
    }
    try {}
    catch (Exception e) { // violation, 'Count of 1 for 'LITERAL_CATCH' descendant'
      try {}
      catch (Exception ex) {
        // handle exception
      }
    }
    finally { // violation, 'Count of 1 for 'LITERAL_FINALLY' descendant '
      try {}
      catch (Exception e) {
        // handle exception
      }
    }
  }
}
        

To configure the check to produce a violation on a method with too many local variables:

<module name="Checker">
  <module name="TreeWalker">
    <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>
  </module>
</module>
        

Example:

class Example8 {
  void testMethod1() {
    int var1 = 1;
  }
  void testMethod2() { // violation 'Count of 2 for 'METHOD_DEF' descendant'
    int var1 = 1;
    int var2 = 2;
  }

  int testMethod3(int x) {
    if (x == -1) {
      return -1;
    }
    else if (x == 0) {
      return 0;
    }
    return -1;
  }
  int testMethod4(int x) {
    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 with too many returns:

<module name="Checker">
  <module name="TreeWalker">
    <module name="DescendantToken">
      <property name="tokens" value="METHOD_DEF"/>
      <property name="limitedTokens" value="LITERAL_RETURN"/>
      <property name="maximumNumber" value="2"/>
    </module>
  </module>
</module>
        

Example:

class Example9 {
  void testMethod1() {
    int var1 = 1;
  }
  void testMethod2() {
    int var1 = 1;
    int var2 = 2;
  }

  int testMethod3(int x) { // violation 'Count of 3 for 'METHOD_DEF' descendant'
    if (x == -1) {
      return -1;
    }
    else if (x == 0) {
      return 0;
    }
    return -1;
  }
  int testMethod4(int x) { // violation 'Count of 3 for 'METHOD_DEF' descendant'
    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="Checker">
  <module name="TreeWalker">
    <module name="DescendantToken">
      <property name="tokens" value="LITERAL_THROWS"/>
      <property name="limitedTokens" value="IDENT"/>
      <property name="maximumNumber" value="1"/>
    </module>
  </module>
</module>
        

Example:

class Example10 {
  void testMethod1() throws ArithmeticException {
      // ...
  }
  // violation below, 'Count of 2 for 'LITERAL_THROWS' descendant'
  void testMethod2() throws ArithmeticException, ArithmeticException {
      // ...
  }
}
        

To configure the check to produce a violation on a method with too many expressions:

<module name="Checker">
  <module name="TreeWalker">
    <module name="DescendantToken">
      <property name="tokens" value="METHOD_DEF"/>
      <property name="limitedTokens" value="EXPR"/>
      <property name="maximumNumber" value="2"/>
    </module>
  </module>
</module>
        

Example:

class Example11 {
  void testMethod1() {
    int x = 1;
    int z = x + 2;
  }
  // violation below, 'Count of 3 for 'METHOD_DEF' descendant'
  void testMethod2() {
    int x = 1;
    int y = 2;
    int z = x + y;
  }
}
        

To configure the check to produce a violation on an empty statement:

<module name="Checker">
  <module name="TreeWalker">
    <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>
  </module>
</module>
        

Example:

class Example12 {
  void testMethod1 () {
    System.out.println("Hello");
  }
  void testMethod2() {
      ; // violation, 'Empty statement is not allowed'
  }
}
        

To configure the check to produce a violation on a class or interface with too many fields:

<module name="Checker">
  <module name="TreeWalker">
    <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>
  </module>
</module>
        

Example:

class Example13 {
  private int field1;

  // Some code
}
// violation below, 'Count of 2 for 'CLASS_DEF' descendant'
class ExampleTest {
  private int field1;
  private int field2;

  // Some code
}
interface Test1 {
  int FIELD_1 = 1;
}
// violation below,'Count of 2 for 'INTERFACE_DEF' descendant'
interface Test2 {
  int FIELD_1 = 1;
  int FIELD_2 = 2;
}
        

To configure the check to produce a violation on comparing this with null:

<module name="Checker">
  <module name="TreeWalker">
    <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>
  </module>
</module>
        

Example:

class Example14 {
  void testMethod1() {
    // violation below, 'Total count of 2 exceeds maximum count 1'
    if (this == null) {
      System.out.println("xyz");
    }
    if (this != null) {
      // violation above, 'Total count of 2 exceeds maximum count 1'
      System.out.println("xyz");
    }

    Object obj = new Object();
    if (obj == null) {
      System.out.println("xyz");
    }
    if (obj != null) {
      System.out.println("xyz");
    }
  }
}
        

To configure the check to produce a violation on a String literal equality check:

<module name="Checker">
  <module name="TreeWalker">
    <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>
  </module>
</module>
        

Example:

class Example15 {
  void testMethod1() {
    String str = "abc";
    if (str.equals("abc")) {
      System.out.println("equal.");
    }
    if (str == "abc") { // violation, 'Count of 1 for 'EQUAL' descendant'
      System.out.println("equal.");
    }
  }
}
        

To configure the check to produce a violation on an assert statement that may have side effects:

<module name="Checker">
  <module name="TreeWalker">
    <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>
  </module>
</module>
        

Example:

class Example16 {
  void testMethod1() {
    int a = 5;
    // violation below, 'Count of 1 for 'LITERAL_ASSERT' descendant'
    assert a++ == 0 : "is not";
    System.out.println(a);
    assert a == 0 : "is not";
  }
}
        

Example of Usage

Violation Messages

All messages can be customized if the default message doesn't suit you. Please see the documentation to learn how to.

Package

com.puppycrawl.tools.checkstyle.checks

Parent Module

TreeWalker