Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/java/Identifier.java
38918 views
1
/*
2
* Copyright (c) 1994, 2003, 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 sun.tools.java;
27
28
import java.util.Hashtable;
29
import java.io.PrintStream;
30
import java.util.Enumeration;
31
32
/**
33
* A class to represent identifiers.<p>
34
*
35
* An identifier instance is very similar to a String. The difference
36
* is that identifier can't be instanciated directly, instead they are
37
* looked up in a hash table. This means that identifiers with the same
38
* name map to the same identifier object. This makes comparisons of
39
* identifiers much faster.<p>
40
*
41
* A lot of identifiers are qualified, that is they have '.'s in them.
42
* Each qualified identifier is chopped up into the qualifier and the
43
* name. The qualifier is cached in the value field.<p>
44
*
45
* Unqualified identifiers can have a type. This type is an integer that
46
* can be used by a scanner as a token value. This value has to be set
47
* using the setType method.<p>
48
*
49
* WARNING: The contents of this source file are not part of any
50
* supported API. Code that depends on them does so at its own risk:
51
* they are subject to change or removal without notice.
52
*
53
* @author Arthur van Hoff
54
*/
55
56
public final
57
class Identifier implements Constants {
58
/**
59
* The hashtable of identifiers
60
*/
61
static Hashtable hash = new Hashtable(3001, 0.5f);
62
63
/**
64
* The name of the identifier
65
*/
66
String name;
67
68
/**
69
* The value of the identifier, for keywords this is an
70
* instance of class Integer, for qualified names this is
71
* another identifier (the qualifier).
72
*/
73
Object value;
74
75
/**
76
* The Type which corresponds to this Identifier. This is used as
77
* cache for Type.tClass() and shouldn't be used outside of that
78
* context.
79
*/
80
Type typeObject = null;
81
82
/**
83
* The index of INNERCLASS_PREFIX in the name, or -1 if none.
84
*/
85
private int ipos;
86
87
/**
88
* Construct an identifier. Don't call this directly,
89
* use lookup instead.
90
* @see Identifier.lookup
91
*/
92
private Identifier(String name) {
93
this.name = name;
94
this.ipos = name.indexOf(INNERCLASS_PREFIX);
95
}
96
97
/**
98
* Get the type of the identifier.
99
*/
100
int getType() {
101
return ((value != null) && (value instanceof Integer)) ?
102
((Integer)value).intValue() : IDENT;
103
}
104
105
/**
106
* Set the type of the identifier.
107
*/
108
void setType(int t) {
109
value = new Integer(t);
110
//System.out.println("type(" + this + ")=" + t);
111
}
112
113
/**
114
* Lookup an identifier.
115
*/
116
public static synchronized Identifier lookup(String s) {
117
//System.out.println("lookup(" + s + ")");
118
Identifier id = (Identifier)hash.get(s);
119
if (id == null) {
120
hash.put(s, id = new Identifier(s));
121
}
122
return id;
123
}
124
125
/**
126
* Lookup a qualified identifier.
127
*/
128
public static Identifier lookup(Identifier q, Identifier n) {
129
// lookup("", x) => x
130
if (q == idNull) return n;
131
// lookup(lookupInner(c, ""), n) => lookupInner(c, lookup("", n))
132
if (q.name.charAt(q.name.length()-1) == INNERCLASS_PREFIX)
133
return lookup(q.name+n.name);
134
Identifier id = lookup(q + "." + n);
135
if (!n.isQualified() && !q.isInner())
136
id.value = q;
137
return id;
138
}
139
140
/**
141
* Lookup an inner identifier.
142
* (Note: n can be idNull.)
143
*/
144
public static Identifier lookupInner(Identifier c, Identifier n) {
145
Identifier id;
146
if (c.isInner()) {
147
if (c.name.charAt(c.name.length()-1) == INNERCLASS_PREFIX)
148
id = lookup(c.name+n);
149
else
150
id = lookup(c, n);
151
} else {
152
id = lookup(c + "." + INNERCLASS_PREFIX + n);
153
}
154
id.value = c.value;
155
return id;
156
}
157
158
/**
159
* Convert to a string.
160
*/
161
public String toString() {
162
return name;
163
}
164
165
/**
166
* Check if the name is qualified (ie: it contains a '.').
167
*/
168
public boolean isQualified() {
169
if (value == null) {
170
int idot = ipos;
171
if (idot <= 0)
172
idot = name.length();
173
else
174
idot -= 1; // back up over previous dot
175
int index = name.lastIndexOf('.', idot-1);
176
value = (index < 0) ? idNull : Identifier.lookup(name.substring(0, index));
177
}
178
return (value instanceof Identifier) && (value != idNull);
179
}
180
181
/**
182
* Return the qualifier. The null identifier is returned if
183
* the name was not qualified. The qualifier does not include
184
* any inner part of the name.
185
*/
186
public Identifier getQualifier() {
187
return isQualified() ? (Identifier)value : idNull;
188
}
189
190
/**
191
* Return the unqualified name.
192
* In the case of an inner name, the unqualified name
193
* will itself contain components.
194
*/
195
public Identifier getName() {
196
return isQualified() ?
197
Identifier.lookup(name.substring(((Identifier)value).name.length() + 1)) : this;
198
}
199
200
/** A space character, which precedes the first inner class
201
* name in a qualified name, and thus marks the qualification
202
* as involving inner classes, instead of merely packages.<p>
203
* Ex: <tt>java.util.Vector. Enumerator</tt>.
204
*/
205
public static final char INNERCLASS_PREFIX = ' ';
206
207
/* Explanation:
208
* Since much of the compiler's low-level name resolution code
209
* operates in terms of Identifier objects. This includes the
210
* code which walks around the file system and reports what
211
* classes are where. It is important to get nesting information
212
* right as early as possible, since it affects the spelling of
213
* signatures. Thus, the low-level import and resolve code must
214
* be able Identifier type must be able to report the nesting
215
* of types, which implied that that information must be carried
216
* by Identifiers--or that the low-level interfaces be significantly
217
* changed.
218
*/
219
220
/**
221
* Check if the name is inner (ie: it contains a ' ').
222
*/
223
public boolean isInner() {
224
return (ipos > 0);
225
}
226
227
/**
228
* Return the class name, without its qualifier,
229
* and with any nesting flattened into a new qualfication structure.
230
* If the original identifier is inner,
231
* the result will be qualified, and can be further
232
* decomposed by means of <tt>getQualifier</tt> and <tt>getName</tt>.
233
* <p>
234
* For example:
235
* <pre>
236
* Identifier id = Identifier.lookup("pkg.Foo. Bar");
237
* id.getName().name => "Foo. Bar"
238
* id.getFlatName().name => "Foo.Bar"
239
* </pre>
240
*/
241
public Identifier getFlatName() {
242
if (isQualified()) {
243
return getName().getFlatName();
244
}
245
if (ipos > 0 && name.charAt(ipos-1) == '.') {
246
if (ipos+1 == name.length()) {
247
// last component is idNull
248
return Identifier.lookup(name.substring(0,ipos-1));
249
}
250
String n = name.substring(ipos+1);
251
String t = name.substring(0,ipos);
252
return Identifier.lookup(t+n);
253
}
254
// Not inner. Just return the same as getName()
255
return this;
256
}
257
258
public Identifier getTopName() {
259
if (!isInner()) return this;
260
return Identifier.lookup(getQualifier(), getFlatName().getHead());
261
}
262
263
/**
264
* Yet another way to slice qualified identifiers:
265
* The head of an identifier is its first qualifier component,
266
* and the tail is the rest of them.
267
*/
268
public Identifier getHead() {
269
Identifier id = this;
270
while (id.isQualified())
271
id = id.getQualifier();
272
return id;
273
}
274
275
/**
276
* @see getHead
277
*/
278
public Identifier getTail() {
279
Identifier id = getHead();
280
if (id == this)
281
return idNull;
282
else
283
return Identifier.lookup(name.substring(id.name.length() + 1));
284
}
285
286
// Unfortunately, the current structure of the compiler requires
287
// that the resolveName() family of methods (which appear in
288
// Environment.java, Context.java, and ClassDefinition.java) raise
289
// no exceptions and emit no errors. When we are in resolveName()
290
// and we find a method that is ambiguous, we need to
291
// unambiguously mark it as such, so that later stages of the
292
// compiler realize that they should give an ambig.class rather than
293
// a class.not.found error. To mark it we add a special prefix
294
// which cannot occur in the program source. The routines below
295
// are used to check, add, and remove this prefix.
296
// (part of solution for 4059855).
297
298
/**
299
* A special prefix to add to ambiguous names.
300
*/
301
private static final String ambigPrefix = "<<ambiguous>>";
302
303
/**
304
* Determine whether an Identifier has been marked as ambiguous.
305
*/
306
public boolean hasAmbigPrefix() {
307
return (name.startsWith(ambigPrefix));
308
}
309
310
/**
311
* Add ambigPrefix to `this' to make a new Identifier marked as
312
* ambiguous. It is important that this new Identifier not refer
313
* to an existing class.
314
*/
315
public Identifier addAmbigPrefix() {
316
return Identifier.lookup(ambigPrefix + name);
317
}
318
319
/**
320
* Remove the ambigPrefix from `this' to get the original identifier.
321
*/
322
public Identifier removeAmbigPrefix() {
323
if (hasAmbigPrefix()) {
324
return Identifier.lookup(name.substring(ambigPrefix.length()));
325
} else {
326
return this;
327
}
328
}
329
}
330
331