KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > aspectj > compiler > crosscuts > ast > AfterReturningAdviceDec


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.ast;
26
27 import javax.swing.JPanel JavaDoc;
28
29 import org.aspectj.compiler.base.FlowCheckerPass;
30 import org.aspectj.compiler.base.ast.*;
31 import org.aspectj.compiler.crosscuts.joinpoints.*;
32 import org.aspectj.compiler.base.JavaCompiler;
33
34 /**
35  * @grammar after (formals) returning (formal)
36  * @child FormalDec extraFormal @after formals
37  */

38
39
40 public class AfterReturningAdviceDec extends AdviceDec {
41     protected String JavaDoc getAdviceKind() { return "afterReturning"; }
42
43     protected boolean isAfterAdvice() { return true; }
44     
45     private static final String JavaDoc CONSTRUCTOR_EXECUTION_BINDING_CHANGE =
46         "return value will bind to null, use 'this' pointcut to bind executing object\n" +
47         " behavior change to fix compiler bug in 1.0.3 and earlier";
48         
49     private static final String JavaDoc VOID_RETURN_CHANGE =
50         "will not match this joinpoint, use Object return type in advice if match desired\n" +
51         " behavior change to fix compiler bug in 1.0.3 and earlier";
52
53     protected Stmts wrapStmts(Stmts stmts, AdvicePlan plan) {
54         JoinPoint jp = plan.getJoinPoint();
55         FormalDec formal = getExtraFormal();
56         
57         if (jp instanceof ExceptionHandlerJp) {
58             showWarning("can't apply after returning advice to exception handler join points (compiler limitation)");
59             jp.getSourceLocation().showWarning(
60               "trying to apply above after returning advice to execution of this exception handler");
61             return stmts;
62         }
63         if (jp.getResultType().isVoid()) {
64             if (formal != null && !formal.getType().isObject()) {
65                 jp.showWarning(this, VOID_RETURN_CHANGE);
66                 return stmts;
67             }
68         }
69         
70         if (jp instanceof ConstructorExecutionJp) {
71             if (formal != null && formal.getType().isObject()) {
72                 jp.showWarning(this, CONSTRUCTOR_EXECUTION_BINDING_CHANGE);
73             }
74         }
75
76         ReturnFixerWalker walker = new ReturnFixerWalker(getCompiler(), plan);
77         Stmts ret = walker.removeReturns(stmts);
78         return ret;
79     }
80     
81     /**
82      *
83      * generates code:
84      *
85      * stmts -> ReturnType _thisResult = null;
86      * LABEL: if (true) { stmts; }
87      * doAdvicePlan(_thisResult);
88      * return _thisResult;
89      *
90      * within stmts:
91      * return x; -> _thisResult = x; break LABEL;
92      */

93     static class ReturnFixerWalker extends Walker {
94         AdvicePlan plan;
95     VarDec thisResultVar;
96     String JavaDoc label;
97
98
99         public ReturnFixerWalker(JavaCompiler compiler, AdvicePlan plan) {
100             super(compiler);
101             this.plan = plan;
102         }
103         
104         public Stmts removeReturns(Stmts stmts) {
105             final AST ast = getAST();
106             Type resultType = plan.getJoinPoint().getResultType();
107             
108             Expr thisResultExpr;
109             Stmt returnStmt;
110             
111             if (resultType.isVoid()) {
112                 thisResultVar = null;
113                 //??? Expr var = plan.getJoinPoint().makeVoidReturnExpr();
114
thisResultExpr = ast.makeNull();
115                 returnStmt = ast.makeReturn();
116             } else {
117                 thisResultVar =
118                     ast.makeVarDec(resultType, "_thisResult", resultType.getNullExpr());
119                 thisResultExpr = ast.makeVar(thisResultVar);
120                 returnStmt = ast.makeReturn(ast.makeVar(thisResultVar));
121             }
122             
123             label = getWorld().genLabel();
124             
125             Stmts ret = (Stmts)process(stmts);
126             
127             Stmt body = ast.makeLabeled(label, ast.makeIf(ast.makeLiteral(true),
128                                                           ret.getSingleStmt()));
129             
130             ret = ast.makeStmts(
131                 body,
132                 plan.makeCall(thisResultExpr),
133                 returnStmt);
134                 
135             if (!resultType.isVoid()) {
136                 ret.add(0, thisResultVar);
137             }
138             
139             return ret;
140         }
141
142         boolean seenVoidReturn = false;
143         boolean seenAnyReturns = false;
144         public Stmt wrapReturn(ReturnStmt returnStmt) {
145             final AST ast = this.getAST();
146             
147             Expr returnExpr = returnStmt.getExpr();
148             if (returnExpr == null) {
149                 return ast.makeBreak(label);
150             } else {
151                 return ast.makeBlock(
152                     ast.makeSet(thisResultVar, returnExpr),
153                     ast.makeBreak(label));
154             }
155         }
156         
157         public ASTObject process(ASTObject object) {
158             // make sure we don't walk into inners
159
if (object instanceof TypeDec) return object;
160             if (object instanceof AnonymousMethodExpr) return object;
161             
162             if (object instanceof ReturnStmt) {
163                 return wrapReturn((ReturnStmt)object);
164             }
165
166             return super.process(object);
167         }
168     }
169     
170     // ------------------------------
171
// INTRO from FlowCheckerPass
172

173     protected void setupFlowWalker(FlowCheckerPass w) {
174         if (getExtraFormal() != null)
175             w.setVars(w.getVars().addAssigned(getExtraFormal()));
176         super.setupFlowWalker(w);
177     }
178     
179     //BEGIN: Generated from @child and @property
180
protected FormalDec extraFormal;
181     public FormalDec getExtraFormal() { return extraFormal; }
182     public void setExtraFormal(FormalDec _extraFormal) {
183         if (_extraFormal != null) _extraFormal.setParent(this);
184         extraFormal = _extraFormal;
185     }
186     
187     public AfterReturningAdviceDec(SourceLocation location, Modifiers _modifiers, Formals _formals, FormalDec _extraFormal, TypeDs __throws, Pcd _pcd, CodeBody _body) {
188         super(location, _modifiers, _formals, __throws, _pcd, _body);
189         setExtraFormal(_extraFormal);
190     }
191     protected AfterReturningAdviceDec(SourceLocation source) {
192         super(source);
193     }
194     
195     public ASTObject copyWalk(CopyWalker walker) {
196         AfterReturningAdviceDec ret = new AfterReturningAdviceDec(getSourceLocation());
197         ret.preCopy(walker, this);
198         if (modifiers != null) ret.setModifiers( (Modifiers)walker.process(modifiers) );
199         if (formals != null) ret.setFormals( (Formals)walker.process(formals) );
200         if (extraFormal != null) ret.setExtraFormal( (FormalDec)walker.process(extraFormal) );
201         if (_throws != null) ret.setThrows( (TypeDs)walker.process(_throws) );
202         if (pcd != null) ret.setPcd( (Pcd)walker.process(pcd) );
203         if (body != null) ret.setBody( (CodeBody)walker.process(body) );
204         return ret;
205     }
206     
207     public ASTObject getChildAt(int childIndex) {
208         switch(childIndex) {
209         case 0: return modifiers;
210         case 1: return formals;
211         case 2: return extraFormal;
212         case 3: return _throws;
213         case 4: return pcd;
214         case 5: return body;
215         default: return super.getChildAt(childIndex);
216         }
217     }
218      public String JavaDoc getChildNameAt(int childIndex) {
219         switch(childIndex) {
220         case 0: return "modifiers";
221         case 1: return "formals";
222         case 2: return "extraFormal";
223         case 3: return "throws";
224         case 4: return "pcd";
225         case 5: return "body";
226         default: return super.getChildNameAt(childIndex);
227         }
228     }
229      public void setChildAt(int childIndex, ASTObject child) {
230         switch(childIndex) {
231         case 0: setModifiers((Modifiers)child); return;
232         case 1: setFormals((Formals)child); return;
233         case 2: setExtraFormal((FormalDec)child); return;
234         case 3: setThrows((TypeDs)child); return;
235         case 4: setPcd((Pcd)child); return;
236         case 5: setBody((CodeBody)child); return;
237         default: super.setChildAt(childIndex, child); return;
238         }
239     }
240      public int getChildCount() {
241         return 6;
242     }
243     
244     public String JavaDoc getDefaultDisplayName() {
245         return "AfterReturningAdviceDec()";
246     }
247     
248     //END: Generated from @child and @property
249
}
250
Popular Tags