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 allowClassName} - Controls whether to allow a method name to have the same name 042 * as the residing class name. This is not to be confused with a constructor. An easy mistake is 043 * to place a return type on a constructor declaration which turns it into a method. For example: 044 * <pre> 045 * class MyClass { 046 * public void MyClass() {} //this is a method 047 * public MyClass() {} //this is a constructor 048 * } 049 * </pre> 050 * Type is {@code boolean}. 051 * Default value is {@code false}. 052 * </li> 053 * <li> 054 * Property {@code applyToPackage} - Controls whether to apply the check to package-private member. 055 * Type is {@code boolean}. 056 * Default value is {@code true}. 057 * </li> 058 * <li> 059 * Property {@code applyToPrivate} - Controls whether to apply the check to private 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 applyToPublic} - Controls whether to apply the check to public member. 070 * Type is {@code boolean}. 071 * Default value is {@code true}. 072 * </li> 073 * <li> 074 * Property {@code format} - Specifies valid identifiers. 075 * Type is {@code java.util.regex.Pattern}. 076 * Default value is {@code "^[a-z][a-zA-Z0-9]*$"}. 077 * </li> 078 * </ul> 079 * <p> 080 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} 081 * </p> 082 * <p> 083 * Violation Message Keys: 084 * </p> 085 * <ul> 086 * <li> 087 * {@code method.name.equals.class.name} 088 * </li> 089 * <li> 090 * {@code name.invalidPattern} 091 * </li> 092 * </ul> 093 * 094 * @since 3.0 095 */ 096public class MethodNameCheck 097 extends AbstractAccessControlNameCheck { 098 099 /** 100 * A key is pointing to the warning message text in "messages.properties" 101 * file. 102 */ 103 public static final String MSG_KEY = "method.name.equals.class.name"; 104 105 /** 106 * Controls whether to allow a method name to have the same name as the residing class name. 107 * This is not to be confused with a constructor. An easy mistake is to place a return type on 108 * a constructor declaration which turns it into a method. For example: 109 * <pre> 110 * class MyClass { 111 * public void MyClass() {} //this is a method 112 * public MyClass() {} //this is a constructor 113 * } 114 * </pre> 115 */ 116 private boolean allowClassName; 117 118 /** Creates a new {@code MethodNameCheck} instance. */ 119 public MethodNameCheck() { 120 super("^[a-z][a-zA-Z0-9]*$"); 121 } 122 123 @Override 124 public int[] getDefaultTokens() { 125 return getRequiredTokens(); 126 } 127 128 @Override 129 public int[] getAcceptableTokens() { 130 return getRequiredTokens(); 131 } 132 133 @Override 134 public int[] getRequiredTokens() { 135 return new int[] {TokenTypes.METHOD_DEF, }; 136 } 137 138 @Override 139 public void visitToken(DetailAST ast) { 140 if (!AnnotationUtil.hasOverrideAnnotation(ast)) { 141 // Will check the name against the format. 142 super.visitToken(ast); 143 } 144 145 if (!allowClassName) { 146 final DetailAST method = 147 ast.findFirstToken(TokenTypes.IDENT); 148 // in all cases this will be the classDef type except anon inner 149 // with anon inner classes this will be the Literal_New keyword 150 final DetailAST classDefOrNew = ast.getParent().getParent(); 151 final DetailAST classIdent = 152 classDefOrNew.findFirstToken(TokenTypes.IDENT); 153 // Following logic is to handle when a classIdent can not be 154 // found. This is when you have a Literal_New keyword followed 155 // a DOT, which is when you have: 156 // new Outclass.InnerInterface(x) { ... } 157 // Such a rare case, will not have the logic to handle parsing 158 // down the tree looking for the first ident. 159 if (classIdent != null 160 && method.getText().equals(classIdent.getText())) { 161 log(method, MSG_KEY, method.getText()); 162 } 163 } 164 } 165 166 /** 167 * Setter to controls whether to allow a method name to have the same name as the residing 168 * class name. This is not to be confused with a constructor. An easy mistake is to place 169 * a return type on a constructor declaration which turns it into a method. For example: 170 * <pre> 171 * class MyClass { 172 * public void MyClass() {} //this is a method 173 * public MyClass() {} //this is a constructor 174 * } 175 * </pre> 176 * 177 * @param allowClassName true to allow false to disallow 178 * @since 5.0 179 */ 180 public void setAllowClassName(boolean allowClassName) { 181 this.allowClassName = allowClassName; 182 } 183 184}