Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2015-11-19 17:43:13 +0000
committerStephan Herrmann2015-11-19 18:26:50 +0000
commit48aaa503eb58e270f9afd7df4a85cb65e562a44f (patch)
tree098cb4c2754541078f6106cd29fb7026877ae3b7
parent5499d7ab628f0d031c84d349d565b52915f502cb (diff)
downloadeclipse.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
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java33
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java21
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)) {

Back to the top