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