]> source.dussan.org Git - aspectj.git/blob
5abe2ce07fe53cfda05c4ac2fa614dbe0c3ec38e
[aspectj.git] /
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 Common Public License v1.0 
6  * which accompanies this distribution and is available at 
7  * http://www.eclipse.org/legal/cpl-v10.html 
8  *  
9  * Contributors: 
10  *     PARC     initial implementation 
11  * ******************************************************************/
12
13
14 package org.aspectj.ajdt.internal.compiler.ast;
15
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;
22
23
24 public class InterTypeConstructorDeclaration extends InterTypeDeclaration {     
25         private MethodDeclaration preMethod;
26         private ExplicitConstructorCall explicitConstructorCall = null;
27         
28         public InterTypeConstructorDeclaration(CompilationResult result, TypeReference onType) {
29                 super(result, onType);
30         }
31         
32         public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
33                 if (ignoreFurtherInvestigation)
34                         return;
35             parser.parseAsConstructor(this, unit);
36         }
37
38         public void resolve(ClassScope upperScope) {
39                 if (munger == null || binding == null) ignoreFurtherInvestigation = true;
40                 if (ignoreFurtherInvestigation) return;
41
42                 explicitConstructorCall = null;
43                 if (statements != null && statements.length > 0 && 
44                         statements[0] instanceof ExplicitConstructorCall)
45                 {
46                         explicitConstructorCall = (ExplicitConstructorCall) statements[0];
47                         statements = AstUtil.remove(0, statements);
48                 }
49                 
50                 preMethod = makePreMethod(upperScope, explicitConstructorCall);
51                 
52                 binding.parameters  = AstUtil.insert(onTypeBinding, binding.parameters);
53                 this.arguments = AstUtil.insert(
54                         AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding),
55                         this.arguments);
56                         
57                 super.resolve(upperScope);
58         }
59
60         private MethodDeclaration makePreMethod(ClassScope scope, 
61                                                                                         ExplicitConstructorCall explicitConstructorCall)
62         {
63                 EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(scope);
64                 
65                 TypeX aspectTypeX = EclipseWorld.fromBinding(binding.declaringClass);
66                 TypeX targetTypeX = EclipseWorld.fromBinding(onTypeBinding);
67                 
68                 ArrayBinding objectArrayBinding = scope.createArray(scope.getJavaLangObject(), 1);
69                 
70                 
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();
75                 
76                 
77                 pre.arguments = AstUtil.copyArguments(this.arguments);
78                 
79                 //XXX should do exceptions
80                 
81                 pre.scope = new MethodScope(scope, pre, true);
82                 //??? do we need to do anything with scope???
83                 
84                 pre.binding = world.makeMethodBinding(
85                         AjcMemberMaker.preIntroducedConstructor(aspectTypeX, targetTypeX, 
86                                         world.fromBindings(binding.parameters)));
87                 
88                 pre.bindArguments();
89                 pre.bindThrownExceptions();
90                 
91                 
92                 if (explicitConstructorCall == null) {
93                         pre.statements = new Statement[] {};
94                 } else {
95                         pre.statements = new Statement[] {
96                                 explicitConstructorCall
97                         };
98                 }
99                 
100                 InterTypeScope newParent =
101                         new InterTypeScope(scope, onTypeBinding);
102                 pre.scope.parent = newParent;
103
104                 pre.resolveStatements(newParent);
105                 
106                 
107                 
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);
114                         }
115                 }
116                 
117                 int nExprs;
118                 if (explicitConstructor == null) nExprs = 0;
119                 else nExprs = explicitConstructor.parameters.length;
120                 
121                 
122                 ArrayInitializer init = new ArrayInitializer();
123                 init.expressions = new Expression[nExprs + nParams];
124                 int index = 0;
125                 for (int i=0; i < nExprs; i++) {
126                         if (i >= explicitConstructorCall.arguments.length) {
127                                 init.expressions[index++] = new NullLiteral(0, 0);
128                                 continue;
129                         }
130                         
131                         
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 });
140                         }
141                         init.expressions[index++] = arg;
142                 }
143                 
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 });
154                         }
155                         init.expressions[index++] = arg;
156                 }
157                 
158                 init.binding =objectArrayBinding;
159                 
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;
165                 
166
167                 
168                 
169                 pre.statements = new Statement[] {
170                         new ReturnStatement(newArray, 0, 0),
171                 };
172                 return pre;
173         }
174
175
176
177
178         public void build(ClassScope classScope, CrosscuttingMembers xcut) {
179                 EclipseWorld world = EclipseWorld.fromScopeLookupEnvironment(classScope);
180
181                 binding = classScope.referenceContext.binding.resolveTypesFor(binding);
182                 
183                 resolveOnType(classScope);
184                 if (ignoreFurtherInvestigation) return;
185                 
186                 
187                 if (onTypeBinding.isInterface()) {
188                         ignoreFurtherInvestigation = true;
189                         return;
190                 }
191                 
192                 if (onTypeBinding.isNestedType()) {
193                         classScope.problemReporter().signalError(sourceStart, sourceEnd,
194                                 "can't define constructors on nested types (compiler limitation)");
195                         ignoreFurtherInvestigation = true;
196                         return;
197                 }       
198                 
199                 ResolvedTypeX declaringTypeX = world.fromEclipse(onTypeBinding);
200                 ResolvedTypeX aspectType = world.fromEclipse(classScope.referenceContext.binding);
201                 
202                 ResolvedMember bindingAsMember = world.makeResolvedMember(binding);
203                 
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);
210                 
211                 NewConstructorTypeMunger myMunger = 
212                         new NewConstructorTypeMunger(signature, syntheticInterMember, null, null);
213                 setMunger(myMunger);
214                 myMunger.check(world);
215                 
216                 this.selector = binding.selector =
217                         NameMangler.postIntroducedConstructor(
218                                 EclipseWorld.fromBinding(binding.declaringClass),
219                                 declaringTypeX).toCharArray();
220                 
221                 xcut.addTypeMunger(new EclipseTypeMunger(myMunger, aspectType, this));
222         }
223         
224         
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);
230                         }
231                         
232                         
233                         ((NewConstructorTypeMunger)munger).setExplicitConstructor(
234                                 world.makeResolvedMember(explicitConstructor));
235                 } else {
236                         ((NewConstructorTypeMunger)munger).setExplicitConstructor(
237                                 new ResolvedMember(Member.CONSTRUCTOR, 
238                                         EclipseWorld.fromBinding(onTypeBinding.superclass()),
239                                         0, ResolvedTypeX.VOID, "<init>", TypeX.NONE));
240                 }
241                 return new AjAttribute.TypeMunger(munger);
242         }
243         
244         
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);
250                 
251                 preMethod.generateCode(classScope, classFile);
252         }
253         protected Shadow.Kind getShadowKindForBody() {
254                 return Shadow.ConstructorExecution;
255         }
256
257 }