diff --git a/docs/config_naming.html b/docs/config_naming.html index c64149006..5eb533c46 100644 --- a/docs/config_naming.html +++ b/docs/config_naming.html @@ -58,7 +58,8 @@ LocalVariableName - local, non-final variables + local, non-final variables, including + catch parameters ^[a-z][a-zA-Z0-9]*$ @@ -110,6 +111,22 @@ </module> +
  • + Module LocalVariableName also has property tokens + which can be used to control whether the check applies to variable declarations or + catch clause parameters through + tokens + VARIABLE_DEF and PARAMETER_DEF. + For example, the following configuration element ensures that + catch clause parameters begin with "e", + followed by letters and digits: +
    +        <module name="LocalVariableName">
    +            <property name="format" value="^e[a-zA-Z0-9]*$"/>
    +            <property name="tokens" value="PARAMETER_DEF"/>
    +        </module>
    +            
    +
  • Module TypeName also has property tokens which can be used to control whether the check applies to classes or interfaces through diff --git a/docs/releasenotes.html b/docs/releasenotes.html index 5ca82322c..8e6bc9712 100644 --- a/docs/releasenotes.html +++ b/docs/releasenotes.html @@ -90,6 +90,8 @@
  • EmptyBlock does not accept stmt option (bug 747400)
  • +
  • Inner class fields interpreted as local variables (bug 747530)
  • + diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/ScopeUtils.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/ScopeUtils.java index f095ef51d..7e4343ff2 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/ScopeUtils.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/ScopeUtils.java @@ -178,4 +178,32 @@ public final class ScopeUtils return retVal; } + + /** + * Determines whether a node is a local variable definition, + * i.e. is declared in a code block, a for initializer, or a + * catch parameter. + * @param aAST the node to check. + * @return whether aAST is a local variable definition. + */ + public static boolean isLocalVariableDef(DetailAST aAST) + { + // variable declaration? + if (aAST.getType() == TokenTypes.VARIABLE_DEF) { + final DetailAST parent = aAST.getParent(); + if (parent != null) { + final int type = parent.getType(); + return (type == TokenTypes.SLIST) + || (type == TokenTypes.FOR_INIT); + } + } + // catch parameter? + else if (aAST.getType() == TokenTypes.PARAMETER_DEF) { + final DetailAST parent = aAST.getParent(); + if (parent != null) { + return (parent.getType() == TokenTypes.LITERAL_CATCH); + } + } + return false; + } } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/HiddenFieldCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/HiddenFieldCheck.java index 31befca40..203492b61 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/HiddenFieldCheck.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/HiddenFieldCheck.java @@ -134,7 +134,9 @@ public class HiddenFieldCheck private void processVariable(DetailAST aAST) { if (!ScopeUtils.inInterfaceBlock(aAST)) { - if (ScopeUtils.inCodeBlock(aAST)) { + if (ScopeUtils.isLocalVariableDef(aAST) + || (aAST.getType() == TokenTypes.PARAMETER_DEF)) + { //local variable or parameter. Does it shadow a field? final DetailAST nameAST = aAST.findFirstToken(TokenTypes.IDENT); final String name = nameAST.getText(); diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/LocalFinalVariableNameCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/LocalFinalVariableNameCheck.java index 1e9d899ad..b6949d04d 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/LocalFinalVariableNameCheck.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/LocalFinalVariableNameCheck.java @@ -71,7 +71,6 @@ public class LocalFinalVariableNameCheck aAST.findFirstToken(TokenTypes.MODIFIERS); final boolean isFinal = (modifiersAST != null) && modifiersAST.branchContains(TokenTypes.FINAL); - - return (isFinal && ScopeUtils.inCodeBlock(aAST)); + return (isFinal && ScopeUtils.isLocalVariableDef(aAST)); } } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/LocalVariableNameCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/LocalVariableNameCheck.java index 872621546..bb6f6b86a 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/LocalVariableNameCheck.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/LocalVariableNameCheck.java @@ -25,7 +25,8 @@ import com.puppycrawl.tools.checkstyle.api.TokenTypes; /** *

    * Checks that local, non-final variable names conform to a format specified - * by the format property. The format is a + * by the format property. A catch parameter is considered to be + * a local variable. The format is a * * regular expression * and defaults to @@ -61,7 +62,10 @@ public class LocalVariableNameCheck /** @see com.puppycrawl.tools.checkstyle.api.Check */ public int[] getDefaultTokens() { - return new int[] {TokenTypes.VARIABLE_DEF}; + return new int[] { + TokenTypes.VARIABLE_DEF, + TokenTypes.PARAMETER_DEF, + }; } /** @see com.puppycrawl.tools.checkstyle.checks.AbstractNameCheck */ @@ -71,7 +75,6 @@ public class LocalVariableNameCheck aAST.findFirstToken(TokenTypes.MODIFIERS); final boolean isFinal = (modifiersAST != null) && modifiersAST.branchContains(TokenTypes.FINAL); - - return (!isFinal && ScopeUtils.inCodeBlock(aAST)); + return (!isFinal && ScopeUtils.isLocalVariableDef(aAST)); } } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/MemberNameCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/MemberNameCheck.java index c3a4d7bc7..096894120 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/MemberNameCheck.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/MemberNameCheck.java @@ -73,6 +73,6 @@ public class MemberNameCheck && modifiersAST.branchContains(TokenTypes.LITERAL_STATIC); return (!isStatic && !ScopeUtils.inInterfaceBlock(aAST) - && !ScopeUtils.inCodeBlock(aAST)); + && !ScopeUtils.isLocalVariableDef(aAST)); } } diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/InputInner.java b/src/testinputs/com/puppycrawl/tools/checkstyle/InputInner.java index 0f6f374b5..ca66e4077 100644 --- a/src/testinputs/com/puppycrawl/tools/checkstyle/InputInner.java +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/InputInner.java @@ -41,4 +41,19 @@ class InputInner protected static Object sWeird = new Object(); /** demonstrate bug in handling static final **/ static Object sWeird2 = new Object(); + + /** demonstrate bug in local final variable */ + public interface Inter + { + } + + public static void main() + { + Inter m = new Inter() + { + private static final int CDS = 1; + + private int ABC; + }; + } } diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/LocalFinalVariableNameCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/LocalFinalVariableNameCheckTest.java index 5b214b124..64c15bc30 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/checks/LocalFinalVariableNameCheckTest.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/LocalFinalVariableNameCheckTest.java @@ -28,5 +28,14 @@ public class LocalFinalVariableNameCheckTest }; verify(checkConfig, getPath("InputSimple.java"), expected); } + + public void testInnerClass() + throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(LocalFinalVariableNameCheck.class); + final String[] expected = {}; + verify(checkConfig, getPath("InputInner.java"), expected); + } } diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/LocalVariableNameCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/LocalVariableNameCheckTest.java index ed57fc0d9..2aaa7c2f1 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/checks/LocalVariableNameCheckTest.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/LocalVariableNameCheckTest.java @@ -18,5 +18,27 @@ public class LocalVariableNameCheckTest }; verify(checkConfig, getPath("InputSimple.java"), expected); } + + public void testInnerClass() + throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(LocalVariableNameCheck.class); + final String[] expected = {}; + verify(checkConfig, getPath("InputInner.java"), expected); + } + + public void testCatchParameter() + throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(LocalVariableNameCheck.class); + checkConfig.addAttribute("tokens", "PARAMETER_DEF"); + checkConfig.addAttribute("format", "^e$"); + final String[] expected = { + "74:24: Name 'ex' must match pattern '^e$'.", + }; + verify(checkConfig, getPath("InputEmptyStatement.java"), expected); + } } diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/MemberNameCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/MemberNameCheckTest.java index e66813f03..5808efb04 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/checks/MemberNameCheckTest.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/MemberNameCheckTest.java @@ -17,5 +17,16 @@ public class MemberNameCheckTest }; verify(checkConfig, getPath("InputSimple.java"), expected); } + + public void testInnerClass() + throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(MemberNameCheck.class); + final String[] expected = { + "56:25: Name 'ABC' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + }; + verify(checkConfig, getPath("InputInner.java"), expected); + } }