001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2022 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 specified pattern. 029 * </p> 030 * 031 * <p>Also, checks if a method name has the same name as the residing class. 032 * The default is false (it is not allowed). It is legal in Java to have 033 * method with the same name as a class. As long as a return type is specified 034 * it is a method and not a constructor which it could be easily confused as. 035 * Does not check-style the name of an overridden methods because the developer does not 036 * have a choice in renaming such methods. 037 * </p> 038 * 039 * <ul> 040 * <li> 041 * Property {@code format} - Specifies valid identifiers. 042 * Type is {@code java.util.regex.Pattern}. 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> 055 * Type is {@code boolean}. 056 * Default value is {@code false}. 057 * </li> 058 * <li> 059 * Property {@code applyToPublic} - Controls whether to apply the check to public member. 060 * Type is {@code boolean}. 061 * Default value is {@code true}. 062 * </li> 063 * <li> 064 * Property {@code applyToProtected} - Controls whether to apply the check to protected member. 065 * Type is {@code boolean}. 066 * Default value is {@code true}. 067 * </li> 068 * <li> 069 * Property {@code applyToPackage} - Controls whether to apply the check to package-private member. 070 * Type is {@code boolean}. 071 * Default value is {@code true}. 072 * </li> 073 * <li> 074 * Property {@code applyToPrivate} - Controls whether to apply the check to private member. 075 * Type is {@code boolean}. 076 * Default value is {@code true}. 077 * </li> 078 * </ul> 079 * 080 * <p> 081 * To configure the check: 082 * </p> 083 * <pre> 084 * <module name="MethodName"/> 085 * </pre> 086 * <p>Code Example:</p> 087 * <pre> 088 * class MyClass { 089 * public void firstMethod1() {} // OK 090 * protected void secondMethod() {} // OK 091 * private void ThirdMethod() {} // violation, method name must match to the 092 * // default pattern '^[a-z][a-zA-Z0-9]*$' 093 * public void fourth_Method4() {} // violation, method name must match to the 094 * // default pattern '^[a-z][a-zA-Z0-9]*$' 095 * } 096 * </pre> 097 * <p> 098 * An example of how to configure the check for names that begin with 099 * a lower case letter, followed by letters, digits, and underscores is: 100 * </p> 101 * <pre> 102 * <module name="MethodName"> 103 * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> 104 * </module> 105 * </pre> 106 * <p>Code Example:</p> 107 * <pre> 108 * class MyClass { 109 * public void myMethod() {} // OK 110 * public void MyMethod() {} // violation, name "MyMethod" 111 * // should match the pattern "^[a-z](_?[a-zA-Z0-9]+)*$" 112 * } 113 * </pre> 114 * <p> 115 * An example of how to configure the check to allow method names to be equal to the 116 * residing class name is: 117 * </p> 118 * <pre> 119 * <module name="MethodName"> 120 * <property name="format" value="^[a-zA-Z](_?[a-zA-Z0-9]+)*$"/> 121 * <property name="allowClassName" value="true"/> 122 * </module> 123 * </pre> 124 * <p>Code Example:</p> 125 * <pre> 126 * class MyClass { 127 * public MyClass() {} // OK 128 * public void MyClass() {} // OK, method Name 'MyClass' is allowed to be 129 * // equal to the enclosing class name 130 * } 131 * </pre> 132 * <p> 133 * An example of how to configure the check to disallow method names to be equal to the 134 * residing class name is: 135 * </p> 136 * <pre> 137 * <module name="MethodName"> 138 * <property name="format" value="^[a-zA-Z](_?[a-zA-Z0-9]+)*$"/> 139 * <property name="allowClassName" value="false"/> 140 * </module> 141 * </pre> 142 * <p>Code Example:</p> 143 * <pre> 144 * class MyClass { 145 * public MyClass() {} // OK 146 * public void MyClass() {} // violation, method Name 'MyClass' must not 147 * // equal the enclosing class name 148 * } 149 * </pre> 150 * <p> 151 * An example of how to suppress the check to public and protected methods: 152 * </p> 153 * <pre> 154 * <module name="MethodName"> 155 * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> 156 * <property name="applyToPublic" value="false"/> 157 * <property name="applyToProtected" value="false"/> 158 * </module> 159 * </pre> 160 * <p>Code Example:</p> 161 * <pre> 162 * class MyClass { 163 * public void FirstMethod() {} // OK 164 * protected void SecondMethod() {} // OK 165 * private void ThirdMethod() {} // violation, name 'ThirdMethod' must match 166 * // pattern '^[a-z](_?[a-zA-Z0-9]+)*$' 167 * void FourthMethod() {} // violation, name 'FourthMethod' must match 168 * // pattern '^[a-z](_?[a-zA-Z0-9]+)*$' 169 * } 170 * </pre> 171 * <p> 172 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} 173 * </p> 174 * <p> 175 * Violation Message Keys: 176 * </p> 177 * <ul> 178 * <li> 179 * {@code method.name.equals.class.name} 180 * </li> 181 * <li> 182 * {@code name.invalidPattern} 183 * </li> 184 * </ul> 185 * 186 * @since 3.0 187 */ 188public class MethodNameCheck 189 extends AbstractAccessControlNameCheck { 190 191 /** 192 * A key is pointing to the warning message text in "messages.properties" 193 * file. 194 */ 195 public static final String MSG_KEY = "method.name.equals.class.name"; 196 197 /** 198 * {@link Override Override} annotation name. 199 */ 200 private static final String OVERRIDE = "Override"; 201 202 /** 203 * Canonical {@link Override Override} annotation name. 204 */ 205 private static final String CANONICAL_OVERRIDE = "java.lang." + OVERRIDE; 206 207 /** 208 * Controls whether to allow a method name to have the same name as the residing class name. 209 * This is not to be confused with a constructor. An easy mistake is to place a return type on 210 * a constructor declaration which turns it into a method. For example: 211 * <pre> 212 * class MyClass { 213 * public void MyClass() {} //this is a method 214 * public MyClass() {} //this is a constructor 215 * } 216 * </pre> 217 */ 218 private boolean allowClassName; 219 220 /** Creates a new {@code MethodNameCheck} instance. */ 221 public MethodNameCheck() { 222 super("^[a-z][a-zA-Z0-9]*$"); 223 } 224 225 @Override 226 public int[] getDefaultTokens() { 227 return getRequiredTokens(); 228 } 229 230 @Override 231 public int[] getAcceptableTokens() { 232 return getRequiredTokens(); 233 } 234 235 @Override 236 public int[] getRequiredTokens() { 237 return new int[] {TokenTypes.METHOD_DEF, }; 238 } 239 240 @Override 241 public void visitToken(DetailAST ast) { 242 if (!AnnotationUtil.containsAnnotation(ast, OVERRIDE) 243 && !AnnotationUtil.containsAnnotation(ast, CANONICAL_OVERRIDE)) { 244 // Will check the name against the format. 245 super.visitToken(ast); 246 } 247 248 if (!allowClassName) { 249 final DetailAST method = 250 ast.findFirstToken(TokenTypes.IDENT); 251 // in all cases this will be the classDef type except anon inner 252 // with anon inner classes this will be the Literal_New keyword 253 final DetailAST classDefOrNew = ast.getParent().getParent(); 254 final DetailAST classIdent = 255 classDefOrNew.findFirstToken(TokenTypes.IDENT); 256 // Following logic is to handle when a classIdent can not be 257 // found. This is when you have a Literal_New keyword followed 258 // a DOT, which is when you have: 259 // new Outclass.InnerInterface(x) { ... } 260 // Such a rare case, will not have the logic to handle parsing 261 // down the tree looking for the first ident. 262 if (classIdent != null 263 && method.getText().equals(classIdent.getText())) { 264 log(method, MSG_KEY, method.getText()); 265 } 266 } 267 } 268 269 /** 270 * Setter to controls whether to allow a method name to have the same name as the residing 271 * class name. This is not to be confused with a constructor. An easy mistake is to place 272 * a return type on a constructor declaration which turns it into a method. For example: 273 * <pre> 274 * class MyClass { 275 * public void MyClass() {} //this is a method 276 * public MyClass() {} //this is a constructor 277 * } 278 * </pre> 279 * 280 * @param allowClassName true to allow false to disallow 281 */ 282 public void setAllowClassName(boolean allowClassName) { 283 this.allowClassName = allowClassName; 284 } 285 286}