001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2023 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 * Controls whether to allow a method name to have the same name as the residing class name. 199 * This is not to be confused with a constructor. An easy mistake is to place a return type on 200 * a constructor declaration which turns it into a method. For example: 201 * <pre> 202 * class MyClass { 203 * public void MyClass() {} //this is a method 204 * public MyClass() {} //this is a constructor 205 * } 206 * </pre> 207 */ 208 private boolean allowClassName; 209 210 /** Creates a new {@code MethodNameCheck} instance. */ 211 public MethodNameCheck() { 212 super("^[a-z][a-zA-Z0-9]*$"); 213 } 214 215 @Override 216 public int[] getDefaultTokens() { 217 return getRequiredTokens(); 218 } 219 220 @Override 221 public int[] getAcceptableTokens() { 222 return getRequiredTokens(); 223 } 224 225 @Override 226 public int[] getRequiredTokens() { 227 return new int[] {TokenTypes.METHOD_DEF, }; 228 } 229 230 @Override 231 public void visitToken(DetailAST ast) { 232 if (!AnnotationUtil.hasOverrideAnnotation(ast)) { 233 // Will check the name against the format. 234 super.visitToken(ast); 235 } 236 237 if (!allowClassName) { 238 final DetailAST method = 239 ast.findFirstToken(TokenTypes.IDENT); 240 // in all cases this will be the classDef type except anon inner 241 // with anon inner classes this will be the Literal_New keyword 242 final DetailAST classDefOrNew = ast.getParent().getParent(); 243 final DetailAST classIdent = 244 classDefOrNew.findFirstToken(TokenTypes.IDENT); 245 // Following logic is to handle when a classIdent can not be 246 // found. This is when you have a Literal_New keyword followed 247 // a DOT, which is when you have: 248 // new Outclass.InnerInterface(x) { ... } 249 // Such a rare case, will not have the logic to handle parsing 250 // down the tree looking for the first ident. 251 if (classIdent != null 252 && method.getText().equals(classIdent.getText())) { 253 log(method, MSG_KEY, method.getText()); 254 } 255 } 256 } 257 258 /** 259 * Setter to controls whether to allow a method name to have the same name as the residing 260 * class name. This is not to be confused with a constructor. An easy mistake is to place 261 * a return type on a constructor declaration which turns it into a method. For example: 262 * <pre> 263 * class MyClass { 264 * public void MyClass() {} //this is a method 265 * public MyClass() {} //this is a constructor 266 * } 267 * </pre> 268 * 269 * @param allowClassName true to allow false to disallow 270 */ 271 public void setAllowClassName(boolean allowClassName) { 272 this.allowClassName = allowClassName; 273 } 274 275}