001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2019 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.checks.naming; 021 022import com.puppycrawl.tools.checkstyle.api.DetailAST; 023import com.puppycrawl.tools.checkstyle.api.TokenTypes; 024import com.puppycrawl.tools.checkstyle.utils.AnnotationUtil; 025 026/** 027 * <p> 028 * Checks that method names conform to a format specified 029 * by the format property. 030 * </p> 031 * 032 * <p>Also, checks if a method name has the same name as the residing class. 033 * The default is false (it is not allowed). It is legal in Java to have 034 * method with the same name as a class. As long as a return type is specified 035 * it is a method and not a constructor which it could be easily confused as. 036 * Does not check-style the name of an overridden methods because the developer does not 037 * have a choice in renaming such methods. 038 * </p> 039 * 040 * <ul> 041 * <li> 042 * Property {@code format} - Specifies valid identifiers. 043 * Default value is {@code "^[a-z][a-zA-Z0-9]*$"}. 044 * </li> 045 * <li> 046 * Property {@code allowClassName} - Controls whether to allow a method name to have the same name 047 * as the residing class name. This is not to be confused with a constructor. An easy mistake is 048 * to place a return type on a constructor declaration which turns it into a method. For example: 049 * <pre> 050 * class MyClass { 051 * public void MyClass() {} //this is a method 052 * public MyClass() {} //this is a constructor 053 * } 054 * </pre> Default value is {@code false}. 055 * </li> 056 * <li> 057 * Property {@code applyToPublic} - Controls whether to apply the check to public member. 058 * Default value is {@code true}. 059 * </li> 060 * <li> 061 * Property {@code applyToProtected} - Controls whether to apply the check to protected member. 062 * Default value is {@code true}. 063 * </li> 064 * <li> 065 * Property {@code applyToPackage} - Controls whether to apply the check to package-private member. 066 * Default value is {@code true}. 067 * </li> 068 * <li> 069 * Property {@code applyToPrivate} - Controls whether to apply the check to private member. 070 * Default value is {@code true}. 071 * </li> 072 * </ul> 073 * 074 * <p> 075 * An example of how to configure the check is: 076 * </p> 077 * <pre> 078 * <module name="MethodName"/> 079 * </pre> 080 * <p> 081 * An example of how to configure the check for names that begin with 082 * a lower case letter, followed by letters, digits, and underscores is: 083 * </p> 084 * <pre> 085 * <module name="MethodName"> 086 * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> 087 * </module> 088 * </pre> 089 * <p>Code Example:</p> 090 * <pre> 091 * class MyClass { 092 * public void myMethod() {} // OK 093 * public void MyMethod() {} // violation, name "MyMethod" 094 * // should match the pattern "^[a-z](_?[a-zA-Z0-9]+)*$" 095 * } 096 * </pre> 097 * <p> 098 * An example of how to configure the check to allow method names to be equal to the 099 * residing class name is: 100 * </p> 101 * <pre> 102 * <module name="MethodName"> 103 * <property name="format" value="^[a-zA-Z](_?[a-zA-Z0-9]+)*$"/> 104 * <property name="allowClassName" value="true"/> 105 * </module> 106 * </pre> 107 * <p>Code Example:</p> 108 * <pre> 109 * class MyClass { 110 * public MyClass() {} // OK 111 * public void MyClass() {} // OK, method Name 'MyClass' is allowed to be 112 * // equal to the enclosing class name 113 * } 114 * </pre> 115 * <p> 116 * An example of how to configure the check to disallow method names to be equal to the 117 * residing class name is: 118 * </p> 119 * <pre> 120 * <module name="MethodName"> 121 * <property name="format" value="^[a-zA-Z](_?[a-zA-Z0-9]+)*$"/> 122 * <property name="allowClassName" value="false"/> 123 * </module> 124 * </pre> 125 * <p>Code Example:</p> 126 * <pre> 127 * class MyClass { 128 * public MyClass() {} // OK 129 * public void MyClass() {} // violation, method Name 'MyClass' must not 130 * // equal the enclosing class name 131 * } 132 * </pre> 133 * <p> 134 * An example of how to suppress the check to public and protected methods: 135 * </p> 136 * <pre> 137 * <module name="MethodName"> 138 * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> 139 * <property name="applyToPublic" value="false"> 140 * <property name="applyToProtected" value="false"> 141 * </module> 142 * </pre> 143 * <p>Code Example:</p> 144 * <pre> 145 * class MyClass { 146 * public void FirstMethod() {} // OK 147 * protected void SecondMethod() {} // OK 148 * private void ThirdMethod() {} // violation, name 'ThirdMethod' must match 149 * // pattern '^[a-z](_?[a-zA-Z0-9]+)*$' 150 * void FourthMethod() {} // violation, name 'FourthMethod' must match 151 * // pattern '^[a-z](_?[a-zA-Z0-9]+)*$' 152 * } 153 * </pre> 154 * 155 * @since 3.0 156 */ 157public class MethodNameCheck 158 extends AbstractAccessControlNameCheck { 159 160 /** 161 * A key is pointing to the warning message text in "messages.properties" 162 * file. 163 */ 164 public static final String MSG_KEY = "method.name.equals.class.name"; 165 166 /** 167 * {@link Override Override} annotation name. 168 */ 169 private static final String OVERRIDE = "Override"; 170 171 /** 172 * Canonical {@link Override Override} annotation name. 173 */ 174 private static final String CANONICAL_OVERRIDE = "java.lang." + OVERRIDE; 175 176 /** 177 * Controls whether to allow a method name to have the same name as the residing class name. 178 * This is not to be confused with a constructor. An easy mistake is to place a return type on 179 * a constructor declaration which turns it into a method. For example: 180 * <pre> 181 * class MyClass { 182 * public void MyClass() {} //this is a method 183 * public MyClass() {} //this is a constructor 184 * } 185 * </pre> 186 */ 187 private boolean allowClassName; 188 189 /** Creates a new {@code MethodNameCheck} instance. */ 190 public MethodNameCheck() { 191 super("^[a-z][a-zA-Z0-9]*$"); 192 } 193 194 @Override 195 public int[] getDefaultTokens() { 196 return getRequiredTokens(); 197 } 198 199 @Override 200 public int[] getAcceptableTokens() { 201 return getRequiredTokens(); 202 } 203 204 @Override 205 public int[] getRequiredTokens() { 206 return new int[] {TokenTypes.METHOD_DEF, }; 207 } 208 209 @Override 210 public void visitToken(DetailAST ast) { 211 if (!AnnotationUtil.containsAnnotation(ast, OVERRIDE) 212 && !AnnotationUtil.containsAnnotation(ast, CANONICAL_OVERRIDE)) { 213 // Will check the name against the format. 214 super.visitToken(ast); 215 } 216 217 if (!allowClassName) { 218 final DetailAST method = 219 ast.findFirstToken(TokenTypes.IDENT); 220 //in all cases this will be the classDef type except anon inner 221 //with anon inner classes this will be the Literal_New keyword 222 final DetailAST classDefOrNew = ast.getParent().getParent(); 223 final DetailAST classIdent = 224 classDefOrNew.findFirstToken(TokenTypes.IDENT); 225 // Following logic is to handle when a classIdent can not be 226 // found. This is when you have a Literal_New keyword followed 227 // a DOT, which is when you have: 228 // new Outclass.InnerInterface(x) { ... } 229 // Such a rare case, will not have the logic to handle parsing 230 // down the tree looking for the first ident. 231 if (classIdent != null 232 && method.getText().equals(classIdent.getText())) { 233 log(method, MSG_KEY, method.getText()); 234 } 235 } 236 } 237 238 /** 239 * Setter to controls whether to allow a method name to have the same name as the residing 240 * class name. This is not to be confused with a constructor. An easy mistake is to place 241 * a return type on a constructor declaration which turns it into a method. For example: 242 * <pre> 243 * class MyClass { 244 * public void MyClass() {} //this is a method 245 * public MyClass() {} //this is a constructor 246 * } 247 * </pre> 248 * 249 * @param allowClassName true to allow false to disallow 250 */ 251 public void setAllowClassName(boolean allowClassName) { 252 this.allowClassName = allowClassName; 253 } 254 255}