1.1 --- a/src/share/classes/com/sun/tools/javac/code/Annotations.java Wed Jan 23 20:57:40 2013 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Annotations.java Wed Jan 23 13:27:24 2013 -0800 1.3 @@ -48,7 +48,7 @@ 1.4 * 1.5 * An instance of this class can be in one of three states: 1.6 * 1.7 - * NOT_STARTED indicates that the Symbol this instance belongs to have not been 1.8 + * NOT_STARTED indicates that the Symbol this instance belongs to has not been 1.9 * annotated (yet). Specifically if the declaration is not annotated this 1.10 * instance will never move past NOT_STARTED. You can never go back to 1.11 * NOT_STARTED. 1.12 @@ -59,7 +59,7 @@ 1.13 * 1.14 * "unnamed" this Annotations contains some attributes, possibly the final set. 1.15 * While in this state you can only prepend or append to the attributes not set 1.16 - * it directly. You can also move back to the IN_PROGRESS sate using reset(). 1.17 + * it directly. You can also move back to the IN_PROGRESS state using reset(). 1.18 * 1.19 * <p><b>This is NOT part of any supported API. If you write code that depends 1.20 * on this, you do so at your own risk. This code and its internal interfaces 1.21 @@ -67,14 +67,21 @@ 1.22 */ 1.23 public class Annotations { 1.24 1.25 - private static final List<Attribute.Compound> NOT_STARTED = List.of(null); 1.26 - private static final List<Attribute.Compound> IN_PROGRESS = List.of(null); 1.27 + private static final List<Attribute.Compound> DECL_NOT_STARTED = List.of(null); 1.28 + private static final List<Attribute.Compound> DECL_IN_PROGRESS = List.of(null); 1.29 + 1.30 /* 1.31 * This field should never be null 1.32 */ 1.33 - private List<Attribute.Compound> attributes = NOT_STARTED; 1.34 + private List<Attribute.Compound> attributes = DECL_NOT_STARTED; 1.35 + 1.36 /* 1.37 - * The Symbol this Annotations belong to 1.38 + * This field should never be null 1.39 + */ 1.40 + private List<Attribute.TypeCompound> type_attributes = List.<Attribute.TypeCompound>nil(); 1.41 + 1.42 + /* 1.43 + * The Symbol this Annotations instance belongs to 1.44 */ 1.45 private final Symbol sym; 1.46 1.47 @@ -82,11 +89,15 @@ 1.48 this.sym = sym; 1.49 } 1.50 1.51 - public List<Attribute.Compound> getAttributes() { 1.52 - return filterSentinels(attributes); 1.53 + public List<Attribute.Compound> getDeclarationAttributes() { 1.54 + return filterDeclSentinels(attributes); 1.55 } 1.56 1.57 - public void setAttributes(List<Attribute.Compound> a) { 1.58 + public List<Attribute.TypeCompound> getTypeAttributes() { 1.59 + return type_attributes; 1.60 + } 1.61 + 1.62 + public void setDeclarationAttributes(List<Attribute.Compound> a) { 1.63 Assert.check(pendingCompletion() || !isStarted()); 1.64 if (a == null) { 1.65 throw new NullPointerException(); 1.66 @@ -94,31 +105,51 @@ 1.67 attributes = a; 1.68 } 1.69 1.70 + public void setTypeAttributes(List<Attribute.TypeCompound> a) { 1.71 + if (a == null) { 1.72 + throw new NullPointerException(); 1.73 + } 1.74 + type_attributes = a; 1.75 + } 1.76 + 1.77 public void setAttributes(Annotations other) { 1.78 if (other == null) { 1.79 throw new NullPointerException(); 1.80 } 1.81 - setAttributes(other.getAttributes()); 1.82 + setDeclarationAttributes(other.getDeclarationAttributes()); 1.83 + setTypeAttributes(other.getTypeAttributes()); 1.84 } 1.85 1.86 - public void setAttributesWithCompletion(final Annotate.AnnotateRepeatedContext ctx) { 1.87 + public void setDeclarationAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.Compound> ctx) { 1.88 Assert.check(pendingCompletion() || (!isStarted() && sym.kind == PCK)); 1.89 + this.setDeclarationAttributes(getAttributesForCompletion(ctx)); 1.90 + } 1.91 1.92 - Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated = ctx.annotated; 1.93 + public void appendTypeAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.TypeCompound> ctx) { 1.94 + this.appendUniqueTypes(getAttributesForCompletion(ctx)); 1.95 + } 1.96 + 1.97 + private <T extends Attribute.Compound> List<T> getAttributesForCompletion( 1.98 + final Annotate.AnnotateRepeatedContext<T> ctx) { 1.99 + 1.100 + Map<Symbol.TypeSymbol, ListBuffer<T>> annotated = ctx.annotated; 1.101 boolean atLeastOneRepeated = false; 1.102 - List<Attribute.Compound> buf = List.<Attribute.Compound>nil(); 1.103 - for (ListBuffer<Attribute.Compound> lb : annotated.values()) { 1.104 + List<T> buf = List.<T>nil(); 1.105 + for (ListBuffer<T> lb : annotated.values()) { 1.106 if (lb.size() == 1) { 1.107 buf = buf.prepend(lb.first()); 1.108 } else { // repeated 1.109 - buf = buf.prepend(new Placeholder(lb.toList(), sym)); 1.110 + // This will break when other subtypes of Attributs.Compound 1.111 + // are introduced, because PlaceHolder is a subtype of TypeCompound. 1.112 + T res; 1.113 + @SuppressWarnings("unchecked") 1.114 + T ph = (T) new Placeholder<T>(ctx, lb.toList(), sym); 1.115 + res = ph; 1.116 + buf = buf.prepend(res); 1.117 atLeastOneRepeated = true; 1.118 } 1.119 } 1.120 1.121 - // Add non-repeating attributes 1.122 - setAttributes(buf.reverse()); 1.123 - 1.124 if (atLeastOneRepeated) { 1.125 // The Symbol s is now annotated with a combination of 1.126 // finished non-repeating annotations and placeholders for 1.127 @@ -138,7 +169,6 @@ 1.128 // Queue a pass that will replace Attribute.Placeholders 1.129 // with Attribute.Compound (made from synthesized containers). 1.130 ctx.annotateRepeated(new Annotate.Annotator() { 1.131 - 1.132 @Override 1.133 public String toString() { 1.134 return "repeated annotation pass of: " + sym + " in: " + sym.owner; 1.135 @@ -150,10 +180,12 @@ 1.136 } 1.137 }); 1.138 } 1.139 + // Add non-repeating attributes 1.140 + return buf.reverse(); 1.141 } 1.142 1.143 public Annotations reset() { 1.144 - attributes = IN_PROGRESS; 1.145 + attributes = DECL_IN_PROGRESS; 1.146 return this; 1.147 } 1.148 1.149 @@ -163,12 +195,16 @@ 1.150 || attributes.isEmpty(); 1.151 } 1.152 1.153 + public boolean isTypesEmpty() { 1.154 + return type_attributes.isEmpty(); 1.155 + } 1.156 + 1.157 public boolean pendingCompletion() { 1.158 - return attributes == IN_PROGRESS; 1.159 + return attributes == DECL_IN_PROGRESS; 1.160 } 1.161 1.162 public Annotations append(List<Attribute.Compound> l) { 1.163 - attributes = filterSentinels(attributes); 1.164 + attributes = filterDeclSentinels(attributes); 1.165 1.166 if (l.isEmpty()) { 1.167 ; // no-op 1.168 @@ -180,8 +216,24 @@ 1.169 return this; 1.170 } 1.171 1.172 + public Annotations appendUniqueTypes(List<Attribute.TypeCompound> l) { 1.173 + if (l.isEmpty()) { 1.174 + ; // no-op 1.175 + } else if (type_attributes.isEmpty()) { 1.176 + type_attributes = l; 1.177 + } else { 1.178 + // TODO: in case we expect a large number of annotations, this 1.179 + // might be inefficient. 1.180 + for (Attribute.TypeCompound tc : l) { 1.181 + if (!type_attributes.contains(tc)) 1.182 + type_attributes = type_attributes.append(tc); 1.183 + } 1.184 + } 1.185 + return this; 1.186 + } 1.187 + 1.188 public Annotations prepend(List<Attribute.Compound> l) { 1.189 - attributes = filterSentinels(attributes); 1.190 + attributes = filterDeclSentinels(attributes); 1.191 1.192 if (l.isEmpty()) { 1.193 ; // no-op 1.194 @@ -193,19 +245,29 @@ 1.195 return this; 1.196 } 1.197 1.198 - private List<Attribute.Compound> filterSentinels(List<Attribute.Compound> a) { 1.199 - return (a == IN_PROGRESS || a == NOT_STARTED) 1.200 + private List<Attribute.Compound> filterDeclSentinels(List<Attribute.Compound> a) { 1.201 + return (a == DECL_IN_PROGRESS || a == DECL_NOT_STARTED) 1.202 ? List.<Attribute.Compound>nil() 1.203 : a; 1.204 } 1.205 1.206 private boolean isStarted() { 1.207 - return attributes != NOT_STARTED; 1.208 + return attributes != DECL_NOT_STARTED; 1.209 } 1.210 1.211 private List<Attribute.Compound> getPlaceholders() { 1.212 List<Attribute.Compound> res = List.<Attribute.Compound>nil(); 1.213 - for (Attribute.Compound a : filterSentinels(attributes)) { 1.214 + for (Attribute.Compound a : filterDeclSentinels(attributes)) { 1.215 + if (a instanceof Placeholder) { 1.216 + res = res.prepend(a); 1.217 + } 1.218 + } 1.219 + return res.reverse(); 1.220 + } 1.221 + 1.222 + private List<Attribute.TypeCompound> getTypePlaceholders() { 1.223 + List<Attribute.TypeCompound> res = List.<Attribute.TypeCompound>nil(); 1.224 + for (Attribute.TypeCompound a : type_attributes) { 1.225 if (a instanceof Placeholder) { 1.226 res = res.prepend(a); 1.227 } 1.228 @@ -216,50 +278,78 @@ 1.229 /* 1.230 * Replace Placeholders for repeating annotations with their containers 1.231 */ 1.232 - private void complete(Annotate.AnnotateRepeatedContext ctx) { 1.233 - Assert.check(!pendingCompletion()); 1.234 + private <T extends Attribute.Compound> void complete(Annotate.AnnotateRepeatedContext<T> ctx) { 1.235 Log log = ctx.log; 1.236 Env<AttrContext> env = ctx.env; 1.237 JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile); 1.238 try { 1.239 + // TODO: can we reduce duplication in the following branches? 1.240 + if (ctx.isTypeCompound) { 1.241 + Assert.check(!isTypesEmpty()); 1.242 1.243 - if (isEmpty()) { 1.244 - return; 1.245 + if (isTypesEmpty()) { 1.246 + return; 1.247 + } 1.248 + 1.249 + List<Attribute.TypeCompound> result = List.nil(); 1.250 + for (Attribute.TypeCompound a : getTypeAttributes()) { 1.251 + if (a instanceof Placeholder) { 1.252 + @SuppressWarnings("unchecked") 1.253 + Placeholder<Attribute.TypeCompound> ph = (Placeholder<Attribute.TypeCompound>) a; 1.254 + Attribute.TypeCompound replacement = replaceOne(ph, ph.getRepeatedContext()); 1.255 + 1.256 + if (null != replacement) { 1.257 + result = result.prepend(replacement); 1.258 + } 1.259 + } else { 1.260 + result = result.prepend(a); 1.261 + } 1.262 + } 1.263 + 1.264 + type_attributes = result.reverse(); 1.265 + 1.266 + Assert.check(Annotations.this.getTypePlaceholders().isEmpty()); 1.267 + } else { 1.268 + Assert.check(!pendingCompletion()); 1.269 + 1.270 + if (isEmpty()) { 1.271 + return; 1.272 + } 1.273 + 1.274 + List<Attribute.Compound> result = List.nil(); 1.275 + for (Attribute.Compound a : getDeclarationAttributes()) { 1.276 + if (a instanceof Placeholder) { 1.277 + @SuppressWarnings("unchecked") 1.278 + Attribute.Compound replacement = replaceOne((Placeholder<T>) a, ctx); 1.279 + 1.280 + if (null != replacement) { 1.281 + result = result.prepend(replacement); 1.282 + } 1.283 + } else { 1.284 + result = result.prepend(a); 1.285 + } 1.286 + } 1.287 + 1.288 + attributes = result.reverse(); 1.289 + 1.290 + Assert.check(Annotations.this.getPlaceholders().isEmpty()); 1.291 } 1.292 - 1.293 - List<Attribute.Compound> result = List.nil(); 1.294 - for (Attribute.Compound a : getAttributes()) { 1.295 - if (a instanceof Placeholder) { 1.296 - Attribute.Compound replacement = replaceOne((Placeholder) a, ctx); 1.297 - 1.298 - if (null != replacement) { 1.299 - result = result.prepend(replacement); 1.300 - } 1.301 - } else { 1.302 - result = result.prepend(a); 1.303 - } 1.304 - } 1.305 - 1.306 - attributes = result.reverse(); 1.307 - 1.308 - Assert.check(Annotations.this.getPlaceholders().isEmpty()); 1.309 } finally { 1.310 log.useSource(oldSource); 1.311 } 1.312 } 1.313 1.314 - private Attribute.Compound replaceOne(Placeholder placeholder, Annotate.AnnotateRepeatedContext ctx) { 1.315 + private <T extends Attribute.Compound> T replaceOne(Placeholder<T> placeholder, Annotate.AnnotateRepeatedContext<T> ctx) { 1.316 Log log = ctx.log; 1.317 1.318 // Process repeated annotations 1.319 - Attribute.Compound validRepeated = 1.320 - ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym); 1.321 + T validRepeated = ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym); 1.322 1.323 if (validRepeated != null) { 1.324 // Check that the container isn't manually 1.325 // present along with repeated instances of 1.326 // its contained annotation. 1.327 - ListBuffer<Attribute.Compound> manualContainer = ctx.annotated.get(validRepeated.type.tsym); 1.328 + ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym); 1.329 if (manualContainer != null) { 1.330 log.error(ctx.pos.get(manualContainer.first()), "invalid.repeatable.annotation.repeated.and.container.present", 1.331 manualContainer.first().type.tsym); 1.332 @@ -268,16 +358,20 @@ 1.333 1.334 // A null return will delete the Placeholder 1.335 return validRepeated; 1.336 - 1.337 } 1.338 1.339 - private static class Placeholder extends Attribute.Compound { 1.340 + private static class Placeholder<T extends Attribute.Compound> extends Attribute.TypeCompound { 1.341 1.342 - private List<Attribute.Compound> placeholderFor; 1.343 - private Symbol on; 1.344 + private final Annotate.AnnotateRepeatedContext<T> ctx; 1.345 + private final List<T> placeholderFor; 1.346 + private final Symbol on; 1.347 1.348 - public Placeholder(List<Attribute.Compound> placeholderFor, Symbol on) { 1.349 - super(Type.noType, List.<Pair<Symbol.MethodSymbol, Attribute>>nil()); 1.350 + public Placeholder(Annotate.AnnotateRepeatedContext<T> ctx, List<T> placeholderFor, Symbol on) { 1.351 + super(on.type, List.<Pair<Symbol.MethodSymbol, Attribute>>nil(), 1.352 + ctx.isTypeCompound ? 1.353 + ((Attribute.TypeCompound)placeholderFor.head).position : 1.354 + null); 1.355 + this.ctx = ctx; 1.356 this.placeholderFor = placeholderFor; 1.357 this.on = on; 1.358 } 1.359 @@ -287,8 +381,12 @@ 1.360 return "<placeholder: " + placeholderFor + " on: " + on + ">"; 1.361 } 1.362 1.363 - public List<Attribute.Compound> getPlaceholderFor() { 1.364 + public List<T> getPlaceholderFor() { 1.365 return placeholderFor; 1.366 } 1.367 + 1.368 + public Annotate.AnnotateRepeatedContext<T> getRepeatedContext() { 1.369 + return ctx; 1.370 + } 1.371 } 1.372 }