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             @SuppressWarnings("unchecked") // java.lang.annotation.Repeatable extends Annotation by being an annotation type
 270             Class<? extends Annotation> c = (Class)Class.forName("java.lang.annotation.Repeatable");
 271             return c;
 272         } catch (ClassNotFoundException e) {
 273             return null;
 274         } catch (SecurityException e) {
 275             return null;
 276         }
 277     }
 278     private static Method initValueElementMethod() {
 279         if (REPEATABLE_CLASS == null)
 280             return null;
 281 
 282         Method m = null;
 283         try {
 284             m = REPEATABLE_CLASS.getMethod("value");
 285             if (m != null)
 286                 m.setAccessible(true);
 287             return m;
 288         } catch (NoSuchMethodException e) {
 289             return null;
 290         }
 291     }
 292 
 293     // Helper to getAnnotations
 294     private static Class<? extends Annotation> getContainer(Class<? extends Annotation> annoType) {
 295         // Since we can not refer to java.lang.annotation.Repeatable until we are
 296         // bootstrapping with java 8 we need to get the Repeatable annotation using
 297         // reflective invocations instead of just using its type and element method.
 298         if (REPEATABLE_CLASS != null &&
 299             VALUE_ELEMENT_METHOD != null) {
 300             // Get the Repeatable instance on the annotations declaration
 301             Annotation repeatable = (Annotation)annoType.getAnnotation(REPEATABLE_CLASS);
 302             if (repeatable != null) {
 303                 try {
 304                     // Get the value element, it should be a class
 305                     // indicating the containing annotation type
 306                     @SuppressWarnings("unchecked")
 307                     Class<? extends Annotation> containerType = (Class)VALUE_ELEMENT_METHOD.invoke(repeatable);
 308                     if (containerType == null)
 309                         return null;
 310 
 311                     return containerType;
 312                 } catch (ClassCastException e) {
 313                     return null;
 314                 } catch (IllegalAccessException e) {
 315                     return null;
 316                 } catch (InvocationTargetException e ) {
 317                     return null;
 318                 }
 319             }
 320         }
 321         return null;
 322     }
 323     // Helper to getAnnotations
 324     private static Attribute[] unpackAttributes(Attribute.Compound container) {
 325         // We now have an instance of the container,
 326         // unpack it returning an instance of the
 327         // contained type or null
 328         return ((Attribute.Array)container.member(container.type.tsym.name.table.names.value)).values;
 329     }
 330 
 331     public PackageSymbol getPackageElement(CharSequence name) {
 332         String strName = name.toString();
 333         if (strName.equals(""))
 334             return syms.unnamedPackage;
 335         return SourceVersion.isName(strName)
 336             ? nameToSymbol(strName, PackageSymbol.class)
 337             : null;
 338     }
 339 
 340     public ClassSymbol getTypeElement(CharSequence name) {
 341         String strName = name.toString();
 342         return SourceVersion.isName(strName)
 343             ? nameToSymbol(strName, ClassSymbol.class)
 344             : null;
 345     }
 346 
 347     /**
 348      * Returns a symbol given the type's or packages's canonical name,
 349      * or null if the name isn't found.
 350      */
 351     private <S extends Symbol> S nameToSymbol(String nameStr, Class<S> clazz) {
 352         Name name = names.fromString(nameStr);
 353         // First check cache.
 354         Symbol sym = (clazz == ClassSymbol.class)
 355                     ? syms.classes.get(name)
 356                     : syms.packages.get(name);
 357 
 358         try {
 359             if (sym == null)
 360                 sym = javaCompiler.resolveIdent(nameStr);
 361 
 362             sym.complete();
 363 
 364             return (sym.kind != Kinds.ERR &&
 365                     sym.exists() &&
 366                     clazz.isInstance(sym) &&
 367                     name.equals(sym.getQualifiedName()))
 368                 ? clazz.cast(sym)
 369                 : null;
 370         } catch (CompletionFailure e) {
 371             return null;
 372         }
 373     }
 374 
 375     public JavacSourcePosition getSourcePosition(Element e) {
 376         Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e);
 377         if (treeTop == null)
 378             return null;
 379         JCTree tree = treeTop.fst;
 380         JCCompilationUnit toplevel = treeTop.snd;
 381         JavaFileObject sourcefile = toplevel.sourcefile;
 382         if (sourcefile == null)
 383             return null;
 384         return new JavacSourcePosition(sourcefile, tree.pos, toplevel.lineMap);
 385     }
 386 
 387     public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a) {
 388         Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e);
 389         if (treeTop == null)
 390             return null;
 391         JCTree tree = treeTop.fst;
 392         JCCompilationUnit toplevel = treeTop.snd;
 393         JavaFileObject sourcefile = toplevel.sourcefile;
 394         if (sourcefile == null)
 395             return null;
 396 
 397         JCTree annoTree = matchAnnoToTree(a, e, tree);
 398         if (annoTree == null)
 399             return null;
 400         return new JavacSourcePosition(sourcefile, annoTree.pos,
 401                                        toplevel.lineMap);
 402     }
 403 
 404     public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a,
 405                                             AnnotationValue v) {
 406         // TODO: better accuracy in getSourcePosition(... AnnotationValue)
 407         return getSourcePosition(e, a);
 408     }
 409 
 410     /**
 411      * Returns the tree for an annotation given the annotated element
 412      * and the element's own tree.  Returns null if the tree cannot be found.
 413      */
 414     private JCTree matchAnnoToTree(AnnotationMirror findme,
 415                                    Element e, JCTree tree) {
 416         Symbol sym = cast(Symbol.class, e);
 417         class Vis extends JCTree.Visitor {
 418             List<JCAnnotation> result = null;
 419             public void visitTopLevel(JCCompilationUnit tree) {
 420                 result = tree.packageAnnotations;
 421             }
 422             public void visitClassDef(JCClassDecl tree) {
 423                 result = tree.mods.annotations;
 424             }
 425             public void visitMethodDef(JCMethodDecl tree) {
 426                 result = tree.mods.annotations;
 427             }
 428             public void visitVarDef(JCVariableDecl tree) {
 429                 result = tree.mods.annotations;
 430             }
 431         }
 432         Vis vis = new Vis();
 433         tree.accept(vis);
 434         if (vis.result == null)
 435             return null;
 436 
 437         List<Attribute.Compound> annos = sym.getRawAttributes();
 438         return matchAnnoToTree(cast(Attribute.Compound.class, findme),
 439                                annos,
 440                                vis.result);
 441     }
 442 
 443     /**
 444      * Returns the tree for an annotation given a list of annotations
 445      * in which to search (recursively) and their corresponding trees.
 446      * Returns null if the tree cannot be found.
 447      */
 448     private JCTree matchAnnoToTree(Attribute.Compound findme,
 449                                    List<Attribute.Compound> annos,
 450                                    List<JCAnnotation> trees) {
 451         for (Attribute.Compound anno : annos) {
 452             for (JCAnnotation tree : trees) {
 453                 JCTree match = matchAnnoToTree(findme, anno, tree);
 454                 if (match != null)
 455                     return match;
 456             }
 457         }
 458         return null;
 459     }
 460 
 461     /**
 462      * Returns the tree for an annotation given an Attribute to
 463      * search (recursively) and its corresponding tree.
 464      * Returns null if the tree cannot be found.
 465      */
 466     private JCTree matchAnnoToTree(final Attribute.Compound findme,
 467                                    final Attribute attr,
 468                                    final JCTree tree) {
 469         if (attr == findme)
 470             return (tree.type.tsym == findme.type.tsym) ? tree : null;
 471 
 472         class Vis implements Attribute.Visitor {
 473             JCTree result = null;
 474             public void visitConstant(Attribute.Constant value) {
 475             }
 476             public void visitClass(Attribute.Class clazz) {
 477             }
 478             public void visitCompound(Attribute.Compound anno) {
 479                 for (Pair<MethodSymbol, Attribute> pair : anno.values) {
 480                     JCExpression expr = scanForAssign(pair.fst, tree);
 481                     if (expr != null) {
 482                         JCTree match = matchAnnoToTree(findme, pair.snd, expr);
 483                         if (match != null) {
 484                             result = match;
 485                             return;
 486                         }
 487                     }
 488                 }
 489             }
 490             public void visitArray(Attribute.Array array) {
 491                 if (tree.hasTag(NEWARRAY) &&
 492                         types.elemtype(array.type).tsym == findme.type.tsym) {
 493                     List<JCExpression> elems = ((JCNewArray) tree).elems;
 494                     for (Attribute value : array.values) {
 495                         if (value == findme) {
 496                             result = elems.head;
 497                             return;
 498                         }
 499                         elems = elems.tail;
 500                     }
 501                 }
 502             }
 503             public void visitEnum(Attribute.Enum e) {
 504             }
 505             public void visitError(Attribute.Error e) {
 506             }
 507         }
 508         Vis vis = new Vis();
 509         attr.accept(vis);
 510         return vis.result;
 511     }
 512 
 513     /**
 514      * Scans for a JCAssign node with a LHS matching a given
 515      * symbol, and returns its RHS.  Does not scan nested JCAnnotations.
 516      */
 517     private JCExpression scanForAssign(final MethodSymbol sym,
 518                                        final JCTree tree) {
 519         class TS extends TreeScanner {
 520             JCExpression result = null;
 521             public void scan(JCTree t) {
 522                 if (t != null && result == null)
 523                     t.accept(this);
 524             }
 525             public void visitAnnotation(JCAnnotation t) {
 526                 if (t == tree)
 527                     scan(t.args);
 528             }
 529             public void visitAssign(JCAssign t) {
 530                 if (t.lhs.hasTag(IDENT)) {
 531                     JCIdent ident = (JCIdent) t.lhs;
 532                     if (ident.sym == sym)
 533                         result = t.rhs;
 534                 }
 535             }
 536         }
 537         TS scanner = new TS();
 538         tree.accept(scanner);
 539         return scanner.result;
 540     }
 541 
 542     /**
 543      * Returns the tree node corresponding to this element, or null
 544      * if none can be found.
 545      */
 546     public JCTree getTree(Element e) {
 547         Pair<JCTree, ?> treeTop = getTreeAndTopLevel(e);
 548         return (treeTop != null) ? treeTop.fst : null;
 549     }
 550 
 551     public String getDocComment(Element e) {
 552         // Our doc comment is contained in a map in our toplevel,
 553         // indexed by our tree.  Find our enter environment, which gives
 554         // us our toplevel.  It also gives us a tree that contains our
 555         // tree:  walk it to find our tree.  This is painful.
 556         Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e);
 557         if (treeTop == null)
 558             return null;
 559         JCTree tree = treeTop.fst;
 560         JCCompilationUnit toplevel = treeTop.snd;
 561         if (toplevel.docComments == null)
 562             return null;
 563         return toplevel.docComments.getCommentText(tree);
 564     }
 565 
 566     public PackageElement getPackageOf(Element e) {
 567         return cast(Symbol.class, e).packge();
 568     }
 569 
 570     public boolean isDeprecated(Element e) {
 571         Symbol sym = cast(Symbol.class, e);
 572         return (sym.flags() & Flags.DEPRECATED) != 0;
 573     }
 574 
 575     public Name getBinaryName(TypeElement type) {
 576         return cast(TypeSymbol.class, type).flatName();
 577     }
 578 
 579     public Map<MethodSymbol, Attribute> getElementValuesWithDefaults(
 580                                                         AnnotationMirror a) {
 581         Attribute.Compound anno = cast(Attribute.Compound.class, a);
 582         DeclaredType annotype = a.getAnnotationType();
 583         Map<MethodSymbol, Attribute> valmap = anno.getElementValues();
 584 
 585         for (ExecutableElement ex :
 586                  methodsIn(annotype.asElement().getEnclosedElements())) {
 587             MethodSymbol meth = (MethodSymbol) ex;
 588             Attribute defaultValue = meth.getDefaultValue();
 589             if (defaultValue != null && !valmap.containsKey(meth)) {
 590                 valmap.put(meth, defaultValue);
 591             }
 592         }
 593         return valmap;
 594     }
 595 
 596     /**
 597      * {@inheritDoc}
 598      */
 599     public FilteredMemberList getAllMembers(TypeElement element) {
 600         Symbol sym = cast(Symbol.class, element);
 601         Scope scope = sym.members().dupUnshared();
 602         List<Type> closure = types.closure(sym.asType());
 603         for (Type t : closure)
 604             addMembers(scope, t);
 605         return new FilteredMemberList(scope);
 606     }
 607     // where
 608         private void addMembers(Scope scope, Type type) {
 609             members:
 610             for (Scope.Entry e = type.asElement().members().elems; e != null; e = e.sibling) {
 611                 Scope.Entry overrider = scope.lookup(e.sym.getSimpleName());
 612                 while (overrider.scope != null) {
 613                     if (overrider.sym.kind == e.sym.kind
 614                         && (overrider.sym.flags() & Flags.SYNTHETIC) == 0)
 615                     {
 616                         if (overrider.sym.getKind() == ElementKind.METHOD
 617                         && overrides((ExecutableElement)overrider.sym, (ExecutableElement)e.sym, (TypeElement)type.asElement())) {
 618                             continue members;
 619                         }
 620                     }
 621                     overrider = overrider.next();
 622                 }
 623                 boolean derived = e.sym.getEnclosingElement() != scope.owner;
 624                 ElementKind kind = e.sym.getKind();
 625                 boolean initializer = kind == ElementKind.CONSTRUCTOR
 626                     || kind == ElementKind.INSTANCE_INIT
 627                     || kind == ElementKind.STATIC_INIT;
 628                 if (!derived || (!initializer && e.sym.isInheritedIn(scope.owner, types)))
 629                     scope.enter(e.sym);
 630             }
 631         }
 632 
 633     /**
 634      * Returns all annotations of an element, whether
 635      * inherited or directly present.
 636      *
 637      * @param e  the element being examined
 638      * @return all annotations of the element
 639      */
 640     public List<Attribute.Compound> getAllAnnotationMirrors(Element e) {
 641         Symbol sym = cast(Symbol.class, e);
 642         List<Attribute.Compound> annos = sym.getRawAttributes();
 643         while (sym.getKind() == ElementKind.CLASS) {
 644             Type sup = ((ClassSymbol) sym).getSuperclass();
 645             if (!sup.hasTag(CLASS) || sup.isErroneous() ||
 646                     sup.tsym == syms.objectType.tsym) {
 647                 break;
 648             }
 649             sym = sup.tsym;
 650             List<Attribute.Compound> oldAnnos = annos;
 651             List<Attribute.Compound> newAnnos = sym.getRawAttributes();
 652             for (Attribute.Compound anno : newAnnos) {
 653                 if (isInherited(anno.type) &&
 654                         !containsAnnoOfType(oldAnnos, anno.type)) {
 655                     annos = annos.prepend(anno);
 656                 }
 657             }
 658         }
 659         return annos;
 660     }
 661 
 662     /**
 663      * Tests whether an annotation type is @Inherited.
 664      */
 665     private boolean isInherited(Type annotype) {
 666         return annotype.tsym.attribute(syms.inheritedType.tsym) != null;
 667     }
 668 
 669     /**
 670      * Tests whether a list of annotations contains an annotation
 671      * of a given type.
 672      */
 673     private static boolean containsAnnoOfType(List<Attribute.Compound> annos,
 674                                               Type type) {
 675         for (Attribute.Compound anno : annos) {
 676             if (anno.type.tsym == type.tsym)
 677                 return true;
 678         }
 679         return false;
 680     }
 681 
 682     public boolean hides(Element hiderEl, Element hideeEl) {
 683         Symbol hider = cast(Symbol.class, hiderEl);
 684         Symbol hidee = cast(Symbol.class, hideeEl);
 685 
 686         // Fields only hide fields; methods only methods; types only types.
 687         // Names must match.  Nothing hides itself (just try it).
 688         if (hider == hidee ||
 689                 hider.kind != hidee.kind ||
 690                 hider.name != hidee.name) {
 691             return false;
 692         }
 693 
 694         // Only static methods can hide other methods.
 695         // Methods only hide methods with matching signatures.
 696         if (hider.kind == Kinds.MTH) {
 697             if (!hider.isStatic() ||
 698                         !types.isSubSignature(hider.type, hidee.type)) {
 699                 return false;
 700             }
 701         }
 702 
 703         // Hider must be in a subclass of hidee's class.
 704         // Note that if M1 hides M2, and M2 hides M3, and M3 is accessible
 705         // in M1's class, then M1 and M2 both hide M3.
 706         ClassSymbol hiderClass = hider.owner.enclClass();
 707         ClassSymbol hideeClass = hidee.owner.enclClass();
 708         if (hiderClass == null || hideeClass == null ||
 709                 !hiderClass.isSubClass(hideeClass, types)) {
 710             return false;
 711         }
 712 
 713         // Hidee must be accessible in hider's class.
 714         // The method isInheritedIn is poorly named:  it checks only access.
 715         return hidee.isInheritedIn(hiderClass, types);
 716     }
 717 
 718     public boolean overrides(ExecutableElement riderEl,
 719                              ExecutableElement rideeEl, TypeElement typeEl) {
 720         MethodSymbol rider = cast(MethodSymbol.class, riderEl);
 721         MethodSymbol ridee = cast(MethodSymbol.class, rideeEl);
 722         ClassSymbol origin = cast(ClassSymbol.class, typeEl);
 723 
 724         return rider.name == ridee.name &&
 725 
 726                // not reflexive as per JLS
 727                rider != ridee &&
 728 
 729                // we don't care if ridee is static, though that wouldn't
 730                // compile
 731                !rider.isStatic() &&
 732 
 733                // Symbol.overrides assumes the following
 734                ridee.isMemberOf(origin, types) &&
 735 
 736                // check access and signatures; don't check return types
 737                rider.overrides(ridee, origin, types, false);
 738     }
 739 
 740     public String getConstantExpression(Object value) {
 741         return Constants.format(value);
 742     }
 743 
 744     /**
 745      * Print a representation of the elements to the given writer in
 746      * the specified order.  The main purpose of this method is for
 747      * diagnostics.  The exact format of the output is <em>not</em>
 748      * specified and is subject to change.
 749      *
 750      * @param w the writer to print the output to
 751      * @param elements the elements to print
 752      */
 753     public void printElements(java.io.Writer w, Element... elements) {
 754         for (Element element : elements)
 755             (new PrintingProcessor.PrintingElementVisitor(w, this)).visit(element).flush();
 756     }
 757 
 758     public Name getName(CharSequence cs) {
 759         return names.fromString(cs.toString());
 760     }
 761 
 762     /**
 763      * Returns the tree node and compilation unit corresponding to this
 764      * element, or null if they can't be found.
 765      */
 766     private Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(Element e) {
 767         Symbol sym = cast(Symbol.class, e);
 768         Env<AttrContext> enterEnv = getEnterEnv(sym);
 769         if (enterEnv == null)
 770             return null;
 771         JCTree tree = TreeInfo.declarationFor(sym, enterEnv.tree);
 772         if (tree == null || enterEnv.toplevel == null)
 773             return null;
 774         return new Pair<JCTree,JCCompilationUnit>(tree, enterEnv.toplevel);
 775     }
 776 
 777     /**
 778      * Returns the best approximation for the tree node and compilation unit
 779      * corresponding to the given element, annotation and value.
 780      * If the element is null, null is returned.
 781      * If the annotation is null or cannot be found, the tree node and
 782      * compilation unit for the element is returned.
 783      * If the annotation value is null or cannot be found, the tree node and
 784      * compilation unit for the annotation is returned.
 785      */
 786     public Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(
 787                       Element e, AnnotationMirror a, AnnotationValue v) {
 788         if (e == null)
 789             return null;
 790 
 791         Pair<JCTree, JCCompilationUnit> elemTreeTop = getTreeAndTopLevel(e);
 792         if (elemTreeTop == null)
 793             return null;
 794 
 795         if (a == null)
 796             return elemTreeTop;
 797 
 798         JCTree annoTree = matchAnnoToTree(a, e, elemTreeTop.fst);
 799         if (annoTree == null)
 800             return elemTreeTop;
 801 
 802         // 6388543: if v != null, we should search within annoTree to find
 803         // the tree matching v. For now, we ignore v and return the tree of
 804         // the annotation.
 805         return new Pair<JCTree, JCCompilationUnit>(annoTree, elemTreeTop.snd);
 806     }
 807 
 808     /**
 809      * Returns a symbol's enter environment, or null if it has none.
 810      */
 811     private Env<AttrContext> getEnterEnv(Symbol sym) {
 812         // Get enclosing class of sym, or sym itself if it is a class
 813         // or package.
 814         TypeSymbol ts = (sym.kind != Kinds.PCK)
 815                         ? sym.enclClass()
 816                         : (PackageSymbol) sym;
 817         return (ts != null)
 818                 ? enter.getEnv(ts)
 819                 : null;
 820     }
 821 
 822     /**
 823      * Returns an object cast to the specified type.
 824      * @throws NullPointerException if the object is {@code null}
 825      * @throws IllegalArgumentException if the object is of the wrong type
 826      */
 827     private static <T> T cast(Class<T> clazz, Object o) {
 828         if (! clazz.isInstance(o))
 829             throw new IllegalArgumentException(o.toString());
 830         return clazz.cast(o);
 831     }
 832 }