View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2026 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.checks.indentation;
21  
22  import com.puppycrawl.tools.checkstyle.api.DetailAST;
23  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
24  
25  /**
26   * Handler for class definitions.
27   *
28   */
29  public class ClassDefHandler extends BlockParentHandler {
30  
31      /**
32       * Construct an instance of this handler with the given indentation check,
33       * abstract syntax tree, and parent handler.
34       *
35       * @param indentCheck   the indentation check
36       * @param ast           the abstract syntax tree
37       * @param parent        the parent handler
38       */
39      public ClassDefHandler(IndentationCheck indentCheck,
40                             DetailAST ast,
41                             AbstractExpressionHandler parent) {
42          super(indentCheck, getHandlerName(ast), ast, parent);
43      }
44  
45      @Override
46      protected DetailAST getLeftCurly() {
47          return getMainAst().findFirstToken(TokenTypes.OBJBLOCK)
48              .findFirstToken(TokenTypes.LCURLY);
49      }
50  
51      @Override
52      protected DetailAST getRightCurly() {
53          return getMainAst().findFirstToken(TokenTypes.OBJBLOCK)
54              .findFirstToken(TokenTypes.RCURLY);
55      }
56  
57      @Override
58      protected DetailAST getTopLevelAst() {
59          return null;
60          // note: ident checked by hand in check indentation;
61      }
62  
63      @Override
64      protected DetailAST getListChild() {
65          return getMainAst().findFirstToken(TokenTypes.OBJBLOCK);
66      }
67  
68      @Override
69      public void checkIndentation() {
70          final DetailAST modifiers = getMainAst().findFirstToken(TokenTypes.MODIFIERS);
71          if (modifiers.hasChildren()) {
72              checkModifiers();
73          }
74          else {
75              if (getMainAst().getType() != TokenTypes.ANNOTATION_DEF) {
76                  final DetailAST ident = getMainAst().findFirstToken(TokenTypes.IDENT);
77                  DetailAST tokenToCheck = getMainAst();
78                  if (ident.getLineNo() == getMainAst().getLineNo()) {
79                      tokenToCheck = ident;
80                  }
81                  final int lineStart = getLineStart(tokenToCheck);
82                  if (!getIndent().isAcceptable(lineStart)) {
83                      logError(tokenToCheck, "ident", lineStart);
84                  }
85              }
86          }
87          if (getMainAst().getType() == TokenTypes.ANNOTATION_DEF) {
88              final DetailAST atAst = getMainAst().findFirstToken(TokenTypes.AT);
89              if (isOnStartOfLine(atAst)) {
90                  checkWrappingIndentation(getMainAst(), getListChild(), 0,
91                          getIndent().getFirstIndentLevel(), false);
92              }
93          }
94          else {
95              checkWrappingIndentation(getMainAst(), getListChild());
96          }
97          super.checkIndentation();
98      }
99  
100     @Override
101     protected int[] getCheckedChildren() {
102         return new int[] {
103             TokenTypes.EXPR,
104             TokenTypes.OBJBLOCK,
105             TokenTypes.LITERAL_BREAK,
106             TokenTypes.LITERAL_RETURN,
107             TokenTypes.LITERAL_THROW,
108             TokenTypes.LITERAL_CONTINUE,
109         };
110     }
111 
112     /**
113      * Creates a handler name for this class according to ast type.
114      *
115      * @param ast the abstract syntax tree.
116      * @return handler name for this class.
117      */
118     private static String getHandlerName(DetailAST ast) {
119         final int tokenType = ast.getType();
120 
121         return switch (tokenType) {
122             case TokenTypes.CLASS_DEF -> "class def";
123             case TokenTypes.ENUM_DEF -> "enum def";
124             case TokenTypes.ANNOTATION_DEF -> "annotation def";
125             case TokenTypes.RECORD_DEF -> "record def";
126             default -> "interface def";
127         };
128     }
129 
130 }