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 (a.type.isErroneous() || a.type.tsym.isAnnotationType()) { 336 if (annotated.containsKey(a.type.tsym)) { 337 ListBuffer<T> l = annotated.get(a.type.tsym); 338 l = l.append(c); 339 annotated.put(a.type.tsym, l); 340 pos.put(c, a.pos()); 341 } else { 342 annotated.put(a.type.tsym, ListBuffer.of(c)); 343 pos.put(c, a.pos()); 344 } 345 } 346 347 // Note: @Deprecated has no effect on local variables and parameters 348 if (!c.type.isErroneous() 349 && (toAnnotate.kind == MDL || toAnnotate.owner.kind != MTH) 350 && types.isSameType(c.type, syms.deprecatedType)) { 351 toAnnotate.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION); 352 if (isAttributeTrue(c.member(names.forRemoval))) { 353 toAnnotate.flags_field |= Flags.DEPRECATED_REMOVAL; 354 } 355 } 356 357 if (!c.type.isErroneous() 358 && types.isSameType(c.type, syms.previewFeatureType)) { 359 toAnnotate.flags_field |= Flags.PREVIEW_API; 360 if (isAttributeTrue(c.member(names.reflective))) { 361 toAnnotate.flags_field |= Flags.PREVIEW_REFLECTIVE; 362 } 363 } 364 365 if (!c.type.isErroneous() 366 && toAnnotate.kind == TYP 367 && types.isSameType(c.type, syms.valueBasedType)) { 368 toAnnotate.flags_field |= Flags.VALUE_BASED; 369 } 370 371 if (!c.type.isErroneous() 372 && types.isSameType(c.type, syms.restrictedType)) { 373 toAnnotate.flags_field |= Flags.RESTRICTED; 374 } 375 376 if (!c.type.isErroneous() 377 && toAnnotate.kind == VAR 378 && types.isSameType(c.type, syms.requiresIdentityType)) { 379 toAnnotate.flags_field |= Flags.REQUIRES_IDENTITY; 380 } 381 } 382 383 List<T> buf = List.nil(); 384 for (ListBuffer<T> lb : annotated.values()) { 385 if (lb.size() == 1) { 386 buf = buf.prepend(lb.first()); 387 } else { 388 AnnotationContext<T> ctx = new AnnotationContext<>(env, annotated, pos, typeAnnotations); 389 T res = makeContainerAnnotation(lb.toList(), ctx, toAnnotate, isTypeParam); 390 if (res != null) 391 buf = buf.prepend(res); 392 } 393 } 394 395 if (typeAnnotations) { 396 @SuppressWarnings("unchecked") 397 List<TypeCompound> attrs = (List<TypeCompound>)buf.reverse(); 398 toAnnotate.appendUniqueTypeAttributes(attrs); 399 } else { 400 @SuppressWarnings("unchecked") 401 List<Attribute.Compound> attrs = (List<Attribute.Compound>)buf.reverse(); 402 toAnnotate.resetAnnotations(); 403 toAnnotate.setDeclarationAttributes(attrs); 404 } 405 } 406 //where: 407 private boolean isAttributeTrue(Attribute attr) { 408 return (attr instanceof Attribute.Constant constant) 409 && constant.type == syms.booleanType 410 && ((Integer) constant.value) != 0; 411 } 412 413 /** 414 * Attribute and store a semantic representation of the annotation tree {@code tree} into the 415 * tree.attribute field. 416 * 417 * @param tree the tree representing an annotation 418 * @param expectedAnnotationType the expected (super)type of the annotation 419 * @param env the current env in where the annotation instance is found 420 */ 421 public Attribute.Compound attributeAnnotation(JCAnnotation tree, Type expectedAnnotationType, 422 Env<AttrContext> env) 423 { 424 // The attribute might have been entered if it is Target or Repeatable 425 // Because TreeCopier does not copy type, redo this if type is null 426 if (tree.attribute != null && tree.type != null) 427 return tree.attribute; 428 429 List<Pair<MethodSymbol, Attribute>> elems = attributeAnnotationValues(tree, expectedAnnotationType, env); 430 Attribute.Compound ac = new Attribute.Compound(tree.type, elems); 431 432 return tree.attribute = ac; 433 } 434 435 /** Attribute and store a semantic representation of the type annotation tree {@code tree} into 436 * the tree.attribute field. 437 * 438 * @param a the tree representing an annotation 439 * @param expectedAnnotationType the expected (super)type of the annotation 440 * @param env the current env in where the annotation instance is found 441 */ 442 public Attribute.TypeCompound attributeTypeAnnotation(JCAnnotation a, Type expectedAnnotationType, 443 Env<AttrContext> env) 444 { 445 // The attribute might have been entered if it is Target or Repeatable 446 // Because TreeCopier does not copy type, redo this if type is null 447 if (a.attribute == null || a.type == null || !(a.attribute instanceof Attribute.TypeCompound typeCompound)) { 448 // Create a new TypeCompound 449 List<Pair<MethodSymbol,Attribute>> elems = 450 attributeAnnotationValues(a, expectedAnnotationType, env); 451 452 Attribute.TypeCompound tc = 453 new Attribute.TypeCompound(a.type, elems, TypeAnnotationPosition.unknown); 454 a.attribute = tc; 455 return tc; 456 } else { 457 // Use an existing TypeCompound 458 return typeCompound; 459 } 460 } 461 462 /** 463 * Attribute annotation elements creating a list of pairs of the Symbol representing that 464 * element and the value of that element as an Attribute. */ 465 private List<Pair<MethodSymbol, Attribute>> attributeAnnotationValues(JCAnnotation a, 466 Type expected, Env<AttrContext> env) 467 { 468 // The annotation might have had its type attributed (but not 469 // checked) by attr.attribAnnotationTypes during MemberEnter, 470 // in which case we do not need to do it again. 471 Type at = (a.annotationType.type != null ? 472 a.annotationType.type : attr.attribType(a.annotationType, env)); 473 a.type = chk.checkType(a.annotationType.pos(), at, expected); 474 475 boolean isError = a.type.isErroneous(); 476 if (!a.type.tsym.isAnnotationType() && !isError) { 477 log.error(a.annotationType.pos(), Errors.NotAnnotationType(a.type)); 478 isError = true; 479 } 480 481 // List of name=value pairs (or implicit "value=" if size 1) 482 List<JCExpression> args = a.args; 483 484 boolean elidedValue = false; 485 // special case: elided "value=" assumed 486 if (args.length() == 1 && !args.head.hasTag(ASSIGN)) { 487 args.head = make.at(args.head.pos). 488 Assign(make.Ident(names.value), args.head); 489 elidedValue = true; 490 } 491 492 ListBuffer<Pair<MethodSymbol,Attribute>> buf = new ListBuffer<>(); 493 for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) { 494 Pair<MethodSymbol, Attribute> p = attributeAnnotationNameValuePair(tl.head, a.type, isError, env, elidedValue); 495 if (p != null && !p.fst.type.isErroneous()) 496 buf.append(p); 497 } 498 return buf.toList(); 499 } 500 501 // where 502 private Pair<MethodSymbol, Attribute> attributeAnnotationNameValuePair(JCExpression nameValuePair, 503 Type thisAnnotationType, boolean badAnnotation, Env<AttrContext> env, boolean elidedValue) 504 { 505 if (!nameValuePair.hasTag(ASSIGN)) { 506 log.error(nameValuePair.pos(), Errors.AnnotationValueMustBeNameValue); 507 attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env); 508 return null; 509 } 510 JCAssign assign = (JCAssign)nameValuePair; 511 if (!assign.lhs.hasTag(IDENT)) { 512 log.error(nameValuePair.pos(), Errors.AnnotationValueMustBeNameValue); 513 attributeAnnotationValue(nameValuePair.type = syms.errType, nameValuePair, env); 514 return null; 515 } 516 517 // Resolve element to MethodSym 518 JCIdent left = (JCIdent)assign.lhs; 519 Symbol method = resolve.resolveQualifiedMethod(elidedValue ? assign.rhs.pos() : left.pos(), 520 env, thisAnnotationType, 521 left.name, List.nil(), null); 522 left.sym = method; 523 left.type = method.type; 524 chk.checkDeprecated(left, env.info.scope.owner, method); 525 if (method.owner != thisAnnotationType.tsym && !badAnnotation) 526 log.error(left.pos(), Errors.NoAnnotationMember(left.name, thisAnnotationType)); 527 Type resultType = method.type.getReturnType(); 528 529 // Compute value part 530 Attribute value = attributeAnnotationValue(resultType, assign.rhs, env); 531 nameValuePair.type = resultType; 532 533 return method.type.isErroneous() ? null : new Pair<>((MethodSymbol)method, value); 534 535 } 536 537 /** Attribute an annotation element value */ 538 private Attribute attributeAnnotationValue(Type expectedElementType, JCExpression tree, 539 Env<AttrContext> env) 540 { 541 //first, try completing the symbol for the annotation value - if a completion 542 //error is thrown, we should recover gracefully, and display an 543 //ordinary resolution diagnostic. 544 try { 545 expectedElementType.tsym.complete(); 546 } catch(CompletionFailure e) { 547 log.error(tree.pos(), Errors.CantResolve(Kinds.kindName(e.sym), e.sym.getQualifiedName(), null, null)); 548 expectedElementType = syms.errType; 549 } 550 551 if (expectedElementType.hasTag(ARRAY)) { 552 return getAnnotationArrayValue(expectedElementType, tree, env); 553 } 554 555 //error recovery 556 if (tree.hasTag(NEWARRAY)) { 557 if (!expectedElementType.isErroneous()) 558 log.error(tree.pos(), Errors.AnnotationValueNotAllowableType); 559 JCNewArray na = (JCNewArray)tree; 560 if (na.elemtype != null) { 561 log.error(na.elemtype.pos(), Errors.NewNotAllowedInAnnotation); 562 } 563 for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) { 564 attributeAnnotationValue(syms.errType, 565 l.head, 566 env); 567 } 568 return new Attribute.Error(syms.errType); 569 } 570 571 if (expectedElementType.tsym.isAnnotationType()) { 572 if (tree.hasTag(ANNOTATION)) { 573 return attributeAnnotation((JCAnnotation)tree, expectedElementType, env); 574 } else { 575 log.error(tree.pos(), Errors.AnnotationValueMustBeAnnotation); 576 expectedElementType = syms.errType; 577 } 578 } 579 580 //error recovery 581 if (tree.hasTag(ANNOTATION)) { 582 if (!expectedElementType.isErroneous()) 583 log.error(tree.pos(), Errors.AnnotationNotValidForType(expectedElementType)); 584 attributeAnnotation((JCAnnotation)tree, syms.errType, env); 585 return new Attribute.Error(((JCAnnotation)tree).annotationType.type); 586 } 587 588 MemberEnter.InitTreeVisitor initTreeVisitor = new MemberEnter.InitTreeVisitor() { 589 // the methods below are added to allow class literals on top of constant expressions 590 @Override 591 public void visitTypeIdent(JCPrimitiveTypeTree that) {} 592 593 @Override 594 public void visitTypeArray(JCArrayTypeTree that) {} 595 }; 596 tree.accept(initTreeVisitor); 597 if (!initTreeVisitor.result) { 598 log.error(tree.pos(), Errors.ExpressionNotAllowableAsAnnotationValue); 599 return new Attribute.Error(syms.errType); 600 } 601 602 if (expectedElementType.isPrimitive() || 603 (types.isSameType(expectedElementType, syms.stringType) && !expectedElementType.hasTag(TypeTag.ERROR))) { 604 return getAnnotationPrimitiveValue(expectedElementType, tree, env); 605 } 606 607 if (expectedElementType.tsym == syms.classType.tsym) { 608 return getAnnotationClassValue(expectedElementType, tree, env); 609 } 610 611 if (expectedElementType.hasTag(CLASS) && 612 (expectedElementType.tsym.flags() & Flags.ENUM) != 0) { 613 return getAnnotationEnumValue(expectedElementType, tree, env); 614 } 615 616 //error recovery: 617 if (!expectedElementType.isErroneous()) 618 log.error(tree.pos(), Errors.AnnotationValueNotAllowableType); 619 return new Attribute.Error(attr.attribExpr(tree, env, expectedElementType)); 620 } 621 622 private Attribute getAnnotationEnumValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) { 623 Type result = attr.attribTree(tree, env, annotationValueInfo(expectedElementType)); 624 Symbol sym = TreeInfo.symbol(tree); 625 if (sym == null || 626 TreeInfo.nonstaticSelect(tree) || 627 sym.kind != VAR || 628 (sym.flags() & Flags.ENUM) == 0) { 629 log.error(tree.pos(), Errors.EnumAnnotationMustBeEnumConstant); 630 return new Attribute.Error(result.getOriginalType()); 631 } 632 VarSymbol enumerator = (VarSymbol) sym; 633 return new Attribute.Enum(expectedElementType, enumerator); 634 } 635 636 private Attribute getAnnotationClassValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) { 637 Type result = attr.attribTree(tree, env, annotationValueInfo(expectedElementType)); 638 if (result.isErroneous()) { 639 // Does it look like an unresolved class literal? 640 if (TreeInfo.name(tree) == names._class && 641 ((JCFieldAccess) tree).selected.type.isErroneous()) { 642 Name n = (((JCFieldAccess) tree).selected).type.tsym.flatName(); 643 return new Attribute.UnresolvedClass(expectedElementType, 644 types.createErrorType(n, 645 syms.unknownSymbol, syms.classType)); 646 } else { 647 return new Attribute.Error(result.getOriginalType()); 648 } 649 } 650 651 // Class literals look like field accesses of a field named class 652 // at the tree level 653 if (TreeInfo.name(tree) != names._class) { 654 log.error(tree.pos(), Errors.AnnotationValueMustBeClassLiteral); 655 return new Attribute.Error(syms.errType); 656 } 657 658 return new Attribute.Class(types, 659 (((JCFieldAccess) tree).selected).type); 660 } 661 662 private Attribute getAnnotationPrimitiveValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) { 663 Type result = attr.attribTree(tree, env, annotationValueInfo(expectedElementType)); 664 if (result.isErroneous()) 665 return new Attribute.Error(result.getOriginalType()); 666 if (result.constValue() == null) { 667 log.error(tree.pos(), Errors.AttributeValueMustBeConstant); 668 return new Attribute.Error(expectedElementType); 669 } 670 671 // Scan the annotation element value and then attribute nested annotations if present 672 if (tree.type != null && tree.type.tsym != null) { 673 queueScanTreeAndTypeAnnotate(tree, env, tree.type.tsym); 674 } 675 676 result = cfolder.coerce(result, expectedElementType); 677 return new Attribute.Constant(expectedElementType, result.constValue()); 678 } 679 680 private Attr.ResultInfo annotationValueInfo(Type pt) { 681 return attr.unknownExprInfo.dup(pt, new AnnotationValueContext(attr.unknownExprInfo.checkContext)); 682 } 683 684 class AnnotationValueContext extends Check.NestedCheckContext { 685 AnnotationValueContext(CheckContext enclosingContext) { 686 super(enclosingContext); 687 } 688 689 @Override 690 public boolean compatible(Type found, Type req, Warner warn) { 691 //handle non-final implicitly-typed vars (will be rejected later on) 692 return found.hasTag(TypeTag.NONE) || super.compatible(found, req, warn); 693 } 694 } 695 696 private Attribute getAnnotationArrayValue(Type expectedElementType, JCExpression tree, Env<AttrContext> env) { 697 // Special case, implicit array 698 if (!tree.hasTag(NEWARRAY)) { 699 tree = make.at(tree.pos). 700 NewArray(null, List.nil(), List.of(tree)); 701 } 702 703 JCNewArray na = (JCNewArray)tree; 704 List<JCExpression> elems = na.elems; 705 if (na.elemtype != null) { 706 log.error(na.elemtype.pos(), Errors.NewNotAllowedInAnnotation); 707 if (elems == null) { 708 elems = List.nil(); 709 } 710 } 711 ListBuffer<Attribute> buf = new ListBuffer<>(); 712 for (List<JCExpression> l = elems; l.nonEmpty(); l = l.tail) { 713 buf.append(attributeAnnotationValue(types.elemtype(expectedElementType), 714 l.head, 715 env)); 716 } 717 na.type = expectedElementType; 718 return new Attribute. 719 Array(expectedElementType, buf.toArray(new Attribute[buf.length()])); 720 } 721 722 /* ********************************* 723 * Support for repeating annotations 724 ***********************************/ 725 726 /** 727 * This context contains all the information needed to synthesize new 728 * annotations trees for repeating annotations. 729 */ 730 private class AnnotationContext<T extends Attribute.Compound> { 731 public final Env<AttrContext> env; 732 public final Map<Symbol.TypeSymbol, ListBuffer<T>> annotated; 733 public final Map<T, JCDiagnostic.DiagnosticPosition> pos; 734 public final boolean isTypeCompound; 735 736 public AnnotationContext(Env<AttrContext> env, 737 Map<Symbol.TypeSymbol, ListBuffer<T>> annotated, 738 Map<T, JCDiagnostic.DiagnosticPosition> pos, 739 boolean isTypeCompound) { 740 Assert.checkNonNull(env); 741 Assert.checkNonNull(annotated); 742 Assert.checkNonNull(pos); 743 744 this.env = env; 745 this.annotated = annotated; 746 this.pos = pos; 747 this.isTypeCompound = isTypeCompound; 748 } 749 } 750 751 /* Process repeated annotations. This method returns the 752 * synthesized container annotation or null IFF all repeating 753 * annotation are invalid. This method reports errors/warnings. 754 */ 755 private <T extends Attribute.Compound> T processRepeatedAnnotations(List<T> annotations, 756 AnnotationContext<T> ctx, Symbol on, boolean isTypeParam) 757 { 758 T firstOccurrence = annotations.head; 759 List<Attribute> repeated = List.nil(); 760 Type origAnnoType = null; 761 Type arrayOfOrigAnnoType = null; 762 Type targetContainerType = null; 763 MethodSymbol containerValueSymbol = null; 764 765 Assert.check(!annotations.isEmpty() && !annotations.tail.isEmpty()); // i.e. size() > 1 766 767 int count = 0; 768 for (List<T> al = annotations; !al.isEmpty(); al = al.tail) { 769 count++; 770 771 // There must be more than a single anno in the annotation list 772 Assert.check(count > 1 || !al.tail.isEmpty()); 773 774 T currentAnno = al.head; 775 776 origAnnoType = currentAnno.type; 777 if (arrayOfOrigAnnoType == null) { 778 arrayOfOrigAnnoType = types.makeArrayType(origAnnoType); 779 } 780 781 // Only report errors if this isn't the first occurrence I.E. count > 1 782 boolean reportError = count > 1; 783 Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno), reportError); 784 if (currentContainerType == null) { 785 continue; 786 } 787 // Assert that the target Container is == for all repeated 788 // annos of the same annotation type, the types should 789 // come from the same Symbol, i.e. be '==' 790 Assert.check(targetContainerType == null || currentContainerType == targetContainerType); 791 targetContainerType = currentContainerType; 792 793 containerValueSymbol = validateContainer(targetContainerType, origAnnoType, ctx.pos.get(currentAnno)); 794 795 if (containerValueSymbol == null) { // Check of CA type failed 796 // errors are already reported 797 continue; 798 } 799 800 repeated = repeated.prepend(currentAnno); 801 } 802 803 if (!repeated.isEmpty() && targetContainerType == null) { 804 log.error(ctx.pos.get(annotations.head), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType)); 805 return null; 806 } 807 808 if (!repeated.isEmpty()) { 809 repeated = repeated.reverse(); 810 DiagnosticPosition pos = ctx.pos.get(firstOccurrence); 811 TreeMaker m = make.at(pos); 812 Pair<MethodSymbol, Attribute> p = 813 new Pair<MethodSymbol, Attribute>(containerValueSymbol, 814 new Attribute.Array(arrayOfOrigAnnoType, repeated)); 815 if (ctx.isTypeCompound) { 816 /* TODO: the following code would be cleaner: 817 Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p), 818 ((Attribute.TypeCompound)annotations.head).position); 819 JCTypeAnnotation annoTree = m.TypeAnnotation(at); 820 at = attributeTypeAnnotation(annoTree, targetContainerType, ctx.env); 821 */ 822 // However, we directly construct the TypeCompound to keep the 823 // direct relation to the contained TypeCompounds. 824 Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p), 825 ((Attribute.TypeCompound)annotations.head).position); 826 827 JCAnnotation annoTree = m.TypeAnnotation(at); 828 if (!chk.validateAnnotationDeferErrors(annoTree)) 829 log.error(annoTree.pos(), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType)); 830 831 if (!chk.isTypeAnnotation(annoTree, isTypeParam)) { 832 log.error(pos, isTypeParam ? Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on) 833 : Errors.InvalidRepeatableAnnotationNotApplicableInContext(targetContainerType)); 834 } 835 836 at.setSynthesized(true); 837 838 @SuppressWarnings("unchecked") 839 T x = (T) at; 840 return x; 841 } else { 842 Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p)); 843 JCAnnotation annoTree = m.Annotation(c); 844 845 boolean isRecordMember = (on.flags_field & Flags.RECORD) != 0 || on.enclClass() != null && on.enclClass().isRecord(); 846 /* if it is a record member we will not issue the error now and wait until annotations on records are 847 * checked at Check::validateAnnotation, which will issue it 848 */ 849 if (!chk.annotationApplicable(annoTree, on) && (!isRecordMember || isRecordMember && (on.flags_field & Flags.GENERATED_MEMBER) == 0)) { 850 log.error(annoTree.pos(), 851 Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on)); 852 } 853 854 if (!chk.validateAnnotationDeferErrors(annoTree)) 855 log.error(annoTree.pos(), Errors.DuplicateAnnotationInvalidRepeated(origAnnoType)); 856 857 c = attributeAnnotation(annoTree, targetContainerType, ctx.env); 858 c.setSynthesized(true); 859 860 @SuppressWarnings("unchecked") 861 T x = (T) c; 862 return x; 863 } 864 } else { 865 return null; // errors should have been reported elsewhere 866 } 867 } 868 869 /** 870 * Fetches the actual Type that should be the containing annotation. 871 */ 872 private Type getContainingType(Attribute.Compound currentAnno, 873 DiagnosticPosition pos, 874 boolean reportError) 875 { 876 Type origAnnoType = currentAnno.type; 877 TypeSymbol origAnnoDecl = origAnnoType.tsym; 878 879 // Fetch the Repeatable annotation from the current 880 // annotation's declaration, or null if it has none 881 Attribute.Compound ca = origAnnoDecl.getAnnotationTypeMetadata().getRepeatable(); 882 if (ca == null) { // has no Repeatable annotation 883 if (reportError) 884 log.error(pos, Errors.DuplicateAnnotationMissingContainer(origAnnoType)); 885 return null; 886 } 887 888 return filterSame(extractContainingType(ca, pos, origAnnoDecl), 889 origAnnoType); 890 } 891 892 // returns null if t is same as 's', returns 't' otherwise 893 private Type filterSame(Type t, Type s) { 894 if (t == null || s == null) { 895 return t; 896 } 897 898 return types.isSameType(t, s) ? null : t; 899 } 900 901 /** Extract the actual Type to be used for a containing annotation. */ 902 private Type extractContainingType(Attribute.Compound ca, 903 DiagnosticPosition pos, 904 TypeSymbol annoDecl) 905 { 906 // The next three checks check that the Repeatable annotation 907 // on the declaration of the annotation type that is repeating is 908 // valid. 909 910 // Repeatable must have at least one element 911 if (ca.values.isEmpty()) { 912 log.error(pos, Errors.InvalidRepeatableAnnotation(annoDecl)); 913 return null; 914 } 915 Pair<MethodSymbol,Attribute> p = ca.values.head; 916 Name name = p.fst.name; 917 if (name != names.value) { // should contain only one element, named "value" 918 log.error(pos, Errors.InvalidRepeatableAnnotation(annoDecl)); 919 return null; 920 } 921 if (!(p.snd instanceof Attribute.Class attributeClass)) { // check that the value of "value" is an Attribute.Class 922 log.error(pos, Errors.InvalidRepeatableAnnotation(annoDecl)); 923 return null; 924 } 925 926 return attributeClass.getValue(); 927 } 928 929 /* Validate that the suggested targetContainerType Type is a valid 930 * container type for repeated instances of originalAnnoType 931 * annotations. Return null and report errors if this is not the 932 * case, return the MethodSymbol of the value element in 933 * targetContainerType if it is suitable (this is needed to 934 * synthesize the container). */ 935 private MethodSymbol validateContainer(Type targetContainerType, 936 Type originalAnnoType, 937 DiagnosticPosition pos) { 938 MethodSymbol containerValueSymbol = null; 939 boolean fatalError = false; 940 941 // Validate that there is a (and only 1) value method 942 Scope scope = null; 943 try { 944 scope = targetContainerType.tsym.members(); 945 } catch (CompletionFailure ex) { 946 chk.completionError(pos, ex); 947 return null; 948 } 949 int nr_value_elems = 0; 950 boolean error = false; 951 for(Symbol elm : scope.getSymbolsByName(names.value)) { 952 nr_value_elems++; 953 954 if (nr_value_elems == 1 && 955 elm.kind == MTH) { 956 containerValueSymbol = (MethodSymbol)elm; 957 } else { 958 error = true; 959 } 960 } 961 if (error) { 962 log.error(pos, 963 Errors.InvalidRepeatableAnnotationMultipleValues(targetContainerType, 964 nr_value_elems)); 965 return null; 966 } else if (nr_value_elems == 0) { 967 log.error(pos, 968 Errors.InvalidRepeatableAnnotationNoValue(targetContainerType)); 969 return null; 970 } 971 972 // validate that the 'value' element is a method 973 // probably "impossible" to fail this 974 if (containerValueSymbol.kind != MTH) { 975 log.error(pos, 976 Errors.InvalidRepeatableAnnotationInvalidValue(targetContainerType)); 977 fatalError = true; 978 } 979 980 // validate that the 'value' element has the correct return type 981 // i.e. array of original anno 982 Type valueRetType = containerValueSymbol.type.getReturnType(); 983 Type expectedType = types.makeArrayType(originalAnnoType); 984 if (!(types.isArray(valueRetType) && 985 types.isSameType(expectedType, valueRetType))) { 986 log.error(pos, 987 Errors.InvalidRepeatableAnnotationValueReturn(targetContainerType, 988 valueRetType, 989 expectedType)); 990 fatalError = true; 991 } 992 993 return fatalError ? null : containerValueSymbol; 994 } 995 996 private <T extends Attribute.Compound> T makeContainerAnnotation(List<T> toBeReplaced, 997 AnnotationContext<T> ctx, Symbol sym, boolean isTypeParam) 998 { 999 // Process repeated annotations 1000 T validRepeated = 1001 processRepeatedAnnotations(toBeReplaced, ctx, sym, isTypeParam); 1002 1003 if (validRepeated != null) { 1004 // Check that the container isn't manually 1005 // present along with repeated instances of 1006 // its contained annotation. 1007 ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym); 1008 if (manualContainer != null) { 1009 log.error(ctx.pos.get(manualContainer.first()), 1010 Errors.InvalidRepeatableAnnotationRepeatedAndContainerPresent(manualContainer.first().type.tsym)); 1011 } 1012 } 1013 1014 // A null return will delete the Placeholder 1015 return validRepeated; 1016 } 1017 1018 /* ****************** 1019 * Type annotations * 1020 ********************/ 1021 1022 /** 1023 * Attribute the list of annotations and enter them onto s. 1024 */ 1025 public void enterTypeAnnotations(List<JCAnnotation> annotations, Env<AttrContext> env, Symbol s, boolean isTypeParam) 1026 { 1027 Assert.checkNonNull(s, "Symbol argument to actualEnterTypeAnnotations is nul/"); 1028 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 1029 1030 try { 1031 annotateNow(s, annotations, env, true, isTypeParam); 1032 } finally { 1033 log.useSource(prev); 1034 } 1035 } 1036 1037 /** 1038 * Enqueue tree for scanning of type annotations, attaching to the Symbol sym. 1039 */ 1040 public void queueScanTreeAndTypeAnnotate(JCTree tree, Env<AttrContext> env, Symbol sym) 1041 { 1042 Assert.checkNonNull(sym); 1043 normal(() -> tree.accept(new TypeAnnotate(env, sym))); 1044 } 1045 1046 /** 1047 * Apply the annotations to the particular type. 1048 */ 1049 public void annotateTypeSecondStage(JCTree tree, List<JCAnnotation> annotations, Type storeAt) { 1050 typeAnnotation(() -> { 1051 List<Attribute.TypeCompound> compounds = fromAnnotations(annotations); 1052 Assert.check(annotations.size() == compounds.size()); 1053 // the type already has annotation metadata, but it's empty 1054 Annotations metadata = storeAt.getMetadata(Annotations.class); 1055 Assert.checkNonNull(metadata); 1056 Assert.check(metadata.annotationBuffer().isEmpty()); 1057 metadata.annotationBuffer().appendList(compounds); 1058 }); 1059 } 1060 1061 /** 1062 * Apply the annotations to the particular type. 1063 */ 1064 public void annotateTypeParameterSecondStage(JCTree tree, List<JCAnnotation> annotations) { 1065 typeAnnotation(() -> { 1066 List<Attribute.TypeCompound> compounds = fromAnnotations(annotations); 1067 Assert.check(annotations.size() == compounds.size()); 1068 }); 1069 } 1070 1071 /** 1072 * We need to use a TreeScanner, because it is not enough to visit the top-level 1073 * annotations. We also need to visit type arguments, etc. 1074 */ 1075 private class TypeAnnotate extends TreeScanner { 1076 private final Env<AttrContext> env; 1077 private final Symbol sym; 1078 1079 public TypeAnnotate(Env<AttrContext> env, Symbol sym) { 1080 1081 this.env = env; 1082 this.sym = sym; 1083 } 1084 1085 @Override 1086 public void visitAnnotatedType(JCAnnotatedType tree) { 1087 enterTypeAnnotations(tree.annotations, env, sym, false); 1088 scan(tree.underlyingType); 1089 } 1090 1091 @Override 1092 public void visitTypeParameter(JCTypeParameter tree) { 1093 enterTypeAnnotations(tree.annotations, env, sym, true); 1094 scan(tree.bounds); 1095 } 1096 1097 @Override 1098 public void visitNewArray(JCNewArray tree) { 1099 enterTypeAnnotations(tree.annotations, env, sym, false); 1100 for (List<JCAnnotation> dimAnnos : tree.dimAnnotations) 1101 enterTypeAnnotations(dimAnnos, env, sym, false); 1102 scan(tree.elemtype); 1103 scan(tree.elems); 1104 } 1105 1106 @Override 1107 public void visitMethodDef(JCMethodDecl tree) { 1108 scan(tree.mods); 1109 scan(tree.restype); 1110 scan(tree.typarams); 1111 scan(tree.recvparam); 1112 scan(tree.params); 1113 scan(tree.thrown); 1114 scan(tree.defaultValue); 1115 // Do not annotate the body, just the signature. 1116 } 1117 1118 @Override 1119 public void visitVarDef(JCVariableDecl tree) { 1120 if (sym != null && sym.kind == VAR) { 1121 // Don't visit a parameter once when the sym is the method 1122 // and once when the sym is the parameter. 1123 scan(tree.mods); 1124 scan(tree.vartype); 1125 } 1126 scan(tree.init); 1127 } 1128 1129 @Override 1130 public void visitBindingPattern(JCTree.JCBindingPattern tree) { 1131 //type binding pattern's type will be annotated separately, avoid 1132 //adding its annotations into the owning method here (would clash 1133 //with repeatable annotations). 1134 } 1135 1136 @Override 1137 public void visitClassDef(JCClassDecl tree) { 1138 // We can only hit a classdef if it is declared within 1139 // a method. Ignore it - the class will be visited 1140 // separately later. 1141 } 1142 1143 @Override 1144 public void visitNewClass(JCNewClass tree) { 1145 scan(tree.encl); 1146 scan(tree.typeargs); 1147 if (tree.def == null) { 1148 scan(tree.clazz); 1149 } 1150 scan(tree.args); 1151 // the anonymous class instantiation if any will be visited separately. 1152 } 1153 1154 @Override 1155 public void visitErroneous(JCErroneous tree) { 1156 if (tree.errs != null) { 1157 for (JCTree err : tree.errs) { 1158 scan(err); 1159 } 1160 } 1161 } 1162 } 1163 1164 /* ******************* 1165 * Completer support * 1166 *********************/ 1167 1168 private AnnotationTypeCompleter theSourceCompleter = new AnnotationTypeCompleter() { 1169 @Override 1170 public void complete(ClassSymbol sym) throws CompletionFailure { 1171 Env<AttrContext> context = typeEnvs.get(sym); 1172 Annotate.this.attributeAnnotationType(context); 1173 } 1174 }; 1175 1176 /* Last stage completer to enter just enough annotations to have a prototype annotation type. 1177 * This currently means entering @Target and @Repeatable. 1178 */ 1179 public AnnotationTypeCompleter annotationTypeSourceCompleter() { 1180 return theSourceCompleter; 1181 } 1182 1183 private void attributeAnnotationType(Env<AttrContext> env) { 1184 Assert.check(((JCClassDecl)env.tree).sym.isAnnotationType(), 1185 "Trying to annotation type complete a non-annotation type"); 1186 1187 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 1188 try { 1189 JCClassDecl tree = (JCClassDecl)env.tree; 1190 AnnotationTypeVisitor v = new AnnotationTypeVisitor(attr, chk, syms, typeEnvs); 1191 v.scanAnnotationType(tree); 1192 tree.sym.getAnnotationTypeMetadata().setRepeatable(v.repeatable); 1193 tree.sym.getAnnotationTypeMetadata().setTarget(v.target); 1194 } finally { 1195 log.useSource(prev); 1196 } 1197 } 1198 1199 public Attribute unfinishedDefaultValue() { 1200 return theUnfinishedDefaultValue; 1201 } 1202 1203 public static interface AnnotationTypeCompleter { 1204 void complete(ClassSymbol sym) throws CompletionFailure; 1205 } 1206 1207 /** Visitor to determine a prototype annotation type for a class declaring an annotation type. 1208 * 1209 * <p><b>This is NOT part of any supported API. 1210 * If you write code that depends on this, you do so at your own risk. 1211 * This code and its internal interfaces are subject to change or 1212 * deletion without notice.</b> 1213 */ 1214 public class AnnotationTypeVisitor extends TreeScanner { 1215 private Env<AttrContext> env; 1216 1217 private final Attr attr; 1218 private final Check check; 1219 private final Symtab tab; 1220 private final TypeEnvs typeEnvs; 1221 1222 private Compound target; 1223 private Compound repeatable; 1224 1225 public AnnotationTypeVisitor(Attr attr, Check check, Symtab tab, TypeEnvs typeEnvs) { 1226 this.attr = attr; 1227 this.check = check; 1228 this.tab = tab; 1229 this.typeEnvs = typeEnvs; 1230 } 1231 1232 public Compound getRepeatable() { 1233 return repeatable; 1234 } 1235 1236 public Compound getTarget() { 1237 return target; 1238 } 1239 1240 public void scanAnnotationType(JCClassDecl decl) { 1241 visitClassDef(decl); 1242 } 1243 1244 @Override 1245 public void visitClassDef(JCClassDecl tree) { 1246 Env<AttrContext> prevEnv = env; 1247 env = typeEnvs.get(tree.sym); 1248 try { 1249 scan(tree.mods); // look for repeatable and target 1250 // don't descend into body 1251 } finally { 1252 env = prevEnv; 1253 } 1254 } 1255 1256 @Override 1257 public void visitAnnotation(JCAnnotation tree) { 1258 Type t = tree.annotationType.type; 1259 if (t == null) { 1260 t = attr.attribType(tree.annotationType, env); 1261 tree.annotationType.type = t = check.checkType(tree.annotationType.pos(), t, tab.annotationType); 1262 } 1263 1264 if (t == tab.annotationTargetType) { 1265 target = Annotate.this.attributeAnnotation(tree, tab.annotationTargetType, env); 1266 } else if (t == tab.repeatableType) { 1267 repeatable = Annotate.this.attributeAnnotation(tree, tab.repeatableType, env); 1268 } 1269 } 1270 } 1271 1272 /** Represents the semantics of an Annotation Type. 1273 * 1274 * <p><b>This is NOT part of any supported API. 1275 * If you write code that depends on this, you do so at your own risk. 1276 * This code and its internal interfaces are subject to change or 1277 * deletion without notice.</b> 1278 */ 1279 public static class AnnotationTypeMetadata { 1280 final ClassSymbol metaDataFor; 1281 private Compound target; 1282 private Compound repeatable; 1283 private AnnotationTypeCompleter annotationTypeCompleter; 1284 1285 public AnnotationTypeMetadata(ClassSymbol metaDataFor, AnnotationTypeCompleter annotationTypeCompleter) { 1286 this.metaDataFor = metaDataFor; 1287 this.annotationTypeCompleter = annotationTypeCompleter; 1288 } 1289 1290 private void init() { 1291 // Make sure metaDataFor is member entered 1292 while (!metaDataFor.isCompleted()) 1293 metaDataFor.complete(); 1294 1295 if (annotationTypeCompleter != null) { 1296 AnnotationTypeCompleter c = annotationTypeCompleter; 1297 annotationTypeCompleter = null; 1298 c.complete(metaDataFor); 1299 } 1300 } 1301 1302 public void complete() { 1303 init(); 1304 } 1305 1306 public Compound getRepeatable() { 1307 init(); 1308 return repeatable; 1309 } 1310 1311 public void setRepeatable(Compound repeatable) { 1312 Assert.checkNull(this.repeatable); 1313 this.repeatable = repeatable; 1314 } 1315 1316 public Compound getTarget() { 1317 init(); 1318 return target; 1319 } 1320 1321 public void setTarget(Compound target) { 1322 Assert.checkNull(this.target); 1323 this.target = target; 1324 } 1325 1326 public Set<MethodSymbol> getAnnotationElements() { 1327 init(); 1328 Set<MethodSymbol> members = new LinkedHashSet<>(); 1329 WriteableScope s = metaDataFor.members(); 1330 Iterable<Symbol> ss = s.getSymbols(NON_RECURSIVE); 1331 for (Symbol sym : ss) 1332 if (sym.kind == MTH && 1333 sym.name != sym.name.table.names.clinit && 1334 (sym.flags() & SYNTHETIC) == 0) 1335 members.add((MethodSymbol)sym); 1336 return members; 1337 } 1338 1339 public Set<MethodSymbol> getAnnotationElementsWithDefault() { 1340 init(); 1341 Set<MethodSymbol> members = getAnnotationElements(); 1342 Set<MethodSymbol> res = new LinkedHashSet<>(); 1343 for (MethodSymbol m : members) 1344 if (m.defaultValue != null) 1345 res.add(m); 1346 return res; 1347 } 1348 1349 @Override 1350 public String toString() { 1351 return "Annotation type for: " + metaDataFor; 1352 } 1353 1354 public boolean isMetadataForAnnotationType() { return true; } 1355 1356 public static AnnotationTypeMetadata notAnAnnotationType() { 1357 return NOT_AN_ANNOTATION_TYPE; 1358 } 1359 1360 private static final AnnotationTypeMetadata NOT_AN_ANNOTATION_TYPE = 1361 new AnnotationTypeMetadata(null, null) { 1362 @Override 1363 public void complete() { 1364 } // do nothing 1365 1366 @Override 1367 public String toString() { 1368 return "Not an annotation type"; 1369 } 1370 1371 @Override 1372 public Set<MethodSymbol> getAnnotationElements() { 1373 return new LinkedHashSet<>(0); 1374 } 1375 1376 @Override 1377 public Set<MethodSymbol> getAnnotationElementsWithDefault() { 1378 return new LinkedHashSet<>(0); 1379 } 1380 1381 @Override 1382 public boolean isMetadataForAnnotationType() { 1383 return false; 1384 } 1385 1386 @Override 1387 public Compound getTarget() { 1388 return null; 1389 } 1390 1391 @Override 1392 public Compound getRepeatable() { 1393 return null; 1394 } 1395 }; 1396 } 1397 1398 public void newRound() { 1399 blockCount = 1; 1400 } 1401 1402 public Queues setQueues(Queues nue) { 1403 Queues stored = new Queues(q, validateQ, typesQ, afterTypesQ); 1404 this.q = nue.q; 1405 this.typesQ = nue.typesQ; 1406 this.afterTypesQ = nue.afterTypesQ; 1407 this.validateQ = nue.validateQ; 1408 return stored; 1409 } 1410 1411 static class Queues { 1412 private final ListBuffer<Runnable> q; 1413 private final ListBuffer<Runnable> validateQ; 1414 private final ListBuffer<Runnable> typesQ; 1415 private final ListBuffer<Runnable> afterTypesQ; 1416 1417 public Queues() { 1418 this(new ListBuffer<Runnable>(), new ListBuffer<Runnable>(), new ListBuffer<Runnable>(), new ListBuffer<Runnable>()); 1419 } 1420 1421 public Queues(ListBuffer<Runnable> q, ListBuffer<Runnable> validateQ, ListBuffer<Runnable> typesQ, ListBuffer<Runnable> afterTypesQ) { 1422 this.q = q; 1423 this.validateQ = validateQ; 1424 this.typesQ = typesQ; 1425 this.afterTypesQ = afterTypesQ; 1426 } 1427 } 1428 }