diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheck.java index 3dab2d7ea..5618669f8 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheck.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheck.java @@ -18,6 +18,7 @@ //////////////////////////////////////////////////////////////////////////////// package com.puppycrawl.tools.checkstyle.checks.naming; +import com.puppycrawl.tools.checkstyle.api.DetailAST; import com.puppycrawl.tools.checkstyle.api.TokenTypes; /** @@ -28,6 +29,14 @@ import com.puppycrawl.tools.checkstyle.api.TokenTypes; * and defaults to * ^[a-z][a-zA-Z0-9]*$. *

+ * + *

+ * Also, checks if a method name has the same name as the residing class. + * The default is false (it is not allowed). It is legal in Java to have + * method with the same name as a class. As long as a return type is specified + * it is a method and not a constructor which it could be easily confused as. + *

+ * *

* An example of how to configure the check is: *

@@ -43,12 +52,27 @@ import com.puppycrawl.tools.checkstyle.api.TokenTypes; * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> * </module> * + * + *

+ * An example of how to configure the check to allow method names + * to be equal to the residing class name is: + *

+ *
+ * <module name="MethodName">
+ *    <property name="allowClassName" value="true"/>
+ * </module>
+ * 
* @author Oliver Burn - * @version 1.0 + * @author Travis Schneeberger + * @version 1.1 */ -public class MethodNameCheck - extends AbstractAccessControlNameCheck +public class MethodNameCheck extends AbstractNameCheck { + /** + * for allowing method name to be the same as the class name. + */ + private boolean mAllowClassName; + /** Creates a new MethodNameCheck instance. */ public MethodNameCheck() { @@ -58,6 +82,35 @@ public class MethodNameCheck @Override public int[] getDefaultTokens() { - return new int[] {TokenTypes.METHOD_DEF}; + return new int[] {TokenTypes.METHOD_DEF, }; + } + + @Override + public void visitToken(DetailAST aAst) + { + super.visitToken(aAst); // Will check the name against the format. + + if (!mAllowClassName) { + final DetailAST method = + aAst.findFirstToken(TokenTypes.IDENT); + //in all cases this will be the classDef type except anon inner + //with anon inner classes this will be the Literal_New keyword + final DetailAST classDefOrNew = aAst.getParent().getParent(); + final DetailAST classIdent = + classDefOrNew.findFirstToken(TokenTypes.IDENT); + if (method.getText().equals(classIdent.getText())) { + log(method.getLineNo(), method.getColumnNo(), + "method.name.equals.class.name", method.getText()); + } + } + } + + /** + * Sets the property for allowing a method to be the same name as a class. + * @param aAllowClassName true to allow false to disallow + */ + public void setAllowClassName(boolean aAllowClassName) + { + mAllowClassName = aAllowClassName; } } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/naming/messages.properties b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/naming/messages.properties index 061167c0e..3c4c30ac9 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/naming/messages.properties +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/naming/messages.properties @@ -1,2 +1,3 @@ name.invalidPattern=Name ''{0}'' must match pattern ''{1}''. illegal.abstract.class.name=Name ''{0}'' must match pattern ''{1}''. +method.name.equals.class.name=Method Name ''{0}'' must not equal the enclosing class name. \ No newline at end of file diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/InputMethNameEqualClsName.java b/src/testinputs/com/puppycrawl/tools/checkstyle/InputMethNameEqualClsName.java new file mode 100644 index 000000000..9c520c5e8 --- /dev/null +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/InputMethNameEqualClsName.java @@ -0,0 +1,51 @@ +package com.puppycrawl.tools.checkstyle; + +/** + * Test input for MethodNameCheck specifically + * whether the method name equals the class name. + * + * @author Travis Schneeberger + */ +public class InputMethNameEqualClsName { + + //illegal name + public int InputMethNameEqualClsName() { + return 0; + } + + class Inner { + //illegal name + public int Inner() { + return 0; + } + + //OK name - name of the outter class's ctor + public int InputMethNameEqualClsName() { + return 0; + } + } + + public void anotherMethod() { + new InputMethNameEqualClsName() { + + //illegal name + public int InputMethNameEqualClsName() { + return 1; + } + }; + } +} + +interface SweetInterface { + + //illegal name + int SweetInterface(); +} + +class Outter { + + //illegal name + public void Outter() { + + } +} diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheckTest.java index f5715ee74..46ac90881 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheckTest.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheckTest.java @@ -18,4 +18,46 @@ public class MethodNameCheckTest }; verify(checkConfig, getPath("InputSimple.java"), expected); } + + @Test + public void testMethodEqClass() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(MethodNameCheck.class); + + final String[] expected = { + "12:16: Method Name 'InputMethNameEqualClsName' must not equal the enclosing class name.", + "12:16: Name 'InputMethNameEqualClsName' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "18:20: Method Name 'Inner' must not equal the enclosing class name.", + "18:20: Name 'Inner' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "23:20: Name 'InputMethNameEqualClsName' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "32:24: Method Name 'InputMethNameEqualClsName' must not equal the enclosing class name.", + "32:24: Name 'InputMethNameEqualClsName' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "42:9: Method Name 'SweetInterface' must not equal the enclosing class name.", + "42:9: Name 'SweetInterface' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "48:17: Method Name 'Outter' must not equal the enclosing class name.", + "48:17: Name 'Outter' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + }; + + verify(checkConfig, getPath("InputMethNameEqualClsName.java"), expected); + } + + @Test + public void testMethodEqClassAllow() throws Exception + { + final DefaultConfiguration checkConfig = + createCheckConfig(MethodNameCheck.class); + checkConfig.addAttribute("allowClassName", "true"); //allow method names and class names to equal + + final String[] expected = { + "12:16: Name 'InputMethNameEqualClsName' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "18:20: Name 'Inner' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "23:20: Name 'InputMethNameEqualClsName' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "32:24: Name 'InputMethNameEqualClsName' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "42:9: Name 'SweetInterface' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + "48:17: Name 'Outter' must match pattern '^[a-z][a-zA-Z0-9]*$'.", + }; + + verify(checkConfig, getPath("InputMethNameEqualClsName.java"), expected); + } } diff --git a/src/xdocs/config_naming.xml b/src/xdocs/config_naming.xml index ffd04c66c..ba0a44037 100755 --- a/src/xdocs/config_naming.xml +++ b/src/xdocs/config_naming.xml @@ -18,17 +18,17 @@ href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html"> regular expression for valid identifiers. This is an example of a configuration of the MemberName module to - ensure that member identifiers begin with + ensure that member identifiers begin with 'm', followed by an upper case letter, and then letters and digits:

- + <module name="MemberName"> <property name="format" value="^m[A-Z][a-zA-Z0-9]*$"/> </module> - +

All naming modules belong to package com.puppycrawl.tools.checkstyle.checks.naming and @@ -141,7 +141,7 @@ clause parameters begin with "e", followed by letters and digits:

- + <module name="LocalVariableName"> <property name="format" value="^e[a-zA-Z0-9]*$"/> @@ -169,10 +169,12 @@

- Module MemberName also has the following - properties: + The modules ConstantName, MemberName, StaticVariableName and TypeName also have the following properties:

- + @@ -207,6 +209,38 @@
nametrue
+ +

+ Module MethodName also has the following + properties: +

+ + + + + + + + + + + + + + +
namedescriptiontypedefault value
allowClassName + Controls whether to allow a method name to have the same + name as the residing class name. This is not to be confused + with a constructor. An easy mistake is to place a return + type on a constructor declaration which turns it into a + method. For example: +
+class MyClass {
+    public void MyClass() {} //this is a method
+    public MyClass() {} //this is a constructor
+}
+            
+
Booleanfalse
diff --git a/src/xdocs/releasenotes.xml b/src/xdocs/releasenotes.xml index 945a90754..e162ea5a6 100755 --- a/src/xdocs/releasenotes.xml +++ b/src/xdocs/releasenotes.xml @@ -65,6 +65,12 @@ for ensuring there are no static import statements. Thanks to Travis Schneeberger for providing patch #1940611. +
  • + Enhanced the MethodName check + to detect when a method name is the same as the residing class + name. Thanks to Travis Schneeberger for providing patch + #1892364. +
  • Fixed Bugs:

    diff --git a/src/xdocs/stylesheets/site.vsl b/src/xdocs/stylesheets/site.vsl index 203de8b20..316cd65b6 100644 --- a/src/xdocs/stylesheets/site.vsl +++ b/src/xdocs/stylesheets/site.vsl @@ -322,7 +322,7 @@
    - Copyright © 2001-2007, Oliver Burn + Copyright © 2001-2008, Oliver Burn