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 * Default value is {@code "^[a-z][a-zA-Z0-9]*$"}. 043 * </li> 044 * <li> 045 * Property {@code allowClassName} - Controls whether to allow a method name to have the same name 046 * as the residing class name. This is not to be confused with a constructor. An easy mistake is 047 * to place a return type on a constructor declaration which turns it into a method. For example: 048 * <pre> 049 * class MyClass { 050 * public void MyClass() {} //this is a method 051 * public MyClass() {} //this is a constructor 052 * } 053 * </pre> Default value is {@code false}. 054 * </li> 055 * <li> 056 * Property {@code applyToPublic} - Controls whether to apply the check to public member. 057 * Default value is {@code true}. 058 * </li> 059 * <li> 060 * Property {@code applyToProtected} - Controls whether to apply the check to protected member. 061 * Default value is {@code true}. 062 * </li> 063 * <li> 064 * Property {@code applyToPackage} - Controls whether to apply the check to package-private member. 065 * Default value is {@code true}. 066 * </li> 067 * <li> 068 * Property {@code applyToPrivate} - Controls whether to apply the check to private member. 069 * Default value is {@code true}. 070 * </li> 071 * </ul> 072 * 073 * <p> 074 * An example of how to configure the check is: 075 * </p> 076 * <pre> 077 * <module name="MethodName"/> 078 * </pre> 079 * <p> 080 * An example of how to configure the check for names that begin with 081 * a lower case letter, followed by letters, digits, and underscores is: 082 * </p> 083 * <pre> 084 * <module name="MethodName"> 085 * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> 086 * </module> 087 * </pre> 088 * <p>Code Example:</p> 089 * <pre> 090 * class MyClass { 091 * public void myMethod() {} // OK 092 * public void MyMethod() {} // violation, name "MyMethod" 093 * // should match the pattern "^[a-z](_?[a-zA-Z0-9]+)*$" 094 * } 095 * </pre> 096 * <p> 097 * An example of how to configure the check to allow method names to be equal to the 098 * residing class name is: 099 * </p> 100 * <pre> 101 * <module name="MethodName"> 102 * <property name="format" value="^[a-zA-Z](_?[a-zA-Z0-9]+)*$"/> 103 * <property name="allowClassName" value="true"/> 104 * </module> 105 * </pre> 106 * <p>Code Example:</p> 107 * <pre> 108 * class MyClass { 109 * public MyClass() {} // OK 110 * public void MyClass() {} // OK, method Name 'MyClass' is allowed to be 111 * // equal to the enclosing class name 112 * } 113 * </pre> 114 * <p> 115 * An example of how to configure the check to disallow 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="false"/> 122 * </module> 123 * </pre> 124 * <p>Code Example:</p> 125 * <pre> 126 * class MyClass { 127 * public MyClass() {} // OK 128 * public void MyClass() {} // violation, method Name 'MyClass' must not 129 * // equal the enclosing class name 130 * } 131 * </pre> 132 * <p> 133 * An example of how to suppress the check to public and protected methods: 134 * </p> 135 * <pre> 136 * <module name="MethodName"> 137 * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> 138 * <property name="applyToPublic" value="false"> 139 * <property name="applyToProtected" value="false"> 140 * </module> 141 * </pre> 142 * <p>Code Example:</p> 143 * <pre> 144 * class MyClass { 145 * public void FirstMethod() {} // OK 146 * protected void SecondMethod() {} // OK 147 * private void ThirdMethod() {} // violation, name 'ThirdMethod' must match 148 * // pattern '^[a-z](_?[a-zA-Z0-9]+)*$' 149 * void FourthMethod() {} // violation, name 'FourthMethod' must match 150 * // pattern '^[a-z](_?[a-zA-Z0-9]+)*$' 151 * } 152 * </pre> 153 * 154 * @since 3.0 155 */ 156public class MethodNameCheck 157 extends AbstractAccessControlNameCheck { 158 159 /** 160 * A key is pointing to the warning message text in "messages.properties" 161 * file. 162 */ 163 public static final String MSG_KEY = "method.name.equals.class.name"; 164 165 /** 166 * {@link Override Override} annotation name. 167 */ 168 private static final String OVERRIDE = "Override"; 169 170 /** 171 * Canonical {@link Override Override} annotation name. 172 */ 173 private static final String CANONICAL_OVERRIDE = "java.lang." + OVERRIDE; 174 175 /** 176 * Controls whether to allow a method name to have the same name as the residing class name. 177 * This is not to be confused with a constructor. An easy mistake is to place a return type on 178 * a constructor declaration which turns it into a method. For example: 179 * <pre> 180 * class MyClass { 181 * public void MyClass() {} //this is a method 182 * public MyClass() {} //this is a constructor 183 * } 184 * </pre> 185 */ 186 private boolean allowClassName; 187 188 /** Creates a new {@code MethodNameCheck} instance. */ 189 public MethodNameCheck() { 190 super("^[a-z][a-zA-Z0-9]*$"); 191 } 192 193 @Override 194 public int[] getDefaultTokens() { 195 return getRequiredTokens(); 196 } 197 198 @Override 199 public int[] getAcceptableTokens() { 200 return getRequiredTokens(); 201 } 202 203 @Override 204 public int[] getRequiredTokens() { 205 return new int[] {TokenTypes.METHOD_DEF, }; 206 } 207 208 @Override 209 public void visitToken(DetailAST ast) { 210 if (!AnnotationUtil.containsAnnotation(ast, OVERRIDE) 211 && !AnnotationUtil.containsAnnotation(ast, CANONICAL_OVERRIDE)) { 212 // Will check the name against the format. 213 super.visitToken(ast); 214 } 215 216 if (!allowClassName) { 217 final DetailAST method = 218 ast.findFirstToken(TokenTypes.IDENT); 219 //in all cases this will be the classDef type except anon inner 220 //with anon inner classes this will be the Literal_New keyword 221 final DetailAST classDefOrNew = ast.getParent().getParent(); 222 final DetailAST classIdent = 223 classDefOrNew.findFirstToken(TokenTypes.IDENT); 224 // Following logic is to handle when a classIdent can not be 225 // found. This is when you have a Literal_New keyword followed 226 // a DOT, which is when you have: 227 // new Outclass.InnerInterface(x) { ... } 228 // Such a rare case, will not have the logic to handle parsing 229 // down the tree looking for the first ident. 230 if (classIdent != null 231 && method.getText().equals(classIdent.getText())) { 232 log(method, MSG_KEY, method.getText()); 233 } 234 } 235 } 236 237 /** 238 * Setter to controls whether to allow a method name to have the same name as the residing 239 * class name. This is not to be confused with a constructor. An easy mistake is to place 240 * a return type on a constructor declaration which turns it into a method. For example: 241 * <pre> 242 * class MyClass { 243 * public void MyClass() {} //this is a method 244 * public MyClass() {} //this is a constructor 245 * } 246 * </pre> 247 * 248 * @param allowClassName true to allow false to disallow 249 */ 250 public void setAllowClassName(boolean allowClassName) { 251 this.allowClassName = allowClassName; 252 } 253 254}