Skip to content

Commit

Permalink
Create namedAnyOf(String... varargs) convenience MethodMatchers method.
Browse files Browse the repository at this point in the history
RELNOTES: N/A

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=212299476
  • Loading branch information
epmjohnston authored and ronshapiro committed Sep 12, 2018
1 parent f8d8e93 commit 3926cde
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.errorprone.matchers.method;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.VisitorState;
import com.google.errorprone.matchers.method.MethodMatchers.MethodClassMatcher;
import com.google.errorprone.matchers.method.MethodMatchers.MethodNameMatcher;
Expand Down Expand Up @@ -50,6 +51,16 @@ public MethodNameMatcher named(String name) {
return new MethodNameMatcherImpl.Exact(this, name);
}

@Override
public MethodNameMatcher namedAnyOf(String... names) {
return namedAnyOf(ImmutableList.copyOf(names));
}

@Override
public MethodNameMatcher namedAnyOf(Iterable<String> names) {
return new MethodNameMatcherImpl.AnyOf(this, names);
}

@Override
public MethodNameMatcher withAnyName() {
return new MethodNameMatcherImpl.Any(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ public interface MethodClassMatcher extends Matcher<ExpressionTree> {
/** Match methods with the given name. (e.g. {@code toString}) */
MethodNameMatcher named(String name);

/** Match methods with any of the given names. */
MethodNameMatcher namedAnyOf(String... names);

/** Match methods with any of the given names. */
MethodNameMatcher namedAnyOf(Iterable<String> names);

/** Match methods with any name. */
MethodNameMatcher withAnyName();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.VisitorState;
import com.google.errorprone.matchers.method.MethodMatchers.MethodNameMatcher;
import com.google.errorprone.matchers.method.MethodMatchers.ParameterMatcher;
import com.google.errorprone.suppliers.Suppliers;
import com.sun.source.tree.ExpressionTree;
import com.sun.tools.javac.util.Name;
import java.util.Arrays;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -54,7 +56,7 @@ static class Exact extends MethodNameMatcherImpl {
this.name = name;
checkArgument(
!name.contains("(") && !name.contains(")"),
"method name (%s) cannot contain parentheses; use \"getBytes\" instead of \"getBytes()\"",
"method name (%s) cannot contain parentheses. e.g., use \"foo\" instead of \"foo()\"",
name);
}

Expand Down Expand Up @@ -100,4 +102,24 @@ protected Optional<MatchState> matchResult(
return Optional.of(method);
}
}

/** Matches on any of the given method names. */
static class AnyOf extends MethodNameMatcherImpl {

private final ImmutableList<String> names;

AnyOf(AbstractSimpleMatcher<MatchState> baseMatcher, Iterable<String> names) {
super(baseMatcher);
this.names = ImmutableList.copyOf(names);
}

@Override
protected Optional<MatchState> matchResult(
ExpressionTree item, MatchState method, VisitorState state) {
Name symbolName = method.sym().getSimpleName();
return names.stream().anyMatch(symbolName::contentEquals)
? Optional.of(method)
: Optional.absent();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,18 @@
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
import static com.google.errorprone.matchers.Description.NO_MATCH;
import static com.google.errorprone.matchers.Matchers.instanceMethod;
import static com.google.errorprone.matchers.Matchers.staticMethod;
import static com.google.errorprone.matchers.method.MethodMatchers.constructor;

import com.google.errorprone.BugPattern;
import com.google.errorprone.BugPattern.ProvidesFix;
import com.google.errorprone.CompilationTestHelper;
import com.google.errorprone.VisitorState;
import com.google.errorprone.bugpatterns.BugChecker;
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
import com.google.errorprone.fixes.SuggestedFix;
import com.google.errorprone.matchers.method.MethodMatchers;
import com.google.errorprone.matchers.method.MethodMatchers.MethodNameMatcher;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.NewClassTree;
Expand All @@ -45,7 +48,8 @@ public class MethodMatchersTest {
name = "ConstructorDeleter",
category = JDK,
summary = "Deletes constructors",
severity = ERROR)
severity = ERROR,
providesFix = ProvidesFix.REQUIRES_HUMAN_ATTENTION)
public static class ConstructorDeleter extends BugChecker
implements BugChecker.MethodInvocationTreeMatcher, BugChecker.NewClassTreeMatcher {

Expand Down Expand Up @@ -158,4 +162,54 @@ public void varargsParameterMatcher() {
"}")
.doTest();
}

/** Test BugChecker for namedAnyOf(...) */
@BugPattern(name = "FlagMethodNames", summary = "", severity = ERROR)
public static class FlagMethodNamesChecker extends BugChecker
implements MethodInvocationTreeMatcher {
private static final MethodNameMatcher INSTANCE_MATCHER =
instanceMethod().anyClass().namedAnyOf("foo", "bar");
private static final MethodNameMatcher STATIC_MATCHER =
staticMethod().anyClass().namedAnyOf("fizz", "buzz");

@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (INSTANCE_MATCHER.matches(tree, state)) {
return buildDescription(tree).setMessage("instance varargs").build();
}
if (STATIC_MATCHER.matches(tree, state)) {
return buildDescription(tree).setMessage("static varargs").build();
}
return NO_MATCH;
}
}

@Test
public void namedAnyOfTest() {
CompilationTestHelper.newInstance(FlagMethodNamesChecker.class, getClass())
.addSourceLines(
"Test.java",
"class Test {",
" void foo() {}",
" void bar() {}",
" static void fizz() {}",
" static void buzz() {}",
" void anotherMethod() {}",
" static void yetAnother() {}",
" void f() {",
" // BUG: Diagnostic contains: instance varargs",
" this.foo();",
" // BUG: Diagnostic contains: instance varargs",
" this.bar();",
" // BUG: Diagnostic contains: static varargs",
" Test.fizz();",
" // BUG: Diagnostic contains: static varargs",
" Test.buzz();",
" // These ones are ok",
" this.anotherMethod();",
" Test.yetAnother();",
" }",
"}")
.doTest();
}
}

0 comments on commit 3926cde

Please sign in to comment.