1 /* *******************************************************************
2 * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
4 * This program and the accompanying materials are made available
5 * under the terms of the Common Public License v1.0
6 * which accompanies this distribution and is available at
7 * http://www.eclipse.org/legal/cpl-v10.html
10 * PARC initial implementation
11 * ******************************************************************/
14 package org.aspectj.ajdt.internal.compiler.ast;
16 import org.aspectj.ajdt.internal.compiler.lookup.*;
17 import org.aspectj.weaver.*;
18 import org.eclipse.jdt.internal.compiler.ClassFile;
19 import org.eclipse.jdt.internal.compiler.CompilationResult;
20 import org.eclipse.jdt.internal.compiler.ast.*;
21 import org.eclipse.jdt.internal.compiler.lookup.*;
22 import org.eclipse.jdt.internal.compiler.parser.Parser;
25 * An inter-type constructor declaration.
27 * This will generate two implementation methods in the aspect, the main one for the body
28 * of the constructor, and an additional <code>preMethod</code> for the code that
29 * runs before the super constructor is called.
33 public class InterTypeConstructorDeclaration extends InterTypeDeclaration {
34 private MethodDeclaration preMethod;
35 private ExplicitConstructorCall explicitConstructorCall = null;
37 public InterTypeConstructorDeclaration(CompilationResult result, TypeReference onType) {
38 super(result, onType);
41 public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
42 if (ignoreFurtherInvestigation)
44 parser.parse(this, unit);
47 public void resolve(ClassScope upperScope) {
48 if (munger == null || binding == null) ignoreFurtherInvestigation = true;
49 if (ignoreFurtherInvestigation) return;
51 explicitConstructorCall = null;
52 if (statements != null && statements.length > 0 &&
53 statements[0] instanceof ExplicitConstructorCall)
55 explicitConstructorCall = (ExplicitConstructorCall) statements[0];
56 statements = AstUtil.remove(0, statements);
59 preMethod = makePreMethod(upperScope, explicitConstructorCall);
61 binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters);
62 this.arguments = AstUtil.insert(
63 AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding),
66 super.resolve(upperScope);
69 private MethodDeclaration makePreMethod(ClassScope scope,
70 ExplicitConstructorCall explicitConstructorCall)
72 EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
74 TypeX aspectTypeX = EclipseFactory.fromBinding(binding.declaringClass);
75 TypeX targetTypeX = EclipseFactory.fromBinding(onTypeBinding);
77 ArrayBinding objectArrayBinding = scope.createArray(scope.getJavaLangObject(), 1);
80 MethodDeclaration pre = new MethodDeclaration(compilationResult);
81 pre.modifiers = AccPublic | AccStatic;
82 pre.returnType = AstUtil.makeTypeReference(objectArrayBinding);
83 pre.selector = NameMangler.postIntroducedConstructor(aspectTypeX, targetTypeX).toCharArray();
86 pre.arguments = AstUtil.copyArguments(this.arguments);
88 //XXX should do exceptions
90 pre.scope = new MethodScope(scope, pre, true);
91 //??? do we need to do anything with scope???
93 pre.binding = world.makeMethodBinding(
94 AjcMemberMaker.preIntroducedConstructor(aspectTypeX, targetTypeX,
95 world.fromBindings(binding.parameters)));
98 pre.bindThrownExceptions();
101 if (explicitConstructorCall == null) {
102 pre.statements = new Statement[] {};
104 pre.statements = new Statement[] {
105 explicitConstructorCall
109 InterTypeScope newParent =
110 new InterTypeScope(scope, onTypeBinding);
111 pre.scope.parent = newParent;
113 pre.resolveStatements(); //newParent);
117 int nParams = pre.arguments.length;
118 MethodBinding explicitConstructor = null;
119 if (explicitConstructorCall != null) {
120 explicitConstructor = explicitConstructorCall.binding;
121 if (explicitConstructor.alwaysNeedsAccessMethod()) {
122 explicitConstructor = explicitConstructor.getAccessMethod(true);
127 if (explicitConstructor == null) nExprs = 0;
128 else nExprs = explicitConstructor.parameters.length;
131 ArrayInitializer init = new ArrayInitializer();
132 init.expressions = new Expression[nExprs + nParams];
134 for (int i=0; i < nExprs; i++) {
135 if (i >= explicitConstructorCall.arguments.length) {
136 init.expressions[index++] = new NullLiteral(0, 0);
141 Expression arg = explicitConstructorCall.arguments[i];
142 ResolvedMember conversionMethod =
143 AjcMemberMaker.toObjectConversionMethod(world.fromBinding(explicitConstructorCall.binding.parameters[i]));
144 if (conversionMethod != null) {
145 arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod),
146 new CastExpression(new NullLiteral(0, 0),
147 AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
148 new Expression[] {arg });
150 init.expressions[index++] = arg;
153 for (int i=0; i < nParams; i++) {
154 LocalVariableBinding binding = pre.arguments[i].binding;
155 Expression arg = AstUtil.makeResolvedLocalVariableReference(binding);
156 ResolvedMember conversionMethod =
157 AjcMemberMaker.toObjectConversionMethod(world.fromBinding(binding.type));
158 if (conversionMethod != null) {
159 arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod),
160 new CastExpression(new NullLiteral(0, 0),
161 AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
162 new Expression[] {arg });
164 init.expressions[index++] = arg;
167 init.binding =objectArrayBinding;
169 ArrayAllocationExpression newArray = new ArrayAllocationExpression();
170 newArray.initializer = init;
171 newArray.type = AstUtil.makeTypeReference(scope.getJavaLangObject());
172 newArray.dimensions = new Expression[1];
173 newArray.constant = NotAConstant;
178 pre.statements = new Statement[] {
179 new ReturnStatement(newArray, 0, 0),
187 public EclipseTypeMunger build(ClassScope classScope) {
188 EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
190 binding = classScope.referenceContext.binding.resolveTypesFor(binding);
192 resolveOnType(classScope);
193 if (ignoreFurtherInvestigation) return null;
196 if (onTypeBinding.isInterface()) {
197 ignoreFurtherInvestigation = true;
201 if (onTypeBinding.isNestedType()) {
202 classScope.problemReporter().signalError(sourceStart, sourceEnd,
203 "can't define constructors on nested types (compiler limitation)");
204 ignoreFurtherInvestigation = true;
208 ResolvedTypeX declaringTypeX = world.fromEclipse(onTypeBinding);
209 ResolvedTypeX aspectType = world.fromEclipse(classScope.referenceContext.binding);
211 ResolvedMember bindingAsMember = world.makeResolvedMember(binding);
213 ResolvedMember signature =
214 new ResolvedMember(Member.CONSTRUCTOR, declaringTypeX, declaredModifiers,
215 ResolvedTypeX.VOID, "<init>", bindingAsMember.getParameterTypes(),
216 world.fromEclipse(binding.thrownExceptions));
217 ResolvedMember syntheticInterMember =
218 AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType);
220 NewConstructorTypeMunger myMunger =
221 new NewConstructorTypeMunger(signature, syntheticInterMember, null, null);
223 myMunger.check(world.getWorld());
225 this.selector = binding.selector =
226 NameMangler.postIntroducedConstructor(
227 EclipseFactory.fromBinding(binding.declaringClass),
228 declaringTypeX).toCharArray();
230 return new EclipseTypeMunger(world, myMunger, aspectType, this);
234 private AjAttribute makeAttribute(EclipseFactory world) {
235 if (explicitConstructorCall != null && !(explicitConstructorCall.binding instanceof ProblemMethodBinding)) {
236 MethodBinding explicitConstructor = explicitConstructorCall.binding;
237 if (explicitConstructor.alwaysNeedsAccessMethod()) {
238 explicitConstructor = explicitConstructor.getAccessMethod(true);
242 ((NewConstructorTypeMunger)munger).setExplicitConstructor(
243 world.makeResolvedMember(explicitConstructor));
245 ((NewConstructorTypeMunger)munger).setExplicitConstructor(
246 new ResolvedMember(Member.CONSTRUCTOR,
247 EclipseFactory.fromBinding(onTypeBinding.superclass()),
248 0, ResolvedTypeX.VOID, "<init>", TypeX.NONE));
250 return new AjAttribute.TypeMunger(munger);
254 public void generateCode(ClassScope classScope, ClassFile classFile) {
255 if (ignoreFurtherInvestigation) return;
256 EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
257 classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute(world)));
258 super.generateCode(classScope, classFile);
260 preMethod.generateCode(classScope, classFile);
262 protected Shadow.Kind getShadowKindForBody() {
263 return Shadow.ConstructorExecution;