| 1 | /////////////////////////////////////////////////////////////////////////////////////////////// | |
| 2 | // checkstyle: Checks Java source code and other text files for adherence to a set of rules. | |
| 3 | // Copyright (C) 2001-2022 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.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 | import com.puppycrawl.tools.checkstyle.utils.TokenUtil; | |
| 30 | ||
| 31 | /** | |
| 32 | * <p> | |
| 33 | * Checks for the placement of left curly braces (<code>'{'</code>) for code blocks. | |
| 34 | * </p> | |
| 35 | * <ul> | |
| 36 | * <li> | |
| 37 | * Property {@code option} - Specify the policy on placement of a left curly brace | |
| 38 | * (<code>'{'</code>). | |
| 39 | * Type is {@code com.puppycrawl.tools.checkstyle.checks.blocks.LeftCurlyOption}. | |
| 40 | * Default value is {@code eol}. | |
| 41 | * </li> | |
| 42 | * <li> | |
| 43 | * Property {@code ignoreEnums} - Allow to ignore enums when left curly brace policy is EOL. | |
| 44 | * Type is {@code boolean}. | |
| 45 | * Default value is {@code true}. | |
| 46 | * </li> | |
| 47 | * <li> | |
| 48 | * Property {@code tokens} - tokens to check | |
| 49 | * Type is {@code java.lang.String[]}. | |
| 50 | * Validation type is {@code tokenSet}. | |
| 51 | * Default value is: | |
| 52 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#ANNOTATION_DEF"> | |
| 53 | * ANNOTATION_DEF</a>, | |
| 54 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CLASS_DEF"> | |
| 55 | * CLASS_DEF</a>, | |
| 56 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#CTOR_DEF"> | |
| 57 | * CTOR_DEF</a>, | |
| 58 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#ENUM_CONSTANT_DEF"> | |
| 59 | * ENUM_CONSTANT_DEF</a>, | |
| 60 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#ENUM_DEF"> | |
| 61 | * ENUM_DEF</a>, | |
| 62 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#INTERFACE_DEF"> | |
| 63 | * INTERFACE_DEF</a>, | |
| 64 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LAMBDA"> | |
| 65 | * LAMBDA</a>, | |
| 66 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_CASE"> | |
| 67 | * LITERAL_CASE</a>, | |
| 68 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_CATCH"> | |
| 69 | * LITERAL_CATCH</a>, | |
| 70 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_DEFAULT"> | |
| 71 | * LITERAL_DEFAULT</a>, | |
| 72 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_DO"> | |
| 73 | * LITERAL_DO</a>, | |
| 74 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_ELSE"> | |
| 75 | * LITERAL_ELSE</a>, | |
| 76 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_FINALLY"> | |
| 77 | * LITERAL_FINALLY</a>, | |
| 78 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_FOR"> | |
| 79 | * LITERAL_FOR</a>, | |
| 80 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_IF"> | |
| 81 | * LITERAL_IF</a>, | |
| 82 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_SWITCH"> | |
| 83 | * LITERAL_SWITCH</a>, | |
| 84 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_SYNCHRONIZED"> | |
| 85 | * LITERAL_SYNCHRONIZED</a>, | |
| 86 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_TRY"> | |
| 87 | * LITERAL_TRY</a>, | |
| 88 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#LITERAL_WHILE"> | |
| 89 | * LITERAL_WHILE</a>, | |
| 90 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#METHOD_DEF"> | |
| 91 | * METHOD_DEF</a>, | |
| 92 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#OBJBLOCK"> | |
| 93 | * OBJBLOCK</a>, | |
| 94 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#STATIC_INIT"> | |
| 95 | * STATIC_INIT</a>, | |
| 96 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#RECORD_DEF"> | |
| 97 | * RECORD_DEF</a>, | |
| 98 | * <a href="https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#COMPACT_CTOR_DEF"> | |
| 99 | * COMPACT_CTOR_DEF</a>. | |
| 100 | * </li> | |
| 101 | * </ul> | |
| 102 | * <p> | |
| 103 | * To configure the check: | |
| 104 | * </p> | |
| 105 | * <pre> | |
| 106 | * <module name="LeftCurly"/> | |
| 107 | * </pre> | |
| 108 | * <pre> | |
| 109 | * class Test | |
| 110 | * { // Violation - '{' should be on the previous line | |
| 111 | * private interface TestInterface | |
| 112 | * { // Violation - '{' should be on the previous line | |
| 113 | * } | |
| 114 | * | |
| 115 | * private | |
| 116 | * class | |
| 117 | * MyClass { // OK | |
| 118 | * } | |
| 119 | * | |
| 120 | * enum Colors {RED, // OK | |
| 121 | * BLUE, | |
| 122 | * GREEN; | |
| 123 | * } | |
| 124 | * } | |
| 125 | * </pre> | |
| 126 | * <p> | |
| 127 | * To configure the check to apply the {@code nl} policy to type blocks: | |
| 128 | * </p> | |
| 129 | * <pre> | |
| 130 | * <module name="LeftCurly"> | |
| 131 | * <property name="option" value="nl"/> | |
| 132 | * <property name="tokens" value="CLASS_DEF,INTERFACE_DEF"/> | |
| 133 | * </module> | |
| 134 | * </pre> | |
| 135 | * <pre> | |
| 136 | * class Test | |
| 137 | * { // OK | |
| 138 | * private interface TestInterface | |
| 139 | * { // OK | |
| 140 | * } | |
| 141 | * | |
| 142 | * private | |
| 143 | * class | |
| 144 | * MyClass { // Violation - '{' should be on a new line | |
| 145 | * } | |
| 146 | * | |
| 147 | * enum Colors {RED, // OK | |
| 148 | * BLUE, | |
| 149 | * GREEN; | |
| 150 | * } | |
| 151 | * } | |
| 152 | * </pre> | |
| 153 | * <p> | |
| 154 | * An example of how to configure the check to validate enum definitions: | |
| 155 | * </p> | |
| 156 | * <pre> | |
| 157 | * <module name="LeftCurly"> | |
| 158 | * <property name="ignoreEnums" value="false"/> | |
| 159 | * </module> | |
| 160 | * </pre> | |
| 161 | * <pre> | |
| 162 | * class Test | |
| 163 | * { // Violation - '{' should be on the previous line | |
| 164 | * private interface TestInterface | |
| 165 | * { // Violation - '{' should be on the previous line | |
| 166 | * } | |
| 167 | * | |
| 168 | * private | |
| 169 | * class | |
| 170 | * MyClass { // OK | |
| 171 | * } | |
| 172 | * | |
| 173 | * enum Colors {RED, // Violation - '{' should have line break after | |
| 174 | * BLUE, | |
| 175 | * GREEN; | |
| 176 | * } | |
| 177 | * } | |
| 178 | * </pre> | |
| 179 | * <p> | |
| 180 | * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} | |
| 181 | * </p> | |
| 182 | * <p> | |
| 183 | * Violation Message Keys: | |
| 184 | * </p> | |
| 185 | * <ul> | |
| 186 | * <li> | |
| 187 | * {@code line.break.after} | |
| 188 | * </li> | |
| 189 | * <li> | |
| 190 | * {@code line.new} | |
| 191 | * </li> | |
| 192 | * <li> | |
| 193 | * {@code line.previous} | |
| 194 | * </li> | |
| 195 | * </ul> | |
| 196 | * | |
| 197 | * @since 3.0 | |
| 198 | */ | |
| 199 | @StatelessCheck | |
| 200 | public class LeftCurlyCheck | |
| 201 | extends AbstractCheck { | |
| 202 | ||
| 203 | /** | |
| 204 | * A key is pointing to the warning message text in "messages.properties" | |
| 205 | * file. | |
| 206 | */ | |
| 207 | public static final String MSG_KEY_LINE_NEW = "line.new"; | |
| 208 | ||
| 209 | /** | |
| 210 | * A key is pointing to the warning message text in "messages.properties" | |
| 211 | * file. | |
| 212 | */ | |
| 213 | public static final String MSG_KEY_LINE_PREVIOUS = "line.previous"; | |
| 214 | ||
| 215 | /** | |
| 216 | * A key is pointing to the warning message text in "messages.properties" | |
| 217 | * file. | |
| 218 | */ | |
| 219 | public static final String MSG_KEY_LINE_BREAK_AFTER = "line.break.after"; | |
| 220 | ||
| 221 | /** Open curly brace literal. */ | |
| 222 | private static final String OPEN_CURLY_BRACE = "{"; | |
| 223 | ||
| 224 | /** Allow to ignore enums when left curly brace policy is EOL. */ | |
| 225 | private boolean ignoreEnums = true; | |
| 226 | ||
| 227 | /** | |
| 228 | * Specify the policy on placement of a left curly brace (<code>'{'</code>). | |
| 229 | * */ | |
| 230 | private LeftCurlyOption option = LeftCurlyOption.EOL; | |
| 231 | ||
| 232 | /** | |
| 233 | * Setter to specify the policy on placement of a left curly brace (<code>'{'</code>). | |
| 234 | * | |
| 235 | * @param optionStr string to decode option from | |
| 236 | * @throws IllegalArgumentException if unable to decode | |
| 237 | */ | |
| 238 | public void setOption(String optionStr) { | |
| 239 | option = LeftCurlyOption.valueOf(optionStr.trim().toUpperCase(Locale.ENGLISH)); | |
| 240 | } | |
| 241 | ||
| 242 | /** | |
| 243 | * Setter to allow to ignore enums when left curly brace policy is EOL. | |
| 244 | * | |
| 245 | * @param ignoreEnums check's option for ignoring enums. | |
| 246 | */ | |
| 247 | public void setIgnoreEnums(boolean ignoreEnums) { | |
| 248 | this.ignoreEnums = ignoreEnums; | |
| 249 | } | |
| 250 | ||
| 251 | @Override | |
| 252 | public int[] getDefaultTokens() { | |
| 253 | return getAcceptableTokens(); | |
| 254 | } | |
| 255 | ||
| 256 | @Override | |
| 257 | public int[] getAcceptableTokens() { | |
| 258 | return new int[] { | |
| 259 | TokenTypes.ANNOTATION_DEF, | |
| 260 | TokenTypes.CLASS_DEF, | |
| 261 | TokenTypes.CTOR_DEF, | |
| 262 | TokenTypes.ENUM_CONSTANT_DEF, | |
| 263 | TokenTypes.ENUM_DEF, | |
| 264 | TokenTypes.INTERFACE_DEF, | |
| 265 | TokenTypes.LAMBDA, | |
| 266 | TokenTypes.LITERAL_CASE, | |
| 267 | TokenTypes.LITERAL_CATCH, | |
| 268 | TokenTypes.LITERAL_DEFAULT, | |
| 269 | TokenTypes.LITERAL_DO, | |
| 270 | TokenTypes.LITERAL_ELSE, | |
| 271 | TokenTypes.LITERAL_FINALLY, | |
| 272 | TokenTypes.LITERAL_FOR, | |
| 273 | TokenTypes.LITERAL_IF, | |
| 274 | TokenTypes.LITERAL_SWITCH, | |
| 275 | TokenTypes.LITERAL_SYNCHRONIZED, | |
| 276 | TokenTypes.LITERAL_TRY, | |
| 277 | TokenTypes.LITERAL_WHILE, | |
| 278 | TokenTypes.METHOD_DEF, | |
| 279 | TokenTypes.OBJBLOCK, | |
| 280 | TokenTypes.STATIC_INIT, | |
| 281 | TokenTypes.RECORD_DEF, | |
| 282 | TokenTypes.COMPACT_CTOR_DEF, | |
| 283 | }; | |
| 284 | } | |
| 285 | ||
| 286 | @Override | |
| 287 | public int[] getRequiredTokens() { | |
| 288 | return CommonUtil.EMPTY_INT_ARRAY; | |
| 289 | } | |
| 290 | ||
| 291 | /** | |
| 292 | * We cannot reduce the number of branches in this switch statement, | |
| 293 | * since many tokens require specific methods to find the first left | |
| 294 | * curly. | |
| 295 | * | |
| 296 | * @param ast the token to process | |
| 297 | * @noinspection SwitchStatementWithTooManyBranches | |
| 298 | */ | |
| 299 | @Override | |
| 300 | public void visitToken(DetailAST ast) { | |
| 301 | final DetailAST startToken; | |
| 302 | final DetailAST brace; | |
| 303 | ||
| 304 | switch (ast.getType()) { | |
| 305 | case TokenTypes.CTOR_DEF: | |
| 306 | case TokenTypes.METHOD_DEF: | |
| 307 | case TokenTypes.COMPACT_CTOR_DEF: | |
| 308 | startToken = skipModifierAnnotations(ast); | |
| 309 | brace = ast.findFirstToken(TokenTypes.SLIST); | |
| 310 | break; | |
| 311 | case TokenTypes.INTERFACE_DEF: | |
| 312 | case TokenTypes.CLASS_DEF: | |
| 313 | case TokenTypes.ANNOTATION_DEF: | |
| 314 | case TokenTypes.ENUM_DEF: | |
| 315 | case TokenTypes.ENUM_CONSTANT_DEF: | |
| 316 | case TokenTypes.RECORD_DEF: | |
| 317 | startToken = skipModifierAnnotations(ast); | |
| 318 | brace = ast.findFirstToken(TokenTypes.OBJBLOCK); | |
| 319 | break; | |
| 320 | case TokenTypes.LITERAL_WHILE: | |
| 321 | case TokenTypes.LITERAL_CATCH: | |
| 322 | case TokenTypes.LITERAL_SYNCHRONIZED: | |
| 323 | case TokenTypes.LITERAL_FOR: | |
| 324 | case TokenTypes.LITERAL_TRY: | |
| 325 | case TokenTypes.LITERAL_FINALLY: | |
| 326 | case TokenTypes.LITERAL_DO: | |
| 327 | case TokenTypes.LITERAL_IF: | |
| 328 | case TokenTypes.STATIC_INIT: | |
| 329 | case TokenTypes.LAMBDA: | |
| 330 | startToken = ast; | |
| 331 | brace = ast.findFirstToken(TokenTypes.SLIST); | |
| 332 | break; | |
| 333 | case TokenTypes.LITERAL_ELSE: | |
| 334 | startToken = ast; | |
| 335 | brace = getBraceAsFirstChild(ast); | |
| 336 | break; | |
| 337 | case TokenTypes.LITERAL_CASE: | |
| 338 | case TokenTypes.LITERAL_DEFAULT: | |
| 339 | startToken = ast; | |
| 340 | brace = getBraceFromSwitchMember(ast); | |
| 341 | break; | |
| 342 | default: | |
| 343 | // ATTENTION! We have default here, but we expect case TokenTypes.METHOD_DEF, | |
| 344 | // TokenTypes.LITERAL_FOR, TokenTypes.LITERAL_WHILE, TokenTypes.LITERAL_DO only. | |
| 345 | // It has been done to improve coverage to 100%. I couldn't replace it with | |
| 346 | // if-else-if block because code was ugly and didn't pass pmd check. | |
| 347 | ||
| 348 | startToken = ast; | |
| 349 | brace = ast.findFirstToken(TokenTypes.LCURLY); | |
| 350 | break; | |
| 351 | } | |
| 352 | ||
| 353 | if (brace != null) { | |
| 354 | verifyBrace(brace, startToken); | |
| 355 | } | |
| 356 | } | |
| 357 | ||
| 358 | /** | |
| 359 | * Gets the brace of a switch statement/ expression member. | |
| 360 | * | |
| 361 | * @param ast {@code DetailAST}. | |
| 362 | * @return {@code DetailAST} if the first child is {@code TokenTypes.SLIST}, | |
| 363 | * {@code null} otherwise. | |
| 364 | */ | |
| 365 | private static DetailAST getBraceFromSwitchMember(DetailAST ast) { | |
| 366 | final DetailAST brace; | |
| 367 | final DetailAST parent = ast.getParent(); | |
| 368 | if (parent.getType() == TokenTypes.SWITCH_RULE) { | |
| 369 | brace = parent.findFirstToken(TokenTypes.SLIST); | |
| 370 | } | |
| 371 | else { | |
| 372 | brace = getBraceAsFirstChild(ast.getNextSibling()); | |
| 373 | } | |
| 374 | return brace; | |
| 375 | } | |
| 376 | ||
| 377 | /** | |
| 378 | * Gets a SLIST if it is the first child of the AST. | |
| 379 | * | |
| 380 | * @param ast {@code DetailAST}. | |
| 381 | * @return {@code DetailAST} if the first child is {@code TokenTypes.SLIST}, | |
| 382 | * {@code null} otherwise. | |
| 383 | */ | |
| 384 | private static DetailAST getBraceAsFirstChild(DetailAST ast) { | |
| 385 | DetailAST brace = null; | |
| 386 | if (ast != null) { | |
| 387 | final DetailAST candidate = ast.getFirstChild(); | |
| 388 | if (candidate != null && candidate.getType() == TokenTypes.SLIST) { | |
| 389 | brace = candidate; | |
| 390 | } | |
| 391 | } | |
| 392 | return brace; | |
| 393 | } | |
| 394 | ||
| 395 | /** | |
| 396 | * Skip all {@code TokenTypes.ANNOTATION}s to the first non-annotation. | |
| 397 | * | |
| 398 | * @param ast {@code DetailAST}. | |
| 399 | * @return {@code DetailAST}. | |
| 400 | */ | |
| 401 | private static DetailAST skipModifierAnnotations(DetailAST ast) { | |
| 402 | DetailAST resultNode = ast; | |
| 403 | final DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS); | |
| 404 | ||
| 405 | if (modifiers != null) { | |
| 406 | final DetailAST lastAnnotation = findLastAnnotation(modifiers); | |
| 407 | ||
| 408 | if (lastAnnotation != null) { | |
| 409 | if (lastAnnotation.getNextSibling() == null) { | |
| 410 | resultNode = modifiers.getNextSibling(); | |
| 411 | } | |
| 412 | else { | |
| 413 | resultNode = lastAnnotation.getNextSibling(); | |
| 414 | } | |
| 415 | } | |
| 416 | } | |
| 417 | return resultNode; | |
| 418 | } | |
| 419 | ||
| 420 | /** | |
| 421 | * Find the last token of type {@code TokenTypes.ANNOTATION} | |
| 422 | * under the given set of modifiers. | |
| 423 | * | |
| 424 | * @param modifiers {@code DetailAST}. | |
| 425 | * @return {@code DetailAST} or null if there are no annotations. | |
| 426 | */ | |
| 427 | private static DetailAST findLastAnnotation(DetailAST modifiers) { | |
| 428 | DetailAST annotation = modifiers.findFirstToken(TokenTypes.ANNOTATION); | |
| 429 | while (annotation != null && annotation.getNextSibling() != null | |
| 430 | && annotation.getNextSibling().getType() == TokenTypes.ANNOTATION) { | |
| 431 | annotation = annotation.getNextSibling(); | |
| 432 | } | |
| 433 | return annotation; | |
| 434 | } | |
| 435 | ||
| 436 | /** | |
| 437 | * Verifies that a specified left curly brace is placed correctly | |
| 438 | * according to policy. | |
| 439 | * | |
| 440 | * @param brace token for left curly brace | |
| 441 | * @param startToken token for start of expression | |
| 442 | */ | |
| 443 | private void verifyBrace(final DetailAST brace, | |
| 444 | final DetailAST startToken) { | |
| 445 |
1
1. verifyBrace : Replaced integer subtraction with addition → KILLED |
final String braceLine = getLine(brace.getLineNo() - 1); |
| 446 | ||
| 447 | // Check for being told to ignore, or have '{}' which is a special case | |
| 448 |
1
1. verifyBrace : Replaced integer addition with subtraction → KILLED |
if (braceLine.length() <= brace.getColumnNo() + 1 |
| 449 |
1
1. verifyBrace : Replaced integer addition with subtraction → KILLED |
|| braceLine.charAt(brace.getColumnNo() + 1) != '}') { |
| 450 | if (option == LeftCurlyOption.NL) { | |
| 451 | if (!CommonUtil.hasWhitespaceBefore(brace.getColumnNo(), braceLine)) { | |
| 452 |
1
1. verifyBrace : Replaced integer addition with subtraction → KILLED |
log(brace, MSG_KEY_LINE_NEW, OPEN_CURLY_BRACE, brace.getColumnNo() + 1); |
| 453 | } | |
| 454 | } | |
| 455 | else if (option == LeftCurlyOption.EOL) { | |
| 456 | validateEol(brace, braceLine); | |
| 457 | } | |
| 458 | else if (!TokenUtil.areOnSameLine(startToken, brace)) { | |
| 459 | validateNewLinePosition(brace, startToken, braceLine); | |
| 460 | } | |
| 461 | } | |
| 462 | } | |
| 463 | ||
| 464 | /** | |
| 465 | * Validate EOL case. | |
| 466 | * | |
| 467 | * @param brace brace AST | |
| 468 | * @param braceLine line content | |
| 469 | */ | |
| 470 | private void validateEol(DetailAST brace, String braceLine) { | |
| 471 | if (CommonUtil.hasWhitespaceBefore(brace.getColumnNo(), braceLine)) { | |
| 472 |
1
1. validateEol : Replaced integer addition with subtraction → KILLED |
log(brace, MSG_KEY_LINE_PREVIOUS, OPEN_CURLY_BRACE, brace.getColumnNo() + 1); |
| 473 | } | |
| 474 | if (!hasLineBreakAfter(brace)) { | |
| 475 |
1
1. validateEol : Replaced integer addition with subtraction → KILLED |
log(brace, MSG_KEY_LINE_BREAK_AFTER, OPEN_CURLY_BRACE, brace.getColumnNo() + 1); |
| 476 | } | |
| 477 | } | |
| 478 | ||
| 479 | /** | |
| 480 | * Validate token on new Line position. | |
| 481 | * | |
| 482 | * @param brace brace AST | |
| 483 | * @param startToken start Token | |
| 484 | * @param braceLine content of line with Brace | |
| 485 | */ | |
| 486 | private void validateNewLinePosition(DetailAST brace, DetailAST startToken, String braceLine) { | |
| 487 | // not on the same line | |
| 488 |
1
1. validateNewLinePosition : Replaced integer addition with subtraction → KILLED |
if (startToken.getLineNo() + 1 == brace.getLineNo()) { |
| 489 | if (CommonUtil.hasWhitespaceBefore(brace.getColumnNo(), braceLine)) { | |
| 490 |
1
1. validateNewLinePosition : Replaced integer addition with subtraction → KILLED |
log(brace, MSG_KEY_LINE_PREVIOUS, OPEN_CURLY_BRACE, brace.getColumnNo() + 1); |
| 491 | } | |
| 492 | else { | |
| 493 |
1
1. validateNewLinePosition : Replaced integer addition with subtraction → KILLED |
log(brace, MSG_KEY_LINE_NEW, OPEN_CURLY_BRACE, brace.getColumnNo() + 1); |
| 494 | } | |
| 495 | } | |
| 496 | else if (!CommonUtil.hasWhitespaceBefore(brace.getColumnNo(), braceLine)) { | |
| 497 |
1
1. validateNewLinePosition : Replaced integer addition with subtraction → KILLED |
log(brace, MSG_KEY_LINE_NEW, OPEN_CURLY_BRACE, brace.getColumnNo() + 1); |
| 498 | } | |
| 499 | } | |
| 500 | ||
| 501 | /** | |
| 502 | * Checks if left curly has line break after. | |
| 503 | * | |
| 504 | * @param leftCurly | |
| 505 | * Left curly token. | |
| 506 | * @return | |
| 507 | * True, left curly has line break after. | |
| 508 | */ | |
| 509 | private boolean hasLineBreakAfter(DetailAST leftCurly) { | |
| 510 | DetailAST nextToken = null; | |
| 511 | if (leftCurly.getType() == TokenTypes.SLIST) { | |
| 512 | nextToken = leftCurly.getFirstChild(); | |
| 513 | } | |
| 514 | else { | |
| 515 | if (!ignoreEnums | |
| 516 | && leftCurly.getParent().getParent().getType() == TokenTypes.ENUM_DEF) { | |
| 517 | nextToken = leftCurly.getNextSibling(); | |
| 518 | } | |
| 519 | } | |
| 520 | return nextToken == null | |
| 521 | || nextToken.getType() == TokenTypes.RCURLY | |
| 522 | || !TokenUtil.areOnSameLine(leftCurly, nextToken); | |
| 523 | } | |
| 524 | ||
| 525 | } | |
Mutations | ||
| 445 |
1.1 |
|
| 448 |
1.1 |
|
| 449 |
1.1 |
|
| 452 |
1.1 |
|
| 472 |
1.1 |
|
| 475 |
1.1 |
|
| 488 |
1.1 |
|
| 490 |
1.1 |
|
| 493 |
1.1 |
|
| 497 |
1.1 |