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