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