diff options
author | Stephan Herrmann | 2015-11-19 17:43:13 +0000 |
---|---|---|
committer | Stephan Herrmann | 2015-11-19 18:26:50 +0000 |
commit | 48aaa503eb58e270f9afd7df4a85cb65e562a44f (patch) | |
tree | 098cb4c2754541078f6106cd29fb7026877ae3b7 | |
parent | 5499d7ab628f0d031c84d349d565b52915f502cb (diff) | |
download | eclipse.jdt.core-48aaa503eb58e270f9afd7df4a85cb65e562a44f.tar.gz eclipse.jdt.core-48aaa503eb58e270f9afd7df4a85cb65e562a44f.tar.xz eclipse.jdt.core-48aaa503eb58e270f9afd7df4a85cb65e562a44f.zip |
Bug 482247 - [compiler][null] Empty arrays should satisfy @NonNull
Type[]
Change-Id: Ic595dc7a2ebae034ab47ffeca13a70efe8872f4c
2 files changed, 54 insertions, 0 deletions
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 306882eb70..81fab6e8ab 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 @@ -8664,4 +8664,37 @@ public void testBug477719() { getCompilerOptions(),
"");
}
+public void testBug482247() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class X {\n" +
+ " @NonNull String @NonNull[] s1 = new String[0];\n" + // expected type drives typing
+ " @Nullable String @NonNull[] s2 = new String[0];\n" + // expected type drives typing
+ " <T> @NonNull T first(@NonNull T @NonNull[] arr) {\n" +
+ " return arr[0];\n" +
+ " }\n" +
+ " void other(@Nullable String[] s) {\n" +
+ " s[0] = null;\n" +
+ " }\n" +
+ " @NonNull String test() {\n" +
+ " other(new String[0]);\n" + // unchanged semantics
+ " return first(new String[0]);\n" + // unchanged semantics
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. WARNING in X.java (at line 12)\n" +
+ " other(new String[0]);\n" +
+ " ^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@Nullable String []\'\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 13)\n" +
+ " return first(new String[0]);\n" +
+ " ^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@NonNull String @NonNull[]\'\n" +
+ "----------\n");
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java index 656c770570..30619107f4 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java @@ -39,6 +39,8 @@ public class ArrayAllocationExpression extends Expression { public Annotation [][] annotationsOnDimensions; // jsr308 style annotations. public ArrayInitializer initializer; + private TypeBinding expectedType; + public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { for (int i = 0, max = this.dimensions.length; i < max; i++) { Expression dim; @@ -175,6 +177,21 @@ public class ArrayAllocationExpression extends Expression { { scope.problemReporter().contradictoryNullAnnotations(this.type.annotations[this.type.annotations.length-1]); } + LookupEnvironment environment = scope.environment(); + if (environment.usesNullTypeAnnotations() + && this.annotationsOnDimensions == null // don't annotate if explicit annotations are given on dimensions ... + && ((referenceType.tagBits & TagBits.AnnotationNullMASK) == 0) // ... or leaf type + && this.expectedType != null) // need this to determine our action + { + Expression lastDim = this.dimensions[this.dimensions.length-1]; + if (lastDim instanceof IntLiteral && ((IntLiteral) lastDim).value == 0) { + long tagBit = this.expectedType.leafComponentType().tagBits & TagBits.AnnotationNullMASK; + // let new X[0] be seen as "@NonNull X[]", or "@Nullable X[]" just as expected + AnnotationBinding[] nullAnnotations = environment.nullAnnotationsFromTagBits(tagBit); + if (nullAnnotations != null) + referenceType = environment.createAnnotatedType(referenceType, nullAnnotations); + } + } this.resolvedType = scope.createArrayType(referenceType, this.dimensions.length); if (this.annotationsOnDimensions != null) { @@ -202,6 +219,10 @@ public class ArrayAllocationExpression extends Expression { return this.resolvedType; } + @Override + public void setExpectedType(TypeBinding expectedType) { + this.expectedType = expectedType; + } public void traverse(ASTVisitor visitor, BlockScope scope) { if (visitor.visit(this, scope)) { |