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