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 17KB

21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
11 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  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 v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  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<Proceed>(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 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 (int i = 0; i < n; i++) {
  125. Proceed call = (Proceed) proceedCalls.get(i);
  126. if (call.inInner) {
  127. // System.err.println("proceed in inner: " + call);
  128. proceedInInners = true;
  129. // XXX wrong
  130. // proceedCallSignatures[i] = world.makeResolvedMember(call.binding);
  131. }
  132. }
  133. // ??? should reorganize into AspectDeclaration
  134. // if we have proceed in inners we won't ever be inlined so the code below is unneeded
  135. if (!proceedInInners) {
  136. PrivilegedHandler handler = (PrivilegedHandler) upperScope.referenceContext.binding.privilegedHandler;
  137. if (handler == null) {
  138. handler = new PrivilegedHandler((AspectDeclaration) upperScope.referenceContext);
  139. // upperScope.referenceContext.binding.privilegedHandler = handler;
  140. }
  141. this.traverse(new MakeDeclsPublicVisitor(), (ClassScope) null);
  142. AccessForInlineVisitor v = new AccessForInlineVisitor((AspectDeclaration) upperScope.referenceContext, handler);
  143. ContextToken tok = CompilationAndWeavingContext.enteringPhase(CompilationAndWeavingContext.ACCESS_FOR_INLINE,
  144. selector);
  145. this.traverse(v, (ClassScope) null);
  146. CompilationAndWeavingContext.leavingPhase(tok);
  147. // ??? if we found a construct that we can't inline, set
  148. // proceedInInners so that we won't try to inline this body
  149. if (!v.isInlinable)
  150. proceedInInners = true;
  151. }
  152. }
  153. }
  154. // called by Proceed.resolveType
  155. public int getDeclaredParameterCount() {
  156. // this only works before code generation
  157. return this.arguments.length - 3 - ((extraArgument == null) ? 0 : 1);
  158. // Advice.countOnes(extraArgumentFlags);
  159. }
  160. private void generateProceedMethod(ClassScope classScope, ClassFile classFile) {
  161. MethodBinding binding = proceedMethodBinding;
  162. classFile.generateMethodInfoHeader(binding);
  163. int methodAttributeOffset = classFile.contentsOffset;
  164. int attributeNumber = classFile.generateMethodInfoAttributes(binding, AstUtil.getAjSyntheticAttribute());
  165. int codeAttributeOffset = classFile.contentsOffset;
  166. classFile.generateCodeAttributeHeader();
  167. CodeStream codeStream = classFile.codeStream;
  168. codeStream.reset(this, classFile);
  169. // push the closure
  170. int nargs = binding.parameters.length;
  171. int closureIndex = 0;
  172. for (int i = 0; i < nargs - 1; i++) {
  173. closureIndex += AstUtil.slotsNeeded(binding.parameters[i]);
  174. }
  175. codeStream.aload(closureIndex);
  176. // build the Object[]
  177. codeStream.generateInlinedValue(nargs - 1);
  178. codeStream.newArray(new ArrayBinding(classScope.getType(TypeConstants.JAVA_LANG_OBJECT,
  179. TypeConstants.JAVA_LANG_OBJECT.length), 1, classScope.environment()));
  180. int index = 0;
  181. for (int i = 0; i < nargs - 1; i++) {
  182. TypeBinding type = binding.parameters[i];
  183. codeStream.dup();
  184. codeStream.generateInlinedValue(i);
  185. codeStream.load(type, index);
  186. index += AstUtil.slotsNeeded(type);
  187. if (type.isBaseType()) {
  188. codeStream.invoke(Opcodes.OPC_invokestatic, AjTypeConstants.getConversionMethodToObject(classScope, type), null);
  189. }
  190. codeStream.aastore();
  191. }
  192. // call run
  193. ReferenceBinding closureType = (ReferenceBinding) binding.parameters[nargs - 1];
  194. MethodBinding runMethod = closureType.getMethods("run".toCharArray())[0];
  195. codeStream.invoke(Opcodes.OPC_invokevirtual, runMethod, null);
  196. TypeBinding returnType = binding.returnType;
  197. if (returnType.isBaseType()) {
  198. codeStream.invoke(Opcodes.OPC_invokestatic, AjTypeConstants.getConversionMethodFromObject(classScope, returnType), null);
  199. } else {
  200. codeStream.checkcast(returnType);
  201. }
  202. AstUtil.generateReturn(returnType, codeStream);
  203. codeStream.recordPositionsFrom(0, 1);
  204. classFile.completeCodeAttribute(codeAttributeOffset);
  205. attributeNumber++;
  206. classFile.completeMethodInfo(binding,methodAttributeOffset, attributeNumber);
  207. }
  208. // override
  209. public void generateCode(ClassScope classScope, ClassFile classFile) {
  210. if (ignoreFurtherInvestigation)
  211. return;
  212. super.generateCode(classScope, classFile);
  213. if (proceedMethodBinding != null) {
  214. generateProceedMethod(classScope, classFile);
  215. }
  216. }
  217. private void determineExtraArgumentFlags() {
  218. if (extraArgument != null)
  219. extraArgumentFlags |= Advice.ExtraArgument;
  220. ThisJoinPointVisitor tjp = new ThisJoinPointVisitor(this);
  221. extraArgumentFlags |= tjp.removeUnusedExtraArguments();
  222. }
  223. private static TypeBinding[] resize(int newSize, TypeBinding[] bindings) {
  224. int len = bindings.length;
  225. TypeBinding[] ret = new TypeBinding[newSize];
  226. System.arraycopy(bindings, 0, ret, 0, Math.min(newSize, len));
  227. return ret;
  228. }
  229. /**
  230. * Add either the @Before, @After, @Around, @AfterReturning or @AfterThrowing annotation
  231. */
  232. public void addAtAspectJAnnotations() {
  233. Annotation adviceAnnotation = null;
  234. String pointcutExpression = pointcutDesignator.getPointcut().toString();
  235. String extraArgumentName = "";
  236. if (extraArgument != null) {
  237. extraArgumentName = new String(extraArgument.name);
  238. }
  239. String argNames = buildArgNameRepresentation();
  240. if (kind == AdviceKind.Before) {
  241. adviceAnnotation = AtAspectJAnnotationFactory.createBeforeAnnotation(pointcutExpression, argNames,
  242. declarationSourceStart);
  243. } else if (kind == AdviceKind.After) {
  244. adviceAnnotation = AtAspectJAnnotationFactory.createAfterAnnotation(pointcutExpression, argNames,
  245. declarationSourceStart);
  246. } else if (kind == AdviceKind.AfterReturning) {
  247. adviceAnnotation = AtAspectJAnnotationFactory.createAfterReturningAnnotation(pointcutExpression, argNames,
  248. extraArgumentName, declarationSourceStart);
  249. } else if (kind == AdviceKind.AfterThrowing) {
  250. adviceAnnotation = AtAspectJAnnotationFactory.createAfterThrowingAnnotation(pointcutExpression, argNames,
  251. extraArgumentName, declarationSourceStart);
  252. } else if (kind == AdviceKind.Around) {
  253. adviceAnnotation = AtAspectJAnnotationFactory.createAroundAnnotation(pointcutExpression, argNames,
  254. declarationSourceStart);
  255. }
  256. AtAspectJAnnotationFactory.addAnnotation(this, adviceAnnotation, this.scope);
  257. }
  258. private String buildArgNameRepresentation() {
  259. StringBuffer args = new StringBuffer();
  260. int numArgsWeCareAbout = getDeclaredParameterCount();
  261. if (this.arguments != null) {
  262. for (int i = 0; i < numArgsWeCareAbout; i++) {
  263. if (i != 0)
  264. args.append(",");
  265. args.append(new String(this.arguments[i].name));
  266. }
  267. }
  268. if (extraArgument != null) {
  269. if (numArgsWeCareAbout > 0) {
  270. args.append(",");
  271. }
  272. args.append(new String(extraArgument.name));
  273. }
  274. return args.toString();
  275. }
  276. // override, Called by ClassScope.postParse
  277. public void postParse(TypeDeclaration typeDec) {
  278. AspectDeclaration aspectDecl = (AspectDeclaration) typeDec;
  279. adviceSequenceNumberInType = aspectDecl.adviceCounter++;
  280. StringBuffer stringifiedPointcut = new StringBuffer(30);
  281. pointcutDesignator.print(0, stringifiedPointcut);
  282. this.selector = NameMangler.adviceName(EclipseFactory.getName(typeDec.binding).replace('.', '_'), kind,
  283. adviceSequenceNumberInType, stringifiedPointcut.toString().hashCode()).toCharArray();
  284. if (arguments != null) {
  285. baseArgumentCount = arguments.length;
  286. }
  287. if (kind == AdviceKind.Around) {
  288. extraArgument = makeFinalArgument("ajc$aroundClosure", AjTypeConstants.getAroundClosureType());
  289. }
  290. int addedArguments = 3;
  291. if (extraArgument != null) {
  292. addedArguments += 1;
  293. }
  294. arguments = extendArgumentsLength(arguments, addedArguments);
  295. int index = baseArgumentCount;
  296. if (extraArgument != null) {
  297. arguments[index++] = extraArgument;
  298. }
  299. arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  300. arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType());
  301. arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  302. if (pointcutDesignator.isError()) {
  303. this.ignoreFurtherInvestigation = true;
  304. }
  305. pointcutDesignator.postParse(typeDec, this);
  306. }
  307. private int checkAndSetModifiers(int modifiers, ClassScope scope) {
  308. if (modifiers == 0)
  309. return Modifier.PUBLIC;
  310. else if (modifiers == Modifier.STRICT)
  311. return Modifier.PUBLIC | Modifier.STRICT;
  312. else {
  313. tagAsHavingErrors();
  314. scope.problemReporter().signalError(declarationSourceStart, sourceStart - 1,
  315. "illegal modifier on advice, only strictfp is allowed");
  316. return Modifier.PUBLIC;
  317. }
  318. }
  319. // called by IfPseudoToken
  320. public static Argument[] addTjpArguments(Argument[] arguments, TypeDeclaration containingTypeDec) {
  321. int index = arguments.length;
  322. arguments = extendArgumentsLength(arguments, 4);
  323. arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  324. arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType());
  325. arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  326. arguments[index++] = makeFinalArgument("thisAspectInstance", toReference(containingTypeDec.name));
  327. return arguments;
  328. }
  329. private static TypeReference toReference(char[] typename) {
  330. if (CharOperation.contains('.', typename)) {
  331. char[][] compoundName = CharOperation.splitOn('.', typename);
  332. return new QualifiedTypeReference(compoundName, new long[compoundName.length]);
  333. } else {
  334. return new SingleTypeReference(typename, 0);
  335. }
  336. }
  337. private static Argument makeFinalArgument(String name, TypeReference typeRef) {
  338. long pos = 0; // XXX encode start and end location
  339. return new Argument(name.toCharArray(), pos, typeRef, Modifier.FINAL);
  340. }
  341. private static Argument[] extendArgumentsLength(Argument[] args, int addedArguments) {
  342. if (args == null) {
  343. return new Argument[addedArguments];
  344. }
  345. int len = args.length;
  346. Argument[] ret = new Argument[len + addedArguments];
  347. System.arraycopy(args, 0, ret, 0, len);
  348. return ret;
  349. }
  350. // public String toString(int tab) {
  351. // String s = tabString(tab);
  352. // if (modifiers != AccDefault) {
  353. // s += modifiersString(modifiers);
  354. // }
  355. //
  356. // if (kind == AdviceKind.Around) {
  357. // s += returnTypeToString(0);
  358. // }
  359. //
  360. // s += new String(selector) + "("; //$NON-NLS-1$
  361. // if (arguments != null) {
  362. // for (int i = 0; i < arguments.length; i++) {
  363. // s += arguments[i].toString(0);
  364. // if (i != (arguments.length - 1))
  365. // s = s + ", "; //$NON-NLS-1$
  366. // };
  367. // };
  368. // s += ")"; //$NON-NLS-1$
  369. //
  370. // if (extraArgument != null) {
  371. // s += "(" + extraArgument.toString(0) + ")";
  372. // }
  373. //
  374. //
  375. //
  376. // if (thrownExceptions != null) {
  377. // s += " throws "; //$NON-NLS-1$
  378. // for (int i = 0; i < thrownExceptions.length; i++) {
  379. // s += thrownExceptions[i].toString(0);
  380. // if (i != (thrownExceptions.length - 1))
  381. // s = s + ", "; //$NON-NLS-1$
  382. // };
  383. // };
  384. //
  385. // s += ": ";
  386. // if (pointcutDesignator != null) {
  387. // s += pointcutDesignator.toString(0);
  388. // }
  389. //
  390. // s += toStringStatements(tab + 1);
  391. // return s;
  392. // }
  393. public StringBuffer printBody(int indent, StringBuffer output) {
  394. output.append(": ");
  395. if (pointcutDesignator != null) {
  396. output.append(pointcutDesignator.toString());
  397. }
  398. return super.printBody(indent, output);
  399. }
  400. public StringBuffer printReturnType(int indent, StringBuffer output) {
  401. if (this.kind == AdviceKind.Around) {
  402. return super.printReturnType(indent, output);
  403. }
  404. return output;
  405. }
  406. }