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

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