KickJava   Java API By Example, From Geeks To Geeks.

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


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 org.aspectj.compiler.base.ast.*;
28 import org.aspectj.compiler.crosscuts.joinpoints.*;
29 import org.aspectj.compiler.base.*;
30 import org.aspectj.compiler.base.cst.*;
31
32 import org.aspectj.compiler.base.JavaCompiler;
33
34 import java.util.*;
35
36 /**
37  * @grammar modifiers? name {body};
38  * @child Pcd pcd @after throws
39  */

40
41 public abstract class AdviceDec extends CodeDec implements JpPlannerMaker {
42     public String JavaDoc getKind() { return "advice"; }
43
44     //private AspectDec aspectDec = null;
45
public AspectDec getAspectDec() {
46         return (AspectDec)getDeclaringType().getTypeDec();
47     }
48
49     /**
50      * returns the after returning or after throwing formal.
51      * Overridden in {@link AfterReturningAdviceDec} and {@link AfterThrowingAdviceDec}
52      * and {@link AroundAdviceDec}.
53      */

54     public FormalDec getExtraFormal() { return null; }
55
56     protected boolean isAfterAdvice() { return false; }
57
58     protected boolean reverseSortOrder(AdviceDec a1, AdviceDec a2) {
59         return a1.isAfterAdvice() || a2.isAfterAdvice();
60     }
61
62     public boolean dominates(AdviceDec otherAdvice) {
63         AspectDec myAspectDec = getAspectDec();
64         AspectDec otherAspectDec = otherAdvice.getAspectDec();
65
66         if (myAspectDec == otherAspectDec) {
67             if (reverseSortOrder(this, otherAdvice)) {
68                 return this.getBeginLine() > otherAdvice.getBeginLine();
69             } else {
70                 return this.getBeginLine() < otherAdvice.getBeginLine();
71             }
72         } else {
73             return myAspectDec.dominates(otherAspectDec);
74         }
75     }
76
77     public JpPlanner makePlanner(PlanData planData) {
78         if (planData.inAspect.isAbstract()) return JpPlanner.NO_PLANNER;
79
80         JpPlanner planner = getPcd().makePlanner(planData);
81         //System.out.println(this.toShortString() + ": " + planner);
82
//??? we depend on the order that this will proced in dynamic tests
83
planner = planData.inAspect.findPerClause().makeInnerPlanner(planData).and(planner);
84         return new AdvicePlanner(planData.inAspect, this, planner);
85     }
86
87     public void wrapJoinPoint(JoinPoint joinPoint, AdvicePlan plan) {
88         joinPoint.setStmts(this.wrapStmts(joinPoint.getStmts(), plan));
89     }
90
91     protected Stmts wrapStmts(Stmts stmts, AdvicePlan plan) {
92         this.showError("didn't implement code to concretize this advice");
93         return null;
94     }
95
96     protected final Formals makeFormals() {
97         Formals newFormals = getAST().makeFormals();
98         Formals oldFormals = getFormals();
99
100         for (int i = 0; i < oldFormals.size(); i++) {
101             oldFormals.get(i).clearParent();
102             newFormals.add(oldFormals.get(i));
103         }
104         
105         if (getExtraFormal() != null) {
106             getExtraFormal().clearParent();
107             newFormals.add(getExtraFormal());
108         }
109
110         return newFormals;
111     }
112
113     public final Type getExtraArgType() {
114         if (getExtraFormal() == null) return null;
115         return getExtraFormal().getType();
116     }
117
118     public MethodDec makeConcreteMethod() {
119         if (methodDec == null) {
120             methodDec = getMethodDec();
121         }
122
123         if (methodDec == null) return null;
124         methodDec.setBody(makeMethodBody());
125         finishMethodDec(methodDec);
126         return methodDec;
127     }
128     
129     
130     /** returns the method body used for the java method corresponding to
131      * this advice
132      *
133      * this method body is my actual body in the AST, never a copy
134      */

135     protected CodeBody makeMethodBody() {
136         return body;
137     }
138     
139
140     protected void finishMethodDec(MethodDec methodDec) {
141         if (modifiers.isStrict()) methodDec.getModifiers().setStrict(true);
142     }
143
144     // make a short string based on how high this is in the hierarchy
145
// this avoids some ridiculously long names, but feels hackish
146
int getDepth(AspectDec ad) {
147         Type superType = ad.getSuperClassType();
148         if (superType.isAspect()) {
149             return 1 + getDepth((AspectDec)superType.getTypeDec());
150         } else {
151             return 0;
152         }
153     }
154
155     String JavaDoc makeUniqueAspectString() {
156         int depth = getDepth(getAspectDec());
157         if (depth == 0) return "";
158         else return Integer.toString(depth, 36);
159     }
160
161     String JavaDoc makeUniqueAdviceString() {
162         String JavaDoc kind = getAdviceKind();
163         Decs body = (Decs)getParent();
164         int position = 0;
165         final int N = body.size();
166         //System.out.println("searching for: " + this.toShortString());
167
for (int i = 0; i < N; i++) {
168             Dec dec = body.get(i);
169             //System.out.println(dec.toShortString() + ": " + position);
170
if (dec == this) break;
171             if (!(dec instanceof AdviceDec)) continue;
172             AdviceDec ad = (AdviceDec)dec;
173             if (ad.getAdviceKind().equals(kind)) position++;
174         }
175         return kind + Integer.toString(position, 36);
176     }
177
178
179     String JavaDoc makeUniqueName() {
180         return makeUniqueAdviceString() + "$ajc" + makeUniqueAspectString();
181     }
182
183     private MethodDec methodDec;
184     public synchronized MethodDec getMethodDec() {
185         if (methodDec != null) return methodDec;
186
187         final AST ast = getAST();
188
189         String JavaDoc name = makeUniqueName();
190         Modifiers modifiers = ast.makeModifiers(getModifiers().getValue());
191         modifiers.setPublic(true);
192         modifiers.setFinal(true);
193
194         Formals formals = makeFormals();
195         addJoinPointFormals(formals);
196
197         methodDec = ast.makeMethod(modifiers, getResultType(), name,
198                                         formals, null);
199         if (_throws != null) methodDec.setThrows((TypeDs)_throws.copy());
200
201         methodDec.setAllEnclosingTypes(getAspectDec().getType());
202         return methodDec;
203     }
204
205
206     public Expr makeCall(Expr parent, Exprs baseExprs) {
207         Exprs args = (Exprs)baseExprs.copy();
208         if (parent == null) {
209            parent = getAST().makeTypeExpr(getAspectDec().getType());
210         }
211         CallExpr ret = getAST().makeCall(getMethodDec().getMethod(), parent, args);
212         return ret;
213     }
214
215
216
217
218     //***********************************************************************
219
// Section to determine what meta-joinpoint objects are needed
220

221     private boolean joinPointFlagsSet = false;
222     private boolean needsStaticEnclosingJoinPoint;
223     private boolean needsStaticJoinPoint;
224     private boolean needsDynamicJoinPoint;
225
226     private void setJoinPointFlags() {
227         if (!joinPointFlagsSet) {
228             joinPointFlagsSet = true;
229             DynamicJoinPointChecker jpChecker = new DynamicJoinPointChecker(getCompiler());
230             jpChecker.checkAndFix(getBody());
231             needsDynamicJoinPoint = jpChecker.needsDynamicJoinPoint();
232             needsStaticJoinPoint = jpChecker.needsStaticJoinPoint();
233             needsStaticEnclosingJoinPoint = jpChecker.needsStaticEnclosingJoinPoint();
234         }
235     }
236
237     public boolean needsStaticEnclosingJoinPointFormal() {
238         setJoinPointFlags();
239         return needsStaticEnclosingJoinPoint;
240     }
241
242     public boolean needsStaticJoinPointFormal() {
243         setJoinPointFlags();
244         return needsStaticJoinPoint;
245     }
246
247     public boolean needsDynamicJoinPointFormal() {
248         setJoinPointFlags();
249         return needsDynamicJoinPoint;
250     }
251
252     public boolean needsCallSiteContext() {
253         return needsDynamicJoinPointFormal() ||
254                 needsStaticJoinPointFormal() ||
255                 needsStaticEnclosingJoinPointFormal();
256     }
257
258     public void addJoinPointFormals(Formals formals) {
259         if (needsStaticEnclosingJoinPointFormal()) formals.add(thisStaticEnclosingJoinPointFormal);
260         if (needsStaticJoinPointFormal()) formals.add(thisStaticJoinPointFormal);
261         if (needsDynamicJoinPointFormal()) formals.add(thisDynamicJoinPointFormal);
262     }
263
264
265
266     class DynamicJoinPointChecker extends Walker {
267         boolean needsDynamic = false;
268         boolean needsStatic = false;
269         boolean needsStaticEnclosing = false;
270         boolean needsFakeStatic = false;
271
272         boolean makeFakeStatics = false;
273
274         public boolean needsDynamicJoinPoint() { return needsDynamic; }
275         public boolean needsStaticJoinPoint() { return needsStatic; }
276         public boolean needsStaticEnclosingJoinPoint() { return needsStaticEnclosing; }
277
278         DynamicJoinPointChecker(JavaCompiler compiler) {
279             super(compiler);
280         }
281
282         public void checkAndFix(ASTObject body) {
283             this.process(body);
284             if (needsFakeStatic && !needsDynamic) {
285                 if (!this.getCompiler().getOptions().noMetaJoinPointOptimization) {
286                     makeFakeStatics = true;
287                     needsStatic = true;
288                     this.process(body);
289                 } else {
290                     needsDynamic = true;
291                 }
292             }
293         }
294
295         boolean isStaticEnclosingJoinPoint(VarExpr varExpr) {
296             return varExpr.getVarDec() == thisStaticEnclosingJoinPointFormal;
297         }
298
299         boolean isStaticJoinPoint(VarExpr varExpr) {
300             return varExpr.getVarDec() == thisStaticJoinPointFormal;
301         }
302
303         boolean isDynamicJoinPoint(VarExpr varExpr) {
304             return varExpr.getVarDec() == thisDynamicJoinPointFormal;
305         }
306
307         void checkNoBang(VarExpr varExpr) {
308             if (varExpr.isLhs()) {
309                 varExpr.showError("not allowed to set thisJoinPoint");
310             }
311         }
312
313         boolean isStaticPartCall(CallExpr callExpr) {
314             Expr expr = callExpr.getExpr();
315             if (expr != null && expr instanceof VarExpr &&
316                         isDynamicJoinPoint( (VarExpr)expr ))
317             {
318                 return callExpr.getMethod().getId().equals("getStaticPart");
319             }
320             return false;
321         }
322
323         boolean canTreatAsStatic(Method method) {
324             String JavaDoc id = method.getId();
325             return id.equals("toString") ||
326                 id.equals("toShortString") ||
327                 id.equals("toLongString") ||
328                 id.equals("getKind") ||
329                 id.equals("getSignature") ||
330                 id.equals("getSourceLocation") ||
331                 id.equals("getStaticPart");
332         }
333
334
335         boolean canTreatAsStatic(VarExpr varExpr) {
336             ASTObject parent = varExpr.getParent();
337             if (parent instanceof CallExpr) {
338                 Method calledMethod = ((CallExpr)parent).getMethod();
339                 return canTreatAsStatic(calledMethod);
340
341                 //??? should add a case here to catch
342
//??? tjp.getEnclosingExecutionJoinPoint().STATIC_METHOD()
343
} else if (parent instanceof BinopExpr) {
344                 BinopExpr binop = (BinopExpr)parent;
345                 if (binop.getType().isEquivalent(this.getTypeManager().getStringType())) {
346                     return true;
347                 } else {
348                     return false;
349                 }
350             } else {
351                 return false;
352             }
353         }
354
355
356         boolean inBlockThatCantRun = false;
357
358         boolean isFinalBoolean(Expr expr) {
359             // this assumes that constant folding has already happened
360
return (expr instanceof BooleanLiteralExpr);
361         }
362
363         boolean getFinalBooleanValue(Expr expr) {
364             return ((BooleanLiteralExpr)expr).getBooleanValue();
365         }
366
367         protected Expr makeNullJoinPoint() {
368             final AST ast = this.getAST();
369             return ast.makeParen(ast.forceCast(this.getTypeManager().getJoinPointType(),
370                                                ast.makeNull()));
371         }
372
373         public ASTObject process(ASTObject node) {
374             // make a good effort not to generate non-static join point objects
375
// when in an if block guarded by a false static final field
376
if (node instanceof IfStmt) {
377                 IfStmt ifStmt = (IfStmt)node;
378
379                 if (!inBlockThatCantRun && isFinalBoolean(ifStmt.getTest())) {
380                     ifStmt.setTest((Expr)process(ifStmt.getTest()));
381
382                     inBlockThatCantRun = !getFinalBooleanValue(ifStmt.getTest());
383
384                     ifStmt.setThen((Stmt)process(ifStmt.getThen()));
385
386                     inBlockThatCantRun = !inBlockThatCantRun;
387
388                     if (ifStmt.getElse() != null) {
389                         ifStmt.setElse((Stmt)process(ifStmt.getElse()));
390                     }
391
392                     inBlockThatCantRun = false;
393                     return ifStmt;
394                 } else {
395                     return super.process(ifStmt);
396                 }
397             } else if (node instanceof CallExpr) {
398                 CallExpr callExpr = (CallExpr)node;
399                 if (isStaticPartCall(callExpr)) {
400                     needsFakeStatic = true;
401                     if (makeFakeStatics) {
402                         return AdviceDec.this.getAST().makeVar(thisStaticJoinPointFormal);
403                     }
404                 }
405             } else if (node instanceof VarExpr) {
406                 VarExpr varExpr = (VarExpr)node;
407
408                 if (isStaticEnclosingJoinPoint(varExpr)) {
409                     needsStaticEnclosing = true;
410                     checkNoBang(varExpr);
411                 } else if (isStaticJoinPoint(varExpr)) {
412                     needsStatic = true;
413                     checkNoBang(varExpr);
414                 } else if (isDynamicJoinPoint(varExpr)) {
415                     checkNoBang(varExpr);
416                     if (inBlockThatCantRun) {
417                         //if (makeFakeStatics) {
418
return makeNullJoinPoint();
419                         //}
420
} else if (canTreatAsStatic(varExpr)) {
421                         needsFakeStatic = true;
422                         if (makeFakeStatics) {
423                             varExpr.setVarDec(thisStaticJoinPointFormal);
424                             varExpr.setType(null);
425                             varExpr.getType(); //XXX ugly idiom to reset the type
426
}
427                     } else {
428                         needsDynamic = true;
429                     }
430                 }
431                 return node;
432             }
433
434             return super.process(node);
435         }
436     }
437
438     protected FormalDec makeJoinPointFormal(String JavaDoc name) {
439         return getAST().makeFormal(getTypeManager().getJoinPointType(), name);
440     }
441
442     protected FormalDec makeJoinPointStaticPartFormal(String JavaDoc name) {
443         return getAST().makeFormal(getTypeManager().getJoinPointStaticPartType(), name);
444     }
445
446     protected FormalDec thisDynamicJoinPointFormal = null;
447     protected FormalDec thisStaticJoinPointFormal = null;
448     protected FormalDec thisStaticEnclosingJoinPointFormal = null;
449
450     // ------------------------------
451
// INTRO from FlowCheckerPass
452

453     protected void setupFlowWalker(FlowCheckerPass w) {
454         if (thisDynamicJoinPointFormal == null ||
455             thisStaticJoinPointFormal == null ||
456             thisStaticEnclosingJoinPointFormal == null ) {
457             throw new RuntimeException JavaDoc("join point formals not created yet");
458         }
459         w.setVars(w.getVars().addAssigned(thisDynamicJoinPointFormal)
460                   .addAssigned(thisStaticJoinPointFormal)
461                   .addAssigned(thisStaticEnclosingJoinPointFormal));
462         super.setupFlowWalker(w);
463     }
464
465     // INTRO from ASTFixerPass
466
/**
467      * Replace the advice with its corresponding MethodDec in the AspectDec
468      */

469     public ASTObject postFixAST(final ASTFixerPass fixer) {
470         return makeConcreteMethod();
471     }
472
473     protected BlockScope makeBodyScope(Scope parent) {
474         return new BlockScope(getCompiler(), parent);
475     }
476
477     //INTRO from ScopePass
478
public void preScope(ScopeWalker walker) {
479         super.preScope(walker);
480
481         if (thisDynamicJoinPointFormal == null ) {
482             thisDynamicJoinPointFormal = makeJoinPointFormal("thisJoinPoint");
483         }
484         if (thisStaticJoinPointFormal == null ) {
485             thisStaticJoinPointFormal = makeJoinPointStaticPartFormal("thisJoinPointStaticPart");
486         }
487         if (thisStaticEnclosingJoinPointFormal == null ) {
488             thisStaticEnclosingJoinPointFormal = makeJoinPointStaticPartFormal("thisEnclosingJoinPointStaticPart");
489         }
490
491         walker.process(thisDynamicJoinPointFormal);
492         walker.process(thisStaticJoinPointFormal);
493         walker.process(thisStaticEnclosingJoinPointFormal);
494
495         //XXX there must be a better way to ensure this happens
496
//walker.process(getFormal());
497
}
498
499     public void checkSpec() {
500         if (isStatic()) {
501             getCompiler().warnVersion("0.8beta1", this, "no static modifier on advice");
502         }
503         for (int i=0; i<formals.size(); i++) {
504             if (!formals.get(i).isBound) {
505                 formals.get(i).showError("not bound in this PCD");
506             }
507         }
508         getBody().checkReturnType(getReturnType());
509
510         //make sure this is done at the right time
511
getMethodDec();
512     }
513
514
515     public String JavaDoc getId() {
516         //XXX this name is probably not unique enough
517
return getAdviceKind();
518     }
519
520     public TypeD getResultTypeD() {
521         return getReturnType().makeTypeD();
522     }
523
524     public Type getReturnType() {
525         return getTypeManager().voidType;
526     }
527
528
529     public String JavaDoc toShortString() {
530         String JavaDoc modString = getModifiers().toShortString();
531         if (modString.length() > 0) {
532             modString += " ";
533         }
534
535         return modString + getAdviceKind() + getFormals().toShortString();
536     }
537
538     abstract protected String JavaDoc getAdviceKind();
539
540     public void unparse(CodeWriter writer) {
541         // do not unparse!
542
}
543
544     //BEGIN: Generated from @child and @property
545
protected Pcd pcd;
546     public Pcd getPcd() { return pcd; }
547     public void setPcd(Pcd _pcd) {
548         if (_pcd != null) _pcd.setParent(this);
549         pcd = _pcd;
550     }
551
552     public AdviceDec(SourceLocation location, Modifiers _modifiers, Formals _formals, TypeDs __throws, Pcd _pcd, CodeBody _body) {
553         super(location, _modifiers, _formals, __throws, _body);
554         setPcd(_pcd);
555     }
556     protected AdviceDec(SourceLocation source) {
557         super(source);
558     }
559
560     public ASTObject getChildAt(int childIndex) {
561         switch(childIndex) {
562         case 0: return modifiers;
563         case 1: return formals;
564         case 2: return _throws;
565         case 3: return pcd;
566         case 4: return body;
567         default: return super.getChildAt(childIndex);
568         }
569     }
570      public String JavaDoc getChildNameAt(int childIndex) {
571         switch(childIndex) {
572         case 0: return "modifiers";
573         case 1: return "formals";
574         case 2: return "throws";
575         case 3: return "pcd";
576         case 4: return "body";
577         default: return super.getChildNameAt(childIndex);
578         }
579     }
580      public void setChildAt(int childIndex, ASTObject child) {
581         switch(childIndex) {
582         case 0: setModifiers((Modifiers)child); return;
583         case 1: setFormals((Formals)child); return;
584         case 2: setThrows((TypeDs)child); return;
585         case 3: setPcd((Pcd)child); return;
586         case 4: setBody((CodeBody)child); return;
587         default: super.setChildAt(childIndex, child); return;
588         }
589     }
590      public int getChildCount() {
591         return 5;
592     }
593
594     public String JavaDoc getDefaultDisplayName() {
595         return "AdviceDec()";
596     }
597
598     //END: Generated from @child and @property
599
}
600
Popular Tags