Skip to content

Commit dd91993

Browse files
cushonError Prone Team
authored and
Error Prone Team
committed
Add ByteString.fromHex to AlwaysThrows
Startblock: b/175305585 is fixed PiperOrigin-RevId: 405440198
1 parent 6551909 commit dd91993

File tree

1 file changed

+48
-9
lines changed

1 file changed

+48
-9
lines changed

core/src/main/java/com/google/errorprone/bugpatterns/AlwaysThrows.java

+48-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.google.errorprone.BugPattern.SeverityLevel.ERROR;
2020
import static com.google.errorprone.matchers.Description.NO_MATCH;
21+
import static java.util.Arrays.stream;
2122

2223
import com.google.common.collect.ImmutableMap;
2324
import com.google.common.collect.Iterables;
@@ -28,9 +29,11 @@
2829
import com.google.errorprone.matchers.Matcher;
2930
import com.google.errorprone.matchers.method.MethodMatchers;
3031
import com.google.errorprone.util.ASTHelpers;
32+
import com.google.protobuf.ByteString;
3133
import com.sun.source.tree.ExpressionTree;
3234
import com.sun.source.tree.MethodInvocationTree;
3335
import com.sun.tools.javac.code.Symbol.MethodSymbol;
36+
import java.lang.reflect.InvocationTargetException;
3437
import java.util.function.Consumer;
3538

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

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

61-
private static final Matcher<ExpressionTree> MATCHER =
62-
MethodMatchers.staticMethod()
63-
.onClassAny(VALIDATORS.keySet())
64-
.named("parse")
65-
.withParameters("java.lang.CharSequence");
63+
enum Apis {
64+
PARSE_TIME(
65+
MethodMatchers.staticMethod()
66+
.onClassAny(VALIDATORS.keySet())
67+
.named("parse")
68+
.withParameters("java.lang.CharSequence")) {
69+
@Override
70+
void validate(MethodInvocationTree tree, String argument, VisitorState state)
71+
throws Throwable {
72+
MethodSymbol sym = ASTHelpers.getSymbol(tree);
73+
VALIDATORS.get(sym.owner.getQualifiedName().toString()).accept(argument);
74+
}
75+
},
76+
BYTE_STRING(
77+
MethodMatchers.staticMethod()
78+
.onClass("com.google.protobuf.ByteString")
79+
.named("fromHex")
80+
.withParameters("java.lang.String")) {
81+
@Override
82+
void validate(MethodInvocationTree tree, String argument, VisitorState state)
83+
throws Throwable {
84+
try {
85+
ByteString.class.getMethod("fromHex", String.class).invoke(null, argument);
86+
} catch (NoSuchMethodException | IllegalAccessException e) {
87+
return;
88+
} catch (InvocationTargetException e) {
89+
throw e.getCause();
90+
}
91+
}
92+
};
93+
94+
Apis(Matcher<ExpressionTree> matcher) {
95+
this.matcher = matcher;
96+
}
97+
98+
@SuppressWarnings("ImmutableEnumChecker") // is immutable
99+
private final Matcher<ExpressionTree> matcher;
100+
101+
abstract void validate(MethodInvocationTree tree, String argument, VisitorState state)
102+
throws Throwable;
103+
}
66104

67105
@Override
68106
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
69-
if (!MATCHER.matches(tree, state)) {
107+
Apis api =
108+
stream(Apis.values()).filter(m -> m.matcher.matches(tree, state)).findAny().orElse(null);
109+
if (api == null) {
70110
return NO_MATCH;
71111
}
72112
String argument =
73113
ASTHelpers.constValue(Iterables.getOnlyElement(tree.getArguments()), String.class);
74114
if (argument == null) {
75115
return NO_MATCH;
76116
}
77-
MethodSymbol sym = ASTHelpers.getSymbol(tree);
78117
try {
79-
VALIDATORS.get(sym.owner.getQualifiedName().toString()).accept(argument);
118+
api.validate(tree, argument, state);
80119
} catch (Throwable t) {
81120
return buildDescription(tree)
82121
.setMessage(

0 commit comments

Comments
 (0)