KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > crosscuts > joinpoints > InitializationJp


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.crosscuts.joinpoints;
26
27 import org.aspectj.compiler.base.ast.*;
28 import org.aspectj.compiler.crosscuts.ast.*;
29 import org.aspectj.util.JavaStrings;
30
31 import org.aspectj.compiler.base.JavaCompiler;
32
33 import java.util.*;
34
35
36 public class InitializationJp extends CodeDecJp {
37     public InitializationJp(ConstructorDec constructorDec) {
38         super(constructorDec);
39         constructorDec.getBytecodeTypeDec().getInitializerExecutionJoinPoints().add(this);
40     }
41     
42     public static final Kind KIND = new Kind("initialization", INITIALIZER_EXECUTION);
43
44     public Kind getKind() { return KIND; }
45  
46     //!!! bad name
47
public TypeDec getEnclosingTypeDec() { return getCodeDec().getBytecodeTypeDec(); }
48
49     public ASTObject getSourceLocation() { return getEnclosingTypeDec().getBody(); }
50
51     public void setStmts(Stmts stmts) {
52         makeInnerAndOuterConstructorDecs();
53         innerConstructorDec.getBody().setStmts(stmts);
54     }
55
56     public Stmts getStmts() {
57         makeInnerAndOuterConstructorDecs();
58         return innerConstructorDec.getBody().getStmts();
59     }
60     
61     public boolean needToImplement() {
62         if (!super.needToImplement()) return false;
63         
64         return checkNoLocalTypes();
65     }
66
67     private boolean checkNoLocalTypes() {
68         LocalFinderWalker w = new LocalFinderWalker(getCompiler());
69         w.process(getStmts());
70         return !w.foundLocal;
71     }
72     
73     private class LocalFinderWalker extends Walker {
74         public boolean foundLocal = false;
75         
76         public LocalFinderWalker(JavaCompiler c) { super(c); }
77         
78         public boolean preProcess(ASTObject o) {
79             if (foundLocal) return false;
80             
81             if (o instanceof TypeDec) {
82                 showError(o, "can't handle local classes in initializers with " +
83                             "initialization join points (compiler limitation)");
84                 foundLocal = true;
85                 return false;
86             }
87             return true;
88         }
89     }
90
91     
92     private ConstructorDec innerConstructorDec = null;
93     private ConstructorDec outerConstructorDec = null;
94     
95     public void inlineBodies() {
96         ConstructorDec origConstructorDec = (ConstructorDec)getCodeDec();
97         outerConstructorDec = makeInitializer(origConstructorDec);
98     }
99     
100     
101     public void finishInline() {
102         ConstructorDec origConstructorDec = (ConstructorDec)getCodeDec();
103         ConstructorDec topDec = outerConstructorDec;
104
105         origConstructorDec.setBody(topDec.getBody());
106         if (instanceInitializer != null && instanceInitializer.getBody().getStmts().size() > 0) {
107             Stmt initializerStmt =
108                 getAST().makeBlock(instanceInitializer.getBody().getStmts().copy());
109             innerConstructorDec.getBody().getStmts().add(0, initializerStmt);
110         }
111         
112         // move formals to innerConstructorDec and move references in there as well
113
// this will deal better with advice that holds on to these references
114
Formals oldFormals = origConstructorDec.getFormals();
115         origConstructorDec.setFormals(topDec.getFormals());
116         MovingWalker mover = new MovingWalker(getCompiler());
117         for (int i = 0; i<oldFormals.size(); i++) {
118             FormalDec oldFormal = oldFormals.get(i);
119             FormalDec newFormal = innerConstructorDec.getFormals().get(i);
120             mover.addMapping(newFormal, oldFormal);
121             newFormal.replaceWith(oldFormal);
122         }
123         mover.process(innerConstructorDec.getBody());
124     }
125
126     private InitializerDec instanceInitializer;
127     public void makeInnerAndOuterConstructorDecs() {
128         //System.out.println("making inners and outers: " + this);
129

130         if (outerConstructorDec != null) return;
131         
132         instanceInitializer = getEnclosingTypeDec().getSingleInitializerDec(false);
133         
134         for (Iterator i = getEnclosingTypeDec().getInitializerExecutionJoinPoints().iterator(); i.hasNext(); ) {
135             InitializationJp point = (InitializationJp)i.next();
136             point.instanceInitializer = instanceInitializer;
137             point.inlineBodies();
138         }
139         
140         for (Iterator i = getEnclosingTypeDec().getInitializerExecutionJoinPoints().iterator(); i.hasNext(); ) {
141             InitializationJp point = (InitializationJp)i.next();
142             point.finishInline();
143         }
144         
145         getEnclosingTypeDec().getBody().remove(instanceInitializer);
146         
147         //System.out.println("get: " + innerConstructorDec.getBody().unparse());
148
}
149     
150
151     /**
152      * Takes one step towards making a constructor a reasonable target for
153      * a initializer join point.
154      *
155      * There are three cases
156      * <ul>
157      * <li> C(args) { super(...); ... } <p> This will return a copy of C
158      * <li> C(args) { this(1, "hi"); ... } C(int, String) { ... } <p>
159      * This will inline C(int, String) in the copy of C and return that.
160      * <li> C(args) { this(x+y, s.substring(...)); ... } C(int, String) { ... } <p>
161      * This will produce C(args) { this(x, y, s, x+y, s.substring(...)); } and internally
162      * will produce a C(int, int, String, int, String) { merged bodies }
163      */

164     ConstructorDec makeInitializer(ConstructorDec dec) {
165         // we don't do a simple copy because that will remap references
166
// to this constructor from its body
167
CopyWalker cw = new CopyWalker(getCompiler());
168         ConstructorDec ret =
169             new ConstructorDec(dec.getSourceLocation(),
170                                (Modifiers)cw.cp(dec.getModifiers()),
171                                (Formals)cw.cp(dec.getFormals()),
172                                (TypeDs)cw.cp(dec.getThrows()),
173                                (CodeBody)cw.cp(dec.getBody()));
174
175         ConstructorBody body = (ConstructorBody)ret.getBody();
176         ConstructorCallExpr thisCallExpr = body.getConstructorCall();
177         
178         //ret.setFormalComment("/* from " + this.toString() + " */");
179

180         if (thisCallExpr.getIsSuper()) {
181             body.setStmts(body.getStmts().removeReturns());
182             innerConstructorDec = ret;
183             return ret;
184         }
185         
186         ConstructorDec innerDec =
187                 makeInitializer(thisCallExpr.getConstructor().getConstructorDec());
188
189         Formals oldFormals = ret.getFormals();
190         CopyWalker copier = new CopyWalker(getCompiler());
191         Formals newFormals = (Formals)copier.process(oldFormals);
192         thisCallExpr = (ConstructorCallExpr)copier.process(thisCallExpr);
193         thisCallExpr.getArgs().addAll(0, newFormals.makeExprs());
194         thisCallExpr.setConstructor(innerDec.getConstructor());
195         body.setConstructorCall(thisCallExpr);
196         ret.setFormals(newFormals);
197         Stmts stmts = body.getStmts();
198         body.setStmts(getAST().makeStmts());
199         inlineStmts(stmts, innerDec.getBody().getStmts());
200         innerDec.getFormals().addAll(0, oldFormals);
201         
202         addUniquelyToBody(dec.getBytecodeTypeDec().getBody(), innerDec, thisCallExpr);
203         
204         return ret;
205     }
206     
207     void inlineStmts(Stmts addStmts, Stmts baseStmts) {
208         baseStmts.addAll(addStmts.removeReturns());
209     }
210     
211     void addUniquelyToBody(Decs body, ConstructorDec dec, ConstructorCallExpr thisCallExpr) {
212         final AST ast = getAST();
213         
214         body.add(dec);
215         FormalDec cookieFormal = null;
216         while (true) {
217             int i = 0;
218             for (; i < body.size(); i++) {
219                 Dec idec = body.get(i);
220                 if (! (idec instanceof ConstructorDec) || idec == dec) continue;
221                 
222                 ConstructorDec constructorDec = (ConstructorDec)idec;
223                 if (constructorDec.getFormals().matches(dec.getFormals())) break;
224             }
225             if (i >= body.size()) break;
226             
227             if (cookieFormal == null) {
228                 cookieFormal =
229                   ast.makeFormal(getTypeManager().shortType.getArrayType(), "_ajcookie");
230                 dec.getFormals().add(cookieFormal);
231             } else {
232                 cookieFormal.setTypeD(cookieFormal.getType().getArrayType().makeTypeD());
233             }
234         }
235         
236         if (cookieFormal != null) {
237             thisCallExpr.getArgs().add(ast.forceCast(cookieFormal.getType(), ast.makeNull()));
238         }
239     }
240 }
241
Popular Tags