1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.blocks;
21
22 import java.util.Locale;
23
24 import com.puppycrawl.tools.checkstyle.StatelessCheck;
25 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
26 import com.puppycrawl.tools.checkstyle.api.DetailAST;
27 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
28 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 @StatelessCheck
118 public class EmptyBlockCheck
119 extends AbstractCheck {
120
121
122
123
124
125 public static final String MSG_KEY_BLOCK_NO_STATEMENT = "block.noStatement";
126
127
128
129
130
131 public static final String MSG_KEY_BLOCK_EMPTY = "block.empty";
132
133
134 private BlockOption option = BlockOption.STATEMENT;
135
136
137
138
139
140
141 public void setOption(String optionStr) {
142 option = BlockOption.valueOf(optionStr.trim().toUpperCase(Locale.ENGLISH));
143 }
144
145 @Override
146 public int[] getDefaultTokens() {
147 return new int[] {
148 TokenTypes.LITERAL_WHILE,
149 TokenTypes.LITERAL_TRY,
150 TokenTypes.LITERAL_FINALLY,
151 TokenTypes.LITERAL_DO,
152 TokenTypes.LITERAL_IF,
153 TokenTypes.LITERAL_ELSE,
154 TokenTypes.LITERAL_FOR,
155 TokenTypes.INSTANCE_INIT,
156 TokenTypes.STATIC_INIT,
157 TokenTypes.LITERAL_SWITCH,
158 TokenTypes.LITERAL_SYNCHRONIZED,
159 };
160 }
161
162 @Override
163 public int[] getAcceptableTokens() {
164 return new int[] {
165 TokenTypes.LITERAL_WHILE,
166 TokenTypes.LITERAL_TRY,
167 TokenTypes.LITERAL_CATCH,
168 TokenTypes.LITERAL_FINALLY,
169 TokenTypes.LITERAL_DO,
170 TokenTypes.LITERAL_IF,
171 TokenTypes.LITERAL_ELSE,
172 TokenTypes.LITERAL_FOR,
173 TokenTypes.INSTANCE_INIT,
174 TokenTypes.STATIC_INIT,
175 TokenTypes.LITERAL_SWITCH,
176 TokenTypes.LITERAL_SYNCHRONIZED,
177 TokenTypes.LITERAL_CASE,
178 TokenTypes.LITERAL_DEFAULT,
179 TokenTypes.ARRAY_INIT,
180 };
181 }
182
183 @Override
184 public int[] getRequiredTokens() {
185 return CommonUtil.EMPTY_INT_ARRAY;
186 }
187
188 @Override
189 public void visitToken(DetailAST ast) {
190 final DetailAST leftCurly = findLeftCurly(ast);
191 if (leftCurly != null) {
192 if (option == BlockOption.STATEMENT) {
193 final boolean emptyBlock;
194 if (leftCurly.getType() == TokenTypes.LCURLY) {
195 emptyBlock = leftCurly.getNextSibling().getType() != TokenTypes.CASE_GROUP;
196 }
197 else {
198 emptyBlock = leftCurly.getChildCount() <= 1;
199 }
200 if (emptyBlock) {
201 log(leftCurly,
202 MSG_KEY_BLOCK_NO_STATEMENT,
203 ast.getText());
204 }
205 }
206 else if (!hasText(leftCurly)) {
207 log(leftCurly,
208 MSG_KEY_BLOCK_EMPTY,
209 ast.getText());
210 }
211 }
212 }
213
214
215
216
217
218
219 private boolean hasText(final DetailAST slistAST) {
220 final DetailAST rightCurly = slistAST.findFirstToken(TokenTypes.RCURLY);
221 final DetailAST rcurlyAST;
222
223 if (rightCurly == null) {
224 rcurlyAST = slistAST.getParent().findFirstToken(TokenTypes.RCURLY);
225 }
226 else {
227 rcurlyAST = rightCurly;
228 }
229 final int slistLineNo = slistAST.getLineNo();
230 final int slistColNo = slistAST.getColumnNo();
231 final int rcurlyLineNo = rcurlyAST.getLineNo();
232 final int rcurlyColNo = rcurlyAST.getColumnNo();
233 final String[] lines = getLines();
234 boolean returnValue = false;
235 if (slistLineNo == rcurlyLineNo) {
236
237 final String txt = lines[slistLineNo - 1]
238 .substring(slistColNo + 1, rcurlyColNo);
239 if (!CommonUtil.isBlank(txt)) {
240 returnValue = true;
241 }
242 }
243 else {
244 final String firstLine = lines[slistLineNo - 1].substring(slistColNo + 1);
245 final String lastLine = lines[rcurlyLineNo - 1].substring(0, rcurlyColNo);
246
247 returnValue = !(CommonUtil.isBlank(firstLine) && CommonUtil.isBlank(lastLine))
248 || !checkIsAllLinesAreWhitespace(lines, slistLineNo, rcurlyLineNo);
249 }
250 return returnValue;
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264 private static boolean checkIsAllLinesAreWhitespace(String[] lines, int lineFrom, int lineTo) {
265 boolean result = true;
266 for (int i = lineFrom; i < lineTo - 1; i++) {
267 if (!CommonUtil.isBlank(lines[i])) {
268 result = false;
269 break;
270 }
271 }
272 return result;
273 }
274
275
276
277
278
279
280
281 private static DetailAST findLeftCurly(DetailAST ast) {
282 final DetailAST leftCurly;
283 final DetailAST slistAST = ast.findFirstToken(TokenTypes.SLIST);
284 if ((ast.getType() == TokenTypes.LITERAL_CASE
285 || ast.getType() == TokenTypes.LITERAL_DEFAULT)
286 && ast.getNextSibling() != null
287 && ast.getNextSibling().getFirstChild() != null
288 && ast.getNextSibling().getFirstChild().getType() == TokenTypes.SLIST) {
289 leftCurly = ast.getNextSibling().getFirstChild();
290 }
291 else if (slistAST == null) {
292 leftCurly = ast.findFirstToken(TokenTypes.LCURLY);
293 }
294 else {
295 leftCurly = slistAST;
296 }
297 return leftCurly;
298 }
299
300 }