From 348bb4d997d04b3f86fe6ac629e056c52bfbbb27 Mon Sep 17 00:00:00 2001 From: Manu Sridharan Date: Mon, 4 Mar 2024 09:09:27 -0800 Subject: [PATCH] Fix handling of references to methods of array types and type variables (#926) After #920 we check the nullability of the qualifier expression of a method reference. We weren't correctly handling the cases where that expression was an array type or a type variable --- .../src/main/java/com/uber/nullaway/NullAway.java | 5 +++-- .../java/com/uber/nullaway/NullAwayJava8Tests.java | 11 ++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/nullaway/src/main/java/com/uber/nullaway/NullAway.java b/nullaway/src/main/java/com/uber/nullaway/NullAway.java index 1f67a4a0c0..12e7370d92 100644 --- a/nullaway/src/main/java/com/uber/nullaway/NullAway.java +++ b/nullaway/src/main/java/com/uber/nullaway/NullAway.java @@ -2326,7 +2326,7 @@ private boolean mayBeNullExpr(VisitorState state, ExpressionTree expr) { return true; case NEW_CLASS: case NEW_ARRAY: - // for string concatenation, auto-boxing + case ARRAY_TYPE: case LAMBDA_EXPRESSION: // Lambdas may return null, but the lambda literal itself should not be null case MEMBER_REFERENCE: @@ -2485,7 +2485,8 @@ private Description matchDereference( if (baseExpressionSymbol != null) { if (baseExpressionSymbol.type.isPrimitive() || baseExpressionSymbol.getKind() == ElementKind.PACKAGE - || ElementUtils.isTypeElement(baseExpressionSymbol)) { + || ElementUtils.isTypeElement(baseExpressionSymbol) + || baseExpressionSymbol.getKind() == ElementKind.TYPE_PARAMETER) { // we know we don't have a null dereference here return Description.NO_MATCH; } diff --git a/nullaway/src/test/java/com/uber/nullaway/NullAwayJava8Tests.java b/nullaway/src/test/java/com/uber/nullaway/NullAwayJava8Tests.java index 6c37861534..72fe2a36e7 100644 --- a/nullaway/src/test/java/com/uber/nullaway/NullAwayJava8Tests.java +++ b/nullaway/src/test/java/com/uber/nullaway/NullAwayJava8Tests.java @@ -30,11 +30,20 @@ public void methodReferenceOnNullableVariable() { "Test.java", "package com.uber;", "import org.jspecify.annotations.Nullable;", + "import java.util.Arrays;", + "import java.util.stream.Collectors;", "class Test {", - " public static boolean test(@Nullable String text, java.util.Set s) {", + " public static boolean testPositive(@Nullable String text, java.util.Set s) {", " // BUG: Diagnostic contains: dereferenced expression text is @Nullable", " return s.stream().anyMatch(text::contains);", " }", + " public static String[] testNegative(Object[] arr) {", + " // also tests we don't crash when the qualifier expression of a method reference is a type", + " return Arrays.stream(arr).map(Object::toString).toArray(String[]::new);", + " }", + " public static boolean testNegativeWithTypeVariable(T[] arr) {", + " return Arrays.stream(arr).map(T::toString).collect(Collectors.toList()).isEmpty();", + " }", "}") .doTest(); }