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 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="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 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="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 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="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 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 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 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="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 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="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 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="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 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="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 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="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 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="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 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="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 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="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 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 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 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="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 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="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 Test {
  public void foo() {
    int a = 5;
    assert a++ == 0 : "is not"; // violation
    System.out.println(a);
    assert a == 0 : "is not"; // ok
  }
}
        

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