1 24 25 package org.aspectj.compiler.crosscuts.ast; 26 27 import javax.swing.JPanel ; 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 38 39 40 public class AfterReturningAdviceDec extends AdviceDec { 41 protected String getAdviceKind() { return "afterReturning"; } 42 43 protected boolean isAfterAdvice() { return true; } 44 45 private static final String 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 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 93 static class ReturnFixerWalker extends Walker { 94 AdvicePlan plan; 95 VarDec thisResultVar; 96 String 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 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 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 173 protected void setupFlowWalker(FlowCheckerPass w) { 174 if (getExtraFormal() != null) 175 w.setVars(w.getVars().addAssigned(getExtraFormal())); 176 super.setupFlowWalker(w); 177 } 178 179 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 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 getDefaultDisplayName() { 245 return "AfterReturningAdviceDec()"; 246 } 247 248 } 250 | Popular Tags |