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