| 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 | }; | |
| 311 | } | |
| 312 | ||
| 313 | @Override | |
| 314 | public int[] getRequiredTokens() { | |
| 315 |
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; |
| 316 | } | |
| 317 | ||
| 318 | /** | |
| 319 | * Sets whether or not empty method bodies are allowed. | |
| 320 | * @param allow {@code true} to allow empty method bodies. | |
| 321 | */ | |
| 322 | public void setAllowEmptyMethods(boolean allow) { | |
| 323 | allowEmptyMethods = allow; | |
| 324 | } | |
| 325 | ||
| 326 | /** | |
| 327 | * Sets whether or not empty constructor bodies are allowed. | |
| 328 | * @param allow {@code true} to allow empty constructor bodies. | |
| 329 | */ | |
| 330 | public void setAllowEmptyConstructors(boolean allow) { | |
| 331 | allowEmptyConstructors = allow; | |
| 332 | } | |
| 333 | ||
| 334 | /** | |
| 335 | * Sets whether or not to ignore the whitespace around the | |
| 336 | * colon in an enhanced for loop. | |
| 337 | * @param ignore {@code true} to ignore enhanced for colon. | |
| 338 | */ | |
| 339 | public void setIgnoreEnhancedForColon(boolean ignore) { | |
| 340 | ignoreEnhancedForColon = ignore; | |
| 341 | } | |
| 342 | ||
| 343 | /** | |
| 344 | * Sets whether or not empty type bodies are allowed. | |
| 345 | * @param allow {@code true} to allow empty type bodies. | |
| 346 | */ | |
| 347 | public void setAllowEmptyTypes(boolean allow) { | |
| 348 | allowEmptyTypes = allow; | |
| 349 | } | |
| 350 | ||
| 351 | /** | |
| 352 | * Sets whether or not empty loop bodies are allowed. | |
| 353 | * @param allow {@code true} to allow empty loops bodies. | |
| 354 | */ | |
| 355 | public void setAllowEmptyLoops(boolean allow) { | |
| 356 | allowEmptyLoops = allow; | |
| 357 | } | |
| 358 | ||
| 359 | /** | |
| 360 | * Sets whether or not empty lambdas bodies are allowed. | |
| 361 | * @param allow {@code true} to allow empty lambda expressions. | |
| 362 | */ | |
| 363 | public void setAllowEmptyLambdas(boolean allow) { | |
| 364 | allowEmptyLambdas = allow; | |
| 365 | } | |
| 366 | ||
| 367 | /** | |
| 368 | * Sets whether or not empty catch blocks are allowed. | |
| 369 | * @param allow {@code true} to allow empty catch blocks. | |
| 370 | */ | |
| 371 | public void setAllowEmptyCatches(boolean allow) { | |
| 372 | allowEmptyCatches = allow; | |
| 373 | } | |
| 374 | ||
| 375 | @Override | |
| 376 | public void visitToken(DetailAST ast) { | |
| 377 | final int currentType = ast.getType(); | |
| 378 |
1
1. visitToken : negated conditional → KILLED |
if (!isNotRelevantSituation(ast, currentType)) { |
| 379 |
1
1. visitToken : Replaced integer subtraction with addition → KILLED |
final String line = getLine(ast.getLineNo() - 1); |
| 380 |
1
1. visitToken : Replaced integer subtraction with addition → KILLED |
final int before = ast.getColumnNo() - 1; |
| 381 |
1
1. visitToken : Replaced integer addition with subtraction → KILLED |
final int after = ast.getColumnNo() + ast.getText().length(); |
| 382 | ||
| 383 |
2
1. visitToken : changed conditional boundary → KILLED 2. visitToken : negated conditional → KILLED |
if (before >= 0) { |
| 384 | final char prevChar = line.charAt(before); | |
| 385 |
1
1. visitToken : negated conditional → KILLED |
if (shouldCheckSeparationFromPreviousToken(ast) |
| 386 |
1
1. visitToken : negated conditional → KILLED |
&& !Character.isWhitespace(prevChar)) { |
| 387 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/whitespace/WhitespaceAroundCheck::log → KILLED |
log(ast.getLineNo(), ast.getColumnNo(), |
| 388 | MSG_WS_NOT_PRECEDED, ast.getText()); | |
| 389 | } | |
| 390 | } | |
| 391 | ||
| 392 |
2
1. visitToken : changed conditional boundary → KILLED 2. visitToken : negated conditional → KILLED |
if (after < line.length()) { |
| 393 | final char nextChar = line.charAt(after); | |
| 394 |
1
1. visitToken : negated conditional → KILLED |
if (shouldCheckSeparationFromNextToken(ast, nextChar) |
| 395 |
1
1. visitToken : negated conditional → KILLED |
&& !Character.isWhitespace(nextChar)) { |
| 396 |
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(), |
| 397 | MSG_WS_NOT_FOLLOWED, ast.getText()); | |
| 398 | } | |
| 399 | } | |
| 400 | } | |
| 401 | } | |
| 402 | ||
| 403 | /** | |
| 404 | * Is ast not a target of Check. | |
| 405 | * @param ast ast | |
| 406 | * @param currentType type of ast | |
| 407 | * @return true is ok to skip validation | |
| 408 | */ | |
| 409 | private boolean isNotRelevantSituation(DetailAST ast, int currentType) { | |
| 410 | final int parentType = ast.getParent().getType(); | |
| 411 |
2
1. isNotRelevantSituation : negated conditional → KILLED 2. isNotRelevantSituation : negated conditional → KILLED |
final boolean starImport = currentType == TokenTypes.STAR |
| 412 | && parentType == TokenTypes.DOT; | |
| 413 |
2
1. isNotRelevantSituation : negated conditional → KILLED 2. isNotRelevantSituation : negated conditional → KILLED |
final boolean slistInsideCaseGroup = currentType == TokenTypes.SLIST |
| 414 | && parentType == TokenTypes.CASE_GROUP; | |
| 415 | ||
| 416 |
2
1. isNotRelevantSituation : negated conditional → KILLED 2. isNotRelevantSituation : negated conditional → KILLED |
final boolean starImportOrSlistInsideCaseGroup = starImport || slistInsideCaseGroup; |
| 417 | final boolean colonOfCaseOrDefaultOrForEach = | |
| 418 |
1
1. isNotRelevantSituation : negated conditional → KILLED |
isColonOfCaseOrDefault(currentType, parentType) |
| 419 |
1
1. isNotRelevantSituation : negated conditional → KILLED |
|| isColonOfForEach(currentType, parentType); |
| 420 | final boolean emptyBlockOrType = | |
| 421 |
2
1. isNotRelevantSituation : negated conditional → KILLED 2. isNotRelevantSituation : negated conditional → KILLED |
isEmptyBlock(ast, parentType) |
| 422 |
1
1. isNotRelevantSituation : negated conditional → KILLED |
|| allowEmptyTypes && isEmptyType(ast); |
| 423 | ||
| 424 |
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 |
| 425 | || colonOfCaseOrDefaultOrForEach | |
| 426 | || emptyBlockOrType | |
| 427 |
1
1. isNotRelevantSituation : negated conditional → KILLED |
|| isArrayInitialization(currentType, parentType); |
| 428 | } | |
| 429 | ||
| 430 | /** | |
| 431 | * Check if it should be checked if previous token is separated from current by | |
| 432 | * whitespace. | |
| 433 | * This function is needed to recognise double brace initialization as valid, | |
| 434 | * unfortunately its not possible to implement this functionality | |
| 435 | * in isNotRelevantSituation method, because in this method when we return | |
| 436 | * true(is not relevant) ast is later doesn't check at all. For example: | |
| 437 | * new Properties() {{setProperty("double curly braces", "are not a style error"); | |
| 438 | * }}; | |
| 439 | * For second left curly brace in first line when we would return true from | |
| 440 | * isNotRelevantSituation it wouldn't later check that the next token(setProperty) | |
| 441 | * is not separated from previous token. | |
| 442 | * @param ast current AST. | |
| 443 | * @return true if it should be checked if previous token is separated by whitespace, | |
| 444 | * false otherwise. | |
| 445 | */ | |
| 446 | private static boolean shouldCheckSeparationFromPreviousToken(DetailAST ast) { | |
| 447 |
2
1. shouldCheckSeparationFromPreviousToken : negated conditional → KILLED 2. shouldCheckSeparationFromPreviousToken : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return !isPartOfDoubleBraceInitializerForPreviousToken(ast); |
| 448 | } | |
| 449 | ||
| 450 | /** | |
| 451 | * Check if it should be checked if next token is separated from current by | |
| 452 | * whitespace. Explanation why this method is needed is identical to one | |
| 453 | * included in shouldCheckSeparationFromPreviousToken method. | |
| 454 | * @param ast current AST. | |
| 455 | * @param nextChar next character. | |
| 456 | * @return true if it should be checked if next token is separated by whitespace, | |
| 457 | * false otherwise. | |
| 458 | */ | |
| 459 | private static boolean shouldCheckSeparationFromNextToken(DetailAST ast, char nextChar) { | |
| 460 |
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 |
| 461 |
1
1. shouldCheckSeparationFromNextToken : negated conditional → KILLED |
&& ast.getFirstChild().getType() == TokenTypes.SEMI) |
| 462 |
1
1. shouldCheckSeparationFromNextToken : negated conditional → KILLED |
&& ast.getType() != TokenTypes.ARRAY_INIT |
| 463 |
1
1. shouldCheckSeparationFromNextToken : negated conditional → KILLED |
&& !isAnonymousInnerClassEnd(ast.getType(), nextChar) |
| 464 |
1
1. shouldCheckSeparationFromNextToken : negated conditional → KILLED |
&& !isPartOfDoubleBraceInitializerForNextToken(ast); |
| 465 | } | |
| 466 | ||
| 467 | /** | |
| 468 | * Check for "})" or "};" or "},". Happens with anon-inners | |
| 469 | * @param currentType token | |
| 470 | * @param nextChar next symbol | |
| 471 | * @return true is that is end of anon inner class | |
| 472 | */ | |
| 473 | private static boolean isAnonymousInnerClassEnd(int currentType, char nextChar) { | |
| 474 |
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 |
| 475 | && (nextChar == ')' | |
| 476 | || nextChar == ';' | |
| 477 | || nextChar == ',' | |
| 478 | || nextChar == '.'); | |
| 479 | } | |
| 480 | ||
| 481 | /** | |
| 482 | * Is empty block. | |
| 483 | * @param ast ast | |
| 484 | * @param parentType parent | |
| 485 | * @return true is block is empty | |
| 486 | */ | |
| 487 | private boolean isEmptyBlock(DetailAST ast, int parentType) { | |
| 488 |
2
1. isEmptyBlock : negated conditional → KILLED 2. isEmptyBlock : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return isEmptyMethodBlock(ast, parentType) |
| 489 |
1
1. isEmptyBlock : negated conditional → KILLED |
|| isEmptyCtorBlock(ast, parentType) |
| 490 |
1
1. isEmptyBlock : negated conditional → KILLED |
|| isEmptyLoop(ast, parentType) |
| 491 |
1
1. isEmptyBlock : negated conditional → KILLED |
|| isEmptyLambda(ast, parentType) |
| 492 |
1
1. isEmptyBlock : negated conditional → KILLED |
|| isEmptyCatch(ast, parentType); |
| 493 | } | |
| 494 | ||
| 495 | /** | |
| 496 | * Tests if a given {@code DetailAST} is part of an empty block. | |
| 497 | * An example empty block might look like the following | |
| 498 | * <p> | |
| 499 | * <pre> public void myMethod(int val) {}</pre> | |
| 500 | * </p> | |
| 501 | * In the above, the method body is an empty block ("{}"). | |
| 502 | * | |
| 503 | * @param ast the {@code DetailAST} to test. | |
| 504 | * @param parentType the token type of {@code ast}'s parent. | |
| 505 | * @param match the parent token type we're looking to match. | |
| 506 | * @return {@code true} if {@code ast} makes up part of an | |
| 507 | * empty block contained under a {@code match} token type | |
| 508 | * node. | |
| 509 | */ | |
| 510 | private static boolean isEmptyBlock(DetailAST ast, int parentType, int match) { | |
| 511 | final boolean result; | |
| 512 | final int type = ast.getType(); | |
| 513 |
1
1. isEmptyBlock : negated conditional → KILLED |
if (type == TokenTypes.RCURLY) { |
| 514 | final DetailAST parent = ast.getParent(); | |
| 515 | final DetailAST grandParent = ast.getParent().getParent(); | |
| 516 |
1
1. isEmptyBlock : negated conditional → KILLED |
result = parentType == TokenTypes.SLIST |
| 517 |
1
1. isEmptyBlock : negated conditional → KILLED |
&& parent.getFirstChild().getType() == TokenTypes.RCURLY |
| 518 |
1
1. isEmptyBlock : negated conditional → KILLED |
&& grandParent.getType() == match; |
| 519 | } | |
| 520 | else { | |
| 521 |
2
1. isEmptyBlock : negated conditional → KILLED 2. isEmptyBlock : negated conditional → KILLED |
result = type == TokenTypes.SLIST |
| 522 | && parentType == match | |
| 523 |
1
1. isEmptyBlock : negated conditional → KILLED |
&& ast.getFirstChild().getType() == TokenTypes.RCURLY; |
| 524 | } | |
| 525 |
1
1. isEmptyBlock : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return result; |
| 526 | } | |
| 527 | ||
| 528 | /** | |
| 529 | * Whether colon belongs to cases or defaults. | |
| 530 | * @param currentType current | |
| 531 | * @param parentType parent | |
| 532 | * @return true if current token in colon of case or default tokens | |
| 533 | */ | |
| 534 | private static boolean isColonOfCaseOrDefault(int currentType, int parentType) { | |
| 535 |
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 |
| 536 | && (parentType == TokenTypes.LITERAL_DEFAULT | |
| 537 | || parentType == TokenTypes.LITERAL_CASE); | |
| 538 | } | |
| 539 | ||
| 540 | /** | |
| 541 | * Whether colon belongs to for-each. | |
| 542 | * @param currentType current | |
| 543 | * @param parentType parent | |
| 544 | * @return true if current token in colon of for-each token | |
| 545 | */ | |
| 546 | private boolean isColonOfForEach(int currentType, int parentType) { | |
| 547 |
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 |
| 548 | && parentType == TokenTypes.FOR_EACH_CLAUSE | |
| 549 | && ignoreEnhancedForColon; | |
| 550 | } | |
| 551 | ||
| 552 | /** | |
| 553 | * Is array initialization. | |
| 554 | * @param currentType current token | |
| 555 | * @param parentType parent token | |
| 556 | * @return true is current token inside array initialization | |
| 557 | */ | |
| 558 | private static boolean isArrayInitialization(int currentType, int parentType) { | |
| 559 |
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) |
| 560 | && (parentType == TokenTypes.ARRAY_INIT | |
| 561 | || parentType == TokenTypes.ANNOTATION_ARRAY_INIT); | |
| 562 | } | |
| 563 | ||
| 564 | /** | |
| 565 | * Test if the given {@code DetailAST} is part of an allowed empty | |
| 566 | * method block. | |
| 567 | * @param ast the {@code DetailAST} to test. | |
| 568 | * @param parentType the token type of {@code ast}'s parent. | |
| 569 | * @return {@code true} if {@code ast} makes up part of an | |
| 570 | * allowed empty method block. | |
| 571 | */ | |
| 572 | private boolean isEmptyMethodBlock(DetailAST ast, int parentType) { | |
| 573 |
2
1. isEmptyMethodBlock : negated conditional → KILLED 2. isEmptyMethodBlock : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return allowEmptyMethods |
| 574 |
1
1. isEmptyMethodBlock : negated conditional → KILLED |
&& isEmptyBlock(ast, parentType, TokenTypes.METHOD_DEF); |
| 575 | } | |
| 576 | ||
| 577 | /** | |
| 578 | * Test if the given {@code DetailAST} is part of an allowed empty | |
| 579 | * constructor (ctor) block. | |
| 580 | * @param ast the {@code DetailAST} to test. | |
| 581 | * @param parentType the token type of {@code ast}'s parent. | |
| 582 | * @return {@code true} if {@code ast} makes up part of an | |
| 583 | * allowed empty constructor block. | |
| 584 | */ | |
| 585 | private boolean isEmptyCtorBlock(DetailAST ast, int parentType) { | |
| 586 |
2
1. isEmptyCtorBlock : negated conditional → KILLED 2. isEmptyCtorBlock : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return allowEmptyConstructors |
| 587 |
1
1. isEmptyCtorBlock : negated conditional → KILLED |
&& isEmptyBlock(ast, parentType, TokenTypes.CTOR_DEF); |
| 588 | } | |
| 589 | ||
| 590 | /** | |
| 591 | * Checks if loop is empty. | |
| 592 | * @param ast ast the {@code DetailAST} to test. | |
| 593 | * @param parentType the token type of {@code ast}'s parent. | |
| 594 | * @return {@code true} if {@code ast} makes up part of an | |
| 595 | * allowed empty loop block. | |
| 596 | */ | |
| 597 | private boolean isEmptyLoop(DetailAST ast, int parentType) { | |
| 598 |
2
1. isEmptyLoop : negated conditional → KILLED 2. isEmptyLoop : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return allowEmptyLoops |
| 599 |
1
1. isEmptyLoop : negated conditional → KILLED |
&& (isEmptyBlock(ast, parentType, TokenTypes.LITERAL_FOR) |
| 600 |
1
1. isEmptyLoop : negated conditional → KILLED |
|| isEmptyBlock(ast, parentType, TokenTypes.LITERAL_WHILE) |
| 601 |
1
1. isEmptyLoop : negated conditional → KILLED |
|| isEmptyBlock(ast, parentType, TokenTypes.LITERAL_DO)); |
| 602 | } | |
| 603 | ||
| 604 | /** | |
| 605 | * Test if the given {@code DetailAST} is part of an allowed empty | |
| 606 | * lambda block. | |
| 607 | * @param ast the {@code DetailAST} to test. | |
| 608 | * @param parentType the token type of {@code ast}'s parent. | |
| 609 | * @return {@code true} if {@code ast} makes up part of an | |
| 610 | * allowed empty lambda block. | |
| 611 | */ | |
| 612 | private boolean isEmptyLambda(DetailAST ast, int parentType) { | |
| 613 |
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); |
| 614 | } | |
| 615 | ||
| 616 | /** | |
| 617 | * Tests if the given {@code DetailAst} is part of an allowed empty | |
| 618 | * catch block. | |
| 619 | * @param ast the {@code DetailAst} to test. | |
| 620 | * @param parentType the token type of {@code ast}'s parent | |
| 621 | * @return {@code true} if {@code ast} makes up part of an | |
| 622 | * allowed empty catch block. | |
| 623 | */ | |
| 624 | private boolean isEmptyCatch(DetailAST ast, int parentType) { | |
| 625 |
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); |
| 626 | } | |
| 627 | ||
| 628 | /** | |
| 629 | * Test if the given {@code DetailAST} is part of an empty block. | |
| 630 | * An example empty block might look like the following | |
| 631 | * <p> | |
| 632 | * <pre> class Foo {}</pre> | |
| 633 | * </p> | |
| 634 | * | |
| 635 | * @param ast ast the {@code DetailAST} to test. | |
| 636 | * @return {@code true} if {@code ast} makes up part of an | |
| 637 | * empty block contained under a {@code match} token type | |
| 638 | * node. | |
| 639 | */ | |
| 640 | private static boolean isEmptyType(DetailAST ast) { | |
| 641 | final int type = ast.getType(); | |
| 642 | final DetailAST nextSibling = ast.getNextSibling(); | |
| 643 | final DetailAST previousSibling = ast.getPreviousSibling(); | |
| 644 |
2
1. isEmptyType : negated conditional → KILLED 2. isEmptyType : replaced return of integer sized value with (x == 0 ? 1 : 0) → KILLED |
return type == TokenTypes.LCURLY |
| 645 |
3
1. isEmptyType : negated conditional → KILLED 2. isEmptyType : negated conditional → KILLED 3. isEmptyType : negated conditional → KILLED |
&& nextSibling.getType() == TokenTypes.RCURLY |
| 646 | || type == TokenTypes.RCURLY | |
| 647 | && previousSibling != null | |
| 648 |
1
1. isEmptyType : negated conditional → KILLED |
&& previousSibling.getType() == TokenTypes.LCURLY; |
| 649 | } | |
| 650 | ||
| 651 | /** | |
| 652 | * Check if given ast is part of double brace initializer and if it | |
| 653 | * should omit checking if previous token is separated by whitespace. | |
| 654 | * @param ast ast to check | |
| 655 | * @return true if it should omit checking for previous token, false otherwise | |
| 656 | */ | |
| 657 | private static boolean isPartOfDoubleBraceInitializerForPreviousToken(DetailAST ast) { | |
| 658 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
final boolean initializerBeginsAfterClassBegins = ast.getType() == TokenTypes.SLIST |
| 659 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
&& ast.getParent().getType() == TokenTypes.INSTANCE_INIT; |
| 660 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
final boolean classEndsAfterInitializerEnds = ast.getType() == TokenTypes.RCURLY |
| 661 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
&& ast.getPreviousSibling() != null |
| 662 |
1
1. isPartOfDoubleBraceInitializerForPreviousToken : negated conditional → KILLED |
&& ast.getPreviousSibling().getType() == TokenTypes.INSTANCE_INIT; |
| 663 |
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; |
| 664 | } | |
| 665 | ||
| 666 | /** | |
| 667 | * Check if given ast is part of double brace initializer and if it | |
| 668 | * should omit checking if next token is separated by whitespace. | |
| 669 | * See <a href="https://github.com/checkstyle/checkstyle/pull/2845"> | |
| 670 | * PR#2845</a> for more information why this function was needed. | |
| 671 | * @param ast ast to check | |
| 672 | * @return true if it should omit checking for next token, false otherwise | |
| 673 | */ | |
| 674 | private static boolean isPartOfDoubleBraceInitializerForNextToken(DetailAST ast) { | |
| 675 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
final boolean classBeginBeforeInitializerBegin = ast.getType() == TokenTypes.LCURLY |
| 676 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
&& ast.getNextSibling().getType() == TokenTypes.INSTANCE_INIT; |
| 677 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
final boolean initalizerEndsBeforeClassEnds = ast.getType() == TokenTypes.RCURLY |
| 678 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
&& ast.getParent().getType() == TokenTypes.SLIST |
| 679 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
&& ast.getParent().getParent().getType() == TokenTypes.INSTANCE_INIT |
| 680 |
1
1. isPartOfDoubleBraceInitializerForNextToken : negated conditional → KILLED |
&& ast.getParent().getParent().getNextSibling().getType() == TokenTypes.RCURLY; |
| 681 |
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; |
| 682 | } | |
| 683 | } | |
Mutations | ||
| 197 |
1.1 |
|
| 254 |
1.1 |
|
| 315 |
1.1 |
|
| 378 |
1.1 |
|
| 379 |
1.1 |
|
| 380 |
1.1 |
|
| 381 |
1.1 |
|
| 383 |
1.1 2.2 |
|
| 385 |
1.1 |
|
| 386 |
1.1 |
|
| 387 |
1.1 |
|
| 392 |
1.1 2.2 |
|
| 394 |
1.1 |
|
| 395 |
1.1 |
|
| 396 |
1.1 2.2 |
|
| 411 |
1.1 2.2 |
|
| 413 |
1.1 2.2 |
|
| 416 |
1.1 2.2 |
|
| 418 |
1.1 |
|
| 419 |
1.1 |
|
| 421 |
1.1 2.2 |
|
| 422 |
1.1 |
|
| 424 |
1.1 2.2 3.3 4.4 |
|
| 427 |
1.1 |
|
| 447 |
1.1 2.2 |
|
| 460 |
1.1 2.2 |
|
| 461 |
1.1 |
|
| 462 |
1.1 |
|
| 463 |
1.1 |
|
| 464 |
1.1 |
|
| 474 |
1.1 2.2 3.3 4.4 5.5 6.6 |
|
| 488 |
1.1 2.2 |
|
| 489 |
1.1 |
|
| 490 |
1.1 |
|
| 491 |
1.1 |
|
| 492 |
1.1 |
|
| 513 |
1.1 |
|
| 516 |
1.1 |
|
| 517 |
1.1 |
|
| 518 |
1.1 |
|
| 521 |
1.1 2.2 |
|
| 523 |
1.1 |
|
| 525 |
1.1 |
|
| 535 |
1.1 2.2 3.3 4.4 |
|
| 547 |
1.1 2.2 3.3 4.4 |
|
| 559 |
1.1 2.2 3.3 4.4 5.5 |
|
| 573 |
1.1 2.2 |
|
| 574 |
1.1 |
|
| 586 |
1.1 2.2 |
|
| 587 |
1.1 |
|
| 598 |
1.1 2.2 |
|
| 599 |
1.1 |
|
| 600 |
1.1 |
|
| 601 |
1.1 |
|
| 613 |
1.1 2.2 3.3 |
|
| 625 |
1.1 2.2 3.3 |
|
| 644 |
1.1 2.2 |
|
| 645 |
1.1 2.2 3.3 |
|
| 648 |
1.1 |
|
| 658 |
1.1 |
|
| 659 |
1.1 |
|
| 660 |
1.1 |
|
| 661 |
1.1 |
|
| 662 |
1.1 |
|
| 663 |
1.1 2.2 3.3 |
|
| 675 |
1.1 |
|
| 676 |
1.1 |
|
| 677 |
1.1 |
|
| 678 |
1.1 |
|
| 679 |
1.1 |
|
| 680 |
1.1 |
|
| 681 |
1.1 2.2 3.3 |