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