1 /*
2  * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.tools.javac.code;
27 
28 import java.util.EnumSet;
29 import java.util.Set;
30 import java.util.Locale;
31 
32 import com.sun.source.tree.MemberReferenceTree;
33 import com.sun.tools.javac.api.Formattable;
34 import com.sun.tools.javac.api.Messages;
35 
36 import static com.sun.tools.javac.code.Flags.*;
37 import static com.sun.tools.javac.code.TypeTag.CLASS;
38 import static com.sun.tools.javac.code.TypeTag.PACKAGE;
39 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
40 
41 /** Internal symbol kinds, which distinguish between elements of
42  *  different subclasses of Symbol. Symbol kinds are organized so they can be
43  *  or'ed to sets.
44  *
45  *  <p><b>This is NOT part of any supported API.
46  *  If you write code that depends on this, you do so at your own risk.
47  *  This code and its internal interfaces are subject to change or
48  *  deletion without notice.</b>
49  */
50 public class Kinds {
51 
Kinds()52     private Kinds() {} // uninstantiable
53 
54     /**
55      * Kind of symbols.
56      *
57      * IMPORTANT: This is an ordered type.  The ordering of
58      * declarations in this enum matters.  Be careful when changing
59      * it.
60      */
61     public enum Kind {
62         NIL(Category.BASIC, KindSelector.NIL),
63         PCK(Category.BASIC, KindName.PACKAGE, KindSelector.PCK),
64         TYP(Category.BASIC, KindName.CLASS, KindSelector.TYP),
65         VAR(Category.BASIC, KindName.VAR, KindSelector.VAR),
66         MTH(Category.BASIC, KindName.METHOD, KindSelector.MTH),
67         POLY(Category.BASIC, KindSelector.POLY),
68         MDL(Category.BASIC, KindSelector.MDL),
69         ERR(Category.ERROR, KindSelector.ERR),
70         AMBIGUOUS(Category.RESOLUTION_TARGET),                         // overloaded       target
71         HIDDEN(Category.RESOLUTION_TARGET),                            // not overloaded   non-target
72         STATICERR(Category.RESOLUTION_TARGET),                         // overloaded?      target
73         MISSING_ENCL(Category.RESOLUTION),                             // not overloaded   non-target
74         BAD_RESTRICTED_TYPE(Category.RESOLUTION),                      // not overloaded   non-target
75         ABSENT_VAR(Category.RESOLUTION_TARGET, KindName.VAR),          // not overloaded   non-target
76         WRONG_MTHS(Category.RESOLUTION_TARGET, KindName.METHOD),       // overloaded       target
77         WRONG_MTH(Category.RESOLUTION_TARGET, KindName.METHOD),        // not overloaded   target
78         ABSENT_MTH(Category.RESOLUTION_TARGET, KindName.METHOD),       // not overloaded   non-target
79         ABSENT_TYP(Category.RESOLUTION_TARGET, KindName.CLASS);        // not overloaded   non-target
80 
81         // There are essentially two "levels" to the Kind datatype.
82         // The first is a totally-ordered set of categories of
83         // solutions.  Within each category, we have more
84         // possibilities.
85         private enum Category {
86             BASIC, ERROR, RESOLUTION, RESOLUTION_TARGET;
87         }
88 
89         private final KindName kindName;
90         private final KindName absentKind;
91         private final KindSelector selector;
92         private final Category category;
93 
Kind(Category category)94         private Kind(Category category) {
95             this(category, null, null, null);
96         }
97 
Kind(Category category, KindSelector selector)98         private Kind(Category category,
99                      KindSelector selector) {
100             this(category, null, null, selector);
101         }
102 
Kind(Category category, KindName absentKind)103         private Kind(Category category,
104                      KindName absentKind) {
105             this(category, null, absentKind, null);
106         }
107 
Kind(Category category, KindName kindName, KindSelector selector)108         private Kind(Category category,
109                      KindName kindName,
110                      KindSelector selector) {
111             this(category, kindName, null, selector);
112         }
113 
Kind(Category category, KindName kindName, KindName absentKind, KindSelector selector)114         private Kind(Category category,
115                      KindName kindName,
116                      KindName absentKind,
117                      KindSelector selector) {
118             this.category = category;
119             this.kindName = kindName;
120             this.absentKind = absentKind;
121             this.selector = selector;
122         }
123 
toSelector()124         public KindSelector toSelector() {
125             return selector;
126         }
127 
matches(KindSelector kindSelectors)128         public boolean matches(KindSelector kindSelectors) {
129             return selector.contains(kindSelectors);
130         }
131 
isResolutionError()132         public boolean isResolutionError() {
133             return category == Category.RESOLUTION || category == Category.RESOLUTION_TARGET;
134         }
135 
isResolutionTargetError()136         public boolean isResolutionTargetError() {
137             return category == Category.RESOLUTION_TARGET;
138         }
139 
isValid()140         public boolean isValid() {
141             return category == Category.BASIC;
142         }
143 
betterThan(Kind other)144         public boolean betterThan(Kind other) {
145             return ordinal() < other.ordinal();
146         }
147 
kindName()148         public KindName kindName() {
149             if (kindName == null) {
150                 throw new AssertionError("Unexpected kind: " + this);
151             } else {
152                 return kindName;
153             }
154         }
155 
absentKind()156         public KindName absentKind() {
157             if (absentKind == null) {
158                 throw new AssertionError("Unexpected kind: " + this);
159             } else {
160                 return absentKind;
161             }
162         }
163     }
164 
165     public static class KindSelector {
166 
167         //basic selectors
168         public static final KindSelector NIL = new KindSelector(0);
169         public static final KindSelector PCK = new KindSelector(0x01);
170         public static final KindSelector TYP = new KindSelector(0x02);
171         public static final KindSelector VAR = new KindSelector(0x04);
172         public static final KindSelector VAL = new KindSelector(0x0c);
173         public static final KindSelector MTH = new KindSelector(0x10);
174         public static final KindSelector POLY = new KindSelector(0x20);
175         public static final KindSelector MDL = new KindSelector(0x40);
176         public static final KindSelector ERR = new KindSelector(0x7f);
177         public static final KindSelector ASG = new KindSelector(0x84);
178 
179         //common derived selectors
180         public static final KindSelector TYP_PCK = of(TYP, PCK);
181         public static final KindSelector VAL_MTH = of(VAL, MTH);
182         public static final KindSelector VAL_POLY = of(VAL, POLY);
183         public static final KindSelector VAL_TYP = of(VAL, TYP);
184         public static final KindSelector VAL_TYP_PCK = of(VAL, TYP, PCK);
185 
186         private final byte data;
187 
KindSelector(int data)188         private KindSelector(int data) {
189             this.data = (byte) data;
190         }
191 
of(KindSelector... kindSelectors)192         public static KindSelector of(KindSelector... kindSelectors) {
193             byte newData = 0;
194             for (KindSelector kindSel : kindSelectors) {
195                 newData |= kindSel.data;
196             }
197             return new KindSelector(newData);
198         }
199 
subset(KindSelector other)200         public boolean subset(KindSelector other) {
201             return (data & ~other.data) == 0;
202         }
203 
contains(KindSelector other)204         public boolean contains(KindSelector other) {
205             return (data & other.data) != 0;
206         }
207 
208         /** A set of KindName(s) representing a set of symbol's kinds. */
kindNames()209         public Set<KindName> kindNames() {
210             EnumSet<KindName> kinds = EnumSet.noneOf(KindName.class);
211             if ((data & VAL.data) != 0) {
212                 if ((data & VAL.data) == VAR.data) kinds.add(KindName.VAR);
213                 else kinds.add(KindName.VAL);
214             }
215             if ((data & MTH.data) != 0) kinds.add(KindName.METHOD);
216             if ((data & TYP.data) != 0) kinds.add(KindName.CLASS);
217             if ((data & PCK.data) != 0) kinds.add(KindName.PACKAGE);
218             if ((data & MDL.data) != 0) kinds.add(KindName.MODULE);
219             return kinds;
220         }
221     }
222 
223     public enum KindName implements Formattable {
224         ANNOTATION("kindname.annotation"),
225         CONSTRUCTOR("kindname.constructor"),
226         INTERFACE("kindname.interface"),
227         ENUM("kindname.enum"),
228         STATIC("kindname.static"),
229         TYPEVAR("kindname.type.variable"),
230         BOUND("kindname.type.variable.bound"),
231         VAR("kindname.variable"),
232         VAL("kindname.value"),
233         METHOD("kindname.method"),
234         CLASS("kindname.class"),
235         STATIC_INIT("kindname.static.init"),
236         INSTANCE_INIT("kindname.instance.init"),
237         PACKAGE("kindname.package"),
238         MODULE("kindname.module"),
239         RECORD_COMPONENT("kindname.record.component"),
240         RECORD("kindname.record");
241 
242         private final String name;
243 
KindName(String name)244         KindName(String name) {
245             this.name = name;
246         }
247 
toString()248         public String toString() {
249             return name;
250         }
251 
getKind()252         public String getKind() {
253             return "Kindname";
254         }
255 
toString(Locale locale, Messages messages)256         public String toString(Locale locale, Messages messages) {
257             String s = toString();
258             return messages.getLocalizedString(locale, "compiler.misc." + s);
259         }
260     }
261 
kindName(MemberReferenceTree.ReferenceMode mode)262     public static KindName kindName(MemberReferenceTree.ReferenceMode mode) {
263         switch (mode) {
264             case INVOKE: return KindName.METHOD;
265             case NEW: return KindName.CONSTRUCTOR;
266             default : throw new AssertionError("Unexpected mode: "+ mode);
267         }
268     }
269 
270     /** A KindName representing a given symbol
271      */
kindName(Symbol sym)272     public static KindName kindName(Symbol sym) {
273         switch (sym.getKind()) {
274         case PACKAGE:
275             return KindName.PACKAGE;
276 
277         case ENUM:
278             return KindName.ENUM;
279 
280         case ANNOTATION_TYPE:
281         case CLASS:
282             return KindName.CLASS;
283 
284         case RECORD:
285             return KindName.RECORD;
286 
287         case INTERFACE:
288             return KindName.INTERFACE;
289 
290         case TYPE_PARAMETER:
291             return KindName.TYPEVAR;
292 
293         case BINDING_VARIABLE:
294         case ENUM_CONSTANT:
295         case PARAMETER:
296         case LOCAL_VARIABLE:
297         case EXCEPTION_PARAMETER:
298         case RESOURCE_VARIABLE:
299             return KindName.VAR;
300 
301         case FIELD:
302             return ((sym.flags_field & RECORD) != 0) ? KindName.RECORD_COMPONENT : KindName.VAR;
303 
304         case CONSTRUCTOR:
305             return KindName.CONSTRUCTOR;
306 
307         case METHOD:
308             return KindName.METHOD;
309         case STATIC_INIT:
310             return KindName.STATIC_INIT;
311         case INSTANCE_INIT:
312             return KindName.INSTANCE_INIT;
313 
314         default:
315                 throw new AssertionError("Unexpected kind: "+sym.getKind());
316         }
317     }
318 
319     /** A KindName representing the kind of a given class/interface type.
320      */
typeKindName(Type t)321     public static KindName typeKindName(Type t) {
322         if (t.hasTag(TYPEVAR) ||
323             t.hasTag(CLASS) && (t.tsym.flags() & COMPOUND) != 0)
324             return KindName.BOUND;
325         else if (t.hasTag(PACKAGE))
326             return KindName.PACKAGE;
327         else if ((t.tsym.flags_field & ANNOTATION) != 0)
328             return KindName.ANNOTATION;
329         else if ((t.tsym.flags_field & INTERFACE) != 0)
330             return KindName.INTERFACE;
331         else
332             return KindName.CLASS;
333     }
334 
335 }
336