View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2018 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 member definitions.
27   *
28   * @author o_sukhodolsky
29   */
30  public class MemberDefHandler extends AbstractExpressionHandler {
31  
32      /**
33       * Construct an instance of this handler with the given indentation check,
34       * abstract syntax tree, and parent handler.
35       *
36       * @param indentCheck   the indentation check
37       * @param ast           the abstract syntax tree
38       * @param parent        the parent handler
39       */
40      public MemberDefHandler(IndentationCheck indentCheck,
41          DetailAST ast, AbstractExpressionHandler parent) {
42          super(indentCheck, "member def", ast, parent);
43      }
44  
45      @Override
46      public void checkIndentation() {
47          final DetailAST modifiersNode = getMainAst().findFirstToken(TokenTypes.MODIFIERS);
48          if (modifiersNode.getChildCount() == 0) {
49              checkType();
50          }
51          else {
52              checkModifiers();
53          }
54          final DetailAST firstNode = getMainAst();
55          final DetailAST lastNode = getVarDefStatementSemicolon(firstNode);
56  
57          if (lastNode != null && !isArrayDeclaration(firstNode)) {
58              checkWrappingIndentation(firstNode, lastNode);
59          }
60      }
61  
62      @Override
63      public IndentLevel getSuggestedChildIndent(AbstractExpressionHandler child) {
64          return getIndent();
65      }
66  
67      @Override
68      protected void checkModifiers() {
69          final DetailAST modifier = getMainAst().findFirstToken(TokenTypes.MODIFIERS);
70          if (isOnStartOfLine(modifier)
71              && !getIndent().isAcceptable(expandedTabsColumnNo(modifier))) {
72              logError(modifier, "modifier", expandedTabsColumnNo(modifier));
73          }
74      }
75  
76      /**
77       * Check the indentation of the method type.
78       */
79      private void checkType() {
80          final DetailAST type = getMainAst().findFirstToken(TokenTypes.TYPE);
81          final DetailAST ident = AbstractExpressionHandler.getFirstToken(type);
82          final int columnNo = expandedTabsColumnNo(ident);
83          if (isOnStartOfLine(ident) && !getIndent().isAcceptable(columnNo)) {
84              logError(ident, "type", columnNo);
85          }
86      }
87  
88      /**
89       * Checks if variable_def node is array declaration.
90       * @param variableDef current variable_def.
91       * @return true if variable_def node is array declaration.
92       */
93      private static boolean isArrayDeclaration(DetailAST variableDef) {
94          return variableDef.findFirstToken(TokenTypes.TYPE)
95              .findFirstToken(TokenTypes.ARRAY_DECLARATOR) != null;
96      }
97  
98      /**
99       * Returns semicolon for variable definition statement.
100      * @param variableDef
101      *          ast node of type TokenTypes.VARIABLE_DEF
102      * @return ast node of type TokenTypes.SEMI
103      */
104     private static DetailAST getVarDefStatementSemicolon(DetailAST variableDef) {
105         DetailAST lastNode = variableDef.getLastChild();
106         if (lastNode.getType() != TokenTypes.SEMI) {
107             lastNode = variableDef.getNextSibling();
108         }
109         return lastNode;
110     }
111 
112 }