1 | //////////////////////////////////////////////////////////////////////////////// | |
2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
3 | // Copyright (C) 2001-2017 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.whitespace; | |
21 | ||
22 | import com.puppycrawl.tools.checkstyle.api.AbstractCheck; | |
23 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
24 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
25 | import com.puppycrawl.tools.checkstyle.utils.CommonUtils; | |
26 | ||
27 | /** | |
28 | * Checks that a token is surrounded by whitespace. | |
29 | * | |
30 | * <p>By default the check will check the following operators: | |
31 | * {@link TokenTypes#LITERAL_ASSERT ASSERT}, | |
32 | * {@link TokenTypes#ASSIGN ASSIGN}, | |
33 | * {@link TokenTypes#BAND BAND}, | |
34 | * {@link TokenTypes#BAND_ASSIGN BAND_ASSIGN}, | |
35 | * {@link TokenTypes#BOR BOR}, | |
36 | * {@link TokenTypes#BOR_ASSIGN BOR_ASSIGN}, | |
37 | * {@link TokenTypes#BSR BSR}, | |
38 | * {@link TokenTypes#BSR_ASSIGN BSR_ASSIGN}, | |
39 | * {@link TokenTypes#BXOR BXOR}, | |
40 | * {@link TokenTypes#BXOR_ASSIGN BXOR_ASSIGN}, | |
41 | * {@link TokenTypes#COLON COLON}, | |
42 | * {@link TokenTypes#DIV DIV}, | |
43 | * {@link TokenTypes#DIV_ASSIGN DIV_ASSIGN}, | |
44 | * {@link TokenTypes#DO_WHILE DO_WHILE}, | |
45 | * {@link TokenTypes#EQUAL EQUAL}, | |
46 | * {@link TokenTypes#GE GE}, | |
47 | * {@link TokenTypes#GT GT}, | |
48 | * {@link TokenTypes#LAND LAND}, | |
49 | * {@link TokenTypes#LCURLY LCURLY}, | |
50 | * {@link TokenTypes#LE LE}, | |
51 | * {@link TokenTypes#LITERAL_CATCH LITERAL_CATCH}, | |
52 | * {@link TokenTypes#LITERAL_DO LITERAL_DO}, | |
53 | * {@link TokenTypes#LITERAL_ELSE LITERAL_ELSE}, | |
54 | * {@link TokenTypes#LITERAL_FINALLY LITERAL_FINALLY}, | |
55 | * {@link TokenTypes#LITERAL_FOR LITERAL_FOR}, | |
56 | * {@link TokenTypes#LITERAL_IF LITERAL_IF}, | |
57 | * {@link TokenTypes#LITERAL_RETURN LITERAL_RETURN}, | |
58 | * {@link TokenTypes#LITERAL_SWITCH LITERAL_SWITCH}, | |
59 | * {@link TokenTypes#LITERAL_SYNCHRONIZED LITERAL_SYNCHRONIZED}, | |
60 | * {@link TokenTypes#LITERAL_TRY LITERAL_TRY}, | |
61 | * {@link TokenTypes#LITERAL_WHILE LITERAL_WHILE}, | |
62 | * {@link TokenTypes#LOR LOR}, | |
63 | * {@link TokenTypes#LT LT}, | |
64 | * {@link TokenTypes#MINUS MINUS}, | |
65 | * {@link TokenTypes#MINUS_ASSIGN MINUS_ASSIGN}, | |
66 | * {@link TokenTypes#MOD MOD}, | |
67 | * {@link TokenTypes#MOD_ASSIGN MOD_ASSIGN}, | |
68 | * {@link TokenTypes#NOT_EQUAL NOT_EQUAL}, | |
69 | * {@link TokenTypes#PLUS PLUS}, | |
70 | * {@link TokenTypes#PLUS_ASSIGN PLUS_ASSIGN}, | |
71 | * {@link TokenTypes#QUESTION QUESTION}, | |
72 | * {@link TokenTypes#RCURLY RCURLY}, | |
73 | * {@link TokenTypes#SL SL}, | |
74 | * {@link TokenTypes#SLIST SLIST}, | |
75 | * {@link TokenTypes#SL_ASSIGN SL_ASSIGN}, | |
76 | * {@link TokenTypes#SR SR}, | |
77 | * {@link TokenTypes#SR_ASSIGN SR_ASSIGN}, | |
78 | * {@link TokenTypes#STAR STAR}, | |
79 | * {@link TokenTypes#STAR_ASSIGN STAR_ASSIGN}, | |
80 | * {@link TokenTypes#LITERAL_ASSERT LITERAL_ASSERT}, | |
81 | * {@link TokenTypes#TYPE_EXTENSION_AND TYPE_EXTENSION_AND}. | |
82 | * | |
83 | * <p>An example of how to configure the check is: | |
84 | * | |
85 | * <pre> | |
86 | * <module name="WhitespaceAround"/> | |
87 | * </pre> | |
88 | * | |
89 | * <p>An example of how to configure the check for whitespace only around | |
90 | * assignment operators is: | |
91 | * | |
92 | * <pre> | |
93 | * <module name="WhitespaceAround"> | |
94 | * <property name="tokens" | |
95 | * value="ASSIGN,DIV_ASSIGN,PLUS_ASSIGN,MINUS_ASSIGN,STAR_ASSIGN, | |
96 | * MOD_ASSIGN,SR_ASSIGN,BSR_ASSIGN,SL_ASSIGN,BXOR_ASSIGN, | |
97 | * BOR_ASSIGN,BAND_ASSIGN"/> | |
98 | * </module> | |
99 | * </pre> | |
100 | * | |
101 | * <p>An example of how to configure the check for whitespace only around | |
102 | * curly braces is: | |
103 | * <pre> | |
104 | * <module name="WhitespaceAround"> | |
105 | * <property name="tokens" | |
106 | * value="LCURLY,RCURLY"/> | |
107 | * </module> | |
108 | * </pre> | |
109 | * | |
110 | * <p>In addition, this check can be configured to allow empty methods, types, | |
111 | * for, while, do-while loops, lambdas and constructor bodies. | |
112 | * For example: | |
113 | * | |
114 | * <pre>{@code | |
115 | * public MyClass() {} // empty constructor | |
116 | * public void func() {} // empty method | |
117 | * public interface Foo {} // empty interface | |
118 | * public class Foo {} // empty class | |
119 | * public enum Foo {} // empty enum | |
120 | * MyClass c = new MyClass() {}; // empty anonymous class | |
121 | * while (i = 1) {} // empty while loop | |
122 | * for (int i = 1; i > 1; i++) {} // empty for loop | |
123 | * do {} while (i = 1); // empty do-while loop | |
124 | * Runnable noop = () -> {}; // empty lambda | |
125 | * public @interface Beta {} // empty annotation type | |
126 | * }</pre> | |
127 | * | |
128 | * <p>This check does not flag as violation double brace initialization like:</p> | |
129 | * <pre> | |
130 | * new Properties() {{ | |
131 | * setProperty("key", "value"); | |
132 | * }}; | |
133 | * </pre> | |
134 | * | |
135 | * <p>To configure the check to allow empty method blocks use | |
136 | * | |
137 | * <pre> <property name="allowEmptyMethods" value="true" /></pre> | |
138 | * | |
139 | * <p>To configure the check to allow empty constructor blocks use | |
140 | * | |
141 | * <pre> <property name="allowEmptyConstructors" value="true" /></pre> | |
142 | * | |
143 | * <p>To configure the check to allow empty type blocks use | |
144 | * | |
145 | * <pre> <property name="allowEmptyTypes" value="true" /></pre> | |
146 | * | |
147 | * <p>To configure the check to allow empty loop blocks use | |
148 | * | |
149 | * <pre> <property name="allowEmptyLoops" value="true" /></pre> | |
150 | * | |
151 | * <p>To configure the check to allow empty lambdas blocks use | |
152 | * | |
153 | * <pre> <property name="allowEmptyLambdas" value="true" /></pre> | |
154 | * | |
155 | * <p>Also, this check can be configured to ignore the colon in an enhanced for | |
156 | * loop. The colon in an enhanced for loop is ignored by default | |
157 | * | |
158 | * <p>To configure the check to ignore the colon | |
159 | * | |
160 | * <pre> <property name="ignoreEnhancedForColon" value="true" /></pre> | |
161 | * | |
162 | * @author Oliver Burn | |
163 | * @author maxvetrenko | |
164 | * @author Andrei Selkin | |
165 | */ | |
166 | public class WhitespaceAroundCheck extends AbstractCheck { | |
167 | ||
168 | /** | |
169 | * A key is pointing to the warning message text in "messages.properties" | |
170 | * file. | |
171 | */ | |
172 | public static final String MSG_WS_NOT_PRECEDED = "ws.notPreceded"; | |
173 | ||
174 | /** | |
175 | * A key is pointing to the warning message text in "messages.properties" | |
176 | * file. | |
177 | */ | |
178 | public static final String MSG_WS_NOT_FOLLOWED = "ws.notFollowed"; | |
179 | ||
180 | /** Whether or not empty constructor bodies are allowed. */ | |
181 | private boolean allowEmptyConstructors; | |
182 | /** Whether or not empty method bodies are allowed. */ | |
183 | private boolean allowEmptyMethods; | |
184 | /** Whether or not empty classes, enums and interfaces are allowed. */ | |
185 | private boolean allowEmptyTypes; | |
186 | /** Whether or not empty loops are allowed. */ | |
187 | private boolean allowEmptyLoops; | |
188 | /** Whether or not empty lambda blocks are allowed. */ | |
189 | private boolean allowEmptyLambdas; | |
190 | /** Whether or not empty catch blocks are allowed. */ | |
191 | private boolean allowEmptyCatches; | |
192 | /** Whether or not to ignore a colon in a enhanced for loop. */ | |
193 | private boolean ignoreEnhancedForColon = true; | |
194 | ||
195 | @Override | |
196 | public int[] getDefaultTokens() { | |
197 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAroundCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] { |
198 | TokenTypes.ASSIGN, | |
199 | TokenTypes.BAND, | |
200 | TokenTypes.BAND_ASSIGN, | |
201 | TokenTypes.BOR, | |
202 | TokenTypes.BOR_ASSIGN, | |
203 | TokenTypes.BSR, | |
204 | TokenTypes.BSR_ASSIGN, | |
205 | TokenTypes.BXOR, | |
206 | TokenTypes.BXOR_ASSIGN, | |
207 | TokenTypes.COLON, | |
208 | TokenTypes.DIV, | |
209 | TokenTypes.DIV_ASSIGN, | |
210 | TokenTypes.DO_WHILE, | |
211 | TokenTypes.EQUAL, | |
212 | TokenTypes.GE, | |
213 | TokenTypes.GT, | |
214 | TokenTypes.LAMBDA, | |
215 | TokenTypes.LAND, | |
216 | TokenTypes.LCURLY, | |
217 | TokenTypes.LE, | |
218 | TokenTypes.LITERAL_CATCH, | |
219 | TokenTypes.LITERAL_DO, | |
220 | TokenTypes.LITERAL_ELSE, | |
221 | TokenTypes.LITERAL_FINALLY, | |
222 | TokenTypes.LITERAL_FOR, | |
223 | TokenTypes.LITERAL_IF, | |
224 | TokenTypes.LITERAL_RETURN, | |
225 | TokenTypes.LITERAL_SWITCH, | |
226 | TokenTypes.LITERAL_SYNCHRONIZED, | |
227 | TokenTypes.LITERAL_TRY, | |
228 | TokenTypes.LITERAL_WHILE, | |
229 | TokenTypes.LOR, | |
230 | TokenTypes.LT, | |
231 | TokenTypes.MINUS, | |
232 | TokenTypes.MINUS_ASSIGN, | |
233 | TokenTypes.MOD, | |
234 | TokenTypes.MOD_ASSIGN, | |
235 | TokenTypes.NOT_EQUAL, | |
236 | TokenTypes.PLUS, | |
237 | TokenTypes.PLUS_ASSIGN, | |
238 | TokenTypes.QUESTION, | |
239 | TokenTypes.RCURLY, | |
240 | TokenTypes.SL, | |
241 | TokenTypes.SLIST, | |
242 | TokenTypes.SL_ASSIGN, | |
243 | TokenTypes.SR, | |
244 | TokenTypes.SR_ASSIGN, | |
245 | TokenTypes.STAR, | |
246 | TokenTypes.STAR_ASSIGN, | |
247 | TokenTypes.LITERAL_ASSERT, | |
248 | TokenTypes.TYPE_EXTENSION_AND, | |
249 | }; | |
250 | } | |
251 | ||
252 | @Override | |
253 | public int[] getAcceptableTokens() { | |
254 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAroundCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] { |
255 | TokenTypes.ASSIGN, | |
256 | TokenTypes.ARRAY_INIT, | |
257 | TokenTypes.BAND, | |
258 | TokenTypes.BAND_ASSIGN, | |
259 | TokenTypes.BOR, | |
260 | TokenTypes.BOR_ASSIGN, | |
261 | TokenTypes.BSR, | |
262 | TokenTypes.BSR_ASSIGN, | |
263 | TokenTypes.BXOR, | |
264 | TokenTypes.BXOR_ASSIGN, | |
265 | TokenTypes.COLON, | |
266 | TokenTypes.DIV, | |
267 | TokenTypes.DIV_ASSIGN, | |
268 | TokenTypes.DO_WHILE, | |
269 | TokenTypes.EQUAL, | |
270 | TokenTypes.GE, | |
271 | TokenTypes.GT, | |
272 | TokenTypes.LAMBDA, | |
273 | TokenTypes.LAND, | |
274 | TokenTypes.LCURLY, | |
275 | TokenTypes.LE, | |
276 | TokenTypes.LITERAL_CATCH, | |
277 | TokenTypes.LITERAL_DO, | |
278 | TokenTypes.LITERAL_ELSE, | |
279 | TokenTypes.LITERAL_FINALLY, | |
280 | TokenTypes.LITERAL_FOR, | |
281 | TokenTypes.LITERAL_IF, | |
282 | TokenTypes.LITERAL_RETURN, | |
283 | TokenTypes.LITERAL_SWITCH, | |
284 | TokenTypes.LITERAL_SYNCHRONIZED, | |
285 | TokenTypes.LITERAL_TRY, | |
286 | TokenTypes.LITERAL_WHILE, | |
287 | TokenTypes.LOR, | |
288 | TokenTypes.LT, | |
289 | TokenTypes.MINUS, | |
290 | TokenTypes.MINUS_ASSIGN, | |
291 | TokenTypes.MOD, | |
292 | TokenTypes.MOD_ASSIGN, | |
293 | TokenTypes.NOT_EQUAL, | |
294 | TokenTypes.PLUS, | |
295 | TokenTypes.PLUS_ASSIGN, | |
296 | TokenTypes.QUESTION, | |
297 | TokenTypes.RCURLY, | |
298 | TokenTypes.SL, | |
299 | TokenTypes.SLIST, | |
300 | TokenTypes.SL_ASSIGN, | |
301 | TokenTypes.SR, | |
302 | TokenTypes.SR_ASSIGN, | |
303 | TokenTypes.STAR, | |
304 | TokenTypes.STAR_ASSIGN, | |
305 | TokenTypes.LITERAL_ASSERT, | |
306 | TokenTypes.TYPE_EXTENSION_AND, | |
307 | TokenTypes.WILDCARD_TYPE, | |
308 | TokenTypes.GENERIC_START, | |
309 | TokenTypes.GENERIC_END, | |
310 | TokenTypes.ELLIPSIS, | |
311 | }; | |
312 | } | |
313 | ||
314 | @Override | |
315 | public int[] getRequiredTokens() { | |
316 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAroundCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return CommonUtils.EMPTY_INT_ARRAY; |
317 | } | |
318 | ||
319 | /** | |
320 | * Sets whether or not empty method bodies are allowed. | |
321 | * @param allow {@code true} to allow empty method bodies. | |
322 | */ | |
323 | public void setAllowEmptyMethods(boolean allow) { | |
324 | allowEmptyMethods = allow; | |
325 | } | |
326 | ||
327 | /** | |
328 | * Sets whether or not empty constructor bodies are allowed. | |
329 | * @param allow {@code true} to allow empty constructor bodies. | |
330 | */ | |
331 | public void setAllowEmptyConstructors(boolean allow) { | |
332 | allowEmptyConstructors = allow; | |
333 | } | |
334 | ||
335 | /** | |
336 | * Sets whether or not to ignore the whitespace around the | |
337 | * colon in an enhanced for loop. | |
338 | * @param ignore {@code true} to ignore enhanced for colon. | |
339 | */ | |
340 | public void setIgnoreEnhancedForColon(boolean ignore) { | |
341 | ignoreEnhancedForColon = ignore; | |
342 | } | |
343 | ||
344 | /** | |
345 | * Sets whether or not empty type bodies are allowed. | |
346 | * @param allow {@code true} to allow empty type bodies. | |
347 | */ | |
348 | public void setAllowEmptyTypes(boolean allow) { | |
349 | allowEmptyTypes = allow; | |
350 | } | |
351 | ||
352 | /** | |
353 | * Sets whether or not empty loop bodies are allowed. | |
354 | * @param allow {@code true} to allow empty loops bodies. | |
355 | */ | |
356 | public void setAllowEmptyLoops(boolean allow) { | |
357 | allowEmptyLoops = allow; | |
358 | } | |
359 | ||
360 | /** | |
361 | * Sets whether or not empty lambdas bodies are allowed. | |
362 | * @param allow {@code true} to allow empty lambda expressions. | |
363 | */ | |
364 | public void setAllowEmptyLambdas(boolean allow) { | |
365 | allowEmptyLambdas = allow; | |
366 | } | |
367 | ||
368 | /** | |
369 | * Sets whether or not empty catch blocks are allowed. | |
370 | * @param allow {@code true} to allow empty catch blocks. | |
371 | */ | |
372 | public void setAllowEmptyCatches(boolean allow) { | |
373 | allowEmptyCatches = allow; | |
374 | } | |
375 | ||
376 | @Override | |
377 | public void visitToken(DetailAST ast) { | |
378 | final int currentType = ast.getType(); | |
379 |
1
1. visitToken : negated conditional → KILLED |
if (!isNotRelevantSituation(ast, currentType)) { |
380 |
1
1. visitToken : Replaced integer subtraction with addition → KILLED |
final String line = getLine(ast.getLineNo() - 1); |
381 |
1
1. visitToken : Replaced integer subtraction with addition → KILLED |
final int before = ast.getColumnNo() - 1; |
382 |
1
1. visitToken : Replaced integer addition with subtraction → KILLED |
final int after = ast.getColumnNo() + ast.getText().length(); |
383 | ||
384 |
2
1. visitToken : changed conditional boundary → KILLED 2. visitToken : negated conditional → KILLED |
if (before >= 0) { |
385 | final char prevChar = line.charAt(before); | |
386 |
1
1. visitToken : negated conditional → KILLED |
if (shouldCheckSeparationFromPreviousToken(ast) |
387 |
1
1. visitToken : negated conditional → KILLED |
&& !Character.isWhitespace(prevChar)) { |
388 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAroundCheck::log → KILLED |
log(ast.getLineNo(), ast.getColumnNo(), |
389 | MSG_WS_NOT_PRECEDED, ast.getText()); | |
390 | } | |
391 | } | |
392 | ||
393 |
2
1. visitToken : changed conditional boundary → KILLED 2. visitToken : negated conditional → KILLED |
if (after < line.length()) { |
394 | final char nextChar = line.charAt(after); | |
395 |
1
1. visitToken : negated conditional → KILLED |
if (shouldCheckSeparationFromNextToken(ast, nextChar) |
396 |
1
1. visitToken : negated conditional → KILLED |
&& !Character.isWhitespace(nextChar)) { |
397 |
2
1. visitToken : Replaced integer addition with subtraction → KILLED 2. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAroundCheck::log → KILLED |
log(ast.getLineNo(), ast.getColumnNo() + ast.getText().length(), |
398 | MSG_WS_NOT_FOLLOWED, ast.getText()); | |
399 | } | |
400 | } | |
401 | } | |
402 | } | |
403 | ||
404 | /** | |
405 | * Is ast not a target of Check. | |
406 | * @param ast ast | |
407 | * @param currentType type of ast | |
408 | * @return true is ok to skip validation | |
409 | */ | |
410 | private boolean isNotRelevantSituation(DetailAST ast, int currentType) { | |
411 | final int parentType = ast.getParent().getType(); | |
412 |
2
1. isNotRelevantSituation : negated conditional → KILLED 2. isNotRelevantSituation : negated conditional → KILLED |
final boolean starImport = currentType == TokenTypes.STAR |
413 | && parentType == TokenTypes.DOT; | |
414 |
2
1. isNotRelevantSituation : negated conditional → KILLED 2. isNotRelevantSituation : negated conditional → KILLED |
final boolean slistInsideCaseGroup = currentType == TokenTypes.SLIST |
415 | && parentType == TokenTypes.CASE_GROUP; | |
416 | ||
417 |
2
1. isNotRelevantSituation : negated conditional → KILLED 2. isNotRelevantSituation : negated conditional → KILLED |
final boolean starImportOrSlistInsideCaseGroup = starImport || slistInsideCaseGroup; |
418 | final boolean colonOfCaseOrDefaultOrForEach = | |
419 |
1
1. isNotRelevantSituation : negated conditional → KILLED |
isColonOfCaseOrDefault(currentType, parentType) |
420 |
1
1. isNotRelevantSituation : negated conditional → KILLED |
|| isColonOfForEach(currentType, parentType); |
421 | final boolean emptyBlockOrType = | |
422 |
2
1. isNotRelevantSituation : negated conditional → KILLED 2. isNotRelevantSituation : negated conditional → KILLED |
isEmptyBlock(ast, parentType) |
423 |
1
1. isNotRelevantSituation : negated conditional → KILLED |
|| allowEmptyTypes && isEmptyType(ast); |
424 | ||
425 |
4
1. isNotRelevantSituation : negated conditional → KILLED 2. isNotRelevantSituation : negated conditional → KILLED 3. isNotRelevantSituation : negated conditional → KILLED 4. isNotRelevantSituation : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return starImportOrSlistInsideCaseGroup |
426 | || colonOfCaseOrDefaultOrForEach | |
427 | || emptyBlockOrType | |
428 |
1
1. isNotRelevantSituation : negated conditional → KILLED |
|| isArrayInitialization(currentType, parentType); |
429 | } | |
430 | ||
431 | /** | |
432 | * Check if it should be checked if previous token is separated from current by | |
433 | * whitespace. | |
434 | * This function is needed to recognise double brace initialization as valid, | |
435 | * unfortunately its not possible to implement this functionality | |
436 | * in isNotRelevantSituation method, because in this method when we return | |
437 | * true(is not relevant) ast is later doesn't check at all. For example: | |
438 | * new Properties() {{setProperty("double curly braces", "are not a style error"); | |
439 | * }}; | |
440 | * For second left curly brace in first line when we would return true from | |
441 | * isNotRelevantSituation it wouldn't later check that the next token(setProperty) | |
442 | * is not separated from previous token. | |
443 | * @param ast current AST. | |
444 | * @return true if it should be checked if previous token is separated by whitespace, | |
445 | * false otherwise. | |
446 | */ | |
447 | private static boolean shouldCheckSeparationFromPreviousToken(DetailAST ast) { | |
448 |
2
1. shouldCheckSeparationFromPreviousToken : negated conditional → KILLED 2. shouldCheckSeparationFromPreviousToken : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return !isPartOfDoubleBraceInitializerForPreviousToken(ast); |
449 | } | |
450 | ||
451 | /** | |
452 | * Check if it should be checked if next token is separated from current by | |
453 | * whitespace. Explanation why this method is needed is identical to one | |
454 | * included in shouldCheckSeparationFromPreviousToken method. | |
455 | * @param ast current AST. | |
456 | * @param nextChar next character. | |
457 | * @return true if it should be checked if next token is separated by whitespace, | |
458 | * false otherwise. | |
459 | */ | |
460 | private static boolean shouldCheckSeparationFromNextToken(DetailAST ast, char nextChar) { | |
461 |
2
1. shouldCheckSeparationFromNextToken : negated conditional → KILLED 2. shouldCheckSeparationFromNextToken : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return !(ast.getType() == TokenTypes.LITERAL_RETURN |
462 |
1
1. shouldCheckSeparationFromNextToken : negated conditional → KILLED |
&& ast.getFirstChild().getType() == TokenTypes.SEMI) |
463 |
1
1. shouldCheckSeparationFromNextToken : negated conditional → KILLED |
&& ast.getType() != TokenTypes.ARRAY_INIT |
464 |
1
1. shouldCheckSeparationFromNextToken : negated conditional → KILLED |
&& !isAnonymousInnerClassEnd(ast.getType(), nextChar) |
465 |
1
1. shouldCheckSeparationFromNextToken : negated conditional → KILLED |
&& !isPartOfDoubleBraceInitializerForNextToken(ast); |
466 | } | |
467 | ||
468 | /** | |
469 | * Check for "})" or "};" or "},". Happens with anon-inners | |
470 | * @param currentType token | |
471 | * @param nextChar next symbol | |
472 | * @return true is that is end of anon inner class | |
473 | */ | |
474 | private static boolean isAnonymousInnerClassEnd(int currentType, char nextChar) { | |
475 |
6
1. isAnonymousInnerClassEnd : negated conditional → KILLED 2. isAnonymousInnerClassEnd : negated conditional → KILLED 3. isAnonymousInnerClassEnd : negated conditional → KILLED 4. isAnonymousInnerClassEnd : negated conditional → KILLED 5. isAnonymousInnerClassEnd : negated conditional → KILLED 6. isAnonymousInnerClassEnd : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return currentType == TokenTypes.RCURLY |
476 | && (nextChar == ')' | |
477 | || nextChar == ';' | |
478 | || nextChar == ',' | |
479 | || nextChar == '.'); | |
480 | } | |
481 | ||
482 | /** | |
483 | * Is empty block. | |
484 | * @param ast ast | |
485 | * @param parentType parent | |
486 | * @return true is block is empty | |
487 | */ | |
488 | private boolean isEmptyBlock(DetailAST ast, int parentType) { | |
489 |
2
1. isEmptyBlock : negated conditional → KILLED 2. isEmptyBlock : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return isEmptyMethodBlock(ast, parentType) |
490 |
1
1. isEmptyBlock : negated conditional → KILLED |
|| isEmptyCtorBlock(ast, parentType) |
491 |
1
1. isEmptyBlock : negated conditional → KILLED |
|| isEmptyLoop(ast, parentType) |
492 |
1
1. isEmptyBlock : negated conditional → KILLED |
|| isEmptyLambda(ast, parentType) |
493 |
1
1. isEmptyBlock : negated conditional → KILLED |
|| isEmptyCatch(ast, parentType); |
494 | } | |
495 | ||
496 | /** | |
497 | * Tests if a given {@code DetailAST} is part of an empty block. | |
498 | * An example empty block might look like the following | |
499 | * <p> | |
500 | * <pre> public void myMethod(int val) {}</pre> | |
501 | * </p> | |
502 | * In the above, the method body is an empty block ("{}"). | |
503 | * | |
504 | * @param ast the {@code DetailAST} to test. | |
505 | * @param parentType the token type of {@code ast}'s parent. | |
506 | * @param match the parent token type we're looking to match. | |
507 | * @return {@code true} if {@code ast} makes up part of an | |
508 | * empty block contained under a {@code match} token type | |
509 | * node. | |
510 | */ | |
511 | private static boolean isEmptyBlock(DetailAST ast, int parentType, int match) { | |
512 | final boolean result; | |
513 | final int type = ast.getType(); | |
514 |
1
1. isEmptyBlock : negated conditional → KILLED |
if (type == TokenTypes.RCURLY) { |
515 | final DetailAST parent = ast.getParent(); | |
516 | final DetailAST grandParent = ast.getParent().getParent(); | |
517 |
1
1. isEmptyBlock : negated conditional → KILLED |
result = parentType == TokenTypes.SLIST |
518 |
1
1. isEmptyBlock : negated conditional → KILLED |
&& parent.getFirstChild().getType() == TokenTypes.RCURLY |
519 |
1
1. isEmptyBlock : negated conditional → KILLED |
&& grandParent.getType() == match; |
520 | } | |
521 | else { | |
522 |
2
1. isEmptyBlock : negated conditional → KILLED 2. isEmptyBlock : negated conditional → KILLED |
result = type == TokenTypes.SLIST |
523 | && parentType == match | |
524 |
1
1. isEmptyBlock : negated conditional → KILLED |
&& ast.getFirstChild().getType() == TokenTypes.RCURLY; |
525 | } | |
526 |
1
1. isEmptyBlock : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return result; |
527 | } | |
528 | ||
529 | /** | |
530 | * Whether colon belongs to cases or defaults. | |
531 | * @param currentType current | |
532 | * @param parentType parent | |
533 | * @return true if current token in colon of case or default tokens | |
534 | */ | |
535 | private static boolean isColonOfCaseOrDefault(int currentType, int parentType) { | |
536 |
4
1. isColonOfCaseOrDefault : negated conditional → KILLED 2. isColonOfCaseOrDefault : negated conditional → KILLED 3. isColonOfCaseOrDefault : negated conditional → KILLED 4. isColonOfCaseOrDefault : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return currentType == TokenTypes.COLON |
537 | && (parentType == TokenTypes.LITERAL_DEFAULT | |
538 | || parentType == TokenTypes.LITERAL_CASE); | |
539 | } | |
540 | ||
541 | /** | |
542 | * Whether colon belongs to for-each. | |
543 | * @param currentType current | |
544 | * @param parentType parent | |
545 | * @return true if current token in colon of for-each token | |
546 | */ | |
547 | private boolean isColonOfForEach(int currentType, int parentType) { | |
548 |
4
1. isColonOfForEach : negated conditional → KILLED 2. isColonOfForEach : negated conditional → KILLED 3. isColonOfForEach : negated conditional → KILLED 4. isColonOfForEach : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return currentType == TokenTypes.COLON |
549 | && parentType == TokenTypes.FOR_EACH_CLAUSE | |
550 | && ignoreEnhancedForColon; | |
551 | } | |
552 | ||
553 | /** | |
554 | * Is array initialization. | |
555 | * @param currentType current token | |
556 | * @param parentType parent token | |
557 | * @return true is current token inside array initialization | |
558 | */ | |
559 | private static boolean isArrayInitialization(int currentType, int parentType) { | |
560 |
5
1. isArrayInitialization : negated conditional → KILLED 2. isArrayInitialization : negated conditional → KILLED 3. isArrayInitialization : negated conditional → KILLED 4. isArrayInitialization : negated conditional → KILLED 5. isArrayInitialization : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return (currentType == TokenTypes.RCURLY || currentType == TokenTypes.LCURLY) |
561 | && (parentType == TokenTypes.ARRAY_INIT | |
562 | || parentType == TokenTypes.ANNOTATION_ARRAY_INIT); | |
563 | } | |
564 | ||
565 | /** | |
566 | * Test if the given {@code DetailAST} is part of an allowed empty | |
567 | * method block. | |
568 | * @param ast the {@code DetailAST} to test. | |
569 | * @param parentType the token type of {@code ast}'s parent. | |
570 | * @return {@code true} if {@code ast} makes up part of an | |
571 | * allowed empty method block. | |
572 | */ | |
573 | private boolean isEmptyMethodBlock(DetailAST ast, int parentType) { | |
574 |
2
1. isEmptyMethodBlock : negated conditional → KILLED 2. isEmptyMethodBlock : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return allowEmptyMethods |
575 |
1
1. isEmptyMethodBlock : negated conditional → KILLED |
&& isEmptyBlock(ast, parentType, TokenTypes.METHOD_DEF); |
576 | } | |
577 | ||
578 | /** | |
579 | * Test if the given {@code DetailAST} is part of an allowed empty | |
580 | * constructor (ctor) block. | |
581 | * @param ast the {@code DetailAST} to test. | |
582 | * @param parentType the token type of {@code ast}'s parent. | |
583 | * @return {@code true} if {@code ast} makes up part of an | |
584 | * allowed empty constructor block. | |
585 | */ | |
586 | private boolean isEmptyCtorBlock(DetailAST ast, int parentType) { | |
587 |
2
1. isEmptyCtorBlock : negated conditional → KILLED 2. isEmptyCtorBlock : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return allowEmptyConstructors |
588 |
1
1. isEmptyCtorBlock : negated conditional → KILLED |
&& isEmptyBlock(ast, parentType, TokenTypes.CTOR_DEF); |
589 | } | |
590 | ||
591 | /** | |
592 | * Checks if loop is empty. | |
593 | * @param ast ast the {@code DetailAST} to test. | |
594 | * @param parentType the token type of {@code ast}'s parent. | |
595 | * @return {@code true} if {@code ast} makes up part of an | |
596 | * allowed empty loop block. | |
597 | */ | |
598 | private boolean isEmptyLoop(DetailAST ast, int parentType) { | |
599 |
2
1. isEmptyLoop : negated conditional → KILLED 2. isEmptyLoop : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return allowEmptyLoops |
600 |
1
1. isEmptyLoop : negated conditional → KILLED |
&& (isEmptyBlock(ast, parentType, TokenTypes.LITERAL_FOR) |
601 |
1
1. isEmptyLoop : negated conditional → KILLED |
|| isEmptyBlock(ast, parentType, TokenTypes.LITERAL_WHILE) |
602 |
1
1. isEmptyLoop : negated conditional → KILLED |
|| isEmptyBlock(ast, parentType, TokenTypes.LITERAL_DO)); |
603 | } | |
604 | ||
605 | /** | |
606 | * Test if the given {@code DetailAST} is part of an allowed empty | |
607 | * lambda block. | |
608 | * @param ast the {@code DetailAST} to test. | |
609 | * @param parentType the token type of {@code ast}'s parent. | |
610 | * @return {@code true} if {@code ast} makes up part of an | |
611 | * allowed empty lambda block. | |
612 | */ | |
613 | private boolean isEmptyLambda(DetailAST ast, int parentType) { | |
614 |
3
1. isEmptyLambda : negated conditional → KILLED 2. isEmptyLambda : negated conditional → KILLED 3. isEmptyLambda : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return allowEmptyLambdas && isEmptyBlock(ast, parentType, TokenTypes.LAMBDA); |
615 | } | |
616 | ||
617 | /** | |
618 | * Tests if the given {@code DetailAst} is part of an allowed empty | |
619 | * catch block. | |
620 | * @param ast the {@code DetailAst} to test. | |
621 | * @param parentType the token type of {@code ast}'s parent | |
622 | * @return {@code true} if {@code ast} makes up part of an | |
623 | * allowed empty catch block. | |
624 | */ | |
625 | private boolean isEmptyCatch(DetailAST ast, int parentType) { | |
626 |
3
1. isEmptyCatch : negated conditional → KILLED 2. isEmptyCatch : negated conditional → KILLED 3. isEmptyCatch : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return allowEmptyCatches && isEmptyBlock(ast, parentType, TokenTypes.LITERAL_CATCH); |
627 | } | |
628 | ||
629 | /** | |
630 | * Test if the given {@code DetailAST} is part of an empty block. | |
631 | * An example empty block might look like the following | |
632 | * <p> | |
633 | * <pre> class Foo {}</pre> | |
634 | * </p> | |
635 | * | |
636 | * @param ast ast the {@code DetailAST} to test. | |
637 | * @return {@code true} if {@code ast} makes up part of an | |
638 | * empty block contained under a {@code match} token type | |
639 | * node. | |
640 | */ | |
641 | private static boolean isEmptyType(DetailAST ast) { | |
642 | final int type = ast.getType(); | |
643 | final DetailAST nextSibling = ast.getNextSibling(); | |
644 | final DetailAST previousSibling = ast.getPreviousSibling(); | |
645 |
2
1. isEmptyType : negated conditional → KILLED 2. isEmptyType : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return type == TokenTypes.LCURLY |
646 |
3
1. isEmptyType : negated conditional → KILLED 2. isEmptyType : negated conditional → KILLED 3. isEmptyType : negated conditional → KILLED |
&& nextSibling.getType() == TokenTypes.RCURLY |
647 | || type == TokenTypes.RCURLY | |
648 | && previousSibling != null | |
649 |
1
1. isEmptyType : negated conditional → KILLED |
&& previousSibling.getType() == TokenTypes.LCURLY; |
650 | } | |
651 | ||
652 | /** | |
653 | * Check if given ast is part of double brace initializer and if it | |
654 | * should omit checking if previous token is separated by whitespace. | |
655 | * @param ast ast to check | |
656 | * @return true if it should omit checking for previous token, false otherwise | |
657 | */ | |
658 | private static boolean isPartOfDoubleBraceInitializerForPreviousToken(DetailAST ast) { | |
659 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
final boolean initializerBeginsAfterClassBegins = ast.getType() == TokenTypes.SLIST |
660 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
&& ast.getParent().getType() == TokenTypes.INSTANCE_INIT; |
661 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
final boolean classEndsAfterInitializerEnds = ast.getType() == TokenTypes.RCURLY |
662 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
&& ast.getPreviousSibling() != null |
663 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
&& ast.getPreviousSibling().getType() == TokenTypes.INSTANCE_INIT; |
664 |
3
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED 2. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED 3. isPartOfDoubleBraceInitializerForPreviousToken : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return initializerBeginsAfterClassBegins || classEndsAfterInitializerEnds; |
665 | } | |
666 | ||
667 | /** | |
668 | * Check if given ast is part of double brace initializer and if it | |
669 | * should omit checking if next token is separated by whitespace. | |
670 | * See <a href="https://github.com/checkstyle/checkstyle/pull/2845"> | |
671 | * PR#2845</a> for more information why this function was needed. | |
672 | * @param ast ast to check | |
673 | * @return true if it should omit checking for next token, false otherwise | |
674 | */ | |
675 | private static boolean isPartOfDoubleBraceInitializerForNextToken(DetailAST ast) { | |
676 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
final boolean classBeginBeforeInitializerBegin = ast.getType() == TokenTypes.LCURLY |
677 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
&& ast.getNextSibling().getType() == TokenTypes.INSTANCE_INIT; |
678 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
final boolean initalizerEndsBeforeClassEnds = ast.getType() == TokenTypes.RCURLY |
679 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
&& ast.getParent().getType() == TokenTypes.SLIST |
680 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
&& ast.getParent().getParent().getType() == TokenTypes.INSTANCE_INIT |
681 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
&& ast.getParent().getParent().getNextSibling().getType() == TokenTypes.RCURLY; |
682 |
3
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED 2. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED 3. isPartOfDoubleBraceInitializerForNextToken : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return classBeginBeforeInitializerBegin || initalizerEndsBeforeClassEnds; |
683 | } | |
684 | } | |
Mutations | ||
197 |
1.1 |
|
254 |
1.1 |
|
316 |
1.1 |
|
379 |
1.1 |
|
380 |
1.1 |
|
381 |
1.1 |
|
382 |
1.1 |
|
384 |
1.1 2.2 |
|
386 |
1.1 |
|
387 |
1.1 |
|
388 |
1.1 |
|
393 |
1.1 2.2 |
|
395 |
1.1 |
|
396 |
1.1 |
|
397 |
1.1 2.2 |
|
412 |
1.1 2.2 |
|
414 |
1.1 2.2 |
|
417 |
1.1 2.2 |
|
419 |
1.1 |
|
420 |
1.1 |
|
422 |
1.1 2.2 |
|
423 |
1.1 |
|
425 |
1.1 2.2 3.3 4.4 |
|
428 |
1.1 |
|
448 |
1.1 2.2 |
|
461 |
1.1 2.2 |
|
462 |
1.1 |
|
463 |
1.1 |
|
464 |
1.1 |
|
465 |
1.1 |
|
475 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
489 |
1.1 2.2 |
|
490 |
1.1 |
|
491 |
1.1 |
|
492 |
1.1 |
|
493 |
1.1 |
|
514 |
1.1 |
|
517 |
1.1 |
|
518 |
1.1 |
|
519 |
1.1 |
|
522 |
1.1 2.2 |
|
524 |
1.1 |
|
526 |
1.1 |
|
536 |
1.1 2.2 3.3 4.4 |
|
548 |
1.1 2.2 3.3 4.4 |
|
560 |
1.1 2.2 3.3 4.4 5.5 |
|
574 |
1.1 2.2 |
|
575 |
1.1 |
|
587 |
1.1 2.2 |
|
588 |
1.1 |
|
599 |
1.1 2.2 |
|
600 |
1.1 |
|
601 |
1.1 |
|
602 |
1.1 |
|
614 |
1.1 2.2 3.3 |
|
626 |
1.1 2.2 3.3 |
|
645 |
1.1 2.2 |
|
646 |
1.1 2.2 3.3 |
|
649 |
1.1 |
|
659 |
1.1 |
|
660 |
1.1 |
|
661 |
1.1 |
|
662 |
1.1 |
|
663 |
1.1 |
|
664 |
1.1 2.2 3.3 |
|
676 |
1.1 |
|
677 |
1.1 |
|
678 |
1.1 |
|
679 |
1.1 |
|
680 |
1.1 |
|
681 |
1.1 |
|
682 |
1.1 2.2 3.3 |