001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2020 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 * An example of how to configure the check is: 082 * </p> 083 * <pre> 084 * <module name="MethodName"/> 085 * </pre> 086 * <p> 087 * An example of how to configure the check for names that begin with 088 * a lower case letter, followed by letters, digits, and underscores is: 089 * </p> 090 * <pre> 091 * <module name="MethodName"> 092 * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> 093 * </module> 094 * </pre> 095 * <p>Code Example:</p> 096 * <pre> 097 * class MyClass { 098 * public void myMethod() {} // OK 099 * public void MyMethod() {} // violation, name "MyMethod" 100 * // should match the pattern "^[a-z](_?[a-zA-Z0-9]+)*$" 101 * } 102 * </pre> 103 * <p> 104 * An example of how to configure the check to allow method names to be equal to the 105 * residing class name is: 106 * </p> 107 * <pre> 108 * <module name="MethodName"> 109 * <property name="format" value="^[a-zA-Z](_?[a-zA-Z0-9]+)*$"/> 110 * <property name="allowClassName" value="true"/> 111 * </module> 112 * </pre> 113 * <p>Code Example:</p> 114 * <pre> 115 * class MyClass { 116 * public MyClass() {} // OK 117 * public void MyClass() {} // OK, method Name 'MyClass' is allowed to be 118 * // equal to the enclosing class name 119 * } 120 * </pre> 121 * <p> 122 * An example of how to configure the check to disallow method names to be equal to the 123 * residing class name is: 124 * </p> 125 * <pre> 126 * <module name="MethodName"> 127 * <property name="format" value="^[a-zA-Z](_?[a-zA-Z0-9]+)*$"/> 128 * <property name="allowClassName" value="false"/> 129 * </module> 130 * </pre> 131 * <p>Code Example:</p> 132 * <pre> 133 * class MyClass { 134 * public MyClass() {} // OK 135 * public void MyClass() {} // violation, method Name 'MyClass' must not 136 * // equal the enclosing class name 137 * } 138 * </pre> 139 * <p> 140 * An example of how to suppress the check to public and protected methods: 141 * </p> 142 * <pre> 143 * <module name="MethodName"> 144 * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> 145 * <property name="applyToPublic" value="false"/> 146 * <property name="applyToProtected" value="false"/> 147 * </module> 148 * </pre> 149 * <p>Code Example:</p> 150 * <pre> 151 * class MyClass { 152 * public void FirstMethod() {} // OK 153 * protected void SecondMethod() {} // OK 154 * private void ThirdMethod() {} // violation, name 'ThirdMethod' must match 155 * // pattern '^[a-z](_?[a-zA-Z0-9]+)*$' 156 * void FourthMethod() {} // violation, name 'FourthMethod' must match 157 * // pattern '^[a-z](_?[a-zA-Z0-9]+)*$' 158 * } 159 * </pre> 160 * <p> 161 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} 162 * </p> 163 * <p> 164 * Violation Message Keys: 165 * </p> 166 * <ul> 167 * <li> 168 * {@code method.name.equals.class.name} 169 * </li> 170 * <li> 171 * {@code name.invalidPattern} 172 * </li> 173 * </ul> 174 * 175 * @since 3.0 176 */ 177public class MethodNameCheck 178 extends AbstractAccessControlNameCheck { 179 180 /** 181 * A key is pointing to the warning message text in "messages.properties" 182 * file. 183 */ 184 public static final String MSG_KEY = "method.name.equals.class.name"; 185 186 /** 187 * {@link Override Override} annotation name. 188 */ 189 private static final String OVERRIDE = "Override"; 190 191 /** 192 * Canonical {@link Override Override} annotation name. 193 */ 194 private static final String CANONICAL_OVERRIDE = "java.lang." + OVERRIDE; 195 196 /** 197 * Controls whether to allow a method name to have the same name as the residing class name. 198 * This is not to be confused with a constructor. An easy mistake is to place a return type on 199 * a constructor declaration which turns it into a method. For example: 200 * <pre> 201 * class MyClass { 202 * public void MyClass() {} //this is a method 203 * public MyClass() {} //this is a constructor 204 * } 205 * </pre> 206 */ 207 private boolean allowClassName; 208 209 /** Creates a new {@code MethodNameCheck} instance. */ 210 public MethodNameCheck() { 211 super("^[a-z][a-zA-Z0-9]*$"); 212 } 213 214 @Override 215 public int[] getDefaultTokens() { 216 return getRequiredTokens(); 217 } 218 219 @Override 220 public int[] getAcceptableTokens() { 221 return getRequiredTokens(); 222 } 223 224 @Override 225 public int[] getRequiredTokens() { 226 return new int[] {TokenTypes.METHOD_DEF, }; 227 } 228 229 @Override 230 public void visitToken(DetailAST ast) { 231 if (!AnnotationUtil.containsAnnotation(ast, OVERRIDE) 232 && !AnnotationUtil.containsAnnotation(ast, CANONICAL_OVERRIDE)) { 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}