diff -r 5c956be64b9e -r 71f35e4b93a5 src/share/classes/com/sun/tools/javac/code/Annotations.java
--- a/src/share/classes/com/sun/tools/javac/code/Annotations.java Wed Jan 23 20:57:40 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/code/Annotations.java Wed Jan 23 13:27:24 2013 -0800
@@ -48,7 +48,7 @@
*
* An instance of this class can be in one of three states:
*
- * NOT_STARTED indicates that the Symbol this instance belongs to have not been
+ * NOT_STARTED indicates that the Symbol this instance belongs to has not been
* annotated (yet). Specifically if the declaration is not annotated this
* instance will never move past NOT_STARTED. You can never go back to
* NOT_STARTED.
@@ -59,7 +59,7 @@
*
* "unnamed" this Annotations contains some attributes, possibly the final set.
* While in this state you can only prepend or append to the attributes not set
- * it directly. You can also move back to the IN_PROGRESS sate using reset().
+ * it directly. You can also move back to the IN_PROGRESS state using reset().
*
*
This is NOT part of any supported API. If you write code that depends
* on this, you do so at your own risk. This code and its internal interfaces
@@ -67,14 +67,21 @@
*/
public class Annotations {
- private static final List NOT_STARTED = List.of(null);
- private static final List IN_PROGRESS = List.of(null);
+ private static final List DECL_NOT_STARTED = List.of(null);
+ private static final List DECL_IN_PROGRESS = List.of(null);
+
/*
* This field should never be null
*/
- private List attributes = NOT_STARTED;
+ private List attributes = DECL_NOT_STARTED;
+
/*
- * The Symbol this Annotations belong to
+ * This field should never be null
+ */
+ private List type_attributes = List.nil();
+
+ /*
+ * The Symbol this Annotations instance belongs to
*/
private final Symbol sym;
@@ -82,11 +89,15 @@
this.sym = sym;
}
- public List getAttributes() {
- return filterSentinels(attributes);
+ public List getDeclarationAttributes() {
+ return filterDeclSentinels(attributes);
}
- public void setAttributes(List a) {
+ public List getTypeAttributes() {
+ return type_attributes;
+ }
+
+ public void setDeclarationAttributes(List a) {
Assert.check(pendingCompletion() || !isStarted());
if (a == null) {
throw new NullPointerException();
@@ -94,31 +105,51 @@
attributes = a;
}
+ public void setTypeAttributes(List a) {
+ if (a == null) {
+ throw new NullPointerException();
+ }
+ type_attributes = a;
+ }
+
public void setAttributes(Annotations other) {
if (other == null) {
throw new NullPointerException();
}
- setAttributes(other.getAttributes());
+ setDeclarationAttributes(other.getDeclarationAttributes());
+ setTypeAttributes(other.getTypeAttributes());
}
- public void setAttributesWithCompletion(final Annotate.AnnotateRepeatedContext ctx) {
+ public void setDeclarationAttributesWithCompletion(final Annotate.AnnotateRepeatedContext ctx) {
Assert.check(pendingCompletion() || (!isStarted() && sym.kind == PCK));
+ this.setDeclarationAttributes(getAttributesForCompletion(ctx));
+ }
- Map> annotated = ctx.annotated;
+ public void appendTypeAttributesWithCompletion(final Annotate.AnnotateRepeatedContext ctx) {
+ this.appendUniqueTypes(getAttributesForCompletion(ctx));
+ }
+
+ private List getAttributesForCompletion(
+ final Annotate.AnnotateRepeatedContext ctx) {
+
+ Map> annotated = ctx.annotated;
boolean atLeastOneRepeated = false;
- List buf = List.nil();
- for (ListBuffer lb : annotated.values()) {
+ List buf = List.nil();
+ for (ListBuffer lb : annotated.values()) {
if (lb.size() == 1) {
buf = buf.prepend(lb.first());
} else { // repeated
- buf = buf.prepend(new Placeholder(lb.toList(), sym));
+ // This will break when other subtypes of Attributs.Compound
+ // are introduced, because PlaceHolder is a subtype of TypeCompound.
+ T res;
+ @SuppressWarnings("unchecked")
+ T ph = (T) new Placeholder(ctx, lb.toList(), sym);
+ res = ph;
+ buf = buf.prepend(res);
atLeastOneRepeated = true;
}
}
- // Add non-repeating attributes
- setAttributes(buf.reverse());
-
if (atLeastOneRepeated) {
// The Symbol s is now annotated with a combination of
// finished non-repeating annotations and placeholders for
@@ -138,7 +169,6 @@
// Queue a pass that will replace Attribute.Placeholders
// with Attribute.Compound (made from synthesized containers).
ctx.annotateRepeated(new Annotate.Annotator() {
-
@Override
public String toString() {
return "repeated annotation pass of: " + sym + " in: " + sym.owner;
@@ -150,10 +180,12 @@
}
});
}
+ // Add non-repeating attributes
+ return buf.reverse();
}
public Annotations reset() {
- attributes = IN_PROGRESS;
+ attributes = DECL_IN_PROGRESS;
return this;
}
@@ -163,12 +195,16 @@
|| attributes.isEmpty();
}
+ public boolean isTypesEmpty() {
+ return type_attributes.isEmpty();
+ }
+
public boolean pendingCompletion() {
- return attributes == IN_PROGRESS;
+ return attributes == DECL_IN_PROGRESS;
}
public Annotations append(List l) {
- attributes = filterSentinels(attributes);
+ attributes = filterDeclSentinels(attributes);
if (l.isEmpty()) {
; // no-op
@@ -180,8 +216,24 @@
return this;
}
+ public Annotations appendUniqueTypes(List l) {
+ if (l.isEmpty()) {
+ ; // no-op
+ } else if (type_attributes.isEmpty()) {
+ type_attributes = l;
+ } else {
+ // TODO: in case we expect a large number of annotations, this
+ // might be inefficient.
+ for (Attribute.TypeCompound tc : l) {
+ if (!type_attributes.contains(tc))
+ type_attributes = type_attributes.append(tc);
+ }
+ }
+ return this;
+ }
+
public Annotations prepend(List l) {
- attributes = filterSentinels(attributes);
+ attributes = filterDeclSentinels(attributes);
if (l.isEmpty()) {
; // no-op
@@ -193,19 +245,29 @@
return this;
}
- private List filterSentinels(List a) {
- return (a == IN_PROGRESS || a == NOT_STARTED)
+ private List filterDeclSentinels(List a) {
+ return (a == DECL_IN_PROGRESS || a == DECL_NOT_STARTED)
? List.nil()
: a;
}
private boolean isStarted() {
- return attributes != NOT_STARTED;
+ return attributes != DECL_NOT_STARTED;
}
private List getPlaceholders() {
List res = List.nil();
- for (Attribute.Compound a : filterSentinels(attributes)) {
+ for (Attribute.Compound a : filterDeclSentinels(attributes)) {
+ if (a instanceof Placeholder) {
+ res = res.prepend(a);
+ }
+ }
+ return res.reverse();
+ }
+
+ private List getTypePlaceholders() {
+ List res = List.nil();
+ for (Attribute.TypeCompound a : type_attributes) {
if (a instanceof Placeholder) {
res = res.prepend(a);
}
@@ -216,50 +278,78 @@
/*
* Replace Placeholders for repeating annotations with their containers
*/
- private void complete(Annotate.AnnotateRepeatedContext ctx) {
- Assert.check(!pendingCompletion());
+ private void complete(Annotate.AnnotateRepeatedContext ctx) {
Log log = ctx.log;
Env env = ctx.env;
JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
try {
+ // TODO: can we reduce duplication in the following branches?
+ if (ctx.isTypeCompound) {
+ Assert.check(!isTypesEmpty());
- if (isEmpty()) {
- return;
+ if (isTypesEmpty()) {
+ return;
+ }
+
+ List result = List.nil();
+ for (Attribute.TypeCompound a : getTypeAttributes()) {
+ if (a instanceof Placeholder) {
+ @SuppressWarnings("unchecked")
+ Placeholder ph = (Placeholder) a;
+ Attribute.TypeCompound replacement = replaceOne(ph, ph.getRepeatedContext());
+
+ if (null != replacement) {
+ result = result.prepend(replacement);
+ }
+ } else {
+ result = result.prepend(a);
+ }
+ }
+
+ type_attributes = result.reverse();
+
+ Assert.check(Annotations.this.getTypePlaceholders().isEmpty());
+ } else {
+ Assert.check(!pendingCompletion());
+
+ if (isEmpty()) {
+ return;
+ }
+
+ List result = List.nil();
+ for (Attribute.Compound a : getDeclarationAttributes()) {
+ if (a instanceof Placeholder) {
+ @SuppressWarnings("unchecked")
+ Attribute.Compound replacement = replaceOne((Placeholder) a, ctx);
+
+ if (null != replacement) {
+ result = result.prepend(replacement);
+ }
+ } else {
+ result = result.prepend(a);
+ }
+ }
+
+ attributes = result.reverse();
+
+ Assert.check(Annotations.this.getPlaceholders().isEmpty());
}
-
- List result = List.nil();
- for (Attribute.Compound a : getAttributes()) {
- if (a instanceof Placeholder) {
- Attribute.Compound replacement = replaceOne((Placeholder) a, ctx);
-
- if (null != replacement) {
- result = result.prepend(replacement);
- }
- } else {
- result = result.prepend(a);
- }
- }
-
- attributes = result.reverse();
-
- Assert.check(Annotations.this.getPlaceholders().isEmpty());
} finally {
log.useSource(oldSource);
}
}
- private Attribute.Compound replaceOne(Placeholder placeholder, Annotate.AnnotateRepeatedContext ctx) {
+ private T replaceOne(Placeholder placeholder, Annotate.AnnotateRepeatedContext ctx) {
Log log = ctx.log;
// Process repeated annotations
- Attribute.Compound validRepeated =
- ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym);
+ T validRepeated = ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym);
if (validRepeated != null) {
// Check that the container isn't manually
// present along with repeated instances of
// its contained annotation.
- ListBuffer manualContainer = ctx.annotated.get(validRepeated.type.tsym);
+ ListBuffer manualContainer = ctx.annotated.get(validRepeated.type.tsym);
if (manualContainer != null) {
log.error(ctx.pos.get(manualContainer.first()), "invalid.repeatable.annotation.repeated.and.container.present",
manualContainer.first().type.tsym);
@@ -268,16 +358,20 @@
// A null return will delete the Placeholder
return validRepeated;
-
}
- private static class Placeholder extends Attribute.Compound {
+ private static class Placeholder extends Attribute.TypeCompound {
- private List placeholderFor;
- private Symbol on;
+ private final Annotate.AnnotateRepeatedContext ctx;
+ private final List placeholderFor;
+ private final Symbol on;
- public Placeholder(List placeholderFor, Symbol on) {
- super(Type.noType, List.>nil());
+ public Placeholder(Annotate.AnnotateRepeatedContext ctx, List placeholderFor, Symbol on) {
+ super(on.type, List.>nil(),
+ ctx.isTypeCompound ?
+ ((Attribute.TypeCompound)placeholderFor.head).position :
+ null);
+ this.ctx = ctx;
this.placeholderFor = placeholderFor;
this.on = on;
}
@@ -287,8 +381,12 @@
return "";
}
- public List getPlaceholderFor() {
+ public List getPlaceholderFor() {
return placeholderFor;
}
+
+ public Annotate.AnnotateRepeatedContext getRepeatedContext() {
+ return ctx;
+ }
}
}