Skip to content

Commit

Permalink
JUnitMethodDeclaration: Prevent renaming methods to Java keywords
Browse files Browse the repository at this point in the history
  • Loading branch information
rickie committed Feb 16, 2022
1 parent bb0fd48 commit 6209354
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static com.google.errorprone.matchers.Matchers.anyOf;
import static com.google.errorprone.matchers.Matchers.isType;
import static java.util.function.Predicate.not;
import static tech.picnic.errorprone.bugpatterns.JavaKeywords.isJavaKeyword;

import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableSet;
Expand Down Expand Up @@ -85,35 +86,41 @@ public Description matchMethod(MethodTree tree, VisitorState state) {

if (isTestMethod) {
tryCanonicalizeMethodName(tree)
.filter(methodName -> !reportDescriptionForPossibleNameClash(tree, methodName, state))
.filter(methodName -> isValidMethodName(tree, methodName, state))
.ifPresent(
methodName -> builder.merge(SuggestedFixes.renameMethod(tree, methodName, state)));
}
return builder.isEmpty() ? Description.NO_MATCH : describeMatch(tree, builder.build());
}

private boolean reportDescriptionForPossibleNameClash(
MethodTree tree, String methodName, VisitorState state) {
private boolean isValidMethodName(MethodTree tree, String methodName, VisitorState state) {
if (isMethodNameInClass(methodName, state)) {
state.reportMatch(
buildDescription(tree)
.setMessage(
String.format("A method with name %s already exists in the class.", methodName))
.build());
return true;
reportIncorrectMethodName(
methodName, tree, "A method with name %s already exists in the class.", state);
return false;
}

if (isMethodNameStaticallyImported(methodName, state)) {
state.reportMatch(
buildDescription(tree)
.setMessage(
String.format(
"A method with name %s is already statically imported.", methodName))
.build());
return true;
reportIncorrectMethodName(
methodName, tree, "A method with name %s is already statically imported.", state);
return false;
}

return false;
if (isJavaKeyword(methodName)) {
reportIncorrectMethodName(
methodName,
tree,
"A Java keyword with this name `%s` cannot be used as method name.",
state);
return false;
}
return true;
}

private void reportIncorrectMethodName(
String methodName, MethodTree tree, String message, VisitorState state) {
state.reportMatch(
buildDescription(tree).setMessage(String.format(message, methodName)).build());
}

private static boolean isMethodNameInClass(String methodName, VisitorState state) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package tech.picnic.errorprone.bugpatterns;

import com.google.common.collect.ImmutableSet;

@SuppressWarnings("DeclarationOrder" /* The private constructor should come first. */)
final class JavaKeywords {
private JavaKeywords() {}

/**
* List of all Java Language Keywords.
*
* <p>See: the <a
* href="https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html">Oracle
* Documentation</a> on Java Keywords.
*/
private static final ImmutableSet<String> JAVA_KEYWORDS =
ImmutableSet.of(
"assert",
"boolean",
"break",
"byte",
"case",
"catch",
"char",
"class",
"const",
"continue",
"default",
"do",
"double",
"else",
"enum",
"extends",
"final",
"finally",
"float",
"for",
"goto",
"if",
"implements",
"import",
"instanceof",
"int",
"interface",
"long",
"native",
"new",
"package",
"private",
"protected",
"public",
"return",
"short",
"static",
"strictfp",
"super",
"switch",
"synchronized",
"this",
"throw",
"throws",
"transient",
"try",
"void",
"volatile",
"while");

/**
* Check whether the String is a Java Language Keyword.
*
* @param possibleKeyword a possible Java keyword
* @return whether the String is a Java keyword
*/
public static boolean isJavaKeyword(String possibleKeyword) {
return JAVA_KEYWORDS.contains(possibleKeyword);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -267,4 +267,44 @@ void methodAlreadyInStaticImports() {
"}")
.doTest(TestMode.TEXT_MATCH);
}

@Test
void methodHasJavaKeyword() {
refactoringTestHelper
.addInputLines(
"A.java",
"import org.junit.jupiter.api.Test;",
"",
"class A {",
" @Test",
" void testClass() {}",
"",
" @Test",
" void testClazz() {}",
"",
" @Test",
" void testThrow() {}",
"",
" @Test",
" void testThrowww() {}",
"}")
.addOutputLines(
"A.java",
"import org.junit.jupiter.api.Test;",
"",
"class A {",
" @Test",
" void testClass() {}",
"",
" @Test",
" void clazz() {}",
"",
" @Test",
" void testThrow() {}",
"",
" @Test",
" void throwww() {}",
"}")
.doTest(TestMode.TEXT_MATCH);
}
}

0 comments on commit 6209354

Please sign in to comment.