| 1 | //////////////////////////////////////////////////////////////////////////////// | |
| 2 | // checkstyle: Checks Java source code for adherence to a set of rules. | |
| 3 | // Copyright (C) 2001-2018 the original author or authors. | |
| 4 | // | |
| 5 | // This library is free software; you can redistribute it and/or | |
| 6 | // modify it under the terms of the GNU Lesser General Public | |
| 7 | // License as published by the Free Software Foundation; either | |
| 8 | // version 2.1 of the License, or (at your option) any later version. | |
| 9 | // | |
| 10 | // This library is distributed in the hope that it will be useful, | |
| 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 13 | // Lesser General Public License for more details. | |
| 14 | // | |
| 15 | // You should have received a copy of the GNU Lesser General Public | |
| 16 | // License along with this library; if not, write to the Free Software | |
| 17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 18 | //////////////////////////////////////////////////////////////////////////////// | |
| 19 | ||
| 20 | package com.puppycrawl.tools.checkstyle.checks.naming; | |
| 21 | ||
| 22 | import com.puppycrawl.tools.checkstyle.api.DetailAST; | |
| 23 | import com.puppycrawl.tools.checkstyle.api.TokenTypes; | |
| 24 | import com.puppycrawl.tools.checkstyle.utils.AnnotationUtility; | |
| 25 | ||
| 26 | /** | |
| 27 | * <p> | |
| 28 | * Checks that method names conform to a format specified | |
| 29 | * by the format property. The format is a | |
| 30 | * {@link java.util.regex.Pattern regular expression} | |
| 31 | * and defaults to | |
| 32 | * <strong>^[a-z][a-zA-Z0-9]*$</strong>. | |
| 33 | * </p> | |
| 34 | * | |
| 35 | * <p>Also, checks if a method name has the same name as the residing class. | |
| 36 | * The default is false (it is not allowed). It is legal in Java to have | |
| 37 | * method with the same name as a class. As long as a return type is specified | |
| 38 | * it is a method and not a constructor which it could be easily confused as. | |
| 39 | * <h3>Does not check-style the name of an overridden methods</h3> because the developer does not | |
| 40 | * have a choice in renaming such methods. | |
| 41 | * | |
| 42 | * <p> | |
| 43 | * An example of how to configure the check is: | |
| 44 | * </p> | |
| 45 | * <pre> | |
| 46 | * <module name="MethodName"/> | |
| 47 | * </pre> | |
| 48 | * <p> | |
| 49 | * An example of how to configure the check for names that begin with | |
| 50 | * a lower case letter, followed by letters, digits, and underscores is: | |
| 51 | * </p> | |
| 52 | * <pre> | |
| 53 | * <module name="MethodName"> | |
| 54 | * <property name="format" value="^[a-z](_?[a-zA-Z0-9]+)*$"/> | |
| 55 | * </module> | |
| 56 | * </pre> | |
| 57 | * | |
| 58 | * <p> | |
| 59 | * An example of how to configure the check to allow method names | |
| 60 | * to be equal to the residing class name is: | |
| 61 | * </p> | |
| 62 | * <pre> | |
| 63 | * <module name="MethodName"> | |
| 64 | * <property name="allowClassName" value="true"/> | |
| 65 | * </module> | |
| 66 | * </pre> | |
| 67 | * @author Oliver Burn | |
| 68 | * @author Travis Schneeberger | |
| 69 | * @author Utkarsh Srivastava | |
| 70 | */ | |
| 71 | public class MethodNameCheck | |
| 72 | extends AbstractAccessControlNameCheck { | |
| 73 | ||
| 74 | /** | |
| 75 | * A key is pointing to the warning message text in "messages.properties" | |
| 76 | * file. | |
| 77 | */ | |
| 78 | public static final String MSG_KEY = "method.name.equals.class.name"; | |
| 79 | ||
| 80 | /** | |
| 81 | * {@link Override Override} annotation name. | |
| 82 | */ | |
| 83 | private static final String OVERRIDE = "Override"; | |
| 84 | ||
| 85 | /** | |
| 86 | * Canonical {@link Override Override} annotation name. | |
| 87 | */ | |
| 88 | private static final String CANONICAL_OVERRIDE = "java.lang." + OVERRIDE; | |
| 89 | ||
| 90 | /** | |
| 91 | * For allowing method name to be the same as the class name. | |
| 92 | */ | |
| 93 | private boolean allowClassName; | |
| 94 | ||
| 95 | /** Creates a new {@code MethodNameCheck} instance. */ | |
| 96 | public MethodNameCheck() { | |
| 97 | super("^[a-z][a-zA-Z0-9]*$"); | |
| 98 | } | |
| 99 | ||
| 100 | @Override | |
| 101 | public int[] getDefaultTokens() { | |
| 102 |
1
1. getDefaultTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheck::getDefaultTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getRequiredTokens(); |
| 103 | } | |
| 104 | ||
| 105 | @Override | |
| 106 | public int[] getAcceptableTokens() { | |
| 107 |
1
1. getAcceptableTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheck::getAcceptableTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return getRequiredTokens(); |
| 108 | } | |
| 109 | ||
| 110 | @Override | |
| 111 | public int[] getRequiredTokens() { | |
| 112 |
1
1. getRequiredTokens : mutated return of Object value for com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheck::getRequiredTokens to ( if (x != null) null else throw new RuntimeException ) → KILLED |
return new int[] {TokenTypes.METHOD_DEF, }; |
| 113 | } | |
| 114 | ||
| 115 | @Override | |
| 116 | public void visitToken(DetailAST ast) { | |
| 117 |
1
1. visitToken : negated conditional → KILLED |
if (!AnnotationUtility.containsAnnotation(ast, OVERRIDE) |
| 118 |
1
1. visitToken : negated conditional → KILLED |
&& !AnnotationUtility.containsAnnotation(ast, CANONICAL_OVERRIDE)) { |
| 119 | // Will check the name against the format. | |
| 120 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/naming/AbstractAccessControlNameCheck::visitToken → KILLED |
super.visitToken(ast); |
| 121 | } | |
| 122 | ||
| 123 |
1
1. visitToken : negated conditional → KILLED |
if (!allowClassName) { |
| 124 | final DetailAST method = | |
| 125 | ast.findFirstToken(TokenTypes.IDENT); | |
| 126 | //in all cases this will be the classDef type except anon inner | |
| 127 | //with anon inner classes this will be the Literal_New keyword | |
| 128 | final DetailAST classDefOrNew = ast.getParent().getParent(); | |
| 129 | final DetailAST classIdent = | |
| 130 | classDefOrNew.findFirstToken(TokenTypes.IDENT); | |
| 131 | // Following logic is to handle when a classIdent can not be | |
| 132 | // found. This is when you have a Literal_New keyword followed | |
| 133 | // a DOT, which is when you have: | |
| 134 | // new Outclass.InnerInterface(x) { ... } | |
| 135 | // Such a rare case, will not have the logic to handle parsing | |
| 136 | // down the tree looking for the first ident. | |
| 137 |
1
1. visitToken : negated conditional → KILLED |
if (classIdent != null |
| 138 |
1
1. visitToken : negated conditional → KILLED |
&& method.getText().equals(classIdent.getText())) { |
| 139 |
1
1. visitToken : removed call to com/puppycrawl/tools/checkstyle/checks/naming/MethodNameCheck::log → KILLED |
log(method.getLineNo(), method.getColumnNo(), |
| 140 | MSG_KEY, method.getText()); | |
| 141 | } | |
| 142 | } | |
| 143 | } | |
| 144 | ||
| 145 | /** | |
| 146 | * Sets the property for allowing a method to be the same name as a class. | |
| 147 | * @param allowClassName true to allow false to disallow | |
| 148 | */ | |
| 149 | public void setAllowClassName(boolean allowClassName) { | |
| 150 | this.allowClassName = allowClassName; | |
| 151 | } | |
| 152 | ||
| 153 | } | |
Mutations | ||
| 102 |
1.1 |
|
| 107 |
1.1 |
|
| 112 |
1.1 |
|
| 117 |
1.1 |
|
| 118 |
1.1 |
|
| 120 |
1.1 |
|
| 123 |
1.1 |
|
| 137 |
1.1 |
|
| 138 |
1.1 |
|
| 139 |
1.1 |