JavacElements.java revision 3923:923a093b4bd8
1/* 2 * Copyright (c) 2005, 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 26package com.sun.tools.javac.model; 27 28import java.util.HashSet; 29import java.util.LinkedHashSet; 30import java.util.Map; 31import java.util.Set; 32import java.util.stream.Collectors; 33 34import javax.lang.model.AnnotatedConstruct; 35import javax.lang.model.SourceVersion; 36import javax.lang.model.element.*; 37import javax.lang.model.type.DeclaredType; 38import javax.lang.model.util.Elements; 39import javax.tools.JavaFileObject; 40import static javax.lang.model.util.ElementFilter.methodsIn; 41 42import com.sun.source.util.JavacTask; 43import com.sun.tools.javac.api.JavacTaskImpl; 44import com.sun.tools.javac.code.*; 45import com.sun.tools.javac.code.Attribute.Compound; 46import com.sun.tools.javac.code.Directive.ExportsDirective; 47import com.sun.tools.javac.code.Directive.ExportsFlag; 48import com.sun.tools.javac.code.Directive.OpensDirective; 49import com.sun.tools.javac.code.Directive.OpensFlag; 50import com.sun.tools.javac.code.Directive.RequiresDirective; 51import com.sun.tools.javac.code.Directive.RequiresFlag; 52import com.sun.tools.javac.code.Scope.WriteableScope; 53import com.sun.tools.javac.code.Symbol.*; 54import com.sun.tools.javac.comp.AttrContext; 55import com.sun.tools.javac.comp.Enter; 56import com.sun.tools.javac.comp.Env; 57import com.sun.tools.javac.main.JavaCompiler; 58import com.sun.tools.javac.processing.PrintingProcessor; 59import com.sun.tools.javac.tree.JCTree; 60import com.sun.tools.javac.tree.JCTree.*; 61import com.sun.tools.javac.tree.TreeInfo; 62import com.sun.tools.javac.tree.TreeScanner; 63import com.sun.tools.javac.util.*; 64import com.sun.tools.javac.util.DefinedBy.Api; 65import com.sun.tools.javac.util.Name; 66import static com.sun.tools.javac.code.Kinds.Kind.*; 67import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 68import static com.sun.tools.javac.code.TypeTag.CLASS; 69import com.sun.tools.javac.comp.Modules; 70import com.sun.tools.javac.comp.Resolve; 71import com.sun.tools.javac.comp.Resolve.RecoveryLoadClass; 72import com.sun.tools.javac.resources.CompilerProperties.Notes; 73import static com.sun.tools.javac.tree.JCTree.Tag.*; 74 75/** 76 * Utility methods for operating on program elements. 77 * 78 * <p><b>This is NOT part of any supported API. 79 * If you write code that depends on this, you do so at your own 80 * risk. This code and its internal interfaces are subject to change 81 * or deletion without notice.</b></p> 82 */ 83public class JavacElements implements Elements { 84 85 private final JavaCompiler javaCompiler; 86 private final Symtab syms; 87 private final Modules modules; 88 private final Names names; 89 private final Types types; 90 private final Enter enter; 91 private final Resolve resolve; 92 private final JavacTaskImpl javacTaskImpl; 93 private final Log log; 94 private final boolean allowModules; 95 96 public static JavacElements instance(Context context) { 97 JavacElements instance = context.get(JavacElements.class); 98 if (instance == null) 99 instance = new JavacElements(context); 100 return instance; 101 } 102 103 protected JavacElements(Context context) { 104 context.put(JavacElements.class, this); 105 javaCompiler = JavaCompiler.instance(context); 106 syms = Symtab.instance(context); 107 modules = Modules.instance(context); 108 names = Names.instance(context); 109 types = Types.instance(context); 110 enter = Enter.instance(context); 111 resolve = Resolve.instance(context); 112 JavacTask t = context.get(JavacTask.class); 113 javacTaskImpl = t instanceof JavacTaskImpl ? (JavacTaskImpl) t : null; 114 log = Log.instance(context); 115 Source source = Source.instance(context); 116 allowModules = source.allowModules(); 117 } 118 119 @Override @DefinedBy(Api.LANGUAGE_MODEL) 120 public ModuleSymbol getModuleElement(CharSequence name) { 121 ensureEntered("getModuleElement"); 122 if (modules.getDefaultModule() == syms.noModule) 123 return null; 124 String strName = name.toString(); 125 if (strName.equals("")) 126 return syms.unnamedModule; 127 return modules.getObservableModule(names.fromString(strName)); 128 } 129 130 @Override @DefinedBy(Api.LANGUAGE_MODEL) 131 public PackageSymbol getPackageElement(CharSequence name) { 132 return doGetPackageElement(null, name); 133 } 134 135 @Override @DefinedBy(Api.LANGUAGE_MODEL) 136 public PackageSymbol getPackageElement(ModuleElement module, CharSequence name) { 137 module.getClass(); 138 return doGetPackageElement(module, name); 139 } 140 141 private PackageSymbol doGetPackageElement(ModuleElement module, CharSequence name) { 142 ensureEntered("getPackageElement"); 143 return doGetElement(module, "getPackageElement", name, PackageSymbol.class); 144 } 145 146 @Override @DefinedBy(Api.LANGUAGE_MODEL) 147 public ClassSymbol getTypeElement(CharSequence name) { 148 return doGetTypeElement(null, name); 149 } 150 151 @Override @DefinedBy(Api.LANGUAGE_MODEL) 152 public ClassSymbol getTypeElement(ModuleElement module, CharSequence name) { 153 module.getClass(); 154 155 return doGetTypeElement(module, name); 156 } 157 158 private ClassSymbol doGetTypeElement(ModuleElement module, CharSequence name) { 159 ensureEntered("getTypeElement"); 160 return doGetElement(module, "getTypeElement", name, ClassSymbol.class); 161 } 162 163 private <S extends Symbol> S doGetElement(ModuleElement module, String methodName, 164 CharSequence name, Class<S> clazz) { 165 String strName = name.toString(); 166 if (!SourceVersion.isName(strName) && (!strName.isEmpty() || clazz == ClassSymbol.class)) { 167 return null; 168 } 169 if (module == null) { 170 return unboundNameToSymbol(methodName, strName, clazz); 171 } else { 172 return nameToSymbol((ModuleSymbol) module, strName, clazz); 173 } 174 } 175 176 private final Set<String> alreadyWarnedDuplicates = new HashSet<>(); 177 178 private <S extends Symbol> S unboundNameToSymbol(String methodName, 179 String nameStr, 180 Class<S> clazz) { 181 if (modules.getDefaultModule() == syms.noModule) { //not a modular mode: 182 return nameToSymbol(syms.noModule, nameStr, clazz); 183 } 184 185 Set<S> found = new LinkedHashSet<>(); 186 187 for (ModuleSymbol msym : modules.allModules()) { 188 S sym = nameToSymbol(msym, nameStr, clazz); 189 190 if (sym != null) { 191 if (!allowModules || clazz == ClassSymbol.class || !sym.members().isEmpty()) { 192 //do not add packages without members: 193 found.add(sym); 194 } 195 } 196 } 197 198 if (found.size() == 1) { 199 return found.iterator().next(); 200 } else if (found.size() > 1) { 201 //more than one element found, produce a note: 202 if (alreadyWarnedDuplicates.add(methodName + ":" + nameStr)) { 203 String moduleNames = found.stream() 204 .map(s -> s.packge().modle) 205 .map(m -> m.toString()) 206 .collect(Collectors.joining(", ")); 207 log.note(Notes.MultipleElements(methodName, nameStr, moduleNames)); 208 } 209 return null; 210 } else { 211 //not found, or more than one element found: 212 return null; 213 } 214 } 215 216 /** 217 * Returns a symbol given the type's or package's canonical name, 218 * or null if the name isn't found. 219 */ 220 private <S extends Symbol> S nameToSymbol(ModuleSymbol module, String nameStr, Class<S> clazz) { 221 Name name = names.fromString(nameStr); 222 // First check cache. 223 Symbol sym = (clazz == ClassSymbol.class) 224 ? syms.getClass(module, name) 225 : syms.lookupPackage(module, name); 226 227 try { 228 if (sym == null) 229 sym = javaCompiler.resolveIdent(module, nameStr); 230 231 sym.complete(); 232 233 return (sym.kind != ERR && 234 sym.exists() && 235 clazz.isInstance(sym) && 236 name.equals(sym.getQualifiedName())) 237 ? clazz.cast(sym) 238 : null; 239 } catch (CompletionFailure e) { 240 return null; 241 } 242 } 243 244 /** 245 * Returns the tree for an annotation given the annotated element 246 * and the element's own tree. Returns null if the tree cannot be found. 247 */ 248 private JCTree matchAnnoToTree(AnnotationMirror findme, 249 Element e, JCTree tree) { 250 Symbol sym = cast(Symbol.class, e); 251 class Vis extends JCTree.Visitor { 252 List<JCAnnotation> result = null; 253 public void visitPackageDef(JCPackageDecl tree) { 254 result = tree.annotations; 255 } 256 public void visitClassDef(JCClassDecl tree) { 257 result = tree.mods.annotations; 258 } 259 public void visitMethodDef(JCMethodDecl tree) { 260 result = tree.mods.annotations; 261 } 262 public void visitVarDef(JCVariableDecl tree) { 263 result = tree.mods.annotations; 264 } 265 @Override 266 public void visitTypeParameter(JCTypeParameter tree) { 267 result = tree.annotations; 268 } 269 } 270 Vis vis = new Vis(); 271 tree.accept(vis); 272 if (vis.result == null) 273 return null; 274 275 List<Attribute.Compound> annos = sym.getAnnotationMirrors(); 276 return matchAnnoToTree(cast(Attribute.Compound.class, findme), 277 annos, 278 vis.result); 279 } 280 281 /** 282 * Returns the tree for an annotation given a list of annotations 283 * in which to search (recursively) and their corresponding trees. 284 * Returns null if the tree cannot be found. 285 */ 286 private JCTree matchAnnoToTree(Attribute.Compound findme, 287 List<Attribute.Compound> annos, 288 List<JCAnnotation> trees) { 289 for (Attribute.Compound anno : annos) { 290 for (JCAnnotation tree : trees) { 291 JCTree match = matchAnnoToTree(findme, anno, tree); 292 if (match != null) 293 return match; 294 } 295 } 296 return null; 297 } 298 299 /** 300 * Returns the tree for an annotation given an Attribute to 301 * search (recursively) and its corresponding tree. 302 * Returns null if the tree cannot be found. 303 */ 304 private JCTree matchAnnoToTree(final Attribute.Compound findme, 305 final Attribute attr, 306 final JCTree tree) { 307 if (attr == findme) 308 return (tree.type.tsym == findme.type.tsym) ? tree : null; 309 310 class Vis implements Attribute.Visitor { 311 JCTree result = null; 312 public void visitConstant(Attribute.Constant value) { 313 } 314 public void visitClass(Attribute.Class clazz) { 315 } 316 public void visitCompound(Attribute.Compound anno) { 317 for (Pair<MethodSymbol, Attribute> pair : anno.values) { 318 JCExpression expr = scanForAssign(pair.fst, tree); 319 if (expr != null) { 320 JCTree match = matchAnnoToTree(findme, pair.snd, expr); 321 if (match != null) { 322 result = match; 323 return; 324 } 325 } 326 } 327 } 328 public void visitArray(Attribute.Array array) { 329 if (tree.hasTag(NEWARRAY) && 330 types.elemtype(array.type).tsym == findme.type.tsym) { 331 List<JCExpression> elems = ((JCNewArray) tree).elems; 332 for (Attribute value : array.values) { 333 if (value == findme) { 334 result = elems.head; 335 return; 336 } 337 elems = elems.tail; 338 } 339 } 340 } 341 public void visitEnum(Attribute.Enum e) { 342 } 343 public void visitError(Attribute.Error e) { 344 } 345 } 346 Vis vis = new Vis(); 347 attr.accept(vis); 348 return vis.result; 349 } 350 351 /** 352 * Scans for a JCAssign node with a LHS matching a given 353 * symbol, and returns its RHS. Does not scan nested JCAnnotations. 354 */ 355 private JCExpression scanForAssign(final MethodSymbol sym, 356 final JCTree tree) { 357 class TS extends TreeScanner { 358 JCExpression result = null; 359 public void scan(JCTree t) { 360 if (t != null && result == null) 361 t.accept(this); 362 } 363 public void visitAnnotation(JCAnnotation t) { 364 if (t == tree) 365 scan(t.args); 366 } 367 public void visitAssign(JCAssign t) { 368 if (t.lhs.hasTag(IDENT)) { 369 JCIdent ident = (JCIdent) t.lhs; 370 if (ident.sym == sym) 371 result = t.rhs; 372 } 373 } 374 } 375 TS scanner = new TS(); 376 tree.accept(scanner); 377 return scanner.result; 378 } 379 380 /** 381 * Returns the tree node corresponding to this element, or null 382 * if none can be found. 383 */ 384 public JCTree getTree(Element e) { 385 Pair<JCTree, ?> treeTop = getTreeAndTopLevel(e); 386 return (treeTop != null) ? treeTop.fst : null; 387 } 388 389 @DefinedBy(Api.LANGUAGE_MODEL) 390 public String getDocComment(Element e) { 391 // Our doc comment is contained in a map in our toplevel, 392 // indexed by our tree. Find our enter environment, which gives 393 // us our toplevel. It also gives us a tree that contains our 394 // tree: walk it to find our tree. This is painful. 395 Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); 396 if (treeTop == null) 397 return null; 398 JCTree tree = treeTop.fst; 399 JCCompilationUnit toplevel = treeTop.snd; 400 if (toplevel.docComments == null) 401 return null; 402 return toplevel.docComments.getCommentText(tree); 403 } 404 405 @DefinedBy(Api.LANGUAGE_MODEL) 406 public PackageElement getPackageOf(Element e) { 407 return cast(Symbol.class, e).packge(); 408 } 409 410 @DefinedBy(Api.LANGUAGE_MODEL) 411 public ModuleElement getModuleOf(Element e) { 412 Symbol sym = cast(Symbol.class, e); 413 if (modules.getDefaultModule() == syms.noModule) 414 return null; 415 return (sym.kind == MDL) ? ((ModuleElement) e) : sym.packge().modle; 416 } 417 418 @DefinedBy(Api.LANGUAGE_MODEL) 419 public boolean isDeprecated(Element e) { 420 Symbol sym = cast(Symbol.class, e); 421 sym.complete(); 422 return sym.isDeprecated(); 423 } 424 425 @Override @DefinedBy(Api.LANGUAGE_MODEL) 426 public Origin getOrigin(Element e) { 427 Symbol sym = cast(Symbol.class, e); 428 if ((sym.flags() & Flags.GENERATEDCONSTR) != 0) 429 return Origin.MANDATED; 430 //TypeElement.getEnclosedElements does not return synthetic elements, 431 //and most synthetic elements are not read from the classfile anyway: 432 return Origin.EXPLICIT; 433 } 434 435 @Override @DefinedBy(Api.LANGUAGE_MODEL) 436 public Origin getOrigin(AnnotatedConstruct c, AnnotationMirror a) { 437 Compound ac = cast(Compound.class, a); 438 if (ac.isSynthesized()) 439 return Origin.MANDATED; 440 return Origin.EXPLICIT; 441 } 442 443 @Override @DefinedBy(Api.LANGUAGE_MODEL) 444 public Origin getOrigin(ModuleElement m, ModuleElement.Directive directive) { 445 switch (directive.getKind()) { 446 case REQUIRES: 447 RequiresDirective rd = cast(RequiresDirective.class, directive); 448 if (rd.flags.contains(RequiresFlag.MANDATED)) 449 return Origin.MANDATED; 450 if (rd.flags.contains(RequiresFlag.SYNTHETIC)) 451 return Origin.SYNTHETIC; 452 return Origin.EXPLICIT; 453 case EXPORTS: 454 ExportsDirective ed = cast(ExportsDirective.class, directive); 455 if (ed.flags.contains(ExportsFlag.MANDATED)) 456 return Origin.MANDATED; 457 if (ed.flags.contains(ExportsFlag.SYNTHETIC)) 458 return Origin.SYNTHETIC; 459 return Origin.EXPLICIT; 460 case OPENS: 461 OpensDirective od = cast(OpensDirective.class, directive); 462 if (od.flags.contains(OpensFlag.MANDATED)) 463 return Origin.MANDATED; 464 if (od.flags.contains(OpensFlag.SYNTHETIC)) 465 return Origin.SYNTHETIC; 466 return Origin.EXPLICIT; 467 } 468 return Origin.EXPLICIT; 469 } 470 471 @DefinedBy(Api.LANGUAGE_MODEL) 472 public Name getBinaryName(TypeElement type) { 473 return cast(TypeSymbol.class, type).flatName(); 474 } 475 476 @DefinedBy(Api.LANGUAGE_MODEL) 477 public Map<MethodSymbol, Attribute> getElementValuesWithDefaults( 478 AnnotationMirror a) { 479 Attribute.Compound anno = cast(Attribute.Compound.class, a); 480 DeclaredType annotype = a.getAnnotationType(); 481 Map<MethodSymbol, Attribute> valmap = anno.getElementValues(); 482 483 for (ExecutableElement ex : 484 methodsIn(annotype.asElement().getEnclosedElements())) { 485 MethodSymbol meth = (MethodSymbol) ex; 486 Attribute defaultValue = meth.getDefaultValue(); 487 if (defaultValue != null && !valmap.containsKey(meth)) { 488 valmap.put(meth, defaultValue); 489 } 490 } 491 return valmap; 492 } 493 494 /** 495 * {@inheritDoc} 496 */ 497 @DefinedBy(Api.LANGUAGE_MODEL) 498 public FilteredMemberList getAllMembers(TypeElement element) { 499 Symbol sym = cast(Symbol.class, element); 500 WriteableScope scope = sym.members().dupUnshared(); 501 List<Type> closure = types.closure(sym.asType()); 502 for (Type t : closure) 503 addMembers(scope, t); 504 return new FilteredMemberList(scope); 505 } 506 // where 507 private void addMembers(WriteableScope scope, Type type) { 508 members: 509 for (Symbol e : type.asElement().members().getSymbols(NON_RECURSIVE)) { 510 for (Symbol overrider : scope.getSymbolsByName(e.getSimpleName())) { 511 if (overrider.kind == e.kind && (overrider.flags() & Flags.SYNTHETIC) == 0) { 512 if (overrider.getKind() == ElementKind.METHOD && 513 overrides((ExecutableElement)overrider, (ExecutableElement)e, (TypeElement)type.asElement())) { 514 continue members; 515 } 516 } 517 } 518 boolean derived = e.getEnclosingElement() != scope.owner; 519 ElementKind kind = e.getKind(); 520 boolean initializer = kind == ElementKind.CONSTRUCTOR 521 || kind == ElementKind.INSTANCE_INIT 522 || kind == ElementKind.STATIC_INIT; 523 if (!derived || (!initializer && e.isInheritedIn(scope.owner, types))) 524 scope.enter(e); 525 } 526 } 527 528 /** 529 * Returns all annotations of an element, whether 530 * inherited or directly present. 531 * 532 * @param e the element being examined 533 * @return all annotations of the element 534 */ 535 @Override @DefinedBy(Api.LANGUAGE_MODEL) 536 public List<Attribute.Compound> getAllAnnotationMirrors(Element e) { 537 Symbol sym = cast(Symbol.class, e); 538 List<Attribute.Compound> annos = sym.getAnnotationMirrors(); 539 while (sym.getKind() == ElementKind.CLASS) { 540 Type sup = ((ClassSymbol) sym).getSuperclass(); 541 if (!sup.hasTag(CLASS) || sup.isErroneous() || 542 sup.tsym == syms.objectType.tsym) { 543 break; 544 } 545 sym = sup.tsym; 546 List<Attribute.Compound> oldAnnos = annos; 547 List<Attribute.Compound> newAnnos = sym.getAnnotationMirrors(); 548 for (Attribute.Compound anno : newAnnos) { 549 if (isInherited(anno.type) && 550 !containsAnnoOfType(oldAnnos, anno.type)) { 551 annos = annos.prepend(anno); 552 } 553 } 554 } 555 return annos; 556 } 557 558 /** 559 * Tests whether an annotation type is @Inherited. 560 */ 561 private boolean isInherited(Type annotype) { 562 return annotype.tsym.attribute(syms.inheritedType.tsym) != null; 563 } 564 565 /** 566 * Tests whether a list of annotations contains an annotation 567 * of a given type. 568 */ 569 private static boolean containsAnnoOfType(List<Attribute.Compound> annos, 570 Type type) { 571 for (Attribute.Compound anno : annos) { 572 if (anno.type.tsym == type.tsym) 573 return true; 574 } 575 return false; 576 } 577 578 @DefinedBy(Api.LANGUAGE_MODEL) 579 public boolean hides(Element hiderEl, Element hideeEl) { 580 Symbol hider = cast(Symbol.class, hiderEl); 581 Symbol hidee = cast(Symbol.class, hideeEl); 582 583 // Fields only hide fields; methods only methods; types only types. 584 // Names must match. Nothing hides itself (just try it). 585 if (hider == hidee || 586 hider.kind != hidee.kind || 587 hider.name != hidee.name) { 588 return false; 589 } 590 591 // Only static methods can hide other methods. 592 // Methods only hide methods with matching signatures. 593 if (hider.kind == MTH) { 594 if (!hider.isStatic() || 595 !types.isSubSignature(hider.type, hidee.type)) { 596 return false; 597 } 598 } 599 600 // Hider must be in a subclass of hidee's class. 601 // Note that if M1 hides M2, and M2 hides M3, and M3 is accessible 602 // in M1's class, then M1 and M2 both hide M3. 603 ClassSymbol hiderClass = hider.owner.enclClass(); 604 ClassSymbol hideeClass = hidee.owner.enclClass(); 605 if (hiderClass == null || hideeClass == null || 606 !hiderClass.isSubClass(hideeClass, types)) { 607 return false; 608 } 609 610 // Hidee must be accessible in hider's class. 611 // The method isInheritedIn is poorly named: it checks only access. 612 return hidee.isInheritedIn(hiderClass, types); 613 } 614 615 @DefinedBy(Api.LANGUAGE_MODEL) 616 public boolean overrides(ExecutableElement riderEl, 617 ExecutableElement rideeEl, TypeElement typeEl) { 618 MethodSymbol rider = cast(MethodSymbol.class, riderEl); 619 MethodSymbol ridee = cast(MethodSymbol.class, rideeEl); 620 ClassSymbol origin = cast(ClassSymbol.class, typeEl); 621 622 return rider.name == ridee.name && 623 624 // not reflexive as per JLS 625 rider != ridee && 626 627 // we don't care if ridee is static, though that wouldn't 628 // compile 629 !rider.isStatic() && 630 631 // Symbol.overrides assumes the following 632 ridee.isMemberOf(origin, types) && 633 634 // check access and signatures; don't check return types 635 rider.overrides(ridee, origin, types, false); 636 } 637 638 @DefinedBy(Api.LANGUAGE_MODEL) 639 public String getConstantExpression(Object value) { 640 return Constants.format(value); 641 } 642 643 /** 644 * Print a representation of the elements to the given writer in 645 * the specified order. The main purpose of this method is for 646 * diagnostics. The exact format of the output is <em>not</em> 647 * specified and is subject to change. 648 * 649 * @param w the writer to print the output to 650 * @param elements the elements to print 651 */ 652 @DefinedBy(Api.LANGUAGE_MODEL) 653 public void printElements(java.io.Writer w, Element... elements) { 654 for (Element element : elements) 655 (new PrintingProcessor.PrintingElementVisitor(w, this)).visit(element).flush(); 656 } 657 658 @DefinedBy(Api.LANGUAGE_MODEL) 659 public Name getName(CharSequence cs) { 660 return names.fromString(cs.toString()); 661 } 662 663 @Override @DefinedBy(Api.LANGUAGE_MODEL) 664 public boolean isFunctionalInterface(TypeElement element) { 665 if (element.getKind() != ElementKind.INTERFACE) 666 return false; 667 else { 668 TypeSymbol tsym = cast(TypeSymbol.class, element); 669 return types.isFunctionalInterface(tsym); 670 } 671 } 672 673 /** 674 * Returns the tree node and compilation unit corresponding to this 675 * element, or null if they can't be found. 676 */ 677 private Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(Element e) { 678 Symbol sym = cast(Symbol.class, e); 679 Env<AttrContext> enterEnv = getEnterEnv(sym); 680 if (enterEnv == null) 681 return null; 682 JCTree tree = TreeInfo.declarationFor(sym, enterEnv.tree); 683 if (tree == null || enterEnv.toplevel == null) 684 return null; 685 return new Pair<>(tree, enterEnv.toplevel); 686 } 687 688 /** 689 * Returns the best approximation for the tree node and compilation unit 690 * corresponding to the given element, annotation and value. 691 * If the element is null, null is returned. 692 * If the annotation is null or cannot be found, the tree node and 693 * compilation unit for the element is returned. 694 * If the annotation value is null or cannot be found, the tree node and 695 * compilation unit for the annotation is returned. 696 */ 697 public Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel( 698 Element e, AnnotationMirror a, AnnotationValue v) { 699 if (e == null) 700 return null; 701 702 Pair<JCTree, JCCompilationUnit> elemTreeTop = getTreeAndTopLevel(e); 703 if (elemTreeTop == null) 704 return null; 705 706 if (a == null) 707 return elemTreeTop; 708 709 JCTree annoTree = matchAnnoToTree(a, e, elemTreeTop.fst); 710 if (annoTree == null) 711 return elemTreeTop; 712 713 // 6388543: if v != null, we should search within annoTree to find 714 // the tree matching v. For now, we ignore v and return the tree of 715 // the annotation. 716 return new Pair<>(annoTree, elemTreeTop.snd); 717 } 718 719 /** 720 * Returns a symbol's enter environment, or null if it has none. 721 */ 722 private Env<AttrContext> getEnterEnv(Symbol sym) { 723 // Get enclosing class of sym, or sym itself if it is a class 724 // package, or module. 725 TypeSymbol ts = null; 726 switch (sym.kind) { 727 case PCK: 728 ts = (PackageSymbol)sym; 729 break; 730 case MDL: 731 ts = (ModuleSymbol)sym; 732 break; 733 default: 734 ts = sym.enclClass(); 735 } 736 return (ts != null) 737 ? enter.getEnv(ts) 738 : null; 739 } 740 741 private void ensureEntered(String methodName) { 742 if (javacTaskImpl != null) { 743 javacTaskImpl.ensureEntered(); 744 } 745 if (!javaCompiler.isEnterDone()) { 746 throw new IllegalStateException("Cannot use Elements." + methodName + " before the TaskEvent.Kind.ENTER finished event."); 747 } 748 } 749 750 /** 751 * Returns an object cast to the specified type. 752 * @throws NullPointerException if the object is {@code null} 753 * @throws IllegalArgumentException if the object is of the wrong type 754 */ 755 private static <T> T cast(Class<T> clazz, Object o) { 756 if (! clazz.isInstance(o)) 757 throw new IllegalArgumentException(o.toString()); 758 return clazz.cast(o); 759 } 760} 761