1 /*
   2  * Copyright (c) 2005, 2013, 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.lang.annotation.Annotation;
  29 import java.lang.annotation.Inherited;
  30 import java.lang.reflect.InvocationTargetException;
  31 import java.lang.reflect.Method;
  32 import java.util.Map;
  33 
  34 import javax.lang.model.SourceVersion;
  35 import javax.lang.model.element.*;
  36 import javax.lang.model.type.DeclaredType;
  37 import javax.lang.model.util.Elements;
  38 import javax.tools.JavaFileObject;
  39 import static javax.lang.model.util.ElementFilter.methodsIn;
  40 
  41 import com.sun.tools.javac.code.*;
  42 import com.sun.tools.javac.code.Symbol.*;
  43 import com.sun.tools.javac.code.TypeTag;
  44 import com.sun.tools.javac.comp.AttrContext;
  45 import com.sun.tools.javac.comp.Enter;
  46 import com.sun.tools.javac.comp.Env;
  47 import com.sun.tools.javac.main.JavaCompiler;
  48 import com.sun.tools.javac.processing.PrintingProcessor;
  49 import com.sun.tools.javac.tree.JCTree;
  50 import com.sun.tools.javac.tree.JCTree.*;
  51 import com.sun.tools.javac.tree.TreeInfo;
  52 import com.sun.tools.javac.tree.TreeScanner;
  53 import com.sun.tools.javac.util.*;
  54 import com.sun.tools.javac.util.Name;
  55 import static com.sun.tools.javac.code.TypeTag.CLASS;
  56 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  57 
  58 /**
  59  * Utility methods for operating on program elements.
  60  *
  61  * <p><b>This is NOT part of any supported API.
  62  * If you write code that depends on this, you do so at your own
  63  * risk.  This code and its internal interfaces are subject to change
  64  * or deletion without notice.</b></p>
  65  */
  66 public class JavacElements implements Elements {
  67 
  68     private JavaCompiler javaCompiler;
  69     private Symtab syms;
  70     private Names names;
  71     private Types types;
  72     private Enter enter;
  73 
  74     public static JavacElements instance(Context context) {
  75         JavacElements instance = context.get(JavacElements.class);
  76         if (instance == null)
  77             instance = new JavacElements(context);
  78         return instance;
  79     }
  80 
  81     /**
  82      * Public for use only by JavacProcessingEnvironment
  83      */
  84     protected JavacElements(Context context) {
  85         setContext(context);
  86     }
  87 
  88     /**
  89      * Use a new context.  May be called from outside to update
  90      * internal state for a new annotation-processing round.
  91      */
  92     public void setContext(Context context) {
  93         context.put(JavacElements.class, this);
  94         javaCompiler = JavaCompiler.instance(context);
  95         syms = Symtab.instance(context);
  96         names = Names.instance(context);
  97         types = Types.instance(context);
  98         enter = Enter.instance(context);
  99     }
 100 
 101     /**
 102      * An internal-use utility that creates a runtime view of an
 103      * annotation. This is the implementation of
 104      * Element.getAnnotation(Class).
 105      */
 106     public static <A extends Annotation> A getAnnotation(Symbol annotated,
 107                                                          Class<A> annoType) {
 108         if (!annoType.isAnnotation())
 109             throw new IllegalArgumentException("Not an annotation type: "
 110                                                + annoType);
 111         Attribute.Compound c;
 112         if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) {
 113             c = getAttributeOnClass((ClassSymbol)annotated, annoType);
 114         } else {
 115             c = getAttribute(annotated, annoType);
 116         }
 117         return c == null ? null : AnnotationProxyMaker.generateAnnotation(c, annoType);
 118     }
 119 
 120     // Helper to getAnnotation[s]
 121     private static <A extends Annotation> Attribute.Compound getAttribute(Symbol annotated,
 122                                                                           Class<A> annoType) {
 123         String name = annoType.getName();
 124 
 125         for (Attribute.Compound anno : annotated.getRawAttributes())
 126             if (name.equals(anno.type.tsym.flatName().toString()))
 127                 return anno;
 128 
 129         return null;
 130     }
 131     // Helper to getAnnotation[s]
 132     private static <A extends Annotation> Attribute.Compound getAttributeOnClass(ClassSymbol annotated,
 133                                                                 Class<A> annoType) {
 134         boolean inherited = annoType.isAnnotationPresent(Inherited.class);
 135         Attribute.Compound result = null;
 136         while (annotated.name != annotated.name.table.names.java_lang_Object) {
 137             result = getAttribute(annotated, annoType);
 138             if (result != null || !inherited)
 139                 break;
 140             Type sup = annotated.getSuperclass();
 141             if (!sup.hasTag(CLASS) || sup.isErroneous())
 142                 break;
 143             annotated = (ClassSymbol) sup.tsym;
 144         }
 145         return result;
 146     }
 147 
 148     /**
 149      * An internal-use utility that creates a runtime view of
 150      * annotations. This is the implementation of
 151      * Element.getAnnotations(Class).
 152      */
 153     public static <A extends Annotation> A[] getAnnotations(Symbol annotated,
 154                                                             Class<A> annoType) {
 155         if (!annoType.isAnnotation())
 156             throw new IllegalArgumentException("Not an annotation type: "
 157                                                + annoType);
 158         // If annoType does not declare a container this is equivalent to wrapping
 159         // getAnnotation(...) in an array.
 160         Class <? extends Annotation> containerType = getContainer(annoType);
 161         if (containerType == null) {
 162             A res = getAnnotation(annotated, annoType);
 163             int size;
 164             if (res == null) {
 165                 size = 0;
 166             } else {
 167                 size = 1;
 168             }
 169             @SuppressWarnings("unchecked") // annoType is the Class for A
 170             A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size);
 171             if (res != null)
 172                 arr[0] = res;
 173             return arr;
 174         }
 175 
 176         // So we have a containing type
 177         String name = annoType.getName();
 178         String annoTypeName = annoType.getSimpleName();
 179         String containerTypeName = containerType.getSimpleName();
 180         int directIndex = -1, containerIndex = -1;
 181         Attribute.Compound direct = null, container = null;
 182         Attribute.Compound[] rawAttributes = annotated.getRawAttributes().toArray(new Attribute.Compound[0]);
 183 
 184         // Find directly present annotations
 185         for (int i = 0; i < rawAttributes.length; i++) {
 186             if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) {
 187                 directIndex = i;
 188                 direct = rawAttributes[i];
 189             } else if(containerTypeName != null &&
 190                       containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) {
 191                 containerIndex = i;
 192                 container = rawAttributes[i];
 193             }
 194         }
 195         // Deal with inherited annotations
 196         if (annotated.kind == Kinds.TYP &&
 197                 (annotated instanceof ClassSymbol)) {
 198             ClassSymbol s = (ClassSymbol)annotated;
 199             if (direct == null && container == null) {
 200                 direct = getAttributeOnClass(s, annoType);
 201                 container = getAttributeOnClass(s, containerType);
 202 
 203                 // both are inherited and found, put container last
 204                 if (direct != null && container != null) {
 205                     directIndex = 0;
 206                     containerIndex = 1;
 207                 } else if (direct != null) {
 208                     directIndex = 0;
 209                 } else {
 210                     containerIndex = 0;
 211                 }
 212             } else if (direct == null) {
 213                 direct = getAttributeOnClass(s, annoType);
 214                 if (direct != null)
 215                     directIndex = containerIndex + 1;
 216             } else if (container == null) {
 217                 container = getAttributeOnClass(s, containerType);
 218                 if (container != null)
 219                     containerIndex = directIndex + 1;
 220             }
 221         }
 222 
 223         // Pack them in an array
 224         Attribute[] contained0 = new Attribute[0];
 225         if (container != null)
 226             contained0 = unpackAttributes(container);
 227         ListBuffer<Attribute.Compound> compounds = ListBuffer.lb();
 228         for (Attribute a : contained0)
 229             if (a instanceof Attribute.Compound)
 230                 compounds = compounds.append((Attribute.Compound)a);
 231         Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]);
 232 
 233         int size = (direct == null ? 0 : 1) + contained.length;
 234         @SuppressWarnings("unchecked") // annoType is the Class for A
 235         A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size);
 236 
 237         // if direct && container, which is first?
 238         int insert = -1;
 239         int length = arr.length;
 240         if (directIndex >= 0 && containerIndex >= 0) {
 241             if (directIndex < containerIndex) {
 242                 arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
 243                 insert = 1;
 244             } else {
 245                 arr[arr.length - 1] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
 246                 insert = 0;
 247                 length--;
 248             }
 249         } else if (directIndex >= 0) {
 250             arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
 251             return arr;
 252         } else {
 253             // Only container
 254             insert = 0;
 255         }
 256 
 257         for (int i = 0; i + insert < length; i++)
 258             arr[insert + i] = AnnotationProxyMaker.generateAnnotation(contained[i], annoType);
 259 
 260         return arr;
 261     }
 262 
 263     // Needed to unpack the runtime view of containing annotations
 264     private static final Class<? extends Annotation> REPEATABLE_CLASS = initRepeatable();
 265     private static final Method VALUE_ELEMENT_METHOD = initValueElementMethod();
 266 
 267     private static Class<? extends Annotation> initRepeatable() {
 268         try {
 269             // Repeatable will not be available when bootstrapping on
 270             // JDK 7 so use a reflective lookup instead of a class
 271             // literal for Repeatable.class.
 272             return Class.forName("java.lang.annotation.Repeatable").asSubclass(Annotation.class);
 273         } catch (ClassNotFoundException e) {
 274             return null;
 275         } catch (SecurityException e) {
 276             return null;
 277         }
 278     }
 279     private static Method initValueElementMethod() {
 280         if (REPEATABLE_CLASS == null)
 281             return null;
 282 
 283         Method m = null;
 284         try {
 285             m = REPEATABLE_CLASS.getMethod("value");
 286             if (m != null)
 287                 m.setAccessible(true);
 288             return m;
 289         } catch (NoSuchMethodException e) {
 290             return null;
 291         }
 292     }
 293 
 294     // Helper to getAnnotations
 295     private static Class<? extends Annotation> getContainer(Class<? extends Annotation> annoType) {
 296         // Since we can not refer to java.lang.annotation.Repeatable until we are
 297         // bootstrapping with java 8 we need to get the Repeatable annotation using
 298         // reflective invocations instead of just using its type and element method.
 299         if (REPEATABLE_CLASS != null &&
 300             VALUE_ELEMENT_METHOD != null) {
 301             // Get the Repeatable instance on the annotations declaration
 302             Annotation repeatable = (Annotation)annoType.getAnnotation(REPEATABLE_CLASS);
 303             if (repeatable != null) {
 304                 try {
 305                     // Get the value element, it should be a class
 306                     // indicating the containing annotation type
 307                     @SuppressWarnings("unchecked")
 308                     Class<? extends Annotation> containerType = (Class)VALUE_ELEMENT_METHOD.invoke(repeatable);
 309                     if (containerType == null)
 310                         return null;
 311 
 312                     return containerType;
 313                 } catch (ClassCastException e) {
 314                     return null;
 315                 } catch (IllegalAccessException e) {
 316                     return null;
 317                 } catch (InvocationTargetException e ) {
 318                     return null;
 319                 }
 320             }
 321         }
 322         return null;
 323     }
 324     // Helper to getAnnotations
 325     private static Attribute[] unpackAttributes(Attribute.Compound container) {
 326         // We now have an instance of the container,
 327         // unpack it returning an instance of the
 328         // contained type or null
 329         return ((Attribute.Array)container.member(container.type.tsym.name.table.names.value)).values;
 330     }
 331 
 332     public PackageSymbol getPackageElement(CharSequence name) {
 333         String strName = name.toString();
 334         if (strName.equals(""))
 335             return syms.unnamedPackage;
 336         return SourceVersion.isName(strName)
 337             ? nameToSymbol(strName, PackageSymbol.class)
 338             : null;
 339     }
 340 
 341     public ClassSymbol getTypeElement(CharSequence name) {
 342         String strName = name.toString();
 343         return SourceVersion.isName(strName)
 344             ? nameToSymbol(strName, ClassSymbol.class)
 345             : null;
 346     }
 347 
 348     /**
 349      * Returns a symbol given the type's or packages's canonical name,
 350      * or null if the name isn't found.
 351      */
 352     private <S extends Symbol> S nameToSymbol(String nameStr, Class<S> clazz) {
 353         Name name = names.fromString(nameStr);
 354         // First check cache.
 355         Symbol sym = (clazz == ClassSymbol.class)
 356                     ? syms.classes.get(name)
 357                     : syms.packages.get(name);
 358 
 359         try {
 360             if (sym == null)
 361                 sym = javaCompiler.resolveIdent(nameStr);
 362 
 363             sym.complete();
 364 
 365             return (sym.kind != Kinds.ERR &&
 366                     sym.exists() &&
 367                     clazz.isInstance(sym) &&
 368                     name.equals(sym.getQualifiedName()))
 369                 ? clazz.cast(sym)
 370                 : null;
 371         } catch (CompletionFailure e) {
 372             return null;
 373         }
 374     }
 375 
 376     public JavacSourcePosition getSourcePosition(Element e) {
 377         Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e);
 378         if (treeTop == null)
 379             return null;
 380         JCTree tree = treeTop.fst;
 381         JCCompilationUnit toplevel = treeTop.snd;
 382         JavaFileObject sourcefile = toplevel.sourcefile;
 383         if (sourcefile == null)
 384             return null;
 385         return new JavacSourcePosition(sourcefile, tree.pos, toplevel.lineMap);
 386     }
 387 
 388     public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a) {
 389         Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e);
 390         if (treeTop == null)
 391             return null;
 392         JCTree tree = treeTop.fst;
 393         JCCompilationUnit toplevel = treeTop.snd;
 394         JavaFileObject sourcefile = toplevel.sourcefile;
 395         if (sourcefile == null)
 396             return null;
 397 
 398         JCTree annoTree = matchAnnoToTree(a, e, tree);
 399         if (annoTree == null)
 400             return null;
 401         return new JavacSourcePosition(sourcefile, annoTree.pos,
 402                                        toplevel.lineMap);
 403     }
 404 
 405     public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a,
 406                                             AnnotationValue v) {
 407         // TODO: better accuracy in getSourcePosition(... AnnotationValue)
 408         return getSourcePosition(e, a);
 409     }
 410 
 411     /**
 412      * Returns the tree for an annotation given the annotated element
 413      * and the element's own tree.  Returns null if the tree cannot be found.
 414      */
 415     private JCTree matchAnnoToTree(AnnotationMirror findme,
 416                                    Element e, JCTree tree) {
 417         Symbol sym = cast(Symbol.class, e);
 418         class Vis extends JCTree.Visitor {
 419             List<JCAnnotation> result = null;
 420             public void visitTopLevel(JCCompilationUnit tree) {
 421                 result = tree.packageAnnotations;
 422             }
 423             public void visitClassDef(JCClassDecl tree) {
 424                 result = tree.mods.annotations;
 425             }
 426             public void visitMethodDef(JCMethodDecl tree) {
 427                 result = tree.mods.annotations;
 428             }
 429             public void visitVarDef(JCVariableDecl tree) {
 430                 result = tree.mods.annotations;
 431             }
 432         }
 433         Vis vis = new Vis();
 434         tree.accept(vis);
 435         if (vis.result == null)
 436             return null;
 437 
 438         List<Attribute.Compound> annos = sym.getRawAttributes();
 439         return matchAnnoToTree(cast(Attribute.Compound.class, findme),
 440                                annos,
 441                                vis.result);
 442     }
 443 
 444     /**
 445      * Returns the tree for an annotation given a list of annotations
 446      * in which to search (recursively) and their corresponding trees.
 447      * Returns null if the tree cannot be found.
 448      */
 449     private JCTree matchAnnoToTree(Attribute.Compound findme,
 450                                    List<Attribute.Compound> annos,
 451                                    List<JCAnnotation> trees) {
 452         for (Attribute.Compound anno : annos) {
 453             for (JCAnnotation tree : trees) {
 454                 JCTree match = matchAnnoToTree(findme, anno, tree);
 455                 if (match != null)
 456                     return match;
 457             }
 458         }
 459         return null;
 460     }
 461 
 462     /**
 463      * Returns the tree for an annotation given an Attribute to
 464      * search (recursively) and its corresponding tree.
 465      * Returns null if the tree cannot be found.
 466      */
 467     private JCTree matchAnnoToTree(final Attribute.Compound findme,
 468                                    final Attribute attr,
 469                                    final JCTree tree) {
 470         if (attr == findme)
 471             return (tree.type.tsym == findme.type.tsym) ? tree : null;
 472 
 473         class Vis implements Attribute.Visitor {
 474             JCTree result = null;
 475             public void visitConstant(Attribute.Constant value) {
 476             }
 477             public void visitClass(Attribute.Class clazz) {
 478             }
 479             public void visitCompound(Attribute.Compound anno) {
 480                 for (Pair<MethodSymbol, Attribute> pair : anno.values) {
 481                     JCExpression expr = scanForAssign(pair.fst, tree);
 482                     if (expr != null) {
 483                         JCTree match = matchAnnoToTree(findme, pair.snd, expr);
 484                         if (match != null) {
 485                             result = match;
 486                             return;
 487                         }
 488                     }
 489                 }
 490             }
 491             public void visitArray(Attribute.Array array) {
 492                 if (tree.hasTag(NEWARRAY) &&
 493                         types.elemtype(array.type).tsym == findme.type.tsym) {
 494                     List<JCExpression> elems = ((JCNewArray) tree).elems;
 495                     for (Attribute value : array.values) {
 496                         if (value == findme) {
 497                             result = elems.head;
 498                             return;
 499                         }
 500                         elems = elems.tail;
 501                     }
 502                 }
 503             }
 504             public void visitEnum(Attribute.Enum e) {
 505             }
 506             public void visitError(Attribute.Error e) {
 507             }
 508         }
 509         Vis vis = new Vis();
 510         attr.accept(vis);
 511         return vis.result;
 512     }
 513 
 514     /**
 515      * Scans for a JCAssign node with a LHS matching a given
 516      * symbol, and returns its RHS.  Does not scan nested JCAnnotations.
 517      */
 518     private JCExpression scanForAssign(final MethodSymbol sym,
 519                                        final JCTree tree) {
 520         class TS extends TreeScanner {
 521             JCExpression result = null;
 522             public void scan(JCTree t) {
 523                 if (t != null && result == null)
 524                     t.accept(this);
 525             }
 526             public void visitAnnotation(JCAnnotation t) {
 527                 if (t == tree)
 528                     scan(t.args);
 529             }
 530             public void visitAssign(JCAssign t) {
 531                 if (t.lhs.hasTag(IDENT)) {
 532                     JCIdent ident = (JCIdent) t.lhs;
 533                     if (ident.sym == sym)
 534                         result = t.rhs;
 535                 }
 536             }
 537         }
 538         TS scanner = new TS();
 539         tree.accept(scanner);
 540         return scanner.result;
 541     }
 542 
 543     /**
 544      * Returns the tree node corresponding to this element, or null
 545      * if none can be found.
 546      */
 547     public JCTree getTree(Element e) {
 548         Pair<JCTree, ?> treeTop = getTreeAndTopLevel(e);
 549         return (treeTop != null) ? treeTop.fst : null;
 550     }
 551 
 552     public String getDocComment(Element e) {
 553         // Our doc comment is contained in a map in our toplevel,
 554         // indexed by our tree.  Find our enter environment, which gives
 555         // us our toplevel.  It also gives us a tree that contains our
 556         // tree:  walk it to find our tree.  This is painful.
 557         Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e);
 558         if (treeTop == null)
 559             return null;
 560         JCTree tree = treeTop.fst;
 561         JCCompilationUnit toplevel = treeTop.snd;
 562         if (toplevel.docComments == null)
 563             return null;
 564         return toplevel.docComments.getCommentText(tree);
 565     }
 566 
 567     public PackageElement getPackageOf(Element e) {
 568         return cast(Symbol.class, e).packge();
 569     }
 570 
 571     public boolean isDeprecated(Element e) {
 572         Symbol sym = cast(Symbol.class, e);
 573         return (sym.flags() & Flags.DEPRECATED) != 0;
 574     }
 575 
 576     public Name getBinaryName(TypeElement type) {
 577         return cast(TypeSymbol.class, type).flatName();
 578     }
 579 
 580     public Map<MethodSymbol, Attribute> getElementValuesWithDefaults(
 581                                                         AnnotationMirror a) {
 582         Attribute.Compound anno = cast(Attribute.Compound.class, a);
 583         DeclaredType annotype = a.getAnnotationType();
 584         Map<MethodSymbol, Attribute> valmap = anno.getElementValues();
 585 
 586         for (ExecutableElement ex :
 587                  methodsIn(annotype.asElement().getEnclosedElements())) {
 588             MethodSymbol meth = (MethodSymbol) ex;
 589             Attribute defaultValue = meth.getDefaultValue();
 590             if (defaultValue != null && !valmap.containsKey(meth)) {
 591                 valmap.put(meth, defaultValue);
 592             }
 593         }
 594         return valmap;
 595     }
 596 
 597     /**
 598      * {@inheritDoc}
 599      */
 600     public FilteredMemberList getAllMembers(TypeElement element) {
 601         Symbol sym = cast(Symbol.class, element);
 602         Scope scope = sym.members().dupUnshared();
 603         List<Type> closure = types.closure(sym.asType());
 604         for (Type t : closure)
 605             addMembers(scope, t);
 606         return new FilteredMemberList(scope);
 607     }
 608     // where
 609         private void addMembers(Scope scope, Type type) {
 610             members:
 611             for (Scope.Entry e = type.asElement().members().elems; e != null; e = e.sibling) {
 612                 Scope.Entry overrider = scope.lookup(e.sym.getSimpleName());
 613                 while (overrider.scope != null) {
 614                     if (overrider.sym.kind == e.sym.kind
 615                         && (overrider.sym.flags() & Flags.SYNTHETIC) == 0)
 616                     {
 617                         if (overrider.sym.getKind() == ElementKind.METHOD
 618                         && overrides((ExecutableElement)overrider.sym, (ExecutableElement)e.sym, (TypeElement)type.asElement())) {
 619                             continue members;
 620                         }
 621                     }
 622                     overrider = overrider.next();
 623                 }
 624                 boolean derived = e.sym.getEnclosingElement() != scope.owner;
 625                 ElementKind kind = e.sym.getKind();
 626                 boolean initializer = kind == ElementKind.CONSTRUCTOR
 627                     || kind == ElementKind.INSTANCE_INIT
 628                     || kind == ElementKind.STATIC_INIT;
 629                 if (!derived || (!initializer && e.sym.isInheritedIn(scope.owner, types)))
 630                     scope.enter(e.sym);
 631             }
 632         }
 633 
 634     /**
 635      * Returns all annotations of an element, whether
 636      * inherited or directly present.
 637      *
 638      * @param e  the element being examined
 639      * @return all annotations of the element
 640      */
 641     public List<Attribute.Compound> getAllAnnotationMirrors(Element e) {
 642         Symbol sym = cast(Symbol.class, e);
 643         List<Attribute.Compound> annos = sym.getRawAttributes();
 644         while (sym.getKind() == ElementKind.CLASS) {
 645             Type sup = ((ClassSymbol) sym).getSuperclass();
 646             if (!sup.hasTag(CLASS) || sup.isErroneous() ||
 647                     sup.tsym == syms.objectType.tsym) {
 648                 break;
 649             }
 650             sym = sup.tsym;
 651             List<Attribute.Compound> oldAnnos = annos;
 652             List<Attribute.Compound> newAnnos = sym.getRawAttributes();
 653             for (Attribute.Compound anno : newAnnos) {
 654                 if (isInherited(anno.type) &&
 655                         !containsAnnoOfType(oldAnnos, anno.type)) {
 656                     annos = annos.prepend(anno);
 657                 }
 658             }
 659         }
 660         return annos;
 661     }
 662 
 663     /**
 664      * Tests whether an annotation type is @Inherited.
 665      */
 666     private boolean isInherited(Type annotype) {
 667         return annotype.tsym.attribute(syms.inheritedType.tsym) != null;
 668     }
 669 
 670     /**
 671      * Tests whether a list of annotations contains an annotation
 672      * of a given type.
 673      */
 674     private static boolean containsAnnoOfType(List<Attribute.Compound> annos,
 675                                               Type type) {
 676         for (Attribute.Compound anno : annos) {
 677             if (anno.type.tsym == type.tsym)
 678                 return true;
 679         }
 680         return false;
 681     }
 682 
 683     public boolean hides(Element hiderEl, Element hideeEl) {
 684         Symbol hider = cast(Symbol.class, hiderEl);
 685         Symbol hidee = cast(Symbol.class, hideeEl);
 686 
 687         // Fields only hide fields; methods only methods; types only types.
 688         // Names must match.  Nothing hides itself (just try it).
 689         if (hider == hidee ||
 690                 hider.kind != hidee.kind ||
 691                 hider.name != hidee.name) {
 692             return false;
 693         }
 694 
 695         // Only static methods can hide other methods.
 696         // Methods only hide methods with matching signatures.
 697         if (hider.kind == Kinds.MTH) {
 698             if (!hider.isStatic() ||
 699                         !types.isSubSignature(hider.type, hidee.type)) {
 700                 return false;
 701             }
 702         }
 703 
 704         // Hider must be in a subclass of hidee's class.
 705         // Note that if M1 hides M2, and M2 hides M3, and M3 is accessible
 706         // in M1's class, then M1 and M2 both hide M3.
 707         ClassSymbol hiderClass = hider.owner.enclClass();
 708         ClassSymbol hideeClass = hidee.owner.enclClass();
 709         if (hiderClass == null || hideeClass == null ||
 710                 !hiderClass.isSubClass(hideeClass, types)) {
 711             return false;
 712         }
 713 
 714         // Hidee must be accessible in hider's class.
 715         // The method isInheritedIn is poorly named:  it checks only access.
 716         return hidee.isInheritedIn(hiderClass, types);
 717     }
 718 
 719     public boolean overrides(ExecutableElement riderEl,
 720                              ExecutableElement rideeEl, TypeElement typeEl) {
 721         MethodSymbol rider = cast(MethodSymbol.class, riderEl);
 722         MethodSymbol ridee = cast(MethodSymbol.class, rideeEl);
 723         ClassSymbol origin = cast(ClassSymbol.class, typeEl);
 724 
 725         return rider.name == ridee.name &&
 726 
 727                // not reflexive as per JLS
 728                rider != ridee &&
 729 
 730                // we don't care if ridee is static, though that wouldn't
 731                // compile
 732                !rider.isStatic() &&
 733 
 734                // Symbol.overrides assumes the following
 735                ridee.isMemberOf(origin, types) &&
 736 
 737                // check access and signatures; don't check return types
 738                rider.overrides(ridee, origin, types, false);
 739     }
 740 
 741     public String getConstantExpression(Object value) {
 742         return Constants.format(value);
 743     }
 744 
 745     /**
 746      * Print a representation of the elements to the given writer in
 747      * the specified order.  The main purpose of this method is for
 748      * diagnostics.  The exact format of the output is <em>not</em>
 749      * specified and is subject to change.
 750      *
 751      * @param w the writer to print the output to
 752      * @param elements the elements to print
 753      */
 754     public void printElements(java.io.Writer w, Element... elements) {
 755         for (Element element : elements)
 756             (new PrintingProcessor.PrintingElementVisitor(w, this)).visit(element).flush();
 757     }
 758 
 759     public Name getName(CharSequence cs) {
 760         return names.fromString(cs.toString());
 761     }
 762 
 763     @Override
 764     public boolean isFunctionalInterface(TypeElement element) {
 765         if (element.getKind() != ElementKind.INTERFACE)
 766             return false;
 767         else {
 768             TypeSymbol tsym = cast(TypeSymbol.class, element);
 769             return types.isFunctionalInterface(tsym);
 770         }
 771     }
 772 
 773     /**
 774      * Returns the tree node and compilation unit corresponding to this
 775      * element, or null if they can't be found.
 776      */
 777     private Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(Element e) {
 778         Symbol sym = cast(Symbol.class, e);
 779         Env<AttrContext> enterEnv = getEnterEnv(sym);
 780         if (enterEnv == null)
 781             return null;
 782         JCTree tree = TreeInfo.declarationFor(sym, enterEnv.tree);
 783         if (tree == null || enterEnv.toplevel == null)
 784             return null;
 785         return new Pair<JCTree,JCCompilationUnit>(tree, enterEnv.toplevel);
 786     }
 787 
 788     /**
 789      * Returns the best approximation for the tree node and compilation unit
 790      * corresponding to the given element, annotation and value.
 791      * If the element is null, null is returned.
 792      * If the annotation is null or cannot be found, the tree node and
 793      * compilation unit for the element is returned.
 794      * If the annotation value is null or cannot be found, the tree node and
 795      * compilation unit for the annotation is returned.
 796      */
 797     public Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(
 798                       Element e, AnnotationMirror a, AnnotationValue v) {
 799         if (e == null)
 800             return null;
 801 
 802         Pair<JCTree, JCCompilationUnit> elemTreeTop = getTreeAndTopLevel(e);
 803         if (elemTreeTop == null)
 804             return null;
 805 
 806         if (a == null)
 807             return elemTreeTop;
 808 
 809         JCTree annoTree = matchAnnoToTree(a, e, elemTreeTop.fst);
 810         if (annoTree == null)
 811             return elemTreeTop;
 812 
 813         // 6388543: if v != null, we should search within annoTree to find
 814         // the tree matching v. For now, we ignore v and return the tree of
 815         // the annotation.
 816         return new Pair<JCTree, JCCompilationUnit>(annoTree, elemTreeTop.snd);
 817     }
 818 
 819     /**
 820      * Returns a symbol's enter environment, or null if it has none.
 821      */
 822     private Env<AttrContext> getEnterEnv(Symbol sym) {
 823         // Get enclosing class of sym, or sym itself if it is a class
 824         // or package.
 825         TypeSymbol ts = (sym.kind != Kinds.PCK)
 826                         ? sym.enclClass()
 827                         : (PackageSymbol) sym;
 828         return (ts != null)
 829                 ? enter.getEnv(ts)
 830                 : null;
 831     }
 832 
 833     /**
 834      * Returns an object cast to the specified type.
 835      * @throws NullPointerException if the object is {@code null}
 836      * @throws IllegalArgumentException if the object is of the wrong type
 837      */
 838     private static <T> T cast(Class<T> clazz, Object o) {
 839         if (! clazz.isInstance(o))
 840             throw new IllegalArgumentException(o.toString());
 841         return clazz.cast(o);
 842     }
 843 }