KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > jl > types > ClassType_c


1 package polyglot.ext.jl.types;
2
3 import java.util.Collection JavaDoc;
4 import java.util.Iterator JavaDoc;
5 import java.util.List JavaDoc;
6
7 import polyglot.types.ClassType;
8 import polyglot.types.FieldInstance;
9 import polyglot.types.Flags;
10 import polyglot.types.Named;
11 import polyglot.types.Package;
12 import polyglot.types.ReferenceType;
13 import polyglot.types.Resolver;
14 import polyglot.types.SemanticException;
15 import polyglot.types.Type;
16 import polyglot.types.TypeSystem;
17 import polyglot.util.InternalCompilerError;
18 import polyglot.util.Position;
19
20 /**
21  * A <code>ClassType</code> represents a class -- either loaded from a
22  * classpath, parsed from a source file, or obtained from other source.
23  */

24 public abstract class ClassType_c extends ReferenceType_c implements ClassType
25 {
26     /** Used for deserializing types. */
27     protected ClassType_c() { }
28
29     public ClassType_c(TypeSystem ts) {
30     this(ts, null);
31     }
32
33     public ClassType_c(TypeSystem ts, Position pos) {
34     super(ts, pos);
35     }
36
37     /** Get the class's kind. */
38     public abstract Kind kind();
39
40     /** Get the class's outer class, or null if a top-level class. */
41     public abstract ClassType outer();
42
43     /** Get the short name of the class, if possible. */
44     public abstract String JavaDoc name();
45
46     /** Get the container class if a member class. */
47     public ReferenceType container() {
48         if (! isMember())
49             throw new InternalCompilerError("Non-member classes cannot have container classes.");
50         if (outer() == null)
51             throw new InternalCompilerError("Nested classes must have outer classes.");
52         return outer();
53     }
54
55     /** Get the full name of the class, if possible. */
56     public String JavaDoc fullName() {
57         String JavaDoc name;
58         if (isAnonymous()) {
59             if (superType() != null) {
60                 name = "<anon subtype of " + superType().toString() + ">";
61             }
62             else {
63                 name = "<anon subtype of unknown>";
64             }
65         }
66         else {
67             name = name();
68         }
69         if (isTopLevel() && package_() != null) {
70             return package_().fullName() + "." + name;
71         }
72         else if (isMember() && container() instanceof Named) {
73             return ((Named) container()).fullName() + "." + name;
74         }
75         else {
76             return name;
77         }
78     }
79
80     public boolean isTopLevel() { return kind() == TOP_LEVEL; }
81     public boolean isMember() { return kind() == MEMBER; }
82     public boolean isLocal() { return kind() == LOCAL; }
83     public boolean isAnonymous() { return kind() == ANONYMOUS; }
84
85     /**
86     * @deprecated Was incorrectly defined. Use isNested for nested classes,
87     * and isInnerClass for inner classes.
88     */

89     public final boolean isInner() {
90         return isNested();
91     }
92
93     public boolean isNested() {
94         // Implement this way rather than with ! isTopLevel() so that
95
// extensions can add more kinds.
96
return kind() == MEMBER || kind() == LOCAL || kind() == ANONYMOUS;
97     }
98     
99     public boolean isInnerClass() {
100         // it's an inner class if it is not an interface, it is a nested
101
// class, and it is not explicitly or implicitly static.
102
return !flags().isInterface() && isNested() && !flags().isStatic() && !inStaticContext();
103     }
104     
105     public boolean isCanonical() { return true; }
106     public boolean isClass() { return true; }
107     public ClassType toClass() { return this; }
108
109     /** Get the class's package. */
110     public abstract Package JavaDoc package_();
111
112     /** Get the class's flags. */
113     public abstract Flags flags();
114
115     /** Get the class's constructors. */
116     public abstract List JavaDoc constructors();
117
118     /** Get the class's member classes. */
119     public abstract List JavaDoc memberClasses();
120
121     /** Get the class's methods. */
122     public abstract List JavaDoc methods();
123
124     /** Get the class's fields. */
125     public abstract List JavaDoc fields();
126
127     /** Get the class's interfaces. */
128     public abstract List JavaDoc interfaces();
129
130     /** Get the class's super type. */
131     public abstract Type superType();
132
133     /** Get a field of the class by name. */
134     public FieldInstance fieldNamed(String JavaDoc name) {
135         for (Iterator JavaDoc i = fields().iterator(); i.hasNext(); ) {
136         FieldInstance fi = (FieldInstance) i.next();
137         if (fi.name().equals(name)) {
138             return fi;
139         }
140     }
141
142     return null;
143     }
144
145     /** Get a member class of the class by name. */
146     public ClassType memberClassNamed(String JavaDoc name) {
147         for (Iterator JavaDoc i = memberClasses().iterator(); i.hasNext(); ) {
148         ClassType t = (ClassType) i.next();
149         if (t.name().equals(name)) {
150             return t;
151         }
152     }
153
154     return null;
155     }
156
157     public boolean descendsFromImpl(Type ancestor) {
158         if (! ancestor.isCanonical()) {
159             return false;
160         }
161
162         if (ancestor.isNull()) {
163             return false;
164         }
165
166         if (ts.equals(this, ancestor)) {
167             return false;
168         }
169
170         if (! ancestor.isReference()) {
171             return false;
172         }
173
174         if (ts.equals(ancestor, ts.Object())) {
175             return true;
176         }
177
178         // Check subtype relation for classes.
179
if (! flags().isInterface()) {
180             if (ts.equals(this, ts.Object())) {
181                 return false;
182             }
183
184             if (superType() == null) {
185                 return false;
186             }
187
188             if (ts.isSubtype(superType(), ancestor)) {
189                 return true;
190             }
191         }
192
193         // Next check interfaces.
194
for (Iterator JavaDoc i = interfaces().iterator(); i.hasNext(); ) {
195             Type parentType = (Type) i.next();
196
197             if (ts.isSubtype(parentType, ancestor)) {
198                 return true;
199             }
200         }
201
202         return false;
203     }
204
205     public boolean isThrowable() {
206         return ts.isSubtype(this, ts.Throwable());
207     }
208
209     public boolean isUncheckedException() {
210         if (isThrowable()) {
211             Collection JavaDoc c = ts.uncheckedExceptions();
212                                   
213             for (Iterator JavaDoc i = c.iterator(); i.hasNext(); ) {
214                 Type t = (Type) i.next();
215
216                 if (ts.isSubtype(this, t)) {
217                     return true;
218                 }
219             }
220         }
221
222         return false;
223     }
224
225     public boolean isImplicitCastValidImpl(Type toType) {
226         if (! toType.isClass()) return false;
227         return ts.isSubtype(this, toType);
228     }
229
230     /**
231      * Requires: all type arguments are canonical. ToType is not a NullType.
232      *
233      * Returns true iff a cast from this to toType is valid; in other
234      * words, some non-null members of this are also members of toType.
235      **/

236     public boolean isCastValidImpl(Type toType) {
237     if (! toType.isCanonical()) return false;
238     if (! toType.isReference()) return false;
239
240     if (toType.isArray()) {
241         // Ancestor is not an array, but child is. Check if the array
242
// is a subtype of the ancestor. This happens when ancestor
243
// is java.lang.Object.
244
return ts.isSubtype(toType, this);
245     }
246
247     // Both types should be classes now.
248
if (! toType.isClass()) return false;
249
250     // From and to are neither primitive nor an array. They are distinct.
251
boolean fromInterface = flags().isInterface();
252     boolean toInterface = toType.toClass().flags().isInterface();
253     boolean fromFinal = flags().isFinal();
254     boolean toFinal = toType.toClass().flags().isFinal();
255
256     // This is taken from Section 5.5 of the JLS.
257
if (! fromInterface) {
258         // From is not an interface.
259
if (! toInterface) {
260         // Nether from nor to is an interface.
261
return ts.isSubtype(this, toType) || ts.isSubtype(toType, this);
262         }
263
264         if (fromFinal) {
265         // From is a final class, and to is an interface
266
return ts.isSubtype(this, toType);
267         }
268
269         // From is a non-final class, and to is an interface.
270
return true;
271     }
272     else {
273         // From is an interface
274
if (! toInterface && ! toFinal) {
275         // To is a non-final class.
276
return true;
277         }
278
279         if (toFinal) {
280         // To is a final class.
281
return ts.isSubtype(toType, this);
282         }
283
284         // To and From are both interfaces.
285
return true;
286     }
287     }
288
289     public final boolean isEnclosed(ClassType maybe_outer) {
290         return ts.isEnclosed(this, maybe_outer);
291     }
292
293     public final boolean hasEnclosingInstance(ClassType encl) {
294         return ts.hasEnclosingInstance(this, encl);
295     }
296
297     public String JavaDoc translate(Resolver c) {
298         if (isTopLevel()) {
299             if (package_() == null) {
300                 return name();
301             }
302
303             // Use the short name if it is unique.
304
if (c != null) {
305                 try {
306                     Named x = c.find(name());
307
308                     if (ts.equals(this, x)) {
309                         return name();
310                     }
311                 }
312                 catch (SemanticException e) {
313                 }
314             }
315
316             return package_().translate(c) + "." + name();
317         }
318         else if (isMember()) {
319             // Use only the short name if the outer class is anonymous.
320
if (container().toClass().isAnonymous()) {
321                 return name();
322             }
323
324             // Use the short name if it is unique.
325
if (c != null) {
326                 try {
327                     Named x = c.find(name());
328
329                     if (ts.equals(this, x)) {
330                         return name();
331                     }
332                 }
333                 catch (SemanticException e) {
334                 }
335             }
336
337             return container().translate(c) + "." + name();
338         }
339         else if (isLocal()) {
340             return name();
341         }
342         else {
343             throw new InternalCompilerError("Cannot translate an anonymous class.");
344         }
345     }
346
347     public String JavaDoc toString() {
348         if (isTopLevel()) {
349             if (package_() != null) {
350                 return package_().toString() + "." + name();
351             }
352
353             return name();
354         }
355         else if (isMember()) {
356             return container().toString() + "." + name();
357         }
358         else if (isLocal()) {
359             return name();
360         }
361         else {
362             if (superType() != null) {
363                 return "<anon subtype of " + superType().toString() + ">";
364             }
365             else {
366                 return "<anon subtype of unknown>";
367             }
368         }
369     }
370
371     public boolean isEnclosedImpl(ClassType maybe_outer) {
372         if (isTopLevel())
373             return false;
374         else if (outer() != null)
375             return outer().equals(maybe_outer) ||
376                   outer().isEnclosed(maybe_outer);
377         else
378             throw new InternalCompilerError("Non top-level classes " +
379                     "must have outer classes.");
380     }
381
382     /**
383      * Return true if an object of the class has
384      * an enclosing instance of <code>encl</code>.
385      */

386     public boolean hasEnclosingInstanceImpl(ClassType encl) {
387         if (this.equals(encl)) {
388             // object o is the zeroth lexically enclosing instance of itself.
389
return true;
390         }
391         
392         if (!isInnerClass() || inStaticContext()) {
393             // this class is not an inner class, or was declared in a static
394
// context; it cannot have an enclosing
395
// instance of anything.
396
return false;
397         }
398         
399         // see if the immediately lexically enclosing class has an
400
// appropriate enclosing instance
401
return this.outer().hasEnclosingInstance(encl);
402     }
403 }
404
Popular Tags