001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2026 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 * <div> 028 * Checks that method names conform to a specified pattern. 029 * </div> 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 * @since 3.0 040 */ 041public class MethodNameCheck 042 extends AbstractAccessControlNameCheck { 043 044 /** 045 * A key is pointing to the warning message text in "messages.properties" 046 * file. 047 */ 048 public static final String MSG_KEY = "method.name.equals.class.name"; 049 050 /** 051 * A key is pointing to the warning message text in "messages.properties" 052 * file. 053 */ 054 public static final String MSG_INVALID_PATTERN = "name.invalidPattern"; 055 056 /** 057 * Control whether to allow a method name to have the same name as the enclosing class name. 058 * Setting this property {@code false} helps to avoid confusion 059 * between constructors and methods. 060 */ 061 private boolean allowClassName; 062 063 /** Creates a new {@code MethodNameCheck} instance. */ 064 public MethodNameCheck() { 065 super("^[a-z][a-zA-Z0-9]*$", MSG_INVALID_PATTERN); 066 } 067 068 @Override 069 public int[] getDefaultTokens() { 070 return getRequiredTokens(); 071 } 072 073 @Override 074 public int[] getAcceptableTokens() { 075 return getRequiredTokens(); 076 } 077 078 @Override 079 public int[] getRequiredTokens() { 080 return new int[] {TokenTypes.METHOD_DEF, }; 081 } 082 083 /** 084 * Setter to control if check should apply to package-private members. 085 * 086 * @param applyTo new value of the property. 087 * @propertySince 5.1 088 */ 089 @Override 090 public final void setApplyToPackage(boolean applyTo) { 091 super.setApplyToPackage(applyTo); 092 } 093 094 /** 095 * Setter to control if check should apply to private members. 096 * 097 * @param applyTo new value of the property. 098 * @propertySince 5.1 099 */ 100 @Override 101 public final void setApplyToPrivate(boolean applyTo) { 102 super.setApplyToPrivate(applyTo); 103 } 104 105 /** 106 * Setter to control if check should apply to protected members. 107 * 108 * @param applyTo new value of the property. 109 * @propertySince 5.1 110 */ 111 @Override 112 public final void setApplyToProtected(boolean applyTo) { 113 super.setApplyToProtected(applyTo); 114 } 115 116 /** 117 * Setter to control if check should apply to public members. 118 * 119 * @param applyTo new value of the property. 120 * @propertySince 5.1 121 */ 122 @Override 123 public final void setApplyToPublic(boolean applyTo) { 124 super.setApplyToPublic(applyTo); 125 } 126 127 @Override 128 public void visitToken(DetailAST ast) { 129 if (!AnnotationUtil.hasOverrideAnnotation(ast)) { 130 // Will check the name against the format. 131 super.visitToken(ast); 132 } 133 134 if (!allowClassName) { 135 // in all cases this will be the classDef type except anon inner 136 // with anon inner classes this will be the Literal_New keyword 137 final DetailAST classDefOrNew = ast.getParent().getParent(); 138 139 if (classDefOrNew != null) { 140 final DetailAST method = ast.findFirstToken(TokenTypes.IDENT); 141 final DetailAST classIdent = 142 classDefOrNew.findFirstToken(TokenTypes.IDENT); 143 // Following logic is to handle when a classIdent can not be 144 // found. This is when you have a Literal_New keyword followed 145 // a DOT, which is when you have: 146 // new Outclass.InnerInterface(x) { ... } 147 // Such a rare case, will not have the logic to handle parsing 148 // down the tree looking for the first ident. 149 if (classIdent != null 150 && method.getText().equals(classIdent.getText())) { 151 log(method, MSG_KEY, method.getText()); 152 } 153 } 154 } 155 } 156 157 /** 158 * Setter to control whether to allow a method name to have the same name 159 * as the enclosing class name. Setting this property {@code false} 160 * helps to avoid confusion between constructors and methods. 161 * 162 * @param allowClassName true to allow false to disallow 163 * @since 5.0 164 */ 165 public void setAllowClassName(boolean allowClassName) { 166 this.allowClassName = allowClassName; 167 } 168 169}