diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheck.java index 2d872b1f3..870038c45 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheck.java @@ -109,7 +109,8 @@ public class FinalLocalVariableCheck extends Check } case TokenTypes.VARIABLE_DEF: if ((ast.getParent().getType() != TokenTypes.OBJBLOCK) - && (ast.getParent().getType() != TokenTypes.FOR_EACH_CLAUSE)) + && (ast.getParent().getType() != TokenTypes.FOR_EACH_CLAUSE) + && isFirstVariableInForInit(ast)) { insertVariable(ast); } @@ -146,6 +147,25 @@ public class FinalLocalVariableCheck extends Check } } + /** + * Checks if current variable is defined first in + * {@link TokenTypes#FOR_INIT for-loop init}, e.g.: + *

+ * + * for (int i = 0, j = 0; i < j; i++) { . . . } + * + *

+ * i is first variable in {@link TokenTypes#FOR_INIT for-loop init} + * @param variableDef variable definition node. + * @return true if variableDef is first variable in {@link TokenTypes#FOR_INIT for-loop init} + */ + private static boolean isFirstVariableInForInit(DetailAST variableDef) + { + return variableDef.getParent().getType() != TokenTypes.FOR_INIT + || variableDef.getPreviousSibling() == null + || variableDef.getPreviousSibling().getType() != TokenTypes.COMMA; + } + /** * Determines whether an AST is a descendant of an abstract or native method. * @param ast the AST to check. diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheckTest.java index 48e83a8fb..a6b4ac587 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheckTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheckTest.java @@ -82,4 +82,17 @@ public class FinalLocalVariableCheckTest }; verify(checkConfig, getPath("coding/InputFinalLocalVariableNativeMethods.java"), expected); } + + @Test + public void testFalsePositive() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(FinalLocalVariableCheck.class); + checkConfig.addAttribute("tokens", "VARIABLE_DEF, PARAMETER_DEF"); + + final String[] expected = { + + }; + verify(checkConfig, getPath("coding/InputFinalLocalVariableCheckFalsePositive.java"), expected); + } } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/coding/InputFinalLocalVariableCheckFalsePositive.java b/src/test/resources/com/puppycrawl/tools/checkstyle/coding/InputFinalLocalVariableCheckFalsePositive.java new file mode 100644 index 000000000..d1e9aca55 --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/coding/InputFinalLocalVariableCheckFalsePositive.java @@ -0,0 +1,13 @@ +package com.puppycrawl.tools.checkstyle.coding; + +public class InputFinalLocalVariableCheckFalsePositive +{ + public void method() + { + final java.util.List list = new java.util.ArrayList<>(); + + for ( int i = 0, s0 = list.size(); i < s0; i++ ) + { + } + } +}