src/share/classes/com/sun/tools/javac/comp/Annotate.java

changeset 1521
71f35e4b93a5
parent 1492
df694c775e8a
child 1629
f427043f8c65
equal deleted inserted replaced
1520:5c956be64b9e 1521:71f35e4b93a5
24 */ 24 */
25 25
26 package com.sun.tools.javac.comp; 26 package com.sun.tools.javac.comp;
27 27
28 import java.util.Map; 28 import java.util.Map;
29
29 import com.sun.tools.javac.util.*; 30 import com.sun.tools.javac.util.*;
30 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 31 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
31 import com.sun.tools.javac.code.*; 32 import com.sun.tools.javac.code.*;
32 import com.sun.tools.javac.code.Symbol.*; 33 import com.sun.tools.javac.code.Symbol.*;
33 import com.sun.tools.javac.tree.*; 34 import com.sun.tools.javac.tree.*;
85 *********************************************************************/ 86 *********************************************************************/
86 87
87 private int enterCount = 0; 88 private int enterCount = 0;
88 89
89 ListBuffer<Annotator> q = new ListBuffer<Annotator>(); 90 ListBuffer<Annotator> q = new ListBuffer<Annotator>();
91 ListBuffer<Annotator> typesQ = new ListBuffer<Annotator>();
90 ListBuffer<Annotator> repeatedQ = new ListBuffer<Annotator>(); 92 ListBuffer<Annotator> repeatedQ = new ListBuffer<Annotator>();
93 ListBuffer<Annotator> afterRepeatedQ = new ListBuffer<Annotator>();
94
95 public void earlier(Annotator a) {
96 q.prepend(a);
97 }
91 98
92 public void normal(Annotator a) { 99 public void normal(Annotator a) {
93 q.append(a); 100 q.append(a);
94 } 101 }
95 102
96 public void earlier(Annotator a) { 103 public void typeAnnotation(Annotator a) {
97 q.prepend(a); 104 typesQ.append(a);
98 } 105 }
99 106
100 public void repeated(Annotator a) { 107 public void repeated(Annotator a) {
101 repeatedQ.append(a); 108 repeatedQ.append(a);
109 }
110
111 public void afterRepeated(Annotator a) {
112 afterRepeatedQ.append(a);
102 } 113 }
103 114
104 /** Called when the Enter phase starts. */ 115 /** Called when the Enter phase starts. */
105 public void enterStart() { 116 public void enterStart() {
106 enterCount++; 117 enterCount++;
114 125
115 public void flush() { 126 public void flush() {
116 if (enterCount != 0) return; 127 if (enterCount != 0) return;
117 enterCount++; 128 enterCount++;
118 try { 129 try {
119 while (q.nonEmpty()) 130 while (q.nonEmpty()) {
120 q.next().enterAnnotation(); 131 q.next().enterAnnotation();
121 132 }
133 while (typesQ.nonEmpty()) {
134 typesQ.next().enterAnnotation();
135 }
122 while (repeatedQ.nonEmpty()) { 136 while (repeatedQ.nonEmpty()) {
123 repeatedQ.next().enterAnnotation(); 137 repeatedQ.next().enterAnnotation();
138 }
139 while (afterRepeatedQ.nonEmpty()) {
140 afterRepeatedQ.next().enterAnnotation();
124 } 141 }
125 } finally { 142 } finally {
126 enterCount--; 143 enterCount--;
127 } 144 }
128 } 145 }
139 156
140 /** 157 /**
141 * This context contains all the information needed to synthesize new 158 * This context contains all the information needed to synthesize new
142 * annotations trees by the completer for repeating annotations. 159 * annotations trees by the completer for repeating annotations.
143 */ 160 */
144 public class AnnotateRepeatedContext { 161 public class AnnotateRepeatedContext<T extends Attribute.Compound> {
145 public final Env<AttrContext> env; 162 public final Env<AttrContext> env;
146 public final Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated; 163 public final Map<Symbol.TypeSymbol, ListBuffer<T>> annotated;
147 public final Map<Attribute.Compound, JCDiagnostic.DiagnosticPosition> pos; 164 public final Map<T, JCDiagnostic.DiagnosticPosition> pos;
148 public final Log log; 165 public final Log log;
166 public final boolean isTypeCompound;
149 167
150 public AnnotateRepeatedContext(Env<AttrContext> env, 168 public AnnotateRepeatedContext(Env<AttrContext> env,
151 Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated, 169 Map<Symbol.TypeSymbol, ListBuffer<T>> annotated,
152 Map<Attribute.Compound, JCDiagnostic.DiagnosticPosition> pos, 170 Map<T, JCDiagnostic.DiagnosticPosition> pos,
153 Log log) { 171 Log log,
172 boolean isTypeCompound) {
154 Assert.checkNonNull(env); 173 Assert.checkNonNull(env);
155 Assert.checkNonNull(annotated); 174 Assert.checkNonNull(annotated);
156 Assert.checkNonNull(pos); 175 Assert.checkNonNull(pos);
157 Assert.checkNonNull(log); 176 Assert.checkNonNull(log);
158 177
159 this.env = env; 178 this.env = env;
160 this.annotated = annotated; 179 this.annotated = annotated;
161 this.pos = pos; 180 this.pos = pos;
162 this.log = log; 181 this.log = log;
182 this.isTypeCompound = isTypeCompound;
163 } 183 }
164 184
165 /** 185 /**
166 * Process a list of repeating annotations returning a new 186 * Process a list of repeating annotations returning a new
167 * Attribute.Compound that is the attribute for the synthesized tree 187 * Attribute.Compound that is the attribute for the synthesized tree
168 * for the container. 188 * for the container.
169 * 189 *
170 * @param repeatingAnnotations a List of repeating annotations 190 * @param repeatingAnnotations a List of repeating annotations
171 * @return a new Attribute.Compound that is the container for the repeatingAnnotations 191 * @return a new Attribute.Compound that is the container for the repeatingAnnotations
172 */ 192 */
173 public Attribute.Compound processRepeatedAnnotations(List<Attribute.Compound> repeatingAnnotations, Symbol sym) { 193 public T processRepeatedAnnotations(List<T> repeatingAnnotations, Symbol sym) {
174 return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this, sym); 194 return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this, sym);
175 } 195 }
176 196
177 /** 197 /**
178 * Queue the Annotator a on the repeating annotations queue of the 198 * Queue the Annotator a on the repeating annotations queue of the
244 if (!method.type.isErroneous()) 264 if (!method.type.isErroneous())
245 buf.append(new Pair<MethodSymbol,Attribute> 265 buf.append(new Pair<MethodSymbol,Attribute>
246 ((MethodSymbol)method, value)); 266 ((MethodSymbol)method, value));
247 t.type = result; 267 t.type = result;
248 } 268 }
249 return new Attribute.Compound(a.type, buf.toList()); 269 // TODO: this should be a TypeCompound if "a" is a JCTypeAnnotation.
270 // However, how do we find the correct position?
271 Attribute.Compound ac = new Attribute.Compound(a.type, buf.toList());
272 // TODO: is this something we want? Who would use it?
273 // a.attribute = ac;
274 return ac;
250 } 275 }
251 276
252 Attribute enterAttributeValue(Type expected, 277 Attribute enterAttributeValue(Type expected,
253 JCExpression tree, 278 JCExpression tree,
254 Env<AttrContext> env) { 279 Env<AttrContext> env) {
327 if (!expected.isErroneous()) 352 if (!expected.isErroneous())
328 log.error(tree.pos(), "annotation.value.not.allowable.type"); 353 log.error(tree.pos(), "annotation.value.not.allowable.type");
329 return new Attribute.Error(attr.attribExpr(tree, env, expected)); 354 return new Attribute.Error(attr.attribExpr(tree, env, expected));
330 } 355 }
331 356
357 Attribute.TypeCompound enterTypeAnnotation(JCAnnotation a,
358 Type expected,
359 Env<AttrContext> env) {
360 Attribute.Compound c = enterAnnotation(a, expected, env);
361 Attribute.TypeCompound tc = new Attribute.TypeCompound(c.type, c.values, new TypeAnnotationPosition());
362 a.attribute = tc;
363 return tc;
364 }
365
332 /* ********************************* 366 /* *********************************
333 * Support for repeating annotations 367 * Support for repeating annotations
334 ***********************************/ 368 ***********************************/
335 369
336 /* Process repeated annotations. This method returns the 370 /* Process repeated annotations. This method returns the
337 * synthesized container annotation or null IFF all repeating 371 * synthesized container annotation or null IFF all repeating
338 * annotation are invalid. This method reports errors/warnings. 372 * annotation are invalid. This method reports errors/warnings.
339 */ 373 */
340 private Attribute.Compound processRepeatedAnnotations(List<Attribute.Compound> annotations, 374 private <T extends Attribute.Compound> T processRepeatedAnnotations(List<T> annotations,
341 AnnotateRepeatedContext ctx, 375 AnnotateRepeatedContext<T> ctx,
342 Symbol on) { 376 Symbol on) {
343 Attribute.Compound firstOccurrence = annotations.head; 377 T firstOccurrence = annotations.head;
344 List<Attribute> repeated = List.nil(); 378 List<Attribute> repeated = List.nil();
345 Type origAnnoType = null; 379 Type origAnnoType = null;
346 Type arrayOfOrigAnnoType = null; 380 Type arrayOfOrigAnnoType = null;
347 Type targetContainerType = null; 381 Type targetContainerType = null;
348 MethodSymbol containerValueSymbol = null; 382 MethodSymbol containerValueSymbol = null;
349 383
350 Assert.check(!annotations.isEmpty() && 384 Assert.check(!annotations.isEmpty() &&
351 !annotations.tail.isEmpty()); // i.e. size() > 1 385 !annotations.tail.isEmpty()); // i.e. size() > 1
352 386
353 for (List<Attribute.Compound> al = annotations; 387 for (List<T> al = annotations;
354 !al.isEmpty(); 388 !al.isEmpty();
355 al = al.tail) 389 al = al.tail)
356 { 390 {
357 Attribute.Compound currentAnno = al.head; 391 T currentAnno = al.head;
358 392
359 origAnnoType = currentAnno.type; 393 origAnnoType = currentAnno.type;
360 if (arrayOfOrigAnnoType == null) { 394 if (arrayOfOrigAnnoType == null) {
361 arrayOfOrigAnnoType = types.makeArrayType(origAnnoType); 395 arrayOfOrigAnnoType = types.makeArrayType(origAnnoType);
362 } 396 }
363 397
364 Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno)); 398 Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno));
365 if (currentContainerType == null) { 399 if (currentContainerType == null) {
366 continue; 400 continue;
367 } 401 }
381 repeated = repeated.prepend(currentAnno); 415 repeated = repeated.prepend(currentAnno);
382 } 416 }
383 417
384 if (!repeated.isEmpty()) { 418 if (!repeated.isEmpty()) {
385 repeated = repeated.reverse(); 419 repeated = repeated.reverse();
386 JCAnnotation annoTree;
387 TreeMaker m = make.at(ctx.pos.get(firstOccurrence)); 420 TreeMaker m = make.at(ctx.pos.get(firstOccurrence));
388 Pair<MethodSymbol, Attribute> p = 421 Pair<MethodSymbol, Attribute> p =
389 new Pair<MethodSymbol, Attribute>(containerValueSymbol, 422 new Pair<MethodSymbol, Attribute>(containerValueSymbol,
390 new Attribute.Array(arrayOfOrigAnnoType, repeated)); 423 new Attribute.Array(arrayOfOrigAnnoType, repeated));
391 annoTree = m.Annotation(new Attribute.Compound(targetContainerType, 424 if (ctx.isTypeCompound) {
392 List.of(p))); 425 /* TODO: the following code would be cleaner:
393 426 Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
394 if (!chk.annotationApplicable(annoTree, on)) 427 ((Attribute.TypeCompound)annotations.head).position);
395 log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType); 428 JCTypeAnnotation annoTree = m.TypeAnnotation(at);
396 429 at = enterTypeAnnotation(annoTree, targetContainerType, ctx.env);
397 if (!chk.validateAnnotationDeferErrors(annoTree)) 430 */
398 log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType); 431 // However, we directly construct the TypeCompound to keep the
399 432 // direct relation to the contained TypeCompounds.
400 Attribute.Compound c = enterAnnotation(annoTree, 433 Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
401 targetContainerType, 434 ((Attribute.TypeCompound)annotations.head).position);
402 ctx.env); 435
403 c.setSynthesized(true); 436 // TODO: annotation applicability checks from below?
404 return c; 437
438 at.setSynthesized(true);
439
440 @SuppressWarnings("unchecked")
441 T x = (T) at;
442 return x;
443 } else {
444 Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p));
445 JCAnnotation annoTree = m.Annotation(c);
446
447 if (!chk.annotationApplicable(annoTree, on))
448 log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType);
449
450 if (!chk.validateAnnotationDeferErrors(annoTree))
451 log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType);
452
453 c = enterAnnotation(annoTree, targetContainerType, ctx.env);
454 c.setSynthesized(true);
455
456 @SuppressWarnings("unchecked")
457 T x = (T) c;
458 return x;
459 }
405 } else { 460 } else {
406 return null; // errors should have been reported elsewhere 461 return null; // errors should have been reported elsewhere
407 } 462 }
408 } 463 }
409 464

mercurial