Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java')
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java117
1 files changed, 79 insertions, 38 deletions
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 1648cff86..4af69a35d 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
@@ -15,6 +15,7 @@
* bug 364890 - BinaryTypeBinding should use char constants from Util
* bug 365387 - [compiler][null] bug 186342: Issues to follow up post review and verification.
* bug 358903 - Filter practically unimportant resource leak warnings
+ * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -552,6 +553,11 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
}
}
+ // need type annotations before processing methods (for @NonNullByDefault)
+ if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+ scanTypeForNullDefaultAnnotation(binaryType);
+ }
+
if (needFieldsAndMethods) {
createFields(binaryType.getFields(), sourceLevel, missingTypeNames);
createMethods(binaryType.getMethods(), sourceLevel, missingTypeNames);
@@ -581,14 +587,6 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
// SH}
if (this.environment.globalOptions.storeAnnotations)
setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));
-
- if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled
- && CharOperation.equals(TypeConstants.PACKAGE_INFO_NAME, binaryType.getSourceName()))
- {
- // only for package-info.java can type-level null-annotations (i.e., @NonNullByDefault)
- // on a binary type influence the compilation
- scanPackageInfoForNullDefaultAnnotation(binaryType);
- }
} finally {
// protect against incorrect use of the needFieldsAndMethods flag, see 48459
if (this.fields == null)
@@ -1586,65 +1584,93 @@ void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBindi
return;
char[][] nullableAnnotationName = this.environment.getNullableAnnotationName();
char[][] nonNullAnnotationName = this.environment.getNonNullAnnotationName();
- if (nullableAnnotationName == null || nonNullAnnotationName == null)
+ char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName();
+ if (nullableAnnotationName == null || nonNullAnnotationName == null || nonNullByDefaultAnnotationName == null)
return; // not well-configured to use null annotations
+ int currentDefault = NO_NULL_DEFAULT;
+ if ((this.tagBits & TagBits.AnnotationNonNullByDefault) != 0) {
+ currentDefault = NONNULL_BY_DEFAULT;
+ } else if ((this.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0) {
+ currentDefault = NULL_UNSPECIFIED_BY_DEFAULT;
+ }
+
// return:
IBinaryAnnotation[] annotations = method.getAnnotations();
+ boolean explicitNullness = false;
if (annotations != null) {
for (int i = 0; i < annotations.length; i++) {
char[] annotationTypeName = annotations[i].getTypeName();
if (annotationTypeName[0] != Util.C_RESOLVED)
continue;
char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
- if (CharOperation.equals(typeName, nonNullAnnotationName)) {
+ if (CharOperation.equals(typeName, nonNullByDefaultAnnotationName)) {
+ methodBinding.tagBits |= TagBits.AnnotationNonNullByDefault;
+ currentDefault = NONNULL_BY_DEFAULT;
+ }
+ if (!explicitNullness && CharOperation.equals(typeName, nonNullAnnotationName)) {
methodBinding.tagBits |= TagBits.AnnotationNonNull;
- break;
+ explicitNullness = true;
}
- if (CharOperation.equals(typeName, nullableAnnotationName)) {
+ if (!explicitNullness && CharOperation.equals(typeName, nullableAnnotationName)) {
methodBinding.tagBits |= TagBits.AnnotationNullable;
- break;
+ explicitNullness = true;
}
}
}
+ if (!explicitNullness && currentDefault == NONNULL_BY_DEFAULT) {
+ methodBinding.tagBits |= TagBits.AnnotationNonNull;
+ }
// parameters:
TypeBinding[] parameters = methodBinding.parameters;
int numVisibleParams = parameters.length;
int numParamAnnotations = method.getAnnotatedParametersCount();
- if (numParamAnnotations > 0) {
- int startIndex = numParamAnnotations - numVisibleParams;
+ if (numParamAnnotations > 0 || currentDefault == NONNULL_BY_DEFAULT) {
for (int j = 0; j < numVisibleParams; j++) {
- IBinaryAnnotation[] paramAnnotations = method.getParameterAnnotations(j+startIndex);
- if (paramAnnotations != null) {
- for (int i = 0; i < paramAnnotations.length; i++) {
- char[] annotationTypeName = paramAnnotations[i].getTypeName();
- if (annotationTypeName[0] != Util.C_RESOLVED)
- continue;
- char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
- if (CharOperation.equals(typeName, nonNullAnnotationName)) {
- if (methodBinding.parameterNonNullness == null)
- methodBinding.parameterNonNullness = new Boolean[numVisibleParams];
- methodBinding.parameterNonNullness[j] = Boolean.TRUE;
- break;
- } else if (CharOperation.equals(typeName, nullableAnnotationName)) {
- if (methodBinding.parameterNonNullness == null)
- methodBinding.parameterNonNullness = new Boolean[numVisibleParams];
- methodBinding.parameterNonNullness[j] = Boolean.FALSE;
- break;
+ explicitNullness = false;
+ if (numParamAnnotations > 0) {
+ int startIndex = numParamAnnotations - numVisibleParams;
+ IBinaryAnnotation[] paramAnnotations = method.getParameterAnnotations(j+startIndex);
+ if (paramAnnotations != null) {
+ for (int i = 0; i < paramAnnotations.length; i++) {
+ char[] annotationTypeName = paramAnnotations[i].getTypeName();
+ if (annotationTypeName[0] != Util.C_RESOLVED)
+ continue;
+ char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
+ if (CharOperation.equals(typeName, nonNullAnnotationName)) {
+ if (methodBinding.parameterNonNullness == null)
+ methodBinding.parameterNonNullness = new Boolean[numVisibleParams];
+ methodBinding.parameterNonNullness[j] = Boolean.TRUE;
+ explicitNullness = true;
+ break;
+ } else if (CharOperation.equals(typeName, nullableAnnotationName)) {
+ if (methodBinding.parameterNonNullness == null)
+ methodBinding.parameterNonNullness = new Boolean[numVisibleParams];
+ methodBinding.parameterNonNullness[j] = Boolean.FALSE;
+ explicitNullness = true;
+ break;
+ }
}
}
}
+ if (!explicitNullness && currentDefault == NONNULL_BY_DEFAULT) {
+ if (methodBinding.parameterNonNullness == null)
+ methodBinding.parameterNonNullness = new Boolean[numVisibleParams];
+ methodBinding.parameterNonNullness[j] = Boolean.TRUE;
+ }
}
}
}
-void scanPackageInfoForNullDefaultAnnotation(IBinaryType binaryType) {
+void scanTypeForNullDefaultAnnotation(IBinaryType binaryType) {
char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName();
if (nonNullByDefaultAnnotationName == null)
return; // not well-configured to use null annotations
IBinaryAnnotation[] annotations = binaryType.getAnnotations();
if (annotations != null) {
+ long annotationBit = 0L;
+ int nullness = NO_NULL_DEFAULT;
int length = annotations.length;
for (int i = 0; i < length; i++) {
char[] annotationTypeName = annotations[i].getTypeName();
@@ -1659,13 +1685,28 @@ void scanPackageInfoForNullDefaultAnnotation(IBinaryType binaryType) {
&& !((BooleanConstant)value).booleanValue())
{
// parameter is 'false': this means we cancel defaults from outer scopes:
- this.getPackage().nullnessDefaultAnnotation = ReferenceBinding.NULL_UNSPECIFIED;
- return;
+ annotationBit = TagBits.AnnotationNullUnspecifiedByDefault;
+ nullness = NULL_UNSPECIFIED_BY_DEFAULT;
+ break;
}
}
- this.getPackage().nullnessDefaultAnnotation =
- this.environment.getNullAnnotationBinding(TagBits.AnnotationNonNull, false/*resolve*/);
- return;
+ annotationBit = TagBits.AnnotationNonNullByDefault;
+ nullness = NONNULL_BY_DEFAULT;
+ break;
+ }
+ }
+ if (annotationBit != 0L) {
+ this.tagBits |= annotationBit;
+ if (CharOperation.equals(this.sourceName(), TypeConstants.PACKAGE_INFO_NAME))
+ this.getPackage().defaultNullness = nullness;
+ } else {
+ switch (this.getPackage().defaultNullness) {
+ case NONNULL_BY_DEFAULT :
+ this.tagBits |= TagBits.AnnotationNonNullByDefault;
+ break;
+ case NULL_UNSPECIFIED_BY_DEFAULT :
+ this.tagBits |= TagBits.AnnotationNullUnspecifiedByDefault;
+ break;
}
}
}

Back to the top