JavacElements.java revision 3826:0939cac53f1d
11573Srgrimes/* 214272Spst * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 31573Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41573Srgrimes * 51573Srgrimes * This code is free software; you can redistribute it and/or modify it 61573Srgrimes * under the terms of the GNU General Public License version 2 only, as 71573Srgrimes * published by the Free Software Foundation. Oracle designates this 81573Srgrimes * particular file as subject to the "Classpath" exception as provided 91573Srgrimes * by Oracle in the LICENSE file that accompanied this code. 101573Srgrimes * 111573Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT 121573Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 131573Srgrimes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 141573Srgrimes * version 2 for more details (a copy is included in the LICENSE file that 151573Srgrimes * accompanied this code). 161573Srgrimes * 171573Srgrimes * You should have received a copy of the GNU General Public License version 181573Srgrimes * 2 along with this work; if not, write to the Free Software Foundation, 191573Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 201573Srgrimes * 211573Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 221573Srgrimes * or visit www.oracle.com if you need additional information or have any 231573Srgrimes * questions. 241573Srgrimes */ 251573Srgrimes 261573Srgrimespackage com.sun.tools.javac.model; 271573Srgrimes 281573Srgrimesimport java.util.LinkedHashSet; 291573Srgrimesimport java.util.Map; 301573Srgrimesimport java.util.Set; 311573Srgrimes 321573Srgrimesimport javax.lang.model.AnnotatedConstruct; 331573Srgrimesimport javax.lang.model.SourceVersion; 3414272Spstimport javax.lang.model.element.*; 351573Srgrimesimport javax.lang.model.type.DeclaredType; 3692905Sobrienimport javax.lang.model.util.Elements; 3792905Sobrienimport javax.tools.JavaFileObject; 381573Srgrimesimport static javax.lang.model.util.ElementFilter.methodsIn; 391573Srgrimes 401573Srgrimesimport com.sun.source.util.JavacTask; 411573Srgrimesimport com.sun.tools.javac.api.JavacTaskImpl; 421573Srgrimesimport com.sun.tools.javac.code.*; 431573Srgrimesimport com.sun.tools.javac.code.Attribute.Compound; 441573Srgrimesimport com.sun.tools.javac.code.Directive.ExportsDirective; 451573Srgrimesimport com.sun.tools.javac.code.Directive.ExportsFlag; 4692905Sobrienimport com.sun.tools.javac.code.Directive.OpensDirective; 471573Srgrimesimport com.sun.tools.javac.code.Directive.OpensFlag; 481573Srgrimesimport com.sun.tools.javac.code.Directive.RequiresDirective; 491573Srgrimesimport com.sun.tools.javac.code.Directive.RequiresFlag; 501573Srgrimesimport com.sun.tools.javac.code.Scope.WriteableScope; 511573Srgrimesimport com.sun.tools.javac.code.Symbol.*; 521573Srgrimesimport com.sun.tools.javac.comp.AttrContext; 531573Srgrimesimport com.sun.tools.javac.comp.Enter; 541573Srgrimesimport com.sun.tools.javac.comp.Env; 551573Srgrimesimport com.sun.tools.javac.main.JavaCompiler; 561573Srgrimesimport com.sun.tools.javac.processing.PrintingProcessor; 571573Srgrimesimport com.sun.tools.javac.tree.JCTree; 581573Srgrimesimport com.sun.tools.javac.tree.JCTree.*; 59189291Sdelphijimport com.sun.tools.javac.tree.TreeInfo; 601573Srgrimesimport com.sun.tools.javac.tree.TreeScanner; 611573Srgrimesimport com.sun.tools.javac.util.*; 621573Srgrimesimport com.sun.tools.javac.util.DefinedBy.Api; 631573Srgrimesimport com.sun.tools.javac.util.Name; 641573Srgrimesimport static com.sun.tools.javac.code.Kinds.Kind.*; 651573Srgrimesimport static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 6614272Spstimport static com.sun.tools.javac.code.TypeTag.CLASS; 671573Srgrimesimport com.sun.tools.javac.comp.Modules; 681573Srgrimesimport com.sun.tools.javac.comp.Resolve; 691573Srgrimesimport com.sun.tools.javac.comp.Resolve.RecoveryLoadClass; 701573Srgrimesimport static com.sun.tools.javac.tree.JCTree.Tag.*; 711573Srgrimes 721573Srgrimes/** 731573Srgrimes * Utility methods for operating on program elements. 741573Srgrimes * 751573Srgrimes * <p><b>This is NOT part of any supported API. 761573Srgrimes * If you write code that depends on this, you do so at your own 771573Srgrimes * risk. This code and its internal interfaces are subject to change 781573Srgrimes * or deletion without notice.</b></p> 791573Srgrimes */ 801573Srgrimespublic class JavacElements implements Elements { 811573Srgrimes 821573Srgrimes private final JavaCompiler javaCompiler; 831573Srgrimes private final Symtab syms; 841573Srgrimes private final Modules modules; 851573Srgrimes private final Names names; 861573Srgrimes private final Types types; 8714272Spst private final Enter enter; 881573Srgrimes private final Resolve resolve; 891573Srgrimes private final JavacTaskImpl javacTaskImpl; 901573Srgrimes 911573Srgrimes public static JavacElements instance(Context context) { 921573Srgrimes JavacElements instance = context.get(JavacElements.class); 931573Srgrimes if (instance == null) 941573Srgrimes instance = new JavacElements(context); 951573Srgrimes return instance; 961573Srgrimes } 971573Srgrimes 981573Srgrimes protected JavacElements(Context context) { 991573Srgrimes context.put(JavacElements.class, this); 1001573Srgrimes javaCompiler = JavaCompiler.instance(context); 1011573Srgrimes syms = Symtab.instance(context); 10214272Spst modules = Modules.instance(context); 1031573Srgrimes names = Names.instance(context); 10414272Spst types = Types.instance(context); 1051573Srgrimes enter = Enter.instance(context); 1061573Srgrimes resolve = Resolve.instance(context); 1071573Srgrimes JavacTask t = context.get(JavacTask.class); 1081573Srgrimes javacTaskImpl = t instanceof JavacTaskImpl ? (JavacTaskImpl) t : null; 1091573Srgrimes } 1101573Srgrimes 1111573Srgrimes @Override @DefinedBy(Api.LANGUAGE_MODEL) 1121573Srgrimes public ModuleSymbol getModuleElement(CharSequence name) { 1131573Srgrimes ensureEntered("getModuleElement"); 11414272Spst if (modules.getDefaultModule() == syms.noModule) 1151573Srgrimes return null; 1161573Srgrimes String strName = name.toString(); 1171573Srgrimes if (strName.equals("")) 1181573Srgrimes return syms.unnamedModule; 1191573Srgrimes return modules.getObservableModule(names.fromString(strName)); 1201573Srgrimes } 1211573Srgrimes 1221573Srgrimes @Override @DefinedBy(Api.LANGUAGE_MODEL) 1231573Srgrimes public PackageSymbol getPackageElement(CharSequence name) { 124189291Sdelphij return doGetPackageElement(null, name); 1251573Srgrimes } 1261573Srgrimes 1271573Srgrimes @Override @DefinedBy(Api.LANGUAGE_MODEL) 1281573Srgrimes public PackageSymbol getPackageElement(ModuleElement module, CharSequence name) { 1291573Srgrimes module.getClass(); 1301573Srgrimes return doGetPackageElement(module, name); 13114272Spst } 1321573Srgrimes 1331573Srgrimes private PackageSymbol doGetPackageElement(ModuleElement module, CharSequence name) { 1341573Srgrimes ensureEntered("getPackageElement"); 1351573Srgrimes if (name.length() == 0) 1361573Srgrimes return syms.unnamedModule.unnamedPackage; 1371573Srgrimes return doGetElement(module, name, PackageSymbol.class); 1381573Srgrimes } 1391573Srgrimes 1401573Srgrimes @Override @DefinedBy(Api.LANGUAGE_MODEL) 1411573Srgrimes public ClassSymbol getTypeElement(CharSequence name) { 1421573Srgrimes return doGetTypeElement(null, name); 1431573Srgrimes } 14414272Spst 1451573Srgrimes @Override @DefinedBy(Api.LANGUAGE_MODEL) 1461573Srgrimes public ClassSymbol getTypeElement(ModuleElement module, CharSequence name) { 1471573Srgrimes module.getClass(); 1481573Srgrimes 1491573Srgrimes return doGetTypeElement(module, name); 1501573Srgrimes } 1511573Srgrimes 1521573Srgrimes private ClassSymbol doGetTypeElement(ModuleElement module, CharSequence name) { 1531573Srgrimes ensureEntered("getTypeElement"); 1541573Srgrimes return doGetElement(module, name, ClassSymbol.class); 1551573Srgrimes } 1561573Srgrimes 1571573Srgrimes private <S extends Symbol> S doGetElement(ModuleElement module, CharSequence name, Class<S> clazz) { 1581573Srgrimes String strName = name.toString(); 15914272Spst if (!SourceVersion.isName(strName)) { 1601573Srgrimes return null; 16114272Spst } 1621573Srgrimes if (module == null) { 1631573Srgrimes return unboundNameToSymbol(strName, clazz); 1641573Srgrimes } else { 1651573Srgrimes return nameToSymbol((ModuleSymbol) module, strName, clazz); 1661573Srgrimes } 1671573Srgrimes } 1681573Srgrimes 1691573Srgrimes private <S extends Symbol> S unboundNameToSymbol(String nameStr, Class<S> clazz) { 1701573Srgrimes if (modules.getDefaultModule() == syms.noModule) { //not a modular mode: 17114272Spst return nameToSymbol(syms.noModule, nameStr, clazz); 1721573Srgrimes } 1731573Srgrimes 1741573Srgrimes RecoveryLoadClass prevRecoveryLoadClass = resolve.setRecoveryLoadClass((env, name) -> null); 1751573Srgrimes try { 1761573Srgrimes Set<S> found = new LinkedHashSet<>(); 1771573Srgrimes 1781573Srgrimes for (ModuleSymbol msym : modules.allModules()) { 1791573Srgrimes S sym = nameToSymbol(msym, nameStr, clazz); 1801573Srgrimes 1811573Srgrimes if (sym != null) { 1821573Srgrimes found.add(sym); 1831573Srgrimes } 1841573Srgrimes } 1851573Srgrimes 1861573Srgrimes if (found.size() == 1) { 1871573Srgrimes return found.iterator().next(); 1881573Srgrimes } else { 1891573Srgrimes //not found, or more than one element found: 1901573Srgrimes return null; 1911573Srgrimes } 1921573Srgrimes } finally { 1931573Srgrimes resolve.setRecoveryLoadClass(prevRecoveryLoadClass); 1941573Srgrimes } 195189291Sdelphij } 1961573Srgrimes 1971573Srgrimes /** 1981573Srgrimes * Returns a symbol given the type's or package's canonical name, 1991573Srgrimes * or null if the name isn't found. 20014272Spst */ 2011573Srgrimes private <S extends Symbol> S nameToSymbol(ModuleSymbol module, String nameStr, Class<S> clazz) { 20214272Spst Name name = names.fromString(nameStr); 2031573Srgrimes // First check cache. 20414272Spst Symbol sym = (clazz == ClassSymbol.class) 2051573Srgrimes ? syms.getClass(module, name) 20614272Spst : syms.lookupPackage(module, name); 2071573Srgrimes 20814272Spst try { 2091573Srgrimes if (sym == null) 21014272Spst sym = javaCompiler.resolveIdent(module, nameStr); 2111573Srgrimes 2121573Srgrimes sym.complete(); 213 214 return (sym.kind != ERR && 215 sym.exists() && 216 clazz.isInstance(sym) && 217 name.equals(sym.getQualifiedName())) 218 ? clazz.cast(sym) 219 : null; 220 } catch (CompletionFailure e) { 221 return null; 222 } 223 } 224 225 public JavacSourcePosition getSourcePosition(Element e) { 226 Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); 227 if (treeTop == null) 228 return null; 229 JCTree tree = treeTop.fst; 230 JCCompilationUnit toplevel = treeTop.snd; 231 JavaFileObject sourcefile = toplevel.sourcefile; 232 if (sourcefile == null) 233 return null; 234 return new JavacSourcePosition(sourcefile, tree.pos, toplevel.lineMap); 235 } 236 237 public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a) { 238 Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); 239 if (treeTop == null) 240 return null; 241 JCTree tree = treeTop.fst; 242 JCCompilationUnit toplevel = treeTop.snd; 243 JavaFileObject sourcefile = toplevel.sourcefile; 244 if (sourcefile == null) 245 return null; 246 247 JCTree annoTree = matchAnnoToTree(a, e, tree); 248 if (annoTree == null) 249 return null; 250 return new JavacSourcePosition(sourcefile, annoTree.pos, 251 toplevel.lineMap); 252 } 253 254 public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a, 255 AnnotationValue v) { 256 // TODO: better accuracy in getSourcePosition(... AnnotationValue) 257 return getSourcePosition(e, a); 258 } 259 260 /** 261 * Returns the tree for an annotation given the annotated element 262 * and the element's own tree. Returns null if the tree cannot be found. 263 */ 264 private JCTree matchAnnoToTree(AnnotationMirror findme, 265 Element e, JCTree tree) { 266 Symbol sym = cast(Symbol.class, e); 267 class Vis extends JCTree.Visitor { 268 List<JCAnnotation> result = null; 269 public void visitPackageDef(JCPackageDecl tree) { 270 result = tree.annotations; 271 } 272 public void visitClassDef(JCClassDecl tree) { 273 result = tree.mods.annotations; 274 } 275 public void visitMethodDef(JCMethodDecl tree) { 276 result = tree.mods.annotations; 277 } 278 public void visitVarDef(JCVariableDecl tree) { 279 result = tree.mods.annotations; 280 } 281 @Override 282 public void visitTypeParameter(JCTypeParameter tree) { 283 result = tree.annotations; 284 } 285 } 286 Vis vis = new Vis(); 287 tree.accept(vis); 288 if (vis.result == null) 289 return null; 290 291 List<Attribute.Compound> annos = sym.getAnnotationMirrors(); 292 return matchAnnoToTree(cast(Attribute.Compound.class, findme), 293 annos, 294 vis.result); 295 } 296 297 /** 298 * Returns the tree for an annotation given a list of annotations 299 * in which to search (recursively) and their corresponding trees. 300 * Returns null if the tree cannot be found. 301 */ 302 private JCTree matchAnnoToTree(Attribute.Compound findme, 303 List<Attribute.Compound> annos, 304 List<JCAnnotation> trees) { 305 for (Attribute.Compound anno : annos) { 306 for (JCAnnotation tree : trees) { 307 JCTree match = matchAnnoToTree(findme, anno, tree); 308 if (match != null) 309 return match; 310 } 311 } 312 return null; 313 } 314 315 /** 316 * Returns the tree for an annotation given an Attribute to 317 * search (recursively) and its corresponding tree. 318 * Returns null if the tree cannot be found. 319 */ 320 private JCTree matchAnnoToTree(final Attribute.Compound findme, 321 final Attribute attr, 322 final JCTree tree) { 323 if (attr == findme) 324 return (tree.type.tsym == findme.type.tsym) ? tree : null; 325 326 class Vis implements Attribute.Visitor { 327 JCTree result = null; 328 public void visitConstant(Attribute.Constant value) { 329 } 330 public void visitClass(Attribute.Class clazz) { 331 } 332 public void visitCompound(Attribute.Compound anno) { 333 for (Pair<MethodSymbol, Attribute> pair : anno.values) { 334 JCExpression expr = scanForAssign(pair.fst, tree); 335 if (expr != null) { 336 JCTree match = matchAnnoToTree(findme, pair.snd, expr); 337 if (match != null) { 338 result = match; 339 return; 340 } 341 } 342 } 343 } 344 public void visitArray(Attribute.Array array) { 345 if (tree.hasTag(NEWARRAY) && 346 types.elemtype(array.type).tsym == findme.type.tsym) { 347 List<JCExpression> elems = ((JCNewArray) tree).elems; 348 for (Attribute value : array.values) { 349 if (value == findme) { 350 result = elems.head; 351 return; 352 } 353 elems = elems.tail; 354 } 355 } 356 } 357 public void visitEnum(Attribute.Enum e) { 358 } 359 public void visitError(Attribute.Error e) { 360 } 361 } 362 Vis vis = new Vis(); 363 attr.accept(vis); 364 return vis.result; 365 } 366 367 /** 368 * Scans for a JCAssign node with a LHS matching a given 369 * symbol, and returns its RHS. Does not scan nested JCAnnotations. 370 */ 371 private JCExpression scanForAssign(final MethodSymbol sym, 372 final JCTree tree) { 373 class TS extends TreeScanner { 374 JCExpression result = null; 375 public void scan(JCTree t) { 376 if (t != null && result == null) 377 t.accept(this); 378 } 379 public void visitAnnotation(JCAnnotation t) { 380 if (t == tree) 381 scan(t.args); 382 } 383 public void visitAssign(JCAssign t) { 384 if (t.lhs.hasTag(IDENT)) { 385 JCIdent ident = (JCIdent) t.lhs; 386 if (ident.sym == sym) 387 result = t.rhs; 388 } 389 } 390 } 391 TS scanner = new TS(); 392 tree.accept(scanner); 393 return scanner.result; 394 } 395 396 /** 397 * Returns the tree node corresponding to this element, or null 398 * if none can be found. 399 */ 400 public JCTree getTree(Element e) { 401 Pair<JCTree, ?> treeTop = getTreeAndTopLevel(e); 402 return (treeTop != null) ? treeTop.fst : null; 403 } 404 405 @DefinedBy(Api.LANGUAGE_MODEL) 406 public String getDocComment(Element e) { 407 // Our doc comment is contained in a map in our toplevel, 408 // indexed by our tree. Find our enter environment, which gives 409 // us our toplevel. It also gives us a tree that contains our 410 // tree: walk it to find our tree. This is painful. 411 Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); 412 if (treeTop == null) 413 return null; 414 JCTree tree = treeTop.fst; 415 JCCompilationUnit toplevel = treeTop.snd; 416 if (toplevel.docComments == null) 417 return null; 418 return toplevel.docComments.getCommentText(tree); 419 } 420 421 @DefinedBy(Api.LANGUAGE_MODEL) 422 public PackageElement getPackageOf(Element e) { 423 return cast(Symbol.class, e).packge(); 424 } 425 426 @DefinedBy(Api.LANGUAGE_MODEL) 427 public ModuleElement getModuleOf(Element e) { 428 Symbol sym = cast(Symbol.class, e); 429 if (modules.getDefaultModule() == syms.noModule) 430 return null; 431 return (sym.kind == MDL) ? ((ModuleElement) e) : sym.packge().modle; 432 } 433 434 @DefinedBy(Api.LANGUAGE_MODEL) 435 public boolean isDeprecated(Element e) { 436 Symbol sym = cast(Symbol.class, e); 437 sym.complete(); 438 return sym.isDeprecated(); 439 } 440 441 @Override @DefinedBy(Api.LANGUAGE_MODEL) 442 public Origin getOrigin(Element e) { 443 Symbol sym = cast(Symbol.class, e); 444 if ((sym.flags() & Flags.GENERATEDCONSTR) != 0) 445 return Origin.MANDATED; 446 //TypeElement.getEnclosedElements does not return synthetic elements, 447 //and most synthetic elements are not read from the classfile anyway: 448 return Origin.EXPLICIT; 449 } 450 451 @Override @DefinedBy(Api.LANGUAGE_MODEL) 452 public Origin getOrigin(AnnotatedConstruct c, AnnotationMirror a) { 453 Compound ac = cast(Compound.class, a); 454 if (ac.isSynthesized()) 455 return Origin.MANDATED; 456 return Origin.EXPLICIT; 457 } 458 459 @Override @DefinedBy(Api.LANGUAGE_MODEL) 460 public Origin getOrigin(ModuleElement m, ModuleElement.Directive directive) { 461 switch (directive.getKind()) { 462 case REQUIRES: 463 RequiresDirective rd = cast(RequiresDirective.class, directive); 464 if (rd.flags.contains(RequiresFlag.MANDATED)) 465 return Origin.MANDATED; 466 if (rd.flags.contains(RequiresFlag.SYNTHETIC)) 467 return Origin.SYNTHETIC; 468 return Origin.EXPLICIT; 469 case EXPORTS: 470 ExportsDirective ed = cast(ExportsDirective.class, directive); 471 if (ed.flags.contains(ExportsFlag.MANDATED)) 472 return Origin.MANDATED; 473 if (ed.flags.contains(ExportsFlag.SYNTHETIC)) 474 return Origin.SYNTHETIC; 475 return Origin.EXPLICIT; 476 case OPENS: 477 OpensDirective od = cast(OpensDirective.class, directive); 478 if (od.flags.contains(OpensFlag.MANDATED)) 479 return Origin.MANDATED; 480 if (od.flags.contains(OpensFlag.SYNTHETIC)) 481 return Origin.SYNTHETIC; 482 return Origin.EXPLICIT; 483 } 484 return Origin.EXPLICIT; 485 } 486 487 @DefinedBy(Api.LANGUAGE_MODEL) 488 public Name getBinaryName(TypeElement type) { 489 return cast(TypeSymbol.class, type).flatName(); 490 } 491 492 @DefinedBy(Api.LANGUAGE_MODEL) 493 public Map<MethodSymbol, Attribute> getElementValuesWithDefaults( 494 AnnotationMirror a) { 495 Attribute.Compound anno = cast(Attribute.Compound.class, a); 496 DeclaredType annotype = a.getAnnotationType(); 497 Map<MethodSymbol, Attribute> valmap = anno.getElementValues(); 498 499 for (ExecutableElement ex : 500 methodsIn(annotype.asElement().getEnclosedElements())) { 501 MethodSymbol meth = (MethodSymbol) ex; 502 Attribute defaultValue = meth.getDefaultValue(); 503 if (defaultValue != null && !valmap.containsKey(meth)) { 504 valmap.put(meth, defaultValue); 505 } 506 } 507 return valmap; 508 } 509 510 /** 511 * {@inheritDoc} 512 */ 513 @DefinedBy(Api.LANGUAGE_MODEL) 514 public FilteredMemberList getAllMembers(TypeElement element) { 515 Symbol sym = cast(Symbol.class, element); 516 WriteableScope scope = sym.members().dupUnshared(); 517 List<Type> closure = types.closure(sym.asType()); 518 for (Type t : closure) 519 addMembers(scope, t); 520 return new FilteredMemberList(scope); 521 } 522 // where 523 private void addMembers(WriteableScope scope, Type type) { 524 members: 525 for (Symbol e : type.asElement().members().getSymbols(NON_RECURSIVE)) { 526 for (Symbol overrider : scope.getSymbolsByName(e.getSimpleName())) { 527 if (overrider.kind == e.kind && (overrider.flags() & Flags.SYNTHETIC) == 0) { 528 if (overrider.getKind() == ElementKind.METHOD && 529 overrides((ExecutableElement)overrider, (ExecutableElement)e, (TypeElement)type.asElement())) { 530 continue members; 531 } 532 } 533 } 534 boolean derived = e.getEnclosingElement() != scope.owner; 535 ElementKind kind = e.getKind(); 536 boolean initializer = kind == ElementKind.CONSTRUCTOR 537 || kind == ElementKind.INSTANCE_INIT 538 || kind == ElementKind.STATIC_INIT; 539 if (!derived || (!initializer && e.isInheritedIn(scope.owner, types))) 540 scope.enter(e); 541 } 542 } 543 544 /** 545 * Returns all annotations of an element, whether 546 * inherited or directly present. 547 * 548 * @param e the element being examined 549 * @return all annotations of the element 550 */ 551 @Override @DefinedBy(Api.LANGUAGE_MODEL) 552 public List<Attribute.Compound> getAllAnnotationMirrors(Element e) { 553 Symbol sym = cast(Symbol.class, e); 554 List<Attribute.Compound> annos = sym.getAnnotationMirrors(); 555 while (sym.getKind() == ElementKind.CLASS) { 556 Type sup = ((ClassSymbol) sym).getSuperclass(); 557 if (!sup.hasTag(CLASS) || sup.isErroneous() || 558 sup.tsym == syms.objectType.tsym) { 559 break; 560 } 561 sym = sup.tsym; 562 List<Attribute.Compound> oldAnnos = annos; 563 List<Attribute.Compound> newAnnos = sym.getAnnotationMirrors(); 564 for (Attribute.Compound anno : newAnnos) { 565 if (isInherited(anno.type) && 566 !containsAnnoOfType(oldAnnos, anno.type)) { 567 annos = annos.prepend(anno); 568 } 569 } 570 } 571 return annos; 572 } 573 574 /** 575 * Tests whether an annotation type is @Inherited. 576 */ 577 private boolean isInherited(Type annotype) { 578 return annotype.tsym.attribute(syms.inheritedType.tsym) != null; 579 } 580 581 /** 582 * Tests whether a list of annotations contains an annotation 583 * of a given type. 584 */ 585 private static boolean containsAnnoOfType(List<Attribute.Compound> annos, 586 Type type) { 587 for (Attribute.Compound anno : annos) { 588 if (anno.type.tsym == type.tsym) 589 return true; 590 } 591 return false; 592 } 593 594 @DefinedBy(Api.LANGUAGE_MODEL) 595 public boolean hides(Element hiderEl, Element hideeEl) { 596 Symbol hider = cast(Symbol.class, hiderEl); 597 Symbol hidee = cast(Symbol.class, hideeEl); 598 599 // Fields only hide fields; methods only methods; types only types. 600 // Names must match. Nothing hides itself (just try it). 601 if (hider == hidee || 602 hider.kind != hidee.kind || 603 hider.name != hidee.name) { 604 return false; 605 } 606 607 // Only static methods can hide other methods. 608 // Methods only hide methods with matching signatures. 609 if (hider.kind == MTH) { 610 if (!hider.isStatic() || 611 !types.isSubSignature(hider.type, hidee.type)) { 612 return false; 613 } 614 } 615 616 // Hider must be in a subclass of hidee's class. 617 // Note that if M1 hides M2, and M2 hides M3, and M3 is accessible 618 // in M1's class, then M1 and M2 both hide M3. 619 ClassSymbol hiderClass = hider.owner.enclClass(); 620 ClassSymbol hideeClass = hidee.owner.enclClass(); 621 if (hiderClass == null || hideeClass == null || 622 !hiderClass.isSubClass(hideeClass, types)) { 623 return false; 624 } 625 626 // Hidee must be accessible in hider's class. 627 // The method isInheritedIn is poorly named: it checks only access. 628 return hidee.isInheritedIn(hiderClass, types); 629 } 630 631 @DefinedBy(Api.LANGUAGE_MODEL) 632 public boolean overrides(ExecutableElement riderEl, 633 ExecutableElement rideeEl, TypeElement typeEl) { 634 MethodSymbol rider = cast(MethodSymbol.class, riderEl); 635 MethodSymbol ridee = cast(MethodSymbol.class, rideeEl); 636 ClassSymbol origin = cast(ClassSymbol.class, typeEl); 637 638 return rider.name == ridee.name && 639 640 // not reflexive as per JLS 641 rider != ridee && 642 643 // we don't care if ridee is static, though that wouldn't 644 // compile 645 !rider.isStatic() && 646 647 // Symbol.overrides assumes the following 648 ridee.isMemberOf(origin, types) && 649 650 // check access and signatures; don't check return types 651 rider.overrides(ridee, origin, types, false); 652 } 653 654 @DefinedBy(Api.LANGUAGE_MODEL) 655 public String getConstantExpression(Object value) { 656 return Constants.format(value); 657 } 658 659 /** 660 * Print a representation of the elements to the given writer in 661 * the specified order. The main purpose of this method is for 662 * diagnostics. The exact format of the output is <em>not</em> 663 * specified and is subject to change. 664 * 665 * @param w the writer to print the output to 666 * @param elements the elements to print 667 */ 668 @DefinedBy(Api.LANGUAGE_MODEL) 669 public void printElements(java.io.Writer w, Element... elements) { 670 for (Element element : elements) 671 (new PrintingProcessor.PrintingElementVisitor(w, this)).visit(element).flush(); 672 } 673 674 @DefinedBy(Api.LANGUAGE_MODEL) 675 public Name getName(CharSequence cs) { 676 return names.fromString(cs.toString()); 677 } 678 679 @Override @DefinedBy(Api.LANGUAGE_MODEL) 680 public boolean isFunctionalInterface(TypeElement element) { 681 if (element.getKind() != ElementKind.INTERFACE) 682 return false; 683 else { 684 TypeSymbol tsym = cast(TypeSymbol.class, element); 685 return types.isFunctionalInterface(tsym); 686 } 687 } 688 689 /** 690 * Returns the tree node and compilation unit corresponding to this 691 * element, or null if they can't be found. 692 */ 693 private Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(Element e) { 694 Symbol sym = cast(Symbol.class, e); 695 Env<AttrContext> enterEnv = getEnterEnv(sym); 696 if (enterEnv == null) 697 return null; 698 JCTree tree = TreeInfo.declarationFor(sym, enterEnv.tree); 699 if (tree == null || enterEnv.toplevel == null) 700 return null; 701 return new Pair<>(tree, enterEnv.toplevel); 702 } 703 704 /** 705 * Returns the best approximation for the tree node and compilation unit 706 * corresponding to the given element, annotation and value. 707 * If the element is null, null is returned. 708 * If the annotation is null or cannot be found, the tree node and 709 * compilation unit for the element is returned. 710 * If the annotation value is null or cannot be found, the tree node and 711 * compilation unit for the annotation is returned. 712 */ 713 public Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel( 714 Element e, AnnotationMirror a, AnnotationValue v) { 715 if (e == null) 716 return null; 717 718 Pair<JCTree, JCCompilationUnit> elemTreeTop = getTreeAndTopLevel(e); 719 if (elemTreeTop == null) 720 return null; 721 722 if (a == null) 723 return elemTreeTop; 724 725 JCTree annoTree = matchAnnoToTree(a, e, elemTreeTop.fst); 726 if (annoTree == null) 727 return elemTreeTop; 728 729 // 6388543: if v != null, we should search within annoTree to find 730 // the tree matching v. For now, we ignore v and return the tree of 731 // the annotation. 732 return new Pair<>(annoTree, elemTreeTop.snd); 733 } 734 735 /** 736 * Returns a symbol's enter environment, or null if it has none. 737 */ 738 private Env<AttrContext> getEnterEnv(Symbol sym) { 739 // Get enclosing class of sym, or sym itself if it is a class 740 // package, or module. 741 TypeSymbol ts = null; 742 switch (sym.kind) { 743 case PCK: 744 ts = (PackageSymbol)sym; 745 break; 746 case MDL: 747 ts = (ModuleSymbol)sym; 748 break; 749 default: 750 ts = sym.enclClass(); 751 } 752 return (ts != null) 753 ? enter.getEnv(ts) 754 : null; 755 } 756 757 private void ensureEntered(String methodName) { 758 if (javacTaskImpl != null) { 759 javacTaskImpl.ensureEntered(); 760 } 761 if (!javaCompiler.isEnterDone()) { 762 throw new IllegalStateException("Cannot use Elements." + methodName + " before the TaskEvent.Kind.ENTER finished event."); 763 } 764 } 765 766 /** 767 * Returns an object cast to the specified type. 768 * @throws NullPointerException if the object is {@code null} 769 * @throws IllegalArgumentException if the object is of the wrong type 770 */ 771 private static <T> T cast(Class<T> clazz, Object o) { 772 if (! clazz.isInstance(o)) 773 throw new IllegalArgumentException(o.toString()); 774 return clazz.cast(o); 775 } 776} 777