Bug 513495 - [null][1.8] Missing warning if method reference maps
@Nullable first arg to receiver
Change-Id: Ie343dcef76136342173e6016a87e6871ba174a84
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
index d327440..4b4bae1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
@@ -15108,4 +15108,36 @@
"----------\n"
);
}
+public void testBug513495() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "test/Test3.java",
+ "package test;\n" +
+ "\n" +
+ "import java.util.function.Function;\n" +
+ "\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "public class Test3 {\n" +
+ " public static void main(String[] args) {\n" +
+ " Function<@Nullable Integer, Object> sam = Integer::intValue;\n" +
+ " sam.apply(null); // <- NullPointerExpection\n" +
+ " Function<Integer, Object> sam2 = Integer::intValue;\n" +
+ " sam2.apply(null); // variation: unchecked, so intentionally no warning reported, but would give NPE too \n" +
+ " }\n" +
+ " void wildcards(Class<?>[] params) { // unchecked case with wildcards\n" +
+ " java.util.Arrays.stream(params).map(Class::getName).toArray(String[]::new);\n" +
+ " }\n" +
+ "}\n" +
+ "",
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in test\\Test3.java (at line 9)\n" +
+ " Function<@Nullable Integer, Object> sam = Integer::intValue;\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Null type mismatch at parameter 'this': required \'@NonNull Integer\' but provided \'@Nullable Integer\' via method descriptor Function<Integer,Object>.apply(Integer)\n" +
+ "----------\n"
+ );
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
index 7627374..4a7a5cf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
@@ -797,8 +797,16 @@
int len;
int expectedlen = this.binding.parameters.length;
int providedLen = this.descriptor.parameters.length;
- if (this.receiverPrecedesParameters)
+ if (this.receiverPrecedesParameters) {
providedLen--; // one parameter is 'consumed' as the receiver
+
+ TypeBinding descriptorParameter = this.descriptor.parameters[0];
+ if((descriptorParameter.tagBits & TagBits.AnnotationNullable) != 0) { // Note: normal dereferencing of 'unchecked' values is not reported, either
+ final TypeBinding receiver = scope.environment().createAnnotatedType(this.binding.declaringClass,
+ new AnnotationBinding[] { scope.environment().getNonNullAnnotation() });
+ scope.problemReporter().referenceExpressionArgumentNullityMismatch(this, receiver, descriptorParameter, this.descriptor, -1, NullAnnotationMatching.NULL_ANNOTATIONS_MISMATCH);
+ }
+ }
boolean isVarArgs = false;
if (this.binding.isVarargs()) {
isVarArgs = (providedLen == expectedlen)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 5d40ddf..0dc2f7d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -9592,11 +9592,11 @@
.append(descriptorMethod.shortReadableName());
this.handle(
status.isUnchecked() ? IProblem.ReferenceExpressionParameterNullityUnchecked : IProblem.ReferenceExpressionParameterNullityMismatch,
- new String[] { String.valueOf(idx+1),
+ new String[] { idx == -1 ? "'this'" : String.valueOf(idx + 1), //$NON-NLS-1$
String.valueOf(requiredType.nullAnnotatedReadableName(this.options, false)),
String.valueOf(providedType.nullAnnotatedReadableName(this.options, false)),
methodSignature.toString() },
- new String[] { String.valueOf(idx+1),
+ new String[] { idx == -1 ? "'this'" : String.valueOf(idx + 1), //$NON-NLS-1$
String.valueOf(requiredType.nullAnnotatedReadableName(this.options, true)),
String.valueOf(providedType.nullAnnotatedReadableName(this.options, true)),
shortSignature.toString() },