Bug 437767 - [java8][null] semantically integrate null type annotations
with anchored role types
- improve parsing of mixed type annotation / type anchor patterns
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index 177da4b..1e7b2af 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -7602,6 +7602,12 @@
// PushZeroTypeAnnotations ::= $empty
// Name ::= SimpleName
// TypeAnnotationsopt ::= $empty
+ int sentinelPos = -1;
+ if (this.typeAnnotationLengthPtr != -1) {
+ sentinelPos = this.typeAnnotationPtr - this.typeAnnotationLengthStack[this.typeAnnotationLengthPtr];
+ if (sentinelPos > -1 && this.typeAnnotationStack[sentinelPos] == annotationSentinel)
+ return; // convertTypeAnchor already allocated a sentinel-delimited annotation list, don't add another one
+ }
pushOnTypeAnnotationLengthStack(0); // signal absence of @308 annotations.
}
// This method is part of an automatic generation : do NOT edit-modify
@@ -9398,6 +9404,10 @@
consumeAnnotationsOnTypeArgumentFromAnchor();
break;
+ case 763 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument1 ::= AnyTypeAnchor..."); } //$NON-NLS-1$
+ confirmTypeAnchor();
+ break;
+
case 764 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument1 ::=..."); } //$NON-NLS-1$
consumeAnnotationsOnTypeArgumentFromAnchor();
break;
@@ -9406,6 +9416,10 @@
consumeAnnotationsOnTypeArgumentFromAnchor();
break;
+ case 766 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument2 ::= AnyTypeAnchor..."); } //$NON-NLS-1$
+ confirmTypeAnchor();
+ break;
+
case 767 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument2 ::=..."); } //$NON-NLS-1$
consumeAnnotationsOnTypeArgumentFromAnchor();
break;
@@ -9414,6 +9428,10 @@
consumeAnnotationsOnTypeArgumentFromAnchor();
break;
+ case 769 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument3 ::= AnyTypeAnchor..."); } //$NON-NLS-1$
+ confirmTypeAnchor();
+ break;
+
case 770 : if (DEBUG) { System.out.println("TypeAnchorOrAnnotatedTypeArgument3 ::=..."); } //$NON-NLS-1$
consumeAnnotationsOnTypeArgumentFromAnchor();
break;
@@ -11420,6 +11438,11 @@
// anchor has no type annotations, yet it will be consumed in a context where type annotations are possible
pushOnTypeAnnotationLengthStack(0);
}
+protected void confirmTypeAnchor() {
+ // tentative type anchor is indeed a type anchor (not converted to type annotation).
+ // need to remove the empty type annotation list now (see consumeTypeAnchor()).
+ this.typeAnnotationLengthPtr--;
+}
// this sentinel annotation is pushed below a type annotation that was converted from a type anchor.
// it signals to a subsequent type annotation that it shall be merged into the existing list
static final Annotation annotationSentinel = new MarkerAnnotation(new SingleTypeReference("annotationSentinel".toCharArray(), 0), 0); //$NON-NLS-1$
@@ -11518,35 +11541,13 @@
// TypeAnchorOrAnnotatedTypeArgument2 -> TentativeTypeAnchor NotAnAnchor ReferenceType2
// TypeAnchorOrAnnotatedTypeArgument2 -> TentativeTypeAnchor NotAnAnchor Wildcard2
- // in all these cases a type reference (with dims) already exists
- // and only type annotations need to be added/merged (if any)
-
- TypeReference ref = (TypeReference) this.genericsStack[this.genericsPtr];
- // insert or merge converted annotation at first level into ref's annotations:
- int length = this.typeAnnotationLengthStack[this.typeAnnotationLengthPtr--];
- if (length != 0) {
- if (ref.annotations == null)
- ref.annotations = new Annotation[ref.getAnnotatableLevels()][];
- Annotation[] annotations = ref.annotations[0];
- int oldLen = 0;
- if (annotations != null) {
- oldLen = annotations.length;
- System.arraycopy(annotations, 0, annotations = new Annotation[oldLen+length], length, oldLen);
- } else {
- annotations = new Annotation[length];
- }
- System.arraycopy(
- this.typeAnnotationStack,
- (this.typeAnnotationPtr -= length) + 1,
- annotations,
- 0,
- length);
- ref.annotations[0] = annotations;
- ref.sourceStart = annotations[0].sourceStart;
- ref.bits |= ASTNode.HasTypeAnnotations;
+ // in all these cases a type reference (with dims) already exists on the genericsStack
+ // (will be collected by consumeTypeArgumentList1())
+ // type annotations should have been attached via the tail of the production (e.g., consumeReferenceType1())
+ // now just clean-up the remaining annotation sentinel
+ if (this.typeAnnotationStack[this.typeAnnotationPtr] == annotationSentinel) {
+ this.typeAnnotationPtr--; // drop the annotationSentinel
}
- // type references are already on genericsStack, will be collected by consumeTypeArgumentList1()
- this.typeAnnotationPtr--; // drop the annotationSentinel
}
protected NameReference newBaseReference() {
return new SingleNameReference(IOTConstants._OT_BASE, (((long)this.intStack[this.intPtr--])<<32)+this.intStack[this.intPtr--]);
@@ -11558,6 +11559,8 @@
// Cannot use ThisReference as type anchor.
// Since R<@this> is redundant, simply drop the argument (see also concatGenericsList()).
this.intPtr-=2;
+ // anchor has not type annotations, yet it will be consumed in a context where type annotations are possible
+ pushOnTypeAnnotationLengthStack(0);
}
protected void consumeQualifiedBaseTypeAnchor() {
// TypeAnchor ::= '@OT' UnannotatableName '.' 'base'
@@ -11566,7 +11569,8 @@
// handle type arguments (see consumePrimaryNoNewArrayNameThis):
pushOnGenericsIdentifiersLengthStack(this.identifierLengthStack[this.identifierLengthPtr]);
pushOnGenericsLengthStack(0); // handle type arguments
- TypeReference prefix = getTypeReference(0);
+ pushOnTypeAnnotationLengthStack(0); // unannotated by construction, but haven't yet pushed zero type annotatations
+ TypeReference prefix = getTypeReference(0); // consumes the above zero type annotations
Reference anchor = new QualifiedBaseReference(prefix, this.intStack[this.intPtr--], this.intStack[this.intPtr--]);
pushOnGenericsStack(new TypeAnchorReference(anchor, this.intStack[this.intPtr--]));
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
index c8f6027..57d2985 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.props b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.props
index b198740..fd6a148 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.props
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.props
@@ -370,9 +370,9 @@
TryStatementWithResources=TryStatementWithResources
Type=Type
TypeAnchor=typeAnchor
-TypeAnchorOrAnnotatedTypeArgument1=TypeArgument
-TypeAnchorOrAnnotatedTypeArgument2=TypeArgument
-TypeAnchorOrAnnotatedTypeArgument3=TypeArgument
+TypeAnchorOrAnnotatedTypeArgument1=TypeAnchor
+TypeAnchorOrAnnotatedTypeArgument2=TypeAnchor
+TypeAnchorOrAnnotatedTypeArgument3=TypeAnchor
TypeAnchorOrAnnotatedTypeArgument=TypeArgument
TypeAnnotation=TypeAnnotation
TypeAnnotationName=AnnotationName
diff --git a/org.eclipse.jdt.core/grammar/java.g b/org.eclipse.jdt.core/grammar/java.g
index 6eacdc8..923faa4 100644
--- a/org.eclipse.jdt.core/grammar/java.g
+++ b/org.eclipse.jdt.core/grammar/java.g
@@ -2601,12 +2601,12 @@
-- ==== No Nested Generics ====
-- case 1: it was indeed a type anchor:
TypeAnchorOrAnnotatedTypeArgument -> AnyTypeAnchor
--- case 2a: we were wrong in assuming a type anchor, now is the time to convert it into a marker type annotation:
+-- case 2a: we were wrong in assuming a type anchor, converted marker type annotation exists, time to clean up
TypeAnchorOrAnnotatedTypeArgument -> TentativeTypeAnchor NotAnAnchor ReferenceType
/.$putCase consumeTypeArgumentFromAnchor(); $break ./
/:$readableName TypeArgument:/
/:$compliance 1.5:/
--- case 2b: we were wrong in assuming a type anchor, now is the time to convert it into a marker type annotation:
+-- case 2b: we were wrong in assuming a type anchor, converted marker type annotation exists, time to clean up
TypeAnchorOrAnnotatedTypeArgument -> TentativeTypeAnchor NotAnAnchor Wildcard
/.$putCase consumeAnnotationsOnTypeArgumentFromAnchor(); $break ./
/:$readableName TypeArgument:/
@@ -2615,12 +2615,15 @@
-- ==== One Level Nested Generics ====
-- case 1: it was indeed a type anchor:
TypeAnchorOrAnnotatedTypeArgument1 -> AnyTypeAnchor '>'
--- case 2a: we were wrong in assuming a type anchor, now is the time to convert it into a marker type annotation:
+/.$putCase confirmTypeAnchor(); $break ./
+/:$readableName TypeAnchor:/
+/:$compliance 1.5:/
+-- case 2a: we were wrong in assuming a type anchor, converted marker type annotation exists, time to clean up
TypeAnchorOrAnnotatedTypeArgument1 -> TentativeTypeAnchor NotAnAnchor ReferenceType1
/.$putCase consumeAnnotationsOnTypeArgumentFromAnchor(); $break ./
/:$readableName TypeArgument:/
/:$compliance 1.5:/
--- case 2b: we were wrong in assuming a type anchor, now is the time to convert it into a marker type annotation:
+-- case 2b: we were wrong in assuming a type anchor, converted marker type annotation exists, time to clean up
TypeAnchorOrAnnotatedTypeArgument1 -> TentativeTypeAnchor NotAnAnchor Wildcard1
/.$putCase consumeAnnotationsOnTypeArgumentFromAnchor(); $break ./
/:$readableName TypeArgument:/
@@ -2629,12 +2632,15 @@
-- ==== Two Levels Nested Generics ====
-- case 1: it was indeed a type anchor:
TypeAnchorOrAnnotatedTypeArgument2 -> AnyTypeAnchor '>>'
--- case 2a: we were wrong in assuming a type anchor, now is the time to convert it into a marker type annotation:
+/.$putCase confirmTypeAnchor(); $break ./
+/:$readableName TypeAnchor:/
+/:$compliance 1.5:/
+-- case 2a: we were wrong in assuming a type anchor, converted marker type annotation exists, time to clean up
TypeAnchorOrAnnotatedTypeArgument2 -> TentativeTypeAnchor NotAnAnchor ReferenceType2
/.$putCase consumeAnnotationsOnTypeArgumentFromAnchor(); $break ./
/:$readableName TypeArgument:/
/:$compliance 1.5:/
--- case 2b: we were wrong in assuming a type anchor, now is the time to convert it into a marker type annotation:
+-- case 2b: we were wrong in assuming a type anchor, converted marker type annotation exists, time to clean up
TypeAnchorOrAnnotatedTypeArgument2 -> TentativeTypeAnchor NotAnAnchor Wildcard2
/.$putCase consumeAnnotationsOnTypeArgumentFromAnchor(); $break ./
/:$readableName TypeArgument:/
@@ -2643,19 +2649,22 @@
-- ==== Three Levels Nested Generics ====
-- case 1: it was indeed a type anchor:
TypeAnchorOrAnnotatedTypeArgument3 -> AnyTypeAnchor '>>>'
--- case 2a: we were wrong in assuming a type anchor, now is the time to convert it into a marker type annotation:
+/.$putCase confirmTypeAnchor(); $break ./
+/:$readableName TypeAnchor:/
+/:$compliance 1.5:/
+-- case 2a: we were wrong in assuming a type anchor, converted marker type annotation exists, time to clean up
TypeAnchorOrAnnotatedTypeArgument3 -> TentativeTypeAnchor NotAnAnchor ReferenceType3
/.$putCase consumeAnnotationsOnTypeArgumentFromAnchor(); $break ./
/:$readableName TypeArgument:/
/:$compliance 1.5:/
--- case 2b: we were wrong in assuming a type anchor, now is the time to convert it into a marker type annotation:
+-- case 2b: we were wrong in assuming a type anchor, converted marker type annotation exists, time to clean up
TypeAnchorOrAnnotatedTypeArgument3 -> TentativeTypeAnchor NotAnAnchor Wildcard3
/.$putCase consumeAnnotationsOnTypeArgumentFromAnchor(); $break ./
/:$readableName TypeArgument:/
/:$compliance 1.5:/
-- =====================================
--- trigger converting a mistaken type anchor into a type argument
+-- trigger converting a mistaken type anchor into a type annotation on a type argument
NotAnAnchor ::= $empty
/.$putCase convertTypeAnchor(0); $break ./
/:$readableName annotatedTypeArgument:/