Skip to content

Commit bc3309a

Browse files
cpovirkError Prone Team
authored and
Error Prone Team
committed
Flag comparisons of SomeEnum.valueOf(...) to null.
(also `SomeNumber.valueOf(...)`, but that comes up very rarely, enough so that I didn't bother to explore `Boolean.valueOf` or `String.valueOf`) PiperOrigin-RevId: 629692421
1 parent 6a8f493 commit bc3309a

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

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

+20
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,14 @@ private static boolean isNull(ExpressionTree tree) {
145145

146146
private final boolean matchTestAssertions;
147147
private final boolean checkPrimitives;
148+
private final boolean checkValueOf;
148149

149150
@Inject
150151
ImpossibleNullComparison(ErrorProneFlags flags) {
151152
this.matchTestAssertions =
152153
flags.getBoolean("ProtoFieldNullComparison:MatchTestAssertions").orElse(true);
153154
this.checkPrimitives = flags.getBoolean("ImmutableNullComparison:CheckPrimitives").orElse(true);
155+
this.checkValueOf = flags.getBoolean("ImpossibleNullComparison:CheckValueOf").orElse(true);
154156
}
155157

156158
@Override
@@ -262,6 +264,7 @@ private Optional<Fixer> getFixer(ExpressionTree tree, VisitorState state) {
262264
}
263265
return stream(GetterTypes.values())
264266
.filter(gt -> !gt.equals(GetterTypes.PRIMITIVE) || checkPrimitives)
267+
.filter(gt -> !gt.equals(GetterTypes.VALUE_OF) || checkValueOf)
265268
.map(type -> type.match(resolvedTree, state))
266269
.filter(Objects::nonNull)
267270
.findFirst();
@@ -311,6 +314,12 @@ private interface Fixer {
311314
private static final Matcher<ExpressionTree> TABLE_COLUMN_MATCHER =
312315
instanceMethod().onDescendantOf("com.google.common.collect.Table").named("column");
313316

317+
private static final Matcher<ExpressionTree> NON_NULL_VALUE_OF =
318+
staticMethod()
319+
.onDescendantOfAny("java.lang.Enum", "java.lang.Number")
320+
.named("valueOf")
321+
.withParameters("java.lang.String");
322+
314323
private enum GetterTypes {
315324
OPTIONAL_GET {
316325
@Nullable
@@ -394,6 +403,17 @@ Fixer match(ExpressionTree tree, VisitorState state) {
394403
return type != null && type.isPrimitive() ? GetterTypes::emptyFix : null;
395404
}
396405
},
406+
VALUE_OF {
407+
@Nullable
408+
@Override
409+
Fixer match(ExpressionTree tree, VisitorState state) {
410+
if (!NON_NULL_VALUE_OF.matches(tree, state)) {
411+
return null;
412+
}
413+
// TODO(cpovirk): Suggest Enums.getIfPresent, Ints.tryParse, etc.
414+
return GetterTypes::emptyFix;
415+
}
416+
},
397417
/** {@code proto.getFoo()} */
398418
SCALAR {
399419
@Nullable

core/src/test/java/com/google/errorprone/bugpatterns/ImpossibleNullComparisonTest.java

+18
Original file line numberDiff line numberDiff line change
@@ -497,4 +497,22 @@ public void primitives() {
497497
"}")
498498
.doTest();
499499
}
500+
501+
@Test
502+
public void valueOf() {
503+
compilationHelper
504+
.addSourceLines(
505+
"Test.java",
506+
"import static com.google.common.truth.Truth.assertThat;",
507+
"import java.util.concurrent.TimeUnit;",
508+
"public class Test {",
509+
" public void o(String s) {",
510+
" // BUG: Diagnostic contains:",
511+
" assertThat(TimeUnit.valueOf(s)).isNotNull();",
512+
" // BUG: Diagnostic contains:",
513+
" assertThat(Integer.valueOf(s)).isNotNull();",
514+
" }",
515+
"}")
516+
.doTest();
517+
}
500518
}

0 commit comments

Comments
 (0)