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 4501a820c..5dc34fccc 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 @@ -39,6 +39,32 @@ import java.util.Map; * <property name="token" value="VARIABLE_DEF"/> * </module> * + *

+ * By default, this Check skip final validation on + * + * Enhanced For-Loop + *

+ *

+ * Option 'validateEnhancedForLoopVariable' could be used to make Check to validate even variable + * from Enhanced For Loop. + *

+ *

+ * An example of how to configure the check so that it also validates enhanced For Loop Variable is: + *

+ *
+ * <module name="FinalLocalVariable">
+ *     <property name="token" value="VARIABLE_DEF"/>
+ *     <property name="validateEnhancedForLoopVariable" value="true"/>
+ * </module>
+ * 
+ *

Example:

+ *

+ * + * for (int number : myNumbers) { // violation + * System.out.println(number); + * } + * + *

* @author k_gibbs, r_auckenthaler */ public class FinalLocalVariableCheck extends Check @@ -54,6 +80,18 @@ public class FinalLocalVariableCheck extends Check private final FastStack> scopeStack = FastStack.newInstance(); + /** Controls whether to check enhanced for-loop variable. */ + private boolean validateEnhancedForLoopVariable; + + /** + * Whether to check enhanced for-loop variable or not. + * @param validateEnhancedForLoopVariable whether to check for-loop variable + */ + public final void setValidateEnhancedForLoopVariable(boolean validateEnhancedForLoopVariable) + { + this.validateEnhancedForLoopVariable = validateEnhancedForLoopVariable; + } + @Override public int[] getDefaultTokens() { @@ -116,7 +154,7 @@ public class FinalLocalVariableCheck extends Check } case TokenTypes.VARIABLE_DEF: if ((ast.getParent().getType() != TokenTypes.OBJBLOCK) - && (ast.getParent().getType() != TokenTypes.FOR_EACH_CLAUSE) + && shouldCheckEnhancedForLoopVariable(ast) && isVariableInForInit(ast)) { insertVariable(ast); @@ -154,6 +192,17 @@ public class FinalLocalVariableCheck extends Check } } + /** + * Determines whether enhanced for-loop variable should be checked or not. + * @param ast The ast to compare. + * @return true if enhanced for-loop variable should be checked. + */ + private boolean shouldCheckEnhancedForLoopVariable(DetailAST ast) + { + return validateEnhancedForLoopVariable + || ast.getParent().getType() != TokenTypes.FOR_EACH_CLAUSE; + } + /** * Checks if current variable is defined in * {@link TokenTypes#FOR_INIT for-loop init}, e.g.: 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 c757c7897..a6eebb532 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 @@ -20,6 +20,7 @@ package com.puppycrawl.tools.checkstyle.checks.coding; import com.puppycrawl.tools.checkstyle.BaseCheckTestSupport; import com.puppycrawl.tools.checkstyle.DefaultConfiguration; + import org.junit.Test; import static com.puppycrawl.tools.checkstyle.checks.coding.FinalLocalVariableCheck.MSG_KEY; @@ -96,4 +97,28 @@ public class FinalLocalVariableCheckTest }; verify(checkConfig, getPath("coding/InputFinalLocalVariableCheckFalsePositive.java"), expected); } + @Test + public void testEnhancedForLoopVariableTrue() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(FinalLocalVariableCheck.class); + checkConfig.addAttribute("tokens", "VARIABLE_DEF, PARAMETER_DEF"); + checkConfig.addAttribute("validateEnhancedForLoopVariable", "true"); + final String[] expected = { + "8:20: " + "Variable 'a' should be declared final.", + "15:13: " + "Variable 'x' should be declared final.", + }; + verify(checkConfig, getPath("coding/InputFinalLocalVariableEnhancedForLoopVariable.java"), expected); + } + @Test + public void testEnhancedForLoopVariableFalse() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(FinalLocalVariableCheck.class); + checkConfig.addAttribute("tokens", "VARIABLE_DEF, PARAMETER_DEF"); + final String[] expected = { + "15:13: " + "Variable 'x' should be declared final.", + }; + verify(checkConfig, getPath("coding/InputFinalLocalVariableEnhancedForLoopVariable.java"), expected); + } } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/coding/InputFinalLocalVariableEnhancedForLoopVariable.java b/src/test/resources/com/puppycrawl/tools/checkstyle/coding/InputFinalLocalVariableEnhancedForLoopVariable.java new file mode 100644 index 000000000..e073f3770 --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/coding/InputFinalLocalVariableEnhancedForLoopVariable.java @@ -0,0 +1,21 @@ +package com.puppycrawl.tools.checkstyle.coding; + +public class InputFinalLocalVariableEnhancedForLoopVariable { + public void method1() + { + final java.util.List list = new java.util.ArrayList<>(); + + for(Object a : list){ + } + } + + public void method2() + { + final int[] squares = {0, 1, 4, 9, 16, 25}; + int x; + for (final int i : squares) { + } + + } + +} diff --git a/src/xdocs/config_coding.xml b/src/xdocs/config_coding.xml index deb23025f..3f5624324 100644 --- a/src/xdocs/config_coding.xml +++ b/src/xdocs/config_coding.xml @@ -344,6 +344,19 @@ number.equals(i + j); href="apidocs/com/puppycrawl/tools/checkstyle/api/TokenTypes.html#VARIABLE_DEF">VARIABLE_DEF + + validateEnhancedForLoopVariable + Controls whether to check enhanced for-loop variable. + + Boolean, + + + + false + + + @@ -364,6 +377,32 @@ number.equals(i + j); <property name="tokens" value="VARIABLE_DEF,PARAMETER_DEF"/> </module> +

+ By default, this Check skip final validation on + + Enhanced For-Loop. +

+

+ Option 'validateEnhancedForLoopVariable' could be used to make Check to validate even variable + from Enhanced For Loop. +

+

+ An example of how to configure the check so that it also validates enhanced For Loop Variable is: +

+ + <module name="FinalLocalVariable"> + <property name="token" value="VARIABLE_DEF"/> + <property name="validateEnhancedForLoopVariable" value="true"/> + </module> + +

Example:

+

+ + for (int number : myNumbers) { // violation + System.out.println(number); + } + +