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() },