001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2014 Oliver Burn 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//////////////////////////////////////////////////////////////////////////////// 019package com.puppycrawl.tools.checkstyle.checks.naming; 020 021import com.puppycrawl.tools.checkstyle.api.DetailAST; 022import com.puppycrawl.tools.checkstyle.api.TokenTypes; 023 024/** 025 * <p> 026 * Checks that method names conform to a format specified 027 * by the format property. The format is a 028 * {@link java.util.regex.Pattern regular expression} 029 * and defaults to 030 * <strong>^[a-z][a-zA-Z0-9]*$</strong>. 031 * </p> 032 * 033 * <p> 034 * Also, checks if a method name has the same name as the residing class. 035 * The default is false (it is not allowed). It is legal in Java to have 036 * method with the same name as a class. As long as a return type is specified 037 * it is a method and not a constructor which it could be easily confused as. 038 * </p> 039 * 040 * <p> 041 * An example of how to configure the check is: 042 * </p> 043 * <pre> 044 * <module name="MethodName"/> 045 * </pre> 046 * <p> 047 * An example of how to configure the check for names that begin with 048 * a lower case letter, followed by letters, digits, and underscores is: 049 * </p> 050 * <pre> 051 * <module name="MethodName"> 052 * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> 053 * </module> 054 * </pre> 055 * 056 * <p> 057 * An example of how to configure the check to allow method names 058 * to be equal to the residing class name is: 059 * </p> 060 * <pre> 061 * <module name="MethodName"> 062 * <property name="allowClassName" value="true"/> 063 * </module> 064 * </pre> 065 * @author Oliver Burn 066 * @author Travis Schneeberger 067 * @version 1.1 068 */ 069public class MethodNameCheck 070 extends AbstractAccessControlNameCheck 071{ 072 /** 073 * for allowing method name to be the same as the class name. 074 */ 075 private boolean mAllowClassName; 076 077 /** Creates a new <code>MethodNameCheck</code> instance. */ 078 public MethodNameCheck() 079 { 080 super("^[a-z][a-zA-Z0-9]*$"); 081 } 082 083 @Override 084 public int[] getDefaultTokens() 085 { 086 return new int[] {TokenTypes.METHOD_DEF, }; 087 } 088 089 @Override 090 public void visitToken(DetailAST aAst) 091 { 092 super.visitToken(aAst); // Will check the name against the format. 093 094 if (!mAllowClassName) { 095 final DetailAST method = 096 aAst.findFirstToken(TokenTypes.IDENT); 097 //in all cases this will be the classDef type except anon inner 098 //with anon inner classes this will be the Literal_New keyword 099 final DetailAST classDefOrNew = aAst.getParent().getParent(); 100 final DetailAST classIdent = 101 classDefOrNew.findFirstToken(TokenTypes.IDENT); 102 // Following logic is to handle when a classIdent can not be 103 // found. This is when you have a Literal_New keyword followed 104 // a DOT, which is when you have: 105 // new Outclass.InnerInterface(x) { ... } 106 // Such a rare case, will not have the logic to handle parsing 107 // down the tree looking for the first ident. 108 if ((null != classIdent) 109 && method.getText().equals(classIdent.getText())) 110 { 111 log(method.getLineNo(), method.getColumnNo(), 112 "method.name.equals.class.name", method.getText()); 113 } 114 } 115 } 116 117 /** 118 * Sets the property for allowing a method to be the same name as a class. 119 * @param aAllowClassName true to allow false to disallow 120 */ 121 public void setAllowClassName(boolean aAllowClassName) 122 { 123 mAllowClassName = aAllowClassName; 124 } 125}