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

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