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.

AspectDeclaration.java 54KB

21 years ago
14 years ago
14 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
14 years ago
14 years ago
21 years ago
21 years ago
21 years ago
21 years ago
14 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
14 years ago
14 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
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
14 years ago
21 years ago
14 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
14 years ago
14 years ago
21 years ago
21 years ago
14 years ago
14 years ago
21 years ago
14 years ago
14 years ago
21 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 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
14 years ago
4 years ago
21 years ago
21 years ago
21 years ago
14 years ago
14 years ago
4 years ago
4 years ago
14 years ago
14 years ago
4 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
10 years ago
10 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
4 years ago
4 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
13 years ago
10 years ago
10 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
14 years ago
14 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
14 years ago
14 years ago
21 years ago
21 years ago
14 years ago
14 years ago
21 years ago
21 years ago
14 years ago
14 years ago
14 years ago
14 years ago
21 years ago
21 years ago
14 years ago
14 years ago
13 years ago
13 years ago
14 years ago
13 years ago
14 years ago
21 years ago
21 years ago
14 years ago
14 years ago
21 years ago
13 years ago
21 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. /* *******************************************************************
  2. * Copyright (c) 2002-2010 Contributors
  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, Andy Clement (SpringSource)
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.internal.compiler.ast;
  13. import java.lang.reflect.Modifier;
  14. import java.util.ArrayList;
  15. import java.util.HashMap;
  16. import java.util.LinkedHashMap;
  17. import java.util.List;
  18. import java.util.Map;
  19. import org.aspectj.ajdt.internal.compiler.ast.AccessForInlineVisitor.SuperAccessMethodPair;
  20. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  21. import org.aspectj.ajdt.internal.compiler.lookup.EclipseScope;
  22. import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceType;
  23. import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
  24. import org.aspectj.ajdt.internal.compiler.lookup.HelperInterfaceBinding;
  25. import org.aspectj.ajdt.internal.compiler.lookup.InlineAccessFieldBinding;
  26. import org.aspectj.ajdt.internal.compiler.lookup.IntertypeMemberTypeFinder;
  27. import org.aspectj.ajdt.internal.compiler.lookup.PrivilegedHandler;
  28. import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
  29. import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
  30. import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
  31. import org.aspectj.org.eclipse.jdt.internal.compiler.IAttribute;
  32. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
  33. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Clinit;
  34. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
  35. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
  36. import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
  37. import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
  38. import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.CodeStream;
  39. import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
  40. import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.Opcodes;
  41. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
  42. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding;
  43. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  44. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
  45. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
  46. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
  47. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
  48. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
  49. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
  50. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
  51. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
  52. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
  53. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  54. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding;
  55. import org.aspectj.weaver.AjAttribute;
  56. import org.aspectj.weaver.AjcMemberMaker;
  57. import org.aspectj.weaver.NameMangler;
  58. import org.aspectj.weaver.NewMemberClassTypeMunger;
  59. import org.aspectj.weaver.ReferenceType;
  60. import org.aspectj.weaver.ResolvedMember;
  61. import org.aspectj.weaver.ResolvedType;
  62. import org.aspectj.weaver.Shadow;
  63. import org.aspectj.weaver.UnresolvedType;
  64. import org.aspectj.weaver.patterns.Declare;
  65. import org.aspectj.weaver.patterns.FormalBinding;
  66. import org.aspectj.weaver.patterns.PerClause;
  67. import org.aspectj.weaver.patterns.PerFromSuper;
  68. import org.aspectj.weaver.patterns.PerSingleton;
  69. import org.aspectj.weaver.patterns.TypePattern;
  70. /**
  71. * Represents an aspect declaration.
  72. *
  73. * @author PARC
  74. * @author Andy Clement
  75. */
  76. public class AspectDeclaration extends TypeDeclaration {
  77. // public IAjDeclaration[] ajDeclarations;
  78. // private AjAttribute.Aspect aspectAttribute;
  79. public PerClause perClause;
  80. public ResolvedMember aspectOfMethod;
  81. public ResolvedMember ptwGetWithinTypeNameMethod;
  82. public ResolvedMember hasAspectMethod;
  83. public Map<ResolvedMember, Binding> accessForInline = new LinkedHashMap<>();
  84. public Map<ResolvedMember, AccessForInlineVisitor.SuperAccessMethodPair> superAccessForInline = new HashMap<>();
  85. public boolean isPrivileged;
  86. public EclipseSourceType concreteName;
  87. public ReferenceType typeX;
  88. public EclipseFactory factory; // ??? should use this consistently
  89. public int adviceCounter = 1; // Used as a part of the generated name for advice methods
  90. public int declareCounter = 1; // Used as a part of the generated name for methods representing declares
  91. // for better error messages in 1.0 to 1.1 transition
  92. public TypePattern dominatesPattern;
  93. private int declaredModifiers;
  94. public AspectDeclaration(CompilationResult compilationResult) {
  95. super(compilationResult);
  96. // perClause = new PerSingleton();
  97. }
  98. public boolean isAbstract() {
  99. return (modifiers & ClassFileConstants.AccAbstract) != 0;
  100. }
  101. public void resolve() {
  102. declaredModifiers = modifiers; // remember our modifiers, we're going to be public in generateCode
  103. if (binding == null) {
  104. ignoreFurtherInvestigation = true;
  105. return;
  106. }
  107. super.resolve();
  108. }
  109. public void checkSpec(ClassScope scope) {
  110. if (ignoreFurtherInvestigation) {
  111. return;
  112. }
  113. if (dominatesPattern != null) {
  114. scope.problemReporter().signalError(
  115. dominatesPattern.getStart(),
  116. dominatesPattern.getEnd(),
  117. "dominates has changed for 1.1, use 'declare precedence: " + new String(this.name) + ", "
  118. + dominatesPattern.toString() + ";' " + "in the body of the aspect instead");
  119. }
  120. if (!isAbstract()) {
  121. MethodBinding[] methods = binding.methods();
  122. for (int i = 0, len = methods.length; i < len; i++) {
  123. MethodBinding m = methods[i];
  124. if (m.isConstructor()) {
  125. // this make all constructors in aspects invisible and thus uncallable
  126. // XXX this only works for aspects that come from source
  127. methods[i] = new MethodBinding(m, binding) {
  128. public boolean canBeSeenBy(InvocationSite invocationSite, Scope scope) {
  129. return false;
  130. }
  131. };
  132. if (m.parameters != null && m.parameters.length != 0) {
  133. scope.problemReporter().signalError(m.sourceStart(), m.sourceEnd(),
  134. "only zero-argument constructors allowed in concrete aspect");
  135. }
  136. }
  137. }
  138. // check the aspect was not declared generic, only abstract aspects can have type params
  139. if (typeParameters != null && typeParameters.length > 0) {
  140. scope.problemReporter().signalError(sourceStart(), sourceEnd(), "only abstract aspects can have type parameters");
  141. }
  142. }
  143. if (this.enclosingType != null) {
  144. if (
  145. !Modifier.isStatic(modifiers) &&
  146. // Inner classes/aspects of interfaces are implicitly static,
  147. // see https://github.com/eclipse/org.aspectj/issues/162
  148. (this.enclosingType.modifiers & ClassFileConstants.AccInterface) == 0
  149. ) {
  150. scope.problemReporter().signalError(sourceStart, sourceEnd, "inner aspects must be static");
  151. ignoreFurtherInvestigation = true;
  152. return;
  153. }
  154. }
  155. EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
  156. ResolvedType myType = typeX;
  157. // if (myType == null) System.err.println("bad myType for: " + this);
  158. ResolvedType superType = myType.getSuperclass();
  159. // can't be Serializable/Cloneable unless -XserializableAspects
  160. if (!world.isXSerializableAspects()) {
  161. if (world.getWorld().getCoreType(UnresolvedType.SERIALIZABLE).isAssignableFrom(myType)) {
  162. scope.problemReporter().signalError(sourceStart, sourceEnd, "aspects may not implement Serializable");
  163. ignoreFurtherInvestigation = true;
  164. return;
  165. }
  166. if (world.getWorld().getCoreType(UnresolvedType.CLONEABLE).isAssignableFrom(myType)) {
  167. scope.problemReporter().signalError(sourceStart, sourceEnd, "aspects may not implement Cloneable");
  168. ignoreFurtherInvestigation = true;
  169. return;
  170. }
  171. }
  172. if (superType.isAspect()) {
  173. if (!superType.isAbstract()) {
  174. scope.problemReporter().signalError(sourceStart, sourceEnd, "can not extend a concrete aspect");
  175. ignoreFurtherInvestigation = true;
  176. return;
  177. }
  178. // if super type is generic, check that we have fully parameterized it
  179. if (superType.isRawType()) {
  180. scope.problemReporter().signalError(sourceStart, sourceEnd,
  181. "a generic super-aspect must be fully parameterized in an extends clause");
  182. ignoreFurtherInvestigation = true;
  183. return;
  184. }
  185. }
  186. }
  187. private FieldBinding initFailureField = null;
  188. /**
  189. * AMC - this method is called by the AtAspectJVisitor during beforeCompilation processing in the AjCompiler adapter. We use
  190. * this hook to add in the @AspectJ annotations.
  191. */
  192. public void addAtAspectJAnnotations() {
  193. if (ignoreFurtherInvestigation) {
  194. // perClause likely to be null. This flag used to be checked before we got called (at e33 level, in traverse(ASTVisitor
  195. // visitor, CompilationUnitScope unitScope))
  196. // For e37 moved the check down to this level
  197. return;
  198. }
  199. if ((binding.tagBits & TagBits.AnnotationResolved) != 0) {
  200. // possibly resolution occurred during hasUnsatisfiedDependency()...
  201. binding.tagBits = (binding.tagBits & ~TagBits.AnnotationResolved);
  202. }
  203. Annotation atAspectAnnotation = AtAspectJAnnotationFactory.createAspectAnnotation(perClause.toDeclarationString(),
  204. declarationSourceStart);
  205. Annotation privilegedAnnotation = null;
  206. if (isPrivileged) {
  207. privilegedAnnotation = AtAspectJAnnotationFactory.createPrivilegedAnnotation(declarationSourceStart);
  208. }
  209. Annotation[] toAdd = new Annotation[isPrivileged ? 2 : 1];
  210. toAdd[0] = atAspectAnnotation;
  211. if (isPrivileged) {
  212. toAdd[1] = privilegedAnnotation;
  213. }
  214. if (annotations == null) {
  215. annotations = toAdd;
  216. } else {
  217. Annotation[] old = annotations;
  218. annotations = new Annotation[annotations.length + toAdd.length];
  219. System.arraycopy(old, 0, annotations, 0, old.length);
  220. System.arraycopy(toAdd, 0, annotations, old.length, toAdd.length);
  221. }
  222. TypeDeclaration.resolveAnnotations(staticInitializerScope, annotations, binding);
  223. }
  224. public void generateCode(ClassFile enclosingClassFile) {
  225. if (ignoreFurtherInvestigation) {
  226. if (binding == null) {
  227. return;
  228. }
  229. ClassFile.createProblemType(this, scope.referenceCompilationUnit().compilationResult);
  230. return;
  231. }
  232. // make me and my binding public
  233. this.modifiers = AstUtil.makePublic(this.modifiers);
  234. this.binding.modifiers = AstUtil.makePublic(this.binding.modifiers);
  235. if (!isAbstract()) {
  236. if (perClause != null && perClause.getKind() == PerClause.SINGLETON) {
  237. initFailureField = factory.createSyntheticFieldBinding(binding, AjcMemberMaker.initFailureCauseField(typeX));
  238. }
  239. // binding.addSyntheticField((SyntheticFieldBinding)initFailureField);
  240. // initFailureField = factory.makeFieldBinding(AjcMemberMaker.initFailureCauseField(typeX));
  241. // binding.addField(initFailureField);
  242. if (perClause == null) {
  243. // we've already produced an error for this
  244. } else if (perClause.getKind() == PerClause.SINGLETON) {
  245. factory.createSyntheticFieldBinding(binding, AjcMemberMaker.perSingletonField(typeX));
  246. // CUSTARD binding.addField(factory.makeFieldBinding(AjcMemberMaker.perSingletonField(typeX)));
  247. // CUSTARD
  248. methods[0] = new AspectClinit((Clinit) methods[0], compilationResult, false, true, initFailureField);
  249. } else if (perClause.getKind() == PerClause.PERCFLOW) {
  250. factory.createSyntheticFieldBinding(binding, AjcMemberMaker.perCflowField(typeX));
  251. // CUSTARD binding.addField(factory.makeFieldBinding(AjcMemberMaker.perCflowField(typeX)));
  252. methods[0] = new AspectClinit((Clinit) methods[0], compilationResult, true, false, null);
  253. } else if (perClause.getKind() == PerClause.PEROBJECT) {
  254. // binding.addField(
  255. // world.makeFieldBinding(
  256. // AjcMemberMaker.perCflowField(
  257. // typeX)));
  258. } else if (perClause.getKind() == PerClause.PERTYPEWITHIN) {
  259. factory.createSyntheticFieldBinding(binding, AjcMemberMaker.perTypeWithinWithinTypeField(typeX, typeX));
  260. // PTWIMPL Add field for storing typename in aspect for which the aspect instance exists
  261. // binding.addField(factory.makeFieldBinding(AjcMemberMaker.perTypeWithinWithinTypeField(typeX,typeX)));
  262. } else {
  263. throw new RuntimeException("unimplemented");
  264. }
  265. }
  266. if (EclipseFactory.DEBUG) {
  267. System.out.println(toString());
  268. }
  269. super.generateCode(enclosingClassFile);
  270. }
  271. public boolean needClassInitMethod() {
  272. return true;
  273. }
  274. @SuppressWarnings("unchecked")
  275. protected void generateAttributes(ClassFile classFile) {
  276. if (!isAbstract()) {
  277. generatePerSupportMembers(classFile);
  278. }
  279. generateInlineAccessMembers(classFile);
  280. addVersionAttributeIfNecessary(classFile);
  281. classFile.extraAttributes.add(new EclipseAttributeAdapter(new AjAttribute.Aspect(perClause)));
  282. if (binding.privilegedHandler != null) {
  283. // Only build the attribute if necessary
  284. PrivilegedHandler privilegedHandler = (PrivilegedHandler) binding.privilegedHandler;
  285. ResolvedMember[] members = privilegedHandler.getMembers();
  286. if (members.length > 0) {
  287. classFile.extraAttributes.add(new EclipseAttributeAdapter(new AjAttribute.PrivilegedAttribute(members)));
  288. }
  289. }
  290. if (memberTypes != null) {
  291. for (TypeDeclaration memberType : memberTypes) {
  292. if (memberType instanceof IntertypeMemberClassDeclaration) {
  293. IntertypeMemberClassDeclaration itdMemberClassDeclaration = (IntertypeMemberClassDeclaration) memberType;
  294. AjAttribute attribute = itdMemberClassDeclaration.getAttribute();
  295. if (attribute != null) {
  296. classFile.extraAttributes.add(new EclipseAttributeAdapter(attribute));
  297. }
  298. }
  299. }
  300. }
  301. // XXX need to get this attribute on anyone with a pointcut for good errors
  302. classFile.extraAttributes.add(new EclipseAttributeAdapter(new AjAttribute.SourceContextAttribute(new String(
  303. compilationResult().getFileName()), compilationResult().lineSeparatorPositions)));
  304. super.generateAttributes(classFile);
  305. }
  306. /**
  307. * A pointcut might have already added the attribute, let's not add it again.
  308. */
  309. @SuppressWarnings("unchecked")
  310. private void addVersionAttributeIfNecessary(ClassFile classFile) {
  311. for (Object o : classFile.extraAttributes) {
  312. EclipseAttributeAdapter element = (EclipseAttributeAdapter) o;
  313. if (CharOperation.equals(element.getNameChars(), weaverVersionChars)) {
  314. return;
  315. }
  316. }
  317. classFile.extraAttributes.add(new EclipseAttributeAdapter(new AjAttribute.WeaverVersionInfo()));
  318. }
  319. private static char[] weaverVersionChars = "org.aspectj.weaver.WeaverVersion".toCharArray();
  320. private void generateInlineAccessMembers(ClassFile classFile) {
  321. for (SuperAccessMethodPair pair : superAccessForInline.values()) {
  322. generateSuperAccessMethod(classFile, pair.accessMethod, pair.originalMethod);
  323. }
  324. for (Map.Entry<ResolvedMember, Binding> e : accessForInline.entrySet()) {
  325. generateInlineAccessMethod(classFile, e.getValue(), e.getKey());
  326. }
  327. }
  328. private void generatePerSupportMembers(ClassFile classFile) {
  329. if (isAbstract()) {
  330. return;
  331. }
  332. // XXX otherwise we need to have this (error handling?)
  333. if (aspectOfMethod == null) {
  334. return;
  335. }
  336. if (perClause == null) {
  337. System.err.println("has null perClause: " + this);
  338. return;
  339. }
  340. // EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  341. if (perClause.getKind() == PerClause.SINGLETON) {
  342. generatePerSingletonAspectOfMethod(classFile);
  343. generatePerSingletonHasAspectMethod(classFile);
  344. generatePerSingletonAjcClinitMethod(classFile);
  345. } else if (perClause.getKind() == PerClause.PERCFLOW) {
  346. generatePerCflowAspectOfMethod(classFile);
  347. generatePerCflowHasAspectMethod(classFile);
  348. generatePerCflowPushMethod(classFile);
  349. generatePerCflowAjcClinitMethod(classFile);
  350. } else if (perClause.getKind() == PerClause.PEROBJECT) {
  351. TypeBinding interfaceType = generatePerObjectInterface(classFile);
  352. generatePerObjectAspectOfMethod(classFile, interfaceType);
  353. generatePerObjectHasAspectMethod(classFile, interfaceType);
  354. generatePerObjectBindMethod(classFile, interfaceType);
  355. } else if (perClause.getKind() == PerClause.PERTYPEWITHIN) {
  356. // PTWIMPL Generate the methods required *in the aspect*
  357. generatePerTypeWithinAspectOfMethod(classFile); // public static <aspecttype> aspectOf(java.lang.Class)
  358. generatePerTypeWithinGetInstanceMethod(classFile); // private static <aspecttype> ajc$getInstance(Class c) throws
  359. // Exception
  360. generatePerTypeWithinHasAspectMethod(classFile);
  361. generatePerTypeWithinCreateAspectInstanceMethod(classFile); // generate public static X ajc$createAspectInstance(Class
  362. // forClass) {
  363. generatePerTypeWithinGetWithinTypeNameMethod(classFile);
  364. } else {
  365. throw new RuntimeException("unimplemented");
  366. }
  367. }
  368. private interface BodyGenerator {
  369. void generate(CodeStream codeStream);
  370. }
  371. private void generateMethod(ClassFile classFile, ResolvedMember member, BodyGenerator gen) {
  372. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  373. generateMethod(classFile, world.makeMethodBinding(member), gen);
  374. }
  375. private void generateMethod(ClassFile classFile, MethodBinding methodBinding, BodyGenerator gen) {
  376. generateMethod(classFile, methodBinding, null, gen);
  377. }
  378. protected List<EclipseAttributeAdapter> makeEffectiveSignatureAttribute(ResolvedMember sig, Shadow.Kind kind, boolean weaveBody) {
  379. List<EclipseAttributeAdapter> l = new ArrayList<>(1);
  380. l.add(new EclipseAttributeAdapter(new AjAttribute.EffectiveSignatureAttribute(sig, kind, weaveBody)));
  381. return l;
  382. }
  383. public static final char[] HAS_ASPECT = "hasAspect".toCharArray();
  384. /*
  385. * additionalAttributes allows us to pass some optional attributes we want to attach to the method we generate. Currently this
  386. * is used for inline accessor methods that have been generated to allow private field references or private method calls to be
  387. * inlined (PR71377). In these cases the optional attribute is an effective signature attribute which means calls to these
  388. * methods are able to masquerade as any join point (a field set, field get or method call). The effective signature attribute
  389. * is 'unwrapped' in BcelClassWeaver.matchInvokeInstruction()
  390. */
  391. private void generateMethod(ClassFile classFile, MethodBinding methodBinding, List<EclipseAttributeAdapter> additionalAttributes, BodyGenerator gen) {
  392. // EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  393. classFile.generateMethodInfoHeader(methodBinding);
  394. int methodAttributeOffset = classFile.contentsOffset;
  395. int attributeNumber;
  396. if (additionalAttributes != null) { // mini optimization
  397. List<IAttribute> attrs = new ArrayList<>();
  398. attrs.addAll(AstUtil.getAjSyntheticAttribute());
  399. attrs.addAll(additionalAttributes);
  400. attributeNumber = classFile.generateMethodInfoAttributes(methodBinding, attrs);
  401. } else {
  402. attributeNumber = classFile.generateMethodInfoAttributes(methodBinding, AstUtil.getAjSyntheticAttribute());
  403. }
  404. int codeAttributeOffset = classFile.contentsOffset;
  405. classFile.generateCodeAttributeHeader();
  406. CodeStream codeStream = classFile.codeStream;
  407. // Use reset() rather than init()
  408. // XXX We need a scope to keep reset happy, initializerScope is *not* the right one, but it works !
  409. // codeStream.init(classFile);
  410. // codeStream.initializeMaxLocals(methodBinding);
  411. MethodDeclaration md = AstUtil.makeMethodDeclaration(methodBinding);
  412. md.scope = initializerScope;
  413. codeStream.reset(md, classFile);
  414. // body starts here
  415. gen.generate(codeStream);
  416. // body ends here
  417. if (codeStream.pcToSourceMapSize == 0) {
  418. codeStream.recordPositionsFrom(0, 1);
  419. }
  420. // Seems a dirty hack around some underlying issue...?
  421. boolean b2 = CharOperation.equals(methodBinding.selector,HAS_ASPECT) &&
  422. ((classFile.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0 ? true : false);
  423. if (b2) {
  424. classFile.produceAttributes &= ~ClassFileConstants.ATTR_STACK_MAP_TABLE;
  425. }
  426. boolean b = ((codeStream.generateAttributes & ClassFileConstants.ATTR_VARS) != 0 ? true : false); // pr148693
  427. if (codeStream.maxLocals == 0) {
  428. codeStream.generateAttributes &= ~ClassFileConstants.ATTR_VARS;
  429. }
  430. classFile.completeCodeAttribute(codeAttributeOffset, md.scope);
  431. if (b) {
  432. codeStream.generateAttributes |= ClassFileConstants.ATTR_VARS;
  433. }
  434. if (b2) {
  435. classFile.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE;
  436. }
  437. attributeNumber++;
  438. classFile.completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber);
  439. }
  440. private void generatePerCflowAspectOfMethod(ClassFile classFile) {
  441. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  442. generateMethod(classFile, aspectOfMethod, new BodyGenerator() {
  443. public void generate(CodeStream codeStream) {
  444. // body starts here
  445. codeStream.fieldAccess(Opcodes.OPC_getstatic, world.makeFieldBinding(AjcMemberMaker.perCflowField(typeX)), null);
  446. codeStream.invoke(Opcodes.OPC_invokevirtual,
  447. world.makeMethodBindingForCall(AjcMemberMaker.cflowStackPeekInstance()), null);
  448. codeStream.checkcast(binding);
  449. codeStream.areturn();
  450. // body ends here
  451. }
  452. });
  453. }
  454. private void generatePerCflowHasAspectMethod(ClassFile classFile) {
  455. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  456. generateMethod(classFile, hasAspectMethod, new BodyGenerator() {
  457. public void generate(CodeStream codeStream) {
  458. // body starts here
  459. codeStream.fieldAccess(Opcodes.OPC_getstatic, world.makeFieldBinding(AjcMemberMaker.perCflowField(typeX)), null);
  460. codeStream.invoke(Opcodes.OPC_invokevirtual, world.makeMethodBindingForCall(AjcMemberMaker.cflowStackIsValid()),
  461. null);
  462. codeStream.ireturn();
  463. // body ends here
  464. }
  465. });
  466. }
  467. private void generatePerCflowPushMethod(ClassFile classFile) {
  468. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  469. generateMethod(classFile, world.makeMethodBinding(AjcMemberMaker.perCflowPush(factory.fromBinding(binding))),
  470. new BodyGenerator() {
  471. public void generate(CodeStream codeStream) {
  472. // body starts here
  473. codeStream.fieldAccess(Opcodes.OPC_getstatic, world.makeFieldBinding(AjcMemberMaker.perCflowField(typeX)),
  474. null);
  475. codeStream.new_(binding);
  476. codeStream.dup();
  477. codeStream.invoke(Opcodes.OPC_invokespecial, new MethodBinding(0, "<init>".toCharArray(), TypeBinding.VOID,
  478. new TypeBinding[0], new ReferenceBinding[0], binding), null);
  479. codeStream.invoke(Opcodes.OPC_invokevirtual,
  480. world.makeMethodBindingForCall(AjcMemberMaker.cflowStackPushInstance()), null);
  481. codeStream.return_();
  482. // body ends here
  483. }
  484. });
  485. }
  486. private void generatePerCflowAjcClinitMethod(ClassFile classFile) {
  487. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  488. generateMethod(classFile, world.makeMethodBinding(AjcMemberMaker.ajcPreClinitMethod(world.fromBinding(binding))),
  489. new BodyGenerator() {
  490. public void generate(CodeStream codeStream) {
  491. // body starts here
  492. codeStream.new_(world.makeTypeBinding(AjcMemberMaker.CFLOW_STACK_TYPE));
  493. codeStream.dup();
  494. codeStream.invoke(Opcodes.OPC_invokespecial,
  495. world.makeMethodBindingForCall(AjcMemberMaker.cflowStackInit()), null);
  496. codeStream.fieldAccess(Opcodes.OPC_putstatic, world.makeFieldBinding(AjcMemberMaker.perCflowField(typeX)),
  497. null);
  498. codeStream.return_();
  499. // body ends here
  500. }
  501. });
  502. }
  503. private TypeBinding generatePerObjectInterface(ClassFile classFile) {
  504. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  505. UnresolvedType interfaceTypeX = AjcMemberMaker.perObjectInterfaceType(typeX);
  506. HelperInterfaceBinding interfaceType = new HelperInterfaceBinding(this.binding, interfaceTypeX);
  507. world.addTypeBindingAndStoreInWorld(interfaceType);
  508. interfaceType.addMethod(world, AjcMemberMaker.perObjectInterfaceGet(typeX));
  509. interfaceType.addMethod(world, AjcMemberMaker.perObjectInterfaceSet(typeX));
  510. interfaceType.generateClass(compilationResult, classFile);
  511. return interfaceType;
  512. }
  513. /*
  514. * private void generatePerTypeWithinGetWithinTypeMethod(ClassFile classFile) { final EclipseFactory world =
  515. * EclipseFactory.fromScopeLookupEnvironment(this.scope); generateMethod(classFile,ptwGetWithinTypeMethod,new BodyGenerator() {
  516. * public void generate(CodeStream codeStream) { codeStream.aload_0();
  517. * codeStream.getfield(world.makeFieldBinding(AjcMemberMaker.perTypeWithinWithinTypeField(typeX,typeX))); codeStream.areturn();
  518. * }}); }
  519. */
  520. // PTWIMPL Generate aspectOf() method
  521. private void generatePerTypeWithinAspectOfMethod(ClassFile classFile) {
  522. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  523. generateMethod(classFile, aspectOfMethod, new BodyGenerator() {
  524. public void generate(CodeStream codeStream) {
  525. LocalVariableBinding theTypeVar = new LocalVariableBinding("type".toCharArray(), world
  526. .makeTypeBinding(UnresolvedType.JL_CLASS), Modifier.PUBLIC, true);
  527. codeStream.record(theTypeVar);
  528. theTypeVar.recordInitializationStartPC(0);
  529. BranchLabel instanceFound = new BranchLabel(codeStream);
  530. TypeBinding exceptionTypeBinding = world.makeTypeBinding(UnresolvedType.JL_EXCEPTION);
  531. ExceptionLabel anythingGoesWrong = new ExceptionLabel(codeStream, exceptionTypeBinding);
  532. anythingGoesWrong.placeStart();
  533. codeStream.aload_0();
  534. codeStream.invoke(Opcodes.OPC_invokestatic,
  535. world.makeMethodBindingForCall(AjcMemberMaker.perTypeWithinGetInstance(typeX)), null);
  536. LocalVariableBinding aspectInstanceVar = new LocalVariableBinding("instance".toCharArray(), world
  537. .makeTypeBinding(UnresolvedType.OBJECT), Modifier.PUBLIC, false);
  538. aspectInstanceVar.resolvedPosition = 1;
  539. codeStream.record(aspectInstanceVar);
  540. aspectInstanceVar.recordInitializationStartPC(codeStream.position);
  541. codeStream.astore_1();
  542. codeStream.aload_1();
  543. codeStream.ifnonnull(instanceFound);
  544. codeStream.new_(world.makeTypeBinding(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION));
  545. codeStream.dup();
  546. codeStream.ldc(typeX.getName());
  547. codeStream.aconst_null();
  548. codeStream.invoke(Opcodes.OPC_invokespecial,
  549. world.makeMethodBindingForCall(AjcMemberMaker.noAspectBoundExceptionInit2()), null);
  550. codeStream.athrow();
  551. instanceFound.place();
  552. codeStream.aload_1();
  553. codeStream.areturn();
  554. anythingGoesWrong.placeEnd();
  555. anythingGoesWrong.place();
  556. codeStream.pushExceptionOnStack(exceptionTypeBinding); // For stackmap computation to behave
  557. codeStream.astore_1();
  558. codeStream.new_(world.makeTypeBinding(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION));
  559. codeStream.dup();
  560. // Run the simple ctor for NABE
  561. codeStream.invoke(Opcodes.OPC_invokespecial,
  562. world.makeMethodBindingForCall(AjcMemberMaker.noAspectBoundExceptionInit()), null);
  563. codeStream.athrow();
  564. theTypeVar.recordInitializationEndPC(codeStream.position);
  565. aspectInstanceVar.recordInitializationEndPC(codeStream.position);
  566. }
  567. });
  568. }
  569. private void generatePerObjectAspectOfMethod(ClassFile classFile, final TypeBinding interfaceType) {
  570. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  571. generateMethod(classFile, aspectOfMethod, new BodyGenerator() {
  572. public void generate(CodeStream codeStream) {
  573. LocalVariableBinding objectVar = new LocalVariableBinding("object".toCharArray(), world
  574. .makeTypeBinding(UnresolvedType.OBJECT), Modifier.PUBLIC, true);
  575. codeStream.record(objectVar);
  576. objectVar.recordInitializationStartPC(0);
  577. BranchLabel wrongType = new BranchLabel(codeStream);
  578. BranchLabel returnIt = new BranchLabel(codeStream);
  579. codeStream.aload_0();
  580. codeStream.instance_of(interfaceType);
  581. codeStream.ifeq(wrongType);
  582. codeStream.aload_0();
  583. codeStream.checkcast(interfaceType);
  584. codeStream.invoke(Opcodes.OPC_invokeinterface,
  585. world.makeMethodBindingForCall(AjcMemberMaker.perObjectInterfaceGet(typeX)), null);
  586. codeStream.dup();
  587. codeStream.ifnonnull(returnIt);
  588. codeStream.pop();
  589. wrongType.place();
  590. codeStream.new_(world.makeTypeBinding(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION));
  591. codeStream.dup();
  592. codeStream.invoke(Opcodes.OPC_invokespecial,
  593. world.makeMethodBindingForCall(AjcMemberMaker.noAspectBoundExceptionInit()), null);
  594. codeStream.athrow();
  595. returnIt.place();
  596. codeStream.areturn();
  597. codeStream.locals[0].recordInitializationEndPC(codeStream.position);
  598. // body ends here
  599. }
  600. });
  601. }
  602. private void generatePerObjectHasAspectMethod(ClassFile classFile, final TypeBinding interfaceType) {
  603. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  604. generateMethod(classFile, hasAspectMethod, new BodyGenerator() {
  605. public void generate(CodeStream codeStream) {
  606. // body starts here
  607. LocalVariableBinding objectVar = new LocalVariableBinding("object".toCharArray(), world
  608. .makeTypeBinding(UnresolvedType.OBJECT), Modifier.PUBLIC, true);
  609. codeStream.record(objectVar);
  610. objectVar.recordInitializationStartPC(0);
  611. BranchLabel wrongType = new BranchLabel(codeStream);
  612. codeStream.aload_0();
  613. codeStream.instance_of(interfaceType);
  614. codeStream.ifeq(wrongType);
  615. codeStream.aload_0();
  616. codeStream.checkcast(interfaceType);
  617. codeStream.invoke(Opcodes.OPC_invokeinterface,
  618. world.makeMethodBindingForCall(AjcMemberMaker.perObjectInterfaceGet(typeX)), null);
  619. codeStream.ifnull(wrongType);
  620. codeStream.iconst_1();
  621. codeStream.ireturn();
  622. wrongType.place();
  623. codeStream.iconst_0();
  624. codeStream.ireturn();
  625. codeStream.locals[0].recordInitializationEndPC(codeStream.position);
  626. // body ends here
  627. }
  628. });
  629. }
  630. // PTWIMPL Generate hasAspect() method
  631. private void generatePerTypeWithinHasAspectMethod(ClassFile classFile) {
  632. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  633. generateMethod(classFile, hasAspectMethod, new BodyGenerator() {
  634. public void generate(CodeStream codeStream) {
  635. LocalVariableBinding classVariable = new LocalVariableBinding("clazz".toCharArray(), world
  636. .makeTypeBinding(UnresolvedType.JL_CLASS), Modifier.PUBLIC, true);
  637. codeStream.record(classVariable);
  638. classVariable.recordInitializationStartPC(codeStream.position);
  639. ExceptionLabel goneBang = new ExceptionLabel(codeStream, world.makeTypeBinding(UnresolvedType.JL_EXCEPTION));
  640. BranchLabel noInstanceExists = new BranchLabel(codeStream);
  641. BranchLabel leave = new BranchLabel(codeStream);
  642. goneBang.placeStart();
  643. codeStream.aload_0();
  644. codeStream.invoke(Opcodes.OPC_invokestatic,
  645. world.makeMethodBinding(AjcMemberMaker.perTypeWithinGetInstance(typeX)), null);
  646. codeStream.ifnull(noInstanceExists);
  647. codeStream.iconst_1();
  648. codeStream.ireturn();
  649. // codeStream.goto_(leave);
  650. noInstanceExists.place();
  651. codeStream.iconst_0();
  652. leave.place();
  653. goneBang.placeEnd();
  654. codeStream.ireturn();
  655. goneBang.place();
  656. //codeStream.astore_1();
  657. codeStream.pop();
  658. codeStream.iconst_0();
  659. codeStream.ireturn();
  660. codeStream.locals[0].recordInitializationEndPC(codeStream.position);
  661. }
  662. });
  663. }
  664. private void generatePerObjectBindMethod(ClassFile classFile, final TypeBinding interfaceType) {
  665. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  666. generateMethod(classFile, AjcMemberMaker.perObjectBind(world.fromBinding(binding)), new BodyGenerator() {
  667. public void generate(CodeStream codeStream) {
  668. // body starts here
  669. LocalVariableBinding aspectInstanceVar = new LocalVariableBinding("aspectInstance".toCharArray(), world
  670. .makeTypeBinding(UnresolvedType.OBJECT), Modifier.PUBLIC, true);
  671. codeStream.record(aspectInstanceVar);
  672. aspectInstanceVar.recordInitializationStartPC(0);
  673. BranchLabel wrongType = new BranchLabel(codeStream);
  674. codeStream.aload_0();
  675. codeStream.instance_of(interfaceType);
  676. codeStream.ifeq(wrongType); // XXX this case might call for screaming
  677. codeStream.aload_0();
  678. codeStream.checkcast(interfaceType);
  679. codeStream.invoke(Opcodes.OPC_invokeinterface,
  680. world.makeMethodBindingForCall(AjcMemberMaker.perObjectInterfaceGet(typeX)), null);
  681. // XXX should do a check for null here and throw a NoAspectBound
  682. codeStream.ifnonnull(wrongType);
  683. codeStream.aload_0();
  684. codeStream.checkcast(interfaceType);
  685. codeStream.new_(binding);
  686. codeStream.dup();
  687. codeStream.invoke(Opcodes.OPC_invokespecial, new MethodBinding(0, "<init>".toCharArray(), TypeBinding.VOID,
  688. new TypeBinding[0], new ReferenceBinding[0], binding), null);
  689. codeStream.invoke(Opcodes.OPC_invokeinterface,
  690. world.makeMethodBindingForCall(AjcMemberMaker.perObjectInterfaceSet(typeX)), null);
  691. wrongType.place();
  692. codeStream.return_();
  693. codeStream.locals[0].recordInitializationEndPC(codeStream.position);
  694. // body ends here
  695. }
  696. });
  697. }
  698. private void generatePerTypeWithinGetWithinTypeNameMethod(ClassFile classFile) {
  699. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  700. // Code:
  701. /*
  702. * Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: getfield #14; //Field ajc$withinType:Ljava/lang/String; 4: areturn
  703. */
  704. generateMethod(classFile,
  705. AjcMemberMaker.perTypeWithinGetWithinTypeNameMethod(world.fromBinding(binding), world.getWorld().isInJava5Mode()),
  706. new BodyGenerator() {
  707. public void generate(CodeStream codeStream) {
  708. ExceptionLabel exc = new ExceptionLabel(codeStream, world.makeTypeBinding(UnresolvedType.JL_EXCEPTION));
  709. exc.placeStart();
  710. codeStream.aload_0();
  711. codeStream.fieldAccess(Opcodes.OPC_getfield,
  712. world.makeFieldBinding(AjcMemberMaker.perTypeWithinWithinTypeField(typeX, typeX)), null);
  713. codeStream.areturn();
  714. }
  715. });
  716. }
  717. // PTWIMPL Generate getInstance method
  718. private void generatePerTypeWithinGetInstanceMethod(ClassFile classFile) {
  719. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  720. generateMethod(classFile, AjcMemberMaker.perTypeWithinGetInstance(world.fromBinding(binding)), new BodyGenerator() {
  721. public void generate(CodeStream codeStream) {
  722. LocalVariableBinding theTypeVar = new LocalVariableBinding("type".toCharArray(), world
  723. .makeTypeBinding(UnresolvedType.JL_CLASS), Modifier.PUBLIC, true);
  724. codeStream.record(theTypeVar);
  725. theTypeVar.recordInitializationStartPC(0);
  726. TypeBinding exceptionTypeBinding = world.makeTypeBinding(UnresolvedType.JL_EXCEPTION);
  727. ExceptionLabel exc = new ExceptionLabel(codeStream, exceptionTypeBinding);
  728. exc.placeStart();
  729. codeStream.aload_0();
  730. codeStream.ldc(NameMangler.perTypeWithinLocalAspectOf(typeX));
  731. codeStream.aconst_null();
  732. TypeBinding methodTypeBinding = world.makeTypeBinding(UnresolvedType.forSignature("Ljava/lang/reflect/Method;"));
  733. codeStream.invoke(
  734. Opcodes.OPC_invokevirtual,
  735. new MethodBinding(0, "getDeclaredMethod".toCharArray(),
  736. methodTypeBinding, // return type
  737. new TypeBinding[] { world.makeTypeBinding(UnresolvedType.forSignature("Ljava/lang/String;")),
  738. world.makeTypeBinding(UnresolvedType.forSignature("[Ljava/lang/Class;")) },
  739. new ReferenceBinding[0], (ReferenceBinding) world.makeTypeBinding(UnresolvedType.JL_CLASS)), null);
  740. codeStream.astore_1();
  741. LocalVariableBinding methodVariable = new LocalVariableBinding("method".toCharArray(), methodTypeBinding,
  742. Modifier.PUBLIC, true);
  743. codeStream.record(methodVariable);
  744. methodVariable.resolvedPosition = 1;
  745. methodVariable.recordInitializationStartPC(codeStream.position);
  746. codeStream.aload_1();
  747. codeStream.aconst_null();
  748. codeStream.aconst_null();
  749. codeStream.invoke(
  750. Opcodes.OPC_invokevirtual,
  751. new MethodBinding(0, "invoke".toCharArray(), world.makeTypeBinding(UnresolvedType.OBJECT),
  752. new TypeBinding[] { world.makeTypeBinding(UnresolvedType.OBJECT),
  753. world.makeTypeBinding(UnresolvedType.forSignature("[Ljava/lang/Object;")) },
  754. new ReferenceBinding[0], (ReferenceBinding) world
  755. .makeTypeBinding(UnresolvedType.JAVA_LANG_REFLECT_METHOD)), null);
  756. codeStream.checkcast(world.makeTypeBinding(typeX));
  757. codeStream.astore_2();
  758. LocalVariableBinding aspectInstanceVariable = new LocalVariableBinding("aspectInstance".toCharArray(), world
  759. .makeTypeBinding(typeX), Modifier.PUBLIC, true);
  760. codeStream.record(aspectInstanceVariable);
  761. aspectInstanceVariable.resolvedPosition = 2;
  762. aspectInstanceVariable.recordInitializationStartPC(codeStream.position);
  763. codeStream.aload_2();
  764. exc.placeEnd();
  765. codeStream.areturn();
  766. exc.place();
  767. codeStream.pushExceptionOnStack(exceptionTypeBinding); // For stackmap computation to behave
  768. codeStream.astore_1();
  769. // this just returns null now - the old version used to throw the caught exception!
  770. codeStream.aconst_null();
  771. codeStream.areturn();
  772. codeStream.locals[0].recordInitializationEndPC(codeStream.position);
  773. codeStream.locals[1].recordInitializationEndPC(codeStream.position);
  774. codeStream.locals[2].recordInitializationEndPC(codeStream.position);
  775. }
  776. });
  777. }
  778. private void generatePerTypeWithinCreateAspectInstanceMethod(ClassFile classFile) {
  779. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  780. generateMethod(classFile, AjcMemberMaker.perTypeWithinCreateAspectInstance(world.fromBinding(binding)),
  781. new BodyGenerator() {
  782. public void generate(CodeStream codeStream) {
  783. codeStream.new_(world.makeTypeBinding(typeX));
  784. codeStream.dup();
  785. codeStream.invoke(Opcodes.OPC_invokespecial, new MethodBinding(0, "<init>".toCharArray(), TypeBinding.VOID,
  786. new TypeBinding[0], new ReferenceBinding[0], binding), null);
  787. codeStream.astore_1();
  788. codeStream.aload_1();
  789. codeStream.aload_0();
  790. codeStream.fieldAccess(Opcodes.OPC_putfield,
  791. world.makeFieldBinding(AjcMemberMaker.perTypeWithinWithinTypeField(typeX, typeX)), null);
  792. codeStream.aload_1();
  793. codeStream.areturn();
  794. }
  795. });
  796. }
  797. private void generatePerSingletonAspectOfMethod(ClassFile classFile) {
  798. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  799. generateMethod(classFile, aspectOfMethod, new BodyGenerator() {
  800. public void generate(CodeStream codeStream) {
  801. // Old style aspectOf() method which confused decompilers
  802. // // body starts here
  803. // codeStream.getstatic(world.makeFieldBinding(AjcMemberMaker.perSingletonField(
  804. // typeX)));
  805. // Label isNull = new Label(codeStream);
  806. // codeStream.dup();
  807. // codeStream.ifnull(isNull);
  808. // codeStream.areturn();
  809. // isNull.place();
  810. //
  811. // codeStream.incrStackSize(+1); // the dup trick above confuses the stack counter
  812. // codeStream.new_(world.makeTypeBinding(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION));
  813. // codeStream.dup();
  814. // codeStream.ldc(typeX.getNameAsIdentifier());
  815. // codeStream.getstatic(initFailureField);
  816. // codeStream.invokespecial(world.makeMethodBindingForCall(
  817. // AjcMemberMaker.noAspectBoundExceptionInitWithCause()
  818. // ));
  819. // codeStream.athrow();
  820. // // body ends here
  821. // The stuff below generates code that looks like this:
  822. /*
  823. * if (ajc$perSingletonInstance == null) throw new NoAspectBoundException("A", ajc$initFailureCause); else return
  824. * ajc$perSingletonInstance;
  825. */
  826. // body starts here (see end of each line for what it is doing!)
  827. FieldBinding fb = world.makeFieldBinding(AjcMemberMaker.perSingletonField(typeX));
  828. codeStream.fieldAccess(Opcodes.OPC_getstatic, fb, null);
  829. BranchLabel isNonNull = new BranchLabel(codeStream);
  830. codeStream.ifnonnull(isNonNull); // IFNONNULL
  831. codeStream.new_(world.makeTypeBinding(AjcMemberMaker.NO_ASPECT_BOUND_EXCEPTION)); // NEW
  832. codeStream.dup(); // DUP
  833. codeStream.ldc(typeX.getNameAsIdentifier()); // LDC
  834. codeStream.fieldAccess(Opcodes.OPC_getstatic, initFailureField, null);
  835. codeStream.invoke(Opcodes.OPC_invokespecial,
  836. world.makeMethodBindingForCall(AjcMemberMaker.noAspectBoundExceptionInitWithCause()), null); // INVOKESPECIAL
  837. codeStream.athrow(); // ATHROW
  838. isNonNull.place();
  839. codeStream.fieldAccess(Opcodes.OPC_getstatic, fb, null);
  840. codeStream.areturn(); // ARETURN
  841. // body ends here
  842. }
  843. });
  844. }
  845. private void generatePerSingletonHasAspectMethod(ClassFile classFile) {
  846. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  847. generateMethod(classFile, hasAspectMethod, new BodyGenerator() {
  848. public void generate(CodeStream codeStream) {
  849. // body starts here
  850. codeStream.fieldAccess(Opcodes.OPC_getstatic, world.makeFieldBinding(AjcMemberMaker.perSingletonField(typeX)), null);
  851. BranchLabel isNull = new BranchLabel(codeStream);
  852. codeStream.ifnull(isNull);
  853. codeStream.iconst_1();
  854. codeStream.ireturn();
  855. isNull.place();
  856. codeStream.iconst_0();
  857. codeStream.ireturn();
  858. // body ends here
  859. }
  860. });
  861. }
  862. private void generatePerSingletonAjcClinitMethod(ClassFile classFile) {
  863. final EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(this.scope);
  864. generateMethod(classFile, world.makeMethodBinding(AjcMemberMaker.ajcPostClinitMethod(world.fromBinding(binding))),
  865. new BodyGenerator() {
  866. public void generate(CodeStream codeStream) {
  867. // body starts here
  868. codeStream.new_(binding);
  869. codeStream.dup();
  870. codeStream.invoke(Opcodes.OPC_invokespecial, new MethodBinding(0, "<init>".toCharArray(), TypeBinding.VOID,
  871. new TypeBinding[0], new ReferenceBinding[0], binding), null);
  872. codeStream.fieldAccess(Opcodes.OPC_putstatic,
  873. world.makeFieldBinding(AjcMemberMaker.perSingletonField(typeX)), null);
  874. codeStream.return_();
  875. // body ends here
  876. }
  877. });
  878. }
  879. private void generateSuperAccessMethod(ClassFile classFile, final MethodBinding accessMethod, final ResolvedMember method) {
  880. generateMethod(classFile, accessMethod, new BodyGenerator() {
  881. public void generate(CodeStream codeStream) {
  882. // body starts here
  883. codeStream.aload_0();
  884. AstUtil.generateParameterLoads(accessMethod.parameters, codeStream, 1);
  885. codeStream.invoke(Opcodes.OPC_invokespecial, factory.makeMethodBinding(method), null);
  886. AstUtil.generateReturn(accessMethod.returnType, codeStream);
  887. // body ends here
  888. }
  889. });
  890. }
  891. private void generateInlineAccessMethod(ClassFile classFile, final Binding binding, final ResolvedMember member) {
  892. if (binding instanceof InlineAccessFieldBinding) {
  893. generateInlineAccessors(classFile, (InlineAccessFieldBinding) binding, member);
  894. } else {
  895. generateInlineAccessMethod(classFile, (MethodBinding) binding, member);
  896. }
  897. }
  898. private void generateInlineAccessors(ClassFile classFile, final InlineAccessFieldBinding accessField, final ResolvedMember field) {
  899. final FieldBinding fieldBinding = factory.makeFieldBinding(field);
  900. generateMethod(classFile, accessField.reader, makeEffectiveSignatureAttribute(field, Shadow.FieldGet, false),
  901. new BodyGenerator() {
  902. public void generate(CodeStream codeStream) {
  903. // body starts here
  904. if (Modifier.isStatic(field.getModifiers())) {
  905. codeStream.fieldAccess(Opcodes.OPC_getstatic, fieldBinding, null);
  906. } else {
  907. codeStream.aload_0();
  908. codeStream.fieldAccess(Opcodes.OPC_getfield, fieldBinding, null);
  909. }
  910. AstUtil.generateReturn(accessField.reader.returnType, codeStream);
  911. // body ends here
  912. }
  913. });
  914. generateMethod(classFile, accessField.writer, makeEffectiveSignatureAttribute(field, Shadow.FieldSet, false),
  915. new BodyGenerator() {
  916. public void generate(CodeStream codeStream) {
  917. // body starts here
  918. if (Modifier.isStatic(field.getModifiers())) {
  919. codeStream.load(fieldBinding.type, 0);
  920. codeStream.fieldAccess(Opcodes.OPC_putstatic, fieldBinding, null);
  921. } else {
  922. codeStream.aload_0();
  923. codeStream.load(fieldBinding.type, 1);
  924. codeStream.fieldAccess(Opcodes.OPC_putfield, fieldBinding, null);
  925. }
  926. codeStream.return_();
  927. // body ends here
  928. }
  929. });
  930. }
  931. private void generateInlineAccessMethod(ClassFile classFile, final MethodBinding accessMethod, final ResolvedMember method) {
  932. generateMethod(classFile, accessMethod, makeEffectiveSignatureAttribute(method, Shadow.MethodCall, false),
  933. new BodyGenerator() {
  934. public void generate(CodeStream codeStream) {
  935. // body starts here
  936. AstUtil.generateParameterLoads(accessMethod.parameters, codeStream);
  937. if (Modifier.isStatic(method.getModifiers())) {
  938. codeStream.invoke(Opcodes.OPC_invokestatic, factory.makeMethodBinding(method), null);
  939. } else {
  940. codeStream.invoke(Opcodes.OPC_invokevirtual, factory.makeMethodBinding(method), null);
  941. }
  942. AstUtil.generateReturn(accessMethod.returnType, codeStream);
  943. // body ends here
  944. }
  945. });
  946. }
  947. private PerClause.Kind lookupPerClauseKind(ReferenceBinding binding) {
  948. PerClause perClause;
  949. if (binding instanceof BinaryTypeBinding) {
  950. ResolvedType superTypeX = factory.fromEclipse(binding);
  951. perClause = superTypeX.getPerClause();
  952. } else if (binding instanceof SourceTypeBinding) {
  953. SourceTypeBinding sourceSc = (SourceTypeBinding) binding;
  954. if (sourceSc.scope.referenceContext instanceof AspectDeclaration) {
  955. perClause = ((AspectDeclaration) sourceSc.scope.referenceContext).perClause;
  956. } else {
  957. return null;
  958. }
  959. } else if (binding instanceof ParameterizedTypeBinding) {
  960. ParameterizedTypeBinding pBinding = (ParameterizedTypeBinding) binding;
  961. if (pBinding.type instanceof SourceTypeBinding) {
  962. SourceTypeBinding sourceSc = (SourceTypeBinding) pBinding.type;
  963. if (sourceSc.scope != null && sourceSc.scope.referenceContext instanceof AspectDeclaration) {
  964. perClause = ((AspectDeclaration) sourceSc.scope.referenceContext).perClause;
  965. } else {
  966. return null;
  967. }
  968. } else {
  969. perClause = null;
  970. }
  971. } else {
  972. // XXX need to handle this too
  973. return null;
  974. }
  975. if (perClause == null) {
  976. return lookupPerClauseKind(binding.superclass());
  977. } else {
  978. return perClause.getKind();
  979. }
  980. }
  981. private void buildPerClause(ClassScope scope) {
  982. EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
  983. if (perClause == null) {
  984. PerClause.Kind kind = lookupPerClauseKind(binding.superclass);
  985. if (kind == null) {
  986. perClause = new PerSingleton();
  987. } else {
  988. perClause = new PerFromSuper(kind);
  989. }
  990. }
  991. // aspectAttribute = new AjAttribute.Aspect(perClause);
  992. if (ignoreFurtherInvestigation) {
  993. return; // ???
  994. }
  995. if (!isAbstract()) {
  996. if (perClause.getKind() == PerClause.SINGLETON) {
  997. aspectOfMethod = AjcMemberMaker.perSingletonAspectOfMethod(typeX);
  998. hasAspectMethod = AjcMemberMaker.perSingletonHasAspectMethod(typeX);
  999. } else if (perClause.getKind() == PerClause.PERCFLOW) {
  1000. aspectOfMethod = AjcMemberMaker.perCflowAspectOfMethod(typeX);
  1001. hasAspectMethod = AjcMemberMaker.perCflowHasAspectMethod(typeX);
  1002. } else if (perClause.getKind() == PerClause.PEROBJECT) {
  1003. aspectOfMethod = AjcMemberMaker.perObjectAspectOfMethod(typeX);
  1004. hasAspectMethod = AjcMemberMaker.perObjectHasAspectMethod(typeX);
  1005. } else if (perClause.getKind() == PerClause.PERTYPEWITHIN) {
  1006. // PTWIMPL Use these variants of aspectOf()/hasAspect()
  1007. aspectOfMethod = AjcMemberMaker.perTypeWithinAspectOfMethod(typeX, world.getWorld().isInJava5Mode());
  1008. hasAspectMethod = AjcMemberMaker.perTypeWithinHasAspectMethod(typeX, world.getWorld().isInJava5Mode());
  1009. ptwGetWithinTypeNameMethod = AjcMemberMaker.perTypeWithinGetWithinTypeNameMethod(typeX, world.getWorld()
  1010. .isInJava5Mode());
  1011. binding.addMethod(world.makeMethodBinding(ptwGetWithinTypeNameMethod));
  1012. } else {
  1013. throw new RuntimeException("bad per clause: " + perClause);
  1014. }
  1015. binding.addMethod(world.makeMethodBinding(aspectOfMethod));
  1016. binding.addMethod(world.makeMethodBinding(hasAspectMethod));
  1017. }
  1018. resolvePerClause(); // XXX might be too soon for some error checking
  1019. }
  1020. private PerClause resolvePerClause() {
  1021. EclipseScope iscope = new EclipseScope(FormalBinding.NONE, scope);
  1022. perClause.resolve(iscope);
  1023. return perClause;
  1024. }
  1025. public void processIntertypeMemberTypes(ClassScope classScope) {
  1026. factory = EclipseFactory.fromScopeLookupEnvironment(scope);
  1027. if (memberTypes != null) {
  1028. for (TypeDeclaration memberType : memberTypes) {
  1029. if (memberType instanceof IntertypeMemberClassDeclaration) {
  1030. EclipseTypeMunger m = ((IntertypeMemberClassDeclaration) memberType).build(classScope);
  1031. if (m != null) {
  1032. mungeNewInnerClass(m, factory);
  1033. concreteName.typeMungers.add(m);
  1034. }
  1035. }
  1036. }
  1037. }
  1038. }
  1039. public void buildInterTypeAndPerClause(ClassScope classScope) {
  1040. factory = EclipseFactory.fromScopeLookupEnvironment(scope);
  1041. if (isPrivileged) {
  1042. binding.privilegedHandler = new PrivilegedHandler(this);
  1043. }
  1044. checkSpec(classScope);
  1045. if (ignoreFurtherInvestigation) {
  1046. return;
  1047. }
  1048. buildPerClause(scope);
  1049. if (methods != null) {
  1050. for (org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration method : methods) {
  1051. if (method instanceof InterTypeDeclaration) {
  1052. EclipseTypeMunger m = ((InterTypeDeclaration) method).build(classScope);
  1053. if (m != null) {
  1054. concreteName.typeMungers.add(m);
  1055. }
  1056. } else if (method instanceof DeclareDeclaration) {
  1057. Declare d = ((DeclareDeclaration) method).build(classScope);
  1058. if (d != null) {
  1059. concreteName.declares.add(d);
  1060. }
  1061. }
  1062. }
  1063. }
  1064. concreteName.getDeclaredPointcuts();
  1065. }
  1066. // public String toString(int tab) {
  1067. // return tabString(tab) + toStringHeader() + toStringBody(tab);
  1068. // }
  1069. //
  1070. // public String toStringBody(int tab) {
  1071. //
  1072. // String s = " {"; //$NON-NLS-1$
  1073. //
  1074. //
  1075. // if (memberTypes != null) {
  1076. // for (int i = 0; i < memberTypes.length; i++) {
  1077. // if (memberTypes[i] != null) {
  1078. // s += "\n" + memberTypes[i].toString(tab + 1); //$NON-NLS-1$
  1079. // }
  1080. // }
  1081. // }
  1082. // if (fields != null) {
  1083. // for (int fieldI = 0; fieldI < fields.length; fieldI++) {
  1084. // if (fields[fieldI] != null) {
  1085. // s += "\n" + fields[fieldI].toString(tab + 1); //$NON-NLS-1$
  1086. // if (fields[fieldI].isField())
  1087. // s += ";"; //$NON-NLS-1$
  1088. // }
  1089. // }
  1090. // }
  1091. // if (methods != null) {
  1092. // for (int i = 0; i < methods.length; i++) {
  1093. // if (methods[i] != null) {
  1094. // s += "\n" + methods[i].toString(tab + 1); //$NON-NLS-1$
  1095. // }
  1096. // }
  1097. // }
  1098. // s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
  1099. // return s;
  1100. // }
  1101. // very similar to code in EclipseTypeMunger
  1102. private void mungeNewInnerClass(EclipseTypeMunger m, EclipseFactory world) {
  1103. NewMemberClassTypeMunger munger = (NewMemberClassTypeMunger) m.getMunger();
  1104. // private boolean mungeNewInnerClass(SourceTypeBinding sourceType, ResolvedType onType, NewMemberClassTypeMunger munger,
  1105. // boolean isExactTargetType) {
  1106. SourceTypeBinding aspectTypeBinding = (SourceTypeBinding) world.makeTypeBinding(m.getAspectType());
  1107. char[] mungerMemberTypeName = ("$" + munger.getMemberTypeName()).toCharArray();
  1108. ReferenceBinding innerTypeBinding = null;
  1109. for (ReferenceBinding innerType : aspectTypeBinding.memberTypes) {
  1110. char[] compounded = CharOperation.concatWith(innerType.compoundName, '.');
  1111. if (org.aspectj.org.eclipse.jdt.core.compiler.CharOperation.endsWith(compounded, mungerMemberTypeName)) {
  1112. innerTypeBinding = innerType;
  1113. break;
  1114. }
  1115. }
  1116. // may be unresolved if the aspect type binding was a BinaryTypeBinding
  1117. if (innerTypeBinding instanceof UnresolvedReferenceBinding) {
  1118. innerTypeBinding = (ReferenceBinding) BinaryTypeBinding.resolveType(innerTypeBinding, world.getLookupEnvironment(),
  1119. true);
  1120. }
  1121. if (innerTypeBinding == null) {
  1122. throw new IllegalStateException("Could not find inner type binding for '" + munger.getMemberTypeName() + "'");
  1123. }
  1124. // TODO adjust modifier?
  1125. // TODO deal with itd of it onto an interface
  1126. SourceTypeBinding targetSourceTypeBinding = (SourceTypeBinding) world.makeTypeBinding(munger.getTargetType());
  1127. // if it is a binary type binding it is likely to be something we ITD'd on before
  1128. // TODO should probably avoid putting it onto BTBs at all (since already there)
  1129. if (!(targetSourceTypeBinding instanceof BinaryTypeBinding)) {
  1130. ReferenceBinding[] existingMemberTypes = targetSourceTypeBinding.memberTypes();
  1131. for (ReferenceBinding existingMemberType : existingMemberTypes) {
  1132. char[] compounded = CharOperation.concatWith(existingMemberType.compoundName, '.');
  1133. if (CharOperation.endsWith(compounded, mungerMemberTypeName)) {
  1134. scope.problemReporter().signalError(sourceStart(), sourceEnd(),
  1135. "target type already declares a member type with the name '" + munger.getMemberTypeName() + "'");
  1136. return;
  1137. }
  1138. }
  1139. }
  1140. /*
  1141. * char[][] className = CharOperation.deepCopy(targetSourceTypeBinding.compoundName); className[className.length - 1] =
  1142. * CharOperation.concat(className[className.length - 1], munger.getMemberTypeName() .toCharArray(), '$'); //
  1143. * ReferenceBinding existingType = packageBinding.getType0(className[className.length - 1]); innerTypeBinding.compoundName =
  1144. * className; innerTypeBinding.fPackage = targetSourceTypeBinding.fPackage;
  1145. */
  1146. findOrCreateInterTypeMemberClassFinder(targetSourceTypeBinding).addInterTypeMemberType(innerTypeBinding);
  1147. }
  1148. private IntertypeMemberTypeFinder findOrCreateInterTypeMemberClassFinder(SourceTypeBinding sourceType) {
  1149. IntertypeMemberTypeFinder finder = (IntertypeMemberTypeFinder) sourceType.typeFinder;
  1150. if (finder == null) {
  1151. finder = new IntertypeMemberTypeFinder();
  1152. sourceType.typeFinder = finder;
  1153. finder.targetTypeBinding = sourceType;
  1154. sourceType.tagBits &= ~TagBits.HasNoMemberTypes; // ensure it thinks it has one
  1155. }
  1156. return finder;
  1157. }
  1158. public StringBuffer printHeader(int indent, StringBuffer output) {
  1159. // since all aspects are made public we want to print the
  1160. // modifiers that were supplied in the original source code
  1161. printModifiers(this.declaredModifiers, output);
  1162. output.append("aspect ");
  1163. output.append(name);
  1164. if (superclass != null) {
  1165. output.append(" extends "); //$NON-NLS-1$
  1166. superclass.print(0, output);
  1167. }
  1168. if (superInterfaces != null && superInterfaces.length > 0) {
  1169. output.append((TypeDeclaration.kind(this.modifiers) == TypeDeclaration.INTERFACE_DECL) ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
  1170. for (int i = 0; i < superInterfaces.length; i++) {
  1171. if (i > 0) {
  1172. output.append(", "); //$NON-NLS-1$
  1173. }
  1174. superInterfaces[i].print(0, output);
  1175. }
  1176. }
  1177. return output;
  1178. // XXX we should append the per-clause
  1179. }
  1180. /**
  1181. * All aspects are made public after type checking etc. and before generating code (so that the advice can be called!). This
  1182. * method returns the modifiers as specified in the original source code declaration so that the structure model sees the right
  1183. * thing.
  1184. */
  1185. public int getDeclaredModifiers() {
  1186. return declaredModifiers;
  1187. }
  1188. public char[] getLocalTypeNameSuffix() {
  1189. return name;
  1190. }
  1191. }