KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > ext > jl > ast > ClassDecl_c


1 package polyglot.ext.jl.ast;
2
3 import java.util.Collections JavaDoc;
4 import java.util.Iterator JavaDoc;
5 import java.util.List JavaDoc;
6
7 import polyglot.ast.*;
8 import polyglot.main.Report;
9 import polyglot.types.*;
10 import polyglot.util.CodeWriter;
11 import polyglot.util.CollectionUtil;
12 import polyglot.util.Position;
13 import polyglot.util.TypedList;
14 import polyglot.visit.*;
15
16 /**
17  * A <code>ClassDecl</code> is the definition of a class, abstract class,
18  * or interface. It may be a public or other top-level class, or an inner
19  * named class, or an anonymous class.
20  */

21 public class ClassDecl_c extends Term_c implements ClassDecl
22 {
23     protected Flags flags;
24     protected String JavaDoc name;
25     protected TypeNode superClass;
26     protected List JavaDoc interfaces;
27     protected ClassBody body;
28
29     protected ParsedClassType type;
30
31     public ClassDecl_c(Position pos, Flags flags, String JavaDoc name,
32                        TypeNode superClass, List JavaDoc interfaces, ClassBody body) {
33         super(pos);
34         this.flags = flags;
35         this.name = name;
36         this.superClass = superClass;
37         this.interfaces = TypedList.copyAndCheck(interfaces, TypeNode.class, true);
38         this.body = body;
39     }
40
41     public Named declaration() {
42         return type();
43     }
44
45     public ParsedClassType type() {
46         return type;
47     }
48
49     public ClassDecl type(ParsedClassType type) {
50         ClassDecl_c n = (ClassDecl_c) copy();
51         n.type = type;
52         return n;
53     }
54
55     public Flags flags() {
56         return this.flags;
57     }
58
59     public ClassDecl flags(Flags flags) {
60         ClassDecl_c n = (ClassDecl_c) copy();
61         n.flags = flags;
62         return n;
63     }
64
65     public String JavaDoc name() {
66         return this.name;
67     }
68
69     public ClassDecl name(String JavaDoc name) {
70         ClassDecl_c n = (ClassDecl_c) copy();
71         n.name = name;
72         return n;
73     }
74
75     public TypeNode superClass() {
76         return this.superClass;
77     }
78
79     public ClassDecl superClass(TypeNode superClass) {
80         ClassDecl_c n = (ClassDecl_c) copy();
81         n.superClass = superClass;
82         return n;
83     }
84
85     public List JavaDoc interfaces() {
86         return this.interfaces;
87     }
88
89     public ClassDecl interfaces(List JavaDoc interfaces) {
90         ClassDecl_c n = (ClassDecl_c) copy();
91         n.interfaces = TypedList.copyAndCheck(interfaces, TypeNode.class, true);
92         return n;
93     }
94
95     public ClassBody body() {
96         return this.body;
97     }
98
99     public ClassDecl body(ClassBody body) {
100         ClassDecl_c n = (ClassDecl_c) copy();
101         n.body = body;
102         return n;
103     }
104
105     protected ClassDecl_c reconstruct(TypeNode superClass, List JavaDoc interfaces, ClassBody body) {
106         if (superClass != this.superClass || ! CollectionUtil.equals(interfaces, this.interfaces) || body != this.body) {
107             ClassDecl_c n = (ClassDecl_c) copy();
108             n.superClass = superClass;
109             n.interfaces = TypedList.copyAndCheck(interfaces, TypeNode.class, true);
110             n.body = body;
111             return n;
112         }
113
114         return this;
115     }
116
117     /**
118      * Return the first (sub)term performed when evaluating this
119      * term.
120      */

121     public Term entry() {
122         return this.body().entry();
123     }
124
125     /**
126      * Visit this term in evaluation order.
127      */

128     public List JavaDoc acceptCFG(CFGBuilder v, List JavaDoc succs) {
129         v.visitCFG(this.body(), this);
130         return succs;
131     }
132
133     public Node visitChildren(NodeVisitor v) {
134         TypeNode superClass = (TypeNode) visitChild(this.superClass, v);
135         List JavaDoc interfaces = visitList(this.interfaces, v);
136         ClassBody body = (ClassBody) visitChild(this.body, v);
137         return reconstruct(superClass, interfaces, body);
138     }
139
140     public NodeVisitor buildTypesEnter(TypeBuilder tb) throws SemanticException {
141     tb = tb.pushClass(position(), flags, name);
142         
143         ParsedClassType ct = tb.currentClass();
144
145         // Member classes of interfaces are implicitly public and static.
146
if (ct.isMember() && ct.outer().flags().isInterface()) {
147             ct.flags(ct.flags().Public().Static());
148         }
149
150         // Member interfaces are implicitly static.
151
if (ct.isMember() && ct.flags().isInterface()) {
152             ct.flags(ct.flags().Static());
153         }
154
155         // Interfaces are implicitly abstract.
156
if (ct.flags().isInterface()) {
157             ct.flags(ct.flags().Abstract());
158         }
159
160         return tb;
161     }
162
163     public Node buildTypes(TypeBuilder tb) throws SemanticException {
164     ParsedClassType type = tb.currentClass();
165         if (type != null) {
166             return type(type).flags(type.flags());
167         }
168         return this;
169     }
170
171     public Context enterScope(Node child, Context c) {
172         if (child == this.body) {
173             TypeSystem ts = c.typeSystem();
174             c = c.pushClass(type, ts.staticTarget(type).toClass());
175         }
176         return super.enterScope(child, c);
177     }
178
179     public NodeVisitor disambiguateEnter(AmbiguityRemover ar) throws SemanticException {
180         if (ar.kind() == AmbiguityRemover.SUPER) {
181             return ar.bypass(body);
182         }
183
184         return ar;
185     }
186
187     protected void disambiguateSuperType(AmbiguityRemover ar) throws SemanticException {
188         TypeSystem ts = ar.typeSystem();
189
190         if (this.superClass != null) {
191             Type t = this.superClass.type();
192
193             if (! t.isCanonical()) {
194                 throw new SemanticException("Could not disambiguate super" +
195                         " class of " + type + ".", superClass.position());
196             }
197
198             if (! t.isClass() || t.toClass().flags().isInterface()) {
199                 throw new SemanticException("Super class " + t + " of " +
200                         type + " is not a class.", superClass.position());
201             }
202
203             if (Report.should_report(Report.types, 3))
204                 Report.report(3, "setting super type of " + this.type + " to " + t);
205
206             this.type.superType(t);
207
208             ts.checkCycles(t.toReference());
209         }
210         else if (ts.Object() != this.type &&
211                  !ts.Object().fullName().equals(this.type.fullName())) {
212             // the supertype was not specified, and the type is not the same
213
// as ts.Object() (which is typically java.lang.Object)
214
// As such, the default supertype is ts.Object().
215
this.type.superType(ts.Object());
216         }
217         else {
218             // the type is the same as ts.Object(), so it has no supertype.
219
this.type.superType(null);
220         }
221     }
222
223     public Node disambiguate(AmbiguityRemover ar) throws SemanticException {
224         if (ar.kind() == AmbiguityRemover.SIGNATURES) {
225             // make sure that the inStaticContext flag of the class is
226
// correct
227
Context ctxt = ar.context();
228             this.type().inStaticContext(ctxt.inStaticContext());
229
230
231         }
232
233         if (ar.kind() == AmbiguityRemover.SIGNATURES) {
234             // make sure that this class has the correct dependencies
235
// recorded for its super classes and interfaces.
236
ar.addSuperDependencies(this.type());
237         }
238
239         if (ar.kind() != AmbiguityRemover.SUPER) {
240             return this;
241         }
242
243         TypeSystem ts = ar.typeSystem();
244
245         if (Report.should_report(Report.types, 2))
246         Report.report(2, "Cleaning " + type + ".");
247
248         disambiguateSuperType(ar);
249         
250         for (Iterator JavaDoc i = this.interfaces.iterator(); i.hasNext(); ) {
251             TypeNode tn = (TypeNode) i.next();
252             Type t = tn.type();
253
254             if (! t.isCanonical()) {
255                 throw new SemanticException("Could not disambiguate super" +
256                         " class of " + type + ".", tn.position());
257             }
258
259             if (! t.isClass() || ! t.toClass().flags().isInterface()) {
260                 throw new SemanticException("Interface " + t + " of " +
261                         type + " is not an interface.", tn.position());
262             }
263
264             if (Report.should_report(Report.types, 3))
265         Report.report(3, "adding interface of " + this.type + " to " + t);
266
267             if (!this.type.interfaces().contains(t)) this.type.addInterface(t);
268
269             ts.checkCycles(t.toReference());
270         }
271
272         return this;
273     }
274
275     public Node addMembers(AddMemberVisitor tc) throws SemanticException {
276     TypeSystem ts = tc.typeSystem();
277     NodeFactory nf = tc.nodeFactory();
278         return addDefaultConstructorIfNeeded(ts, nf);
279     }
280
281     protected Node addDefaultConstructorIfNeeded(TypeSystem ts,
282                                                  NodeFactory nf) {
283         if (defaultConstructorNeeded()) {
284             return addDefaultConstructor(ts, nf);
285         }
286         return this;
287     }
288
289     protected boolean defaultConstructorNeeded() {
290         if (flags().isInterface()) {
291             return false;
292         }
293         return type().constructors().isEmpty();
294     }
295
296     protected Node addDefaultConstructor(TypeSystem ts, NodeFactory nf) {
297         ConstructorInstance ci = ts.defaultConstructor(position(), this.type);
298         this.type.addConstructor(ci);
299         Block block = null;
300         if (this.type.superType() instanceof ClassType) {
301             ConstructorInstance sci = ts.defaultConstructor(position(),
302                                                 (ClassType) this.type.superType());
303             ConstructorCall cc = nf.SuperCall(position(),
304                                               Collections.EMPTY_LIST);
305             cc = cc.constructorInstance(sci);
306             block = nf.Block(position(), cc);
307         }
308         else {
309             block = nf.Block(position());
310         }
311         ConstructorDecl cd = nf.ConstructorDecl(position(), Flags.PUBLIC,
312                                                 name, Collections.EMPTY_LIST,
313                                                 Collections.EMPTY_LIST,
314                                                 block);
315         cd = (ConstructorDecl) cd.constructorInstance(ci);
316         return body(body.addMember(cd));
317     }
318
319     public Node typeCheck(TypeChecker tc) throws SemanticException {
320         if (this.type().isNested() && (this.type() instanceof Named)) {
321             // The class cannot have the same simple name as any enclosing class.
322
ClassType container = this.type.outer();
323
324             while (container instanceof Named) {
325                 if (!container.isAnonymous()) {
326                     String JavaDoc name = ((Named) container).name();
327     
328                     if (name.equals(this.name)) {
329                         throw new SemanticException("Cannot declare member " +
330                                                     "class \"" + this.type +
331                                                     "\" inside class with the " +
332                                                     "same name.", position());
333                     }
334                 }
335                 if (container.isNested()) {
336                     container = container.outer();
337                 }
338                 else {
339                     break;
340                 }
341             }
342                         
343             if (this.type().isLocal()) {
344                 // a local class name cannot be redeclared within the same
345
// method, constructor or initializer, and within its scope
346
Context ctxt = tc.context();
347
348                 if (ctxt.isLocal(this.name)) {
349                     // something with the same name was declared locally.
350
// (but not in an enclosing class)
351
Named nm = ctxt.find(this.name);
352                     if (nm instanceof Type) {
353                         Type another = (Type)nm;
354                         if (another.isClass() && another.toClass().isLocal()) {
355                             throw new SemanticException("Cannot declare local " +
356                                 "class \"" + this.type + "\" within the same " +
357                                 "method, constructor or initializer as another " +
358                                 "local class of the same name.", position());
359                         }
360                     }
361                 }
362             }
363         }
364
365         // check that inner classes do not declare member interfaces
366
if (type().isMember() && flags().isInterface() &&
367               type().outer().isInnerClass()) {
368             // it's a member interface in an inner class.
369
throw new SemanticException("Inner classes cannot declare " +
370                     "member interfaces.", this.position());
371         }
372
373         // Make sure that static members are not declared inside inner classes
374
if (type().isMember() && type().flags().isStatic()
375                && type().outer().isInnerClass()) {
376             throw new SemanticException("Inner classes cannot declare static "
377                                  + "member classes.", position());
378         }
379         
380         if (type.superType() != null) {
381             if (! type.superType().isClass()) {
382                 throw new SemanticException("Cannot extend non-class \"" +
383                                             type.superType() + "\".",
384                                             position());
385             }
386
387             if (type.superType().toClass().flags().isFinal()) {
388                 throw new SemanticException("Cannot extend final class \"" +
389                                             type.superType() + "\".",
390                                             position());
391             }
392         }
393
394         TypeSystem ts = tc.typeSystem();
395
396         try {
397             if (type.isTopLevel()) {
398                 ts.checkTopLevelClassFlags(type.flags());
399             }
400             if (type.isMember()) {
401                 ts.checkMemberClassFlags(type.flags());
402             }
403             if (type.isLocal()) {
404                 ts.checkLocalClassFlags(type.flags());
405             }
406         }
407         catch (SemanticException e) {
408             throw new SemanticException(e.getMessage(), position());
409         }
410         
411         // check the class implements all abstract methods that it needs to.
412
ts.checkClassConformance(type);
413
414         return this;
415     }
416
417     public String JavaDoc toString() {
418         return flags.clearInterface().translate() +
419                (flags.isInterface() ? "interface " : "class ") + name + " " + body;
420     }
421
422     public void prettyPrintHeader(CodeWriter w, PrettyPrinter tr) {
423         if (flags.isInterface()) {
424             w.write(flags.clearInterface().clearAbstract().translate());
425         }
426         else {
427             w.write(flags.translate());
428         }
429
430         if (flags.isInterface()) {
431             w.write("interface ");
432         }
433         else {
434             w.write("class ");
435         }
436
437         w.write(name);
438
439         if (superClass() != null) {
440             w.write(" extends ");
441             print(superClass(), w, tr);
442         }
443
444         if (! interfaces.isEmpty()) {
445             if (flags.isInterface()) {
446                 w.write(" extends ");
447             }
448             else {
449                 w.write(" implements ");
450             }
451
452             for (Iterator JavaDoc i = interfaces().iterator(); i.hasNext(); ) {
453                 TypeNode tn = (TypeNode) i.next();
454                 print(tn, w, tr);
455
456                 if (i.hasNext()) {
457                     w.write (", ");
458                 }
459             }
460         }
461
462         w.write(" {");
463     }
464
465     public void prettyPrintFooter(CodeWriter w, PrettyPrinter tr) {
466         w.write("}");
467         w.newline(0);
468     }
469     
470     public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
471         prettyPrintHeader(w, tr);
472         print(body(), w, tr);
473         prettyPrintFooter(w, tr);
474     }
475
476     public void dump(CodeWriter w) {
477             super.dump(w);
478
479             w.allowBreak(4, " ");
480             w.begin(0);
481             w.write("(name " + name + ")");
482             w.end();
483
484             if (type != null) {
485                     w.allowBreak(4, " ");
486                     w.begin(0);
487                     w.write("(type " + type + ")");
488                     w.end();
489             }
490     }
491 }
492
Popular Tags