diff --git a/docs/config_coding.html b/docs/config_coding.html index 7a4ad407e..96b5d7de2 100644 --- a/docs/config_coding.html +++ b/docs/config_coding.html @@ -322,6 +322,15 @@ public class MySingleton regular expression (not applied) + + + ignoreSetter + Controls whether to ignore the parameter of a property setter method, where + the property setter method for field "xyz" has name "setXyz", + one parameter named "xyz", and return type void. + Boolean + false +

Examples

@@ -344,6 +353,14 @@ public class MySingleton

 <module name="HiddenField">
     <property name="ignoreFormat" value="^rcsid$"/>
+</module>
+      
+

+ To configure the check so that it ignores the parameter of setter methods: +

+
+<module name="HiddenField">
+    <property name="ignoreSetter" value="true"/>
 </module>
       

Package

diff --git a/docs/releasenotes.html b/docs/releasenotes.html index 1544b66bc..75859b89f 100644 --- a/docs/releasenotes.html +++ b/docs/releasenotes.html @@ -136,6 +136,10 @@
  • Added a check for illegal token text (requests 740694 and 750633).
  • +
  • Added property to HiddenFieldCheck to ignore the parameter of + property setter methods (request 790456).
  • + +

    diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck.java index de2cae59d..06a507629 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheck.java @@ -51,6 +51,16 @@ import com.puppycrawl.tools.checkstyle.api.Utils; * <property name="tokens" value="VARIABLE_DEF"/> * </module> * + *

    + * An example of how to configure the check so that it ignores the parameter of + * a setter method is: + *

    + *
    + * <module name="HiddenField">
    + *    <property name="ignoreSetter" value="true"/>
    + * </module>
    + * 
    + * @author Rick Giles * @version 1.0 */ @@ -64,6 +74,9 @@ public class HiddenFieldCheck /** the regexp to match against */ private RE mRegexp = null; + /** controls whether to check the parameter of a property setter method */ + private boolean mIgnoreSetter = false; + /** @see com.puppycrawl.tools.checkstyle.api.Check */ public int[] getDefaultTokens() { @@ -152,9 +165,11 @@ public class HiddenFieldCheck final HashSet aFieldsSet = (HashSet) it.next(); if (aFieldsSet.contains(name)) { if ((mRegexp == null) || (!getRegexp().match(name))) { - log(nameAST.getLineNo(), nameAST.getColumnNo(), - "hidden.field", name); - break; + if (!isIgnoredSetterParam(aAST, name)) { + log(nameAST.getLineNo(), nameAST.getColumnNo(), + "hidden.field", name); + break; + } } } } @@ -162,6 +177,48 @@ public class HiddenFieldCheck } } + /** + * Decides whether to ignore an AST node that is the parameter of a + * setter method, where the property setter method for field 'xyz' has + * name 'setXyz', one parameter named 'xyz', and return type void. + * @param aAST the AST to check. + * @param aName the name of aAST. + * @return true if aAST should be ignored because check property + * ignoreSetter is true and aAST is the parameter of a setter method. + */ + private boolean isIgnoredSetterParam(DetailAST aAST, String aName) + { + if (!(aAST.getType() == TokenTypes.PARAMETER_DEF) + || !mIgnoreSetter) + { + return false; + } + //single parameter? + final DetailAST parametersAST = aAST.getParent(); + if (parametersAST.getChildCount() != 1) + { + return false; + } + //method parameter, not constructor parameter? + final DetailAST methodAST = parametersAST.getParent(); + if (methodAST.getType() != TokenTypes.METHOD_DEF) { + return false; + } + //property setter name? + final String expectedName = + "set" + aName.substring(0, 1).toUpperCase() + aName.substring(1); + final DetailAST methodNameAST + = methodAST.findFirstToken(TokenTypes.IDENT); + final String methodName = methodNameAST.getText(); + if (!methodName.equals(expectedName)) { + return false; + } + //void? + final DetailAST typeAST + = methodAST.findFirstToken(TokenTypes.TYPE); + return typeAST.branchContains(TokenTypes.LITERAL_VOID); + } + /** * Set the ignore format to the specified regular expression. * @param aFormat a String value @@ -178,6 +235,16 @@ public class HiddenFieldCheck } } + /** + * Set whether to ignore the parameter of a property setter method. + * @param aIgnoreSetter decide whether to ignore the parameter of + * a property setter method. + */ + public void setIgnoreSetter(boolean aIgnoreSetter) + { + mIgnoreSetter = aIgnoreSetter; + } + /** @return the regexp to match against */ public RE getRegexp() { diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/InputHiddenField.java b/src/testinputs/com/puppycrawl/tools/checkstyle/InputHiddenField.java index 8de89f9a1..d96eeddb1 100644 --- a/src/testinputs/com/puppycrawl/tools/checkstyle/InputHiddenField.java +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/InputHiddenField.java @@ -90,3 +90,40 @@ interface NothingHidden // not an error public void noShadow(int notHidden); } + +/** tests ignoring the parameter of a property setter method */ +class PropertySetter +{ + private int prop; + + /** setter */ + public void setProp(int prop) + { + this.prop = prop; + } + + /** error - incorrect method name */ + public void setprop(int prop) + { + this.prop = prop; + } + + /** error - more than one parameter */ + public void setProp(int prop, int extra) + { + this.prop = prop; + } +} + +/** tests a non-void method */ +class PropertySetter2 +{ + private int prop; + + /** error - not a void method */ + public int setProp(int prop) + { + this.prop = prop; + return 0; + } +} diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheckTest.java index 79c3ec821..1afd0d292 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheckTest.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/coding/HiddenFieldCheckTest.java @@ -50,6 +50,10 @@ public class HiddenFieldCheckTest "76:17: 'innerHidden' hides a field.", "77:17: 'hidden' hides a field.", "82:13: 'hidden' hides a field.", + "100:29: 'prop' hides a field.", + "106:29: 'prop' hides a field.", + "112:29: 'prop' hides a field.", + "124:28: 'prop' hides a field.", }; verify(checkConfig, getPath("InputHiddenField.java"), expected); } @@ -72,10 +76,45 @@ public class HiddenFieldCheckTest "70:17: 'hidden' hides a field.", "77:17: 'hidden' hides a field.", "82:13: 'hidden' hides a field.", + "100:29: 'prop' hides a field.", + "106:29: 'prop' hides a field.", + "112:29: 'prop' hides a field.", + "124:28: 'prop' hides a field.", }; verify(checkConfig, getPath("InputHiddenField.java"), expected); } - + + /** tests ignoreSetter property */ + public void testIgnoreSetter() + throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(HiddenFieldCheck.class); + checkConfig.addAttribute("ignoreSetter", "true"); + final String[] expected = { + "18:13: 'hidden' hides a field.", + "21:33: 'hidden' hides a field.", + "27:13: 'hidden' hides a field.", + "32:18: 'hidden' hides a field.", + "36:33: 'hidden' hides a field.", + "46:17: 'innerHidden' hides a field.", + "49:26: 'innerHidden' hides a field.", + "55:17: 'innerHidden' hides a field.", + "56:17: 'hidden' hides a field.", + "61:22: 'innerHidden' hides a field.", + "64:22: 'hidden' hides a field.", + "69:17: 'innerHidden' hides a field.", + "70:17: 'hidden' hides a field.", + "76:17: 'innerHidden' hides a field.", + "77:17: 'hidden' hides a field.", + "82:13: 'hidden' hides a field.", + "106:29: 'prop' hides a field.", + "112:29: 'prop' hides a field.", + "124:28: 'prop' hides a field.", + }; + verify(checkConfig, getPath("InputHiddenField.java"), expected); + } + /** Test against a class with field declarations in different order */ public void testReordered() throws Exception