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