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