| 1 | /* | 
| 2 |  * Copyright 2005-2006 Sun Microsystems, Inc.  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.  Sun designates this | 
| 8 |  * particular file as subject to the "Classpath" exception as provided | 
| 9 |  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | 
| 22 |  * CA 95054 USA or visit www.sun.com if you need additional information or | 
| 23 |  * have any 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.util.Map; | 
| 31 | import javax.lang.model.SourceVersion; | 
| 32 | import javax.lang.model.element.*; | 
| 33 | import javax.lang.model.type.DeclaredType; | 
| 34 | import javax.lang.model.util.Elements; | 
| 35 | import javax.tools.JavaFileObject; | 
| 36 | import com.sun.tools.javac.code.*; | 
| 37 | import com.sun.tools.javac.code.Symbol.*; | 
| 38 | import com.sun.tools.javac.code.TypeTags; | 
| 39 | import com.sun.tools.javac.comp.AttrContext; | 
| 40 | import com.sun.tools.javac.comp.Enter; | 
| 41 | import com.sun.tools.javac.comp.Env; | 
| 42 | import com.sun.tools.javac.jvm.ClassReader; | 
| 43 | import com.sun.tools.javac.main.JavaCompiler; | 
| 44 | import com.sun.tools.javac.processing.PrintingProcessor; | 
| 45 | import com.sun.tools.javac.tree.JCTree; | 
| 46 | import com.sun.tools.javac.tree.JCTree.*; | 
| 47 | import com.sun.tools.javac.tree.TreeInfo; | 
| 48 | import com.sun.tools.javac.tree.TreeScanner; | 
| 49 | import com.sun.tools.javac.util.Name; | 
| 50 | import com.sun.tools.javac.util.*; | 
| 51 |   | 
| 52 | import static javax.lang.model.util.ElementFilter.methodsIn; | 
| 53 |   | 
| 54 | /** | 
| 55 |  * Utility methods for operating on program elements. | 
| 56 |  * | 
| 57 |  * <p><b>This is NOT part of any API supported by Sun Microsystems. | 
| 58 |  * If you write code that depends on this, you do so at your own | 
| 59 |  * risk.  This code and its internal interfaces are subject to change | 
| 60 |  * or deletion without notice.</b></p> | 
| 61 |  */ | 
| 62 | public class JavacElements implements Elements { | 
| 63 |   | 
| 64 |     private JavaCompiler javaCompiler; | 
| 65 |     private Symtab syms; | 
| 66 |     private Name.Table names; | 
| 67 |     private Types types; | 
| 68 |     private Enter enter; | 
| 69 |     private ClassReader reader; | 
| 70 |   | 
| 71 |     private static final Context.Key<JavacElements> KEY = | 
| 72 |             new Context.Key<JavacElements>(); | 
| 73 |   | 
| 74 |     public static JavacElements instance(Context context) { | 
| 75 |         JavacElements instance = context.get(KEY); | 
| 76 |         if (instance == null) { | 
| 77 |             instance = new JavacElements(context); | 
| 78 |             context.put(KEY, instance); | 
| 79 |         } | 
| 80 |         return instance; | 
| 81 |     } | 
| 82 |   | 
| 83 |     /** | 
| 84 |      * Public for use only by JavacProcessingEnvironment | 
| 85 |      */ | 
| 86 |     // TODO JavacElements constructor should be protected | 
| 87 |     public JavacElements(Context context) { | 
| 88 |         setContext(context); | 
| 89 |     } | 
| 90 |   | 
| 91 |     /** | 
| 92 |      * Use a new context.  May be called from outside to update | 
| 93 |      * internal state for a new annotation-processing round. | 
| 94 |      * This instance is *not* then registered with the new context. | 
| 95 |      */ | 
| 96 |     public void setContext(Context context) { | 
| 97 |         javaCompiler = JavaCompiler.instance(context); | 
| 98 |         syms = Symtab.instance(context); | 
| 99 |         names = Name.Table.instance(context); | 
| 100 |         types = Types.instance(context); | 
| 101 |         enter = Enter.instance(context); | 
| 102 |         reader = ClassReader.instance(context); | 
| 103 |     } | 
| 104 |   | 
| 105 |   | 
| 106 |     /** | 
| 107 |      * An internal-use utility that creates a reified annotation. | 
| 108 |      */ | 
| 109 |     public static <A extends Annotation> A getAnnotation(Symbol annotated, | 
| 110 |                                                          Class<A> annoType) { | 
| 111 |         if (!annoType.isAnnotation()) | 
| 112 |             throw new IllegalArgumentException("Not an annotation type: " | 
| 113 |                                                + annoType); | 
| 114 |         String name = annoType.getName(); | 
| 115 |         for (Attribute.Compound anno : annotated.getAnnotationMirrors()) | 
| 116 |             if (name.equals(anno.type.tsym.flatName().toString())) | 
| 117 |                 return AnnotationProxyMaker.generateAnnotation(anno, annoType); | 
| 118 |         return null; | 
| 119 |     } | 
| 120 |   | 
| 121 |     /** | 
| 122 |      * An internal-use utility that creates a reified annotation. | 
| 123 |      * This overloaded version take annotation inheritance into account. | 
| 124 |      */ | 
| 125 |     public static <A extends Annotation> A getAnnotation(ClassSymbol annotated, | 
| 126 |                                                          Class<A> annoType) { | 
| 127 |         boolean inherited = annoType.isAnnotationPresent(Inherited.class); | 
| 128 |         A result = null; | 
| 129 |         while (annotated.name != annotated.name.table.java_lang_Object) { | 
| 130 |             result = getAnnotation((Symbol)annotated, annoType); | 
| 131 |             if (result != null || !inherited) | 
| 132 |                 break; | 
| 133 |             Type sup = annotated.getSuperclass(); | 
| 134 |             if (sup.tag != TypeTags.CLASS || sup.isErroneous()) | 
| 135 |                 break; | 
| 136 |             annotated = (ClassSymbol) sup.tsym; | 
| 137 |         } | 
| 138 |         return result; | 
| 139 |     } | 
| 140 |   | 
| 141 |   | 
| 142 |     public PackageSymbol getPackageElement(CharSequence name) { | 
| 143 |         String strName = name.toString(); | 
| 144 |         if (strName.equals("")) | 
| 145 |             return syms.unnamedPackage; | 
| 146 |         return SourceVersion.isName(strName) | 
| 147 |             ? nameToSymbol(strName, PackageSymbol.class) | 
| 148 |             : null; | 
| 149 |     } | 
| 150 |   | 
| 151 |     public ClassSymbol getTypeElement(CharSequence name) { | 
| 152 |         String strName = name.toString(); | 
| 153 |         return SourceVersion.isName(strName) | 
| 154 |             ? nameToSymbol(strName, ClassSymbol.class) | 
| 155 |             : null; | 
| 156 |     } | 
| 157 |   | 
| 158 |     /** | 
| 159 |      * Returns a symbol given the type's or packages's canonical name, | 
| 160 |      * or null if the name isn't found. | 
| 161 |      */ | 
| 162 |     private <S extends Symbol> S nameToSymbol(String nameStr, Class<S> clazz) { | 
| 163 |         Name name = names.fromString(nameStr); | 
| 164 |         // First check cache. | 
| 165 |         Symbol sym = (clazz == ClassSymbol.class) | 
| 166 |                     ? syms.classes.get(name) | 
| 167 |                     : syms.packages.get(name); | 
| 168 |   | 
| 169 |         try { | 
| 170 |             if (sym == null) | 
| 171 |                 sym = javaCompiler.resolveIdent(nameStr); | 
| 172 |   | 
| 173 |             sym.complete(); | 
| 174 |   | 
| 175 |             return (sym.kind != Kinds.ERR && | 
| 176 |                     sym.exists() && | 
| 177 |                     clazz.isInstance(sym) && | 
| 178 |                     name.equals(sym.getQualifiedName())) | 
| 179 |                 ? clazz.cast(sym) | 
| 180 |                 : null; | 
| 181 |         } catch (CompletionFailure e) { | 
| 182 |             return null; | 
| 183 |         } | 
| 184 |     } | 
| 185 |   | 
| 186 |     public JavacSourcePosition getSourcePosition(Element e) { | 
| 187 |         Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); | 
| 188 |         if (treeTop == null) | 
| 189 |             return null; | 
| 190 |         JCTree tree = treeTop.fst; | 
| 191 |         JCCompilationUnit toplevel = treeTop.snd; | 
| 192 |         JavaFileObject sourcefile = toplevel.sourcefile; | 
| 193 |         if (sourcefile == null) | 
| 194 |             return null; | 
| 195 |         return new JavacSourcePosition(sourcefile, tree.pos, toplevel.lineMap); | 
| 196 |     } | 
| 197 |   | 
| 198 |     public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a) { | 
| 199 |         Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); | 
| 200 |         if (treeTop == null) | 
| 201 |             return null; | 
| 202 |         JCTree tree = treeTop.fst; | 
| 203 |         JCCompilationUnit toplevel = treeTop.snd; | 
| 204 |         JavaFileObject sourcefile = toplevel.sourcefile; | 
| 205 |         if (sourcefile == null) | 
| 206 |             return null; | 
| 207 |   | 
| 208 |         JCTree annoTree = matchAnnoToTree(a, e, tree); | 
| 209 |         if (annoTree == null) | 
| 210 |             return null; | 
| 211 |         return new JavacSourcePosition(sourcefile, annoTree.pos, | 
| 212 |                                        toplevel.lineMap); | 
| 213 |     } | 
| 214 |   | 
| 215 |     public JavacSourcePosition getSourcePosition(Element e, AnnotationMirror a, | 
| 216 |                                             AnnotationValue v) { | 
| 217 |         // TODO: better accuracy in getSourcePosition(... AnnotationValue) | 
| 218 |         return getSourcePosition(e, a); | 
| 219 |     } | 
| 220 |   | 
| 221 |     /** | 
| 222 |      * Returns the tree for an annotation given the annotated element | 
| 223 |      * and the element's own tree.  Returns null if the tree cannot be found. | 
| 224 |      */ | 
| 225 |     private JCTree matchAnnoToTree(AnnotationMirror findme, | 
| 226 |                                    Element e, JCTree tree) { | 
| 227 |         Symbol sym = cast(Symbol.class, e); | 
| 228 |         class Vis extends JCTree.Visitor { | 
| 229 |             List<JCAnnotation> result = null; | 
| 230 |             public void visitTopLevel(JCCompilationUnit tree) { | 
| 231 |                 result = tree.packageAnnotations; | 
| 232 |             } | 
| 233 |             public void visitClassDef(JCClassDecl tree) { | 
| 234 |                 result = tree.mods.annotations; | 
| 235 |             } | 
| 236 |             public void visitMethodDef(JCMethodDecl tree) { | 
| 237 |                 result = tree.mods.annotations; | 
| 238 |             } | 
| 239 |             public void visitVarDef(JCVariableDecl tree) { | 
| 240 |                 result = tree.mods.annotations; | 
| 241 |             } | 
| 242 |         } | 
| 243 |         Vis vis = new Vis(); | 
| 244 |         tree.accept(vis); | 
| 245 |         if (vis.result == null) | 
| 246 |             return null; | 
| 247 |         return matchAnnoToTree(cast(Attribute.Compound.class, findme), | 
| 248 |                                sym.getAnnotationMirrors(), | 
| 249 |                                vis.result); | 
| 250 |     } | 
| 251 |   | 
| 252 |     /** | 
| 253 |      * Returns the tree for an annotation given a list of annotations | 
| 254 |      * in which to search (recursively) and their corresponding trees. | 
| 255 |      * Returns null if the tree cannot be found. | 
| 256 |      */ | 
| 257 |     private JCTree matchAnnoToTree(Attribute.Compound findme, | 
| 258 |                                    List<Attribute.Compound> annos, | 
| 259 |                                    List<JCAnnotation> trees) { | 
| 260 |         for (Attribute.Compound anno : annos) { | 
| 261 |             for (JCAnnotation tree : trees) { | 
| 262 |                 JCTree match = matchAnnoToTree(findme, anno, tree); | 
| 263 |                 if (match != null) | 
| 264 |                     return match; | 
| 265 |             } | 
| 266 |         } | 
| 267 |         return null; | 
| 268 |     } | 
| 269 |   | 
| 270 |     /** | 
| 271 |      * Returns the tree for an annotation given an Attribute to | 
| 272 |      * search (recursively) and its corresponding tree. | 
| 273 |      * Returns null if the tree cannot be found. | 
| 274 |      */ | 
| 275 |     private JCTree matchAnnoToTree(final Attribute.Compound findme, | 
| 276 |                                    final Attribute attr, | 
| 277 |                                    final JCTree tree) { | 
| 278 |         if (attr == findme) | 
| 279 |             return (tree.type.tsym == findme.type.tsym) ? tree : null; | 
| 280 |   | 
| 281 |         class Vis implements Attribute.Visitor { | 
| 282 |             JCTree result = null; | 
| 283 |             public void visitConstant(Attribute.Constant value) { | 
| 284 |             } | 
| 285 |             public void visitClass(Attribute.Class clazz) { | 
| 286 |             } | 
| 287 |             public void visitCompound(Attribute.Compound anno) { | 
| 288 |                 for (Pair<MethodSymbol, Attribute> pair : anno.values) { | 
| 289 |                     JCExpression expr = scanForAssign(pair.fst, tree); | 
| 290 |                     if (expr != null) { | 
| 291 |                         JCTree match = matchAnnoToTree(findme, pair.snd, expr); | 
| 292 |                         if (match != null) { | 
| 293 |                             result = match; | 
| 294 |                             return; | 
| 295 |                         } | 
| 296 |                     } | 
| 297 |                 } | 
| 298 |             } | 
| 299 |             public void visitArray(Attribute.Array array) { | 
| 300 |                 if (tree.getTag() == JCTree.NEWARRAY && | 
| 301 |                         types.elemtype(array.type).tsym == findme.type.tsym) { | 
| 302 |                     List<JCExpression> elems = ((JCNewArray) tree).elems; | 
| 303 |                     for (Attribute value : array.values) { | 
| 304 |                         if (value == findme) { | 
| 305 |                             result = elems.head; | 
| 306 |                             return; | 
| 307 |                         } | 
| 308 |                         elems = elems.tail; | 
| 309 |                     } | 
| 310 |                 } | 
| 311 |             } | 
| 312 |             public void visitEnum(Attribute.Enum e) { | 
| 313 |             } | 
| 314 |             public void visitError(Attribute.Error e) { | 
| 315 |             } | 
| 316 |         } | 
| 317 |         Vis vis = new Vis(); | 
| 318 |         attr.accept(vis); | 
| 319 |         return vis.result; | 
| 320 |     } | 
| 321 |   | 
| 322 |     /** | 
| 323 |      * Scans for a JCAssign node with a LHS matching a given | 
| 324 |      * symbol, and returns its RHS.  Does not scan nested JCAnnotations. | 
| 325 |      */ | 
| 326 |     private JCExpression scanForAssign(final MethodSymbol sym, | 
| 327 |                                        final JCTree tree) { | 
| 328 |         class TS extends TreeScanner { | 
| 329 |             JCExpression result = null; | 
| 330 |             public void scan(JCTree t) { | 
| 331 |                 if (t != null && result == null) | 
| 332 |                     t.accept(this); | 
| 333 |             } | 
| 334 |             public void visitAnnotation(JCAnnotation t) { | 
| 335 |                 if (t == tree) | 
| 336 |                     scan(t.args); | 
| 337 |             } | 
| 338 |             public void visitAssign(JCAssign t) { | 
| 339 |                 if (t.lhs.getTag() == JCTree.IDENT) { | 
| 340 |                     JCIdent ident = (JCIdent) t.lhs; | 
| 341 |                     if (ident.sym == sym) | 
| 342 |                         result = t.rhs; | 
| 343 |                 } | 
| 344 |             } | 
| 345 |         } | 
| 346 |         TS scanner = new TS(); | 
| 347 |         tree.accept(scanner); | 
| 348 |         return scanner.result; | 
| 349 |     } | 
| 350 |   | 
| 351 |     /** | 
| 352 |      * Returns the tree node corresponding to this element, or null | 
| 353 |      * if none can be found. | 
| 354 |      */ | 
| 355 |     public JCTree getTree(Element e) { | 
| 356 |         Pair<JCTree, ?> treeTop = getTreeAndTopLevel(e); | 
| 357 |         return (treeTop != null) ? treeTop.fst : null; | 
| 358 |     } | 
| 359 |   | 
| 360 |     public String getDocComment(Element e) { | 
| 361 |         // Our doc comment is contained in a map in our toplevel, | 
| 362 |         // indexed by our tree.  Find our enter environment, which gives | 
| 363 |         // us our toplevel.  It also gives us a tree that contains our | 
| 364 |         // tree:  walk it to find our tree.  This is painful. | 
| 365 |         Pair<JCTree, JCCompilationUnit> treeTop = getTreeAndTopLevel(e); | 
| 366 |         if (treeTop == null) | 
| 367 |             return null; | 
| 368 |         JCTree tree = treeTop.fst; | 
| 369 |         JCCompilationUnit toplevel = treeTop.snd; | 
| 370 |         if (toplevel.docComments == null) | 
| 371 |             return null; | 
| 372 |         return toplevel.docComments.get(tree); | 
| 373 |     } | 
| 374 |   | 
| 375 |     public PackageElement getPackageOf(Element e) { | 
| 376 |         return cast(Symbol.class, e).packge(); | 
| 377 |     } | 
| 378 |   | 
| 379 |     public boolean isDeprecated(Element e) { | 
| 380 |         Symbol sym = cast(Symbol.class, e); | 
| 381 |         return (sym.flags() & Flags.DEPRECATED) != 0; | 
| 382 |     } | 
| 383 |   | 
| 384 |     public Name getBinaryName(TypeElement type) { | 
| 385 |         return cast(TypeSymbol.class, type).flatName(); | 
| 386 |     } | 
| 387 |   | 
| 388 |     public Map<MethodSymbol, Attribute> getElementValuesWithDefaults( | 
| 389 |                                                         AnnotationMirror a) { | 
| 390 |         Attribute.Compound anno = cast(Attribute.Compound.class, a); | 
| 391 |         DeclaredType annotype = a.getAnnotationType(); | 
| 392 |         Map<MethodSymbol, Attribute> valmap = anno.getElementValues(); | 
| 393 |   | 
| 394 |         for (ExecutableElement ex : | 
| 395 |                  methodsIn(annotype.asElement().getEnclosedElements())) { | 
| 396 |             MethodSymbol meth = (MethodSymbol) ex; | 
| 397 |             Attribute defaultValue = meth.getDefaultValue(); | 
| 398 |             if (defaultValue != null && !valmap.containsKey(meth)) { | 
| 399 |                 valmap.put(meth, defaultValue); | 
| 400 |             } | 
| 401 |         } | 
| 402 |         return valmap; | 
| 403 |     } | 
| 404 |   | 
| 405 |     /** | 
| 406 |      * {@inheritDoc} | 
| 407 |      */ | 
| 408 |     public FilteredMemberList getAllMembers(TypeElement element) { | 
| 409 |         Symbol sym = cast(Symbol.class, element); | 
| 410 |         Scope scope = sym.members().dupUnshared(); | 
| 411 |         List<Type> closure = types.closure(sym.asType()); | 
| 412 |         for (Type t : closure) | 
| 413 |             addMembers(scope, t); | 
| 414 |         return new FilteredMemberList(scope); | 
| 415 |     } | 
| 416 |     // where | 
| 417 |         private void addMembers(Scope scope, Type type) { | 
| 418 |             members: | 
| 419 |             for (Scope.Entry e = type.asElement().members().elems; e != null; e = e.sibling) { | 
| 420 |                 Scope.Entry overrider = scope.lookup(e.sym.getSimpleName()); | 
| 421 |                 while (overrider.scope != null) { | 
| 422 |                     if (overrider.sym.kind == e.sym.kind | 
| 423 |                         && (overrider.sym.flags() & Flags.SYNTHETIC) == 0) | 
| 424 |                     { | 
| 425 |                         if (overrider.sym.getKind() == ElementKind.METHOD | 
| 426 |                         && overrides((ExecutableElement)overrider.sym, (ExecutableElement)e.sym, (TypeElement)type.asElement())) { | 
| 427 |                             continue members; | 
| 428 |                         } | 
| 429 |                     } | 
| 430 |                     overrider = overrider.next(); | 
| 431 |                 } | 
| 432 |                 boolean derived = e.sym.getEnclosingElement() != scope.owner; | 
| 433 |                 ElementKind kind = e.sym.getKind(); | 
| 434 |                 boolean initializer = kind == ElementKind.CONSTRUCTOR | 
| 435 |                     || kind == ElementKind.INSTANCE_INIT | 
| 436 |                     || kind == ElementKind.STATIC_INIT; | 
| 437 |                 if (!derived || (!initializer && e.sym.isInheritedIn(scope.owner, types))) | 
| 438 |                     scope.enter(e.sym); | 
| 439 |             } | 
| 440 |         } | 
| 441 |   | 
| 442 |     /** | 
| 443 |      * Returns all annotations of an element, whether | 
| 444 |      * inherited or directly present. | 
| 445 |      * | 
| 446 |      * @param e  the element being examined | 
| 447 |      * @return all annotations of the element | 
| 448 |      */ | 
| 449 |     public List<Attribute.Compound> getAllAnnotationMirrors(Element e) { | 
| 450 |         Symbol sym = cast(Symbol.class, e); | 
| 451 |         List<Attribute.Compound> annos = sym.getAnnotationMirrors(); | 
| 452 |         while (sym.getKind() == ElementKind.CLASS) { | 
| 453 |             Type sup = ((ClassSymbol) sym).getSuperclass(); | 
| 454 |             if (sup.tag != TypeTags.CLASS || sup.isErroneous() || | 
| 455 |                     sup.tsym == syms.objectType.tsym) { | 
| 456 |                 break; | 
| 457 |             } | 
| 458 |             sym = sup.tsym; | 
| 459 |             List<Attribute.Compound> oldAnnos = annos; | 
| 460 |             for (Attribute.Compound anno : sym.getAnnotationMirrors()) { | 
| 461 |                 if (isInherited(anno.type) && | 
| 462 |                         !containsAnnoOfType(oldAnnos, anno.type)) { | 
| 463 |                     annos = annos.prepend(anno); | 
| 464 |                 } | 
| 465 |             } | 
| 466 |         } | 
| 467 |         return annos; | 
| 468 |     } | 
| 469 |   | 
| 470 |     /** | 
| 471 |      * Tests whether an annotation type is @Inherited. | 
| 472 |      */ | 
| 473 |     private boolean isInherited(Type annotype) { | 
| 474 |         for (Attribute.Compound anno : annotype.tsym.getAnnotationMirrors()) { | 
| 475 |             if (anno.type.tsym == syms.inheritedType.tsym) | 
| 476 |                 return true; | 
| 477 |         } | 
| 478 |         return false; | 
| 479 |     } | 
| 480 |   | 
| 481 |     /** | 
| 482 |      * Tests whether a list of annotations contains an annotation | 
| 483 |      * of a given type. | 
| 484 |      */ | 
| 485 |     private static boolean containsAnnoOfType(List<Attribute.Compound> annos, | 
| 486 |                                               Type type) { | 
| 487 |         for (Attribute.Compound anno : annos) { | 
| 488 |             if (anno.type.tsym == type.tsym) | 
| 489 |                 return true; | 
| 490 |         } | 
| 491 |         return false; | 
| 492 |     } | 
| 493 |   | 
| 494 |     public boolean hides(Element hiderEl, Element hideeEl) { | 
| 495 |         Symbol hider = cast(Symbol.class, hiderEl); | 
| 496 |         Symbol hidee = cast(Symbol.class, hideeEl); | 
| 497 |   | 
| 498 |         // Fields only hide fields; methods only methods; types only types. | 
| 499 |         // Names must match.  Nothing hides itself (just try it). | 
| 500 |         if (hider == hidee || | 
| 501 |                 hider.kind != hidee.kind || | 
| 502 |                 hider.name != hidee.name) { | 
| 503 |             return false; | 
| 504 |         } | 
| 505 |   | 
| 506 |         // Only static methods can hide other methods. | 
| 507 |         // Methods only hide methods with matching signatures. | 
| 508 |         if (hider.kind == Kinds.MTH) { | 
| 509 |             if (!hider.isStatic() || | 
| 510 |                         !types.isSubSignature(hider.type, hidee.type)) { | 
| 511 |                 return false; | 
| 512 |             } | 
| 513 |         } | 
| 514 |   | 
| 515 |         // Hider must be in a subclass of hidee's class. | 
| 516 |         // Note that if M1 hides M2, and M2 hides M3, and M3 is accessible | 
| 517 |         // in M1's class, then M1 and M2 both hide M3. | 
| 518 |         ClassSymbol hiderClass = hider.owner.enclClass(); | 
| 519 |         ClassSymbol hideeClass = hidee.owner.enclClass(); | 
| 520 |         if (hiderClass == null || hideeClass == null || | 
| 521 |                 !hiderClass.isSubClass(hideeClass, types)) { | 
| 522 |             return false; | 
| 523 |         } | 
| 524 |   | 
| 525 |         // Hidee must be accessible in hider's class. | 
| 526 |         // The method isInheritedIn is poorly named:  it checks only access. | 
| 527 |         return hidee.isInheritedIn(hiderClass, types); | 
| 528 |     } | 
| 529 |   | 
| 530 |     public boolean overrides(ExecutableElement riderEl, | 
| 531 |                              ExecutableElement rideeEl, TypeElement typeEl) { | 
| 532 |         MethodSymbol rider = cast(MethodSymbol.class, riderEl); | 
| 533 |         MethodSymbol ridee = cast(MethodSymbol.class, rideeEl); | 
| 534 |         ClassSymbol origin = cast(ClassSymbol.class, typeEl); | 
| 535 |   | 
| 536 |         return rider.name == ridee.name && | 
| 537 |   | 
| 538 |                // not reflexive as per JLS | 
| 539 |                rider != ridee && | 
| 540 |   | 
| 541 |                // we don't care if ridee is static, though that wouldn't | 
| 542 |                // compile | 
| 543 |                !rider.isStatic() && | 
| 544 |   | 
| 545 |                // Symbol.overrides assumes the following | 
| 546 |                ridee.isMemberOf(origin, types) && | 
| 547 |   | 
| 548 |                // check access and signatures; don't check return types | 
| 549 |                rider.overrides(ridee, origin, types, false); | 
| 550 |     } | 
| 551 |   | 
| 552 |     public String getConstantExpression(Object value) { | 
| 553 |         return Constants.format(value); | 
| 554 |     } | 
| 555 |   | 
| 556 |     /** | 
| 557 |      * Print a representation of the elements to the given writer in | 
| 558 |      * the specified order.  The main purpose of this method is for | 
| 559 |      * diagnostics.  The exact format of the output is <em>not</em> | 
| 560 |      * specified and is subject to change. | 
| 561 |      * | 
| 562 |      * @param w the writer to print the output to | 
| 563 |      * @param elements the elements to print | 
| 564 |      */ | 
| 565 |     public void printElements(java.io.Writer w, Element... elements) { | 
| 566 |         for (Element element : elements) | 
| 567 |             (new PrintingProcessor.PrintingElementVisitor(w, this)).visit(element).flush(); | 
| 568 |     } | 
| 569 |   | 
| 570 |     public Name getName(CharSequence cs) { | 
| 571 |         return Name.fromString(names, cs.toString()); | 
| 572 |     } | 
| 573 |   | 
| 574 |     /** | 
| 575 |      * Returns the tree node and compilation unit corresponding to this | 
| 576 |      * element, or null if they can't be found. | 
| 577 |      */ | 
| 578 |     private Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel(Element e) { | 
| 579 |         Symbol sym = cast(Symbol.class, e); | 
| 580 |         Env<AttrContext> enterEnv = getEnterEnv(sym); | 
| 581 |         if (enterEnv == null) | 
| 582 |             return null; | 
| 583 |         JCTree tree = TreeInfo.declarationFor(sym, enterEnv.tree); | 
| 584 |         if (tree == null || enterEnv.toplevel == null) | 
| 585 |             return null; | 
| 586 |         return new Pair<JCTree,JCCompilationUnit>(tree, enterEnv.toplevel); | 
| 587 |     } | 
| 588 |   | 
| 589 |     /** | 
| 590 |      * Returns the best approximation for the tree node and compilation unit | 
| 591 |      * corresponding to the given element, annotation and value. | 
| 592 |      * If the element is null, null is returned. | 
| 593 |      * If the annotation is null or cannot be found, the tree node and | 
| 594 |      * compilation unit for the element is returned. | 
| 595 |      * If the annotation value is null or cannot be found, the tree node and | 
| 596 |      * compilation unit for the annotation is returned. | 
| 597 |      */ | 
| 598 |     public Pair<JCTree, JCCompilationUnit> getTreeAndTopLevel( | 
| 599 |                       Element e, AnnotationMirror a, AnnotationValue v) { | 
| 600 |         if (e == null) | 
| 601 |             return null; | 
| 602 |   | 
| 603 |         Pair<JCTree, JCCompilationUnit> elemTreeTop = getTreeAndTopLevel(e); | 
| 604 |         if (elemTreeTop == null) | 
| 605 |             return null; | 
| 606 |   | 
| 607 |         if (a == null) | 
| 608 |             return elemTreeTop; | 
| 609 |   | 
| 610 |         JCTree annoTree = matchAnnoToTree(a, e, elemTreeTop.fst); | 
| 611 |         if (annoTree == null) | 
| 612 |             return elemTreeTop; | 
| 613 |   | 
| 614 |         // 6388543: if v != null, we should search within annoTree to find | 
| 615 |         // the tree matching v. For now, we ignore v and return the tree of | 
| 616 |         // the annotation. | 
| 617 |         return new Pair<JCTree, JCCompilationUnit>(annoTree, elemTreeTop.snd); | 
| 618 |     } | 
| 619 |   | 
| 620 |     /** | 
| 621 |      * Returns a symbol's enter environment, or null if it has none. | 
| 622 |      */ | 
| 623 |     private Env<AttrContext> getEnterEnv(Symbol sym) { | 
| 624 |         // Get enclosing class of sym, or sym itself if it is a class | 
| 625 |         // or package. | 
| 626 |         TypeSymbol ts = (sym.kind != Kinds.PCK) | 
| 627 |                         ? sym.enclClass() | 
| 628 |                         : (PackageSymbol) sym; | 
| 629 |         return (ts != null) | 
| 630 |                 ? enter.getEnv(ts) | 
| 631 |                 : null; | 
| 632 |     } | 
| 633 |   | 
| 634 |     /** | 
| 635 |      * Returns an object cast to the specified type. | 
| 636 |      * @throws NullPointerException if the object is {@code null} | 
| 637 |      * @throws IllegalArgumentException if the object is of the wrong type | 
| 638 |      */ | 
| 639 |     private static <T> T cast(Class<T> clazz, Object o) { | 
| 640 |         if (! clazz.isInstance(o)) | 
| 641 |             throw new IllegalArgumentException(o.toString()); | 
| 642 |         return clazz.cast(o); | 
| 643 |     } | 
| 644 | } |