1 /*
2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
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_VAR(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 
240         private final String name;
241 
KindName(String name)242         KindName(String name) {
243             this.name = name;
244         }
245 
toString()246         public String toString() {
247             return name;
248         }
249 
getKind()250         public String getKind() {
251             return "Kindname";
252         }
253 
toString(Locale locale, Messages messages)254         public String toString(Locale locale, Messages messages) {
255             String s = toString();
256             return messages.getLocalizedString(locale, "compiler.misc." + s);
257         }
258     }
259 
kindName(MemberReferenceTree.ReferenceMode mode)260     public static KindName kindName(MemberReferenceTree.ReferenceMode mode) {
261         switch (mode) {
262             case INVOKE: return KindName.METHOD;
263             case NEW: return KindName.CONSTRUCTOR;
264             default : throw new AssertionError("Unexpected mode: "+ mode);
265         }
266     }
267 
268     /** A KindName representing a given symbol
269      */
kindName(Symbol sym)270     public static KindName kindName(Symbol sym) {
271         switch (sym.getKind()) {
272         case PACKAGE:
273             return KindName.PACKAGE;
274 
275         case ENUM:
276             return KindName.ENUM;
277 
278         case ANNOTATION_TYPE:
279         case CLASS:
280             return KindName.CLASS;
281 
282         case INTERFACE:
283             return KindName.INTERFACE;
284 
285         case TYPE_PARAMETER:
286             return KindName.TYPEVAR;
287 
288         case ENUM_CONSTANT:
289         case FIELD:
290         case PARAMETER:
291         case LOCAL_VARIABLE:
292         case EXCEPTION_PARAMETER:
293         case RESOURCE_VARIABLE:
294             return KindName.VAR;
295 
296         case CONSTRUCTOR:
297             return KindName.CONSTRUCTOR;
298 
299         case METHOD:
300             return KindName.METHOD;
301         case STATIC_INIT:
302             return KindName.STATIC_INIT;
303         case INSTANCE_INIT:
304             return KindName.INSTANCE_INIT;
305 
306         default:
307                 throw new AssertionError("Unexpected kind: "+sym.getKind());
308         }
309     }
310 
311     /** A KindName representing the kind of a given class/interface type.
312      */
typeKindName(Type t)313     public static KindName typeKindName(Type t) {
314         if (t.hasTag(TYPEVAR) ||
315             t.hasTag(CLASS) && (t.tsym.flags() & COMPOUND) != 0)
316             return KindName.BOUND;
317         else if (t.hasTag(PACKAGE))
318             return KindName.PACKAGE;
319         else if ((t.tsym.flags_field & ANNOTATION) != 0)
320             return KindName.ANNOTATION;
321         else if ((t.tsym.flags_field & INTERFACE) != 0)
322             return KindName.INTERFACE;
323         else
324             return KindName.CLASS;
325     }
326 
327 }
328