Skip to content

Commit

Permalink
Add ByteString.fromHex to AlwaysThrows
Browse files Browse the repository at this point in the history
Startblock:
   b/175305585 is fixed
PiperOrigin-RevId: 405440198
  • Loading branch information
cushon authored and Error Prone Team committed Oct 25, 2021
1 parent 6551909 commit dd91993
Showing 1 changed file with 48 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
import static com.google.errorprone.matchers.Description.NO_MATCH;
import static java.util.Arrays.stream;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
Expand All @@ -28,9 +29,11 @@
import com.google.errorprone.matchers.Matcher;
import com.google.errorprone.matchers.method.MethodMatchers;
import com.google.errorprone.util.ASTHelpers;
import com.google.protobuf.ByteString;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import java.lang.reflect.InvocationTargetException;
import java.util.function.Consumer;

/** A {@link BugChecker}; see the associated {@link BugPattern} annotation for details. */
Expand All @@ -40,7 +43,6 @@
severity = ERROR)
public class AlwaysThrows extends BugChecker implements MethodInvocationTreeMatcher {

// TODO(cushon): generalize assumptions here (e.g. about 'parse' and 'CharSequence')
@SuppressWarnings("UnnecessarilyFullyQualified")
private static final ImmutableMap<String, Consumer<CharSequence>> VALIDATORS =
ImmutableMap.<String, Consumer<CharSequence>>builder()
Expand All @@ -58,25 +60,62 @@ public class AlwaysThrows extends BugChecker implements MethodInvocationTreeMatc
.put("java.time.ZonedDateTime", java.time.ZonedDateTime::parse)
.build();

private static final Matcher<ExpressionTree> MATCHER =
MethodMatchers.staticMethod()
.onClassAny(VALIDATORS.keySet())
.named("parse")
.withParameters("java.lang.CharSequence");
enum Apis {
PARSE_TIME(
MethodMatchers.staticMethod()
.onClassAny(VALIDATORS.keySet())
.named("parse")
.withParameters("java.lang.CharSequence")) {
@Override
void validate(MethodInvocationTree tree, String argument, VisitorState state)
throws Throwable {
MethodSymbol sym = ASTHelpers.getSymbol(tree);
VALIDATORS.get(sym.owner.getQualifiedName().toString()).accept(argument);
}
},
BYTE_STRING(
MethodMatchers.staticMethod()
.onClass("com.google.protobuf.ByteString")
.named("fromHex")
.withParameters("java.lang.String")) {
@Override
void validate(MethodInvocationTree tree, String argument, VisitorState state)
throws Throwable {
try {
ByteString.class.getMethod("fromHex", String.class).invoke(null, argument);
} catch (NoSuchMethodException | IllegalAccessException e) {
return;
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
};

Apis(Matcher<ExpressionTree> matcher) {
this.matcher = matcher;
}

@SuppressWarnings("ImmutableEnumChecker") // is immutable
private final Matcher<ExpressionTree> matcher;

abstract void validate(MethodInvocationTree tree, String argument, VisitorState state)
throws Throwable;
}

@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (!MATCHER.matches(tree, state)) {
Apis api =
stream(Apis.values()).filter(m -> m.matcher.matches(tree, state)).findAny().orElse(null);
if (api == null) {
return NO_MATCH;
}
String argument =
ASTHelpers.constValue(Iterables.getOnlyElement(tree.getArguments()), String.class);
if (argument == null) {
return NO_MATCH;
}
MethodSymbol sym = ASTHelpers.getSymbol(tree);
try {
VALIDATORS.get(sym.owner.getQualifiedName().toString()).accept(argument);
api.validate(tree, argument, state);
} catch (Throwable t) {
return buildDescription(tree)
.setMessage(
Expand Down

0 comments on commit dd91993

Please sign in to comment.