Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup')
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java117
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java19
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java56
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java104
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java4
11 files changed, 150 insertions, 205 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;
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
index ea41433e6..f4c04c2ff 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
@@ -10,6 +10,8 @@
* IBM Corporation - initial API and implementation
* Fraunhofer FIRST - extended API and implementation
* Technical University Berlin - extended API and implementation
+ * Stephan Herrmann - Contribution for
+ * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -68,6 +70,11 @@ public abstract class Binding {
public static final MethodBinding[] UNINITIALIZED_METHODS = new MethodBinding[0];
public static final ReferenceBinding[] UNINITIALIZED_REFERENCE_TYPES = new ReferenceBinding[0];
+ // Nullness defaults:
+ public static final int NO_NULL_DEFAULT = 0;
+ public static final int NULL_UNSPECIFIED_BY_DEFAULT = 1;
+ public static final int NONNULL_BY_DEFAULT = 2;
+
/*
* Answer the receiver's binding type from Binding.BindingID.
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index ba128f166..5df6a31d1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -14,6 +14,8 @@
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 359334 - Analysis for resource leak warnings does not consider exceptions as method exit points
* bug 358903 - Filter practically unimportant resource leak warnings
+ * bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
+ * bug 370639 - [compiler][resource] restore the default for resource leak warnings
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -28,6 +30,7 @@ import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.WrapperKind;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
@@ -1156,11 +1159,12 @@ public void pruneWrapperTrackingVar(FakedTrackingVariable trackingVariable) {
* At the end of a block check the closing-status of all tracked closeables that are declared in this block.
* Also invoked when entering unreachable code.
*/
-public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location, BlockScope locationScope) {
+public void checkUnclosedCloseables(FlowInfo flowInfo, FlowContext flowContext, ASTNode location, BlockScope locationScope) {
+ if (!compilerOptions().analyseResourceLeaks) return;
if (this.trackingVariables == null) {
// at a method return we also consider enclosing scopes
if (location != null && this.parent instanceof BlockScope)
- ((BlockScope) this.parent).checkUnclosedCloseables(flowInfo, location, locationScope);
+ ((BlockScope) this.parent).checkUnclosedCloseables(flowInfo, flowContext, location, locationScope);
return;
}
if (location != null && flowInfo.reachMode() != 0) return;
@@ -1177,9 +1181,14 @@ public void checkUnclosedCloseables(FlowInfo flowInfo, ASTNode location, BlockSc
continue;
}
- if (location != null && trackingVar.originalBinding != null && flowInfo.isDefinitelyNull(trackingVar.originalBinding))
- continue; // reporting against a specific location, resource is null at this flow, don't complain
-
+ if (location != null && trackingVar.hasDefinitelyNoResource(flowInfo)) {
+ continue; // reporting against a specific location, there is no resource at this flow, don't complain
+ }
+
+ if (location != null && flowContext != null && flowContext.recordExitAgainstResource(this, flowInfo, trackingVar, location)) {
+ continue; // handled by the flow context
+ }
+
// compute the most specific null status for this resource,
int status = trackingVar.findMostSpecificStatus(flowInfo, this, locationScope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index b82025b21..f8ec700ab 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -139,6 +139,7 @@ public class ClassScope extends Scope {
public TypeDeclaration referenceContext;
public TypeReference superTypeReference;
java.util.ArrayList deferredBoundChecks;
+
public ClassScope(Scope parent, TypeDeclaration context) {
super(Scope.CLASS_SCOPE, parent);
this.referenceContext = context;
@@ -179,7 +180,6 @@ public class ClassScope extends Scope {
}
}
}
- this.referenceContext.binding.cumulativeFieldCount += outerMostMethodScope().analysisIndex;
connectMemberTypes();
buildFieldsAndMethods();
//{ObjectTeams: catchup also in OT-specific process (see class comment concerning local types in Dependencies):
@@ -271,7 +271,6 @@ public class ClassScope extends Scope {
// remove duplicate fields
if (count != fieldBindings.length)
System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
- sourceType.cumulativeFieldCount += count;
sourceType.tagBits &= ~(TagBits.AreFieldsSorted|TagBits.AreFieldsComplete); // in case some static imports reached already into this type
sourceType.setFields(fieldBindings);
}
@@ -412,7 +411,6 @@ public class ClassScope extends Scope {
checkParameterizedTypeBounds();
checkParameterizedSuperTypeCollisions();
}
- this.referenceContext.binding.cumulativeFieldCount += outerMostMethodScope().analysisIndex;
buildFieldsAndMethods();
//{ObjectTeams: catchup also in OT-specific process (see class comment concerning local types in Dependencies).
if (this.referenceContext.isRole()) {
@@ -842,8 +840,6 @@ public class ClassScope extends Scope {
fieldDeclaration, null, fieldDeclaration.modifiers|ExtraCompilerModifiers.AccUnresolved, sourceType);
sourceType.addField(fieldBinding);
- sourceType.cumulativeFieldCount++;
- this.referenceContext.updateMaxFieldCount();
checkAndSetModifiersForField(fieldBinding, fieldDeclaration);
// FIXME(SH): does this improve robustness?
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index 5d20c1d42..28818d76a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -351,13 +351,6 @@ public long getAnnotationTagBits() {
return originalField.tagBits;
}
-public int getAnalysisId(int maxFieldCount) {
- TypeBinding original = this.declaringClass.original();
- if (original instanceof SourceTypeBinding)
- return ((SourceTypeBinding)original).fieldAnalysisOffset + this.id;
- return this.id;
-}
-
public final boolean isDefault() {
return !isPublic() && !isProtected() && !isPrivate();
}
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 8951528e0..8e8fa9446 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,7 @@
* Stephan Herrmann - contributions for
* bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment
* bug 186342 - [compiler][null] Using annotations for null checking
+ * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -1301,59 +1302,6 @@ public char[][] getNonNullByDefaultAnnotationName() {
return this.globalOptions.nonNullByDefaultAnnotationName;
}
-/**
- * Answer the type binding representing the null-annotation identified by the given tag bits.
- * @param annotationTagBit tag bits potentially denoting a null-annotation
- * @param resolve should the resulting type binding be resolved?
- * @return the corresponding annotation type binding
- * or <code>null</code> if no annotation bits are contained in the given tag bits.
- */
-public TypeBinding getNullAnnotationBinding(long annotationTagBit, boolean resolve) {
- char[][] name = null;
- if (annotationTagBit == TagBits.AnnotationNonNull)
- name = getNonNullAnnotationName();
- else if (annotationTagBit == TagBits.AnnotationNullable)
- name = getNullableAnnotationName();
- else
- return null;
- if (resolve)
- return getType(name);
- else
- return getTypeFromCompoundName(name, false, false);
-}
-
-/**
- * Inspect the given tag bits and answer a corresponding null annotation type binding
- * @param defaultTagBit tag bits representing the default applicable at the current code location
- * @param resolve should the resulting type binding be resolved?
- * @return the corresponding concrete annotation type binding (<code>@NonNull</code> or <code>@Nullable</code>)
- * or <code>null</code> if no bits of a default-annotation are contained in the given tag bits.
- */
-public TypeBinding getNullAnnotationBindingFromDefault(long defaultTagBit, boolean resolve) {
- if ((defaultTagBit & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
- return ReferenceBinding.NULL_UNSPECIFIED;
- if ((defaultTagBit & TagBits.AnnotationNonNullByDefault) != 0)
- return getNullAnnotationBinding(TagBits.AnnotationNonNull, resolve);
- return null;
-}
-
-TypeBinding getNullAnnotationResolved(TypeBinding nullAnnotation, Scope scope) {
- // avoid unspecific error "The type in.valid cannot be resolved. It is indirectly referenced from required .class files"
- boolean tolerateMissing = this.mayTolerateMissingType;
- this.mayTolerateMissingType = true;
- try {
- nullAnnotation = BinaryTypeBinding.resolveType(nullAnnotation, this, false);
- } finally {
- this.mayTolerateMissingType = tolerateMissing;
- }
- if (nullAnnotation instanceof MissingTypeBinding) {
- // convert error into a specific one:
- scope.problemReporter().missingNullAnnotationType(((MissingTypeBinding)nullAnnotation).compoundName);
- return null;
- }
- return nullAnnotation;
-}
-
/* Answer the top level package named name if it exists in the cache.
* Answer theNotFoundPackage if it could not be resolved the first time
* it was looked up, otherwise answer null.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index d49b3039e..da2f17577 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -14,6 +14,7 @@
* bug 367203 - [compiler][null] detect assigning null to nonnull argument
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
* bug 365662 - [compiler][null] warn on contradictory and redundant null annotations
+ * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -854,10 +855,9 @@ public final char[] constantPoolName() {
}
/**
- * After method verifier has finished, fill in missing nullness values from the applicable default.
- * @param annotationBinding the null annotation specified to be the default at the current code location.
+ * After method verifier has finished, fill in missing @NonNull specification from the applicable default.
*/
-protected void fillInDefaultNonNullness(TypeBinding annotationBinding) {
+protected void fillInDefaultNonNullness() {
if (this.parameterNonNullness == null)
this.parameterNonNullness = new Boolean[this.parameters.length];
AbstractMethodDeclaration sourceMethod = sourceMethod();
@@ -870,9 +870,7 @@ protected void fillInDefaultNonNullness(TypeBinding annotationBinding) {
added = true;
this.parameterNonNullness[i] = Boolean.TRUE;
if (sourceMethod != null) {
- Argument argument = sourceMethod.arguments[i];
- sourceMethod.addParameterNonNullAnnotation(argument, (ReferenceBinding)annotationBinding);
- argument.binding.tagBits |= TagBits.AnnotationNonNull;
+ sourceMethod.arguments[i].binding.tagBits |= TagBits.AnnotationNonNull;
}
} else if (this.parameterNonNullness[i].booleanValue()) {
sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i);
@@ -885,8 +883,6 @@ protected void fillInDefaultNonNullness(TypeBinding annotationBinding) {
&& (this.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0)
{
this.tagBits |= TagBits.AnnotationNonNull;
- if (sourceMethod != null)
- sourceMethod.addNonNullAnnotation((ReferenceBinding)annotationBinding);
} else if ((this.tagBits & TagBits.AnnotationNonNull) != 0) {
sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, -1/*signifies method return*/);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
index a7cc75a7b..0c6cd255e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
@@ -13,6 +13,7 @@
* Stephan Herrmann - Contributions for
* bug 186342 - [compiler][null] Using annotations for null checking
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
+ * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -35,8 +36,9 @@ public class PackageBinding extends Binding implements TypeConstants {
HashtableOfType knownTypes;
HashtableOfPackage knownPackages;
- // annotation type binding representing the default that has been defined for this package (using @NonNullByDefault)
- protected TypeBinding nullnessDefaultAnnotation;
+ // code representing the default that has been defined for this package (using @NonNullByDefault)
+ // one of Binding.{NO_NULL_DEFAULT,NULL_UNSPECIFIED_BY_DEFAULT,NONNULL_BY_DEFAULT}
+ protected int defaultNullness = NO_NULL_DEFAULT;
protected PackageBinding() {
// for creating problem package
@@ -297,12 +299,6 @@ void checkIfNullAnnotationType(ReferenceBinding type) {
}
}
-public TypeBinding getNullnessDefaultAnnotation(Scope scope) {
- if (this.nullnessDefaultAnnotation instanceof UnresolvedReferenceBinding)
- return this.nullnessDefaultAnnotation = this.environment.getNullAnnotationResolved(this.nullnessDefaultAnnotation, scope);
- return this.nullnessDefaultAnnotation;
-}
-
public char[] readableName() /*java.lang*/ {
return CharOperation.concatWith(this.compoundName, '.');
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index 22e8ec920..fe876d5c6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -14,6 +14,7 @@
* bug 186342 - [compiler][null] Using annotations for null checking
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
* 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;
@@ -101,14 +102,6 @@ abstract public class ReferenceBinding extends AbstractOTReferenceBinding {
public boolean hasTypeBit(int bit) { return false; }
};
- /**
- * This faked annotation type binding marks types with unspecified nullness.
- * For use in {@link PackageBinding#nullnessDefaultAnnotation} and SourceTypeBinding#nullnessDefaultAnnotation
- */
- final static ReferenceBinding NULL_UNSPECIFIED = new ReferenceBinding() { /* faked type binding */
- public boolean hasTypeBit(int bit) { return false; }
- };
-
private static final Comparator FIELD_COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2) {
char[] n1 = ((FieldBinding) o1).name;
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 07d1434a1..dc57ce771 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
@@ -16,6 +16,8 @@
* bug 365836 - [compiler][null] Incomplete propagation of null defaults.
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
* bug 365662 - [compiler][null] warn on contradictory and redundant null annotations
+ * bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
+ * bug 366063 - Compiler should not add synthetic @NonNull annotations
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -107,8 +109,6 @@ public class SourceTypeBinding extends ReferenceBinding {
// SH}
public ClassScope scope;
- public int fieldAnalysisOffset; // an offset for ids of fields of this class (id to be used for flow analysis)
- public int cumulativeFieldCount; // cumulative field count from all enclosing types, used to build unique field id's for member types.
// Synthetics are separated into 4 categories: methods, super methods, fields, class literals and bridge methods
// if a new category is added, also increment MAX_SYNTHETICS
@@ -139,7 +139,7 @@ public class SourceTypeBinding extends ReferenceBinding {
private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
- private TypeBinding nullnessDefaultAnnotation;
+ private int defaultNullness;
private int nullnessDefaultInitialized = 0; // 0: nothing; 1: type; 2: package
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
@@ -158,7 +158,6 @@ public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassSc
// SH}
this.sourceName = scope.referenceContext.name;
this.scope = scope;
- this.cumulativeFieldCount = 0;
//{ObjectTeams: ROFI create a package binding for our role files (if any):
maybeSetTeamPackage(compoundName, fPackage, scope.environment());
// SH}
@@ -2376,9 +2375,9 @@ private void createArgumentBindings(MethodBinding method) {
if (methodDecl != null) {
if (method.parameters != Binding.NO_PARAMETERS)
methodDecl.createArgumentBindings();
- TypeBinding annotationBinding = findDefaultNullness(methodDecl.scope, methodDecl.scope.environment());
- if (annotationBinding != null && annotationBinding.id == TypeIds.T_ConfiguredAnnotationNonNull)
- method.fillInDefaultNonNullness(annotationBinding);
+ if ((findNonNullDefault(methodDecl.scope, methodDecl.scope.environment()) == NONNULL_BY_DEFAULT)) {
+ method.fillInDefaultNonNullness();
+ }
}
}
private void evaluateNullAnnotations(long annotationTagBits) {
@@ -2386,18 +2385,16 @@ private void evaluateNullAnnotations(long annotationTagBits) {
return;
this.nullnessDefaultInitialized = 1;
// transfer nullness info from tagBits to this.nullnessDefaultAnnotation
- TypeBinding defaultAnnotation = getPackage().environment
- .getNullAnnotationBindingFromDefault(annotationTagBits, false/*resolve*/);
- if (defaultAnnotation != null) {
+ int newDefaultNullness = NO_NULL_DEFAULT;
+ if ((annotationTagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
+ newDefaultNullness = NULL_UNSPECIFIED_BY_DEFAULT;
+ else if ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0)
+ newDefaultNullness = NONNULL_BY_DEFAULT;
+ if (newDefaultNullness != NO_NULL_DEFAULT) {
if (CharOperation.equals(this.sourceName, TypeConstants.PACKAGE_INFO_NAME)) {
- getPackage().nullnessDefaultAnnotation = defaultAnnotation;
- long globalDefault = this.scope.compilerOptions().defaultNonNullness;
- if (globalDefault == TagBits.AnnotationNonNull && (annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0) {
- TypeDeclaration typeDecl = this.scope.referenceContext;
- this.scope.problemReporter().nullDefaultAnnotationIsRedundant(typeDecl, typeDecl.annotations, null);
- }
+ getPackage().defaultNullness = newDefaultNullness;
} else {
- this.nullnessDefaultAnnotation = defaultAnnotation;
+ this.defaultNullness = newDefaultNullness;
TypeDeclaration typeDecl = this.scope.referenceContext;
long nullDefaultBits = annotationTagBits & (TagBits.AnnotationNullUnspecifiedByDefault|TagBits.AnnotationNonNullByDefault);
checkRedundantNullnessDefaultRecurse(typeDecl, typeDecl.annotations, nullDefaultBits);
@@ -2406,25 +2403,20 @@ private void evaluateNullAnnotations(long annotationTagBits) {
}
protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) {
- if (this.fPackage.nullnessDefaultAnnotation != null) {
- if ((this.fPackage.nullnessDefaultAnnotation.id == TypeIds.T_ConfiguredAnnotationNonNull
+ if (this.fPackage.defaultNullness != NO_NULL_DEFAULT) {
+ if ((this.fPackage.defaultNullness == NONNULL_BY_DEFAULT
&& ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0))) {
this.scope.problemReporter().nullDefaultAnnotationIsRedundant(location, annotations, this.fPackage);
}
return;
}
- long globalDefault = this.scope.compilerOptions().defaultNonNullness;
- if (globalDefault == TagBits.AnnotationNonNull && annotationTagBits == TagBits.AnnotationNonNullByDefault) {
- this.scope.problemReporter().nullDefaultAnnotationIsRedundant(location, annotations, null);
- }
}
// return: should caller continue searching?
protected boolean checkRedundantNullnessDefaultOne(ASTNode location, Annotation[] annotations, long annotationTagBits) {
- TypeBinding thisDefault = this.nullnessDefaultAnnotation;
- if (thisDefault != null) {
- if (thisDefault.id == TypeIds.T_ConfiguredAnnotationNonNull
- && ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0)) {
+ int thisDefault = this.defaultNullness;
+ if (thisDefault == NONNULL_BY_DEFAULT) {
+ if ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0) {
this.scope.problemReporter().nullDefaultAnnotationIsRedundant(location, annotations, this);
}
return false; // different default means inner default is not redundant -> we're done
@@ -2432,42 +2424,35 @@ protected boolean checkRedundantNullnessDefaultOne(ASTNode location, Annotation[
return true;
}
-private TypeBinding getNullnessDefaultAnnotation() {
- if (this.nullnessDefaultAnnotation instanceof UnresolvedReferenceBinding)
- this.nullnessDefaultAnnotation = this.scope.environment().getNullAnnotationResolved(this.nullnessDefaultAnnotation, this.scope);
- return this.nullnessDefaultAnnotation;
-}
/**
* Answer the nullness default applicable at the given method binding.
- * Possible values:<ul>
- * <li>the type binding for @NonNulByDefault</li>
- * <li>the synthetic type {@link ReferenceBinding#NULL_UNSPECIFIED} if a default from outer scope has been canceled</li>
- * <li>null if no default has been defined</li>
- * </ul>
+ * Possible values: {@link Binding#NO_NULL_DEFAULT}, {@link Binding#NULL_UNSPECIFIED_BY_DEFAULT}, {@link Binding#NONNULL_BY_DEFAULT}.
* @param currentScope where to start search for lexically enclosing default
- * @param environment gateway to options and configured annotation types
+ * @param environment gateway to options
*/
-private TypeBinding findDefaultNullness(Scope currentScope, LookupEnvironment environment) {
+private int findNonNullDefault(Scope currentScope, LookupEnvironment environment) {
// find the applicable default inside->out:
SourceTypeBinding currentType = null;
- TypeBinding annotationBinding;
while (currentScope != null) {
switch (currentScope.kind) {
case Scope.METHOD_SCOPE:
AbstractMethodDeclaration referenceMethod = ((MethodScope)currentScope).referenceMethod();
if (referenceMethod != null && referenceMethod.binding != null) {
- annotationBinding = environment.getNullAnnotationBindingFromDefault(referenceMethod.binding.tagBits, true/*resolve*/);
- if (annotationBinding != null)
- return annotationBinding;
+ long methodTagBits = referenceMethod.binding.tagBits;
+ if ((methodTagBits & TagBits.AnnotationNonNullByDefault) != 0)
+ return NONNULL_BY_DEFAULT;
+ if ((methodTagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
+ return NULL_UNSPECIFIED_BY_DEFAULT;
}
break;
case Scope.CLASS_SCOPE:
currentType = ((ClassScope)currentScope).referenceContext.binding;
if (currentType != null) {
- annotationBinding = currentType.getNullnessDefaultAnnotation();
- if (annotationBinding != null)
- return annotationBinding;
+ int foundDefaultNullness = currentType.defaultNullness;
+ if (foundDefaultNullness != NO_NULL_DEFAULT) {
+ return foundDefaultNullness;
+ }
}
break;
}
@@ -2476,28 +2461,13 @@ private TypeBinding findDefaultNullness(Scope currentScope, LookupEnvironment en
// package
if (currentType != null) {
- annotationBinding = currentType.getPackage().getNullnessDefaultAnnotation(this.scope);
- if (annotationBinding != null)
- return annotationBinding;
- }
-
- // global
- long defaultNullness = environment.globalOptions.defaultNonNullness;
- if (defaultNullness != 0) {
- // we have a default, so we need an annotation type to record this during compile and in the byte code
- annotationBinding = environment.getNullAnnotationBinding(defaultNullness, true/*resolve*/);
- if (annotationBinding != null)
- return annotationBinding;
-
- // on this branch default was not defined using an annotation, thus annotation type can still be missing
- if (defaultNullness == TagBits.AnnotationNonNull)
- this.scope.problemReporter().missingNullAnnotationType(environment.getNonNullAnnotationName());
- else
- this.scope.problemReporter().abortDueToInternalError("Illegal default nullness value: "+defaultNullness); //$NON-NLS-1$
- // reset default to avoid duplicate errors:
- environment.globalOptions.defaultNonNullness = 0;
+ int foundDefaultNullness = currentType.getPackage().defaultNullness;
+ if (foundDefaultNullness != NO_NULL_DEFAULT) {
+ return foundDefaultNullness;
+ }
}
- return null;
+
+ return NO_NULL_DEFAULT;
}
//{ObjectTeams: helper to find args allowing baseclass decapsulation:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
index ae9a80904..d11f88d6c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
@@ -60,10 +60,6 @@ public abstract class VariableBinding
return this.constant;
}
- public int getAnalysisId(int maxFieldCount) {
- return this.id + maxFieldCount;
- }
-
public abstract AnnotationBinding[] getAnnotations();
public final boolean isBlankFinal(){

Back to the top