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