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.

AdviceDeclaration.java 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * Xerox/PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.internal.compiler.ast;
  13. import java.io.*;
  14. import java.lang.reflect.*;
  15. import java.util.*;
  16. import org.aspectj.ajdt.internal.compiler.lookup.*;
  17. import org.aspectj.ajdt.internal.compiler.lookup.AjTypeConstants;
  18. import org.aspectj.weaver.*;
  19. //import org.aspectj.weaver.bcel.*;
  20. import org.eclipse.jdt.internal.compiler.*;
  21. import org.eclipse.jdt.internal.compiler.CompilationResult;
  22. import org.eclipse.jdt.internal.compiler.ast.*;
  23. import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
  24. import org.eclipse.jdt.internal.compiler.lookup.*;
  25. import org.eclipse.jdt.internal.compiler.parser.Parser;
  26. import org.eclipse.jdt.internal.core.util.CharArrayOps;
  27. /**
  28. * Represents before, after and around advice in an aspect.
  29. * Will generate a method corresponding to the body of the advice with an
  30. * attribute including additional information.
  31. *
  32. * @author Jim Hugunin
  33. */
  34. public class AdviceDeclaration extends MethodDeclaration {
  35. public PointcutDesignator pointcutDesignator;
  36. int baseArgumentCount;
  37. public Argument extraArgument;
  38. public AdviceKind kind;
  39. private int extraArgumentFlags = 0;
  40. public MethodBinding proceedMethodBinding;
  41. public AdviceDeclaration(CompilationResult result, AdviceKind kind) {
  42. super(result);
  43. this.returnType = TypeReference.baseTypeReference(T_void, 0);
  44. this.kind = kind;
  45. }
  46. protected int generateInfoAttributes(ClassFile classFile) {
  47. List l = new ArrayList(1);
  48. l.add(new EclipseAttributeAdapter(makeAttribute()));
  49. return classFile.generateMethodInfoAttribute(binding, l);
  50. }
  51. public AjAttribute makeAttribute() {
  52. return new AjAttribute.AdviceAttribute(kind, pointcutDesignator.getPointcut(),
  53. extraArgumentFlags, sourceStart, sourceEnd, null);
  54. }
  55. public void resolveStatements(ClassScope upperScope) {
  56. if (binding == null || ignoreFurtherInvestigation) return;
  57. modifiers = binding.modifiers = checkAndSetModifiers(modifiers, upperScope);
  58. pointcutDesignator.finishResolveTypes(this, this.binding,
  59. baseArgumentCount, upperScope.referenceContext.binding);
  60. if (kind == AdviceKind.Around && binding != null) {
  61. ReferenceBinding[] exceptions =
  62. new ReferenceBinding[] { upperScope.getJavaLangThrowable() };
  63. proceedMethodBinding = new MethodBinding(Modifier.STATIC,
  64. "proceed".toCharArray(), binding.returnType,
  65. resize(baseArgumentCount+1, binding.parameters),
  66. exceptions, binding.declaringClass);
  67. proceedMethodBinding.selector =
  68. CharArrayOps.concat(selector, proceedMethodBinding.selector);
  69. }
  70. super.resolveStatements(upperScope);
  71. if (binding != null) determineExtraArgumentFlags();
  72. }
  73. public int getDeclaredParameterCount() {
  74. // this only works before code generation
  75. return this.arguments.length - 3 - ((extraArgument == null) ? 0 : 1);
  76. //Advice.countOnes(extraArgumentFlags);
  77. }
  78. public void generateProceedMethod(ClassScope classScope, ClassFile classFile) {
  79. MethodBinding binding = (MethodBinding)proceedMethodBinding;
  80. classFile.generateMethodInfoHeader(binding);
  81. int methodAttributeOffset = classFile.contentsOffset;
  82. int attributeNumber = classFile.generateMethodInfoAttribute(binding, AstUtil.getAjSyntheticAttribute());
  83. int codeAttributeOffset = classFile.contentsOffset;
  84. classFile.generateCodeAttributeHeader();
  85. CodeStream codeStream = classFile.codeStream;
  86. codeStream.reset(this, classFile);
  87. // push the closure
  88. int nargs = binding.parameters.length;
  89. int closureIndex = 0;
  90. for (int i=0; i < nargs-1; i++) {
  91. closureIndex += AstUtil.slotsNeeded(binding.parameters[i]);
  92. }
  93. codeStream.loadObject(closureIndex);
  94. // build the Object[]
  95. codeStream.generateInlinedValue(nargs-1);
  96. codeStream.anewarrayJavaLangObject();
  97. int index = 0;
  98. for (int i=0; i < nargs-1; i++) {
  99. TypeBinding type = binding.parameters[i];
  100. codeStream.dup();
  101. codeStream.generateInlinedValue(i);
  102. codeStream.load(type, index);
  103. index += AstUtil.slotsNeeded(type);
  104. if (type.isBaseType()) {
  105. codeStream.invokestatic(AjTypeConstants.getConversionMethodToObject(classScope, type));
  106. }
  107. codeStream.aastore();
  108. }
  109. // call run
  110. ReferenceBinding closureType = (ReferenceBinding)binding.parameters[nargs-1];
  111. MethodBinding runMethod = closureType.getMethods("run".toCharArray())[0];
  112. codeStream.invokevirtual(runMethod);
  113. TypeBinding returnType = binding.returnType;
  114. if (returnType.isBaseType()) {
  115. codeStream.invokestatic(AjTypeConstants.getConversionMethodFromObject(classScope, returnType));
  116. } else {
  117. codeStream.checkcast(returnType);
  118. }
  119. AstUtil.generateReturn(returnType, codeStream);
  120. classFile.completeCodeAttribute(codeAttributeOffset);
  121. attributeNumber++;
  122. classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
  123. }
  124. public void generateCode(ClassScope classScope, ClassFile classFile) {
  125. super.generateCode(classScope, classFile);
  126. if (proceedMethodBinding != null) {
  127. generateProceedMethod(classScope, classFile);
  128. }
  129. }
  130. private void determineExtraArgumentFlags() {
  131. if (extraArgument != null) extraArgumentFlags |= Advice.ExtraArgument;
  132. ThisJoinPointVisitor tjp = new ThisJoinPointVisitor(this);
  133. extraArgumentFlags |= tjp.removeUnusedExtraArguments();
  134. }
  135. private static TypeBinding[] resize(int newSize, TypeBinding[] bindings) {
  136. int len = bindings.length;
  137. TypeBinding[] ret = new TypeBinding[newSize];
  138. System.arraycopy(bindings, 0, ret, 0, Math.min(newSize, len));
  139. return ret;
  140. }
  141. public void postParse(TypeDeclaration typeDec) {
  142. this.selector =
  143. NameMangler.adviceName(EclipseWorld.fromBinding(typeDec.binding), kind, sourceStart).toCharArray();
  144. if (arguments != null) {
  145. baseArgumentCount = arguments.length;
  146. }
  147. if (kind == AdviceKind.Around) {
  148. extraArgument = makeFinalArgument("ajc_aroundClosure",
  149. AjTypeConstants.getAroundClosureType());
  150. }
  151. int addedArguments = 3;
  152. if (extraArgument != null) {
  153. addedArguments += 1;
  154. }
  155. arguments = extendArgumentsLength(arguments, addedArguments);
  156. int index = baseArgumentCount;
  157. if (extraArgument != null) {
  158. arguments[index++] = extraArgument;
  159. }
  160. arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  161. arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType());
  162. arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  163. if (pointcutDesignator.isError()) {
  164. this.ignoreFurtherInvestigation = true;
  165. }
  166. pointcutDesignator.postParse(typeDec, this);
  167. }
  168. private int checkAndSetModifiers(int modifiers, ClassScope scope) {
  169. if (modifiers == 0) return Modifier.PUBLIC;
  170. else if (modifiers == Modifier.STRICT) return Modifier.PUBLIC | Modifier.STRICT;
  171. else {
  172. tagAsHavingErrors();
  173. scope.problemReporter().signalError(declarationSourceStart, sourceStart-1, "illegal modifier on advice, only strictfp is allowed");
  174. return Modifier.PUBLIC;
  175. }
  176. }
  177. public static Argument[] addTjpArguments(Argument[] arguments) {
  178. int index = arguments.length;
  179. arguments = extendArgumentsLength(arguments, 3);
  180. arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  181. arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType());
  182. arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  183. return arguments;
  184. }
  185. private static Argument makeFinalArgument(String name, TypeReference typeRef) {
  186. long pos = 0; //XXX encode start and end location
  187. return new Argument(name.toCharArray(), pos, typeRef, Modifier.FINAL);
  188. }
  189. private static Argument[] extendArgumentsLength(Argument[] args, int addedArguments) {
  190. if (args == null) {
  191. return new Argument[addedArguments];
  192. }
  193. int len = args.length;
  194. Argument[] ret = new Argument[len + addedArguments];
  195. System.arraycopy(args, 0, ret, 0, len);
  196. return ret;
  197. }
  198. public String toString(int tab) {
  199. String s = tabString(tab);
  200. if (modifiers != AccDefault) {
  201. s += modifiersString(modifiers);
  202. }
  203. if (kind == AdviceKind.Around) {
  204. s += returnTypeToString(0);
  205. }
  206. s += new String(selector) + "("; //$NON-NLS-1$
  207. if (arguments != null) {
  208. for (int i = 0; i < arguments.length; i++) {
  209. s += arguments[i].toString(0);
  210. if (i != (arguments.length - 1))
  211. s = s + ", "; //$NON-NLS-1$
  212. };
  213. };
  214. s += ")"; //$NON-NLS-1$
  215. if (extraArgument != null) {
  216. s += "(" + extraArgument.toString(0) + ")";
  217. }
  218. if (thrownExceptions != null) {
  219. s += " throws "; //$NON-NLS-1$
  220. for (int i = 0; i < thrownExceptions.length; i++) {
  221. s += thrownExceptions[i].toString(0);
  222. if (i != (thrownExceptions.length - 1))
  223. s = s + ", "; //$NON-NLS-1$
  224. };
  225. };
  226. s += ": ";
  227. if (pointcutDesignator != null) {
  228. s += pointcutDesignator.toString(0);
  229. }
  230. s += toStringStatements(tab + 1);
  231. return s;
  232. }
  233. }