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 java.util.Arrays;
23
24 import com.puppycrawl.tools.checkstyle.api.DetailAST;
25 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
26
27 /**
28 * Handler for a list of statements.
29 *
30 */
31 public class SlistHandler extends BlockParentHandler {
32
33 /**
34 * Parent token types.
35 */
36 private static final int[] PARENT_TOKEN_TYPES = {
37 TokenTypes.CTOR_DEF,
38 TokenTypes.METHOD_DEF,
39 TokenTypes.STATIC_INIT,
40 TokenTypes.LITERAL_SYNCHRONIZED,
41 TokenTypes.LITERAL_IF,
42 TokenTypes.LITERAL_WHILE,
43 TokenTypes.LITERAL_DO,
44 TokenTypes.LITERAL_FOR,
45 TokenTypes.LITERAL_ELSE,
46 TokenTypes.LITERAL_TRY,
47 TokenTypes.LITERAL_CATCH,
48 TokenTypes.LITERAL_FINALLY,
49 };
50
51 static {
52 // Array sorting for binary search
53 Arrays.sort(PARENT_TOKEN_TYPES);
54 }
55
56 /**
57 * Construct an instance of this handler with the given indentation check,
58 * abstract syntax tree, and parent handler.
59 *
60 * @param indentCheck the indentation check
61 * @param ast the abstract syntax tree
62 * @param parent the parent handler
63 */
64 public SlistHandler(IndentationCheck indentCheck,
65 DetailAST ast, AbstractExpressionHandler parent) {
66 super(indentCheck, "block", ast, parent);
67 }
68
69 @Override
70 public IndentLevel getSuggestedChildIndent(AbstractExpressionHandler child) {
71 // this is:
72 // switch (var) {
73 // case 3: {
74 // break;
75 // }
76 // }
77 // ... the case SLIST is followed by a user-created SLIST and
78 // preceded by a switch
79
80 final IndentLevel result;
81 // if our parent is a block handler we want to be transparent
82 if (getParent() instanceof BlockParentHandler
83 && !(getParent() instanceof SlistHandler)
84 || child instanceof SlistHandler
85 && getParent() instanceof CaseHandler) {
86 result = getParent().getSuggestedChildIndent(child);
87 }
88 else {
89 result = super.getSuggestedChildIndent(child);
90 }
91 return result;
92 }
93
94 @Override
95 protected DetailAST getListChild() {
96 return getMainAst();
97 }
98
99 @Override
100 protected DetailAST getLeftCurly() {
101 return getMainAst();
102 }
103
104 @Override
105 protected DetailAST getRightCurly() {
106 return getMainAst().findFirstToken(TokenTypes.RCURLY);
107 }
108
109 @Override
110 protected DetailAST getTopLevelAst() {
111 return null;
112 }
113
114 /**
115 * Determine if the expression we are handling has a block parent.
116 *
117 * @return true if it does, false otherwise
118 */
119 private boolean hasBlockParent() {
120 final int parentType = getMainAst().getParent().getType();
121 return Arrays.binarySearch(PARENT_TOKEN_TYPES, parentType) >= 0;
122 }
123
124 @Override
125 public void checkIndentation() {
126 // only need to check this if parent is not
127 // an if, else, while, do, ctor, method
128 if (!hasBlockParent() && !isSameLineCaseGroup()) {
129 super.checkIndentation();
130 }
131 }
132
133 /**
134 * Checks if SLIST node is placed at the same line as CASE_GROUP node.
135 * @return true, if SLIST node is places at the same line as CASE_GROUP node.
136 */
137 private boolean isSameLineCaseGroup() {
138 final DetailAST parentNode = getMainAst().getParent();
139 return parentNode.getType() == TokenTypes.CASE_GROUP
140 && getMainAst().getLineNo() == parentNode.getLineNo();
141 }
142
143 }