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