KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > base > ast > ASTObject


1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * This file is part of the compiler and core tools for the AspectJ(tm)
4  * programming language; see http://aspectj.org
5  *
6  * The contents of this file are subject to the Mozilla Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License at
9  * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/.
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is AspectJ.
17  *
18  * The Initial Developer of the Original Code is Xerox Corporation. Portions
19  * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation.
20  * All Rights Reserved.
21  *
22  * Contributor(s):
23  */

24
25 package org.aspectj.compiler.base.ast;
26
27 import org.aspectj.compiler.base.*;
28 import org.aspectj.compiler.base.cst.*;
29
30 // to get the passes for introductions
31
import org.aspectj.compiler.crosscuts.*;
32
33 import java.util.*;
34 import java.io.IOException JavaDoc;
35
36 public abstract class ASTObject extends CompilerObject {
37     protected SourceLocation sourceLocation = null;
38     protected ASTObject parent;
39
40     public ASTObject(SourceLocation loc) {
41         super(loc.getCompiler());
42         this.sourceLocation = loc;
43     }
44
45     public boolean hasSourceLocation() {
46         return sourceLocation != null;
47     }
48
49     public SourceLocation getSourceLocation() {
50         return sourceLocation;
51     }
52     public void setSourceLocation(SourceLocation newLocation) {
53         sourceLocation = newLocation;
54     }
55
56     public int getStartPosition() { return getSourceLocation().getStartPosition(); }
57     public int getEndPosition() { return getSourceLocation().getEndPosition(); }
58     public int getBeginLine() { return getSourceLocation().getBeginLine(); }
59     public int getEndLine() { return getSourceLocation().getEndLine(); }
60     public int getBeginColumn() { return getSourceLocation().getBeginColumn(); }
61     public int getEndColumn() { return getSourceLocation().getBeginLine(); }
62
63     public Comment getComment() {
64         return getSourceLocation().getComment();
65     }
66
67     public void addComment(Comment _comment) {
68         getSourceLocation().addComment(_comment);
69     }
70
71     public boolean isSynthetic() {
72         return getSourceLocation().isSynthetic();
73     }
74     public boolean isLanguageVisible() {
75         return !getSourceLocation().isSynthetic();
76     }
77
78
79     public void setFormalComment(String JavaDoc comment) {
80         getSourceLocation().setFormalComment(comment);
81     }
82
83     public String JavaDoc getFormalComment() {
84         return getSourceLocation().getFormalComment();
85     }
86
87     public void clearComment() {
88         getSourceLocation().clearComment();
89     }
90
91     public CompilationUnit getCompilationUnit() {
92         return getSourceLocation().getCompilationUnit();
93     }
94
95     public java.io.File JavaDoc getSourceFile() {
96         return getSourceLocation().getSourceFile();
97     }
98
99     final public String JavaDoc getSourceFileName() {
100         return getSourceLocation().getSourceFileName();
101     }
102
103     final public String JavaDoc getSourceDirectoryName() {
104         return getSourceLocation().getSourceDirectoryName();
105     }
106
107
108     public boolean hasSource() {
109         return getSourceLocation().hasSource();
110     }
111
112     public boolean fromSource() {
113         return getSourceLocation().fromSource();
114     }
115
116
117     //!!! probably should remove
118
public void setParent(ASTObject x) {
119         //!!! this should probably lead to warnings at some point in time
120
if (getOptions().strictTree && parent != null && parent != x) {
121             this.showError("changing parent from " + parent + " to " + x);
122         }
123         parent = x;
124     }
125
126
127     // basically steal the API from javax.swing.Tree.TreeNode
128
public ASTObject getParent() { return parent; }
129
130     public int getChildCount() { return 0; }
131
132     // sets a policy about how to handle out-of-bounds indices
133
public ASTObject getChildAt(int childIndex) { return null; }
134     public String JavaDoc getChildNameAt(int childIndex) { return null; }
135     public void setChildAt(int childIndex, ASTObject child) {}
136     public void removeChildAt(int childIndex) {
137         remove(childIndex);
138     }
139
140     public void remove(int index) {
141         //XXX
142
setChildAt(index, null);
143         //throw new RuntimeException("can't remove child from: " + this);
144
}
145     
146     public void remove(ASTObject child) {
147         int index = indexOf(child);
148         if (index == -1) {
149             throw new IllegalArgumentException JavaDoc("not a child");
150         }
151         remove(index);
152     }
153     
154
155     public boolean isLeaf() {
156         return getChildCount() == 0;
157     }
158
159     public int indexOf(ASTObject node) {
160         int n = getChildCount();
161         for(int i=0; i<n; i++) {
162             //System.out.println(this);
163
ASTObject child = getChildAt(i);
164
165             if (child != null && child == node) return i; //.equals(node)) return i;
166
}
167         return -1;
168     }
169
170     public boolean contains(ASTObject node) {
171         return indexOf(node) != -1;
172     }
173
174     // this is a freaky method to have here
175
public boolean hasLegalProtectedAccess(Type fromType) {
176         //XXX must be overriden appropriately to implement JLSv2 6.6.2
177
return true;
178     }
179     
180     public final boolean containsTypes() {
181         if (this instanceof TypeDec) return true;
182         
183         for(int i=0, n=getChildCount(); i<n; i++) {
184             ASTObject child = getChildAt(i);
185             if (child != null && child.containsTypes()) return true;
186         }
187         return false;
188     }
189
190     // ------------------------------
191
// Intro: ForwardReferenceChecker
192

193     public void walkForwardReference(ForwardReferenceChecker w) {
194         this.walk(w);
195     }
196
197     // ------------------------------
198
// Intro: FlowCheckerPass
199

200     public void walkFlow(FlowCheckerPass w) {
201         this.walk(w);
202     }
203
204     // ------------------------------
205
// Intro: FrameLocPass
206

207     public void walkFrameLoc(FrameLocPass walker) {
208         this.walk(walker);
209     }
210
211
212
213     //INTRO from MovingWalker
214
public void preMove(MovingWalker walker) {
215     }
216
217     public ASTObject postMove(MovingWalker walker) {
218         return this;
219     }
220
221     //INTRO from AccessFixer
222
public ASTObject fixAccessPost(org.aspectj.compiler.crosscuts.AccessFixer fixer) {
223         return this;
224     }
225
226     //INTRO from CopyWalker
227
public ASTObject copyWalk(CopyWalker walker) { return null; }
228     public ASTObject postCopy(CopyWalker walker, ASTObject oldObject) {
229         return this;
230     }
231     public void preCopy(CopyWalker walker, ASTObject oldObject) { }
232
233     //INTRO from IntroductionPlannerPass
234
public void preIntroduction(IntroductionPlannerPass pass) { }
235
236     //INTRO from ScopePass
237
public void preScope(ScopeWalker walker) { }
238     public ASTObject postScope(ScopeWalker walker) { return this; }
239     public void walkScope(ScopeWalker walker) { walk(walker); }
240
241
242     public void walk(Walker walker) {
243         //int N = getChildCount();
244
for(int i=0; i<getChildCount(); i++) {
245             /*
246             if (this instanceof TypeDec) {
247                 System.out.println("walk: " + getChildNameAt(i));
248                 if (getChildNameAt(i).equals("implements")) {
249                     if (getChildAt(i) == null) {
250                         System.out.println(" null");
251                     } else {
252                         getChildAt(i).showWarning("implements clause: ");
253                         getChildAt(i).display(2);
254                     }
255                 }
256             }
257             */

258             ASTObject child = getChildAt(i);
259             if (child != null) {
260                 if (getOptions().strictTree && child.getParent() != this) {
261                     child.showError("wrong parent: " + this.unparse() + " '" + child.unparse() + "'");
262                     System.out.println(child.getParent().unparse());
263                 }
264                 ASTObject newChild = walker.process(child);
265                 if (newChild == child) continue;
266                 if (newChild == null) {
267                     removeChildAt(i);
268                     //System.out.println("removed: " + i);
269
i -= 1;
270                     //N -= 1;
271
} else {
272                     setChildAt(i, newChild);
273                 }
274             }
275         }
276     }
277
278     public Type getOutermostLexicalType() {
279         if (parent == null) return getTypeManager().TYPE_NOT_FOUND;
280         return parent.getOutermostLexicalType();
281     }
282
283     public Type getOutermostBytecodeType() {
284         if (parent == null) return getTypeManager().TYPE_NOT_FOUND;
285
286         return parent.getOutermostBytecodeType();
287     }
288
289     /** returns the lexically enclosing Type for this object.
290      * For pure Java code this is always identical to getDeclaringType() and
291      * getBytecodeTypeDec().getType().
292      *
293      * For introduced methods, this can be different, i.e.
294      * <code>
295      * interface I { }
296      * class C implements I { }
297      * aspect A {
298      * void C.m() { ... }
299      * }
300      * </code>
301      *
302      * For the method I.m() implemented in C and for any ASTObjects inside of it,
303      * getLexicalType() == A
304      * getDeclaringType() == I
305      * getBytecodeTypeDec().getType() == C
306      */

307
308
309     public Type getLexicalType() {
310         //XXX awful hack
311
if (getParent() == null) {
312             //showError("no parent: " + this);
313
return null;
314         }
315         if (this instanceof Decs && getParent() instanceof TypeDec) return ((TypeDec)getParent()).getType();
316         return getParent().getLexicalType();
317     }
318
319     /**
320      * returns the declaring type of a method. For non-static methods, this type
321      * will always be the type of 'this' within the method. For static methods, this
322      * type will always be the type used to name the method for outside
323      * of its scope, i.e. DeclaringType.m()
324      *
325      * For a comparision with getLexicalType() and getBytecodeTypeDec() see
326      * getLexicalType().
327      */

328
329     public Type getDeclaringType() {
330         if (getParent() == null) {
331             //showError("no parent: " + this);
332
return null;
333         }
334         if (getParent() instanceof TypeDec) return ((TypeDec)getParent()).getType();
335         return getParent().getDeclaringType();
336     }
337
338     /**
339      * not part of the language's semantic model, but part of the compiler's
340      * generated code model. This will return the type declaration
341      * that will actually be
342      * enclosing this point in the bytecodes produced by the compiler.
343      */

344     public TypeDec getBytecodeTypeDec() {
345         if (getParent() == null) {
346             showError("no parent: " + this + ": " + System.identityHashCode(this));
347             System.out.println(unparse());
348             return getTypeManager().TYPE_DEC_NOT_FOUND; //null;
349
}
350         if (getParent() instanceof TypeDec) return (TypeDec)getParent();
351         return getParent().getBytecodeTypeDec();
352     }
353
354
355     public Type getBytecodeType() {
356         TypeDec dec = getBytecodeTypeDec();
357         if (dec == null) return null;
358         return dec.getType();
359     }
360
361     public Dec getEnclosingDec() {
362         if (getParent() == null) {
363             //this.showWarning("missing parent");
364
//this.display(2);
365
return null;
366         }
367         return getParent().getEnclosingDec();
368     }
369
370     public CodeDec getEnclosingCodeDec() {
371         if (getParent() == null) {
372             //this.showWarning("missing parent");
373
//this.display(2);
374
return null;
375         }
376         return getParent().getEnclosingCodeDec();
377     }
378     
379
380
381     public boolean inStaticContext() {
382         if (getParent() == null) return true;
383         return getParent().inStaticContext();
384     }
385
386     public void showTypeError(Type foundType, Type requiredType) {
387         if (foundType.isMissing() || requiredType.isMissing()) return;
388         showError("incompatible types\n" +
389                   "found : " + foundType.getString() + "\n" +
390                   "required: " + requiredType.getString());
391     }
392     public void showError(String JavaDoc message) {
393         getCompiler().showError(this,message);
394     }
395     public void showWarning(String JavaDoc message) {
396         getCompiler().showWarning(this,message);
397     }
398     //XXX the Tester treats these like showWarning
399
public void showMessage(String JavaDoc message) {
400         getCompiler().showMessage(this,message);
401     }
402
403     public String JavaDoc toShortString() {
404         return this.getClass().getName();
405     }
406
407     public ASTObject copy() { return CopyWalker.copy(this); }
408
409
410     public void checkNoSharing(ASTObject other) {
411         Set s1 = new HashSet();
412         Set s2 = new HashSet();
413         this.addContainedNodes(s1);
414         other.addContainedNodes(s2);
415         
416         s1.retainAll(s2);
417         if (!s1.isEmpty()) {
418             getCompiler().showError(this, "shares nodes with " + other + "\n" +
419                                         s1);
420         }
421     }
422     
423     /**
424      * adds nodes I contain to a Set
425      *
426      * if I'm already in the Set signals an error to catch circularities
427      */

428     private void addContainedNodes(Set ret) {
429         if (ret.contains(this)) {
430             getCompiler().showError(this, "duplicate node in " + ret);
431         }
432         ret.add(this);
433         for(int i=0; i<getChildCount(); i++) {
434             ASTObject o = getChildAt(i);
435             if (o != null) o.addContainedNodes(ret);
436         }
437     }
438
439     /* Sets the ASTObject that this one came from, not the source file.
440      * Call this method whenever you transfroms one astobject into another one.
441      *
442      * @returns this in order to allow lazy method chaining
443      */

444     public ASTObject setSource(ASTObject sourceObject) {
445         sourceLocation = sourceObject.sourceLocation;
446         return this;
447     }
448
449     /** Sets the ASTObject that this one came from, not the source
450         file, but from a synthetic location.
451     */

452     public ASTObject setSyntheticSource(ASTObject sourceObject) {
453         sourceLocation = new SourceSourceLocation(sourceObject);
454         return this;
455     }
456
457     protected void makeChild(ASTObject object) {
458         if (object != null) object.parent = this;
459     }
460
461     protected void makeChild(ASTObject[] array) {
462         if (array == null) return;
463         int n = array.length;
464         for(int i=0; i<n; i++) {
465             makeChild(array[i]);
466         }
467     }
468
469     public String JavaDoc getDefaultDisplayName() {
470         return this.getClass().getName();
471     }
472
473     public void clearParent() { parent = null; }
474
475     protected void setParents() {}
476
477     public void replaceWith(ASTObject other) {
478         ASTObject parent = getParent();
479         if (parent == null) {
480             showWarning("no parent to replace in");
481             display(2);
482             return;
483         }
484         int i = parent.indexOf(this);
485         if (i == -1) {
486             showError("invalid replacement attempt, not in: " + parent);
487             parent.display(2);
488             return;
489         }
490         //System.out.println("replacing: " + this + " with " + other + " at " + i + " in " + parent);
491
parent.setChildAt(i, other);
492     }
493
494     public String JavaDoc toString() {
495         return getDefaultDisplayName(); // + System.identityHashCode(this);
496
}
497
498     public void display(int indent) {
499         for(int s=0; s<indent; s++) System.out.print(" ");
500         System.out.println(getDefaultDisplayName() + System.identityHashCode(this)); //+": "+getContext()); //System.identityHashCode(this)); //getContext());
501

502         final int N = getChildCount();
503         for(int i=0; i<N; i++) {
504             ASTObject child = getChildAt(i);
505             if (child != null) {
506                 child.display(indent+1);
507             }
508         }
509     }
510
511     public AST getAST() {
512         //XXX would like a more sophisticated source location here
513
return new AST(new SourceSourceLocation(this));
514     }
515
516     public String JavaDoc unparse() {
517         CodeWriter writer = new CodeWriter(getCompiler());
518         writer.write(this);
519         return writer.getString();
520     }
521
522     //XXX this should be abstract before all is said and done
523
public void unparse(CodeWriter writer) throws IOException JavaDoc {
524         writer.write("/* ");
525         writer.write(getDefaultDisplayName());
526         writer.write(" */");
527         writer.newLine();
528     }
529
530     public void cleanup() {
531     }
532
533     //INTRO from ASTFixer
534
public void fixAST(ASTFixerPass fixer) { this.walk(fixer); }
535     public ASTObject postFixAST(ASTFixerPass fixer) { return this; }
536
537     //INTRO from MixinImplementationPass
538
public void implementMixin(MixinImplementationPass walker) { this.walk(walker); }
539     public ASTObject postImplementMixin(MixinImplementationPass walker) { return this; }
540
541     // ------------------------------
542
// INTRO from InnerInfoPass
543

544     public void walkInnerInfo(InnerInfoPass walker) {
545         this.walk(walker);
546     }
547     public void postInnerInfo(InnerInfoPass walker) { }
548
549     // ------------------------------
550
// INTRO: SpecCheckerPass
551

552     public void checkSpec() { }
553
554     // ------------------------------
555
// INTRO from AssignmentCheckerPass
556

557     public void preAssignmentCheck(AssignmentCheckerPass walker) { }
558     public void walkAssignmentCheck(AssignmentCheckerPass walker) {
559         this.walk(walker);
560     }
561     public ASTObject postAssignmentCheck(AssignmentCheckerPass walker) {
562         return this;
563     }
564
565     // ------------------------------
566
// INTRO from LocalClassPass
567

568     public void walkAnalysis(LocalClassPass.AnalysisWalker walker) {
569         walk(walker);
570     }
571     public void preLift(LocalClassPass.LiftWalker walker) {}
572     public ASTObject postLift(LocalClassPass.LiftWalker walker) {
573         return this;
574     }
575     public void preThreading(LocalClassPass.ThreadingWalker walker) {}
576     public ASTObject postThreading(LocalClassPass.ThreadingWalker walker) {
577         return this;
578     }
579
580     // ------------------------------
581
// INTRO from MemberClassMunger
582

583     public ASTObject walkMemberMunger(MemberClassMunger w) {
584         this.walk(w);
585         return this;
586     }
587
588     // ------------------------------
589
//INTRO from InnerAccessFixer
590

591     /** Converts an expression accessing inaccessable context to one
592         that is legal. */

593     public ASTObject postInnerAccess(InnerAccessFixer w) {
594         return this;
595     }
596
597     /** Builds a method that would perform the actions of this
598         expression. The InnerAccessFixer object keeps a cache of such
599         methods to provide to the InnerAccessFixer walk, but if no
600         appropriate method has yet been built, the original expression
601         is the one that knows how to build it. This should only be
602         overridden in {@link PrefixExpr}, {@link PostfixExpr}, {@link
603         FieldAccessExpr}, {@link AssignExpr}, and {@link CallExpr}.
604         If and when we do cookie methods for constructor, we may also
605         need to override this in {@link NewInstanceExpr} and {@link
606         ConstructorCallExpr}.
607     */

608     public MethodDec buildAccessMethod(InnerAccessFixer w) {
609         throw new RuntimeException JavaDoc("No access method should be built for " + this);
610     }
611
612     // ------------------------------
613
// bcg cleanups
614

615     public void walkCleanup(ByteCodeCleanupPass walker) {
616         this.walk(walker);
617     }
618     public ASTObject postCleanup(ByteCodeCleanupPass walker) {
619         return this;
620     }
621 }
622
Popular Tags