Symbol.java revision 2646:ff1998c1ecab
115645Sjoerg/*
215645Sjoerg * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
31592Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41592Srgrimes *
51592Srgrimes * This code is free software; you can redistribute it and/or modify it
61592Srgrimes * under the terms of the GNU General Public License version 2 only, as
71592Srgrimes * published by the Free Software Foundation.  Oracle designates this
81592Srgrimes * particular file as subject to the "Classpath" exception as provided
91592Srgrimes * by Oracle in the LICENSE file that accompanied this code.
101592Srgrimes *
111592Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
12262435Sbrueffer * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
131592Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141592Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
151592Srgrimes * accompanied this code).
161592Srgrimes *
171592Srgrimes * You should have received a copy of the GNU General Public License version
181592Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
191592Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
201592Srgrimes *
211592Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
221592Srgrimes * or visit www.oracle.com if you need additional information or have any
231592Srgrimes * questions.
241592Srgrimes */
251592Srgrimes
261592Srgrimespackage com.sun.tools.javac.code;
271592Srgrimes
2815645Sjoergimport java.lang.annotation.Annotation;
2950476Speterimport java.lang.annotation.Inherited;
3015645Sjoergimport java.util.Set;
3115645Sjoergimport java.util.concurrent.Callable;
321592Srgrimes
3379529Sruimport javax.lang.model.element.*;
341592Srgrimesimport javax.tools.JavaFileObject;
351592Srgrimes
361592Srgrimesimport com.sun.tools.javac.code.Scope.WriteableScope;
371592Srgrimesimport com.sun.tools.javac.code.Type.*;
3868949Sruimport com.sun.tools.javac.comp.Attr;
3979754Sddimport com.sun.tools.javac.comp.AttrContext;
401592Srgrimesimport com.sun.tools.javac.comp.Env;
411592Srgrimesimport com.sun.tools.javac.jvm.*;
421592Srgrimesimport com.sun.tools.javac.tree.JCTree.JCVariableDecl;
431592Srgrimesimport com.sun.tools.javac.util.*;
441592Srgrimesimport com.sun.tools.javac.util.DefinedBy.Api;
4531331Scharnierimport com.sun.tools.javac.util.Name;
4699500Scharnierimport static com.sun.tools.javac.code.Flags.*;
471592Srgrimesimport static com.sun.tools.javac.code.Kinds.*;
481592Srgrimesimport static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
491592Srgrimesimport static com.sun.tools.javac.code.TypeTag.CLASS;
501592Srgrimesimport static com.sun.tools.javac.code.TypeTag.FORALL;
511592Srgrimesimport static com.sun.tools.javac.code.TypeTag.TYPEVAR;
521592Srgrimes
531592Srgrimes/** Root class for Java symbols. It contains subclasses
541592Srgrimes *  for specific sorts of symbols, such as variables, methods and operators,
551592Srgrimes *  types, packages. Each subclass is represented as a static inner class
561592Srgrimes *  inside Symbol.
57108221Sru *
581592Srgrimes *  <p><b>This is NOT part of any supported API.
591592Srgrimes *  If you write code that depends on this, you do so at your own risk.
601592Srgrimes *  This code and its internal interfaces are subject to change or
611592Srgrimes *  deletion without notice.</b>
621592Srgrimes */
6331331Scharnierpublic abstract class Symbol extends AnnoConstruct implements Element {
641592Srgrimes
651592Srgrimes    /** The kind of this symbol.
6628316Ssteve     *  @see Kinds
671592Srgrimes     */
681592Srgrimes    public int kind;
691592Srgrimes
701592Srgrimes    /** The flags of this symbol.
711592Srgrimes     */
721592Srgrimes    public long flags_field;
731592Srgrimes
741592Srgrimes    /** An accessor method for the flags of this symbol.
7531331Scharnier     *  Flags of class symbols should be accessed through the accessor
761592Srgrimes     *  method to make sure that the class symbol is loaded.
771592Srgrimes     */
781592Srgrimes    public long flags() { return flags_field; }
791592Srgrimes
801592Srgrimes    /** The name of this symbol in Utf8 representation.
811592Srgrimes     */
821592Srgrimes    public Name name;
8331331Scharnier
841592Srgrimes    /** The type of this symbol.
8531331Scharnier     */
861592Srgrimes    public Type type;
871592Srgrimes
881592Srgrimes    /** The owner of this symbol.
8931331Scharnier     */
9099500Scharnier    public Symbol owner;
911592Srgrimes
921592Srgrimes    /** The completer of this symbol.
93140414Sru     */
94140414Sru    public Completer completer;
95140414Sru
96140414Sru    /** A cache for the type erasure of this symbol.
97140414Sru     */
981592Srgrimes    public Type erasure_field;
991592Srgrimes
1001592Srgrimes    // <editor-fold defaultstate="collapsed" desc="annotations">
1011592Srgrimes
10231331Scharnier    /** The attributes of this symbol are contained in this
1031592Srgrimes     * SymbolMetadata. The SymbolMetadata instance is NOT immutable.
1041592Srgrimes     */
10531331Scharnier    protected SymbolMetadata metadata;
1061592Srgrimes
1071592Srgrimes
1081592Srgrimes    /** An accessor method for the attributes of this symbol.
1091592Srgrimes     *  Attributes of class symbols should be accessed through the accessor
1101592Srgrimes     *  method to make sure that the class symbol is loaded.
1111592Srgrimes     */
1121592Srgrimes    public List<Attribute.Compound> getRawAttributes() {
1131592Srgrimes        return (metadata == null)
1141592Srgrimes                ? List.<Attribute.Compound>nil()
1151592Srgrimes                : metadata.getDeclarationAttributes();
1161592Srgrimes    }
11721635Swosch
11821635Swosch    /** An accessor method for the type attributes of this symbol.
11921635Swosch     *  Attributes of class symbols should be accessed through the accessor
1201592Srgrimes     *  method to make sure that the class symbol is loaded.
1211592Srgrimes     */
12231331Scharnier    public List<Attribute.TypeCompound> getRawTypeAttributes() {
12399500Scharnier        return (metadata == null)
1241592Srgrimes                ? List.<Attribute.TypeCompound>nil()
125                : metadata.getTypeAttributes();
126    }
127
128    /** Fetch a particular annotation from a symbol. */
129    public Attribute.Compound attribute(Symbol anno) {
130        for (Attribute.Compound a : getRawAttributes()) {
131            if (a.type.tsym == anno) return a;
132        }
133        return null;
134    }
135
136    public boolean annotationsPendingCompletion() {
137        return metadata == null ? false : metadata.pendingCompletion();
138    }
139
140    public void appendAttributes(List<Attribute.Compound> l) {
141        if (l.nonEmpty()) {
142            initedMetadata().append(l);
143        }
144    }
145
146    public void appendClassInitTypeAttributes(List<Attribute.TypeCompound> l) {
147        if (l.nonEmpty()) {
148            initedMetadata().appendClassInitTypeAttributes(l);
149        }
150    }
151
152    public void appendInitTypeAttributes(List<Attribute.TypeCompound> l) {
153        if (l.nonEmpty()) {
154            initedMetadata().appendInitTypeAttributes(l);
155        }
156    }
157
158    public void appendUniqueTypeAttributes(List<Attribute.TypeCompound> l) {
159        if (l.nonEmpty()) {
160            initedMetadata().appendUniqueTypes(l);
161        }
162    }
163
164    public List<Attribute.TypeCompound> getClassInitTypeAttributes() {
165        return (metadata == null)
166                ? List.<Attribute.TypeCompound>nil()
167                : metadata.getClassInitTypeAttributes();
168    }
169
170    public List<Attribute.TypeCompound> getInitTypeAttributes() {
171        return (metadata == null)
172                ? List.<Attribute.TypeCompound>nil()
173                : metadata.getInitTypeAttributes();
174    }
175
176    public List<Attribute.Compound> getDeclarationAttributes() {
177        return (metadata == null)
178                ? List.<Attribute.Compound>nil()
179                : metadata.getDeclarationAttributes();
180    }
181
182    public boolean hasAnnotations() {
183        return (metadata != null && !metadata.isEmpty());
184    }
185
186    public boolean hasTypeAnnotations() {
187        return (metadata != null && !metadata.isTypesEmpty());
188    }
189
190    public void prependAttributes(List<Attribute.Compound> l) {
191        if (l.nonEmpty()) {
192            initedMetadata().prepend(l);
193        }
194    }
195
196    public void resetAnnotations() {
197        initedMetadata().reset();
198    }
199
200    public void setAttributes(Symbol other) {
201        if (metadata != null || other.metadata != null) {
202            initedMetadata().setAttributes(other.metadata);
203        }
204    }
205
206    public void setDeclarationAttributes(List<Attribute.Compound> a) {
207        if (metadata != null || a.nonEmpty()) {
208            initedMetadata().setDeclarationAttributes(a);
209        }
210    }
211
212    public void setTypeAttributes(List<Attribute.TypeCompound> a) {
213        if (metadata != null || a.nonEmpty()) {
214            if (metadata == null)
215                metadata = new SymbolMetadata(this);
216            metadata.setTypeAttributes(a);
217        }
218    }
219
220    private SymbolMetadata initedMetadata() {
221        if (metadata == null)
222            metadata = new SymbolMetadata(this);
223        return metadata;
224    }
225
226    /** This method is intended for debugging only. */
227    public SymbolMetadata getMetadata() {
228        return metadata;
229    }
230
231    // </editor-fold>
232
233    /** Construct a symbol with given kind, flags, name, type and owner.
234     */
235    public Symbol(int kind, long flags, Name name, Type type, Symbol owner) {
236        this.kind = kind;
237        this.flags_field = flags;
238        this.type = type;
239        this.owner = owner;
240        this.completer = null;
241        this.erasure_field = null;
242        this.name = name;
243    }
244
245    /** Clone this symbol with new owner.
246     *  Legal only for fields and methods.
247     */
248    public Symbol clone(Symbol newOwner) {
249        throw new AssertionError();
250    }
251
252    public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
253        return v.visitSymbol(this, p);
254    }
255
256    /** The Java source which this symbol represents.
257     *  A description of this symbol; overrides Object.
258     */
259    public String toString() {
260        return name.toString();
261    }
262
263    /** A Java source description of the location of this symbol; used for
264     *  error reporting.
265     *
266     * @return null if the symbol is a package or a toplevel class defined in
267     * the default package; otherwise, the owner symbol is returned
268     */
269    public Symbol location() {
270        if (owner.name == null || (owner.name.isEmpty() &&
271                (owner.flags() & BLOCK) == 0 && owner.kind != PCK && owner.kind != TYP)) {
272            return null;
273        }
274        return owner;
275    }
276
277    public Symbol location(Type site, Types types) {
278        if (owner.name == null || owner.name.isEmpty()) {
279            return location();
280        }
281        if (owner.type.hasTag(CLASS)) {
282            Type ownertype = types.asOuterSuper(site, owner);
283            if (ownertype != null) return ownertype.tsym;
284        }
285        return owner;
286    }
287
288    public Symbol baseSymbol() {
289        return this;
290    }
291
292    /** The symbol's erased type.
293     */
294    public Type erasure(Types types) {
295        if (erasure_field == null)
296            erasure_field = types.erasure(type);
297        return erasure_field;
298    }
299
300    /** The external type of a symbol. This is the symbol's erased type
301     *  except for constructors of inner classes which get the enclosing
302     *  instance class added as first argument.
303     */
304    public Type externalType(Types types) {
305        Type t = erasure(types);
306        if (name == name.table.names.init && owner.hasOuterInstance()) {
307            Type outerThisType = types.erasure(owner.type.getEnclosingType());
308            return new MethodType(t.getParameterTypes().prepend(outerThisType),
309                                  t.getReturnType(),
310                                  t.getThrownTypes(),
311                                  t.tsym);
312        } else {
313            return t;
314        }
315    }
316
317    public boolean isDeprecated() {
318        return (flags_field & DEPRECATED) != 0;
319    }
320
321    public boolean isStatic() {
322        return
323            (flags() & STATIC) != 0 ||
324            (owner.flags() & INTERFACE) != 0 && kind != MTH &&
325             name != name.table.names._this;
326    }
327
328    public boolean isInterface() {
329        return (flags() & INTERFACE) != 0;
330    }
331
332    public boolean isPrivate() {
333        return (flags_field & Flags.AccessFlags) == PRIVATE;
334    }
335
336    public boolean isEnum() {
337        return (flags() & ENUM) != 0;
338    }
339
340    /** Is this symbol declared (directly or indirectly) local
341     *  to a method or variable initializer?
342     *  Also includes fields of inner classes which are in
343     *  turn local to a method or variable initializer.
344     */
345    public boolean isLocal() {
346        return
347            (owner.kind & (VAR | MTH)) != 0 ||
348            (owner.kind == TYP && owner.isLocal());
349    }
350
351    /** Has this symbol an empty name? This includes anonymous
352     *  inner classes.
353     */
354    public boolean isAnonymous() {
355        return name.isEmpty();
356    }
357
358    /** Is this symbol a constructor?
359     */
360    public boolean isConstructor() {
361        return name == name.table.names.init;
362    }
363
364    /** The fully qualified name of this symbol.
365     *  This is the same as the symbol's name except for class symbols,
366     *  which are handled separately.
367     */
368    public Name getQualifiedName() {
369        return name;
370    }
371
372    /** The fully qualified name of this symbol after converting to flat
373     *  representation. This is the same as the symbol's name except for
374     *  class symbols, which are handled separately.
375     */
376    public Name flatName() {
377        return getQualifiedName();
378    }
379
380    /** If this is a class or package, its members, otherwise null.
381     */
382    public WriteableScope members() {
383        return null;
384    }
385
386    /** A class is an inner class if it it has an enclosing instance class.
387     */
388    public boolean isInner() {
389        return kind == TYP && type.getEnclosingType().hasTag(CLASS);
390    }
391
392    /** An inner class has an outer instance if it is not an interface
393     *  it has an enclosing instance class which might be referenced from the class.
394     *  Nested classes can see instance members of their enclosing class.
395     *  Their constructors carry an additional this$n parameter, inserted
396     *  implicitly by the compiler.
397     *
398     *  @see #isInner
399     */
400    public boolean hasOuterInstance() {
401        return
402            type.getEnclosingType().hasTag(CLASS) && (flags() & (INTERFACE | NOOUTERTHIS)) == 0;
403    }
404
405    /** The closest enclosing class of this symbol's declaration.
406     */
407    public ClassSymbol enclClass() {
408        Symbol c = this;
409        while (c != null &&
410               ((c.kind & TYP) == 0 || !c.type.hasTag(CLASS))) {
411            c = c.owner;
412        }
413        return (ClassSymbol)c;
414    }
415
416    /** The outermost class which indirectly owns this symbol.
417     */
418    public ClassSymbol outermostClass() {
419        Symbol sym = this;
420        Symbol prev = null;
421        while (sym.kind != PCK) {
422            prev = sym;
423            sym = sym.owner;
424        }
425        return (ClassSymbol) prev;
426    }
427
428    /** The package which indirectly owns this symbol.
429     */
430    public PackageSymbol packge() {
431        Symbol sym = this;
432        while (sym.kind != PCK) {
433            sym = sym.owner;
434        }
435        return (PackageSymbol) sym;
436    }
437
438    /** Is this symbol a subclass of `base'? Only defined for ClassSymbols.
439     */
440    public boolean isSubClass(Symbol base, Types types) {
441        throw new AssertionError("isSubClass " + this);
442    }
443
444    /** Fully check membership: hierarchy, protection, and hiding.
445     *  Does not exclude methods not inherited due to overriding.
446     */
447    public boolean isMemberOf(TypeSymbol clazz, Types types) {
448        return
449            owner == clazz ||
450            clazz.isSubClass(owner, types) &&
451            isInheritedIn(clazz, types) &&
452            !hiddenIn((ClassSymbol)clazz, types);
453    }
454
455    /** Is this symbol the same as or enclosed by the given class? */
456    public boolean isEnclosedBy(ClassSymbol clazz) {
457        for (Symbol sym = this; sym.kind != PCK; sym = sym.owner)
458            if (sym == clazz) return true;
459        return false;
460    }
461
462    private boolean hiddenIn(ClassSymbol clazz, Types types) {
463        Symbol sym = hiddenInInternal(clazz, types);
464        Assert.check(sym != null, "the result of hiddenInInternal() can't be null");
465        /* If we find the current symbol then there is no symbol hiding it
466         */
467        return sym != this;
468    }
469
470    /** This method looks in the supertypes graph that has the current class as the
471     * initial node, till it finds the current symbol or another symbol that hides it.
472     * If the current class has more than one supertype (extends one class and
473     * implements one or more interfaces) then null can be returned, meaning that
474     * a wrong path in the supertypes graph was selected. Null can only be returned
475     * as a temporary value, as a result of the recursive call.
476     */
477    private Symbol hiddenInInternal(ClassSymbol currentClass, Types types) {
478        if (currentClass == owner) {
479            return this;
480        }
481        for (Symbol sym : currentClass.members().getSymbolsByName(name)) {
482            if (sym.kind == kind &&
483                    (kind != MTH ||
484                    (sym.flags() & STATIC) != 0 &&
485                    types.isSubSignature(sym.type, type))) {
486                return sym;
487            }
488        }
489        Symbol hiddenSym = null;
490        for (Type st : types.interfaces(currentClass.type)
491                .prepend(types.supertype(currentClass.type))) {
492            if (st != null && (st.hasTag(CLASS))) {
493                Symbol sym = hiddenInInternal((ClassSymbol)st.tsym, types);
494                if (sym == this) {
495                    return this;
496                } else if (sym != null) {
497                    hiddenSym = sym;
498                }
499            }
500        }
501        return hiddenSym;
502    }
503
504    /** Is this symbol inherited into a given class?
505     *  PRE: If symbol's owner is a interface,
506     *       it is already assumed that the interface is a superinterface
507     *       of given class.
508     *  @param clazz  The class for which we want to establish membership.
509     *                This must be a subclass of the member's owner.
510     */
511    public boolean isInheritedIn(Symbol clazz, Types types) {
512        switch ((int)(flags_field & Flags.AccessFlags)) {
513        default: // error recovery
514        case PUBLIC:
515            return true;
516        case PRIVATE:
517            return this.owner == clazz;
518        case PROTECTED:
519            // we model interfaces as extending Object
520            return (clazz.flags() & INTERFACE) == 0;
521        case 0:
522            PackageSymbol thisPackage = this.packge();
523            for (Symbol sup = clazz;
524                 sup != null && sup != this.owner;
525                 sup = types.supertype(sup.type).tsym) {
526                while (sup.type.hasTag(TYPEVAR))
527                    sup = sup.type.getUpperBound().tsym;
528                if (sup.type.isErroneous())
529                    return true; // error recovery
530                if ((sup.flags() & COMPOUND) != 0)
531                    continue;
532                if (sup.packge() != thisPackage)
533                    return false;
534            }
535            return (clazz.flags() & INTERFACE) == 0;
536        }
537    }
538
539    /** The (variable or method) symbol seen as a member of given
540     *  class type`site' (this might change the symbol's type).
541     *  This is used exclusively for producing diagnostics.
542     */
543    public Symbol asMemberOf(Type site, Types types) {
544        throw new AssertionError();
545    }
546
547    /** Does this method symbol override `other' symbol, when both are seen as
548     *  members of class `origin'?  It is assumed that _other is a member
549     *  of origin.
550     *
551     *  It is assumed that both symbols have the same name.  The static
552     *  modifier is ignored for this test.
553     *
554     *  See JLS 8.4.6.1 (without transitivity) and 8.4.6.4
555     */
556    public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean checkResult) {
557        return false;
558    }
559
560    /** Complete the elaboration of this symbol's definition.
561     */
562    public void complete() throws CompletionFailure {
563        if (completer != null) {
564            Completer c = completer;
565            completer = null;
566            c.complete(this);
567        }
568    }
569
570    /** True if the symbol represents an entity that exists.
571     */
572    public boolean exists() {
573        return true;
574    }
575
576    @DefinedBy(Api.LANGUAGE_MODEL)
577    public Type asType() {
578        return type;
579    }
580
581    @DefinedBy(Api.LANGUAGE_MODEL)
582    public Symbol getEnclosingElement() {
583        return owner;
584    }
585
586    @DefinedBy(Api.LANGUAGE_MODEL)
587    public ElementKind getKind() {
588        return ElementKind.OTHER;       // most unkind
589    }
590
591    @DefinedBy(Api.LANGUAGE_MODEL)
592    public Set<Modifier> getModifiers() {
593        return Flags.asModifierSet(flags());
594    }
595
596    @DefinedBy(Api.LANGUAGE_MODEL)
597    public Name getSimpleName() {
598        return name;
599    }
600
601    /**
602     * This is the implementation for {@code
603     * javax.lang.model.element.Element.getAnnotationMirrors()}.
604     */
605    @Override @DefinedBy(Api.LANGUAGE_MODEL)
606    public List<Attribute.Compound> getAnnotationMirrors() {
607        return getRawAttributes();
608    }
609
610
611    // TODO: getEnclosedElements should return a javac List, fix in FilteredMemberList
612    @DefinedBy(Api.LANGUAGE_MODEL)
613    public java.util.List<Symbol> getEnclosedElements() {
614        return List.nil();
615    }
616
617    public List<TypeVariableSymbol> getTypeParameters() {
618        ListBuffer<TypeVariableSymbol> l = new ListBuffer<>();
619        for (Type t : type.getTypeArguments()) {
620            Assert.check(t.tsym.getKind() == ElementKind.TYPE_PARAMETER);
621            l.append((TypeVariableSymbol)t.tsym);
622        }
623        return l.toList();
624    }
625
626    public static class DelegatedSymbol<T extends Symbol> extends Symbol {
627        protected T other;
628        public DelegatedSymbol(T other) {
629            super(other.kind, other.flags_field, other.name, other.type, other.owner);
630            this.other = other;
631        }
632        public String toString() { return other.toString(); }
633        public Symbol location() { return other.location(); }
634        public Symbol location(Type site, Types types) { return other.location(site, types); }
635        public Symbol baseSymbol() { return other; }
636        public Type erasure(Types types) { return other.erasure(types); }
637        public Type externalType(Types types) { return other.externalType(types); }
638        public boolean isLocal() { return other.isLocal(); }
639        public boolean isConstructor() { return other.isConstructor(); }
640        public Name getQualifiedName() { return other.getQualifiedName(); }
641        public Name flatName() { return other.flatName(); }
642        public WriteableScope members() { return other.members(); }
643        public boolean isInner() { return other.isInner(); }
644        public boolean hasOuterInstance() { return other.hasOuterInstance(); }
645        public ClassSymbol enclClass() { return other.enclClass(); }
646        public ClassSymbol outermostClass() { return other.outermostClass(); }
647        public PackageSymbol packge() { return other.packge(); }
648        public boolean isSubClass(Symbol base, Types types) { return other.isSubClass(base, types); }
649        public boolean isMemberOf(TypeSymbol clazz, Types types) { return other.isMemberOf(clazz, types); }
650        public boolean isEnclosedBy(ClassSymbol clazz) { return other.isEnclosedBy(clazz); }
651        public boolean isInheritedIn(Symbol clazz, Types types) { return other.isInheritedIn(clazz, types); }
652        public Symbol asMemberOf(Type site, Types types) { return other.asMemberOf(site, types); }
653        public void complete() throws CompletionFailure { other.complete(); }
654
655        @DefinedBy(Api.LANGUAGE_MODEL)
656        public <R, P> R accept(ElementVisitor<R, P> v, P p) {
657            return other.accept(v, p);
658        }
659
660        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
661            return v.visitSymbol(other, p);
662        }
663
664        public T getUnderlyingSymbol() {
665            return other;
666        }
667    }
668
669    /** A base class for Symbols representing types.
670     */
671    public static abstract class TypeSymbol extends Symbol {
672        public TypeSymbol(int kind, long flags, Name name, Type type, Symbol owner) {
673            super(kind, flags, name, type, owner);
674        }
675        /** form a fully qualified name from a name and an owner
676         */
677        static public Name formFullName(Name name, Symbol owner) {
678            if (owner == null) return name;
679            if (((owner.kind != ERR)) &&
680                ((owner.kind & (VAR | MTH)) != 0
681                 || (owner.kind == TYP && owner.type.hasTag(TYPEVAR))
682                 )) return name;
683            Name prefix = owner.getQualifiedName();
684            if (prefix == null || prefix == prefix.table.names.empty)
685                return name;
686            else return prefix.append('.', name);
687        }
688
689        /** form a fully qualified name from a name and an owner, after
690         *  converting to flat representation
691         */
692        static public Name formFlatName(Name name, Symbol owner) {
693            if (owner == null ||
694                (owner.kind & (VAR | MTH)) != 0
695                || (owner.kind == TYP && owner.type.hasTag(TYPEVAR))
696                ) return name;
697            char sep = owner.kind == TYP ? '$' : '.';
698            Name prefix = owner.flatName();
699            if (prefix == null || prefix == prefix.table.names.empty)
700                return name;
701            else return prefix.append(sep, name);
702        }
703
704        /**
705         * A partial ordering between type symbols that refines the
706         * class inheritance graph.
707         *
708         * Type variables always precede other kinds of symbols.
709         */
710        public final boolean precedes(TypeSymbol that, Types types) {
711            if (this == that)
712                return false;
713            if (type.hasTag(that.type.getTag())) {
714                if (type.hasTag(CLASS)) {
715                    return
716                        types.rank(that.type) < types.rank(this.type) ||
717                        types.rank(that.type) == types.rank(this.type) &&
718                        that.getQualifiedName().compareTo(this.getQualifiedName()) < 0;
719                } else if (type.hasTag(TYPEVAR)) {
720                    return types.isSubtype(this.type, that.type);
721                }
722            }
723            return type.hasTag(TYPEVAR);
724        }
725
726        @Override @DefinedBy(Api.LANGUAGE_MODEL)
727        public java.util.List<Symbol> getEnclosedElements() {
728            List<Symbol> list = List.nil();
729            if (kind == TYP && type.hasTag(TYPEVAR)) {
730                return list;
731            }
732            for (Symbol sym : members().getSymbols(NON_RECURSIVE)) {
733                if (sym != null && (sym.flags() & SYNTHETIC) == 0 && sym.owner == this)
734                    list = list.prepend(sym);
735            }
736            return list;
737        }
738
739        @Override
740        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
741            return v.visitTypeSymbol(this, p);
742        }
743    }
744
745    /**
746     * Type variables are represented by instances of this class.
747     */
748    public static class TypeVariableSymbol
749            extends TypeSymbol implements TypeParameterElement {
750
751        public TypeVariableSymbol(long flags, Name name, Type type, Symbol owner) {
752            super(TYP, flags, name, type, owner);
753        }
754
755        @DefinedBy(Api.LANGUAGE_MODEL)
756        public ElementKind getKind() {
757            return ElementKind.TYPE_PARAMETER;
758        }
759
760        @Override @DefinedBy(Api.LANGUAGE_MODEL)
761        public Symbol getGenericElement() {
762            return owner;
763        }
764
765        @DefinedBy(Api.LANGUAGE_MODEL)
766        public List<Type> getBounds() {
767            TypeVar t = (TypeVar)type;
768            Type bound = t.getUpperBound();
769            if (!bound.isCompound())
770                return List.of(bound);
771            ClassType ct = (ClassType)bound;
772            if (!ct.tsym.erasure_field.isInterface()) {
773                return ct.interfaces_field.prepend(ct.supertype_field);
774            } else {
775                // No superclass was given in bounds.
776                // In this case, supertype is Object, erasure is first interface.
777                return ct.interfaces_field;
778            }
779        }
780
781        @Override @DefinedBy(Api.LANGUAGE_MODEL)
782        public List<Attribute.Compound> getAnnotationMirrors() {
783            // Declaration annotations on type variables are stored in type attributes
784            // on the owner of the TypeVariableSymbol
785            List<Attribute.TypeCompound> candidates = owner.getRawTypeAttributes();
786            int index = owner.getTypeParameters().indexOf(this);
787            List<Attribute.Compound> res = List.nil();
788            for (Attribute.TypeCompound a : candidates) {
789                if (isCurrentSymbolsAnnotation(a, index))
790                    res = res.prepend(a);
791            }
792
793            return res.reverse();
794        }
795
796        // Helper to getAnnotation[s]
797        @Override
798        public <A extends Annotation> Attribute.Compound getAttribute(Class<A> annoType) {
799            String name = annoType.getName();
800
801            // Declaration annotations on type variables are stored in type attributes
802            // on the owner of the TypeVariableSymbol
803            List<Attribute.TypeCompound> candidates = owner.getRawTypeAttributes();
804            int index = owner.getTypeParameters().indexOf(this);
805            for (Attribute.TypeCompound anno : candidates)
806                if (isCurrentSymbolsAnnotation(anno, index) &&
807                    name.contentEquals(anno.type.tsym.flatName()))
808                    return anno;
809
810            return null;
811        }
812            //where:
813            boolean isCurrentSymbolsAnnotation(Attribute.TypeCompound anno, int index) {
814                return (anno.position.type == TargetType.CLASS_TYPE_PARAMETER ||
815                        anno.position.type == TargetType.METHOD_TYPE_PARAMETER) &&
816                       anno.position.parameter_index == index;
817            }
818
819
820        @Override @DefinedBy(Api.LANGUAGE_MODEL)
821        public <R, P> R accept(ElementVisitor<R, P> v, P p) {
822            return v.visitTypeParameter(this, p);
823        }
824    }
825
826    /** A class for package symbols
827     */
828    public static class PackageSymbol extends TypeSymbol
829        implements PackageElement {
830
831        public WriteableScope members_field;
832        public Name fullname;
833        public ClassSymbol package_info; // see bug 6443073
834
835        public PackageSymbol(Name name, Type type, Symbol owner) {
836            super(PCK, 0, name, type, owner);
837            this.members_field = null;
838            this.fullname = formFullName(name, owner);
839        }
840
841        public PackageSymbol(Name name, Symbol owner) {
842            this(name, null, owner);
843            this.type = new PackageType(this);
844        }
845
846        public String toString() {
847            return fullname.toString();
848        }
849
850        @DefinedBy(Api.LANGUAGE_MODEL)
851        public Name getQualifiedName() {
852            return fullname;
853        }
854
855        @DefinedBy(Api.LANGUAGE_MODEL)
856        public boolean isUnnamed() {
857            return name.isEmpty() && owner != null;
858        }
859
860        public WriteableScope members() {
861            if (completer != null) complete();
862            return members_field;
863        }
864
865        public long flags() {
866            if (completer != null) complete();
867            return flags_field;
868        }
869
870        @Override
871        public List<Attribute.Compound> getRawAttributes() {
872            if (completer != null) complete();
873            if (package_info != null && package_info.completer != null) {
874                package_info.complete();
875                mergeAttributes();
876            }
877            return super.getRawAttributes();
878        }
879
880        private void mergeAttributes() {
881            if (metadata == null &&
882                package_info.metadata != null) {
883                metadata = new SymbolMetadata(this);
884                metadata.setAttributes(package_info.metadata);
885            }
886        }
887
888        /** A package "exists" if a type or package that exists has
889         *  been seen within it.
890         */
891        public boolean exists() {
892            return (flags_field & EXISTS) != 0;
893        }
894
895        @DefinedBy(Api.LANGUAGE_MODEL)
896        public ElementKind getKind() {
897            return ElementKind.PACKAGE;
898        }
899
900        @DefinedBy(Api.LANGUAGE_MODEL)
901        public Symbol getEnclosingElement() {
902            return null;
903        }
904
905        @DefinedBy(Api.LANGUAGE_MODEL)
906        public <R, P> R accept(ElementVisitor<R, P> v, P p) {
907            return v.visitPackage(this, p);
908        }
909
910        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
911            return v.visitPackageSymbol(this, p);
912        }
913
914        /**Resets the Symbol into the state good for next round of annotation processing.*/
915        public void reset() {
916            metadata = null;
917        }
918
919    }
920
921    /** A class for class symbols
922     */
923    public static class ClassSymbol extends TypeSymbol implements TypeElement {
924
925        /** a scope for all class members; variables, methods and inner classes
926         *  type parameters are not part of this scope
927         */
928        public WriteableScope members_field;
929
930        /** the fully qualified name of the class, i.e. pck.outer.inner.
931         *  null for anonymous classes
932         */
933        public Name fullname;
934
935        /** the fully qualified name of the class after converting to flat
936         *  representation, i.e. pck.outer$inner,
937         *  set externally for local and anonymous classes
938         */
939        public Name flatname;
940
941        /** the sourcefile where the class came from
942         */
943        public JavaFileObject sourcefile;
944
945        /** the classfile from where to load this class
946         *  this will have extension .class or .java
947         */
948        public JavaFileObject classfile;
949
950        /** the list of translated local classes (used for generating
951         * InnerClasses attribute)
952         */
953        public List<ClassSymbol> trans_local;
954
955        /** the constant pool of the class
956         */
957        public Pool pool;
958
959        public ClassSymbol(long flags, Name name, Type type, Symbol owner) {
960            super(TYP, flags, name, type, owner);
961            this.members_field = null;
962            this.fullname = formFullName(name, owner);
963            this.flatname = formFlatName(name, owner);
964            this.sourcefile = null;
965            this.classfile = null;
966            this.pool = null;
967        }
968
969        public ClassSymbol(long flags, Name name, Symbol owner) {
970            this(
971                flags,
972                name,
973                new ClassType(Type.noType, null, null),
974                owner);
975            this.type.tsym = this;
976        }
977
978        /** The Java source which this symbol represents.
979         */
980        public String toString() {
981            return className();
982        }
983
984        public long flags() {
985            if (completer != null) complete();
986            return flags_field;
987        }
988
989        public WriteableScope members() {
990            if (completer != null) complete();
991            return members_field;
992        }
993
994        @Override
995        public List<Attribute.Compound> getRawAttributes() {
996            if (completer != null) complete();
997            return super.getRawAttributes();
998        }
999
1000        @Override
1001        public List<Attribute.TypeCompound> getRawTypeAttributes() {
1002            if (completer != null) complete();
1003            return super.getRawTypeAttributes();
1004        }
1005
1006        public Type erasure(Types types) {
1007            if (erasure_field == null)
1008                erasure_field = new ClassType(types.erasure(type.getEnclosingType()),
1009                                              List.<Type>nil(), this,
1010                                              type.getMetadata());
1011            return erasure_field;
1012        }
1013
1014        public String className() {
1015            if (name.isEmpty())
1016                return
1017                    Log.getLocalizedString("anonymous.class", flatname);
1018            else
1019                return fullname.toString();
1020        }
1021
1022        @DefinedBy(Api.LANGUAGE_MODEL)
1023        public Name getQualifiedName() {
1024            return fullname;
1025        }
1026
1027        public Name flatName() {
1028            return flatname;
1029        }
1030
1031        public boolean isSubClass(Symbol base, Types types) {
1032            if (this == base) {
1033                return true;
1034            } else if ((base.flags() & INTERFACE) != 0) {
1035                for (Type t = type; t.hasTag(CLASS); t = types.supertype(t))
1036                    for (List<Type> is = types.interfaces(t);
1037                         is.nonEmpty();
1038                         is = is.tail)
1039                        if (is.head.tsym.isSubClass(base, types)) return true;
1040            } else {
1041                for (Type t = type; t.hasTag(CLASS); t = types.supertype(t))
1042                    if (t.tsym == base) return true;
1043            }
1044            return false;
1045        }
1046
1047        /** Complete the elaboration of this symbol's definition.
1048         */
1049        public void complete() throws CompletionFailure {
1050            try {
1051                super.complete();
1052            } catch (CompletionFailure ex) {
1053                // quiet error recovery
1054                flags_field |= (PUBLIC|STATIC);
1055                this.type = new ErrorType(this, Type.noType);
1056                throw ex;
1057            }
1058        }
1059
1060        @DefinedBy(Api.LANGUAGE_MODEL)
1061        public List<Type> getInterfaces() {
1062            complete();
1063            if (type instanceof ClassType) {
1064                ClassType t = (ClassType)type;
1065                if (t.interfaces_field == null) // FIXME: shouldn't be null
1066                    t.interfaces_field = List.nil();
1067                if (t.all_interfaces_field != null)
1068                    return Type.getModelTypes(t.all_interfaces_field);
1069                return t.interfaces_field;
1070            } else {
1071                return List.nil();
1072            }
1073        }
1074
1075        @DefinedBy(Api.LANGUAGE_MODEL)
1076        public Type getSuperclass() {
1077            complete();
1078            if (type instanceof ClassType) {
1079                ClassType t = (ClassType)type;
1080                if (t.supertype_field == null) // FIXME: shouldn't be null
1081                    t.supertype_field = Type.noType;
1082                // An interface has no superclass; its supertype is Object.
1083                return t.isInterface()
1084                    ? Type.noType
1085                    : t.supertype_field.getModelType();
1086            } else {
1087                return Type.noType;
1088            }
1089        }
1090
1091        /**
1092         * Returns the next class to search for inherited annotations or {@code null}
1093         * if the next class can't be found.
1094         */
1095        private ClassSymbol getSuperClassToSearchForAnnotations() {
1096
1097            Type sup = getSuperclass();
1098
1099            if (!sup.hasTag(CLASS) || sup.isErroneous())
1100                return null;
1101
1102            return (ClassSymbol) sup.tsym;
1103        }
1104
1105
1106        @Override
1107        protected <A extends Annotation> A[] getInheritedAnnotations(Class<A> annoType) {
1108
1109            ClassSymbol sup = getSuperClassToSearchForAnnotations();
1110
1111            return sup == null ? super.getInheritedAnnotations(annoType)
1112                               : sup.getAnnotationsByType(annoType);
1113        }
1114
1115
1116        @DefinedBy(Api.LANGUAGE_MODEL)
1117        public ElementKind getKind() {
1118            long flags = flags();
1119            if ((flags & ANNOTATION) != 0)
1120                return ElementKind.ANNOTATION_TYPE;
1121            else if ((flags & INTERFACE) != 0)
1122                return ElementKind.INTERFACE;
1123            else if ((flags & ENUM) != 0)
1124                return ElementKind.ENUM;
1125            else
1126                return ElementKind.CLASS;
1127        }
1128
1129        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1130        public Set<Modifier> getModifiers() {
1131            long flags = flags();
1132            return Flags.asModifierSet(flags & ~DEFAULT);
1133        }
1134
1135        @DefinedBy(Api.LANGUAGE_MODEL)
1136        public NestingKind getNestingKind() {
1137            complete();
1138            if (owner.kind == PCK)
1139                return NestingKind.TOP_LEVEL;
1140            else if (name.isEmpty())
1141                return NestingKind.ANONYMOUS;
1142            else if (owner.kind == MTH)
1143                return NestingKind.LOCAL;
1144            else
1145                return NestingKind.MEMBER;
1146        }
1147
1148
1149        @Override
1150        protected <A extends Annotation> Attribute.Compound getAttribute(final Class<A> annoType) {
1151
1152            Attribute.Compound attrib = super.getAttribute(annoType);
1153
1154            boolean inherited = annoType.isAnnotationPresent(Inherited.class);
1155            if (attrib != null || !inherited)
1156                return attrib;
1157
1158            // Search supertypes
1159            ClassSymbol superType = getSuperClassToSearchForAnnotations();
1160            return superType == null ? null
1161                                     : superType.getAttribute(annoType);
1162        }
1163
1164
1165
1166
1167        @DefinedBy(Api.LANGUAGE_MODEL)
1168        public <R, P> R accept(ElementVisitor<R, P> v, P p) {
1169            return v.visitType(this, p);
1170        }
1171
1172        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
1173            return v.visitClassSymbol(this, p);
1174        }
1175
1176        /**Resets the Symbol into the state good for next round of annotation processing.*/
1177        public void reset() {
1178            kind = TYP;
1179            erasure_field = null;
1180            members_field = null;
1181            flags_field = 0;
1182            if (type instanceof ClassType) {
1183                ClassType t = (ClassType)type;
1184                t.setEnclosingType(Type.noType);
1185                t.rank_field = -1;
1186                t.typarams_field = null;
1187                t.allparams_field = null;
1188                t.supertype_field = null;
1189                t.interfaces_field = null;
1190                t.all_interfaces_field = null;
1191            }
1192            metadata = null;
1193        }
1194
1195    }
1196
1197
1198    /** A class for variable symbols
1199     */
1200    public static class VarSymbol extends Symbol implements VariableElement {
1201
1202        /** The variable's declaration position.
1203         */
1204        public int pos = Position.NOPOS;
1205
1206        /** The variable's address. Used for different purposes during
1207         *  flow analysis, translation and code generation.
1208         *  Flow analysis:
1209         *    If this is a blank final or local variable, its sequence number.
1210         *  Translation:
1211         *    If this is a private field, its access number.
1212         *  Code generation:
1213         *    If this is a local variable, its logical slot number.
1214         */
1215        public int adr = -1;
1216
1217        /** Construct a variable symbol, given its flags, name, type and owner.
1218         */
1219        public VarSymbol(long flags, Name name, Type type, Symbol owner) {
1220            super(VAR, flags, name, type, owner);
1221        }
1222
1223        /** Clone this symbol with new owner.
1224         */
1225        public VarSymbol clone(Symbol newOwner) {
1226            VarSymbol v = new VarSymbol(flags_field, name, type, newOwner) {
1227                @Override
1228                public Symbol baseSymbol() {
1229                    return VarSymbol.this;
1230                }
1231            };
1232            v.pos = pos;
1233            v.adr = adr;
1234            v.data = data;
1235//          System.out.println("clone " + v + " in " + newOwner);//DEBUG
1236            return v;
1237        }
1238
1239        public String toString() {
1240            return name.toString();
1241        }
1242
1243        public Symbol asMemberOf(Type site, Types types) {
1244            return new VarSymbol(flags_field, name, types.memberType(site, this), owner);
1245        }
1246
1247        @DefinedBy(Api.LANGUAGE_MODEL)
1248        public ElementKind getKind() {
1249            long flags = flags();
1250            if ((flags & PARAMETER) != 0) {
1251                if (isExceptionParameter())
1252                    return ElementKind.EXCEPTION_PARAMETER;
1253                else
1254                    return ElementKind.PARAMETER;
1255            } else if ((flags & ENUM) != 0) {
1256                return ElementKind.ENUM_CONSTANT;
1257            } else if (owner.kind == TYP || owner.kind == ERR) {
1258                return ElementKind.FIELD;
1259            } else if (isResourceVariable()) {
1260                return ElementKind.RESOURCE_VARIABLE;
1261            } else {
1262                return ElementKind.LOCAL_VARIABLE;
1263            }
1264        }
1265
1266        @DefinedBy(Api.LANGUAGE_MODEL)
1267        public <R, P> R accept(ElementVisitor<R, P> v, P p) {
1268            return v.visitVariable(this, p);
1269        }
1270
1271        @DefinedBy(Api.LANGUAGE_MODEL)
1272        public Object getConstantValue() { // Mirror API
1273            return Constants.decode(getConstValue(), type);
1274        }
1275
1276        public void setLazyConstValue(final Env<AttrContext> env,
1277                                      final Attr attr,
1278                                      final JCVariableDecl variable)
1279        {
1280            setData(new Callable<Object>() {
1281                public Object call() {
1282                    return attr.attribLazyConstantValue(env, variable, type);
1283                }
1284            });
1285        }
1286
1287        /**
1288         * The variable's constant value, if this is a constant.
1289         * Before the constant value is evaluated, it points to an
1290         * initializer environment.  If this is not a constant, it can
1291         * be used for other stuff.
1292         */
1293        private Object data;
1294
1295        public boolean isExceptionParameter() {
1296            return data == ElementKind.EXCEPTION_PARAMETER;
1297        }
1298
1299        public boolean isResourceVariable() {
1300            return data == ElementKind.RESOURCE_VARIABLE;
1301        }
1302
1303        public Object getConstValue() {
1304            // TODO: Consider if getConstValue and getConstantValue can be collapsed
1305            if (data == ElementKind.EXCEPTION_PARAMETER ||
1306                data == ElementKind.RESOURCE_VARIABLE) {
1307                return null;
1308            } else if (data instanceof Callable<?>) {
1309                // In this case, this is a final variable, with an as
1310                // yet unevaluated initializer.
1311                Callable<?> eval = (Callable<?>)data;
1312                data = null; // to make sure we don't evaluate this twice.
1313                try {
1314                    data = eval.call();
1315                } catch (Exception ex) {
1316                    throw new AssertionError(ex);
1317                }
1318            }
1319            return data;
1320        }
1321
1322        public void setData(Object data) {
1323            Assert.check(!(data instanceof Env<?>), this);
1324            this.data = data;
1325        }
1326
1327        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
1328            return v.visitVarSymbol(this, p);
1329        }
1330    }
1331
1332    /** A class for method symbols.
1333     */
1334    public static class MethodSymbol extends Symbol implements ExecutableElement {
1335
1336        /** The code of the method. */
1337        public Code code = null;
1338
1339        /** The extra (synthetic/mandated) parameters of the method. */
1340        public List<VarSymbol> extraParams = List.nil();
1341
1342        /** The captured local variables in an anonymous class */
1343        public List<VarSymbol> capturedLocals = List.nil();
1344
1345        /** The parameters of the method. */
1346        public List<VarSymbol> params = null;
1347
1348        /** The names of the parameters */
1349        public List<Name> savedParameterNames;
1350
1351        /** For an attribute field accessor, its default value if any.
1352         *  The value is null if none appeared in the method
1353         *  declaration.
1354         */
1355        public Attribute defaultValue = null;
1356
1357        /** Construct a method symbol, given its flags, name, type and owner.
1358         */
1359        public MethodSymbol(long flags, Name name, Type type, Symbol owner) {
1360            super(MTH, flags, name, type, owner);
1361            if (owner.type.hasTag(TYPEVAR)) Assert.error(owner + "." + name);
1362        }
1363
1364        /** Clone this symbol with new owner.
1365         */
1366        public MethodSymbol clone(Symbol newOwner) {
1367            MethodSymbol m = new MethodSymbol(flags_field, name, type, newOwner) {
1368                @Override
1369                public Symbol baseSymbol() {
1370                    return MethodSymbol.this;
1371                }
1372            };
1373            m.code = code;
1374            return m;
1375        }
1376
1377        @Override @DefinedBy(Api.LANGUAGE_MODEL)
1378        public Set<Modifier> getModifiers() {
1379            long flags = flags();
1380            return Flags.asModifierSet((flags & DEFAULT) != 0 ? flags & ~ABSTRACT : flags);
1381        }
1382
1383        /** The Java source which this symbol represents.
1384         */
1385        public String toString() {
1386            if ((flags() & BLOCK) != 0) {
1387                return owner.name.toString();
1388            } else {
1389                String s = (name == name.table.names.init)
1390                    ? owner.name.toString()
1391                    : name.toString();
1392                if (type != null) {
1393                    if (type.hasTag(FORALL))
1394                        s = "<" + ((ForAll)type).getTypeArguments() + ">" + s;
1395                    s += "(" + type.argtypes((flags() & VARARGS) != 0) + ")";
1396                }
1397                return s;
1398            }
1399        }
1400
1401        public boolean isDynamic() {
1402            return false;
1403        }
1404
1405        /** find a symbol that this (proxy method) symbol implements.
1406         *  @param    c       The class whose members are searched for
1407         *                    implementations
1408         */
1409        public Symbol implemented(TypeSymbol c, Types types) {
1410            Symbol impl = null;
1411            for (List<Type> is = types.interfaces(c.type);
1412                 impl == null && is.nonEmpty();
1413                 is = is.tail) {
1414                TypeSymbol i = is.head.tsym;
1415                impl = implementedIn(i, types);
1416                if (impl == null)
1417                    impl = implemented(i, types);
1418            }
1419            return impl;
1420        }
1421
1422        public Symbol implementedIn(TypeSymbol c, Types types) {
1423            Symbol impl = null;
1424            for (Symbol sym : c.members().getSymbolsByName(name)) {
1425                if (this.overrides(sym, (TypeSymbol)owner, types, true) &&
1426                    // FIXME: I suspect the following requires a
1427                    // subst() for a parametric return type.
1428                    types.isSameType(type.getReturnType(),
1429                                     types.memberType(owner.type, sym).getReturnType())) {
1430                    impl = sym;
1431                }
1432            }
1433            return impl;
1434        }
1435
1436        /** Will the erasure of this method be considered by the VM to
1437         *  override the erasure of the other when seen from class `origin'?
1438         */
1439        public boolean binaryOverrides(Symbol _other, TypeSymbol origin, Types types) {
1440            if (isConstructor() || _other.kind != MTH) return false;
1441
1442            if (this == _other) return true;
1443            MethodSymbol other = (MethodSymbol)_other;
1444
1445            // check for a direct implementation
1446            if (other.isOverridableIn((TypeSymbol)owner) &&
1447                types.asSuper(owner.type, other.owner) != null &&
1448                types.isSameType(erasure(types), other.erasure(types)))
1449                return true;
1450
1451            // check for an inherited implementation
1452            return
1453                (flags() & ABSTRACT) == 0 &&
1454                other.isOverridableIn(origin) &&
1455                this.isMemberOf(origin, types) &&
1456                types.isSameType(erasure(types), other.erasure(types));
1457        }
1458
1459        /** The implementation of this (abstract) symbol in class origin,
1460         *  from the VM's point of view, null if method does not have an
1461         *  implementation in class.
1462         *  @param origin   The class of which the implementation is a member.
1463         */
1464        public MethodSymbol binaryImplementation(ClassSymbol origin, Types types) {
1465            for (TypeSymbol c = origin; c != null; c = types.supertype(c.type).tsym) {
1466                for (Symbol sym : c.members().getSymbolsByName(name)) {
1467                    if (sym.kind == MTH &&
1468                        ((MethodSymbol)sym).binaryOverrides(this, origin, types))
1469                        return (MethodSymbol)sym;
1470                }
1471            }
1472            return null;
1473        }
1474
1475        /** Does this symbol override `other' symbol, when both are seen as
1476         *  members of class `origin'?  It is assumed that _other is a member
1477         *  of origin.
1478         *
1479         *  It is assumed that both symbols have the same name.  The static
1480         *  modifier is ignored for this test.
1481         *
1482         *  See JLS 8.4.6.1 (without transitivity) and 8.4.6.4
1483         */
1484        public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean checkResult) {
1485            if (isConstructor() || _other.kind != MTH) return false;
1486
1487            if (this == _other) return true;
1488            MethodSymbol other = (MethodSymbol)_other;
1489
1490            // check for a direct implementation
1491            if (other.isOverridableIn((TypeSymbol)owner) &&
1492                types.asSuper(owner.type, other.owner) != null) {
1493                Type mt = types.memberType(owner.type, this);
1494                Type ot = types.memberType(owner.type, other);
1495                if (types.isSubSignature(mt, ot)) {
1496                    if (!checkResult)
1497                        return true;
1498                    if (types.returnTypeSubstitutable(mt, ot))
1499                        return true;
1500                }
1501            }
1502
1503            // check for an inherited implementation
1504            if ((flags() & ABSTRACT) != 0 ||
1505                    ((other.flags() & ABSTRACT) == 0 && (other.flags() & DEFAULT) == 0) ||
1506                    !other.isOverridableIn(origin) ||
1507                    !this.isMemberOf(origin, types))
1508                return false;
1509
1510            // assert types.asSuper(origin.type, other.owner) != null;
1511            Type mt = types.memberType(origin.type, this);
1512            Type ot = types.memberType(origin.type, other);
1513            return
1514                types.isSubSignature(mt, ot) &&
1515                (!checkResult || types.resultSubtype(mt, ot, types.noWarnings));
1516        }
1517
1518        private boolean isOverridableIn(TypeSymbol origin) {
1519            // JLS 8.4.6.1
1520            switch ((int)(flags_field & Flags.AccessFlags)) {
1521            case Flags.PRIVATE:
1522                return false;
1523            case Flags.PUBLIC:
1524                return !this.owner.isInterface() ||
1525                        (flags_field & STATIC) == 0;
1526            case Flags.PROTECTED:
1527                return (origin.flags() & INTERFACE) == 0;
1528            case 0:
1529                // for package private: can only override in the same
1530                // package
1531                return
1532                    this.packge() == origin.packge() &&
1533                    (origin.flags() & INTERFACE) == 0;
1534            default:
1535                return false;
1536            }
1537        }
1538
1539        @Override
1540        public boolean isInheritedIn(Symbol clazz, Types types) {
1541            switch ((int)(flags_field & Flags.AccessFlags)) {
1542                case PUBLIC:
1543                    return !this.owner.isInterface() ||
1544                            clazz == owner ||
1545                            (flags_field & STATIC) == 0;
1546                default:
1547                    return super.isInheritedIn(clazz, types);
1548            }
1549        }
1550
1551        /** The implementation of this (abstract) symbol in class origin;
1552         *  null if none exists. Synthetic methods are not considered
1553         *  as possible implementations.
1554         */
1555        public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
1556            return implementation(origin, types, checkResult, implementation_filter);
1557        }
1558        // where
1559            public static final Filter<Symbol> implementation_filter = new Filter<Symbol>() {
1560                public boolean accepts(Symbol s) {
1561                    return s.kind == Kinds.MTH &&
1562                            (s.flags() & SYNTHETIC) == 0;
1563                }
1564            };
1565
1566        public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult, Filter<Symbol> implFilter) {
1567            MethodSymbol res = types.implementation(this, origin, checkResult, implFilter);
1568            if (res != null)
1569                return res;
1570            // if origin is derived from a raw type, we might have missed
1571            // an implementation because we do not know enough about instantiations.
1572            // in this case continue with the supertype as origin.
1573            if (types.isDerivedRaw(origin.type) && !origin.isInterface())
1574                return implementation(types.supertype(origin.type).tsym, types, checkResult);
1575            else
1576                return null;
1577        }
1578
1579        public List<VarSymbol> params() {
1580            owner.complete();
1581            if (params == null) {
1582                // If ClassReader.saveParameterNames has been set true, then
1583                // savedParameterNames will be set to a list of names that
1584                // matches the types in type.getParameterTypes().  If any names
1585                // were not found in the class file, those names in the list will
1586                // be set to the empty name.
1587                // If ClassReader.saveParameterNames has been set false, then
1588                // savedParameterNames will be null.
1589                List<Name> paramNames = savedParameterNames;
1590                savedParameterNames = null;
1591                // discard the provided names if the list of names is the wrong size.
1592                if (paramNames == null || paramNames.size() != type.getParameterTypes().size()) {
1593                    paramNames = List.nil();
1594                }
1595                ListBuffer<VarSymbol> buf = new ListBuffer<>();
1596                List<Name> remaining = paramNames;
1597                // assert: remaining and paramNames are both empty or both
1598                // have same cardinality as type.getParameterTypes()
1599                int i = 0;
1600                for (Type t : type.getParameterTypes()) {
1601                    Name paramName;
1602                    if (remaining.isEmpty()) {
1603                        // no names for any parameters available
1604                        paramName = createArgName(i, paramNames);
1605                    } else {
1606                        paramName = remaining.head;
1607                        remaining = remaining.tail;
1608                        if (paramName.isEmpty()) {
1609                            // no name for this specific parameter
1610                            paramName = createArgName(i, paramNames);
1611                        }
1612                    }
1613                    buf.append(new VarSymbol(PARAMETER, paramName, t, this));
1614                    i++;
1615                }
1616                params = buf.toList();
1617            }
1618            return params;
1619        }
1620
1621        // Create a name for the argument at position 'index' that is not in
1622        // the exclude list. In normal use, either no names will have been
1623        // provided, in which case the exclude list is empty, or all the names
1624        // will have been provided, in which case this method will not be called.
1625        private Name createArgName(int index, List<Name> exclude) {
1626            String prefix = "arg";
1627            while (true) {
1628                Name argName = name.table.fromString(prefix + index);
1629                if (!exclude.contains(argName))
1630                    return argName;
1631                prefix += "$";
1632            }
1633        }
1634
1635        public Symbol asMemberOf(Type site, Types types) {
1636            return new MethodSymbol(flags_field, name, types.memberType(site, this), owner);
1637        }
1638
1639        @DefinedBy(Api.LANGUAGE_MODEL)
1640        public ElementKind getKind() {
1641            if (name == name.table.names.init)
1642                return ElementKind.CONSTRUCTOR;
1643            else if (name == name.table.names.clinit)
1644                return ElementKind.STATIC_INIT;
1645            else if ((flags() & BLOCK) != 0)
1646                return isStatic() ? ElementKind.STATIC_INIT : ElementKind.INSTANCE_INIT;
1647            else
1648                return ElementKind.METHOD;
1649        }
1650
1651        public boolean isStaticOrInstanceInit() {
1652            return getKind() == ElementKind.STATIC_INIT ||
1653                    getKind() == ElementKind.INSTANCE_INIT;
1654        }
1655
1656        @DefinedBy(Api.LANGUAGE_MODEL)
1657        public Attribute getDefaultValue() {
1658            return defaultValue;
1659        }
1660
1661        @DefinedBy(Api.LANGUAGE_MODEL)
1662        public List<VarSymbol> getParameters() {
1663            return params();
1664        }
1665
1666        @DefinedBy(Api.LANGUAGE_MODEL)
1667        public boolean isVarArgs() {
1668            return (flags() & VARARGS) != 0;
1669        }
1670
1671        @DefinedBy(Api.LANGUAGE_MODEL)
1672        public boolean isDefault() {
1673            return (flags() & DEFAULT) != 0;
1674        }
1675
1676        @DefinedBy(Api.LANGUAGE_MODEL)
1677        public <R, P> R accept(ElementVisitor<R, P> v, P p) {
1678            return v.visitExecutable(this, p);
1679        }
1680
1681        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
1682            return v.visitMethodSymbol(this, p);
1683        }
1684
1685        @DefinedBy(Api.LANGUAGE_MODEL)
1686        public Type getReceiverType() {
1687            return asType().getReceiverType();
1688        }
1689
1690        @DefinedBy(Api.LANGUAGE_MODEL)
1691        public Type getReturnType() {
1692            return asType().getReturnType();
1693        }
1694
1695        @DefinedBy(Api.LANGUAGE_MODEL)
1696        public List<Type> getThrownTypes() {
1697            return asType().getThrownTypes();
1698        }
1699    }
1700
1701    /** A class for invokedynamic method calls.
1702     */
1703    public static class DynamicMethodSymbol extends MethodSymbol {
1704
1705        public Object[] staticArgs;
1706        public Symbol bsm;
1707        public int bsmKind;
1708
1709        public DynamicMethodSymbol(Name name, Symbol owner, int bsmKind, MethodSymbol bsm, Type type, Object[] staticArgs) {
1710            super(0, name, type, owner);
1711            this.bsm = bsm;
1712            this.bsmKind = bsmKind;
1713            this.staticArgs = staticArgs;
1714        }
1715
1716        @Override
1717        public boolean isDynamic() {
1718            return true;
1719        }
1720    }
1721
1722    /** A class for predefined operators.
1723     */
1724    public static class OperatorSymbol extends MethodSymbol {
1725
1726        public int opcode;
1727
1728        public OperatorSymbol(Name name, Type type, int opcode, Symbol owner) {
1729            super(PUBLIC | STATIC, name, type, owner);
1730            this.opcode = opcode;
1731        }
1732
1733        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
1734            return v.visitOperatorSymbol(this, p);
1735        }
1736    }
1737
1738    /** Symbol completer interface.
1739     */
1740    public static interface Completer {
1741        void complete(Symbol sym) throws CompletionFailure;
1742    }
1743
1744    public static class CompletionFailure extends RuntimeException {
1745        private static final long serialVersionUID = 0;
1746        public Symbol sym;
1747
1748        /** A diagnostic object describing the failure
1749         */
1750        public JCDiagnostic diag;
1751
1752        /** A localized string describing the failure.
1753         * @deprecated Use {@code getDetail()} or {@code getMessage()}
1754         */
1755        @Deprecated
1756        public String errmsg;
1757
1758        public CompletionFailure(Symbol sym, String errmsg) {
1759            this.sym = sym;
1760            this.errmsg = errmsg;
1761//          this.printStackTrace();//DEBUG
1762        }
1763
1764        public CompletionFailure(Symbol sym, JCDiagnostic diag) {
1765            this.sym = sym;
1766            this.diag = diag;
1767//          this.printStackTrace();//DEBUG
1768        }
1769
1770        public JCDiagnostic getDiagnostic() {
1771            return diag;
1772        }
1773
1774        @Override
1775        public String getMessage() {
1776            if (diag != null)
1777                return diag.getMessage(null);
1778            else
1779                return errmsg;
1780        }
1781
1782        public Object getDetailValue() {
1783            return (diag != null ? diag : errmsg);
1784        }
1785
1786        @Override
1787        public CompletionFailure initCause(Throwable cause) {
1788            super.initCause(cause);
1789            return this;
1790        }
1791
1792    }
1793
1794    /**
1795     * A visitor for symbols.  A visitor is used to implement operations
1796     * (or relations) on symbols.  Most common operations on types are
1797     * binary relations and this interface is designed for binary
1798     * relations, that is, operations on the form
1799     * Symbol&nbsp;&times;&nbsp;P&nbsp;&rarr;&nbsp;R.
1800     * <!-- In plain text: Type x P -> R -->
1801     *
1802     * @param <R> the return type of the operation implemented by this
1803     * visitor; use Void if no return type is needed.
1804     * @param <P> the type of the second argument (the first being the
1805     * symbol itself) of the operation implemented by this visitor; use
1806     * Void if a second argument is not needed.
1807     */
1808    public interface Visitor<R,P> {
1809        R visitClassSymbol(ClassSymbol s, P arg);
1810        R visitMethodSymbol(MethodSymbol s, P arg);
1811        R visitPackageSymbol(PackageSymbol s, P arg);
1812        R visitOperatorSymbol(OperatorSymbol s, P arg);
1813        R visitVarSymbol(VarSymbol s, P arg);
1814        R visitTypeSymbol(TypeSymbol s, P arg);
1815        R visitSymbol(Symbol s, P arg);
1816    }
1817}
1818