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