You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 21 години
преди 4 години
преди 4 години
преди 4 години
преди 21 години
преди 21 години
преди 12 години
преди 21 години
преди 21 години
преди 15 години
преди 21 години
преди 4 години
преди 21 години
преди 15 години
преди 21 години
преди 4 години
преди 15 години
преди 15 години
преди 15 години
преди 21 години
преди 10 години
преди 21 години
преди 21 години
преди 21 години
преди 15 години
преди 12 години
преди 21 години
преди 15 години
преди 15 години
преди 15 години
преди 21 години
преди 15 години
преди 15 години
преди 12 години
преди 15 години
преди 15 години
преди 21 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 4 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 12 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 12 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 12 години
преди 21 години
преди 12 години
преди 21 години
преди 15 години
преди 4 години
преди 21 години
преди 12 години
преди 21 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 21 години
преди 15 години
преди 15 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 21 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 15 години
преди 15 години
преди 15 години
преди 21 години
преди 21 години
преди 21 години
преди 15 години
преди 21 години
преди 15 години
преди 21 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v 2.0
  6. * which accompanies this distribution and is available at
  7. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.internal.compiler.ast;
  13. import java.lang.reflect.Modifier;
  14. import java.util.ArrayList;
  15. import java.util.List;
  16. import org.aspectj.ajdt.internal.compiler.lookup.AjTypeConstants;
  17. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  18. import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedHandler;
  19. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  20. import org.aspectj.bridge.context.ContextToken;
  21. import org.aspectj.org.eclipse.jdt.core.Flags;
  22. import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
  23. import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
  24. import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
  25. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
  26. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument;
  27. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
  28. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
  29. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
  30. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
  31. import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.CodeStream;
  32. import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.Opcodes;
  33. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
  34. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  35. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
  36. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
  37. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
  38. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  39. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
  40. import org.aspectj.weaver.Advice;
  41. import org.aspectj.weaver.AdviceKind;
  42. import org.aspectj.weaver.AjAttribute;
  43. import org.aspectj.weaver.NameMangler;
  44. import org.aspectj.weaver.ResolvedMember;
  45. import org.aspectj.weaver.UnresolvedType;
  46. /**
  47. * Represents before, after and around advice in an aspect. Will generate a method corresponding to the body of the advice with an
  48. * attribute including additional information.
  49. *
  50. * @author Jim Hugunin
  51. */
  52. public class AdviceDeclaration extends AjMethodDeclaration {
  53. public PointcutDesignator pointcutDesignator; // set during parsing
  54. int baseArgumentCount; // referenced by IfPseudoToken.makeArguments
  55. public Argument extraArgument; // set during parsing, referenced by Proceed
  56. public AdviceKind kind; // set during parsing, referenced by Proceed and AsmElementFormatter
  57. private int extraArgumentFlags = 0;
  58. public int adviceSequenceNumberInType;
  59. public MethodBinding proceedMethodBinding; // set during this.resolveStaments, referenced by Proceed
  60. public List<Proceed> proceedCalls = new ArrayList<>(2); // populated during Proceed.findEnclosingAround
  61. private boolean proceedInInners;
  62. private ResolvedMember[] proceedCallSignatures;
  63. private boolean[] formalsUnchangedToProceed;
  64. private UnresolvedType[] declaredExceptions;
  65. public AdviceDeclaration(CompilationResult result, AdviceKind kind) {
  66. super(result);
  67. this.returnType = TypeReference.baseTypeReference(T_void, 0,null);
  68. this.kind = kind;
  69. }
  70. // override
  71. protected int generateInfoAttributes(ClassFile classFile) {
  72. List<EclipseAttributeAdapter> l = new ArrayList<>(1);
  73. l.add(new EclipseAttributeAdapter(makeAttribute()));
  74. addDeclarationStartLineAttribute(l, classFile);
  75. return classFile.generateMethodInfoAttributes(binding, l);
  76. }
  77. private AjAttribute makeAttribute() {
  78. if (kind == AdviceKind.Around) {
  79. return new AjAttribute.AdviceAttribute(kind, pointcutDesignator.getPointcut(), extraArgumentFlags, sourceStart,
  80. sourceEnd, null, proceedInInners, proceedCallSignatures, formalsUnchangedToProceed, declaredExceptions);
  81. } else {
  82. return new AjAttribute.AdviceAttribute(kind, pointcutDesignator.getPointcut(), extraArgumentFlags, sourceStart,
  83. sourceEnd, null);
  84. }
  85. }
  86. // override
  87. public void resolveStatements() {
  88. if (binding == null || ignoreFurtherInvestigation)
  89. return;
  90. ClassScope upperScope = (ClassScope) scope.parent; // !!! safety
  91. modifiers = checkAndSetModifiers(modifiers, upperScope);
  92. int bindingModifiers = (modifiers | (binding.modifiers & ExtraCompilerModifiers.AccGenericSignature));
  93. binding.modifiers = bindingModifiers;
  94. if (kind == AdviceKind.AfterThrowing && extraArgument != null) {
  95. TypeBinding argTb = extraArgument.binding.type;
  96. TypeBinding expectedTb = upperScope.getJavaLangThrowable();
  97. if (!argTb.isCompatibleWith(expectedTb)) {
  98. scope.problemReporter().typeMismatchError(argTb, expectedTb, extraArgument,null);
  99. ignoreFurtherInvestigation = true;
  100. return;
  101. }
  102. }
  103. pointcutDesignator.finishResolveTypes(this, this.binding, baseArgumentCount, upperScope.referenceContext.binding);
  104. if (binding == null || ignoreFurtherInvestigation)
  105. return;
  106. if (kind == AdviceKind.Around) {
  107. ReferenceBinding[] exceptions = new ReferenceBinding[] { upperScope.getJavaLangThrowable() };
  108. proceedMethodBinding = new MethodBinding(Modifier.STATIC | Flags.AccSynthetic, "proceed".toCharArray(),
  109. binding.returnType, resize(baseArgumentCount + 1, binding.parameters), exceptions, binding.declaringClass);
  110. proceedMethodBinding.selector = CharOperation.concat(selector, proceedMethodBinding.selector);
  111. }
  112. super.resolveStatements(); // upperScope);
  113. if (binding != null)
  114. determineExtraArgumentFlags();
  115. if (kind == AdviceKind.Around) {
  116. int n = proceedCalls.size();
  117. // EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(upperScope);
  118. // System.err.println("access to: " + Arrays.asList(handler.getMembers()));
  119. // XXX set these correctly
  120. formalsUnchangedToProceed = new boolean[baseArgumentCount];
  121. proceedCallSignatures = new ResolvedMember[0];
  122. proceedInInners = false;
  123. declaredExceptions = new UnresolvedType[0];
  124. for (Proceed call : proceedCalls) {
  125. if (call.inInner) {
  126. // System.err.println("proceed in inner: " + call);
  127. proceedInInners = true;
  128. // XXX wrong
  129. // proceedCallSignatures[i] = world.makeResolvedMember(call.binding);
  130. }
  131. }
  132. // ??? should reorganize into AspectDeclaration
  133. // if we have proceed in inners we won't ever be inlined so the code below is unneeded
  134. if (!proceedInInners) {
  135. PrivilegedHandler handler = (PrivilegedHandler) upperScope.referenceContext.binding.privilegedHandler;
  136. if (handler == null) {
  137. handler = new PrivilegedHandler((AspectDeclaration) upperScope.referenceContext);
  138. // upperScope.referenceContext.binding.privilegedHandler = handler;
  139. }
  140. this.traverse(new MakeDeclsPublicVisitor(), (ClassScope) null);
  141. AccessForInlineVisitor v = new AccessForInlineVisitor((AspectDeclaration) upperScope.referenceContext, handler);
  142. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ACCESS_FOR_INLINE,
  143. selector);
  144. this.traverse(v, (ClassScope) null);
  145. CompilationAndWeavingContext.leavingPhase(tok);
  146. // ??? if we found a construct that we can't inline, set
  147. // proceedInInners so that we won't try to inline this body
  148. if (!v.isInlinable)
  149. proceedInInners = true;
  150. }
  151. }
  152. }
  153. // called by Proceed.resolveType
  154. public int getDeclaredParameterCount() {
  155. // this only works before code generation
  156. if (this.arguments == null) {
  157. // Indicates something seriously wrong and a separate error should show the real problem.
  158. // (for example duplicate .aj file: https://bugs.eclipse.org/bugs/show_bug.cgi?id=549583)
  159. return 0;
  160. } else {
  161. return this.arguments.length - 3 - ((extraArgument == null) ? 0 : 1);
  162. }
  163. // Advice.countOnes(extraArgumentFlags);
  164. }
  165. private void generateProceedMethod(ClassScope classScope, ClassFile classFile) {
  166. MethodBinding binding = proceedMethodBinding;
  167. classFile.generateMethodInfoHeader(binding);
  168. int methodAttributeOffset = classFile.contentsOffset;
  169. int attributeNumber = classFile.generateMethodInfoAttributes(binding, AstUtil.getAjSyntheticAttribute());
  170. int codeAttributeOffset = classFile.contentsOffset;
  171. classFile.generateCodeAttributeHeader();
  172. CodeStream codeStream = classFile.codeStream;
  173. codeStream.reset(this, classFile);
  174. // push the closure
  175. int nargs = binding.parameters.length;
  176. int closureIndex = 0;
  177. for (int i = 0; i < nargs - 1; i++) {
  178. closureIndex += AstUtil.slotsNeeded(binding.parameters[i]);
  179. }
  180. codeStream.aload(closureIndex);
  181. // build the Object[]
  182. codeStream.generateInlinedValue(nargs - 1);
  183. codeStream.newArray(new ArrayBinding(classScope.getType(TypeConstants.JAVA_LANG_OBJECT,
  184. TypeConstants.JAVA_LANG_OBJECT.length), 1, classScope.environment()));
  185. int index = 0;
  186. for (int i = 0; i < nargs - 1; i++) {
  187. TypeBinding type = binding.parameters[i];
  188. codeStream.dup();
  189. codeStream.generateInlinedValue(i);
  190. codeStream.load(type, index);
  191. index += AstUtil.slotsNeeded(type);
  192. if (type.isBaseType()) {
  193. codeStream.invoke(Opcodes.OPC_invokestatic, AjTypeConstants.getConversionMethodToObject(classScope, type), null);
  194. }
  195. codeStream.aastore();
  196. }
  197. // call run
  198. ReferenceBinding closureType = (ReferenceBinding) binding.parameters[nargs - 1];
  199. MethodBinding runMethod = closureType.getMethods("run".toCharArray())[0];
  200. codeStream.invoke(Opcodes.OPC_invokevirtual, runMethod, null);
  201. TypeBinding returnType = binding.returnType;
  202. if (returnType.isBaseType()) {
  203. codeStream.invoke(Opcodes.OPC_invokestatic, AjTypeConstants.getConversionMethodFromObject(classScope, returnType), null);
  204. } else {
  205. codeStream.checkcast(returnType);
  206. }
  207. AstUtil.generateReturn(returnType, codeStream);
  208. codeStream.recordPositionsFrom(0, 1);
  209. classFile.completeCodeAttribute(codeAttributeOffset,scope);
  210. attributeNumber++;
  211. classFile.completeMethodInfo(binding,methodAttributeOffset, attributeNumber);
  212. }
  213. // override
  214. public void generateCode(ClassScope classScope, ClassFile classFile) {
  215. if (ignoreFurtherInvestigation)
  216. return;
  217. super.generateCode(classScope, classFile);
  218. if (proceedMethodBinding != null) {
  219. generateProceedMethod(classScope, classFile);
  220. }
  221. }
  222. private void determineExtraArgumentFlags() {
  223. if (extraArgument != null)
  224. extraArgumentFlags |= Advice.ExtraArgument;
  225. ThisJoinPointVisitor tjp = new ThisJoinPointVisitor(this);
  226. extraArgumentFlags |= tjp.removeUnusedExtraArguments();
  227. }
  228. private static TypeBinding[] resize(int newSize, TypeBinding[] bindings) {
  229. int len = bindings.length;
  230. TypeBinding[] ret = new TypeBinding[newSize];
  231. System.arraycopy(bindings, 0, ret, 0, Math.min(newSize, len));
  232. return ret;
  233. }
  234. /**
  235. * Add either the @Before, @After, @Around, @AfterReturning or @AfterThrowing annotation
  236. */
  237. public void addAtAspectJAnnotations() {
  238. Annotation adviceAnnotation = null;
  239. String pointcutExpression = pointcutDesignator.getPointcut().toString();
  240. String extraArgumentName = "";
  241. if (extraArgument != null) {
  242. extraArgumentName = new String(extraArgument.name);
  243. }
  244. String argNames = buildArgNameRepresentation();
  245. if (kind == AdviceKind.Before) {
  246. adviceAnnotation = AtAspectJAnnotationFactory.createBeforeAnnotation(pointcutExpression, argNames,
  247. declarationSourceStart);
  248. } else if (kind == AdviceKind.After) {
  249. adviceAnnotation = AtAspectJAnnotationFactory.createAfterAnnotation(pointcutExpression, argNames,
  250. declarationSourceStart);
  251. } else if (kind == AdviceKind.AfterReturning) {
  252. adviceAnnotation = AtAspectJAnnotationFactory.createAfterReturningAnnotation(pointcutExpression, argNames,
  253. extraArgumentName, declarationSourceStart);
  254. } else if (kind == AdviceKind.AfterThrowing) {
  255. adviceAnnotation = AtAspectJAnnotationFactory.createAfterThrowingAnnotation(pointcutExpression, argNames,
  256. extraArgumentName, declarationSourceStart);
  257. } else if (kind == AdviceKind.Around) {
  258. adviceAnnotation = AtAspectJAnnotationFactory.createAroundAnnotation(pointcutExpression, argNames,
  259. declarationSourceStart);
  260. }
  261. AtAspectJAnnotationFactory.addAnnotation(this, adviceAnnotation, this.scope);
  262. }
  263. private String buildArgNameRepresentation() {
  264. StringBuilder args = new StringBuilder();
  265. int numArgsWeCareAbout = getDeclaredParameterCount();
  266. if (this.arguments != null) {
  267. for (int i = 0; i < numArgsWeCareAbout; i++) {
  268. if (i != 0)
  269. args.append(",");
  270. args.append(new String(this.arguments[i].name));
  271. }
  272. }
  273. if (extraArgument != null) {
  274. if (numArgsWeCareAbout > 0) {
  275. args.append(",");
  276. }
  277. args.append(new String(extraArgument.name));
  278. }
  279. return args.toString();
  280. }
  281. // override, Called by ClassScope.postParse
  282. public void postParse(TypeDeclaration typeDec) {
  283. AspectDeclaration aspectDecl = (AspectDeclaration) typeDec;
  284. adviceSequenceNumberInType = aspectDecl.adviceCounter++;
  285. StringBuffer stringifiedPointcut = new StringBuffer(30);
  286. pointcutDesignator.print(0, stringifiedPointcut);
  287. this.selector = NameMangler.adviceName(EclipseFactory.getName(typeDec.binding).replace('.', '_'), kind,
  288. adviceSequenceNumberInType, stringifiedPointcut.toString().hashCode()).toCharArray();
  289. if (arguments != null) {
  290. baseArgumentCount = arguments.length;
  291. }
  292. if (kind == AdviceKind.Around) {
  293. extraArgument = makeFinalArgument("ajc$aroundClosure", AjTypeConstants.getAroundClosureType());
  294. }
  295. int addedArguments = 3;
  296. if (extraArgument != null) {
  297. addedArguments += 1;
  298. }
  299. arguments = extendArgumentsLength(arguments, addedArguments);
  300. int index = baseArgumentCount;
  301. if (extraArgument != null) {
  302. arguments[index++] = extraArgument;
  303. }
  304. arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  305. arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType());
  306. arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  307. if (pointcutDesignator.isError()) {
  308. this.ignoreFurtherInvestigation = true;
  309. }
  310. pointcutDesignator.postParse(typeDec, this);
  311. }
  312. private int checkAndSetModifiers(int modifiers, ClassScope scope) {
  313. if (modifiers == 0)
  314. return Modifier.PUBLIC;
  315. else if (modifiers == Modifier.STRICT)
  316. return Modifier.PUBLIC | Modifier.STRICT;
  317. else {
  318. tagAsHavingErrors();
  319. scope.problemReporter().signalError(declarationSourceStart, sourceStart - 1,
  320. "illegal modifier on advice, only strictfp is allowed");
  321. return Modifier.PUBLIC;
  322. }
  323. }
  324. // called by IfPseudoToken
  325. public static Argument[] addTjpArguments(Argument[] arguments, TypeDeclaration containingTypeDec) {
  326. int index = arguments.length;
  327. arguments = extendArgumentsLength(arguments, 4);
  328. arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  329. arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType());
  330. arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  331. arguments[index++] = makeFinalArgument("thisAspectInstance", toReference(containingTypeDec.name));
  332. return arguments;
  333. }
  334. private static TypeReference toReference(char[] typename) {
  335. if (CharOperation.contains('.', typename)) {
  336. char[][] compoundName = CharOperation.splitOn('.', typename);
  337. return new QualifiedTypeReference(compoundName, new long[compoundName.length]);
  338. } else {
  339. return new SingleTypeReference(typename, 0);
  340. }
  341. }
  342. private static Argument makeFinalArgument(String name, TypeReference typeRef) {
  343. long pos = 0; // XXX encode start and end location
  344. return new Argument(name.toCharArray(), pos, typeRef, Modifier.FINAL);
  345. }
  346. private static Argument[] extendArgumentsLength(Argument[] args, int addedArguments) {
  347. if (args == null) {
  348. return new Argument[addedArguments];
  349. }
  350. int len = args.length;
  351. Argument[] ret = new Argument[len + addedArguments];
  352. System.arraycopy(args, 0, ret, 0, len);
  353. return ret;
  354. }
  355. // public String toString(int tab) {
  356. // String s = tabString(tab);
  357. // if (modifiers != AccDefault) {
  358. // s += modifiersString(modifiers);
  359. // }
  360. //
  361. // if (kind == AdviceKind.Around) {
  362. // s += returnTypeToString(0);
  363. // }
  364. //
  365. // s += new String(selector) + "("; //$NON-NLS-1$
  366. // if (arguments != null) {
  367. // for (int i = 0; i < arguments.length; i++) {
  368. // s += arguments[i].toString(0);
  369. // if (i != (arguments.length - 1))
  370. // s = s + ", "; //$NON-NLS-1$
  371. // };
  372. // };
  373. // s += ")"; //$NON-NLS-1$
  374. //
  375. // if (extraArgument != null) {
  376. // s += "(" + extraArgument.toString(0) + ")";
  377. // }
  378. //
  379. //
  380. //
  381. // if (thrownExceptions != null) {
  382. // s += " throws "; //$NON-NLS-1$
  383. // for (int i = 0; i < thrownExceptions.length; i++) {
  384. // s += thrownExceptions[i].toString(0);
  385. // if (i != (thrownExceptions.length - 1))
  386. // s = s + ", "; //$NON-NLS-1$
  387. // };
  388. // };
  389. //
  390. // s += ": ";
  391. // if (pointcutDesignator != null) {
  392. // s += pointcutDesignator.toString(0);
  393. // }
  394. //
  395. // s += toStringStatements(tab + 1);
  396. // return s;
  397. // }
  398. public StringBuffer printBody(int indent, StringBuffer output) {
  399. output.append(": ");
  400. if (pointcutDesignator != null) {
  401. output.append(pointcutDesignator.toString());
  402. }
  403. return super.printBody(indent, output);
  404. }
  405. public StringBuffer printReturnType(int indent, StringBuffer output) {
  406. if (this.kind == AdviceKind.Around) {
  407. return super.printReturnType(indent, output);
  408. }
  409. return output;
  410. }
  411. }