| 1 | /* | 
| 2 |  * Copyright 1999-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.code; | 
| 27 |   | 
| 28 | import java.util.ArrayList; | 
| 29 | import java.util.Collections; | 
| 30 | import java.util.Set; | 
| 31 | import java.util.concurrent.Callable; | 
| 32 | import javax.lang.model.element.*; | 
| 33 | import javax.lang.model.type.ReferenceType; | 
| 34 | import javax.lang.model.type.TypeMirror; | 
| 35 | import javax.tools.JavaFileObject; | 
| 36 |   | 
| 37 | import com.sun.tools.javac.util.*; | 
| 38 | import com.sun.tools.javac.util.Name; | 
| 39 | import com.sun.tools.javac.code.Type.*; | 
| 40 | import com.sun.tools.javac.comp.Attr; | 
| 41 | import com.sun.tools.javac.comp.AttrContext; | 
| 42 | import com.sun.tools.javac.comp.Env; | 
| 43 | import com.sun.tools.javac.jvm.*; | 
| 44 | import com.sun.tools.javac.model.*; | 
| 45 | import com.sun.tools.javac.tree.JCTree; | 
| 46 |   | 
| 47 | import static com.sun.tools.javac.code.Flags.*; | 
| 48 | import static com.sun.tools.javac.code.Kinds.*; | 
| 49 | import static com.sun.tools.javac.code.TypeTags.*; | 
| 50 |   | 
| 51 | /** Root class for Java symbols. It contains subclasses | 
| 52 |  *  for specific sorts of symbols, such as variables, methods and operators, | 
| 53 |  *  types, packages. Each subclass is represented as a static inner class | 
| 54 |  *  inside Symbol. | 
| 55 |  * | 
| 56 |  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If | 
| 57 |  *  you write code that depends on this, you do so at your own risk. | 
| 58 |  *  This code and its internal interfaces are subject to change or | 
| 59 |  *  deletion without notice.</b> | 
| 60 |  */ | 
| 61 | public abstract class Symbol implements Element { | 
| 62 |     // public Throwable debug = new Throwable(); | 
| 63 |   | 
| 64 |     /** The kind of this symbol. | 
| 65 |      *  @see Kinds | 
| 66 |      */ | 
| 67 |     public int kind; | 
| 68 |   | 
| 69 |     /** The flags of this symbol. | 
| 70 |      */ | 
| 71 |     public long flags_field; | 
| 72 |   | 
| 73 |     /** An accessor method for the flags of this symbol. | 
| 74 |      *  Flags of class symbols should be accessed through the accessor | 
| 75 |      *  method to make sure that the class symbol is loaded. | 
| 76 |      */ | 
| 77 |     public long flags() { return flags_field; } | 
| 78 |   | 
| 79 |     /** The attributes of this symbol. | 
| 80 |      */ | 
| 81 |     public List<Attribute.Compound> attributes_field; | 
| 82 |   | 
| 83 |     /** An accessor method for the attributes of this symbol. | 
| 84 |      *  Attributes of class symbols should be accessed through the accessor | 
| 85 |      *  method to make sure that the class symbol is loaded. | 
| 86 |      */ | 
| 87 |     public List<Attribute.Compound> getAnnotationMirrors() { | 
| 88 |         assert attributes_field != null; | 
| 89 |         return attributes_field; | 
| 90 |     } | 
| 91 |   | 
| 92 |     /** Fetch a particular annotation from a symbol. */ | 
| 93 |     public Attribute.Compound attribute(Symbol anno) { | 
| 94 |         for (Attribute.Compound a : getAnnotationMirrors()) | 
| 95 |             if (a.type.tsym == anno) return a; | 
| 96 |         return null; | 
| 97 |     } | 
| 98 |   | 
| 99 |     /** The name of this symbol in Utf8 representation. | 
| 100 |      */ | 
| 101 |     public Name name; | 
| 102 |   | 
| 103 |     /** The type of this symbol. | 
| 104 |      */ | 
| 105 |     public Type type; | 
| 106 |   | 
| 107 |     /** The owner of this symbol. | 
| 108 |      */ | 
| 109 |     public Symbol owner; | 
| 110 |   | 
| 111 |     /** The completer of this symbol. | 
| 112 |      */ | 
| 113 |     public Completer completer; | 
| 114 |   | 
| 115 |     /** A cache for the type erasure of this symbol. | 
| 116 |      */ | 
| 117 |     public Type erasure_field; | 
| 118 |   | 
| 119 |     /** Construct a symbol with given kind, flags, name, type and owner. | 
| 120 |      */ | 
| 121 |     public Symbol(int kind, long flags, Name name, Type type, Symbol owner) { | 
| 122 |         this.kind = kind; | 
| 123 |         this.flags_field = flags; | 
| 124 |         this.type = type; | 
| 125 |         this.owner = owner; | 
| 126 |         this.completer = null; | 
| 127 |         this.erasure_field = null; | 
| 128 |         this.attributes_field = List.nil(); | 
| 129 |         this.name = name; | 
| 130 |     } | 
| 131 |   | 
| 132 |     /** Clone this symbol with new owner. | 
| 133 |      *  Legal only for fields and methods. | 
| 134 |      */ | 
| 135 |     public Symbol clone(Symbol newOwner) { | 
| 136 |         throw new AssertionError(); | 
| 137 |     } | 
| 138 |   | 
| 139 |     /** The Java source which this symbol represents. | 
| 140 |      *  A description of this symbol; overrides Object. | 
| 141 |      */ | 
| 142 |     public String toString() { | 
| 143 |         return name.toString(); | 
| 144 |     } | 
| 145 |   | 
| 146 |     /** A Java source description of the location of this symbol; used for | 
| 147 |      *  error reporting.  Use of this method may result in the loss of the | 
| 148 |      *  symbol's description. | 
| 149 |      */ | 
| 150 |     public String location() { | 
| 151 |         if (owner.name == null || (owner.name.len == 0 && owner.kind != PCK)) { | 
| 152 |             return ""; | 
| 153 |         } | 
| 154 |         return owner.toString(); | 
| 155 |     } | 
| 156 |   | 
| 157 |     public String location(Type site, Types types) { | 
| 158 |         if (owner.name == null || owner.name.len == 0) { | 
| 159 |             return location(); | 
| 160 |         } | 
| 161 |         if (owner.type.tag == CLASS) { | 
| 162 |             Type ownertype = types.asOuterSuper(site, owner); | 
| 163 |             if (ownertype != null) return ownertype.toString(); | 
| 164 |         } | 
| 165 |         return owner.toString(); | 
| 166 |     } | 
| 167 |   | 
| 168 |     /** The symbol's erased type. | 
| 169 |      */ | 
| 170 |     public Type erasure(Types types) { | 
| 171 |         if (erasure_field == null) | 
| 172 |             erasure_field = types.erasure(type); | 
| 173 |         return erasure_field; | 
| 174 |     } | 
| 175 |   | 
| 176 |     /** The external type of a symbol. This is the symbol's erased type | 
| 177 |      *  except for constructors of inner classes which get the enclosing | 
| 178 |      *  instance class added as first argument. | 
| 179 |      */ | 
| 180 |     public Type externalType(Types types) { | 
| 181 |         Type t = erasure(types); | 
| 182 |         if (name == name.table.init && owner.hasOuterInstance()) { | 
| 183 |             Type outerThisType = types.erasure(owner.type.getEnclosingType()); | 
| 184 |             return new MethodType(t.getParameterTypes().prepend(outerThisType), | 
| 185 |                                   t.getReturnType(), | 
| 186 |                                   t.getThrownTypes(), | 
| 187 |                                   t.tsym); | 
| 188 |         } else { | 
| 189 |             return t; | 
| 190 |         } | 
| 191 |     } | 
| 192 |   | 
| 193 |     public boolean isStatic() { | 
| 194 |         return | 
| 195 |             (flags() & STATIC) != 0 || | 
| 196 |             (owner.flags() & INTERFACE) != 0 && kind != MTH; | 
| 197 |     } | 
| 198 |   | 
| 199 |     public boolean isInterface() { | 
| 200 |         return (flags() & INTERFACE) != 0; | 
| 201 |     } | 
| 202 |   | 
| 203 |     /** Is this symbol declared (directly or indirectly) local | 
| 204 |      *  to a method or variable initializer? | 
| 205 |      *  Also includes fields of inner classes which are in | 
| 206 |      *  turn local to a method or variable initializer. | 
| 207 |      */ | 
| 208 |     public boolean isLocal() { | 
| 209 |         return | 
| 210 |             (owner.kind & (VAR | MTH)) != 0 || | 
| 211 |             (owner.kind == TYP && owner.isLocal()); | 
| 212 |     } | 
| 213 |   | 
| 214 |     /** Is this symbol a constructor? | 
| 215 |      */ | 
| 216 |     public boolean isConstructor() { | 
| 217 |         return name == name.table.init; | 
| 218 |     } | 
| 219 |   | 
| 220 |     /** The fully qualified name of this symbol. | 
| 221 |      *  This is the same as the symbol's name except for class symbols, | 
| 222 |      *  which are handled separately. | 
| 223 |      */ | 
| 224 |     public Name getQualifiedName() { | 
| 225 |         return name; | 
| 226 |     } | 
| 227 |   | 
| 228 |     /** The fully qualified name of this symbol after converting to flat | 
| 229 |      *  representation. This is the same as the symbol's name except for | 
| 230 |      *  class symbols, which are handled separately. | 
| 231 |      */ | 
| 232 |     public Name flatName() { | 
| 233 |         return getQualifiedName(); | 
| 234 |     } | 
| 235 |   | 
| 236 |     /** If this is a class or package, its members, otherwise null. | 
| 237 |      */ | 
| 238 |     public Scope members() { | 
| 239 |         return null; | 
| 240 |     } | 
| 241 |   | 
| 242 |     /** A class is an inner class if it it has an enclosing instance class. | 
| 243 |      */ | 
| 244 |     public boolean isInner() { | 
| 245 |         return type.getEnclosingType().tag == CLASS; | 
| 246 |     } | 
| 247 |   | 
| 248 |     /** An inner class has an outer instance if it is not an interface | 
| 249 |      *  it has an enclosing instance class which might be referenced from the class. | 
| 250 |      *  Nested classes can see instance members of their enclosing class. | 
| 251 |      *  Their constructors carry an additional this$n parameter, inserted | 
| 252 |      *  implicitly by the compiler. | 
| 253 |      * | 
| 254 |      *  @see #isInner | 
| 255 |      */ | 
| 256 |     public boolean hasOuterInstance() { | 
| 257 |         return | 
| 258 |             type.getEnclosingType().tag == CLASS && (flags() & (INTERFACE | NOOUTERTHIS)) == 0; | 
| 259 |     } | 
| 260 |   | 
| 261 |     /** The closest enclosing class of this symbol's declaration. | 
| 262 |      */ | 
| 263 |     public ClassSymbol enclClass() { | 
| 264 |         Symbol c = this; | 
| 265 |         while (c != null && | 
| 266 |                ((c.kind & TYP) == 0 || c.type.tag != CLASS)) { | 
| 267 |             c = c.owner; | 
| 268 |         } | 
| 269 |         return (ClassSymbol)c; | 
| 270 |     } | 
| 271 |   | 
| 272 |     /** The outermost class which indirectly owns this symbol. | 
| 273 |      */ | 
| 274 |     public ClassSymbol outermostClass() { | 
| 275 |         Symbol sym = this; | 
| 276 |         Symbol prev = null; | 
| 277 |         while (sym.kind != PCK) { | 
| 278 |             prev = sym; | 
| 279 |             sym = sym.owner; | 
| 280 |         } | 
| 281 |         return (ClassSymbol) prev; | 
| 282 |     } | 
| 283 |   | 
| 284 |     /** The package which indirectly owns this symbol. | 
| 285 |      */ | 
| 286 |     public PackageSymbol packge() { | 
| 287 |         Symbol sym = this; | 
| 288 |         while (sym.kind != PCK) { | 
| 289 |             sym = sym.owner; | 
| 290 |         } | 
| 291 |         return (PackageSymbol) sym; | 
| 292 |     } | 
| 293 |   | 
| 294 |     /** Is this symbol a subclass of `base'? Only defined for ClassSymbols. | 
| 295 |      */ | 
| 296 |     public boolean isSubClass(Symbol base, Types types) { | 
| 297 |         throw new AssertionError("isSubClass " + this); | 
| 298 |     } | 
| 299 |   | 
| 300 |     /** Fully check membership: hierarchy, protection, and hiding. | 
| 301 |      *  Does not exclude methods not inherited due to overriding. | 
| 302 |      */ | 
| 303 |     public boolean isMemberOf(TypeSymbol clazz, Types types) { | 
| 304 |         return | 
| 305 |             owner == clazz || | 
| 306 |             clazz.isSubClass(owner, types) && | 
| 307 |             isInheritedIn(clazz, types) && | 
| 308 |             !hiddenIn((ClassSymbol)clazz, types); | 
| 309 |     } | 
| 310 |   | 
| 311 |     /** Is this symbol the same as or enclosed by the given class? */ | 
| 312 |     public boolean isEnclosedBy(ClassSymbol clazz) { | 
| 313 |         for (Symbol sym = this; sym.kind != PCK; sym = sym.owner) | 
| 314 |             if (sym == clazz) return true; | 
| 315 |         return false; | 
| 316 |     } | 
| 317 |   | 
| 318 |     /** Check for hiding.  Note that this doesn't handle multiple | 
| 319 |      *  (interface) inheritance. */ | 
| 320 |     private boolean hiddenIn(ClassSymbol clazz, Types types) { | 
| 321 |         if (kind == MTH && (flags() & STATIC) == 0) return false; | 
| 322 |         while (true) { | 
| 323 |             if (owner == clazz) return false; | 
| 324 |             Scope.Entry e = clazz.members().lookup(name); | 
| 325 |             while (e.scope != null) { | 
| 326 |                 if (e.sym == this) return false; | 
| 327 |                 if (e.sym.kind == kind && | 
| 328 |                     (kind != MTH || | 
| 329 |                      (e.sym.flags() & STATIC) != 0 && | 
| 330 |                      types.isSubSignature(e.sym.type, type))) | 
| 331 |                     return true; | 
| 332 |                 e = e.next(); | 
| 333 |             } | 
| 334 |             Type superType = types.supertype(clazz.type); | 
| 335 |             if (superType.tag != TypeTags.CLASS) return false; | 
| 336 |             clazz = (ClassSymbol)superType.tsym; | 
| 337 |         } | 
| 338 |     } | 
| 339 |   | 
| 340 |     /** Is this symbol inherited into a given class? | 
| 341 |      *  PRE: If symbol's owner is a interface, | 
| 342 |      *       it is already assumed that the interface is a superinterface | 
| 343 |      *       of given class. | 
| 344 |      *  @param clazz  The class for which we want to establish membership. | 
| 345 |      *                This must be a subclass of the member's owner. | 
| 346 |      */ | 
| 347 |     public boolean isInheritedIn(Symbol clazz, Types types) { | 
| 348 |         switch ((int)(flags_field & Flags.AccessFlags)) { | 
| 349 |         default: // error recovery | 
| 350 |         case PUBLIC: | 
| 351 |             return true; | 
| 352 |         case PRIVATE: | 
| 353 |             return this.owner == clazz; | 
| 354 |         case PROTECTED: | 
| 355 |             // we model interfaces as extending Object | 
| 356 |             return (clazz.flags() & INTERFACE) == 0; | 
| 357 |         case 0: | 
| 358 |             PackageSymbol thisPackage = this.packge(); | 
| 359 |             for (Symbol sup = clazz; | 
| 360 |                  sup != null && sup != this.owner; | 
| 361 |                  sup = types.supertype(sup.type).tsym) { | 
| 362 |                 if (sup.type.isErroneous()) | 
| 363 |                     return true; // error recovery | 
| 364 |                 if ((sup.flags() & COMPOUND) != 0) | 
| 365 |                     continue; | 
| 366 |                 if (sup.packge() != thisPackage) | 
| 367 |                     return false; | 
| 368 |             } | 
| 369 |             return (clazz.flags() & INTERFACE) == 0; | 
| 370 |         } | 
| 371 |     } | 
| 372 |   | 
| 373 |     /** The (variable or method) symbol seen as a member of given | 
| 374 |      *  class type`site' (this might change the symbol's type). | 
| 375 |      *  This is used exclusively for producing diagnostics. | 
| 376 |      */ | 
| 377 |     public Symbol asMemberOf(Type site, Types types) { | 
| 378 |         throw new AssertionError(); | 
| 379 |     } | 
| 380 |   | 
| 381 |     /** Does this method symbol override `other' symbol, when both are seen as | 
| 382 |      *  members of class `origin'?  It is assumed that _other is a member | 
| 383 |      *  of origin. | 
| 384 |      * | 
| 385 |      *  It is assumed that both symbols have the same name.  The static | 
| 386 |      *  modifier is ignored for this test. | 
| 387 |      * | 
| 388 |      *  See JLS 8.4.6.1 (without transitivity) and 8.4.6.4 | 
| 389 |      */ | 
| 390 |     public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean checkResult) { | 
| 391 |         return false; | 
| 392 |     } | 
| 393 |   | 
| 394 |     /** Complete the elaboration of this symbol's definition. | 
| 395 |      */ | 
| 396 |     public void complete() throws CompletionFailure { | 
| 397 |         if (completer != null) { | 
| 398 |             Completer c = completer; | 
| 399 |             completer = null; | 
| 400 |             c.complete(this); | 
| 401 |         } | 
| 402 |     } | 
| 403 |   | 
| 404 |     /** True if the symbol represents an entity that exists. | 
| 405 |      */ | 
| 406 |     public boolean exists() { | 
| 407 |         return true; | 
| 408 |     } | 
| 409 |   | 
| 410 |     public Type asType() { | 
| 411 |         return type; | 
| 412 |     } | 
| 413 |   | 
| 414 |     public Symbol getEnclosingElement() { | 
| 415 |         return owner; | 
| 416 |     } | 
| 417 |   | 
| 418 |     public ElementKind getKind() { | 
| 419 |         return ElementKind.OTHER;       // most unkind | 
| 420 |     } | 
| 421 |   | 
| 422 |     public Set<Modifier> getModifiers() { | 
| 423 |         return Flags.asModifierSet(flags()); | 
| 424 |     } | 
| 425 |   | 
| 426 |     public Name getSimpleName() { | 
| 427 |         return name; | 
| 428 |     } | 
| 429 |   | 
| 430 |     /** | 
| 431 |      * @deprecated this method should never be used by javac internally. | 
| 432 |      */ | 
| 433 |     @Deprecated | 
| 434 |     public <A extends java.lang.annotation.Annotation> A getAnnotation(Class<A> annoType) { | 
| 435 |         return JavacElements.getAnnotation(this, annoType); | 
| 436 |     } | 
| 437 |   | 
| 438 |     // TODO: getEnclosedElements should return a javac List, fix in FilteredMemberList | 
| 439 |     public java.util.List<Symbol> getEnclosedElements() { | 
| 440 |         return List.nil(); | 
| 441 |     } | 
| 442 |   | 
| 443 |     public List<TypeSymbol> getTypeParameters() { | 
| 444 |         ListBuffer<TypeSymbol> l = ListBuffer.lb(); | 
| 445 |         for (Type t : type.getTypeArguments()) { | 
| 446 |             l.append(t.tsym); | 
| 447 |         } | 
| 448 |         return l.toList(); | 
| 449 |     } | 
| 450 |   | 
| 451 |     public static class DelegatedSymbol extends Symbol { | 
| 452 |         protected Symbol other; | 
| 453 |         public DelegatedSymbol(Symbol other) { | 
| 454 |             super(other.kind, other.flags_field, other.name, other.type, other.owner); | 
| 455 |             this.other = other; | 
| 456 |         } | 
| 457 |         public String toString() { return other.toString(); } | 
| 458 |         public String location() { return other.location(); } | 
| 459 |         public String location(Type site, Types types) { return other.location(site, types); } | 
| 460 |         public Type erasure(Types types) { return other.erasure(types); } | 
| 461 |         public Type externalType(Types types) { return other.externalType(types); } | 
| 462 |         public boolean isLocal() { return other.isLocal(); } | 
| 463 |         public boolean isConstructor() { return other.isConstructor(); } | 
| 464 |         public Name getQualifiedName() { return other.getQualifiedName(); } | 
| 465 |         public Name flatName() { return other.flatName(); } | 
| 466 |         public Scope members() { return other.members(); } | 
| 467 |         public boolean isInner() { return other.isInner(); } | 
| 468 |         public boolean hasOuterInstance() { return other.hasOuterInstance(); } | 
| 469 |         public ClassSymbol enclClass() { return other.enclClass(); } | 
| 470 |         public ClassSymbol outermostClass() { return other.outermostClass(); } | 
| 471 |         public PackageSymbol packge() { return other.packge(); } | 
| 472 |         public boolean isSubClass(Symbol base, Types types) { return other.isSubClass(base, types); } | 
| 473 |         public boolean isMemberOf(TypeSymbol clazz, Types types) { return other.isMemberOf(clazz, types); } | 
| 474 |         public boolean isEnclosedBy(ClassSymbol clazz) { return other.isEnclosedBy(clazz); } | 
| 475 |         public boolean isInheritedIn(Symbol clazz, Types types) { return other.isInheritedIn(clazz, types); } | 
| 476 |         public Symbol asMemberOf(Type site, Types types) { return other.asMemberOf(site, types); } | 
| 477 |         public void complete() throws CompletionFailure { other.complete(); } | 
| 478 |   | 
| 479 |         public <R, P> R accept(ElementVisitor<R, P> v, P p) { | 
| 480 |             return other.accept(v, p); | 
| 481 |         } | 
| 482 |     } | 
| 483 |   | 
| 484 |     /** A class for type symbols. Type variables are represented by instances | 
| 485 |      *  of this class, classes and packages by instances of subclasses. | 
| 486 |      */ | 
| 487 |     public static class TypeSymbol | 
| 488 |             extends Symbol implements TypeParameterElement { | 
| 489 |         // Implements TypeParameterElement because type parameters don't | 
| 490 |         // have their own TypeSymbol subclass. | 
| 491 |         // TODO: type parameters should have their own TypeSymbol subclass | 
| 492 |   | 
| 493 |         public TypeSymbol(long flags, Name name, Type type, Symbol owner) { | 
| 494 |             super(TYP, flags, name, type, owner); | 
| 495 |         } | 
| 496 |   | 
| 497 |         /** form a fully qualified name from a name and an owner | 
| 498 |          */ | 
| 499 |         static public Name formFullName(Name name, Symbol owner) { | 
| 500 |             if (owner == null) return name; | 
| 501 |             if (((owner.kind != ERR)) && | 
| 502 |                 ((owner.kind & (VAR | MTH)) != 0 | 
| 503 |                  || (owner.kind == TYP && owner.type.tag == TYPEVAR) | 
| 504 |                  )) return name; | 
| 505 |             Name prefix = owner.getQualifiedName(); | 
| 506 |             if (prefix == null || prefix == prefix.table.empty) | 
| 507 |                 return name; | 
| 508 |             else return prefix.append('.', name); | 
| 509 |         } | 
| 510 |   | 
| 511 |         /** form a fully qualified name from a name and an owner, after | 
| 512 |          *  converting to flat representation | 
| 513 |          */ | 
| 514 |         static public Name formFlatName(Name name, Symbol owner) { | 
| 515 |             if (owner == null || | 
| 516 |                 (owner.kind & (VAR | MTH)) != 0 | 
| 517 |                 || (owner.kind == TYP && owner.type.tag == TYPEVAR) | 
| 518 |                 ) return name; | 
| 519 |             char sep = owner.kind == TYP ? '$' : '.'; | 
| 520 |             Name prefix = owner.flatName(); | 
| 521 |             if (prefix == null || prefix == prefix.table.empty) | 
| 522 |                 return name; | 
| 523 |             else return prefix.append(sep, name); | 
| 524 |         } | 
| 525 |   | 
| 526 |         /** | 
| 527 |          * A total ordering between type symbols that refines the | 
| 528 |          * class inheritance graph. | 
| 529 |          * | 
| 530 |          * Typevariables always precede other kinds of symbols. | 
| 531 |          */ | 
| 532 |         public final boolean precedes(TypeSymbol that, Types types) { | 
| 533 |             if (this == that) | 
| 534 |                 return false; | 
| 535 |             if (this.type.tag == that.type.tag) { | 
| 536 |                 if (this.type.tag == CLASS) { | 
| 537 |                     return | 
| 538 |                         types.rank(that.type) < types.rank(this.type) || | 
| 539 |                         types.rank(that.type) == types.rank(this.type) && | 
| 540 |                         that.getQualifiedName().compareTo(this.getQualifiedName()) < 0; | 
| 541 |                 } else if (this.type.tag == TYPEVAR) { | 
| 542 |                     return types.isSubtype(this.type, that.type); | 
| 543 |                 } | 
| 544 |             } | 
| 545 |             return this.type.tag == TYPEVAR; | 
| 546 |         } | 
| 547 |   | 
| 548 |         // For type params; overridden in subclasses. | 
| 549 |         public ElementKind getKind() { | 
| 550 |             return ElementKind.TYPE_PARAMETER; | 
| 551 |         } | 
| 552 |   | 
| 553 |         public java.util.List<Symbol> getEnclosedElements() { | 
| 554 |             List<Symbol> list = List.nil(); | 
| 555 |             for (Scope.Entry e = members().elems; e != null; e = e.sibling) { | 
| 556 |                 if (e.sym != null && (e.sym.flags() & SYNTHETIC) == 0 && e.sym.owner == this) | 
| 557 |                     list = list.prepend(e.sym); | 
| 558 |             } | 
| 559 |             return list; | 
| 560 |         } | 
| 561 |   | 
| 562 |         // For type params. | 
| 563 |         // Perhaps not needed if getEnclosingElement can be spec'ed | 
| 564 |         // to do the same thing. | 
| 565 |         // TODO: getGenericElement() might not be needed | 
| 566 |         public Symbol getGenericElement() { | 
| 567 |             return owner; | 
| 568 |         } | 
| 569 |   | 
| 570 |         public <R, P> R accept(ElementVisitor<R, P> v, P p) { | 
| 571 |             assert type.tag == TYPEVAR; // else override will be invoked | 
| 572 |             return v.visitTypeParameter(this, p); | 
| 573 |         } | 
| 574 |   | 
| 575 |         public List<Type> getBounds() { | 
| 576 |             TypeVar t = (TypeVar)type; | 
| 577 |             Type bound = t.getUpperBound(); | 
| 578 |             if (!bound.isCompound()) | 
| 579 |                 return List.of(bound); | 
| 580 |             ClassType ct = (ClassType)bound; | 
| 581 |             if (!ct.tsym.erasure_field.isInterface()) { | 
| 582 |                 return ct.interfaces_field.prepend(ct.supertype_field); | 
| 583 |             } else { | 
| 584 |                 // No superclass was given in bounds. | 
| 585 |                 // In this case, supertype is Object, erasure is first interface. | 
| 586 |                 return ct.interfaces_field; | 
| 587 |             } | 
| 588 |         } | 
| 589 |     } | 
| 590 |   | 
| 591 |     /** A class for package symbols | 
| 592 |      */ | 
| 593 |     public static class PackageSymbol extends TypeSymbol | 
| 594 |         implements PackageElement { | 
| 595 |   | 
| 596 |         public Scope members_field; | 
| 597 |         public Name fullname; | 
| 598 |         public ClassSymbol package_info; // see bug 6443073 | 
| 599 |   | 
| 600 |         public PackageSymbol(Name name, Type type, Symbol owner) { | 
| 601 |             super(0, name, type, owner); | 
| 602 |             this.kind = PCK; | 
| 603 |             this.members_field = null; | 
| 604 |             this.fullname = formFullName(name, owner); | 
| 605 |         } | 
| 606 |   | 
| 607 |         public PackageSymbol(Name name, Symbol owner) { | 
| 608 |             this(name, null, owner); | 
| 609 |             this.type = new PackageType(this); | 
| 610 |         } | 
| 611 |   | 
| 612 |         public String toString() { | 
| 613 |             return fullname.toString(); | 
| 614 |         } | 
| 615 |   | 
| 616 |         public Name getQualifiedName() { | 
| 617 |             return fullname; | 
| 618 |         } | 
| 619 |   | 
| 620 |         public boolean isUnnamed() { | 
| 621 |             return name.isEmpty() && owner != null; | 
| 622 |         } | 
| 623 |   | 
| 624 |         public Scope members() { | 
| 625 |             if (completer != null) complete(); | 
| 626 |             return members_field; | 
| 627 |         } | 
| 628 |   | 
| 629 |         public long flags() { | 
| 630 |             if (completer != null) complete(); | 
| 631 |             return flags_field; | 
| 632 |         } | 
| 633 |   | 
| 634 |         public List<Attribute.Compound> getAnnotationMirrors() { | 
| 635 |             if (completer != null) complete(); | 
| 636 |             assert attributes_field != null; | 
| 637 |             return attributes_field; | 
| 638 |         } | 
| 639 |   | 
| 640 |         /** A package "exists" if a type or package that exists has | 
| 641 |          *  been seen within it. | 
| 642 |          */ | 
| 643 |         public boolean exists() { | 
| 644 |             return (flags_field & EXISTS) != 0; | 
| 645 |         } | 
| 646 |   | 
| 647 |         public ElementKind getKind() { | 
| 648 |             return ElementKind.PACKAGE; | 
| 649 |         } | 
| 650 |   | 
| 651 |         public Symbol getEnclosingElement() { | 
| 652 |             return null; | 
| 653 |         } | 
| 654 |   | 
| 655 |         public <R, P> R accept(ElementVisitor<R, P> v, P p) { | 
| 656 |             return v.visitPackage(this, p); | 
| 657 |         } | 
| 658 |     } | 
| 659 |   | 
| 660 |     /** A class for class symbols | 
| 661 |      */ | 
| 662 |     public static class ClassSymbol extends TypeSymbol implements TypeElement { | 
| 663 |   | 
| 664 |         /** a scope for all class members; variables, methods and inner classes | 
| 665 |          *  type parameters are not part of this scope | 
| 666 |          */ | 
| 667 |         public Scope members_field; | 
| 668 |   | 
| 669 |         /** the fully qualified name of the class, i.e. pck.outer.inner. | 
| 670 |          *  null for anonymous classes | 
| 671 |          */ | 
| 672 |         public Name fullname; | 
| 673 |   | 
| 674 |         /** the fully qualified name of the class after converting to flat | 
| 675 |          *  representation, i.e. pck.outer$inner, | 
| 676 |          *  set externally for local and anonymous classes | 
| 677 |          */ | 
| 678 |         public Name flatname; | 
| 679 |   | 
| 680 |         /** the sourcefile where the class came from | 
| 681 |          */ | 
| 682 |         public JavaFileObject sourcefile; | 
| 683 |   | 
| 684 |         /** the classfile from where to load this class | 
| 685 |          *  this will have extension .class or .java | 
| 686 |          */ | 
| 687 |         public JavaFileObject classfile; | 
| 688 |   | 
| 689 |         /** the constant pool of the class | 
| 690 |          */ | 
| 691 |         public Pool pool; | 
| 692 |   | 
| 693 |         public ClassSymbol(long flags, Name name, Type type, Symbol owner) { | 
| 694 |             super(flags, name, type, owner); | 
| 695 |             this.members_field = null; | 
| 696 |             this.fullname = formFullName(name, owner); | 
| 697 |             this.flatname = formFlatName(name, owner); | 
| 698 |             this.sourcefile = null; | 
| 699 |             this.classfile = null; | 
| 700 |             this.pool = null; | 
| 701 |         } | 
| 702 |   | 
| 703 |         public ClassSymbol(long flags, Name name, Symbol owner) { | 
| 704 |             this( | 
| 705 |                 flags, | 
| 706 |                 name, | 
| 707 |                 new ClassType(Type.noType, null, null), | 
| 708 |                 owner); | 
| 709 |             this.type.tsym = this; | 
| 710 |         } | 
| 711 |   | 
| 712 |         /** The Java source which this symbol represents. | 
| 713 |          */ | 
| 714 |         public String toString() { | 
| 715 |             return className(); | 
| 716 |         } | 
| 717 |   | 
| 718 |         public long flags() { | 
| 719 |             if (completer != null) complete(); | 
| 720 |             return flags_field; | 
| 721 |         } | 
| 722 |   | 
| 723 |         public Scope members() { | 
| 724 |             if (completer != null) complete(); | 
| 725 |             return members_field; | 
| 726 |         } | 
| 727 |   | 
| 728 |         public List<Attribute.Compound> getAnnotationMirrors() { | 
| 729 |             if (completer != null) complete(); | 
| 730 |             assert attributes_field != null; | 
| 731 |             return attributes_field; | 
| 732 |         } | 
| 733 |   | 
| 734 |         public Type erasure(Types types) { | 
| 735 |             if (erasure_field == null) | 
| 736 |                 erasure_field = new ClassType(types.erasure(type.getEnclosingType()), | 
| 737 |                                               List.<Type>nil(), this); | 
| 738 |             return erasure_field; | 
| 739 |         } | 
| 740 |   | 
| 741 |         public String className() { | 
| 742 |             if (name.len == 0) | 
| 743 |                 return | 
| 744 |                     Log.getLocalizedString("anonymous.class", flatname); | 
| 745 |             else | 
| 746 |                 return fullname.toString(); | 
| 747 |         } | 
| 748 |   | 
| 749 |         public Name getQualifiedName() { | 
| 750 |             return fullname; | 
| 751 |         } | 
| 752 |   | 
| 753 |         public Name flatName() { | 
| 754 |             return flatname; | 
| 755 |         } | 
| 756 |   | 
| 757 |         public boolean isSubClass(Symbol base, Types types) { | 
| 758 |             if (this == base) { | 
| 759 |                 return true; | 
| 760 |             } else if ((base.flags() & INTERFACE) != 0) { | 
| 761 |                 for (Type t = type; t.tag == CLASS; t = types.supertype(t)) | 
| 762 |                     for (List<Type> is = types.interfaces(t); | 
| 763 |                          is.nonEmpty(); | 
| 764 |                          is = is.tail) | 
| 765 |                         if (is.head.tsym.isSubClass(base, types)) return true; | 
| 766 |             } else { | 
| 767 |                 for (Type t = type; t.tag == CLASS; t = types.supertype(t)) | 
| 768 |                     if (t.tsym == base) return true; | 
| 769 |             } | 
| 770 |             return false; | 
| 771 |         } | 
| 772 |   | 
| 773 |         /** Complete the elaboration of this symbol's definition. | 
| 774 |          */ | 
| 775 |         public void complete() throws CompletionFailure { | 
| 776 |             try { | 
| 777 |                 super.complete(); | 
| 778 |             } catch (CompletionFailure ex) { | 
| 779 |                 // quiet error recovery | 
| 780 |                 flags_field |= (PUBLIC|STATIC); | 
| 781 |                 this.type = new ErrorType(this); | 
| 782 |                 throw ex; | 
| 783 |             } | 
| 784 |         } | 
| 785 |   | 
| 786 |         public List<Type> getInterfaces() { | 
| 787 |             complete(); | 
| 788 |             if (type instanceof ClassType) { | 
| 789 |                 ClassType t = (ClassType)type; | 
| 790 |                 if (t.interfaces_field == null) // FIXME: shouldn't be null | 
| 791 |                     t.interfaces_field = List.nil(); | 
| 792 |                 return t.interfaces_field; | 
| 793 |             } else { | 
| 794 |                 return List.nil(); | 
| 795 |             } | 
| 796 |         } | 
| 797 |   | 
| 798 |         public Type getSuperclass() { | 
| 799 |             complete(); | 
| 800 |             if (type instanceof ClassType) { | 
| 801 |                 ClassType t = (ClassType)type; | 
| 802 |                 if (t.supertype_field == null) // FIXME: shouldn't be null | 
| 803 |                     t.supertype_field = Type.noType; | 
| 804 |                 // An interface has no superclass; its supertype is Object. | 
| 805 |                 return t.isInterface() | 
| 806 |                     ? Type.noType | 
| 807 |                     : t.supertype_field; | 
| 808 |             } else { | 
| 809 |                 return Type.noType; | 
| 810 |             } | 
| 811 |         } | 
| 812 |   | 
| 813 |         public ElementKind getKind() { | 
| 814 |             long flags = flags(); | 
| 815 |             if ((flags & ANNOTATION) != 0) | 
| 816 |                 return ElementKind.ANNOTATION_TYPE; | 
| 817 |             else if ((flags & INTERFACE) != 0) | 
| 818 |                 return ElementKind.INTERFACE; | 
| 819 |             else if ((flags & ENUM) != 0) | 
| 820 |                 return ElementKind.ENUM; | 
| 821 |             else | 
| 822 |                 return ElementKind.CLASS; | 
| 823 |         } | 
| 824 |   | 
| 825 |         public NestingKind getNestingKind() { | 
| 826 |             complete(); | 
| 827 |             if (owner.kind == PCK) | 
| 828 |                 return NestingKind.TOP_LEVEL; | 
| 829 |             else if (name.isEmpty()) | 
| 830 |                 return NestingKind.ANONYMOUS; | 
| 831 |             else if (owner.kind == MTH) | 
| 832 |                 return NestingKind.LOCAL; | 
| 833 |             else | 
| 834 |                 return NestingKind.MEMBER; | 
| 835 |         } | 
| 836 |   | 
| 837 |         /** | 
| 838 |          * @deprecated this method should never be used by javac internally. | 
| 839 |          */ | 
| 840 |         @Override @Deprecated | 
| 841 |         public <A extends java.lang.annotation.Annotation> A getAnnotation(Class<A> annoType) { | 
| 842 |             return JavacElements.getAnnotation(this, annoType); | 
| 843 |         } | 
| 844 |   | 
| 845 |         public <R, P> R accept(ElementVisitor<R, P> v, P p) { | 
| 846 |             return v.visitType(this, p); | 
| 847 |         } | 
| 848 |     } | 
| 849 |   | 
| 850 |   | 
| 851 |     /** A class for variable symbols | 
| 852 |      */ | 
| 853 |     public static class VarSymbol extends Symbol implements VariableElement { | 
| 854 |   | 
| 855 |         /** The variable's declaration position. | 
| 856 |          */ | 
| 857 |         public int pos = Position.NOPOS; | 
| 858 |   | 
| 859 |         /** The variable's address. Used for different purposes during | 
| 860 |          *  flow analysis, translation and code generation. | 
| 861 |          *  Flow analysis: | 
| 862 |          *    If this is a blank final or local variable, its sequence number. | 
| 863 |          *  Translation: | 
| 864 |          *    If this is a private field, its access number. | 
| 865 |          *  Code generation: | 
| 866 |          *    If this is a local variable, its logical slot number. | 
| 867 |          */ | 
| 868 |         public int adr = -1; | 
| 869 |   | 
| 870 |         /** Construct a variable symbol, given its flags, name, type and owner. | 
| 871 |          */ | 
| 872 |         public VarSymbol(long flags, Name name, Type type, Symbol owner) { | 
| 873 |             super(VAR, flags, name, type, owner); | 
| 874 |         } | 
| 875 |   | 
| 876 |         /** Clone this symbol with new owner. | 
| 877 |          */ | 
| 878 |         public VarSymbol clone(Symbol newOwner) { | 
| 879 |             VarSymbol v = new VarSymbol(flags_field, name, type, newOwner); | 
| 880 |             v.pos = pos; | 
| 881 |             v.adr = adr; | 
| 882 |             v.data = data; | 
| 883 | //          System.out.println("clone " + v + " in " + newOwner);//DEBUG | 
| 884 |             return v; | 
| 885 |         } | 
| 886 |   | 
| 887 |         public String toString() { | 
| 888 |             return name.toString(); | 
| 889 |         } | 
| 890 |   | 
| 891 |         public Symbol asMemberOf(Type site, Types types) { | 
| 892 |             return new VarSymbol(flags_field, name, types.memberType(site, this), owner); | 
| 893 |         } | 
| 894 |   | 
| 895 |         public ElementKind getKind() { | 
| 896 |             long flags = flags(); | 
| 897 |             if ((flags & PARAMETER) != 0) { | 
| 898 |                 if (isExceptionParameter()) | 
| 899 |                     return ElementKind.EXCEPTION_PARAMETER; | 
| 900 |                 else | 
| 901 |                     return ElementKind.PARAMETER; | 
| 902 |             } else if ((flags & ENUM) != 0) { | 
| 903 |                 return ElementKind.ENUM_CONSTANT; | 
| 904 |             } else if (owner.kind == TYP || owner.kind == ERR) { | 
| 905 |                 return ElementKind.FIELD; | 
| 906 |             } else { | 
| 907 |                 return ElementKind.LOCAL_VARIABLE; | 
| 908 |             } | 
| 909 |         } | 
| 910 |   | 
| 911 |         public <R, P> R accept(ElementVisitor<R, P> v, P p) { | 
| 912 |             return v.visitVariable(this, p); | 
| 913 |         } | 
| 914 |   | 
| 915 |         public Object getConstantValue() { // Mirror API | 
| 916 |             return Constants.decode(getConstValue(), type); | 
| 917 |         } | 
| 918 |   | 
| 919 |         public void setLazyConstValue(final Env<AttrContext> env, | 
| 920 |                                       final Log log, | 
| 921 |                                       final Attr attr, | 
| 922 |                                       final JCTree.JCExpression initializer) | 
| 923 |         { | 
| 924 |             setData(new Callable<Object>() { | 
| 925 |                 public Object call() { | 
| 926 |                     JavaFileObject source = log.useSource(env.toplevel.sourcefile); | 
| 927 |                     try { | 
| 928 |                         // In order to catch self-references, we set | 
| 929 |                         // the variable's declaration position to | 
| 930 |                         // maximal possible value, effectively marking | 
| 931 |                         // the variable as undefined. | 
| 932 |                         int pos = VarSymbol.this.pos; | 
| 933 |                         VarSymbol.this.pos = Position.MAXPOS; | 
| 934 |                         Type itype = attr.attribExpr(initializer, env, type); | 
| 935 |                         VarSymbol.this.pos = pos; | 
| 936 |                         if (itype.constValue() != null) | 
| 937 |                             return attr.coerce(itype, type).constValue(); | 
| 938 |                         else | 
| 939 |                             return null; | 
| 940 |                     } finally { | 
| 941 |                         log.useSource(source); | 
| 942 |                     } | 
| 943 |                 } | 
| 944 |             }); | 
| 945 |         } | 
| 946 |   | 
| 947 |         /** | 
| 948 |          * The variable's constant value, if this is a constant. | 
| 949 |          * Before the constant value is evaluated, it points to an | 
| 950 |          * initalizer environment.  If this is not a constant, it can | 
| 951 |          * be used for other stuff. | 
| 952 |          */ | 
| 953 |         private Object data; | 
| 954 |   | 
| 955 |         public boolean isExceptionParameter() { | 
| 956 |             return data == ElementKind.EXCEPTION_PARAMETER; | 
| 957 |         } | 
| 958 |   | 
| 959 |         public Object getConstValue() { | 
| 960 |             // TODO: Consider if getConstValue and getConstantValue can be collapsed | 
| 961 |             if (data == ElementKind.EXCEPTION_PARAMETER) { | 
| 962 |                 return null; | 
| 963 |             } else if (data instanceof Callable<?>) { | 
| 964 |                 // In this case, this is final a variable, with an as | 
| 965 |                 // yet unevaluated initializer. | 
| 966 |                 Callable<?> eval = (Callable<?>)data; | 
| 967 |                 data = null; // to make sure we don't evaluate this twice. | 
| 968 |                 try { | 
| 969 |                     data = eval.call(); | 
| 970 |                 } catch (Exception ex) { | 
| 971 |                     throw new AssertionError(ex); | 
| 972 |                 } | 
| 973 |             } | 
| 974 |             return data; | 
| 975 |         } | 
| 976 |   | 
| 977 |         public void setData(Object data) { | 
| 978 |             assert !(data instanceof Env<?>) : this; | 
| 979 |             this.data = data; | 
| 980 |         } | 
| 981 |     } | 
| 982 |   | 
| 983 |     /** A class for method symbols. | 
| 984 |      */ | 
| 985 |     public static class MethodSymbol extends Symbol implements ExecutableElement { | 
| 986 |   | 
| 987 |         /** The code of the method. */ | 
| 988 |         public Code code = null; | 
| 989 |   | 
| 990 |         /** The parameters of the method. */ | 
| 991 |         public List<VarSymbol> params = null; | 
| 992 |   | 
| 993 |         /** The names of the parameters */ | 
| 994 |         public List<Name> savedParameterNames; | 
| 995 |   | 
| 996 |         /** For an attribute field accessor, its default value if any. | 
| 997 |          *  The value is null if none appeared in the method | 
| 998 |          *  declaration. | 
| 999 |          */ | 
| 1000 |         public Attribute defaultValue = null; | 
| 1001 |   | 
| 1002 |         /** Construct a method symbol, given its flags, name, type and owner. | 
| 1003 |          */ | 
| 1004 |         public MethodSymbol(long flags, Name name, Type type, Symbol owner) { | 
| 1005 |             super(MTH, flags, name, type, owner); | 
| 1006 |             assert owner.type.tag != TYPEVAR : owner + "." + name; | 
| 1007 |         } | 
| 1008 |   | 
| 1009 |         /** Clone this symbol with new owner. | 
| 1010 |          */ | 
| 1011 |         public MethodSymbol clone(Symbol newOwner) { | 
| 1012 |             MethodSymbol m = new MethodSymbol(flags_field, name, type, newOwner); | 
| 1013 |             m.code = code; | 
| 1014 |             return m; | 
| 1015 |         } | 
| 1016 |   | 
| 1017 |         /** The Java source which this symbol represents. | 
| 1018 |          */ | 
| 1019 |         public String toString() { | 
| 1020 |             if ((flags() & BLOCK) != 0) { | 
| 1021 |                 return owner.name.toString(); | 
| 1022 |             } else { | 
| 1023 |                 String s = (name == name.table.init) | 
| 1024 |                     ? owner.name.toString() | 
| 1025 |                     : name.toString(); | 
| 1026 |                 if (type != null) { | 
| 1027 |                     if (type.tag == FORALL) | 
| 1028 |                         s = "<" + ((ForAll)type).getTypeArguments() + ">" + s; | 
| 1029 |                     s += "(" + type.argtypes((flags() & VARARGS) != 0) + ")"; | 
| 1030 |                 } | 
| 1031 |                 return s; | 
| 1032 |             } | 
| 1033 |         } | 
| 1034 |   | 
| 1035 |         /** find a symbol that this (proxy method) symbol implements. | 
| 1036 |          *  @param    c       The class whose members are searched for | 
| 1037 |          *                    implementations | 
| 1038 |          */ | 
| 1039 |         public Symbol implemented(TypeSymbol c, Types types) { | 
| 1040 |             Symbol impl = null; | 
| 1041 |             for (List<Type> is = types.interfaces(c.type); | 
| 1042 |                  impl == null && is.nonEmpty(); | 
| 1043 |                  is = is.tail) { | 
| 1044 |                 TypeSymbol i = is.head.tsym; | 
| 1045 |                 for (Scope.Entry e = i.members().lookup(name); | 
| 1046 |                      impl == null && e.scope != null; | 
| 1047 |                      e = e.next()) { | 
| 1048 |                     if (this.overrides(e.sym, (TypeSymbol)owner, types, true) && | 
| 1049 |                         // FIXME: I suspect the following requires a | 
| 1050 |                         // subst() for a parametric return type. | 
| 1051 |                         types.isSameType(type.getReturnType(), | 
| 1052 |                                          types.memberType(owner.type, e.sym).getReturnType())) { | 
| 1053 |                         impl = e.sym; | 
| 1054 |                     } | 
| 1055 |                     if (impl == null) | 
| 1056 |                         impl = implemented(i, types); | 
| 1057 |                 } | 
| 1058 |             } | 
| 1059 |             return impl; | 
| 1060 |         } | 
| 1061 |   | 
| 1062 |         /** Will the erasure of this method be considered by the VM to | 
| 1063 |          *  override the erasure of the other when seen from class `origin'? | 
| 1064 |          */ | 
| 1065 |         public boolean binaryOverrides(Symbol _other, TypeSymbol origin, Types types) { | 
| 1066 |             if (isConstructor() || _other.kind != MTH) return false; | 
| 1067 |   | 
| 1068 |             if (this == _other) return true; | 
| 1069 |             MethodSymbol other = (MethodSymbol)_other; | 
| 1070 |   | 
| 1071 |             // check for a direct implementation | 
| 1072 |             if (other.isOverridableIn((TypeSymbol)owner) && | 
| 1073 |                 types.asSuper(owner.type, other.owner) != null && | 
| 1074 |                 types.isSameType(erasure(types), other.erasure(types))) | 
| 1075 |                 return true; | 
| 1076 |   | 
| 1077 |             // check for an inherited implementation | 
| 1078 |             return | 
| 1079 |                 (flags() & ABSTRACT) == 0 && | 
| 1080 |                 other.isOverridableIn(origin) && | 
| 1081 |                 this.isMemberOf(origin, types) && | 
| 1082 |                 types.isSameType(erasure(types), other.erasure(types)); | 
| 1083 |         } | 
| 1084 |   | 
| 1085 |         /** The implementation of this (abstract) symbol in class origin, | 
| 1086 |          *  from the VM's point of view, null if method does not have an | 
| 1087 |          *  implementation in class. | 
| 1088 |          *  @param origin   The class of which the implementation is a member. | 
| 1089 |          */ | 
| 1090 |         public MethodSymbol binaryImplementation(ClassSymbol origin, Types types) { | 
| 1091 |             for (TypeSymbol c = origin; c != null; c = types.supertype(c.type).tsym) { | 
| 1092 |                 for (Scope.Entry e = c.members().lookup(name); | 
| 1093 |                      e.scope != null; | 
| 1094 |                      e = e.next()) { | 
| 1095 |                     if (e.sym.kind == MTH && | 
| 1096 |                         ((MethodSymbol)e.sym).binaryOverrides(this, origin, types)) | 
| 1097 |                         return (MethodSymbol)e.sym; | 
| 1098 |                 } | 
| 1099 |             } | 
| 1100 |             return null; | 
| 1101 |         } | 
| 1102 |   | 
| 1103 |         /** Does this symbol override `other' symbol, when both are seen as | 
| 1104 |          *  members of class `origin'?  It is assumed that _other is a member | 
| 1105 |          *  of origin. | 
| 1106 |          * | 
| 1107 |          *  It is assumed that both symbols have the same name.  The static | 
| 1108 |          *  modifier is ignored for this test. | 
| 1109 |          * | 
| 1110 |          *  See JLS 8.4.6.1 (without transitivity) and 8.4.6.4 | 
| 1111 |          */ | 
| 1112 |         public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean checkResult) { | 
| 1113 |             if (isConstructor() || _other.kind != MTH) return false; | 
| 1114 |   | 
| 1115 |             if (this == _other) return true; | 
| 1116 |             MethodSymbol other = (MethodSymbol)_other; | 
| 1117 |   | 
| 1118 |             // check for a direct implementation | 
| 1119 |             if (other.isOverridableIn((TypeSymbol)owner) && | 
| 1120 |                 types.asSuper(owner.type, other.owner) != null) { | 
| 1121 |                 Type mt = types.memberType(owner.type, this); | 
| 1122 |                 Type ot = types.memberType(owner.type, other); | 
| 1123 |                 if (types.isSubSignature(mt, ot)) { | 
| 1124 |                     if (!checkResult) | 
| 1125 |                         return true; | 
| 1126 |                     if (types.returnTypeSubstitutable(mt, ot)) | 
| 1127 |                         return true; | 
| 1128 |                 } | 
| 1129 |             } | 
| 1130 |   | 
| 1131 |             // check for an inherited implementation | 
| 1132 |             if ((flags() & ABSTRACT) != 0 || | 
| 1133 |                 (other.flags() & ABSTRACT) == 0 || | 
| 1134 |                 !other.isOverridableIn(origin) || | 
| 1135 |                 !this.isMemberOf(origin, types)) | 
| 1136 |                 return false; | 
| 1137 |   | 
| 1138 |             // assert types.asSuper(origin.type, other.owner) != null; | 
| 1139 |             Type mt = types.memberType(origin.type, this); | 
| 1140 |             Type ot = types.memberType(origin.type, other); | 
| 1141 |             return | 
| 1142 |                 types.isSubSignature(mt, ot) && | 
| 1143 |                 (!checkResult || types.resultSubtype(mt, ot, Warner.noWarnings)); | 
| 1144 |         } | 
| 1145 |   | 
| 1146 |         private boolean isOverridableIn(TypeSymbol origin) { | 
| 1147 |             // JLS3 8.4.6.1 | 
| 1148 |             switch ((int)(flags_field & Flags.AccessFlags)) { | 
| 1149 |             case Flags.PRIVATE: | 
| 1150 |                 return false; | 
| 1151 |             case Flags.PUBLIC: | 
| 1152 |                 return true; | 
| 1153 |             case Flags.PROTECTED: | 
| 1154 |                 return (origin.flags() & INTERFACE) == 0; | 
| 1155 |             case 0: | 
| 1156 |                 // for package private: can only override in the same | 
| 1157 |                 // package | 
| 1158 |                 return | 
| 1159 |                     this.packge() == origin.packge() && | 
| 1160 |                     (origin.flags() & INTERFACE) == 0; | 
| 1161 |             default: | 
| 1162 |                 return false; | 
| 1163 |             } | 
| 1164 |         } | 
| 1165 |   | 
| 1166 |         /** The implementation of this (abstract) symbol in class origin; | 
| 1167 |          *  null if none exists. Synthetic methods are not considered | 
| 1168 |          *  as possible implementations. | 
| 1169 |          */ | 
| 1170 |         public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) { | 
| 1171 |             for (Type t = origin.type; t.tag == CLASS; t = types.supertype(t)) { | 
| 1172 |                 TypeSymbol c = t.tsym; | 
| 1173 |                 for (Scope.Entry e = c.members().lookup(name); | 
| 1174 |                      e.scope != null; | 
| 1175 |                      e = e.next()) { | 
| 1176 |                     if (e.sym.kind == MTH) { | 
| 1177 |                         MethodSymbol m = (MethodSymbol) e.sym; | 
| 1178 |                         if (m.overrides(this, origin, types, checkResult) && | 
| 1179 |                             (m.flags() & SYNTHETIC) == 0) | 
| 1180 |                             return m; | 
| 1181 |                     } | 
| 1182 |                 } | 
| 1183 |             } | 
| 1184 |             // if origin is derived from a raw type, we might have missed | 
| 1185 |             // an implementation because we do not know enough about instantiations. | 
| 1186 |             // in this case continue with the supertype as origin. | 
| 1187 |             if (types.isDerivedRaw(origin.type)) | 
| 1188 |                 return implementation(types.supertype(origin.type).tsym, types, checkResult); | 
| 1189 |             else | 
| 1190 |                 return null; | 
| 1191 |         } | 
| 1192 |   | 
| 1193 |         public List<VarSymbol> params() { | 
| 1194 |             owner.complete(); | 
| 1195 |             if (params == null) { | 
| 1196 |                 List<Name> names = savedParameterNames; | 
| 1197 |                 savedParameterNames = null; | 
| 1198 |                 if (names == null) { | 
| 1199 |                     names = List.nil(); | 
| 1200 |                     int i = 0; | 
| 1201 |                     for (Type t : type.getParameterTypes()) | 
| 1202 |                         names = names.prepend(name.table.fromString("arg" + i++)); | 
| 1203 |                     names = names.reverse(); | 
| 1204 |                 } | 
| 1205 |                 ListBuffer<VarSymbol> buf = new ListBuffer<VarSymbol>(); | 
| 1206 |                 for (Type t : type.getParameterTypes()) { | 
| 1207 |                     buf.append(new VarSymbol(PARAMETER, names.head, t, this)); | 
| 1208 |                     names = names.tail; | 
| 1209 |                 } | 
| 1210 |                 params = buf.toList(); | 
| 1211 |             } | 
| 1212 |             return params; | 
| 1213 |         } | 
| 1214 |   | 
| 1215 |         public Symbol asMemberOf(Type site, Types types) { | 
| 1216 |             return new MethodSymbol(flags_field, name, types.memberType(site, this), owner); | 
| 1217 |         } | 
| 1218 |   | 
| 1219 |         public ElementKind getKind() { | 
| 1220 |             if (name == name.table.init) | 
| 1221 |                 return ElementKind.CONSTRUCTOR; | 
| 1222 |             else if (name == name.table.clinit) | 
| 1223 |                 return ElementKind.STATIC_INIT; | 
| 1224 |             else | 
| 1225 |                 return ElementKind.METHOD; | 
| 1226 |         } | 
| 1227 |   | 
| 1228 |         public Attribute getDefaultValue() { | 
| 1229 |             return defaultValue; | 
| 1230 |         } | 
| 1231 |   | 
| 1232 |         public List<VarSymbol> getParameters() { | 
| 1233 |             return params(); | 
| 1234 |         } | 
| 1235 |   | 
| 1236 |         public boolean isVarArgs() { | 
| 1237 |             return (flags() & VARARGS) != 0; | 
| 1238 |         } | 
| 1239 |   | 
| 1240 |         public <R, P> R accept(ElementVisitor<R, P> v, P p) { | 
| 1241 |             return v.visitExecutable(this, p); | 
| 1242 |         } | 
| 1243 |   | 
| 1244 |         public Type getReturnType() { | 
| 1245 |             return asType().getReturnType(); | 
| 1246 |         } | 
| 1247 |   | 
| 1248 |         public List<Type> getThrownTypes() { | 
| 1249 |             return asType().getThrownTypes(); | 
| 1250 |         } | 
| 1251 |     } | 
| 1252 |   | 
| 1253 |     /** A class for predefined operators. | 
| 1254 |      */ | 
| 1255 |     public static class OperatorSymbol extends MethodSymbol { | 
| 1256 |   | 
| 1257 |         public int opcode; | 
| 1258 |   | 
| 1259 |         public OperatorSymbol(Name name, Type type, int opcode, Symbol owner) { | 
| 1260 |             super(PUBLIC | STATIC, name, type, owner); | 
| 1261 |             this.opcode = opcode; | 
| 1262 |         } | 
| 1263 |     } | 
| 1264 |   | 
| 1265 |     /** Symbol completer interface. | 
| 1266 |      */ | 
| 1267 |     public static interface Completer { | 
| 1268 |         void complete(Symbol sym) throws CompletionFailure; | 
| 1269 |     } | 
| 1270 |   | 
| 1271 |     public static class CompletionFailure extends RuntimeException { | 
| 1272 |         private static final long serialVersionUID = 0; | 
| 1273 |         public Symbol sym; | 
| 1274 |   | 
| 1275 |         /** A localized string describing the failure. | 
| 1276 |          */ | 
| 1277 |         public String errmsg; | 
| 1278 |   | 
| 1279 |         public CompletionFailure(Symbol sym, String errmsg) { | 
| 1280 |             this.sym = sym; | 
| 1281 |             this.errmsg = errmsg; | 
| 1282 | //          this.printStackTrace();//DEBUG | 
| 1283 |         } | 
| 1284 |   | 
| 1285 |         public String getMessage() { | 
| 1286 |             return errmsg; | 
| 1287 |         } | 
| 1288 |   | 
| 1289 |         @Override | 
| 1290 |         public CompletionFailure initCause(Throwable cause) { | 
| 1291 |             super.initCause(cause); | 
| 1292 |             return this; | 
| 1293 |         } | 
| 1294 |   | 
| 1295 |     } | 
| 1296 | } |