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 |