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