JavacElements.java revision 2601:8e638f046bf0
1178173Simp/* 2178173Simp * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. 3178173Simp * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4178173Simp * 5178173Simp * This code is free software; you can redistribute it and/or modify it 6178173Simp * under the terms of the GNU General Public License version 2 only, as 7178173Simp * published by the Free Software Foundation. Oracle designates this 8178173Simp * particular file as subject to the "Classpath" exception as provided 9178173Simp * by Oracle in the LICENSE file that accompanied this code. 10178173Simp * 11178173Simp * This code is distributed in the hope that it will be useful, but WITHOUT 12178173Simp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13178173Simp * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14178173Simp * version 2 for more details (a copy is included in the LICENSE file that 15178173Simp * accompanied this code). 16178173Simp * 17178173Simp * You should have received a copy of the GNU General Public License version 18178173Simp * 2 along with this work; if not, write to the Free Software Foundation, 19178173Simp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20178173Simp * 21178173Simp * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22178173Simp * or visit www.oracle.com if you need additional information or have any 23178173Simp * questions. 24178173Simp */ 25178173Simp 26178173Simppackage com.sun.tools.javac.model; 27178173Simp 28178173Simpimport java.util.Map; 29178173Simp 30178173Simpimport javax.lang.model.SourceVersion; 31178173Simpimport javax.lang.model.element.*; 32178173Simpimport javax.lang.model.type.DeclaredType; 33178173Simpimport javax.lang.model.util.Elements; 34178173Simpimport javax.tools.JavaFileObject; 35178173Simpimport static javax.lang.model.util.ElementFilter.methodsIn; 36178173Simp 37178173Simpimport com.sun.tools.javac.code.*; 38178173Simpimport com.sun.tools.javac.code.Scope.WriteableScope; 39178173Simpimport com.sun.tools.javac.code.Symbol.*; 40178173Simpimport com.sun.tools.javac.comp.AttrContext; 41178173Simpimport com.sun.tools.javac.comp.Enter; 42178173Simpimport com.sun.tools.javac.comp.Env; 43178173Simpimport com.sun.tools.javac.main.JavaCompiler; 44178173Simpimport com.sun.tools.javac.processing.PrintingProcessor; 45178173Simpimport com.sun.tools.javac.tree.JCTree; 46178173Simpimport com.sun.tools.javac.tree.JCTree.*; 47182901Sgonzoimport com.sun.tools.javac.tree.TreeInfo; 48182901Sgonzoimport com.sun.tools.javac.tree.TreeScanner; 49178173Simpimport com.sun.tools.javac.util.*; 50178173Simpimport com.sun.tools.javac.util.DefinedBy.Api; 51178173Simpimport com.sun.tools.javac.util.Name; 52178173Simpimport static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 53178173Simpimport static com.sun.tools.javac.code.TypeTag.CLASS; 54178173Simpimport static com.sun.tools.javac.tree.JCTree.Tag.*; 55178173Simp 56178173Simp/** 57178173Simp * Utility methods for operating on program elements. 58178173Simp * 59178173Simp * <p><b>This is NOT part of any supported API. 60212413Savg * If you write code that depends on this, you do so at your own 61178173Simp * risk. This code and its internal interfaces are subject to change 62294883Sjhibbits * or deletion without notice.</b></p> 63294883Sjhibbits */ 64178173Simppublic class JavacElements implements Elements { 65178173Simp 66178173Simp private final JavaCompiler javaCompiler; 67178173Simp private final Symtab syms; 68178173Simp private final Names names; 69178173Simp private final Types types; 70178173Simp private final Enter enter; 71178173Simp 72178173Simp public static JavacElements instance(Context context) { 73178173Simp JavacElements instance = context.get(JavacElements.class); 74178173Simp if (instance == null) 75178173Simp instance = new JavacElements(context); 76178173Simp return instance; 77178173Simp } 78178173Simp 79202027Simp protected JavacElements(Context context) { 80202027Simp context.put(JavacElements.class, this); 81178173Simp javaCompiler = JavaCompiler.instance(context); 82202027Simp syms = Symtab.instance(context); 83178173Simp names = Names.instance(context); 84178173Simp types = Types.instance(context); 85178173Simp enter = Enter.instance(context); 86178173Simp } 87178173Simp 88178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 89178173Simp public PackageSymbol getPackageElement(CharSequence name) { 90178173Simp String strName = name.toString(); 91178173Simp if (strName.equals("")) 92178173Simp return syms.unnamedPackage; 93202027Simp return SourceVersion.isName(strName) 94202027Simp ? nameToSymbol(strName, PackageSymbol.class) 95178173Simp : null; 96202027Simp } 97178173Simp 98178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 99178173Simp public ClassSymbol getTypeElement(CharSequence name) { 100178173Simp String strName = name.toString(); 101178173Simp return SourceVersion.isName(strName) 102178173Simp ? nameToSymbol(strName, ClassSymbol.class) 103178173Simp : null; 104178173Simp } 105178173Simp 106178173Simp /** 107178173Simp * Returns a symbol given the type's or packages's canonical name, 108178173Simp * or null if the name isn't found. 109178173Simp */ 110178173Simp private <S extends Symbol> S nameToSymbol(String nameStr, Class<S> clazz) { 111257338Snwhitehorn Name name = names.fromString(nameStr); 112178173Simp // First check cache. 113178173Simp Symbol sym = (clazz == ClassSymbol.class) 114178173Simp ? syms.classes.get(name) 115178173Simp : syms.packages.get(name); 116178173Simp 117178173Simp try { 118178173Simp if (sym == null) 119178173Simp sym = javaCompiler.resolveIdent(nameStr); 120178173Simp 121178173Simp sym.complete(); 122178173Simp 123178173Simp return (sym.kind != Kinds.ERR && 124178173Simp sym.exists() && 125178173Simp clazz.isInstance(sym) && 126178173Simp name.equals(sym.getQualifiedName())) 127178173Simp ? clazz.cast(sym) 128178173Simp : null; 129178173Simp } catch (CompletionFailure e) { 130178173Simp return null; 131178173Simp } 132178173Simp } 133178173Simp 134178173Simp public JavacSourcePosition getSourcePosition(Element e) { 135178173Simp Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); 136178173Simp if (treeTop == null) 137178173Simp return null; 138178173Simp JCTree tree = treeTop.fst; 139178173Simp JCCompilationUnit toplevel = treeTop.snd; 140178173Simp JavaFileObject sourcefile = toplevel.sourcefile; 141178173Simp if (sourcefile == null) 142178173Simp return null; 143178173Simp return new JavacSourcePosition(sourcefile, tree.pos, toplevel.lineMap); 144178173Simp } 145178173Simp 146178173Simp public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a) { 147178173Simp Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); 148178173Simp if (treeTop == null) 149178173Simp return null; 150178173Simp JCTree tree = treeTop.fst; 151178173Simp JCCompilationUnit toplevel = treeTop.snd; 152178173Simp JavaFileObject sourcefile = toplevel.sourcefile; 153178173Simp if (sourcefile == null) 154178173Simp return null; 155178173Simp 156178173Simp JCTree annoTree = matchAnnoToTree(a, e, tree); 157178173Simp if (annoTree == null) 158178173Simp return null; 159294883Sjhibbits return new JavacSourcePosition(sourcefile, annoTree.pos, 160178173Simp toplevel.lineMap); 161178173Simp } 162178173Simp 163178173Simp public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a, 164178173Simp AnnotationValue v) { 165178173Simp // TODO: better accuracy in getSourcePosition(... AnnotationValue) 166178173Simp return getSourcePosition(e, a); 167178173Simp } 168295832Sjhibbits 169178173Simp /** 170178173Simp * Returns the tree for an annotation given the annotated element 171178173Simp * and the element's own tree. Returns null if the tree cannot be found. 172178173Simp */ 173178173Simp private JCTree matchAnnoToTree(AnnotationMirror findme, 174178173Simp Element e, JCTree tree) { 175178173Simp Symbol sym = cast(Symbol.class, e); 176178173Simp class Vis extends JCTree.Visitor { 177178173Simp List<JCAnnotation> result = null; 178178173Simp public void visitPackageDef(JCPackageDecl tree) { 179178173Simp result = tree.annotations; 180178173Simp } 181178173Simp public void visitClassDef(JCClassDecl tree) { 182178173Simp result = tree.mods.annotations; 183178173Simp } 184178173Simp public void visitMethodDef(JCMethodDecl tree) { 185178173Simp result = tree.mods.annotations; 186178173Simp } 187178173Simp public void visitVarDef(JCVariableDecl tree) { 188178173Simp result = tree.mods.annotations; 189178173Simp } 190178173Simp @Override 191178173Simp public void visitTypeParameter(JCTypeParameter tree) { 192178173Simp result = tree.annotations; 193178173Simp } 194178173Simp } 195178173Simp Vis vis = new Vis(); 196178173Simp tree.accept(vis); 197178173Simp if (vis.result == null) 198178173Simp return null; 199178173Simp 200178173Simp List<Attribute.Compound> annos = sym.getAnnotationMirrors(); 201178173Simp return matchAnnoToTree(cast(Attribute.Compound.class, findme), 202178173Simp annos, 203178173Simp vis.result); 204178173Simp } 205178173Simp 206178173Simp /** 207298053Spfg * Returns the tree for an annotation given a list of annotations 208178173Simp * in which to search (recursively) and their corresponding trees. 209178173Simp * Returns null if the tree cannot be found. 210178173Simp */ 211178173Simp private JCTree matchAnnoToTree(Attribute.Compound findme, 212178173Simp List<Attribute.Compound> annos, 213178173Simp List<JCAnnotation> trees) { 214178173Simp for (Attribute.Compound anno : annos) { 215178173Simp for (JCAnnotation tree : trees) { 216178173Simp JCTree match = matchAnnoToTree(findme, anno, tree); 217178173Simp if (match != null) 218178173Simp return match; 219178173Simp } 220178173Simp } 221178173Simp return null; 222178173Simp } 223178173Simp 224178173Simp /** 225178173Simp * Returns the tree for an annotation given an Attribute to 226178173Simp * search (recursively) and its corresponding tree. 227178173Simp * Returns null if the tree cannot be found. 228178173Simp */ 229178173Simp private JCTree matchAnnoToTree(final Attribute.Compound findme, 230178173Simp final Attribute attr, 231178173Simp final JCTree tree) { 232178173Simp if (attr == findme) 233178173Simp return (tree.type.tsym == findme.type.tsym) ? tree : null; 234178173Simp 235178173Simp class Vis implements Attribute.Visitor { 236178173Simp JCTree result = null; 237178173Simp public void visitConstant(Attribute.Constant value) { 238178173Simp } 239178173Simp public void visitClass(Attribute.Class clazz) { 240178173Simp } 241178173Simp public void visitCompound(Attribute.Compound anno) { 242178173Simp for (Pair<MethodSymbol, Attribute> pair : anno.values) { 243178173Simp JCExpression expr = scanForAssign(pair.fst, tree); 244178173Simp if (expr != null) { 245178173Simp JCTree match = matchAnnoToTree(findme, pair.snd, expr); 246178173Simp if (match != null) { 247178173Simp result = match; 248178173Simp return; 249178173Simp } 250178173Simp } 251178173Simp } 252178173Simp } 253178173Simp public void visitArray(Attribute.Array array) { 254178173Simp if (tree.hasTag(NEWARRAY) && 255178173Simp types.elemtype(array.type).tsym == findme.type.tsym) { 256178173Simp List<JCExpression> elems = ((JCNewArray) tree).elems; 257178173Simp for (Attribute value : array.values) { 258178173Simp if (value == findme) { 259178173Simp result = elems.head; 260178173Simp return; 261178173Simp } 262178173Simp elems = elems.tail; 263178173Simp } 264178173Simp } 265178173Simp } 266178173Simp public void visitEnum(Attribute.Enum e) { 267178173Simp } 268178173Simp public void visitError(Attribute.Error e) { 269178173Simp } 270178173Simp } 271178173Simp Vis vis = new Vis(); 272178173Simp attr.accept(vis); 273178173Simp return vis.result; 274178173Simp } 275178173Simp 276178173Simp /** 277178173Simp * Scans for a JCAssign node with a LHS matching a given 278178173Simp * symbol, and returns its RHS. Does not scan nested JCAnnotations. 279178173Simp */ 280183173Simp private JCExpression scanForAssign(final MethodSymbol sym, 281202027Simp final JCTree tree) { 282178173Simp class TS extends TreeScanner { 283178173Simp JCExpression result = null; 284178173Simp public void scan(JCTree t) { 285178173Simp if (t != null && result == null) 286178173Simp t.accept(this); 287178173Simp } 288178173Simp public void visitAnnotation(JCAnnotation t) { 289178173Simp if (t == tree) 290178173Simp scan(t.args); 291178173Simp } 292178173Simp public void visitAssign(JCAssign t) { 293178173Simp if (t.lhs.hasTag(IDENT)) { 294178173Simp JCIdent ident = (JCIdent) t.lhs; 295178173Simp if (ident.sym == sym) 296178173Simp result = t.rhs; 297178173Simp } 298178173Simp } 299178173Simp } 300178173Simp TS scanner = new TS(); 301178173Simp tree.accept(scanner); 302178173Simp return scanner.result; 303178173Simp } 304178173Simp 305178173Simp /** 306178173Simp * Returns the tree node corresponding to this element, or null 307178173Simp * if none can be found. 308178173Simp */ 309178173Simp public JCTree getTree(Element e) { 310178173Simp Pair<JCTree, ?> treeTop = getTreeAndTopLevel(e); 311178173Simp return (treeTop != null) ? treeTop.fst : null; 312178173Simp } 313178173Simp 314178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 315178173Simp public String getDocComment(Element e) { 316178173Simp // Our doc comment is contained in a map in our toplevel, 317178173Simp // indexed by our tree. Find our enter environment, which gives 318178173Simp // us our toplevel. It also gives us a tree that contains our 319178173Simp // tree: walk it to find our tree. This is painful. 320178173Simp Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); 321178173Simp if (treeTop == null) 322178173Simp return null; 323178173Simp JCTree tree = treeTop.fst; 324178173Simp JCCompilationUnit toplevel = treeTop.snd; 325178173Simp if (toplevel.docComments == null) 326178173Simp return null; 327178173Simp return toplevel.docComments.getCommentText(tree); 328178173Simp } 329178173Simp 330178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 331178173Simp public PackageElement getPackageOf(Element e) { 332178173Simp return cast(Symbol.class, e).packge(); 333178173Simp } 334178173Simp 335178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 336183173Simp public boolean isDeprecated(Element e) { 337178173Simp Symbol sym = cast(Symbol.class, e); 338178173Simp return (sym.flags() & Flags.DEPRECATED) != 0; 339178173Simp } 340178173Simp 341178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 342178173Simp public Name getBinaryName(TypeElement type) { 343178173Simp return cast(TypeSymbol.class, type).flatName(); 344178173Simp } 345178173Simp 346178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 347178173Simp public Map<MethodSymbol, Attribute> getElementValuesWithDefaults( 348178173Simp AnnotationMirror a) { 349178173Simp Attribute.Compound anno = cast(Attribute.Compound.class, a); 350178173Simp DeclaredType annotype = a.getAnnotationType(); 351178173Simp Map<MethodSymbol, Attribute> valmap = anno.getElementValues(); 352178173Simp 353178173Simp for (ExecutableElement ex : 354178173Simp methodsIn(annotype.asElement().getEnclosedElements())) { 355178173Simp MethodSymbol meth = (MethodSymbol) ex; 356178173Simp Attribute defaultValue = meth.getDefaultValue(); 357183173Simp if (defaultValue != null && !valmap.containsKey(meth)) { 358178173Simp valmap.put(meth, defaultValue); 359178173Simp } 360178173Simp } 361178173Simp return valmap; 362178173Simp } 363178173Simp 364178173Simp /** 365178173Simp * {@inheritDoc} 366178173Simp */ 367178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 368178173Simp public FilteredMemberList getAllMembers(TypeElement element) { 369178173Simp Symbol sym = cast(Symbol.class, element); 370178173Simp WriteableScope scope = sym.members().dupUnshared(); 371178173Simp List<Type> closure = types.closure(sym.asType()); 372178173Simp for (Type t : closure) 373178173Simp addMembers(scope, t); 374178173Simp return new FilteredMemberList(scope); 375178173Simp } 376178173Simp // where 377178173Simp private void addMembers(WriteableScope scope, Type type) { 378178173Simp members: 379178173Simp for (Symbol e : type.asElement().members().getSymbols(NON_RECURSIVE)) { 380178173Simp for (Symbol overrider : scope.getSymbolsByName(e.getSimpleName())) { 381178173Simp if (overrider.kind == e.kind && (overrider.flags() & Flags.SYNTHETIC) == 0) { 382178173Simp if (overrider.getKind() == ElementKind.METHOD && 383178173Simp overrides((ExecutableElement)overrider, (ExecutableElement)e, (TypeElement)type.asElement())) { 384178173Simp continue members; 385178173Simp } 386178173Simp } 387178173Simp } 388178173Simp boolean derived = e.getEnclosingElement() != scope.owner; 389178173Simp ElementKind kind = e.getKind(); 390178173Simp boolean initializer = kind == ElementKind.CONSTRUCTOR 391178173Simp || kind == ElementKind.INSTANCE_INIT 392178173Simp || kind == ElementKind.STATIC_INIT; 393178173Simp if (!derived || (!initializer && e.isInheritedIn(scope.owner, types))) 394178173Simp scope.enter(e); 395178173Simp } 396178173Simp } 397178173Simp 398178173Simp /** 399178173Simp * Returns all annotations of an element, whether 400178173Simp * inherited or directly present. 401178173Simp * 402178173Simp * @param e the element being examined 403178173Simp * @return all annotations of the element 404178173Simp */ 405178173Simp @Override @DefinedBy(Api.LANGUAGE_MODEL) 406178173Simp public List<Attribute.Compound> getAllAnnotationMirrors(Element e) { 407178173Simp Symbol sym = cast(Symbol.class, e); 408178173Simp List<Attribute.Compound> annos = sym.getAnnotationMirrors(); 409178173Simp while (sym.getKind() == ElementKind.CLASS) { 410178173Simp Type sup = ((ClassSymbol) sym).getSuperclass(); 411178173Simp if (!sup.hasTag(CLASS) || sup.isErroneous() || 412178173Simp sup.tsym == syms.objectType.tsym) { 413178173Simp break; 414178173Simp } 415178173Simp sym = sup.tsym; 416178173Simp List<Attribute.Compound> oldAnnos = annos; 417178173Simp List<Attribute.Compound> newAnnos = sym.getAnnotationMirrors(); 418178173Simp for (Attribute.Compound anno : newAnnos) { 419178173Simp if (isInherited(anno.type) && 420178173Simp !containsAnnoOfType(oldAnnos, anno.type)) { 421178173Simp annos = annos.prepend(anno); 422178173Simp } 423178173Simp } 424178173Simp } 425212413Savg return annos; 426178173Simp } 427178173Simp 428178173Simp /** 429178173Simp * Tests whether an annotation type is @Inherited. 430178173Simp */ 431178173Simp private boolean isInherited(Type annotype) { 432178173Simp return annotype.tsym.attribute(syms.inheritedType.tsym) != null; 433178173Simp } 434178173Simp 435178173Simp /** 436178173Simp * Tests whether a list of annotations contains an annotation 437178173Simp * of a given type. 438178173Simp */ 439178173Simp private static boolean containsAnnoOfType(List<Attribute.Compound> annos, 440178173Simp Type type) { 441178173Simp for (Attribute.Compound anno : annos) { 442178173Simp if (anno.type.tsym == type.tsym) 443178173Simp return true; 444178173Simp } 445178173Simp return false; 446178173Simp } 447178173Simp 448178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 449178173Simp public boolean hides(Element hiderEl, Element hideeEl) { 450178173Simp Symbol hider = cast(Symbol.class, hiderEl); 451178173Simp Symbol hidee = cast(Symbol.class, hideeEl); 452178173Simp 453178173Simp // Fields only hide fields; methods only methods; types only types. 454178173Simp // Names must match. Nothing hides itself (just try it). 455178173Simp if (hider == hidee || 456178173Simp hider.kind != hidee.kind || 457178173Simp hider.name != hidee.name) { 458178173Simp return false; 459178173Simp } 460178173Simp 461178173Simp // Only static methods can hide other methods. 462178173Simp // Methods only hide methods with matching signatures. 463178173Simp if (hider.kind == Kinds.MTH) { 464178173Simp if (!hider.isStatic() || 465178173Simp !types.isSubSignature(hider.type, hidee.type)) { 466178173Simp return false; 467178173Simp } 468178173Simp } 469178173Simp 470178173Simp // Hider must be in a subclass of hidee's class. 471178173Simp // Note that if M1 hides M2, and M2 hides M3, and M3 is accessible 472178173Simp // in M1's class, then M1 and M2 both hide M3. 473178173Simp ClassSymbol hiderClass = hider.owner.enclClass(); 474178173Simp ClassSymbol hideeClass = hidee.owner.enclClass(); 475178173Simp if (hiderClass == null || hideeClass == null || 476178173Simp !hiderClass.isSubClass(hideeClass, types)) { 477178173Simp return false; 478178173Simp } 479178173Simp 480178173Simp // Hidee must be accessible in hider's class. 481178173Simp // The method isInheritedIn is poorly named: it checks only access. 482178173Simp return hidee.isInheritedIn(hiderClass, types); 483178173Simp } 484178173Simp 485178173Simp @DefinedBy(Api.LANGUAGE_MODEL) 486178173Simp public boolean overrides(ExecutableElement riderEl, 487 ExecutableElement rideeEl, TypeElement typeEl) { 488 MethodSymbol rider = cast(MethodSymbol.class, riderEl); 489 MethodSymbol ridee = cast(MethodSymbol.class, rideeEl); 490 ClassSymbol origin = cast(ClassSymbol.class, typeEl); 491 492 return rider.name == ridee.name && 493 494 // not reflexive as per JLS 495 rider != ridee && 496 497 // we don't care if ridee is static, though that wouldn't 498 // compile 499 !rider.isStatic() && 500 501 // Symbol.overrides assumes the following 502 ridee.isMemberOf(origin, types) && 503 504 // check access and signatures; don't check return types 505 rider.overrides(ridee, origin, types, false); 506 } 507 508 @DefinedBy(Api.LANGUAGE_MODEL) 509 public String getConstantExpression(Object value) { 510 return Constants.format(value); 511 } 512 513 /** 514 * Print a representation of the elements to the given writer in 515 * the specified order. The main purpose of this method is for 516 * diagnostics. The exact format of the output is <em>not</em> 517 * specified and is subject to change. 518 * 519 * @param w the writer to print the output to 520 * @param elements the elements to print 521 */ 522 @DefinedBy(Api.LANGUAGE_MODEL) 523 public void printElements(java.io.Writer w, Element... elements) { 524 for (Element element : elements) 525 (new PrintingProcessor.PrintingElementVisitor(w, this)).visit(element).flush(); 526 } 527 528 @DefinedBy(Api.LANGUAGE_MODEL) 529 public Name getName(CharSequence cs) { 530 return names.fromString(cs.toString()); 531 } 532 533 @Override @DefinedBy(Api.LANGUAGE_MODEL) 534 public boolean isFunctionalInterface(TypeElement element) { 535 if (element.getKind() != ElementKind.INTERFACE) 536 return false; 537 else { 538 TypeSymbol tsym = cast(TypeSymbol.class, element); 539 return types.isFunctionalInterface(tsym); 540 } 541 } 542 543 /** 544 * Returns the tree node and compilation unit corresponding to this 545 * element, or null if they can't be found. 546 */ 547 private Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(Element e) { 548 Symbol sym = cast(Symbol.class, e); 549 Env<AttrContext> enterEnv = getEnterEnv(sym); 550 if (enterEnv == null) 551 return null; 552 JCTree tree = TreeInfo.declarationFor(sym, enterEnv.tree); 553 if (tree == null || enterEnv.toplevel == null) 554 return null; 555 return new Pair<>(tree, enterEnv.toplevel); 556 } 557 558 /** 559 * Returns the best approximation for the tree node and compilation unit 560 * corresponding to the given element, annotation and value. 561 * If the element is null, null is returned. 562 * If the annotation is null or cannot be found, the tree node and 563 * compilation unit for the element is returned. 564 * If the annotation value is null or cannot be found, the tree node and 565 * compilation unit for the annotation is returned. 566 */ 567 public Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel( 568 Element e, AnnotationMirror a, AnnotationValue v) { 569 if (e == null) 570 return null; 571 572 Pair<JCTree, JCCompilationUnit> elemTreeTop = getTreeAndTopLevel(e); 573 if (elemTreeTop == null) 574 return null; 575 576 if (a == null) 577 return elemTreeTop; 578 579 JCTree annoTree = matchAnnoToTree(a, e, elemTreeTop.fst); 580 if (annoTree == null) 581 return elemTreeTop; 582 583 // 6388543: if v != null, we should search within annoTree to find 584 // the tree matching v. For now, we ignore v and return the tree of 585 // the annotation. 586 return new Pair<>(annoTree, elemTreeTop.snd); 587 } 588 589 /** 590 * Returns a symbol's enter environment, or null if it has none. 591 */ 592 private Env<AttrContext> getEnterEnv(Symbol sym) { 593 // Get enclosing class of sym, or sym itself if it is a class 594 // or package. 595 TypeSymbol ts = (sym.kind != Kinds.PCK) 596 ? sym.enclClass() 597 : (PackageSymbol) sym; 598 return (ts != null) 599 ? enter.getEnv(ts) 600 : null; 601 } 602 603 /** 604 * Returns an object cast to the specified type. 605 * @throws NullPointerException if the object is {@code null} 606 * @throws IllegalArgumentException if the object is of the wrong type 607 */ 608 private static <T> T cast(Class<T> clazz, Object o) { 609 if (! clazz.isInstance(o)) 610 throw new IllegalArgumentException(o.toString()); 611 return clazz.cast(o); 612 } 613} 614