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

21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
21 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  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. * 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.weaver.Advice;
  20. import org.aspectj.weaver.AdviceKind;
  21. import org.aspectj.weaver.AjAttribute;
  22. import org.aspectj.weaver.NameMangler;
  23. import org.aspectj.weaver.ResolvedMember;
  24. import org.aspectj.weaver.TypeX;
  25. import org.eclipse.jdt.internal.compiler.ClassFile;
  26. import org.eclipse.jdt.internal.compiler.CompilationResult;
  27. import org.eclipse.jdt.internal.compiler.ast.Argument;
  28. import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
  29. import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
  30. import org.eclipse.jdt.internal.compiler.ast.TypeReference;
  31. import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
  32. import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
  33. import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  34. import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
  35. import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
  36. import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  37. import org.eclipse.jdt.core.compiler.CharOperation;
  38. /**
  39. * Represents before, after and around advice in an aspect.
  40. * Will generate a method corresponding to the body of the advice with an
  41. * attribute including additional information.
  42. *
  43. * @author Jim Hugunin
  44. */
  45. public class AdviceDeclaration extends MethodDeclaration {
  46. public PointcutDesignator pointcutDesignator;
  47. int baseArgumentCount;
  48. public Argument extraArgument;
  49. public AdviceKind kind;
  50. private int extraArgumentFlags = 0;
  51. public MethodBinding proceedMethodBinding;
  52. public List proceedCalls = new ArrayList(2);
  53. public boolean proceedInInners;
  54. public ResolvedMember[] proceedCallSignatures;
  55. public boolean[] formalsUnchangedToProceed;
  56. public TypeX[] declaredExceptions;
  57. public AdviceDeclaration(CompilationResult result, AdviceKind kind) {
  58. super(result);
  59. this.returnType = TypeReference.baseTypeReference(T_void, 0);
  60. this.kind = kind;
  61. }
  62. protected int generateInfoAttributes(ClassFile classFile) {
  63. List l = new ArrayList(1);
  64. l.add(new EclipseAttributeAdapter(makeAttribute()));
  65. return classFile.generateMethodInfoAttribute(binding, l);
  66. }
  67. public AjAttribute makeAttribute() {
  68. if (kind == AdviceKind.Around) {
  69. return new AjAttribute.AdviceAttribute(kind, pointcutDesignator.getPointcut(),
  70. extraArgumentFlags, sourceStart, sourceEnd, null,
  71. proceedInInners, proceedCallSignatures, formalsUnchangedToProceed,
  72. declaredExceptions);
  73. } else {
  74. return new AjAttribute.AdviceAttribute(kind, pointcutDesignator.getPointcut(),
  75. extraArgumentFlags, sourceStart, sourceEnd, null);
  76. }
  77. }
  78. public void resolveStatements() {
  79. if (binding == null || ignoreFurtherInvestigation) return;
  80. ClassScope upperScope = (ClassScope)scope.parent; //!!! safety
  81. modifiers = binding.modifiers = checkAndSetModifiers(modifiers, upperScope);
  82. if (kind == AdviceKind.AfterThrowing && extraArgument != null) {
  83. TypeBinding argTb = extraArgument.binding.type;
  84. TypeBinding expectedTb = upperScope.getJavaLangThrowable();
  85. if (!argTb.isCompatibleWith(expectedTb)) {
  86. scope.problemReporter().typeMismatchError(argTb, expectedTb, extraArgument);
  87. ignoreFurtherInvestigation = true;
  88. return;
  89. }
  90. }
  91. pointcutDesignator.finishResolveTypes(this, this.binding,
  92. baseArgumentCount, upperScope.referenceContext.binding);
  93. if (binding == null || ignoreFurtherInvestigation) return;
  94. if (kind == AdviceKind.Around) {
  95. ReferenceBinding[] exceptions =
  96. new ReferenceBinding[] { upperScope.getJavaLangThrowable() };
  97. proceedMethodBinding = new MethodBinding(Modifier.STATIC,
  98. "proceed".toCharArray(), binding.returnType,
  99. resize(baseArgumentCount+1, binding.parameters),
  100. exceptions, binding.declaringClass);
  101. proceedMethodBinding.selector =
  102. CharOperation.concat(selector, proceedMethodBinding.selector);
  103. }
  104. super.resolveStatements(); //upperScope);
  105. if (binding != null) determineExtraArgumentFlags();
  106. if (kind == AdviceKind.Around) {
  107. int n = proceedCalls.size();
  108. EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(upperScope);
  109. //System.err.println("access to: " + Arrays.asList(handler.getMembers()));
  110. //XXX set these correctly
  111. formalsUnchangedToProceed = new boolean[baseArgumentCount];
  112. proceedCallSignatures = new ResolvedMember[0];
  113. proceedInInners = false;
  114. declaredExceptions = new TypeX[0];
  115. for (int i=0; i < n; i++) {
  116. Proceed call = (Proceed)proceedCalls.get(i);
  117. if (call.inInner) {
  118. //System.err.println("proceed in inner: " + call);
  119. proceedInInners = true;
  120. //XXX wrong
  121. //proceedCallSignatures[i] = world.makeResolvedMember(call.binding);
  122. }
  123. }
  124. // ??? should reorganize into AspectDeclaration
  125. // if we have proceed in inners we won't ever be inlined so the code below is unneeded
  126. if (!proceedInInners) {
  127. PrivilegedHandler handler = (PrivilegedHandler)upperScope.referenceContext.binding.privilegedHandler;
  128. if (handler == null) {
  129. handler = new PrivilegedHandler((AspectDeclaration)upperScope.referenceContext);
  130. //upperScope.referenceContext.binding.privilegedHandler = handler;
  131. }
  132. this.traverse(new MakeDeclsPublicVisitor(), (ClassScope)null);
  133. AccessForInlineVisitor v = new AccessForInlineVisitor((AspectDeclaration)upperScope.referenceContext, handler);
  134. this.traverse(v, (ClassScope) null);
  135. // ??? if we found a construct that we can't inline, set
  136. // proceedInInners so that we won't try to inline this body
  137. if (!v.isInlinable) proceedInInners = true;
  138. }
  139. }
  140. }
  141. public int getDeclaredParameterCount() {
  142. // this only works before code generation
  143. return this.arguments.length - 3 - ((extraArgument == null) ? 0 : 1);
  144. //Advice.countOnes(extraArgumentFlags);
  145. }
  146. public void generateProceedMethod(ClassScope classScope, ClassFile classFile) {
  147. MethodBinding binding = (MethodBinding)proceedMethodBinding;
  148. classFile.generateMethodInfoHeader(binding);
  149. int methodAttributeOffset = classFile.contentsOffset;
  150. int attributeNumber = classFile.generateMethodInfoAttribute(binding, AstUtil.getAjSyntheticAttribute());
  151. int codeAttributeOffset = classFile.contentsOffset;
  152. classFile.generateCodeAttributeHeader();
  153. CodeStream codeStream = classFile.codeStream;
  154. codeStream.reset(this, classFile);
  155. // push the closure
  156. int nargs = binding.parameters.length;
  157. int closureIndex = 0;
  158. for (int i=0; i < nargs-1; i++) {
  159. closureIndex += AstUtil.slotsNeeded(binding.parameters[i]);
  160. }
  161. codeStream.loadObject(closureIndex);
  162. // build the Object[]
  163. codeStream.generateInlinedValue(nargs-1);
  164. codeStream.newArray(classScope, new ArrayBinding(classScope.getType(TypeBinding.JAVA_LANG_OBJECT), 1));
  165. int index = 0;
  166. for (int i=0; i < nargs-1; i++) {
  167. TypeBinding type = binding.parameters[i];
  168. codeStream.dup();
  169. codeStream.generateInlinedValue(i);
  170. codeStream.load(type, index);
  171. index += AstUtil.slotsNeeded(type);
  172. if (type.isBaseType()) {
  173. codeStream.invokestatic(AjTypeConstants.getConversionMethodToObject(classScope, type));
  174. }
  175. codeStream.aastore();
  176. }
  177. // call run
  178. ReferenceBinding closureType = (ReferenceBinding)binding.parameters[nargs-1];
  179. MethodBinding runMethod = closureType.getMethods("run".toCharArray())[0];
  180. codeStream.invokevirtual(runMethod);
  181. TypeBinding returnType = binding.returnType;
  182. if (returnType.isBaseType()) {
  183. codeStream.invokestatic(AjTypeConstants.getConversionMethodFromObject(classScope, returnType));
  184. } else {
  185. codeStream.checkcast(returnType);
  186. }
  187. AstUtil.generateReturn(returnType, codeStream);
  188. classFile.completeCodeAttribute(codeAttributeOffset);
  189. attributeNumber++;
  190. classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
  191. }
  192. public void generateCode(ClassScope classScope, ClassFile classFile) {
  193. if (ignoreFurtherInvestigation) return;
  194. super.generateCode(classScope, classFile);
  195. if (proceedMethodBinding != null) {
  196. generateProceedMethod(classScope, classFile);
  197. }
  198. }
  199. private void determineExtraArgumentFlags() {
  200. if (extraArgument != null) extraArgumentFlags |= Advice.ExtraArgument;
  201. ThisJoinPointVisitor tjp = new ThisJoinPointVisitor(this);
  202. extraArgumentFlags |= tjp.removeUnusedExtraArguments();
  203. }
  204. private static TypeBinding[] resize(int newSize, TypeBinding[] bindings) {
  205. int len = bindings.length;
  206. TypeBinding[] ret = new TypeBinding[newSize];
  207. System.arraycopy(bindings, 0, ret, 0, Math.min(newSize, len));
  208. return ret;
  209. }
  210. public void postParse(TypeDeclaration typeDec) {
  211. this.selector =
  212. NameMangler.adviceName(EclipseFactory.fromBinding(typeDec.binding), kind, sourceStart).toCharArray();
  213. if (arguments != null) {
  214. baseArgumentCount = arguments.length;
  215. }
  216. if (kind == AdviceKind.Around) {
  217. extraArgument = makeFinalArgument("ajc_aroundClosure",
  218. AjTypeConstants.getAroundClosureType());
  219. }
  220. int addedArguments = 3;
  221. if (extraArgument != null) {
  222. addedArguments += 1;
  223. }
  224. arguments = extendArgumentsLength(arguments, addedArguments);
  225. int index = baseArgumentCount;
  226. if (extraArgument != null) {
  227. arguments[index++] = extraArgument;
  228. }
  229. arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  230. arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType());
  231. arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  232. if (pointcutDesignator.isError()) {
  233. this.ignoreFurtherInvestigation = true;
  234. }
  235. pointcutDesignator.postParse(typeDec, this);
  236. }
  237. private int checkAndSetModifiers(int modifiers, ClassScope scope) {
  238. if (modifiers == 0) return Modifier.PUBLIC;
  239. else if (modifiers == Modifier.STRICT) return Modifier.PUBLIC | Modifier.STRICT;
  240. else {
  241. tagAsHavingErrors();
  242. scope.problemReporter().signalError(declarationSourceStart, sourceStart-1, "illegal modifier on advice, only strictfp is allowed");
  243. return Modifier.PUBLIC;
  244. }
  245. }
  246. public static Argument[] addTjpArguments(Argument[] arguments) {
  247. int index = arguments.length;
  248. arguments = extendArgumentsLength(arguments, 3);
  249. arguments[index++] = makeFinalArgument("thisJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  250. arguments[index++] = makeFinalArgument("thisJoinPoint", AjTypeConstants.getJoinPointType());
  251. arguments[index++] = makeFinalArgument("thisEnclosingJoinPointStaticPart", AjTypeConstants.getJoinPointStaticPartType());
  252. return arguments;
  253. }
  254. private static Argument makeFinalArgument(String name, TypeReference typeRef) {
  255. long pos = 0; //XXX encode start and end location
  256. return new Argument(name.toCharArray(), pos, typeRef, Modifier.FINAL);
  257. }
  258. private static Argument[] extendArgumentsLength(Argument[] args, int addedArguments) {
  259. if (args == null) {
  260. return new Argument[addedArguments];
  261. }
  262. int len = args.length;
  263. Argument[] ret = new Argument[len + addedArguments];
  264. System.arraycopy(args, 0, ret, 0, len);
  265. return ret;
  266. }
  267. // public String toString(int tab) {
  268. // String s = tabString(tab);
  269. // if (modifiers != AccDefault) {
  270. // s += modifiersString(modifiers);
  271. // }
  272. //
  273. // if (kind == AdviceKind.Around) {
  274. // s += returnTypeToString(0);
  275. // }
  276. //
  277. // s += new String(selector) + "("; //$NON-NLS-1$
  278. // if (arguments != null) {
  279. // for (int i = 0; i < arguments.length; i++) {
  280. // s += arguments[i].toString(0);
  281. // if (i != (arguments.length - 1))
  282. // s = s + ", "; //$NON-NLS-1$
  283. // };
  284. // };
  285. // s += ")"; //$NON-NLS-1$
  286. //
  287. // if (extraArgument != null) {
  288. // s += "(" + extraArgument.toString(0) + ")";
  289. // }
  290. //
  291. //
  292. //
  293. // if (thrownExceptions != null) {
  294. // s += " throws "; //$NON-NLS-1$
  295. // for (int i = 0; i < thrownExceptions.length; i++) {
  296. // s += thrownExceptions[i].toString(0);
  297. // if (i != (thrownExceptions.length - 1))
  298. // s = s + ", "; //$NON-NLS-1$
  299. // };
  300. // };
  301. //
  302. // s += ": ";
  303. // if (pointcutDesignator != null) {
  304. // s += pointcutDesignator.toString(0);
  305. // }
  306. //
  307. // s += toStringStatements(tab + 1);
  308. // return s;
  309. // }
  310. public StringBuffer printBody(int indent, StringBuffer output) {
  311. output.append(": ");
  312. if (pointcutDesignator != null) {
  313. output.append(pointcutDesignator.toString());
  314. }
  315. return super.printBody(indent,output);
  316. }
  317. public StringBuffer printReturnType(int indent, StringBuffer output) {
  318. if (this.kind == AdviceKind.Around) {
  319. return super.printReturnType(indent,output);
  320. }
  321. return output;
  322. }
  323. }