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.

InterTypeConstructorDeclaration.java 15KB

21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
19 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License 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 initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.internal.compiler.ast;
  13. import java.lang.reflect.Modifier;
  14. import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
  15. import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
  16. import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
  17. import org.aspectj.ajdt.internal.compiler.lookup.InterTypeScope;
  18. import org.aspectj.bridge.ISourceLocation;
  19. import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
  20. import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
  21. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
  22. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
  23. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CastExpression;
  24. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
  25. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
  26. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
  27. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
  28. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
  29. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NullLiteral;
  30. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
  31. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
  32. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Statement;
  33. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.StringLiteral;
  34. import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
  35. import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
  36. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
  37. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
  38. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
  39. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
  40. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
  41. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
  42. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedMethodBinding;
  43. import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
  44. import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
  45. import org.aspectj.weaver.AjAttribute;
  46. import org.aspectj.weaver.AjcMemberMaker;
  47. import org.aspectj.weaver.Constants;
  48. import org.aspectj.weaver.Member;
  49. import org.aspectj.weaver.NameMangler;
  50. import org.aspectj.weaver.NewConstructorTypeMunger;
  51. import org.aspectj.weaver.ResolvedMember;
  52. import org.aspectj.weaver.ResolvedMemberImpl;
  53. import org.aspectj.weaver.ResolvedType;
  54. import org.aspectj.weaver.Shadow;
  55. import org.aspectj.weaver.UnresolvedType;
  56. /**
  57. * An inter-type constructor declaration.
  58. *
  59. * This will generate two implementation methods in the aspect, the main one for the body of the constructor, and an additional
  60. * <code>preMethod</code> for the code that runs before the super constructor is called.
  61. *
  62. * @author Jim Hugunin
  63. */
  64. public class InterTypeConstructorDeclaration extends InterTypeDeclaration {
  65. private static final String SUPPRESSAJWARNINGS = "Lorg/aspectj/lang/annotation/SuppressAjWarnings;";
  66. private static final String NOEXPLICITCONSTRUCTORCALL = "noExplicitConstructorCall";
  67. private MethodDeclaration preMethod;
  68. private ExplicitConstructorCall explicitConstructorCall = null;
  69. public InterTypeConstructorDeclaration(CompilationResult result, TypeReference onType) {
  70. super(result, onType);
  71. }
  72. public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
  73. if (ignoreFurtherInvestigation)
  74. return;
  75. parser.parse(this, unit);
  76. }
  77. protected char[] getPrefix() {
  78. return (NameMangler.ITD_PREFIX + "interConstructor$").toCharArray();
  79. }
  80. public void resolve(ClassScope upperScope) {
  81. if (munger == null || binding == null)
  82. ignoreFurtherInvestigation = true;
  83. if (ignoreFurtherInvestigation)
  84. return;
  85. explicitConstructorCall = null;
  86. if (statements != null && statements.length > 0 && statements[0] instanceof ExplicitConstructorCall) {
  87. explicitConstructorCall = (ExplicitConstructorCall) statements[0];
  88. statements = AstUtil.remove(0, statements);
  89. }
  90. preMethod = makePreMethod(upperScope, explicitConstructorCall);
  91. binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters);
  92. this.arguments = AstUtil.insert(AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding), this.arguments);
  93. super.resolve(upperScope);
  94. // after annotations have been resolved...
  95. if (explicitConstructorCall == null) {
  96. raiseNoFieldInitializersWarning();
  97. }
  98. }
  99. /**
  100. * Warning added in response to PR 62606 - if an ITD constructor does not make an explicit constructor call then field
  101. * initializers in the target class will not be executed leading to unexpected behaviour.
  102. */
  103. private void raiseNoFieldInitializersWarning() {
  104. if (suppressingNoExplicitConstructorCall())
  105. return;
  106. EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
  107. ISourceLocation location = new EclipseSourceLocation(scope.problemReporter().referenceContext.compilationResult(),
  108. sourceStart(), sourceEnd());
  109. world.getWorld().getLint().noExplicitConstructorCall.signal(null, location);
  110. }
  111. /**
  112. * true iff constructor has @SuppressAjWarnings or @SuppressAjWarnings("xyz,noExplicitConstructorCall,def,...")
  113. *
  114. * @return
  115. */
  116. private boolean suppressingNoExplicitConstructorCall() {
  117. if (this.annotations == null)
  118. return false;
  119. for (org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation annotation : this.annotations) {
  120. if (new String(annotation.resolvedType.signature()).equals(SUPPRESSAJWARNINGS)) {
  121. if (annotation instanceof MarkerAnnotation) {
  122. return true;
  123. } else if (annotation instanceof SingleMemberAnnotation) {
  124. SingleMemberAnnotation sma = (SingleMemberAnnotation) annotation;
  125. if (sma.memberValue instanceof ArrayInitializer) {
  126. ArrayInitializer memberValue = (ArrayInitializer) sma.memberValue;
  127. for (int j = 0; j < memberValue.expressions.length; j++) {
  128. if (memberValue.expressions[j] instanceof StringLiteral) {
  129. StringLiteral val = (StringLiteral) memberValue.expressions[j];
  130. if (new String(val.source()).equals(NOEXPLICITCONSTRUCTORCALL))
  131. return true;
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }
  138. return false;
  139. }
  140. private MethodDeclaration makePreMethod(ClassScope scope, ExplicitConstructorCall explicitConstructorCall) {
  141. EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
  142. UnresolvedType aspectTypeX = world.fromBinding(binding.declaringClass);
  143. UnresolvedType targetTypeX = world.fromBinding(onTypeBinding);
  144. ArrayBinding objectArrayBinding = scope.createArrayType(scope.getJavaLangObject(), 1);
  145. MethodDeclaration pre = new MethodDeclaration(compilationResult);
  146. pre.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic;
  147. pre.returnType = AstUtil.makeTypeReference(objectArrayBinding);
  148. pre.selector = NameMangler.postIntroducedConstructor(aspectTypeX, targetTypeX).toCharArray();
  149. pre.arguments = AstUtil.copyArguments(this.arguments);
  150. // XXX should do exceptions
  151. pre.scope = new MethodScope(scope, pre, true);
  152. // ??? do we need to do anything with scope???
  153. // Use the factory to build a semi-correct resolvedmember - then patch it up with
  154. // reset calls. This is SAFE
  155. ResolvedMemberImpl preIntroducedConstructorRM = world.makeResolvedMember(binding);
  156. preIntroducedConstructorRM.resetName(NameMangler.preIntroducedConstructor(aspectTypeX, targetTypeX));
  157. preIntroducedConstructorRM.resetModifiers(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
  158. preIntroducedConstructorRM.resetReturnTypeToObjectArray();
  159. pre.binding = world.makeMethodBinding(preIntroducedConstructorRM);
  160. pre.bindArguments();
  161. pre.bindThrownExceptions();
  162. if (explicitConstructorCall == null) {
  163. pre.statements = new Statement[] {};
  164. } else {
  165. pre.statements = new Statement[] { explicitConstructorCall };
  166. }
  167. InterTypeScope newParent = new InterTypeScope(scope, onTypeBinding);
  168. // Use setter in order to also update member 'compilationUnitScope'
  169. pre.scope.setParent(newParent);
  170. pre.resolveStatements(); // newParent);
  171. int nParams = pre.arguments.length;
  172. MethodBinding explicitConstructor = null;
  173. if (explicitConstructorCall != null) {
  174. explicitConstructor = explicitConstructorCall.binding;
  175. // If it is null then we are going to report something else is wrong with this code!
  176. if (explicitConstructor != null && explicitConstructor.alwaysNeedsAccessMethod()) {
  177. explicitConstructor = explicitConstructor.getAccessMethod(true);
  178. }
  179. }
  180. int nExprs;
  181. if (explicitConstructor == null)
  182. nExprs = 0;
  183. else
  184. nExprs = explicitConstructor.parameters.length;
  185. ArrayInitializer init = new ArrayInitializer();
  186. init.expressions = new Expression[nExprs + nParams];
  187. int index = 0;
  188. for (int i = 0; i < nExprs; i++) {
  189. if (i >= (explicitConstructorCall.arguments == null ? 0 : explicitConstructorCall.arguments.length)) {
  190. init.expressions[index++] = new NullLiteral(0, 0);
  191. continue;
  192. }
  193. Expression arg = explicitConstructorCall.arguments[i];
  194. ResolvedMember conversionMethod = AjcMemberMaker.toObjectConversionMethod(world
  195. .fromBinding(explicitConstructorCall.binding.parameters[i]));
  196. if (conversionMethod != null) {
  197. arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), new CastExpression(new NullLiteral(0,
  198. 0), AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
  199. new Expression[] { arg });
  200. }
  201. init.expressions[index++] = arg;
  202. }
  203. for (int i = 0; i < nParams; i++) {
  204. LocalVariableBinding binding = pre.arguments[i].binding;
  205. Expression arg = AstUtil.makeResolvedLocalVariableReference(binding);
  206. ResolvedMember conversionMethod = AjcMemberMaker.toObjectConversionMethod(world.fromBinding(binding.type));
  207. if (conversionMethod != null) {
  208. arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod), new CastExpression(new NullLiteral(0,
  209. 0), AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
  210. new Expression[] { arg });
  211. }
  212. init.expressions[index++] = arg;
  213. }
  214. init.binding = objectArrayBinding;
  215. ArrayAllocationExpression newArray = new ArrayAllocationExpression();
  216. newArray.initializer = init;
  217. newArray.type = AstUtil.makeTypeReference(scope.getJavaLangObject());
  218. newArray.dimensions = new Expression[1];
  219. newArray.constant = Constant.NotAConstant;
  220. pre.statements = new Statement[] { new ReturnStatement(newArray, 0, 0), };
  221. return pre;
  222. }
  223. public EclipseTypeMunger build(ClassScope classScope) {
  224. EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
  225. resolveOnType(classScope);
  226. if (ignoreFurtherInvestigation)
  227. return null;
  228. binding = classScope.referenceContext.binding.resolveTypesFor(binding);
  229. if (isTargetAnnotation(classScope, "constructor"))
  230. return null; // Error message output in isTargetAnnotation
  231. if (isTargetEnum(classScope, "constructor"))
  232. return null; // Error message output in isTargetEnum
  233. if (onTypeBinding.isInterface()) {
  234. classScope.problemReporter().signalError(sourceStart, sourceEnd, "can't define constructors on interfaces");
  235. ignoreFurtherInvestigation = true;
  236. return null;
  237. }
  238. if (onTypeBinding.isNestedType()) {
  239. classScope.problemReporter().signalError(sourceStart, sourceEnd,
  240. "can't define constructors on nested types (compiler limitation)");
  241. ignoreFurtherInvestigation = true;
  242. return null;
  243. }
  244. ResolvedType declaringTypeX = world.fromEclipse(onTypeBinding);
  245. ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding);
  246. if (interTypeScope == null)
  247. return null; // We encountered a problem building the scope, don't continue - error already reported
  248. // This signature represents what we want consumers of the targetted type to 'see'
  249. ResolvedMemberImpl signature = world.makeResolvedMemberForITD(binding, onTypeBinding, interTypeScope.getRecoveryAliases());
  250. signature.resetKind(Member.CONSTRUCTOR);
  251. signature.resetName("<init>");
  252. int resetModifiers = declaredModifiers;
  253. if (binding.isVarargs())
  254. resetModifiers = resetModifiers | Constants.ACC_VARARGS;
  255. signature.resetModifiers(resetModifiers);
  256. ResolvedMember syntheticInterMember = AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType);
  257. NewConstructorTypeMunger myMunger = new NewConstructorTypeMunger(signature, syntheticInterMember, null, null,
  258. typeVariableAliases);
  259. setMunger(myMunger);
  260. myMunger.check(world.getWorld());
  261. this.selector = binding.selector = NameMangler.postIntroducedConstructor(world.fromBinding(binding.declaringClass),
  262. declaringTypeX).toCharArray();
  263. return new EclipseTypeMunger(world, myMunger, aspectType, this);
  264. }
  265. private AjAttribute makeAttribute(EclipseFactory world) {
  266. if (explicitConstructorCall != null && (explicitConstructorCall.binding != null)
  267. && !(explicitConstructorCall.binding instanceof ProblemMethodBinding)) {
  268. MethodBinding explicitConstructor = explicitConstructorCall.binding;
  269. if (explicitConstructor.alwaysNeedsAccessMethod()) {
  270. explicitConstructor = explicitConstructor.getAccessMethod(true);
  271. }
  272. if (explicitConstructor instanceof ParameterizedMethodBinding) {
  273. explicitConstructor = explicitConstructor.original();
  274. }
  275. ((NewConstructorTypeMunger) munger).setExplicitConstructor(world.makeResolvedMember(explicitConstructor));
  276. } else {
  277. ((NewConstructorTypeMunger) munger).setExplicitConstructor(new ResolvedMemberImpl(Member.CONSTRUCTOR, world
  278. .fromBinding(onTypeBinding.superclass()), 0, UnresolvedType.VOID, "<init>", UnresolvedType.NONE));
  279. }
  280. return new AjAttribute.TypeMunger(munger);
  281. }
  282. public void generateCode(ClassScope classScope, ClassFile classFile) {
  283. if (ignoreFurtherInvestigation)
  284. return;
  285. EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
  286. classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute(world)));
  287. super.generateCode(classScope, classFile);
  288. // classFile.codeStream.generateAttributes &= ~ClassFileConstants.ATTR_VARS;
  289. preMethod.generateCode(classScope, classFile);
  290. }
  291. protected Shadow.Kind getShadowKindForBody() {
  292. return Shadow.ConstructorExecution;
  293. }
  294. }