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