1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 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.getChildCount() == 0) {
72              if (getMainAst().getType() != TokenTypes.ANNOTATION_DEF) {
73                  final DetailAST ident = getMainAst().findFirstToken(TokenTypes.IDENT);
74                  final int lineStart = getLineStart(ident);
75                  if (!getIndent().isAcceptable(lineStart)) {
76                      logError(ident, "ident", lineStart);
77                  }
78              }
79          }
80          else {
81              checkModifiers();
82          }
83          if (getMainAst().getType() == TokenTypes.ANNOTATION_DEF) {
84              final DetailAST atAst = getMainAst().findFirstToken(TokenTypes.AT);
85              if (isOnStartOfLine(atAst)) {
86                  checkWrappingIndentation(getMainAst(), getListChild(), 0,
87                          getIndent().getFirstIndentLevel(), false);
88              }
89          }
90          else {
91              checkWrappingIndentation(getMainAst(), getListChild());
92          }
93          super.checkIndentation();
94      }
95  
96      @Override
97      protected int[] getCheckedChildren() {
98          return new int[] {
99              TokenTypes.EXPR,
100             TokenTypes.OBJBLOCK,
101             TokenTypes.LITERAL_BREAK,
102             TokenTypes.LITERAL_RETURN,
103             TokenTypes.LITERAL_THROW,
104             TokenTypes.LITERAL_CONTINUE,
105         };
106     }
107 
108     /**
109      * Creates a handler name for this class according to ast type.
110      *
111      * @param ast the abstract syntax tree.
112      * @return handler name for this class.
113      */
114     private static String getHandlerName(DetailAST ast) {
115         final String name;
116 
117         if (ast.getType() == TokenTypes.CLASS_DEF) {
118             name = "class def";
119         }
120         else if (ast.getType() == TokenTypes.ENUM_DEF) {
121             name = "enum def";
122         }
123         else if (ast.getType() == TokenTypes.ANNOTATION_DEF) {
124             name = "annotation def";
125         }
126         else {
127             name = "interface def";
128         }
129         return name;
130     }
131 
132 }