Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2014-07-14 10:40:07 +0000
committerStephan Herrmann2014-07-22 12:37:56 +0000
commit63231f253dc3aaae18caf57a7f77da85f8cefe96 (patch)
tree732498dc8eac297112c1c4960944922be823d6b9
parentb1c69f20f23ddb575225e5b5cb5d470714f41aad (diff)
downloadeclipse.jdt.core-63231f253dc3aaae18caf57a7f77da85f8cefe96.tar.gz
eclipse.jdt.core-63231f253dc3aaae18caf57a7f77da85f8cefe96.tar.xz
eclipse.jdt.core-63231f253dc3aaae18caf57a7f77da85f8cefe96.zip
Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit
type bound of binary type
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java25
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java32
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java19
5 files changed, 64 insertions, 23 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 376b52deb0..ae505e794e 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
@@ -5383,6 +5383,31 @@ public void testTypeVariable7err() {
"Null type safety (type annotations): The expression of type \'String\' needs unchecked conversion to conform to \'@NonNull String\'\n" +
"----------\n");
}
+// Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type
+public void testTypeVariable10() {
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "@org.eclipse.jdt.annotation.NonNullByDefault\n" +
+ "public class X<T> {\n" +
+ " void test(T t) {}\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+ runConformTestWithLibs(
+ false,
+ new String[] {
+ "Y.java",
+ "public class Y {\n" +
+ " void foo(X<@org.eclipse.jdt.annotation.Nullable String> xs) {\n" +
+ " xs.test(null);\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+}
public void testBug434600() {
runConformTestWithLibs(
new String[] {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
index fd8105b6b2..cac02c8e7c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
@@ -16,6 +16,7 @@ import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
/**
* A type annotation walker that adds missing NonNull annotations according to the current default.
@@ -25,6 +26,8 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke
private int defaultNullness;
private boolean atDefaultLocation;
private boolean nextIsDefaultLocation;
+ private boolean atTypeBound;
+ private boolean nextIsTypeBound;
private boolean isEmpty;
IBinaryAnnotation nonNullAnnotation;
@@ -38,24 +41,26 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke
/** Create an initial walker without 'real' type annotations, but with a nonnull default. */
public NonNullDefaultAwareTypeAnnotationWalker(int defaultNullness, LookupEnvironment environment) {
- this(defaultNullness, getNonNullAnnotation(environment), false);
+ this(defaultNullness, getNonNullAnnotation(environment), false, false);
}
/** Get restricted walker, still with non-empty type annotations. */
NonNullDefaultAwareTypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations, long newMatches, int newPathPtr,
- int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation) {
+ int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation, boolean atTypeBound) {
super(typeAnnotations, newMatches, newPathPtr);
this.defaultNullness = defaultNullness;
this.nonNullAnnotation = nonNullAnnotation;
this.atDefaultLocation = atDefaultLocation;
+ this.atTypeBound = atTypeBound;
}
/** Create a restricted walker without 'real' type annotations, but with a nonnull default. */
- NonNullDefaultAwareTypeAnnotationWalker(int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation) {
+ NonNullDefaultAwareTypeAnnotationWalker(int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation, boolean atTypeBound) {
super(null, 0, 0);
this.nonNullAnnotation = nonNullAnnotation;
this.defaultNullness = defaultNullness;
this.atDefaultLocation = atDefaultLocation;
+ this.atTypeBound = atTypeBound;
this.isEmpty = true;
}
@@ -79,16 +84,19 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke
// considers nextIsDefaultLocation as the new atDefaultLocation
try {
// do we have any change at all?
- if (this.matches == newMatches && this.pathPtr == newPathPtr && this.atDefaultLocation == this.nextIsDefaultLocation)
+ if (this.matches == newMatches && this.pathPtr == newPathPtr
+ && this.atDefaultLocation == this.nextIsDefaultLocation && this.atTypeBound == this.nextIsTypeBound)
return this;
// are we running out of real type annotations?
if (newMatches == 0 || this.typeAnnotations == null || this.typeAnnotations.length == 0)
- return new NonNullDefaultAwareTypeAnnotationWalker(this.defaultNullness, this.nonNullAnnotation, this.nextIsDefaultLocation);
+ return new NonNullDefaultAwareTypeAnnotationWalker(this.defaultNullness, this.nonNullAnnotation,
+ this.nextIsDefaultLocation, this.nextIsTypeBound);
// proceed as normal, but pass on our specific fields, too:
return new NonNullDefaultAwareTypeAnnotationWalker(this.typeAnnotations, newMatches, newPathPtr,
- this.defaultNullness, this.nonNullAnnotation, this.nextIsDefaultLocation);
+ this.defaultNullness, this.nonNullAnnotation, this.nextIsDefaultLocation, this.nextIsTypeBound);
} finally {
this.nextIsDefaultLocation = false; // expire
+ this.nextIsTypeBound = false;
}
}
@@ -109,6 +117,7 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke
@Override
public TypeAnnotationWalker toTypeBound(short boundIndex) {
this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeBound) != 0;
+ this.nextIsTypeBound = true;
if (this.isEmpty) return restrict(this.matches, this.pathPtr);
return super.toTypeBound(boundIndex);
}
@@ -116,6 +125,7 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke
@Override
public TypeAnnotationWalker toTypeParameterBounds(boolean isClassTypeParameter, int parameterRank) {
this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeBound) != 0;
+ this.nextIsTypeBound = true;
if (this.isEmpty) return restrict(this.matches, this.pathPtr);
return super.toTypeParameterBounds(isClassTypeParameter, parameterRank);
}
@@ -123,6 +133,7 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke
@Override
public TypeAnnotationWalker toTypeArgument(int rank) {
this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeArgument) != 0;
+ this.nextIsTypeBound = false;
if (this.isEmpty) return restrict(this.matches, this.pathPtr);
return super.toTypeArgument(rank);
}
@@ -130,14 +141,17 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke
@Override
public TypeAnnotationWalker toTypeParameter(boolean isClassTypeParameter, int rank) {
this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeParameter) != 0;
+ this.nextIsTypeBound = false;
if (this.isEmpty) return restrict(this.matches, this.pathPtr);
return super.toTypeParameter(isClassTypeParameter, rank);
}
@Override
- public IBinaryAnnotation[] getAnnotationsAtCursor() {
- IBinaryAnnotation[] normalAnnotations = this.isEmpty ? null : super.getAnnotationsAtCursor();
- if (this.atDefaultLocation) {
+ public IBinaryAnnotation[] getAnnotationsAtCursor(int currentTypeId) {
+ IBinaryAnnotation[] normalAnnotations = this.isEmpty ? null : super.getAnnotationsAtCursor(currentTypeId);
+ if (this.atDefaultLocation &&
+ !(this.atTypeBound && currentTypeId == TypeIds.T_JavaLangObject)) // for CLIMB-to-top consider a j.l.Object type bound as no explicit type bound
+ {
if (normalAnnotations == null || normalAnnotations.length == 0)
return new IBinaryAnnotation[] { this.nonNullAnnotation };
int len = normalAnnotations.length;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java
index 9f189b7cf4..3e525b7879 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java
@@ -41,7 +41,7 @@ public class TypeAnnotationWalker {
public TypeAnnotationWalker toTypeBound(short boundIndex) { return this; }
public TypeAnnotationWalker toTypeParameter(boolean isClassTypeParameter, int rank) { return this; }
public TypeAnnotationWalker toNextDetail(int detailKind) { return this; }
- public IBinaryAnnotation[] getAnnotationsAtCursor() { return NO_ANNOTATIONS; }
+ public IBinaryAnnotation[] getAnnotationsAtCursor(int currentTypeId) { return NO_ANNOTATIONS; }
};
final protected IBinaryTypeAnnotation[] typeAnnotations; // the actual material we're managing here
@@ -298,7 +298,7 @@ public class TypeAnnotationWalker {
* Retrieve the type annotations at the current position
* reached by invocations of toXYZ() methods.
*/
- public IBinaryAnnotation[] getAnnotationsAtCursor() {
+ public IBinaryAnnotation[] getAnnotationsAtCursor(int currentTypeId) {
int length = this.typeAnnotations.length;
IBinaryAnnotation[] filtered = new IBinaryAnnotation[length];
long ptr = 1;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index bfe7fcb74d..b6ed2c8c94 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -27,6 +27,7 @@
* Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Bug 390889 - [1.8][compiler] Evaluate options to support 1.7- projects against 1.8 JRE.
* Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
+ * Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type
* Jesper Steen Moller - Contributions for
* Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing
* Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
@@ -744,7 +745,7 @@ private MethodBinding createMethod(IBinaryMethod method, long sourceLevel, char[
? new MethodBinding(methodModifiers, parameters, exceptions, this)
: new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this);
- IBinaryAnnotation[] receiverAnnotations = walker.toReceiver().getAnnotationsAtCursor();
+ IBinaryAnnotation[] receiverAnnotations = walker.toReceiver().getAnnotationsAtCursor(0);
if (receiverAnnotations != null && receiverAnnotations.length > 0) {
result.receiver = this.environment.createAnnotatedType(this, createAnnotations(receiverAnnotations, this.environment, missingTypeNames));
}
@@ -753,7 +754,7 @@ private MethodBinding createMethod(IBinaryMethod method, long sourceLevel, char[
IBinaryAnnotation[] annotations = method.getAnnotations();
if (annotations == null || annotations.length == 0)
if (method.isConstructor())
- annotations = walker.toMethodReturn().getAnnotationsAtCursor(); // FIXME: When both exist, order could become an issue.
+ annotations = walker.toMethodReturn().getAnnotationsAtCursor(0); // FIXME: When both exist, order could become an issue.
result.setAnnotations(
createAnnotations(annotations, this.environment, missingTypeNames),
paramAnnotations,
@@ -865,7 +866,7 @@ private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, bool
int colon = CharOperation.indexOf(Util.C_COLON, typeSignature, i);
char[] variableName = CharOperation.subarray(typeSignature, i, colon);
TypeVariableBinding typeVariable = new TypeVariableBinding(variableName, this, rank, this.environment);
- AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.toTypeParameter(isClassTypeParameter, rank++).getAnnotationsAtCursor(),
+ AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.toTypeParameter(isClassTypeParameter, rank++).getAnnotationsAtCursor(0),
this.environment, missingTypeNames);
if (annotations != null && annotations != Binding.NO_ANNOTATIONS)
typeVariable.setTypeAnnotations(annotations, this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index a2420003ea..5fe450c9c5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -25,6 +25,7 @@
* Bug 416190 - [1.8][null] detect incompatible overrides due to null type annotations
* Bug 424624 - [1.8][null] if a static-object with annotation @NonNull is used, a warning is shown
* Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
+ * Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -1257,7 +1258,7 @@ TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean i
AnnotationBinding [][] annotationsOnDimensions = null;
if (dimension > 0 && walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
for (int i = 0; i < dimension; i++) {
- AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames);
if (annotations != Binding.NO_ANNOTATIONS) {
if (annotationsOnDimensions == null)
annotationsOnDimensions = new AnnotationBinding[dimension][];
@@ -1342,7 +1343,7 @@ private TypeBinding annotateType(TypeBinding binding, TypeAnnotationWalker walke
}
AnnotationBinding [][] annotations = null;
for (int i = 0; i < depth; i++) {
- AnnotationBinding[] annots = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ AnnotationBinding[] annots = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(binding.id), this, missingTypeNames);
if (annots != null && annots.length > 0) {
if (annotations == null)
annotations = new AnnotationBinding[depth][];
@@ -1387,7 +1388,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab
AnnotationBinding [][] annotationsOnDimensions = null;
if (dimension > 0 && walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
for (int i = 0; i < dimension; i++) {
- AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames);
if (annotations != Binding.NO_ANNOTATIONS) {
if (annotationsOnDimensions == null)
annotationsOnDimensions = new AnnotationBinding[dimension][];
@@ -1432,7 +1433,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab
if (actualEnclosing != null) { // convert needed if read some static member type
actualEnclosing = (ReferenceBinding) convertToRawType(actualEnclosing, false /*do not force conversion of enclosing types*/);
}
- AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(actualType.id), this, missingTypeNames);
TypeBinding[] typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, actualType, missingTypeNames, walker);
ParameterizedTypeBinding parameterizedType = createParameterizedType(actualType, typeArguments, actualEnclosing, annotations);
@@ -1446,7 +1447,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab
if (memberType == null)
this.problemReporter.corruptedSignature(parameterizedType, wrapper.signature, memberStart); // aborts
walker = walker.toNextNestedType();
- annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(memberType.id), this, missingTypeNames);
if (wrapper.signature[wrapper.start] == '<') {
wrapper.start++; // skip '<'
typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, memberType, missingTypeNames, walker);
@@ -1460,7 +1461,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab
}
private TypeBinding getTypeFromTypeVariable(TypeVariableBinding typeVariableBinding, int dimension, AnnotationBinding [][] annotationsOnDimensions, TypeAnnotationWalker walker, char [][][] missingTypeNames) {
- AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames);
if (annotations != null && annotations != Binding.NO_ANNOTATIONS)
typeVariableBinding = (TypeVariableBinding) createAnnotatedType(typeVariableBinding, new AnnotationBinding [][] { annotations });
@@ -1487,18 +1488,18 @@ TypeBinding getTypeFromVariantTypeSignature(
// ? super aType
wrapper.start++;
TypeBinding bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames, walker.toWildcardBound());
- AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames);
return this.typeSystem.getWildcard(genericType, rank, bound, null /*no extra bound*/, Wildcard.SUPER, annotations);
case '+' :
// ? extends aType
wrapper.start++;
bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames, walker.toWildcardBound());
- annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames);
return this.typeSystem.getWildcard(genericType, rank, bound, null /*no extra bound*/, Wildcard.EXTENDS, annotations);
case '*' :
// ?
wrapper.start++;
- annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames);
return this.typeSystem.getWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND, annotations);
default :
return getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames, walker);

Back to the top