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