Class CommentsIndentationCheck

  • All Implemented Interfaces:
    Configurable, Contextualizable

    public class CommentsIndentationCheck
    extends AbstractCheck

    Controls the indentation between comments and surrounding code. Comments are indented at the same level as the surrounding code. Detailed info about such convention can be found here

    Please take a look at the following examples to understand how the check works:

    Example #1: Block comments.

     1   /*
     2    * it is Ok
     3    */
     4   boolean bool = true;
     5
     6     /* violation
     7      * (block comment should have the same indentation level as line 9)
     8      */
     9   double d = 3.14;
     

    Example #2: Comment is placed at the end of the block and has previous statement.

     1   public void foo1() {
     2     foo2();
     3     // it is OK
     4   }
     5
     6   public void foo2() {
     7     foo3();
     8       // violation (comment should have the same indentation level as line 7)
     9   }
     

    Example #3: Comment is used as a single line border to separate groups of methods.

     1   /////////////////////////////// it is OK
     2
     3   public void foo7() {
     4     int a = 0;
     5   }
     6
     7     ///////////////////////////// violation (should have the same indentation level as line 9)
     8
     9   public void foo8() {}
     

    Example #4: Comment has distributed previous statement.

     1   public void foo11() {
     2     CheckUtil
     3       .getFirstNode(new DetailAST())
     4       .getFirstChild()
     5       .getNextSibling();
     6     // it is OK
     7   }
     8
     9   public void foo12() {
     10    CheckUtil
     11      .getFirstNode(new DetailAST())
     12      .getFirstChild()
     13      .getNextSibling();
     14              // violation (should have the same indentation level as line 10)
     15  }
     

    Example #5: Single line block comment is placed within an empty code block. Note, if comment is placed at the end of the empty code block, we have Checkstyle's limitations to clearly detect user intention of explanation target - above or below. The only case we can assume as a violation is when a single line comment within the empty code block has indentation level that is lower than the indentation level of the closing right curly brace.

     1   public void foo46() {
     2     // comment
     3     // block
     4     // it is OK (we cannot clearly detect user intention of explanation target)
     5   }
     6
     7   public void foo46() {
     8  // comment
     9  // block
     10 // violation (comment should have the same indentation level as line 11)
     11  }
     

    Example #6: 'fallthrough' comments and similar.

     0   switch(a) {
     1     case "1":
     2       int k = 7;
     3       // it is OK
     4     case "2":
     5       int k = 7;
     6     // it is OK
     7     case "3":
     8       if (true) {}
     9           // violation (should have the same indentation level as line 8 or 10)
     10    case "4":
     11    case "5": {
     12      int a;
     13    }
     14    // fall through (it is OK)
     15    case "12": {
     16      int a;
     17    }
     18    default:
     19      // it is OK
     20  }
     

    Example #7: Comment is placed within a distributed statement.

     1   String breaks = "J"
     2   // violation (comment should have the same indentation level as line 3)
     3       + "A"
     4       // it is OK
     5       + "V"
     6       + "A"
     7   // it is OK
     8   ;
     

    Example #8: Comment is placed within an empty case block. Note, if comment is placed at the end of the empty case block, we have Checkstyle's limitations to clearly detect user intention of explanation target - above or below. The only case we can assume as a violation is when a single line comment within the empty case block has indentation level that is lower than the indentation level of the next case token.

     1   case 4:
     2     // it is OK
     3   case 5:
     4  // violation (should have the same indentation level as line 3 or 5)
     5   case 6:
     

    Example #9: Single line block comment has previous and next statement.

     1   String s1 = "Clean code!";
     2      s.toString().toString().toString();
     3   // single line
     4   // block
     5   // comment (it is OK)
     6   int a = 5;
     7
     8   String s2 = "Code complete!";
     9    s.toString().toString().toString();
     10            // violation (should have the same indentation level as line 11)
     11       // violation (should have the same indentation level as line 12)
     12     // violation (should have the same indentation level as line 13)
     13  int b = 18;
     

    Example #10: Comment within the block tries to describe the next code block.

     1   public void foo42() {
     2     int a = 5;
     3     if (a == 5) {
     4       int b;
     5       // it is OK
     6      } else if (a ==6) { ... }
     7   }
     8
     9   public void foo43() {
     10    try {
     11      int a;
     12     // Why do we catch exception here? - violation (not the same indentation as line 11)
     13     } catch (Exception e) { ... }
     14  }
     

    To configure the Check:

     <module name="CommentsIndentation"/>
     

    Parent is com.puppycrawl.tools.checkstyle.TreeWalker

    Violation Message Keys:

    • comments.indentation.block
    • comments.indentation.single
    Since:
    6.10
    • 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 class AbstractCheck
        Returns:
        the token set this check is designed for.
        See Also:
        TokenTypes
      • visitComment

        private void visitComment​(DetailAST comment)
        Checks comment indentations over surrounding code, e.g.:

        // some comment - this is ok double d = 3.14; // some comment - this is <b>not</b> ok. double d1 = 5.0;

        Parameters:
        comment - comment to check.
      • getNextStmt

        private static DetailAST getNextStmt​(DetailAST comment)
        Returns the next statement of a comment.
        Parameters:
        comment - comment.
        Returns:
        the next statement of a comment.
      • getPreviousStatement

        private DetailAST getPreviousStatement​(DetailAST comment)
        Returns the previous statement of a comment.
        Parameters:
        comment - comment.
        Returns:
        the previous statement of a comment.
      • isDistributedPreviousStatement

        private boolean isDistributedPreviousStatement​(DetailAST comment)
        Checks whether the previous statement of a comment is distributed over two or more lines.
        Parameters:
        comment - comment to check.
        Returns:
        true if the previous statement of a comment is distributed over two or more lines.
      • isDistributedExpression

        private boolean isDistributedExpression​(DetailAST comment)
        Checks whether the previous statement of a comment is a method call chain or string concatenation statement distributed over two ore more lines.
        Parameters:
        comment - comment to check.
        Returns:
        true if the previous statement is a distributed expression.
      • isStatementWithPossibleCurlies

        private static boolean isStatementWithPossibleCurlies​(DetailAST previousSibling)
        Whether the statement can have or always have curly brackets.
        Parameters:
        previousSibling - the statement to check.
        Returns:
        true if the statement can have or always have curly brackets.
      • isDefinition

        private static boolean isDefinition​(DetailAST previousSibling)
        Whether the statement is a kind of definition (method, class etc.).
        Parameters:
        previousSibling - the statement to check.
        Returns:
        true if the statement is a kind of definition.
      • isDistributedReturnStatement

        private static boolean isDistributedReturnStatement​(DetailAST commentPreviousSibling)
        Checks whether the previous statement of a comment is a distributed return statement.
        Parameters:
        commentPreviousSibling - previous sibling of the comment.
        Returns:
        true if the previous statement of a comment is a distributed return statement.
      • isDistributedThrowStatement

        private static boolean isDistributedThrowStatement​(DetailAST commentPreviousSibling)
        Checks whether the previous statement of a comment is a distributed throw statement.
        Parameters:
        commentPreviousSibling - previous sibling of the comment.
        Returns:
        true if the previous statement of a comment is a distributed throw statement.
      • getDistributedPreviousStatement

        private static DetailAST getDistributedPreviousStatement​(DetailAST comment)
        Returns the first token of the distributed previous statement of comment.
        Parameters:
        comment - comment to check.
        Returns:
        the first token of the distributed previous statement of comment.
      • isInEmptyCaseBlock

        private static boolean isInEmptyCaseBlock​(DetailAST prevStmt,
                                                  DetailAST nextStmt)
        Checks whether case block is empty.
        Parameters:
        prevStmt - next statement.
        nextStmt - previous statement.
        Returns:
        true if case block is empty.
      • isFallThroughComment

        private static boolean isFallThroughComment​(DetailAST prevStmt,
                                                    DetailAST nextStmt)
        Checks whether comment is a 'fall through' comment. For example:

        ... case OPTION_ONE: int someVariable = 1; // fall through case OPTION_TWO: int a = 5; break; ...

        Parameters:
        prevStmt - previous statement.
        nextStmt - next statement.
        Returns:
        true if a comment is a 'fall through' comment.
      • isCommentAtTheEndOfTheCodeBlock

        private static boolean isCommentAtTheEndOfTheCodeBlock​(DetailAST nextStmt)
        Checks whether a comment is placed at the end of the code block.
        Parameters:
        nextStmt - next statement.
        Returns:
        true if a comment is placed at the end of the block.
      • isInEmptyCodeBlock

        private static boolean isInEmptyCodeBlock​(DetailAST prevStmt,
                                                  DetailAST nextStmt)
        Checks whether comment is placed in the empty code block. For example:

        ... // empty code block ...

        Note, the method does not treat empty case blocks.
        Parameters:
        prevStmt - previous statement.
        nextStmt - next statement.
        Returns:
        true if comment is placed in the empty code block.
      • handleCommentInEmptyCaseBlock

        private void handleCommentInEmptyCaseBlock​(DetailAST prevStmt,
                                                   DetailAST comment,
                                                   DetailAST nextStmt)
        Handles a comment which is placed within empty case block. Note, if comment is placed at the end of the empty case block, we have Checkstyle's limitations to clearly detect user intention of explanation target - above or below. The only case we can assume as a violation is when a single line comment within the empty case block has indentation level that is lower than the indentation level of the next case token. For example:

        ... case OPTION_ONE: // violation case OPTION_TWO: ...

        Parameters:
        prevStmt - previous statement.
        comment - single line comment.
        nextStmt - next statement.
      • handleFallThroughComment

        private void handleFallThroughComment​(DetailAST prevStmt,
                                              DetailAST comment,
                                              DetailAST nextStmt)
        Handles 'fall through' single line comment. Note, 'fall through' and similar comments can have indentation level as next or previous statement. For example:

        ... case OPTION_ONE: int someVariable = 1; // fall through - OK case OPTION_TWO: int a = 5; break; ...

        ... case OPTION_ONE: int someVariable = 1; // then init variable a - OK case OPTION_TWO: int a = 5; break; ...

        Parameters:
        prevStmt - previous statement.
        comment - single line comment.
        nextStmt - next statement.
      • handleCommentAtTheEndOfTheCodeBlock

        private void handleCommentAtTheEndOfTheCodeBlock​(DetailAST prevStmt,
                                                         DetailAST comment,
                                                         DetailAST nextStmt)
        Handles a comment which is placed at the end of non empty code block. Note, if single line comment is placed at the end of non empty block the comment should have the same indentation level as the previous statement. For example:

        if (a == true) { int b = 1; // comment }

        Parameters:
        prevStmt - previous statement.
        comment - comment to check.
        nextStmt - next statement.
      • isCommentForMultiblock

        private static boolean isCommentForMultiblock​(DetailAST endBlockStmt)
        Whether the comment might have been used for the next block in a multi-block structure.
        Parameters:
        endBlockStmt - the end of the current block.
        Returns:
        true, if the comment might have been used for the next block in a multi-block structure.
      • handleCommentInEmptyCodeBlock

        private void handleCommentInEmptyCodeBlock​(DetailAST comment,
                                                   DetailAST nextStmt)
        Handles a comment which is placed within the empty code block. Note, if comment is placed at the end of the empty code block, we have Checkstyle's limitations to clearly detect user intention of explanation target - above or below. The only case we can assume as a violation is when a single line comment within the empty code block has indentation level that is lower than the indentation level of the closing right curly brace. For example:

        if (a == true) { // violation }

        Parameters:
        comment - comment to check.
        nextStmt - next statement.
      • getOneLinePreviousStatement

        private DetailAST getOneLinePreviousStatement​(DetailAST comment)
        Does pre-order traverse of abstract syntax tree to find the previous statement of the comment. If previous statement of the comment is found, then the traverse will be finished.
        Parameters:
        comment - current statement.
        Returns:
        previous statement of the comment or null if the comment does not have previous statement.
      • isComment

        private static boolean isComment​(DetailAST ast)
        Whether the ast is a comment.
        Parameters:
        ast - the ast to check.
        Returns:
        true if the ast is a comment.
      • isBlockStart

        private static boolean isBlockStart​(DetailAST root)
        Whether the AST node starts a block.
        Parameters:
        root - the AST node to check.
        Returns:
        true if the AST node starts a block.
      • findPreviousStatement

        private DetailAST findPreviousStatement​(DetailAST comment,
                                                DetailAST root)
        Finds a previous statement of the comment. Uses root token of the line while searching.
        Parameters:
        comment - comment.
        root - root token of the line.
        Returns:
        previous statement of the comment or null if previous statement was not found.
      • isUsingOfObjectReferenceToInvokeMethod

        private static boolean isUsingOfObjectReferenceToInvokeMethod​(DetailAST root)
        Checks whether there is a use of an object reference to invoke an object's method on line.
        Parameters:
        root - root token of the line.
        Returns:
        true if there is a use of an object reference to invoke an object's method on line.
      • findStartTokenOfMethodCallChain

        private static DetailAST findStartTokenOfMethodCallChain​(DetailAST root)
        Finds the start token of method call chain.
        Parameters:
        root - root token of the line.
        Returns:
        the start token of method call chain.
      • isOnPreviousLineIgnoringComments

        private boolean isOnPreviousLineIgnoringComments​(DetailAST currentStatement,
                                                         DetailAST checkedStatement)
        Checks whether the checked statement is on the previous line ignoring empty lines and lines which contain only comments.
        Parameters:
        currentStatement - current statement.
        checkedStatement - checked statement.
        Returns:
        true if checked statement is on the line which is previous to current statement ignoring empty lines and lines which contain only comments.
      • getNextToken

        private DetailAST getNextToken​(DetailAST checkedStatement)
        Get the token to start counting the number of lines to add to the distance aim from.
        Parameters:
        checkedStatement - the checked statement.
        Returns:
        the token to start counting the number of lines to add to the distance aim from.
      • countEmptyLines

        private int countEmptyLines​(DetailAST startStatement,
                                    DetailAST endStatement)
        Count the number of empty lines between statements.
        Parameters:
        startStatement - start statement.
        endStatement - end statement.
        Returns:
        the number of empty lines between statements.
      • logMultilineIndentation

        private void logMultilineIndentation​(DetailAST prevStmt,
                                             DetailAST comment,
                                             DetailAST nextStmt)
        Logs comment which can have the same indentation level as next or previous statement.
        Parameters:
        prevStmt - previous statement.
        comment - comment.
        nextStmt - next statement.
      • getMessageKey

        private static String getMessageKey​(DetailAST comment)
        Get a message key depending on a comment type.
        Parameters:
        comment - the comment to process.
        Returns:
        a message key.
      • getPrevStatementWhenCommentIsUnderCase

        private static DetailAST getPrevStatementWhenCommentIsUnderCase​(DetailAST parentStatement)
        Gets previous statement for comment which is placed immediately under case.
        Parameters:
        parentStatement - comment's parent statement.
        Returns:
        comment's previous statement or null if previous statement is absent.
      • getPrevCaseToken

        private static DetailAST getPrevCaseToken​(DetailAST parentStatement)
        Gets previous case-token for comment.
        Parameters:
        parentStatement - comment's parent statement.
        Returns:
        previous case-token or null if previous case-token is absent.
      • areSameLevelIndented

        private boolean areSameLevelIndented​(DetailAST comment,
                                             DetailAST prevStmt,
                                             DetailAST nextStmt)
        Checks if comment and next code statement (or previous code stmt like case in switch block) are indented at the same level, e.g.:
         
         // some comment - same indentation level
         int x = 10;
             // some comment - different indentation level
         int x1 = 5;
         /*
          *
          *&#47;
          boolean bool = true; - same indentation level
         
         
        Parameters:
        comment - single line comment.
        prevStmt - previous code statement.
        nextStmt - next code statement.
        Returns:
        true if comment and next code statement are indented at the same level.
      • getLineStart

        private int getLineStart​(int lineNo)
        Get a column number where a code starts.
        Parameters:
        lineNo - the line number to get column number in.
        Returns:
        the column number where a code starts.
      • isTrailingComment

        private boolean isTrailingComment​(DetailAST comment)
        Checks if current comment is a trailing comment.
        Parameters:
        comment - comment to check.
        Returns:
        true if current comment is a trailing comment.
      • isTrailingSingleLineComment

        private boolean isTrailingSingleLineComment​(DetailAST singleLineComment)
        Checks if current single line comment is trailing comment, e.g.:

        double d = 3.14; // some comment

        Parameters:
        singleLineComment - single line comment.
        Returns:
        true if current single line comment is trailing comment.
      • isTrailingBlockComment

        private boolean isTrailingBlockComment​(DetailAST blockComment)
        Checks if current comment block is trailing comment, e.g.:

        double d = 3.14; /* some comment *&#47; /* some comment *&#47; double d = 18.5;

        Parameters:
        blockComment - block comment begin.
        Returns:
        true if current comment block is trailing comment.
      • areInSameMethodCallWithSameIndent

        private static boolean areInSameMethodCallWithSameIndent​(DetailAST comment)
        Checks if the comment is inside a method call with same indentation of first expression. e.g:

        private final boolean myList = someMethod( // Some comment here s1, s2, s3 // ok );

        Parameters:
        comment - comment to check.
        Returns:
        true, if comment is inside inside a method call with same indentation.
      • getFirstExpressionNodeFromMethodCall

        private static DetailAST getFirstExpressionNodeFromMethodCall​(DetailAST methodCall)
        Returns the first EXPR DetailAST child from parent of comment.
        Parameters:
        methodCall - methodCall DetailAst from which node to be extracted.
        Returns:
        first EXPR DetailAST child from parent of comment.