Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type
annotations
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 cd44512..4f93557 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
@@ -767,8 +767,8 @@
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=403216#c9
- public void testBug403216_3() {
- runConformTestWithLibs(
+ public void testBug403216_3a() {
+ runNegativeTestWithLibs(
new String[] {
"Test.java",
"import java.lang.annotation.ElementType;\n" +
@@ -786,6 +786,33 @@
"@interface A {}\n"
},
getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in Test.java (at line 9)\n" +
+ " public void foo( @A X. @NonNull Y this) {}\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "Nullness annotations are not applicable at this location \n" +
+ "----------\n");
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=403216#c9
+ public void testBug403216_3b() {
+ runConformTestWithLibs(
+ new String[] {
+ "Test.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "public class Test {}\n" +
+ "\n" +
+ "class X {\n" +
+ " class Y {\n" +
+ " public void foo( @A X. @A Y this) {}\n" +
+ " }\n" +
+ "}\n" +
+ "@Target(value={ElementType.TYPE_USE})\n" +
+ "@interface A {}\n"
+ },
+ getCompilerOptions(),
"");
}
@@ -2138,7 +2165,7 @@
"----------\n");
}
- // illegal for cast & instanceof with scalar type
+ // illegal / unchecked for cast & instanceof with scalar type
public void testUnsupportedLocation03() {
runNegativeTestWithLibs(
new String[] {
@@ -2170,7 +2197,7 @@
"----------\n");
}
- // illegal for cast & instanceof with complex type
+ // illegal / unchecked for cast & instanceof with complex type
public void testUnsupportedLocation04() {
runNegativeTestWithLibs(
new String[] {
@@ -2235,6 +2262,27 @@
"----------\n");
}
+ // illegal instanceof check with annotated type argument
+ public void testUnsupportedLocation04a() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import java.util.*;\n" +
+ "public class X {\n" +
+ " boolean instanceOf2(Object o) {\n" +
+ " return o instanceof List<@Nullable ?>;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " return o instanceof List<@Nullable ?>;\n" +
+ " ^^^^^^^^^^^^^^^^^\n" +
+ "Nullness annotations are not applicable at this location \n" +
+ "----------\n");
+ }
+
// illegal for allocation expression
public void testUnsupportedLocation05() {
runNegativeTestWithLibs(
@@ -2261,6 +2309,82 @@
"----------\n");
}
+ // method receiver
+ public void testUnsupportedLocation06() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " void receiver(@Nullable X this, Object o) {}\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " void receiver(@Nullable X this, Object o) {}\n" +
+ " ^^^^^^^^^^^\n" +
+ "Nullness annotations are not applicable at this location \n" +
+ "----------\n");
+ }
+
+ // receiver type in method/constructor reference
+ public void testUnsupportedLocation07() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import java.util.function.Supplier;\n" +
+ "public class X {\n" +
+ " void consume(Supplier<Object> c) {}\n" +
+ " static Object supply() { return null; }\n" +
+ " void consumeSupplied() {\n" +
+ " consume(@NonNull X::supply);\n" +
+ " consume(@NonNull X::new);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " consume(@NonNull X::supply);\n" +
+ " ^^^^^^^^^^\n" +
+ "Nullness annotations are not applicable at this location \n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " consume(@NonNull X::new);\n" +
+ " ^^^^^^^^^^\n" +
+ "Nullness annotations are not applicable at this location \n" +
+ "----------\n");
+ }
+
+ // exceptions (throws & catch)
+ public void testUnsupportedLocation08() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "import java.io.*;\n" +
+ "public class X {\n" +
+ " void throwsDecl() throws @Nullable IOException {}\n" +
+ " void excParam() {\n" +
+ " try {\n" +
+ " throwsDecl();\n" +
+ " } catch (@NonNull IOException ioe) {}\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " void throwsDecl() throws @Nullable IOException {}\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Nullness annotations are not applicable at this location \n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 8)\n" +
+ " } catch (@NonNull IOException ioe) {}\n" +
+ " ^^^^^^^^^^^\n" +
+ "Nullness annotations are not applicable at this location \n" +
+ "----------\n");
+ }
+
public void testForeach() {
runNegativeTestWithLibs(
new String[] {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index 25326f7..186893e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -24,6 +24,7 @@
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Bug 403216 - [1.8][null] TypeReference#captureTypeAnnotations treats type annotations as type argument annotations
* Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
+ * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -587,6 +588,10 @@
if (TypeBinding.notEquals(enclosingReceiver, resolvedReceiverType)) {
this.scope.problemReporter().illegalTypeForExplicitThis(this.receiver, enclosingReceiver);
}
+
+ if (resolvedReceiverType.hasNullTypeAnnotations()) {
+ this.scope.problemReporter().nullAnnotationUnsupportedLocation(this.receiver.type);
+ }
}
public void resolveJavadoc() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
index b46a2c4..e5567a4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -15,6 +15,7 @@
* bug 186342 - [compiler][null] Using annotations for null checking
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
* Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
+ * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 409246 - [1.8][compiler] Type annotations on catch parameters not handled properly
*******************************************************************************/
@@ -199,6 +200,9 @@
}
resolveAnnotations(scope, this.annotations, this.binding, true);
Annotation.isTypeUseCompatible(this.type, scope, this.annotations);
+ if (this.type.resolvedType != null && this.type.resolvedType.hasNullTypeAnnotations()) {
+ scope.problemReporter().nullAnnotationUnsupportedLocation(this.type);
+ }
scope.addLocalVariable(this.binding);
this.binding.setConstant(Constant.NotAConstant);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index 5f84c19..405e53f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -17,6 +17,7 @@
* Bug 416307 - [1.8][compiler][null] subclass with type parameter substitution confuses null checking
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
+ * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Andy Clement - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
*******************************************************************************/
@@ -92,8 +93,10 @@
this.constant = Constant.NotAConstant;
TypeBinding expressionType = this.expression.resolveType(scope);
TypeBinding checkedType = this.type.resolveType(scope, true /* check bounds*/);
- if (expressionType != null && checkedType != null && NullAnnotationMatching.analyse(checkedType, expressionType, -1).isAnyMismatch()) {
- scope.problemReporter().nullAnnotationUnsupportedLocation(this.type);
+ if (expressionType != null && checkedType != null && checkedType.hasNullTypeAnnotations()) {
+ // don't complain if the entire operation is redundant anyway
+ if (!expressionType.isCompatibleWith(checkedType) || NullAnnotationMatching.analyse(checkedType, expressionType, -1).isAnyMismatch())
+ scope.problemReporter().nullAnnotationUnsupportedLocation(this.type);
}
if (expressionType == null || checkedType == null)
return null;
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 de28ffa..d1c6a56 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
@@ -28,6 +28,7 @@
* Bug 427196 - [1.8][compiler] Compiler error for method reference to overloaded method
* Bug 427438 - [1.8][compiler] NPE at org.eclipse.jdt.internal.compiler.ast.ConditionalExpression.generateCode(ConditionalExpression.java:280)
* Bug 428264 - [1.8] method reference of generic class causes problems (wrong inference result or NPE)
+ * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contribution for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
*******************************************************************************/
@@ -388,6 +389,10 @@
return this.resolvedType = null;
}
+ if (this.lhs instanceof TypeReference && lhsType.hasNullTypeAnnotations()) {
+ scope.problemReporter().nullAnnotationUnsupportedLocation((TypeReference) this.lhs);
+ }
+
/* 15.28: "It is a compile-time error if a method reference of the form super :: NonWildTypeArgumentsopt Identifier or of the form
TypeName . super :: NonWildTypeArgumentsopt Identifier occurs in a static context.": This is nop since the primary when it resolves
itself will complain automatically.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index fb6b282..83be251 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -33,6 +33,7 @@
* Bug 416172 - [1.8][compiler][null] null type annotation not evaluated on method return type
* Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Bug 426048 - [1.8] NPE in TypeVariableBinding.internalBoundCheck when parentheses are not balanced
+ * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
* Till Brychcy - Contributions for
@@ -1815,6 +1816,9 @@
if ((resolvedExceptionType.tagBits & TagBits.HasMissingType) != 0) {
method.tagBits |= TagBits.HasMissingType;
}
+ if (resolvedExceptionType.hasNullTypeAnnotations()) {
+ methodDecl.scope.problemReporter().nullAnnotationUnsupportedLocation(exceptionTypes[i]);
+ }
method.modifiers |= (resolvedExceptionType.modifiers & ExtraCompilerModifiers.AccGenericSignature);
method.thrownExceptions[count++] = resolvedExceptionType;
}