1 /*
2 * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.comp;
27
28 import com.sun.tools.javac.code.*;
29 import com.sun.tools.javac.code.Attribute.Compound;
30 import com.sun.tools.javac.code.Attribute.TypeCompound;
31 import com.sun.tools.javac.code.Kinds.KindSelector;
32 import com.sun.tools.javac.code.Scope.WriteableScope;
33 import com.sun.tools.javac.code.Source.Feature;
34 import com.sun.tools.javac.code.Symbol.*;
35 import com.sun.tools.javac.code.TypeMetadata.Annotations;
36 import com.sun.tools.javac.comp.Check.CheckContext;
37 import com.sun.tools.javac.resources.CompilerProperties.Errors;
38 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
39 import com.sun.tools.javac.tree.JCTree;
40 import com.sun.tools.javac.tree.JCTree.*;
41 import com.sun.tools.javac.tree.TreeInfo;
42 import com.sun.tools.javac.tree.TreeMaker;
43 import com.sun.tools.javac.tree.TreeScanner;
44 import com.sun.tools.javac.util.*;
45 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
46 import com.sun.tools.javac.util.List;
47
48 import javax.tools.JavaFileObject;
49
50 import java.util.*;
51
52 import static com.sun.tools.javac.code.Flags.SYNTHETIC;
53 import static com.sun.tools.javac.code.Kinds.Kind.MDL;
54 import static com.sun.tools.javac.code.Kinds.Kind.MTH;
55 import static com.sun.tools.javac.code.Kinds.Kind.PCK;
56 import static com.sun.tools.javac.code.Kinds.Kind.TYP;
57 import static com.sun.tools.javac.code.Kinds.Kind.VAR;
58 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
59 import static com.sun.tools.javac.code.TypeTag.ARRAY;
60 import static com.sun.tools.javac.code.TypeTag.CLASS;
61 import static com.sun.tools.javac.tree.JCTree.Tag.ANNOTATION;
62 import static com.sun.tools.javac.tree.JCTree.Tag.ASSIGN;
63 import static com.sun.tools.javac.tree.JCTree.Tag.IDENT;
64 import static com.sun.tools.javac.tree.JCTree.Tag.NEWARRAY;
65
66 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
67
68
69 /** Enter annotations onto symbols and types (and trees).
70 *
71 * This is also a pseudo stage in the compiler taking care of scheduling when annotations are
72 * entered.
73 *
74 * <p><b>This is NOT part of any supported API.
75 * If you write code that depends on this, you do so at your own risk.
76 * This code and its internal interfaces are subject to change or
77 * deletion without notice.</b>
78 */
79 public class Annotate {
80 protected static final Context.Key<Annotate> annotateKey = new Context.Key<>();
81
82 public static Annotate instance(Context context) {
83 Annotate instance = context.get(annotateKey);
84 if (instance == null)
85 instance = new Annotate(context);
86 return instance;
87 }
88
89 private final Attr attr;
90 private final Check chk;
91 private final ConstFold cfolder;
92 private final Enter enter;
93 private final Log log;
94 private final Names names;
95 private final Resolve resolve;
96 private final TreeMaker make;
97 private final Symtab syms;
98 private final TypeEnvs typeEnvs;
99 private final Types types;
100
101 private final Attribute theUnfinishedDefaultValue;
102 private final String sourceName;
103
104 @SuppressWarnings("this-escape")
105 protected Annotate(Context context) {
106 context.put(annotateKey, this);
107
108 attr = Attr.instance(context);
109 chk = Check.instance(context);
110 cfolder = ConstFold.instance(context);
111 enter = Enter.instance(context);
112 log = Log.instance(context);
113 make = TreeMaker.instance(context);
114 names = Names.instance(context);
115 resolve = Resolve.instance(context);
116 syms = Symtab.instance(context);
117 typeEnvs = TypeEnvs.instance(context);
118 types = Types.instance(context);
119
120 theUnfinishedDefaultValue = new Attribute.Error(syms.errType);
121
122 Source source = Source.instance(context);
123 sourceName = source.name;
124
125 blockCount = 1;
126 }
127
128 /** Semaphore to delay annotation processing */
129 private int blockCount = 0;
130
131 /** Called when annotations processing needs to be postponed. */
132 public void blockAnnotations() {
133 blockCount++;
134 }
135
136 /** Called when annotation processing can be resumed. */
137 public void unblockAnnotations() {
138 blockCount--;
139 if (blockCount == 0)
140 flush();
141 }
142
143 /** Variant which allows for a delayed flush of annotations.
144 * Needed by ClassReader */
145 public void unblockAnnotationsNoFlush() {
146 blockCount--;
147 }
148
149 /** are we blocking annotation processing? */
150 public boolean annotationsBlocked() {return blockCount > 0; }
151
152 public void enterDone() {
153 unblockAnnotations();
154 }
155
156 public List<TypeCompound> fromAnnotations(List<JCAnnotation> annotations) {
157 if (annotations.isEmpty()) {
158 return List.nil();
159 }
160
161 ListBuffer<TypeCompound> buf = new ListBuffer<>();
162 for (JCAnnotation anno : annotations) {
163 Assert.checkNonNull(anno.attribute);
164 buf.append((TypeCompound) anno.attribute);
165 }
166 return buf.toList();
167 }
168
169 /** Annotate (used for everything else) */
170 public void normal(Runnable r) {
171 q.append(r);
172 }
173
174 /** Validate, triggers after 'normal' */
175 public void validate(Runnable a) {
176 validateQ.append(a);
177 }
178
179 /** Flush all annotation queues */
180 public void flush() {
181 if (annotationsBlocked()) return;
182 if (isFlushing()) return;
183
184 startFlushing();
185 try {
186 while (q.nonEmpty() ||
187 typesQ.nonEmpty() ||
188 afterTypesQ.nonEmpty() ||
189 validateQ.nonEmpty()) {
190 while (q.nonEmpty()) {
191 q.next().run();
192 }
193 while (typesQ.nonEmpty()) {
194 typesQ.next().run();
195 }
196 while (afterTypesQ.nonEmpty()) {
197 afterTypesQ.next().run();
198 }
199 while (validateQ.nonEmpty()) {
200 validateQ.next().run();
201 }
202 }
203 } finally {
204 doneFlushing();
205 }
206 }
207
208 private ListBuffer<Runnable> q = new ListBuffer<>();
209 private ListBuffer<Runnable> validateQ = new ListBuffer<>();
210
211 private int flushCount = 0;
212 private boolean isFlushing() { return flushCount > 0; }
213 private void startFlushing() { flushCount++; }
214 private void doneFlushing() { flushCount--; }
215
216 ListBuffer<Runnable> typesQ = new ListBuffer<>();
217 ListBuffer<Runnable> afterTypesQ = new ListBuffer<>();
218
219
220 public void typeAnnotation(Runnable a) {
221 typesQ.append(a);
222 }
223
224 public void afterTypes(Runnable a) {
225 afterTypesQ.append(a);
226 }
227
228 /**
229 * Queue annotations for later attribution and entering. This is probably the method you are looking for.
230 *
231 * @param annotations the list of JCAnnotations to attribute and enter
232 * @param localEnv the enclosing env
233 * @param s the Symbol on which to enter the annotations
234 */
235 public void annotateLater(List<JCAnnotation> annotations, Env<AttrContext> localEnv, Symbol s)
236 {
237 if (annotations.isEmpty()) {
238 return;
239 }
240
241 s.resetAnnotations(); // mark Annotations as incomplete for now
242
243 normal(() -> {
244 // Packages are unusual, in that they are the only type of declaration that can legally appear
245 // more than once in a compilation, and in all cases refer to the same underlying symbol.
246 // This means they are the only kind of declaration that syntactically may have multiple sets
247 // of annotations, each on a different package declaration, even though that is ultimately
248 // forbidden by JLS 8 section 7.4.
249 // The corollary here is that all of the annotations on a package symbol may have already
250 // been handled, meaning that the set of annotations pending completion is now empty.
251 Assert.check(s.kind == PCK || s.annotationsPendingCompletion());
252 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
253 try {
254 if (s.hasAnnotations() && annotations.nonEmpty())
255 log.error(annotations.head.pos, Errors.AlreadyAnnotated(Kinds.kindName(s), s));
256
257 Assert.checkNonNull(s, "Symbol argument to actualEnterAnnotations is null");
258
259 // false is passed as fifth parameter since annotateLater is
260 // never called for a type parameter
261 annotateNow(s, annotations, localEnv, false, false);
262 } finally {
263 log.useSource(prev);
264 }
265 });
266
267 validate(() -> { //validate annotations
268 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
269 try {
270 chk.validateAnnotations(annotations, TreeInfo.declarationFor(s, localEnv.tree), s);
271 } finally {
272 log.useSource(prev);
273 }
274 });
275 }
276
277
278 /** Queue processing of an attribute default value. */
279 public void annotateDefaultValueLater(JCExpression defaultValue, Env<AttrContext> localEnv, MethodSymbol m)
280 {
281 normal(() -> {
282 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
283 try {
284 enterDefaultValue(defaultValue, localEnv, m);
285 } finally {
286 log.useSource(prev);
287 }
288 });
289
290 validate(() -> { //validate annotations
291 JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
292 try {
293 // if default value is an annotation, check it is a well-formed
294 // annotation value (e.g. no duplicate values, no missing values, etc.)
295 chk.validateAnnotationTree(defaultValue);
296 } finally {
297 log.useSource(prev);
298 }
299 });
300 }
301
302 /** Enter a default value for an annotation element. */
303 private void enterDefaultValue(JCExpression defaultValue,
304 Env<AttrContext> localEnv, MethodSymbol m) {
305 m.defaultValue = attributeAnnotationValue(m.type.getReturnType(), defaultValue, localEnv);
306 }
307
308 /**
309 * Gather up annotations into a map from type symbols to lists of Compound attributes,
310 * then continue on with repeating annotations processing.
311 */
312 private <T extends Attribute.Compound> void annotateNow(Symbol toAnnotate,
313 List<JCAnnotation> withAnnotations, Env<AttrContext> env, boolean typeAnnotations,
314 boolean isTypeParam)
315 {
316 Map<TypeSymbol, ListBuffer<T>> annotated = new LinkedHashMap<>();
317 Map<T, DiagnosticPosition> pos = new HashMap<>();
318
319 for (List<JCAnnotation> al = withAnnotations; !al.isEmpty(); al = al.tail) {
320 JCAnnotation a = al.head;
321
322 T c;
323 if (typeAnnotations) {
324 @SuppressWarnings("unchecked")
325 T tmp = (T)attributeTypeAnnotation(a, syms.annotationType, env);
326 c = tmp;
327 } else {
328 @SuppressWarnings("unchecked")
329 T tmp = (T)attributeAnnotation(a, syms.annotationType, env);
330 c = tmp;
331 }
332
333 Assert.checkNonNull(c, "Failed to create annotation");
334
335 if (env.info.isAnonymousNewClass) {
336 // Annotations on anonymous class instantiations should be attributed,
337 // but not attached to the enclosing element. They will be visited
338 // separately and attached to the synthetic class declaration.
339 continue;
340 }
341
342 if (a.type.isErroneous() || a.type.tsym.isAnnotationType()) {
343 if (annotated.containsKey(a.type.tsym)) {
344 ListBuffer<T> l = annotated.get(a.type.tsym);
345 l = l.append(c);
346 annotated.put(a.type.tsym, l);
347 pos.put(c, a.pos());
348 } else {
349 annotated.put(a.type.tsym, ListBuffer.of(c));
350 pos.put(c, a.pos());
351 }
352 }
353
354 // Note: @Deprecated has no effect on local variables and parameters
355 if (!c.type.isErroneous()
356 && (toAnnotate.kind == MDL || toAnnotate.owner.kind != MTH)
357 && types.isSameType(c.type, syms.deprecatedType)) {
358 toAnnotate.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
359 if (isAttributeTrue(c.member(names.forRemoval))) {
360 toAnnotate.flags_field |= Flags.DEPRECATED_REMOVAL;
361 }
362 }
363
364 if (!c.type.isErroneous()
365 && types.isSameType(c.type, syms.previewFeatureType)) {
366 toAnnotate.flags_field |= Flags.PREVIEW_API;
367 if (isAttributeTrue(c.member(names.reflective))) {
368 toAnnotate.flags_field |= Flags.PREVIEW_REFLECTIVE;
369 }
370 }
371
372 if (!c.type.isErroneous()
373 && toAnnotate.kind == TYP
374 && types.isSameType(c.type, syms.valueBasedType)) {
375 toAnnotate.flags_field |= Flags.VALUE_BASED;
376 }
377
378 if (!c.type.isErroneous()
379 && types.isSameType(c.type, syms.restrictedType)) {
380 toAnnotate.flags_field |= Flags.RESTRICTED;
381 }
382
383 if (!c.type.isErroneous()
384 && toAnnotate.kind == VAR
385 && types.isSameType(c.type, syms.requiresIdentityType)) {
386 toAnnotate.flags_field |= Flags.REQUIRES_IDENTITY;
387 }
388 }
389
390 List<T> buf = List.nil();
391 for (ListBuffer<T> lb : annotated.values()) {
392 if (lb.size() == 1) {
393 buf = buf.prepend(lb.first());
394 } else {
395 AnnotationContext<T> ctx = new AnnotationContext<>(env, annotated, pos, typeAnnotations);
396 T res = makeContainerAnnotation(lb.toList(), ctx, toAnnotate, isTypeParam);
397 if (res != null)
398 buf = buf.prepend(res);
399 }
400 }
401
402 if (typeAnnotations) {
403 @SuppressWarnings("unchecked")
404 List<TypeCompound> attrs = (List<TypeCompound>)buf.reverse();
405 toAnnotate.appendUniqueTypeAttributes(attrs);
406 } else {
407 @SuppressWarnings("unchecked")
408 List<Attribute.Compound> attrs = (List<Attribute.Compound>)buf.reverse();
409 toAnnotate.resetAnnotations();
410 toAnnotate.setDeclarationAttributes(attrs);
411 }
412 }
413 //where:
414 private boolean isAttributeTrue(Attribute attr) {
415 return (attr instanceof Attribute.Constant constant)
416 && constant.type == syms.booleanType
417 && ((Integer) constant.value) != 0;
418 }
419
420 /**
421 * Attribute and store a semantic representation of the annotation tree {@code tree} into the
422 * tree.attribute field.
423 *
424 * @param tree the tree representing an annotation
425 * @param expectedAnnotationType the expected (super)type of the annotation
426 * @param env the current env in where the annotation instance is found
427 */
428 public Attribute.Compound attributeAnnotation(JCAnnotation tree, Type expectedAnnotationType,
429 Env<AttrContext> env)
430 {
431 // The attribute might have been entered if it is Target or Repeatable
432 // Because TreeCopier does not copy type, redo this if type is null
433 if (tree.attribute != null && tree.type != null)
434 return tree.attribute;
435
436 List<Pair<MethodSymbol, Attribute>> elems = attributeAnnotationValues(tree, expectedAnnotationType, env);
437 Attribute.Compound ac = new Attribute.Compound(tree.type, elems);
438
439 return tree.attribute = ac;
440 }
441
442 /** Attribute and store a semantic representation of the type annotation tree {@code tree} into
443 * the tree.attribute field.
444 *
445 * @param a the tree representing an annotation
446 * @param expectedAnnotationType the expected (super)type of the annotation
447 * @param env the current env in where the annotation instance is found
448 */
449 public Attribute.TypeCompound attributeTypeAnnotation(JCAnnotation a, Type expectedAnnotationType,
450 Env<AttrContext> env)
451 {
452 // The attribute might have been entered if it is Target or Repeatable
453 // Because TreeCopier does not copy type, redo this if type is null
454 if (a.attribute == null || a.type == null || !(a.attribute instanceof Attribute.TypeCompound typeCompound)) {
455 // Create a new TypeCompound
456 List<Pair<MethodSymbol,Attribute>> elems =
457 attributeAnnotationValues(a, expectedAnnotationType, env);
458
459 Attribute.TypeCompound tc =
460 new Attribute.TypeCompound(a.type, elems, TypeAnnotationPosition.unknown);
461 a.attribute = tc;
462 return tc;
463 } else {
464 // Use an existing TypeCompound
465 return typeCompound;
466 }
467 }
468
469 /**
470 * Attribute annotation elements creating a list of pairs of the Symbol representing that
471 * element and the value of that element as an Attribute. */
472 private List<Pair<MethodSymbol, Attribute>> attributeAnnotationValues(JCAnnotation a,
473 Type expected, Env<AttrContext> env)
474 {
475 // The annotation might have had its type attributed (but not
476 // checked) by attr.attribAnnotationTypes during MemberEnter,
477 // in which case we do not need to do it again.
478 Type at = (a.annotationType.type != null ?
479 a.annotationType.type : attr.attribType(a.annotationType, env));
480 a.type = chk.checkType(a.annotationType.pos(), at, expected);
481
482 boolean isError = a.type.isErroneous();
483 if (!a.type.tsym.isAnnotationType() && !isError) {
484 log.error(a.annotationType.pos(), Errors.NotAnnotationType(a.type));
485 isError = true;
486 }
487
488 // List of name=value pairs (or implicit "value=" if size 1)
489 List<JCExpression> args = a.args;
490
491 boolean elidedValue = false;
492 // special case: elided "value=" assumed
493 if (args.length() == 1 && !args.head.hasTag(ASSIGN)) {
494 args.head = make.at(args.head.pos).
495 Assign(make.Ident(names.value), args.head);
496 elidedValue = true;
497 }
498
499 ListBuffer<Pair<MethodSymbol,Attribute>> buf = new ListBuffer<>();
500 for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) {
501 Pair<MethodSymbol, Attribute> p = attributeAnnotationNameValuePair(tl.head, a.type, isError, env, elidedValue);
502 if (p != null && !p.fst.type.isErroneous())
503 buf.append(p);
504 }
505 return buf.toList();
506 }
507
508 // where
509 private Pair<MethodSymbol, Attribute> attributeAnnotationNameValuePair(JCExpression nameValuePair,
510 Type thisAnnotationType, boolean badAnnotation, Env<AttrContext> env, boolean elidedValue)
511 {
512 if (!nameValuePair.hasTag(ASSIGN)) {
513 log.error(nameValuePair.pos(), Errors.AnnotationValueMustBeNameValue);
514 attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env);
515 return null;
516 }
517 JCAssign assign = (JCAssign)nameValuePair;
518 if (!assign.lhs.hasTag(IDENT)) {
519 log.error(nameValuePair.pos(), Errors.AnnotationValueMustBeNameValue);
520 attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env);
521 return null;
522 }
523
524 // Resolve element to MethodSym
525 JCIdent left = (JCIdent)assign.lhs;
526 Symbol method = resolve.resolveQualifiedMethod(elidedValue ? assign.rhs.pos() : left.pos(),
527 env, thisAnnotationType,
528 left.name, List.nil(), null);
529 left.sym = method;
530 left.type = method.type;
531 chk.checkDeprecated(left, env.info.scope.owner, method);
532 if (method.owner != thisAnnotationType.tsym && !badAnnotation)
533 log.error(left.pos(), Errors.NoAnnotationMember(left.name, thisAnnotationType));
534 Type resultType = method.type.getReturnType();
535
536 // Compute value part
537 Attribute value = attributeAnnotationValue(resultType, assign.rhs, env);
538 nameValuePair.type = resultType;
539
540 return method.type.isErroneous() ? null : new Pair<>((MethodSymbol)method, value);
541
542 }
543
544 /** Attribute an annotation element value */
545 private Attribute attributeAnnotationValue(Type expectedElementType, JCExpression tree,
546 Env<AttrContext> env)
547 {
548 //first, try completing the symbol for the annotation value - if a completion
549 //error is thrown, we should recover gracefully, and display an
550 //ordinary resolution diagnostic.
551 try {
552 expectedElementType.tsym.complete();
553 } catch(CompletionFailure e) {
554 log.error(tree.pos(), Errors.CantResolve(Kinds.kindName(e.sym), e.sym.getQualifiedName(), null, null));
555 expectedElementType = syms.errType;
556 }
557
558 if (expectedElementType.hasTag(ARRAY)) {
559 return getAnnotationArrayValue(expectedElementType, tree, env);
560 }
561
562 //error recovery
563 if (tree.hasTag(NEWARRAY)) {
564 if (!expectedElementType.isErroneous())
565 log.error(tree.pos(), Errors.AnnotationValueNotAllowableType);
566 JCNewArray na = (JCNewArray)tree;
567 if (na.elemtype != null) {
568 log.error(na.elemtype.pos(), Errors.NewNotAllowedInAnnotation);
569 }
570 for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) {
571 attributeAnnotationValue(syms.errType,
572 l.head,
573 env);
574 }
575 return new Attribute.Error(syms.errType);
576 }
577
578 if (expectedElementType.tsym.isAnnotationType()) {
579 if (tree.hasTag(ANNOTATION)) {
580 return attributeAnnotation((JCAnnotation)tree, expectedElementType, env);
581 } else {
582 log.error(tree.pos(), Errors.AnnotationValueMustBeAnnotation);
583 expectedElementType = syms.errType;
584 }
585 }
586
587 //error recovery
588 if (tree.hasTag(ANNOTATION)) {
589 if (!expectedElementType.isErroneous())
590 log.error(tree.pos(), Errors.AnnotationNotValidForType(expectedElementType));
591 attributeAnnotation((JCAnnotation)tree, syms.errType, env);
592 return new Attribute.Error(((JCAnnotation)tree).annotationType.type);
593 }
594
595 MemberEnter.InitTreeVisitor initTreeVisitor = new MemberEnter.InitTreeVisitor() {
596 // the methods below are added to allow class literals on top of constant expressions
597 @Override
598 public void visitTypeIdent(JCPrimitiveTypeTree that) {}
599
600 @Override
601 public void visitTypeArray(JCArrayTypeTree that) {}
602 };
603 tree.accept(initTreeVisitor);
604 if (!initTreeVisitor.result) {
605 log.error(tree.pos(), Errors.ExpressionNotAllowableAsAnnotationValue);
606 return new Attribute.Error(syms.errType);
607 }
608
609 if (expectedElementType.isPrimitive() ||
610 (types.isSameType(expectedElementType, syms.stringType) && !expectedElementType.hasTag(TypeTag.ERROR))) {
611 return getAnnotationPrimitiveValue(expectedElementType, tree, env);
612 }
613
614 if (expectedElementType.tsym == syms.classType.tsym) {
615 return getAnnotationClassValue(expectedElementType, tree, env);
616 }
617
618 if (expectedElementType.hasTag(CLASS) &&
619 (expectedElementType.tsym.flags() & Flags.ENUM) != 0) {
620 return getAnnotationEnumValue(expectedElementType, tree, env);
621 }
622
623 //error recovery:
624 if (!expectedElementType.isErroneous())
625 log.error(tree.pos(), Errors.AnnotationValueNotAllowableType);
626 return new Attribute.Error(attr.attribExpr(tree, env, expectedElementType));
627 }
628
629 private Attribute getAnnotationEnumValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
630 Type result = attr.attribTree(tree, env, annotationValueInfo(expectedElementType));
631 Symbol sym = TreeInfo.symbol(tree);
632 if (sym == null ||
633 TreeInfo.nonstaticSelect(tree) ||
634 sym.kind != VAR ||
635 (sym.flags() & Flags.ENUM) == 0) {
636 log.error(tree.pos(), Errors.EnumAnnotationMustBeEnumConstant);
637 return new Attribute.Error(result.getOriginalType());
638 }
639 VarSymbol enumerator = (VarSymbol) sym;
640 return new Attribute.Enum(expectedElementType, enumerator);
641 }
642
643 private Attribute getAnnotationClassValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
644 Type result = attr.attribTree(tree, env, annotationValueInfo(expectedElementType));
645 if (result.isErroneous()) {
646 // Does it look like an unresolved class literal?
647 if (TreeInfo.name(tree) == names._class &&
648 ((JCFieldAccess) tree).selected.type.isErroneous()) {
649 Name n = (((JCFieldAccess) tree).selected).type.tsym.flatName();
650 return new Attribute.UnresolvedClass(expectedElementType,
651 types.createErrorType(n,
652 syms.unknownSymbol, syms.classType));
653 } else {
654 return new Attribute.Error(result.getOriginalType());
655 }
656 }
657
658 // Class literals look like field accesses of a field named class
659 // at the tree level
660 if (TreeInfo.name(tree) != names._class) {
661 log.error(tree.pos(), Errors.AnnotationValueMustBeClassLiteral);
662 return new Attribute.Error(syms.errType);
663 }
664
665 return new Attribute.Class(types,
666 (((JCFieldAccess) tree).selected).type);
667 }
668
669 private Attribute getAnnotationPrimitiveValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
670 Type result = attr.attribTree(tree, env, annotationValueInfo(expectedElementType));
671 if (result.isErroneous())
672 return new Attribute.Error(result.getOriginalType());
673 if (result.constValue() == null) {
674 log.error(tree.pos(), Errors.AttributeValueMustBeConstant);
675 return new Attribute.Error(expectedElementType);
676 }
677
678 // Scan the annotation element value and then attribute nested annotations if present
679 if (tree.type != null && tree.type.tsym != null) {
680 queueScanTreeAndTypeAnnotate(tree, env, tree.type.tsym);
681 }
682
683 result = cfolder.coerce(result, expectedElementType);
684 return new Attribute.Constant(expectedElementType, result.constValue());
685 }
686
687 private Attr.ResultInfo annotationValueInfo(Type pt) {
688 return attr.unknownExprInfo.dup(pt, new AnnotationValueContext(attr.unknownExprInfo.checkContext));
689 }
690
691 class AnnotationValueContext extends Check.NestedCheckContext {
692 AnnotationValueContext(CheckContext enclosingContext) {
693 super(enclosingContext);
694 }
695
696 @Override
697 public boolean compatible(Type found, Type req, Warner warn) {
698 //handle non-final implicitly-typed vars (will be rejected later on)
699 return found.hasTag(TypeTag.NONE) || super.compatible(found, req, warn);
700 }
701 }
702
703 private Attribute getAnnotationArrayValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) {
704 // Special case, implicit array
705 if (!tree.hasTag(NEWARRAY)) {
706 tree = make.at(tree.pos).
707 NewArray(null, List.nil(), List.of(tree));
708 }
709
710 JCNewArray na = (JCNewArray)tree;
711 List<JCExpression> elems = na.elems;
712 if (na.elemtype != null) {
713 log.error(na.elemtype.pos(), Errors.NewNotAllowedInAnnotation);
714 if (elems == null) {
715 elems = List.nil();
716 }
717 }
718 ListBuffer<Attribute> buf = new ListBuffer<>();
719 for (List<JCExpression> l = elems; l.nonEmpty(); l = l.tail) {
720 buf.append(attributeAnnotationValue(types.elemtype(expectedElementType),
721 l.head,
722 env));
723 }
724 na.type = expectedElementType;
725 return new Attribute.
726 Array(expectedElementType, buf.toArray(new Attribute[buf.length()]));
727 }
728
729 /* *********************************
730 * Support for repeating annotations
731 ***********************************/
732
733 /**
734 * This context contains all the information needed to synthesize new
735 * annotations trees for repeating annotations.
736 */
737 private class AnnotationContext<T extends Attribute.Compound> {
738 public final Env<AttrContext> env;
739 public final Map<Symbol.TypeSymbol, ListBuffer<T>> annotated;
740 public final Map<T, JCDiagnostic.DiagnosticPosition> pos;
741 public final boolean isTypeCompound;
742
743 public AnnotationContext(Env<AttrContext> env,
744 Map<Symbol.TypeSymbol, ListBuffer<T>> annotated,
745 Map<T, JCDiagnostic.DiagnosticPosition> pos,
746 boolean isTypeCompound) {
747 Assert.checkNonNull(env);
748 Assert.checkNonNull(annotated);
749 Assert.checkNonNull(pos);
750
751 this.env = env;
752 this.annotated = annotated;
753 this.pos = pos;
754 this.isTypeCompound = isTypeCompound;
755 }
756 }
757
758 /* Process repeated annotations. This method returns the
759 * synthesized container annotation or null IFF all repeating
760 * annotation are invalid. This method reports errors/warnings.
761 */
762 private <T extends Attribute.Compound> T processRepeatedAnnotations(List<T> annotations,
763 AnnotationContext<T> ctx, Symbol on, boolean isTypeParam)
764 {
765 T firstOccurrence = annotations.head;
766 List<Attribute> repeated = List.nil();
767 Type origAnnoType = null;
768 Type arrayOfOrigAnnoType = null;
769 Type targetContainerType = null;
770 MethodSymbol containerValueSymbol = null;
771
772 Assert.check(!annotations.isEmpty() && !annotations.tail.isEmpty()); // i.e. size() > 1
773
774 int count = 0;
775 for (List<T> al = annotations; !al.isEmpty(); al = al.tail) {
776 count++;
777
778 // There must be more than a single anno in the annotation list
779 Assert.check(count > 1 || !al.tail.isEmpty());
780
781 T currentAnno = al.head;
782
783 origAnnoType = currentAnno.type;
784 if (arrayOfOrigAnnoType == null) {
785 arrayOfOrigAnnoType = types.makeArrayType(origAnnoType);
786 }
787
788 // Only report errors if this isn't the first occurrence I.E. count > 1
789 boolean reportError = count > 1;
790 Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno), reportError);
791 if (currentContainerType == null) {
792 continue;
793 }
794 // Assert that the target Container is == for all repeated
795 // annos of the same annotation type, the types should
796 // come from the same Symbol, i.e. be '=='
797 Assert.check(targetContainerType == null || currentContainerType == targetContainerType);
798 targetContainerType = currentContainerType;
799
800 containerValueSymbol = validateContainer(targetContainerType, origAnnoType, ctx.pos.get(currentAnno));
801
802 if (containerValueSymbol == null) { // Check of CA type failed
803 // errors are already reported
804 continue;
805 }
806
807 repeated = repeated.prepend(currentAnno);
808 }
809
810 if (!repeated.isEmpty() && targetContainerType == null) {
811 log.error(ctx.pos.get(annotations.head), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType));
812 return null;
813 }
814
815 if (!repeated.isEmpty()) {
816 repeated = repeated.reverse();
817 DiagnosticPosition pos = ctx.pos.get(firstOccurrence);
818 TreeMaker m = make.at(pos);
819 Pair<MethodSymbol, Attribute> p =
820 new Pair<MethodSymbol, Attribute>(containerValueSymbol,
821 new Attribute.Array(arrayOfOrigAnnoType, repeated));
822 if (ctx.isTypeCompound) {
823 /* TODO: the following code would be cleaner:
824 Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
825 ((Attribute.TypeCompound)annotations.head).position);
826 JCTypeAnnotation annoTree = m.TypeAnnotation(at);
827 at = attributeTypeAnnotation(annoTree, targetContainerType, ctx.env);
828 */
829 // However, we directly construct the TypeCompound to keep the
830 // direct relation to the contained TypeCompounds.
831 Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
832 ((Attribute.TypeCompound)annotations.head).position);
833
834 JCAnnotation annoTree = m.TypeAnnotation(at);
835 if (!chk.validateAnnotationDeferErrors(annoTree))
836 log.error(annoTree.pos(), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType));
837
838 if (!chk.isTypeAnnotation(annoTree, isTypeParam)) {
839 log.error(pos, isTypeParam ? Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on)
840 : Errors.InvalidRepeatableAnnotationNotApplicableInContext(targetContainerType));
841 }
842
843 at.setSynthesized(true);
844
845 @SuppressWarnings("unchecked")
846 T x = (T) at;
847 return x;
848 } else {
849 Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p));
850 JCAnnotation annoTree = m.Annotation(c);
851
852 boolean isRecordMember = (on.flags_field & Flags.RECORD) != 0 || on.enclClass() != null && on.enclClass().isRecord();
853 /* if it is a record member we will not issue the error now and wait until annotations on records are
854 * checked at Check::validateAnnotation, which will issue it
855 */
856 if (!chk.annotationApplicable(annoTree, on) && (!isRecordMember || isRecordMember && (on.flags_field & Flags.GENERATED_MEMBER) == 0)) {
857 log.error(annoTree.pos(),
858 Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on));
859 }
860
861 if (!chk.validateAnnotationDeferErrors(annoTree))
862 log.error(annoTree.pos(), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType));
863
864 c = attributeAnnotation(annoTree, targetContainerType, ctx.env);
865 c.setSynthesized(true);
866
867 @SuppressWarnings("unchecked")
868 T x = (T) c;
869 return x;
870 }
871 } else {
872 return null; // errors should have been reported elsewhere
873 }
874 }
875
876 /**
877 * Fetches the actual Type that should be the containing annotation.
878 */
879 private Type getContainingType(Attribute.Compound currentAnno,
880 DiagnosticPosition pos,
881 boolean reportError)
882 {
883 Type origAnnoType = currentAnno.type;
884 TypeSymbol origAnnoDecl = origAnnoType.tsym;
885
886 // Fetch the Repeatable annotation from the current
887 // annotation's declaration, or null if it has none
888 Attribute.Compound ca = origAnnoDecl.getAnnotationTypeMetadata().getRepeatable();
889 if (ca == null) { // has no Repeatable annotation
890 if (reportError)
891 log.error(pos, Errors.DuplicateAnnotationMissingContainer(origAnnoType));
892 return null;
893 }
894
895 return filterSame(extractContainingType(ca, pos, origAnnoDecl),
896 origAnnoType);
897 }
898
899 // returns null if t is same as 's', returns 't' otherwise
900 private Type filterSame(Type t, Type s) {
901 if (t == null || s == null) {
902 return t;
903 }
904
905 return types.isSameType(t, s) ? null : t;
906 }
907
908 /** Extract the actual Type to be used for a containing annotation. */
909 private Type extractContainingType(Attribute.Compound ca,
910 DiagnosticPosition pos,
911 TypeSymbol annoDecl)
912 {
913 // The next three checks check that the Repeatable annotation
914 // on the declaration of the annotation type that is repeating is
915 // valid.
916
917 // Repeatable must have at least one element
918 if (ca.values.isEmpty()) {
919 log.error(pos, Errors.InvalidRepeatableAnnotation(annoDecl));
920 return null;
921 }
922 Pair<MethodSymbol,Attribute> p = ca.values.head;
923 Name name = p.fst.name;
924 if (name != names.value) { // should contain only one element, named "value"
925 log.error(pos, Errors.InvalidRepeatableAnnotation(annoDecl));
926 return null;
927 }
928 if (!(p.snd instanceof Attribute.Class attributeClass)) { // check that the value of "value" is an Attribute.Class
929 log.error(pos, Errors.InvalidRepeatableAnnotation(annoDecl));
930 return null;
931 }
932
933 return attributeClass.getValue();
934 }
935
936 /* Validate that the suggested targetContainerType Type is a valid
937 * container type for repeated instances of originalAnnoType
938 * annotations. Return null and report errors if this is not the
939 * case, return the MethodSymbol of the value element in
940 * targetContainerType if it is suitable (this is needed to
941 * synthesize the container). */
942 private MethodSymbol validateContainer(Type targetContainerType,
943 Type originalAnnoType,
944 DiagnosticPosition pos) {
945 MethodSymbol containerValueSymbol = null;
946 boolean fatalError = false;
947
948 // Validate that there is a (and only 1) value method
949 Scope scope = null;
950 try {
951 scope = targetContainerType.tsym.members();
952 } catch (CompletionFailure ex) {
953 chk.completionError(pos, ex);
954 return null;
955 }
956 int nr_value_elems = 0;
957 boolean error = false;
958 for(Symbol elm : scope.getSymbolsByName(names.value)) {
959 nr_value_elems++;
960
961 if (nr_value_elems == 1 &&
962 elm.kind == MTH) {
963 containerValueSymbol = (MethodSymbol)elm;
964 } else {
965 error = true;
966 }
967 }
968 if (error) {
969 log.error(pos,
970 Errors.InvalidRepeatableAnnotationMultipleValues(targetContainerType,
971 nr_value_elems));
972 return null;
973 } else if (nr_value_elems == 0) {
974 log.error(pos,
975 Errors.InvalidRepeatableAnnotationNoValue(targetContainerType));
976 return null;
977 }
978
979 // validate that the 'value' element is a method
980 // probably "impossible" to fail this
981 if (containerValueSymbol.kind != MTH) {
982 log.error(pos,
983 Errors.InvalidRepeatableAnnotationInvalidValue(targetContainerType));
984 fatalError = true;
985 }
986
987 // validate that the 'value' element has the correct return type
988 // i.e. array of original anno
989 Type valueRetType = containerValueSymbol.type.getReturnType();
990 Type expectedType = types.makeArrayType(originalAnnoType);
991 if (!(types.isArray(valueRetType) &&
992 types.isSameType(expectedType, valueRetType))) {
993 log.error(pos,
994 Errors.InvalidRepeatableAnnotationValueReturn(targetContainerType,
995 valueRetType,
996 expectedType));
997 fatalError = true;
998 }
999
1000 return fatalError ? null : containerValueSymbol;
1001 }
1002
1003 private <T extends Attribute.Compound> T makeContainerAnnotation(List<T> toBeReplaced,
1004 AnnotationContext<T> ctx, Symbol sym, boolean isTypeParam)
1005 {
1006 // Process repeated annotations
1007 T validRepeated =
1008 processRepeatedAnnotations(toBeReplaced, ctx, sym, isTypeParam);
1009
1010 if (validRepeated != null) {
1011 // Check that the container isn't manually
1012 // present along with repeated instances of
1013 // its contained annotation.
1014 ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
1015 if (manualContainer != null) {
1016 log.error(ctx.pos.get(manualContainer.first()),
1017 Errors.InvalidRepeatableAnnotationRepeatedAndContainerPresent(manualContainer.first().type.tsym));
1018 }
1019 }
1020
1021 // A null return will delete the Placeholder
1022 return validRepeated;
1023 }
1024
1025 /* ******************
1026 * Type annotations *
1027 ********************/
1028
1029 /**
1030 * Attribute the list of annotations and enter them onto s.
1031 */
1032 public void enterTypeAnnotations(List<JCAnnotation> annotations, Env<AttrContext> env, Symbol s, boolean isTypeParam)
1033 {
1034 Assert.checkNonNull(s, "Symbol argument to actualEnterTypeAnnotations is nul/");
1035 JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
1036
1037 try {
1038 annotateNow(s, annotations, env, true, isTypeParam);
1039 } finally {
1040 log.useSource(prev);
1041 }
1042 }
1043
1044 /**
1045 * Enqueue tree for scanning of type annotations, attaching to the Symbol sym.
1046 */
1047 public void queueScanTreeAndTypeAnnotate(JCTree tree, Env<AttrContext> env, Symbol sym)
1048 {
1049 Assert.checkNonNull(sym);
1050 normal(() -> tree.accept(new TypeAnnotate(env, sym)));
1051 }
1052
1053 /**
1054 * Apply the annotations to the particular type.
1055 */
1056 public void annotateTypeSecondStage(JCTree tree, List<JCAnnotation> annotations, Type storeAt) {
1057 typeAnnotation(() -> {
1058 List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
1059 Assert.check(annotations.size() == compounds.size());
1060 // the type already has annotation metadata, but it's empty
1061 Annotations metadata = storeAt.getMetadata(Annotations.class);
1062 Assert.checkNonNull(metadata);
1063 Assert.check(metadata.annotationBuffer().isEmpty());
1064 metadata.annotationBuffer().appendList(compounds);
1065 });
1066 }
1067
1068 /**
1069 * Apply the annotations to the particular type.
1070 */
1071 public void annotateTypeParameterSecondStage(JCTree tree, List<JCAnnotation> annotations) {
1072 typeAnnotation(() -> {
1073 List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
1074 Assert.check(annotations.size() == compounds.size());
1075 });
1076 }
1077
1078 /**
1079 * We need to use a TreeScanner, because it is not enough to visit the top-level
1080 * annotations. We also need to visit type arguments, etc.
1081 */
1082 private class TypeAnnotate extends TreeScanner {
1083 private final Env<AttrContext> env;
1084 private final Symbol sym;
1085
1086 public TypeAnnotate(Env<AttrContext> env, Symbol sym) {
1087
1088 this.env = env;
1089 this.sym = sym;
1090 }
1091
1092 @Override
1093 public void visitAnnotatedType(JCAnnotatedType tree) {
1094 enterTypeAnnotations(tree.annotations, env, sym, false);
1095 scan(tree.underlyingType);
1096 }
1097
1098 @Override
1099 public void visitTypeParameter(JCTypeParameter tree) {
1100 enterTypeAnnotations(tree.annotations, env, sym, true);
1101 scan(tree.bounds);
1102 }
1103
1104 @Override
1105 public void visitNewArray(JCNewArray tree) {
1106 enterTypeAnnotations(tree.annotations, env, sym, false);
1107 for (List<JCAnnotation> dimAnnos : tree.dimAnnotations)
1108 enterTypeAnnotations(dimAnnos, env, sym, false);
1109 scan(tree.elemtype);
1110 scan(tree.elems);
1111 }
1112
1113 @Override
1114 public void visitMethodDef(JCMethodDecl tree) {
1115 scan(tree.mods);
1116 scan(tree.restype);
1117 scan(tree.typarams);
1118 scan(tree.recvparam);
1119 scan(tree.params);
1120 scan(tree.thrown);
1121 scan(tree.defaultValue);
1122 // Do not annotate the body, just the signature.
1123 }
1124
1125 @Override
1126 public void visitVarDef(JCVariableDecl tree) {
1127 if (sym != null && sym.kind == VAR) {
1128 // Don't visit a parameter once when the sym is the method
1129 // and once when the sym is the parameter.
1130 scan(tree.mods);
1131 scan(tree.vartype);
1132 }
1133 scan(tree.init);
1134 }
1135
1136 @Override
1137 public void visitBindingPattern(JCTree.JCBindingPattern tree) {
1138 //type binding pattern's type will be annotated separately, avoid
1139 //adding its annotations into the owning method here (would clash
1140 //with repeatable annotations).
1141 }
1142
1143 @Override
1144 public void visitClassDef(JCClassDecl tree) {
1145 // We can only hit a classdef if it is declared within
1146 // a method. Ignore it - the class will be visited
1147 // separately later.
1148 }
1149
1150 @Override
1151 public void visitNewClass(JCNewClass tree) {
1152 scan(tree.encl);
1153 scan(tree.typeargs);
1154 try {
1155 env.info.isAnonymousNewClass = tree.def != null;
1156 scan(tree.clazz);
1157 } finally {
1158 env.info.isAnonymousNewClass = false;
1159 }
1160 scan(tree.args);
1161 // the anonymous class instantiation if any will be visited separately.
1162 }
1163
1164 @Override
1165 public void visitErroneous(JCErroneous tree) {
1166 if (tree.errs != null) {
1167 for (JCTree err : tree.errs) {
1168 scan(err);
1169 }
1170 }
1171 }
1172 }
1173
1174 /* *******************
1175 * Completer support *
1176 *********************/
1177
1178 private AnnotationTypeCompleter theSourceCompleter = new AnnotationTypeCompleter() {
1179 @Override
1180 public void complete(ClassSymbol sym) throws CompletionFailure {
1181 Env<AttrContext> context = typeEnvs.get(sym);
1182 Annotate.this.attributeAnnotationType(context);
1183 }
1184 };
1185
1186 /* Last stage completer to enter just enough annotations to have a prototype annotation type.
1187 * This currently means entering @Target and @Repeatable.
1188 */
1189 public AnnotationTypeCompleter annotationTypeSourceCompleter() {
1190 return theSourceCompleter;
1191 }
1192
1193 private void attributeAnnotationType(Env<AttrContext> env) {
1194 Assert.check(((JCClassDecl)env.tree).sym.isAnnotationType(),
1195 "Trying to annotation type complete a non-annotation type");
1196
1197 JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
1198 try {
1199 JCClassDecl tree = (JCClassDecl)env.tree;
1200 AnnotationTypeVisitor v = new AnnotationTypeVisitor(attr, chk, syms, typeEnvs);
1201 v.scanAnnotationType(tree);
1202 tree.sym.getAnnotationTypeMetadata().setRepeatable(v.repeatable);
1203 tree.sym.getAnnotationTypeMetadata().setTarget(v.target);
1204 } finally {
1205 log.useSource(prev);
1206 }
1207 }
1208
1209 public Attribute unfinishedDefaultValue() {
1210 return theUnfinishedDefaultValue;
1211 }
1212
1213 public static interface AnnotationTypeCompleter {
1214 void complete(ClassSymbol sym) throws CompletionFailure;
1215 }
1216
1217 /** Visitor to determine a prototype annotation type for a class declaring an annotation type.
1218 *
1219 * <p><b>This is NOT part of any supported API.
1220 * If you write code that depends on this, you do so at your own risk.
1221 * This code and its internal interfaces are subject to change or
1222 * deletion without notice.</b>
1223 */
1224 public class AnnotationTypeVisitor extends TreeScanner {
1225 private Env<AttrContext> env;
1226
1227 private final Attr attr;
1228 private final Check check;
1229 private final Symtab tab;
1230 private final TypeEnvs typeEnvs;
1231
1232 private Compound target;
1233 private Compound repeatable;
1234
1235 public AnnotationTypeVisitor(Attr attr, Check check, Symtab tab, TypeEnvs typeEnvs) {
1236 this.attr = attr;
1237 this.check = check;
1238 this.tab = tab;
1239 this.typeEnvs = typeEnvs;
1240 }
1241
1242 public Compound getRepeatable() {
1243 return repeatable;
1244 }
1245
1246 public Compound getTarget() {
1247 return target;
1248 }
1249
1250 public void scanAnnotationType(JCClassDecl decl) {
1251 visitClassDef(decl);
1252 }
1253
1254 @Override
1255 public void visitClassDef(JCClassDecl tree) {
1256 Env<AttrContext> prevEnv = env;
1257 env = typeEnvs.get(tree.sym);
1258 try {
1259 scan(tree.mods); // look for repeatable and target
1260 // don't descend into body
1261 } finally {
1262 env = prevEnv;
1263 }
1264 }
1265
1266 @Override
1267 public void visitAnnotation(JCAnnotation tree) {
1268 Type t = tree.annotationType.type;
1269 if (t == null) {
1270 t = attr.attribType(tree.annotationType, env);
1271 tree.annotationType.type = t = check.checkType(tree.annotationType.pos(), t, tab.annotationType);
1272 }
1273
1274 if (t == tab.annotationTargetType) {
1275 target = Annotate.this.attributeAnnotation(tree, tab.annotationTargetType, env);
1276 } else if (t == tab.repeatableType) {
1277 repeatable = Annotate.this.attributeAnnotation(tree, tab.repeatableType, env);
1278 }
1279 }
1280 }
1281
1282 /** Represents the semantics of an Annotation Type.
1283 *
1284 * <p><b>This is NOT part of any supported API.
1285 * If you write code that depends on this, you do so at your own risk.
1286 * This code and its internal interfaces are subject to change or
1287 * deletion without notice.</b>
1288 */
1289 public static class AnnotationTypeMetadata {
1290 final ClassSymbol metaDataFor;
1291 private Compound target;
1292 private Compound repeatable;
1293 private AnnotationTypeCompleter annotationTypeCompleter;
1294
1295 public AnnotationTypeMetadata(ClassSymbol metaDataFor, AnnotationTypeCompleter annotationTypeCompleter) {
1296 this.metaDataFor = metaDataFor;
1297 this.annotationTypeCompleter = annotationTypeCompleter;
1298 }
1299
1300 private void init() {
1301 // Make sure metaDataFor is member entered
1302 while (!metaDataFor.isCompleted())
1303 metaDataFor.complete();
1304
1305 if (annotationTypeCompleter != null) {
1306 AnnotationTypeCompleter c = annotationTypeCompleter;
1307 annotationTypeCompleter = null;
1308 c.complete(metaDataFor);
1309 }
1310 }
1311
1312 public void complete() {
1313 init();
1314 }
1315
1316 public Compound getRepeatable() {
1317 init();
1318 return repeatable;
1319 }
1320
1321 public void setRepeatable(Compound repeatable) {
1322 Assert.checkNull(this.repeatable);
1323 this.repeatable = repeatable;
1324 }
1325
1326 public Compound getTarget() {
1327 init();
1328 return target;
1329 }
1330
1331 public void setTarget(Compound target) {
1332 Assert.checkNull(this.target);
1333 this.target = target;
1334 }
1335
1336 public Set<MethodSymbol> getAnnotationElements() {
1337 init();
1338 Set<MethodSymbol> members = new LinkedHashSet<>();
1339 WriteableScope s = metaDataFor.members();
1340 Iterable<Symbol> ss = s.getSymbols(NON_RECURSIVE);
1341 for (Symbol sym : ss)
1342 if (sym.kind == MTH &&
1343 sym.name != sym.name.table.names.clinit &&
1344 (sym.flags() & SYNTHETIC) == 0)
1345 members.add((MethodSymbol)sym);
1346 return members;
1347 }
1348
1349 public Set<MethodSymbol> getAnnotationElementsWithDefault() {
1350 init();
1351 Set<MethodSymbol> members = getAnnotationElements();
1352 Set<MethodSymbol> res = new LinkedHashSet<>();
1353 for (MethodSymbol m : members)
1354 if (m.defaultValue != null)
1355 res.add(m);
1356 return res;
1357 }
1358
1359 @Override
1360 public String toString() {
1361 return "Annotation type for: " + metaDataFor;
1362 }
1363
1364 public boolean isMetadataForAnnotationType() { return true; }
1365
1366 public static AnnotationTypeMetadata notAnAnnotationType() {
1367 return NOT_AN_ANNOTATION_TYPE;
1368 }
1369
1370 private static final AnnotationTypeMetadata NOT_AN_ANNOTATION_TYPE =
1371 new AnnotationTypeMetadata(null, null) {
1372 @Override
1373 public void complete() {
1374 } // do nothing
1375
1376 @Override
1377 public String toString() {
1378 return "Not an annotation type";
1379 }
1380
1381 @Override
1382 public Set<MethodSymbol> getAnnotationElements() {
1383 return new LinkedHashSet<>(0);
1384 }
1385
1386 @Override
1387 public Set<MethodSymbol> getAnnotationElementsWithDefault() {
1388 return new LinkedHashSet<>(0);
1389 }
1390
1391 @Override
1392 public boolean isMetadataForAnnotationType() {
1393 return false;
1394 }
1395
1396 @Override
1397 public Compound getTarget() {
1398 return null;
1399 }
1400
1401 @Override
1402 public Compound getRepeatable() {
1403 return null;
1404 }
1405 };
1406 }
1407
1408 public void newRound() {
1409 blockCount = 1;
1410 }
1411
1412 public Queues setQueues(Queues nue) {
1413 Queues stored = new Queues(q, validateQ, typesQ, afterTypesQ);
1414 this.q = nue.q;
1415 this.typesQ = nue.typesQ;
1416 this.afterTypesQ = nue.afterTypesQ;
1417 this.validateQ = nue.validateQ;
1418 return stored;
1419 }
1420
1421 static class Queues {
1422 private final ListBuffer<Runnable> q;
1423 private final ListBuffer<Runnable> validateQ;
1424 private final ListBuffer<Runnable> typesQ;
1425 private final ListBuffer<Runnable> afterTypesQ;
1426
1427 public Queues() {
1428 this(new ListBuffer<Runnable>(), new ListBuffer<Runnable>(), new ListBuffer<Runnable>(), new ListBuffer<Runnable>());
1429 }
1430
1431 public Queues(ListBuffer<Runnable> q, ListBuffer<Runnable> validateQ, ListBuffer<Runnable> typesQ, ListBuffer<Runnable> afterTypesQ) {
1432 this.q = q;
1433 this.validateQ = validateQ;
1434 this.typesQ = typesQ;
1435 this.afterTypesQ = afterTypesQ;
1436 }
1437 }
1438 }