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.*;
19 import org.eclipse.jdt.internal.compiler.ast.*;
20 import org.eclipse.jdt.internal.compiler.lookup.*;
21 import org.eclipse.jdt.internal.compiler.parser.Parser;
24 public class InterTypeConstructorDeclaration extends InterTypeDeclaration {
25 private MethodDeclaration preMethod;
26 private ExplicitConstructorCall explicitConstructorCall = null;
28 public InterTypeConstructorDeclaration(CompilationResult result, TypeReference onType) {
29 super(result, onType);
32 public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
33 if (ignoreFurtherInvestigation)
35 parser.parseAsConstructor(this, unit);
38 public void resolve(ClassScope upperScope) {
39 if (munger == null || binding == null) ignoreFurtherInvestigation = true;
40 if (ignoreFurtherInvestigation) return;
42 explicitConstructorCall = null;
43 if (statements != null && statements.length > 0 &&
44 statements[0] instanceof ExplicitConstructorCall)
46 explicitConstructorCall = (ExplicitConstructorCall) statements[0];
47 statements = AstUtil.remove(0, statements);
50 preMethod = makePreMethod(upperScope, explicitConstructorCall);
52 binding.parameters = AstUtil.insert(onTypeBinding, binding.parameters);
53 this.arguments = AstUtil.insert(
54 AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding),
57 super.resolve(upperScope);
60 private MethodDeclaration makePreMethod(ClassScope scope,
61 ExplicitConstructorCall explicitConstructorCall)
63 EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(scope);
65 TypeX aspectTypeX = EclipseWorld.fromBinding(binding.declaringClass);
66 TypeX targetTypeX = EclipseWorld.fromBinding(onTypeBinding);
68 ArrayBinding objectArrayBinding = scope.createArray(scope.getJavaLangObject(), 1);
71 MethodDeclaration pre = new MethodDeclaration(compilationResult);
72 pre.modifiers = AccPublic | AccStatic;
73 pre.returnType = AstUtil.makeTypeReference(objectArrayBinding);
74 pre.selector = NameMangler.postIntroducedConstructor(aspectTypeX, targetTypeX).toCharArray();
77 pre.arguments = AstUtil.copyArguments(this.arguments);
79 //XXX should do exceptions
81 pre.scope = new MethodScope(scope, pre, true);
82 //??? do we need to do anything with scope???
84 pre.binding = world.makeMethodBinding(
85 AjcMemberMaker.preIntroducedConstructor(aspectTypeX, targetTypeX,
86 world.fromBindings(binding.parameters)));
89 pre.bindThrownExceptions();
92 if (explicitConstructorCall == null) {
93 pre.statements = new Statement[] {};
95 pre.statements = new Statement[] {
96 explicitConstructorCall
100 InterTypeScope newParent =
101 new InterTypeScope(scope, onTypeBinding);
102 pre.scope.parent = newParent;
104 pre.resolveStatements(newParent);
108 int nParams = pre.arguments.length;
109 MethodBinding explicitConstructor = null;
110 if (explicitConstructorCall != null) {
111 explicitConstructor = explicitConstructorCall.binding;
112 if (explicitConstructor.alwaysNeedsAccessMethod()) {
113 explicitConstructor = explicitConstructor.getAccessMethod(true);
118 if (explicitConstructor == null) nExprs = 0;
119 else nExprs = explicitConstructor.parameters.length;
122 ArrayInitializer init = new ArrayInitializer();
123 init.expressions = new Expression[nExprs + nParams];
125 for (int i=0; i < nExprs; i++) {
126 if (i >= explicitConstructorCall.arguments.length) {
127 init.expressions[index++] = new NullLiteral(0, 0);
132 Expression arg = explicitConstructorCall.arguments[i];
133 ResolvedMember conversionMethod =
134 AjcMemberMaker.toObjectConversionMethod(world.fromBinding(explicitConstructorCall.binding.parameters[i]));
135 if (conversionMethod != null) {
136 arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod),
137 new CastExpression(new NullLiteral(0, 0),
138 AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
139 new Expression[] {arg });
141 init.expressions[index++] = arg;
144 for (int i=0; i < nParams; i++) {
145 LocalVariableBinding binding = pre.arguments[i].binding;
146 Expression arg = AstUtil.makeResolvedLocalVariableReference(binding);
147 ResolvedMember conversionMethod =
148 AjcMemberMaker.toObjectConversionMethod(world.fromBinding(binding.type));
149 if (conversionMethod != null) {
150 arg = new KnownMessageSend(world.makeMethodBindingForCall(conversionMethod),
151 new CastExpression(new NullLiteral(0, 0),
152 AstUtil.makeTypeReference(world.makeTypeBinding(AjcMemberMaker.CONVERSIONS_TYPE))),
153 new Expression[] {arg });
155 init.expressions[index++] = arg;
158 init.binding =objectArrayBinding;
160 ArrayAllocationExpression newArray = new ArrayAllocationExpression();
161 newArray.initializer = init;
162 newArray.type = AstUtil.makeTypeReference(scope.getJavaLangObject());
163 newArray.dimensions = new Expression[1];
164 newArray.constant = NotAConstant;
169 pre.statements = new Statement[] {
170 new ReturnStatement(newArray, 0, 0),
178 public void build(ClassScope classScope, CrosscuttingMembers xcut) {
179 EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope);
181 binding = classScope.referenceContext.binding.resolveTypesFor(binding);
183 resolveOnType(classScope);
184 if (ignoreFurtherInvestigation) return;
187 if (onTypeBinding.isInterface()) {
188 ignoreFurtherInvestigation = true;
192 if (onTypeBinding.isNestedType()) {
193 classScope.problemReporter().signalError(sourceStart, sourceEnd,
194 "can't define constructors on nested types (compiler limitation)");
195 ignoreFurtherInvestigation = true;
199 ResolvedTypeX declaringTypeX = world.fromEclipse(onTypeBinding);
200 ResolvedTypeX aspectType = world.fromEclipse(classScope.referenceContext.binding);
202 ResolvedMember bindingAsMember = world.makeResolvedMember(binding);
204 ResolvedMember signature =
205 new ResolvedMember(Member.CONSTRUCTOR, declaringTypeX, declaredModifiers,
206 ResolvedTypeX.VOID, "<init>", bindingAsMember.getParameterTypes());
207 signature.setCheckedExceptions(world.fromEclipse(binding.thrownExceptions));
208 ResolvedMember syntheticInterMember =
209 AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType);
211 NewConstructorTypeMunger myMunger =
212 new NewConstructorTypeMunger(signature, syntheticInterMember, null, null);
214 myMunger.check(world);
216 this.selector = binding.selector =
217 NameMangler.postIntroducedConstructor(
218 EclipseWorld.fromBinding(binding.declaringClass),
219 declaringTypeX).toCharArray();
221 xcut.addTypeMunger(new EclipseTypeMunger(myMunger, aspectType, this));
225 private AjAttribute makeAttribute(EclipseWorld world) {
226 if (explicitConstructorCall != null && !(explicitConstructorCall.binding instanceof ProblemMethodBinding)) {
227 MethodBinding explicitConstructor = explicitConstructorCall.binding;
228 if (explicitConstructor.alwaysNeedsAccessMethod()) {
229 explicitConstructor = explicitConstructor.getAccessMethod(true);
233 ((NewConstructorTypeMunger)munger).setExplicitConstructor(
234 world.makeResolvedMember(explicitConstructor));
236 ((NewConstructorTypeMunger)munger).setExplicitConstructor(
237 new ResolvedMember(Member.CONSTRUCTOR,
238 EclipseWorld.fromBinding(onTypeBinding.superclass()),
239 0, ResolvedTypeX.VOID, "<init>", TypeX.NONE));
241 return new AjAttribute.TypeMunger(munger);
245 public void generateCode(ClassScope classScope, ClassFile classFile) {
246 if (ignoreFurtherInvestigation) return;
247 EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope);
248 classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute(world)));
249 super.generateCode(classScope, classFile);
251 preMethod.generateCode(classScope, classFile);
253 protected Shadow.Kind getShadowKindForBody() {
254 return Shadow.ConstructorExecution;