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