Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 207657 Details for
Bug 186342
[compiler][null] Using annotations for null checking
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
alternative strategy for internally encoding nullness defaults
WIP_DefaultEncoding.patch (text/plain), 36.02 KB, created by
Stephan Herrmann
on 2011-11-29 09:58:57 EST
(
hide
)
Description:
alternative strategy for internally encoding nullness defaults
Filename:
MIME Type:
Creator:
Stephan Herrmann
Created:
2011-11-29 09:58:57 EST
Size:
36.02 KB
patch
obsolete
>diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java >index fc21f6d..fc4d329 100644 >--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java >+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java >@@ -1915,7 +1915,7 @@ > "Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + > "----------\n"); > } >-// package level default is consumed from package-info.class >+// package level default is consumed from package-info.class, similarly for type level default > public void test_default_nullness_003a() { > Map customOptions = getCompilerOptions(); > // customOptions.put(CompilerOptions.OPTION_ReportPotentialNullSpecViolation, JavaCore.ERROR); >@@ -1972,6 +1972,69 @@ > "Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + > "----------\n"); > } >+// same as test_default_nullness_003b, but default-induced annotations are combined with explicit ones (not null related) >+public void test_default_nullness_003b() { >+ Map customOptions = getCompilerOptions(); >+ runConformTestWithLibs( >+ new String[] { >+ "p1/Annot.java", >+ "package p1;\n" + >+ "import static java.lang.annotation.ElementType.*;\n" + >+ "import java.lang.annotation.*;\n" + >+ "@Retention(RetentionPolicy.CLASS)\n" + >+ "@Target({METHOD,PARAMETER})\n" + >+ "public @interface Annot {}\n", >+ "p1/X.java", >+ "package p1;\n" + >+ "import org.eclipse.jdt.annotation.*;\n" + >+ "@NonNullByDefault\n" + >+ "public class X {\n" + >+ " protected @Annot Object getObject(@Annot @Nullable Object o) {\n" + >+ " return new Object();\n" + >+ " }\n" + >+ " protected @Annot void bar(@Annot Object o2) { }\n" + // parameter is nonnull per type default >+ "}\n", >+ "p2/package-info.java", >+ "@org.eclipse.jdt.annotation.NonNullByDefault\n" + >+ "package p2;\n", >+ }, >+ customOptions, >+ ""); >+ // check if default is visible from package-info.class. >+ runNegativeTestWithLibs( >+ false, // don't flush >+ new String[] { >+ "p2/Y.java", >+ "package p2;\n" + >+ "import org.eclipse.jdt.annotation.*;\n" + >+ "public class Y extends p1.X {\n" + >+ " @Override\n" + >+ " protected @Nullable Object getObject(@Nullable Object o) {\n" + // can't override inherited default nonnull >+ " bar(o);\n" + // parameter is nonnull in super class's .class file >+ " accept(o);\n" + >+ " return o;\n" + >+ " }\n" + >+ " void accept(@p1.Annot Object a) {}\n" + // governed by package level default >+ "}\n" >+ }, >+ customOptions, >+ "----------\n" + >+ "1. ERROR in p2\\Y.java (at line 5)\n" + >+ " protected @Nullable Object getObject(@Nullable Object o) {\n" + >+ " ^^^^^^^^^^^^^^^^\n" + >+ "The return type is incompatible with the @NonNull return from X.getObject(Object)\n" + >+ "----------\n" + >+ "2. ERROR in p2\\Y.java (at line 6)\n" + >+ " bar(o);\n" + >+ " ^\n" + >+ "Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + >+ "----------\n" + >+ "3. ERROR in p2\\Y.java (at line 7)\n" + >+ " accept(o);\n" + >+ " ^\n" + >+ "Type mismatch: required \'@NonNull Object\' but the provided value can be null\n" + >+ "----------\n"); >+} > // don't apply type-level default to non-reference type > public void test_default_nullness_004() { > Map customOptions = getCompilerOptions(); >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java >index 5035d83..9deaade 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java >@@ -53,6 +53,7 @@ > import org.eclipse.jdt.internal.compiler.impl.Constant; > import org.eclipse.jdt.internal.compiler.impl.StringConstant; > import org.eclipse.jdt.internal.compiler.lookup.Binding; >+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; > import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; > import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; > import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; >@@ -324,7 +325,7 @@ > if (typeDeclaration != null) { > final Annotation[] annotations = typeDeclaration.annotations; > if (annotations != null) { >- attributesNumber += generateRuntimeAnnotations(annotations); >+ attributesNumber += generateRuntimeAnnotations(annotations, 0); > } > } > } >@@ -413,7 +414,7 @@ > if (fieldDeclaration != null) { > Annotation[] annotations = fieldDeclaration.annotations; > if (annotations != null) { >- attributesNumber += generateRuntimeAnnotations(annotations); >+ attributesNumber += generateRuntimeAnnotations(annotations, 0); > } > } > } >@@ -2683,8 +2684,9 @@ > AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod(); > if (methodDeclaration != null) { > Annotation[] annotations = methodDeclaration.annotations; >- if (annotations != null) { >- attributesNumber += generateRuntimeAnnotations(annotations); >+ int modifiers = methodBinding.modifiers; >+ if (annotations != null || (modifiers & ExtraCompilerModifiers.AccImplicitlyNonNull) != 0) { >+ attributesNumber += generateRuntimeAnnotations(annotations, methodBinding.modifiers); > } > if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) { > Argument[] arguments = methodDeclaration.arguments; >@@ -2868,23 +2870,53 @@ > } > } > >+ private int generateNonNullAttribute() { >+ TypeBinding nonNullAnnotation; >+ try { >+ nonNullAnnotation = this.referenceBinding.fPackage.environment.getNullAnnotationBinding(TagBits.AnnotationNonNull, true); >+ } catch (NullPointerException npe) { >+ return 0; // above chain of dereferencing is quite long, difficult to analyse if all are safe >+ } >+ int localContentsOffset = this.contentsOffset; >+ if (localContentsOffset + 6 >= this.contents.length) { >+ resizeContents(6); >+ } >+ int nonNullAttributeNameIndex = this.constantPool.literalIndex(nonNullAnnotation); >+ this.contents[localContentsOffset++] = (byte) (nonNullAttributeNameIndex >> 8); >+ this.contents[localContentsOffset++] = (byte) nonNullAttributeNameIndex; >+ // the length of a nonNull attribute is equals to 0 >+ this.contents[localContentsOffset++] = 0; >+ this.contents[localContentsOffset++] = 0; >+ this.contents[localContentsOffset++] = 0; >+ this.contents[localContentsOffset++] = 0; >+ this.contentsOffset = localContentsOffset; >+ return 1; >+ } >+ > /** > * @param annotations >+ * @param modifiers modifiers that could trigger generating an implicit annotation > * @return the number of attributes created while dumping the annotations in the .class file > */ >- private int generateRuntimeAnnotations(final Annotation[] annotations) { >+ private int generateRuntimeAnnotations(final Annotation[] annotations, int modifiers) { > int attributesNumber = 0; >- final int length = annotations.length; > int visibleAnnotationsCounter = 0; > int invisibleAnnotationsCounter = 0; >- >- for (int i = 0; i < length; i++) { >- Annotation annotation = annotations[i]; >- if (annotation.isRuntimeInvisible()) { >- invisibleAnnotationsCounter++; >- } else if (annotation.isRuntimeVisible()) { >- visibleAnnotationsCounter++; >+ >+ if (annotations != null) { >+ final int length = annotations.length; >+ for (int i = 0; i < length; i++) { >+ Annotation annotation = annotations[i]; >+ if (annotation.isRuntimeInvisible()) { >+ invisibleAnnotationsCounter++; >+ } else if (annotation.isRuntimeVisible()) { >+ visibleAnnotationsCounter++; >+ } > } >+ } >+ boolean isImplicitlyNonNull = (modifiers & ExtraCompilerModifiers.AccImplicitlyNonNull) != 0; >+ if (isImplicitlyNonNull) { >+ visibleAnnotationsCounter++; > } > > int annotationAttributeOffset = this.contentsOffset; >@@ -2905,15 +2937,18 @@ > this.contentsOffset += 2; // leave space for the annotations length > > int counter = 0; >- loop: for (int i = 0; i < length; i++) { >- if (invisibleAnnotationsCounter == 0) break loop; >- Annotation annotation = annotations[i]; >- if (annotation.isRuntimeInvisible()) { >- int currentAnnotationOffset = this.contentsOffset; >- generateAnnotation(annotation, currentAnnotationOffset); >- invisibleAnnotationsCounter--; >- if (this.contentsOffset != currentAnnotationOffset) { >- counter++; >+ if (annotations != null) { >+ final int length = annotations.length; >+ loop: for (int i = 0; i < length; i++) { >+ if (invisibleAnnotationsCounter == 0) break loop; >+ Annotation annotation = annotations[i]; >+ if (annotation.isRuntimeInvisible()) { >+ int currentAnnotationOffset = this.contentsOffset; >+ generateAnnotation(annotation, currentAnnotationOffset); >+ invisibleAnnotationsCounter--; >+ if (this.contentsOffset != currentAnnotationOffset) { >+ counter++; >+ } > } > } > } >@@ -2952,15 +2987,22 @@ > this.contentsOffset += 2; // leave space for the annotations length > > int counter = 0; >- loop: for (int i = 0; i < length; i++) { >- if (visibleAnnotationsCounter == 0) break loop; >- Annotation annotation = annotations[i]; >- if (annotation.isRuntimeVisible()) { >- visibleAnnotationsCounter--; >- int currentAnnotationOffset = this.contentsOffset; >- generateAnnotation(annotation, currentAnnotationOffset); >- if (this.contentsOffset != currentAnnotationOffset) { >- counter++; >+ if (isImplicitlyNonNull) { >+ counter += generateNonNullAttribute(); >+ visibleAnnotationsCounter--; >+ } >+ if (annotations != null) { >+ final int length = annotations.length; >+ loop: for (int i = 0; i < length; i++) { >+ if (visibleAnnotationsCounter == 0) break loop; >+ Annotation annotation = annotations[i]; >+ if (annotation.isRuntimeVisible()) { >+ visibleAnnotationsCounter--; >+ int currentAnnotationOffset = this.contentsOffset; >+ generateAnnotation(annotation, currentAnnotationOffset); >+ if (this.contentsOffset != currentAnnotationOffset) { >+ counter++; >+ } > } > } > } >@@ -3002,6 +3044,9 @@ > visibleParametersAnnotationsCounter++; > } > } >+ } >+ if ((argument.binding.modifiers & ExtraCompilerModifiers.AccImplicitlyNonNull) != 0) { >+ visibleParametersAnnotationsCounter++; > } > } > int attributesNumber = 0; >@@ -3085,13 +3130,13 @@ > this.contents[this.contentsOffset++] = (byte) 0; > this.contents[this.contentsOffset++] = (byte) 0; > } else { >+ Argument argument = arguments[i]; > final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX]; > int visibleAnnotationsOffset = this.contentsOffset; > // leave space for number of annotations > this.contentsOffset += 2; > int counter = 0; > if (numberOfVisibleAnnotations != 0) { >- Argument argument = arguments[i]; > Annotation[] annotations = argument.annotations; > for (int j = 0, max = annotations.length; j < max; j++) { > Annotation annotation = annotations[j]; >@@ -3106,6 +3151,12 @@ > } > } > } >+ if ((argument.binding.modifiers & ExtraCompilerModifiers.AccImplicitlyNonNull) != 0) { >+ int generated = generateNonNullAttribute(); >+ counter+=generated; >+ globalCounter+=generated; >+ visibleParametersAnnotationsCounter--; >+ } > this.contents[visibleAnnotationsOffset++] = (byte) (counter >> 8); > this.contents[visibleAnnotationsOffset] = (byte) counter; > } >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java >index 4cedddc..0795ad6 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java >@@ -256,8 +256,6 @@ > // this is only used for method invocation as the expression inside an expression statement > public static final int InsideExpressionStatement = Bit5; > >- // for annotation reference, signal if annotation was created from a default: >- public static final int IsSynthetic = ASTNode.Bit7; > // for name reference within a memberValuePair of an annotation: > public static final int IsMemberValueReference = ASTNode.Bit15; > >diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java >index f6d98fd..7af8bbd 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java >@@ -11,8 +11,6 @@ > *******************************************************************************/ > package org.eclipse.jdt.internal.compiler.ast; > >-import java.util.Arrays; >- > import org.eclipse.jdt.core.compiler.*; > import org.eclipse.jdt.internal.compiler.*; > import org.eclipse.jdt.internal.compiler.flow.FlowInfo; >@@ -69,42 +67,6 @@ > default : > throw new AbortMethod(this.compilationResult, problem); > } >- } >- >- /** >- * Materialize a null annotation that has been added from the current default, >- * in order to ensure that this annotation will be generated into the .class file, too. >- */ >- public void addNullnessAnnotation(ReferenceBinding annotationBinding) { >- this.annotations = addAnnotation(this, this.annotations, annotationBinding); >- } >- >- /** >- * Materialize a null parameter annotation that has been added from the current default, >- * in order to ensure that this annotation will be generated into the .class file, too. >- */ >- public void addParameterNonNullAnnotation(int i, ReferenceBinding annotationBinding) { >- Argument argument = this.arguments[i]; >- if (argument.type != null) // null happens for constructors of anonymous classes >- argument.annotations = addAnnotation(argument.type, argument.annotations, annotationBinding); >- } >- >- private Annotation[] addAnnotation(ASTNode location, Annotation[] oldAnnotations, ReferenceBinding annotationBinding) { >- long pos = ((long)location.sourceStart<<32) + location.sourceEnd; >- long[] poss = new long[annotationBinding.compoundName.length]; >- Arrays.fill(poss, pos); >- MarkerAnnotation annotation = new MarkerAnnotation(new QualifiedTypeReference(annotationBinding.compoundName, poss), location.sourceStart); >- annotation.declarationSourceEnd = location.sourceEnd; >- annotation.resolvedType = annotationBinding; >- annotation.bits = IsSynthetic; >- if (oldAnnotations == null) { >- oldAnnotations = new Annotation[] {annotation}; >- } else { >- int len = oldAnnotations.length; >- System.arraycopy(oldAnnotations, 0, oldAnnotations=new Annotation[len+1], 1, len); >- oldAnnotations[0] = annotation; >- } >- return oldAnnotations; > } > > /** >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 4a1bad4..125a30c 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 >@@ -1218,7 +1218,7 @@ > IBinaryAnnotation[] annotations = binaryType.getAnnotations(); > if (annotations != null) { > long annotationBit = 0L; >- TypeBinding defaultNullness = null; >+ int defaultNullness = NO_NULL_DEFAULT; > for (int i = 0; i < annotations.length; i++) { > char[] annotationTypeName = annotations[i].getTypeName(); > if (annotationTypeName[0] != Util.C_RESOLVED) >@@ -1233,19 +1233,19 @@ > { > // parameter is 'false': this means we cancel defaults from outer scopes: > annotationBit = TagBits.AnnotationNullUnspecifiedByDefault; >- defaultNullness = ReferenceBinding.NULL_UNSPECIFIED; >+ defaultNullness = NULL_UNSPECIFIED_BY_DEFAULT; > break; > } > } > annotationBit = TagBits.AnnotationNonNullByDefault; >- defaultNullness = this.environment.getNullAnnotationBinding(TagBits.AnnotationNonNull, false/*resolve*/); >+ defaultNullness = NONNULL_BY_DEFAULT; > break; > } > } > if (annotationBit != 0L) { > this.tagBits |= annotationBit; > if (CharOperation.equals(this.sourceName(), TypeConstants.PACKAGE_INFO_NAME)) >- this.getPackage().nullnessDefaultAnnotation = defaultNullness; >+ this.getPackage().defaultNullness = defaultNullness; > } > } > } >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 d0e769e..3c32855 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 >@@ -48,6 +48,11 @@ > 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/ExtraCompilerModifiers.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java >index 9927aaa..d2d4fe0 100644 >--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java >+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ExtraCompilerModifiers.java >@@ -41,4 +41,5 @@ > final int AccOverriding = ASTNode.Bit29; // record fact a method overrides another one > final int AccImplementing = ASTNode.Bit30; // record fact a method implements another one (it is concrete and overrides an abstract one) > final int AccGenericSignature = ASTNode.Bit31; // record fact a type/method/field involves generics in its signature (and need special signature attr) >+ final int AccImplicitlyNonNull = ASTNode.Bit32; // record fact that a method/argument should be seen as NonNull due to an applicable default > } >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 659ef81..b2a3ccf 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 >@@ -1113,21 +1113,6 @@ > 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; >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 0e1140d..84ca7ce 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 >@@ -444,35 +444,30 @@ > } > > /** >- * 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(); > for (int i = 0; i < this.parameterNonNullness.length; i++) { > if (this.parameters[i].isBaseType()) > continue; >- boolean added = false; > if (this.parameterNonNullness[i] == null) { >- added = true; > this.parameterNonNullness[i] = Boolean.TRUE; > if (sourceMethod != null) >- sourceMethod.addParameterNonNullAnnotation(i, (ReferenceBinding)annotationBinding); >+ sourceMethod.arguments[i].binding.modifiers |= ExtraCompilerModifiers.AccImplicitlyNonNull; >+ this.tagBits |= TagBits.HasParameterAnnotations; > } else if (this.parameterNonNullness[i].booleanValue()) { > sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i); > } >- if (added) >- this.tagBits |= TagBits.HasParameterAnnotations; > } > if ( this.returnType != null > && !this.returnType.isBaseType() > && (this.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0) > { > this.tagBits |= TagBits.AnnotationNonNull; >- if (sourceMethod != null) >- sourceMethod.addNullnessAnnotation((ReferenceBinding)annotationBinding); >+ this.modifiers |= ExtraCompilerModifiers.AccImplicitlyNonNull; > } 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 8d7c02d..965878b 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 >@@ -24,8 +24,9 @@ > 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 >@@ -267,22 +268,19 @@ > if (this.environment.nullableAnnotationPackage == this > && CharOperation.equals(type.compoundName, this.environment.getNullableAnnotationName())) { > type.id = TypeIds.T_ConfiguredAnnotationNullable; >- this.environment.nullableAnnotationPackage = null; // don't check again >+ if (!(type instanceof UnresolvedReferenceBinding)) // unresolved type will come back here >+ this.environment.nullableAnnotationPackage = null; // don't check again > } else if (this.environment.nonnullAnnotationPackage == this > && CharOperation.equals(type.compoundName, this.environment.getNonNullAnnotationName())) { > type.id = TypeIds.T_ConfiguredAnnotationNonNull; >- this.environment.nonnullAnnotationPackage = null; // don't check again >+ if (!(type instanceof UnresolvedReferenceBinding)) // unresolved type will come back here >+ this.environment.nonnullAnnotationPackage = null; // don't check again > } else if (this.environment.nonnullByDefaultAnnotationPackage == this > && CharOperation.equals(type.compoundName, this.environment.getNonNullByDefaultAnnotationName())) { > type.id = TypeIds.T_ConfiguredAnnotationNonNullByDefault; >- this.environment.nonnullByDefaultAnnotationPackage = null; // don't check again >+ if (!(type instanceof UnresolvedReferenceBinding)) // unresolved type will come back here >+ this.environment.nonnullByDefaultAnnotationPackage = null; // don't check again > } >-} >- >-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*/ { >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 75de854..5116382 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 >@@ -50,14 +50,6 @@ > 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 094c155..faa5a51 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 >@@ -56,7 +56,7 @@ > > 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) { >@@ -1618,9 +1618,9 @@ > if (methodDecl != null) { > if (method.parameters != Binding.NO_PARAMETERS) > methodDecl.createArgumentBindings(); >- TypeBinding annotationBinding = findDefaultNullness(method, methodDecl.scope.environment()); >- if (annotationBinding != null && annotationBinding.id == TypeIds.T_ConfiguredAnnotationNonNull) >- method.fillInDefaultNonNullness(annotationBinding); >+ if (hasNonNullDefault(method, methodDecl.scope.environment())) { >+ method.fillInDefaultNonNullness(); >+ } > } > } > private void evaluateNullAnnotations(long annotationTagBits) { >@@ -1628,69 +1628,66 @@ > 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; >+ getPackage().defaultNullness = newDefaultNullness; > } else { >- this.nullnessDefaultAnnotation = defaultAnnotation; >+ this.defaultNullness = newDefaultNullness; > } > } > } >-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> >+ * Answer whether the given method binding is subject to a @NonNull default > */ >-private TypeBinding findDefaultNullness(MethodBinding methodBinding, LookupEnvironment environment) { >+private boolean hasNonNullDefault(MethodBinding methodBinding, LookupEnvironment environment) { >+ int foundDefaultNullness = findNonNullDefault(methodBinding, environment); >+ if (foundDefaultNullness == NONNULL_BY_DEFAULT) { >+ // requesting implicit use of @NonNull, check if the annotation type is present: >+ if (environment.getNullAnnotationBinding(TagBits.AnnotationNonNull, true) == null) { >+ this.scope.problemReporter().missingNullAnnotationType(environment.getNonNullAnnotationName()); >+ environment.globalOptions.defaultNonNullness = 0; >+ return false; >+ } >+ return true; >+ } >+ return false; >+} >+private int findNonNullDefault(MethodBinding methodBinding, LookupEnvironment environment) { > // find the applicable default inside->out: > > // method >- TypeBinding annotationBinding = environment.getNullAnnotationBindingFromDefault(methodBinding.tagBits, true/*resolve*/); >- if (annotationBinding != null) >- return annotationBinding; >+ if ((methodBinding.tagBits & TagBits.AnnotationNonNullByDefault) != 0) >+ return NONNULL_BY_DEFAULT; >+ if ((methodBinding.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0) >+ return NULL_UNSPECIFIED_BY_DEFAULT; > > // type > ReferenceBinding type = methodBinding.declaringClass; > ReferenceBinding currentType = type; >+ int foundDefaultNullness = NO_NULL_DEFAULT; > while (currentType instanceof SourceTypeBinding) { >- annotationBinding = ((SourceTypeBinding) currentType).getNullnessDefaultAnnotation(); >- if (annotationBinding != null) >- return annotationBinding; >+ foundDefaultNullness = ((SourceTypeBinding)currentType).defaultNullness; >+ if (foundDefaultNullness != NO_NULL_DEFAULT) { >+ return foundDefaultNullness; >+ } > currentType = currentType.enclosingType(); > } > > // package >- annotationBinding = type.getPackage().getNullnessDefaultAnnotation(this.scope); >- if (annotationBinding != null) >- return annotationBinding; >+ foundDefaultNullness = type.getPackage().defaultNullness; >+ if (foundDefaultNullness != NO_NULL_DEFAULT) { >+ return foundDefaultNullness; >+ } > > // 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; >- } >- return null; >+ if (environment.globalOptions.defaultNonNullness == TagBits.AnnotationNonNull) >+ return NONNULL_BY_DEFAULT; >+ return NO_NULL_DEFAULT; > } > > public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) { >diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java >index a2d1924..b72a6fb 100644 >--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java >+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java >@@ -4361,7 +4361,6 @@ > int indexInAnnotations = 0; > while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) { > IExtendedModifier modifier = null; >- switchToken: > switch(token) { > case TerminalTokens.TokenNameabstract: > modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD); >@@ -4399,13 +4398,7 @@ > case TerminalTokens.TokenNameAT : > // we have an annotation > if (annotations != null && indexInAnnotations < annotations.length) { >- // method may have synthetic annotations, skip them: >- org.eclipse.jdt.internal.compiler.ast.Annotation annotation; >- do { >- if (indexInAnnotations == annotations.length) >- break switchToken; >- annotation = annotations[indexInAnnotations++]; >- } while ((annotation.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsSynthetic) != 0); >+ org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++]; > modifier = convert(annotation); > this.scanner.resetTo(annotation.declarationSourceEnd + 1, modifiersEnd); > } >@@ -4519,7 +4512,6 @@ > int token; > while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) { > IExtendedModifier modifier = null; >- switchToken: > switch(token) { > case TerminalTokens.TokenNameabstract: > modifier = createModifier(Modifier.ModifierKeyword.ABSTRACT_KEYWORD); >@@ -4557,13 +4549,7 @@ > case TerminalTokens.TokenNameAT : > // we have an annotation > if (annotations != null && indexInAnnotations < annotations.length) { >- // argument may have synthetic annotations, skip them: >- org.eclipse.jdt.internal.compiler.ast.Annotation annotation; >- do { >- if (indexInAnnotations == annotations.length) >- break switchToken; >- annotation = annotations[indexInAnnotations++]; >- } while ((annotation.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsSynthetic) != 0); >+ org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++]; > modifier = convert(annotation); > this.scanner.resetTo(annotation.declarationSourceEnd + 1, this.compilationUnitSourceLength); > } >@@ -4637,7 +4623,6 @@ > break; > case TerminalTokens.TokenNameAT : > // we have an annotation >- // (local variable has no synthetic annotations, no need to skip them) > if (annotations != null && indexInAnnotations < annotations.length) { > org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++]; > modifier = convert(annotation); >@@ -4740,7 +4725,6 @@ > break; > case TerminalTokens.TokenNameAT : > // we have an annotation >- // (local variable has no synthetic annotations, no need to skip them) > if (annotations != null && indexInAnnotations < annotations.length) { > org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++]; > modifier = convert(annotation); >@@ -4822,7 +4806,6 @@ > break; > case TerminalTokens.TokenNameAT : > // we have an annotation >- // (local variable has no synthetic annotations, no need to skip them) > if (annotations != null && indexInAnnotations < annotations.length) { > org.eclipse.jdt.internal.compiler.ast.Annotation annotation = annotations[indexInAnnotations++]; > modifier = convert(annotation);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 186342
:
74851
|
86246
|
86247
|
89354
|
184335
|
185507
|
186796
|
186798
|
186872
|
186876
|
186889
|
186890
|
206525
|
206557
|
207270
|
207308
|
207478
|
207565
|
207567
|
207573
|
207592
|
207604
|
207635
|
207637
|
207639
| 207657 |
207659
|
207672
|
207677
|
207685