]> source.dussan.org Git - aspectj.git/blob
972d07c2a2429bc98c4924684ff04f46b63e0401
[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.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;
23
24 /**
25  * An inter-type constructor declaration.
26  * 
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.
30  * 
31  * @author Jim Hugunin
32  */
33 public class InterTypeConstructorDeclaration extends InterTypeDeclaration {     
34         private MethodDeclaration preMethod;
35         private ExplicitConstructorCall explicitConstructorCall = null;
36         
37         public InterTypeConstructorDeclaration(CompilationResult result, TypeReference onType) {
38                 super(result, onType);
39         }
40         
41         public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
42                 if (ignoreFurtherInvestigation)
43                         return;
44             parser.parse(this, unit); 
45         }
46
47         public void resolve(ClassScope upperScope) {
48                 if (munger == null || binding == null) ignoreFurtherInvestigation = true;
49                 if (ignoreFurtherInvestigation) return;
50
51                 explicitConstructorCall = null;
52                 if (statements != null && statements.length > 0 && 
53                         statements[0] instanceof ExplicitConstructorCall)
54                 {
55                         explicitConstructorCall = (ExplicitConstructorCall) statements[0];
56                         statements = AstUtil.remove(0, statements);
57                 }
58                 
59                 preMethod = makePreMethod(upperScope, explicitConstructorCall);
60                 
61                 binding.parameters  = AstUtil.insert(onTypeBinding, binding.parameters);
62                 this.arguments = AstUtil.insert(
63                         AstUtil.makeFinalArgument("ajc$this_".toCharArray(), onTypeBinding),
64                         this.arguments);
65                         
66                 super.resolve(upperScope);
67         }
68
69         private MethodDeclaration makePreMethod(ClassScope scope, 
70                                                                                         ExplicitConstructorCall explicitConstructorCall)
71         {
72                 EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(scope);
73                 
74                 TypeX aspectTypeX = EclipseFactory.fromBinding(binding.declaringClass);
75                 TypeX targetTypeX = EclipseFactory.fromBinding(onTypeBinding);
76                 
77                 ArrayBinding objectArrayBinding = scope.createArray(scope.getJavaLangObject(), 1);
78                 
79                 
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();
84                 
85                 
86                 pre.arguments = AstUtil.copyArguments(this.arguments);
87                 
88                 //XXX should do exceptions
89                 
90                 pre.scope = new MethodScope(scope, pre, true);
91                 //??? do we need to do anything with scope???
92                 
93                 pre.binding = world.makeMethodBinding(
94                         AjcMemberMaker.preIntroducedConstructor(aspectTypeX, targetTypeX, 
95                                         EclipseFactory.fromBindings(binding.parameters)));
96                 
97                 pre.bindArguments();
98                 pre.bindThrownExceptions();
99                 
100                 
101                 if (explicitConstructorCall == null) {
102                         pre.statements = new Statement[] {};
103                 } else {
104                         pre.statements = new Statement[] {
105                                 explicitConstructorCall
106                         };
107                 }
108                 
109                 InterTypeScope newParent =
110                         new InterTypeScope(scope, onTypeBinding);
111                 pre.scope.parent = newParent;
112
113                 pre.resolveStatements(); //newParent);
114                 
115                 
116                 
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);
123                         }
124                 }
125                 
126                 int nExprs;
127                 if (explicitConstructor == null) nExprs = 0;
128                 else nExprs = explicitConstructor.parameters.length;
129                 
130                 
131                 ArrayInitializer init = new ArrayInitializer();
132                 init.expressions = new Expression[nExprs + nParams];
133                 int index = 0;
134                 for (int i=0; i < nExprs; i++) {
135                         if (i >= explicitConstructorCall.arguments.length) {
136                                 init.expressions[index++] = new NullLiteral(0, 0);
137                                 continue;
138                         }
139                         
140                         
141                         Expression arg = explicitConstructorCall.arguments[i];
142                         ResolvedMember conversionMethod = 
143                                 AjcMemberMaker.toObjectConversionMethod(EclipseFactory.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 });
149                         }
150                         init.expressions[index++] = arg;
151                 }
152                 
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(EclipseFactory.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 });
163                         }
164                         init.expressions[index++] = arg;
165                 }
166                 
167                 init.binding =objectArrayBinding;
168                 
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;
174                 
175
176                 
177                 
178                 pre.statements = new Statement[] {
179                         new ReturnStatement(newArray, 0, 0),
180                 };
181                 return pre;
182         }
183
184
185
186
187         public EclipseTypeMunger build(ClassScope classScope) {
188                 EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
189
190                 binding = classScope.referenceContext.binding.resolveTypesFor(binding);
191                 
192                 resolveOnType(classScope);
193                 if (ignoreFurtherInvestigation) return null;
194                 
195                 
196                 if (onTypeBinding.isInterface()) {
197                         classScope.problemReporter().signalError(sourceStart, sourceEnd,
198                                                         "can't define constructors on interfaces");
199                         ignoreFurtherInvestigation = true;
200                         return null;
201                 }
202                 
203                 if (onTypeBinding.isNestedType()) {
204                         classScope.problemReporter().signalError(sourceStart, sourceEnd,
205                                 "can't define constructors on nested types (compiler limitation)");
206                         ignoreFurtherInvestigation = true;
207                         return null;
208                 }       
209                 
210                 ResolvedTypeX declaringTypeX = world.fromEclipse(onTypeBinding);
211                 ResolvedTypeX aspectType = world.fromEclipse(classScope.referenceContext.binding);
212                 
213                 ResolvedMember bindingAsMember = EclipseFactory.makeResolvedMember(binding);
214                 
215                 ResolvedMember signature =
216                         new ResolvedMember(Member.CONSTRUCTOR, declaringTypeX, declaredModifiers, 
217                                         ResolvedTypeX.VOID, "<init>", bindingAsMember.getParameterTypes(),
218                                         world.fromEclipse(binding.thrownExceptions));                   
219                 ResolvedMember syntheticInterMember =
220                         AjcMemberMaker.interConstructor(declaringTypeX,  signature, aspectType);
221                 
222                 NewConstructorTypeMunger myMunger = 
223                         new NewConstructorTypeMunger(signature, syntheticInterMember, null, null);
224                 setMunger(myMunger);
225                 myMunger.check(world.getWorld());
226                 
227                 this.selector = binding.selector =
228                         NameMangler.postIntroducedConstructor(
229                                 EclipseFactory.fromBinding(binding.declaringClass),
230                                 declaringTypeX).toCharArray();
231                 
232                 return new EclipseTypeMunger(world, myMunger, aspectType, this);
233         }
234         
235         
236         private AjAttribute makeAttribute(EclipseFactory world) {
237                 if (explicitConstructorCall != null && !(explicitConstructorCall.binding instanceof ProblemMethodBinding)) {
238                         MethodBinding explicitConstructor = explicitConstructorCall.binding;
239                         if (explicitConstructor.alwaysNeedsAccessMethod()) {
240                                 explicitConstructor = explicitConstructor.getAccessMethod(true);
241                         }
242                         
243                         
244                         ((NewConstructorTypeMunger)munger).setExplicitConstructor(
245                                 EclipseFactory.makeResolvedMember(explicitConstructor));
246                 } else {
247                         ((NewConstructorTypeMunger)munger).setExplicitConstructor(
248                                 new ResolvedMember(Member.CONSTRUCTOR, 
249                                         EclipseFactory.fromBinding(onTypeBinding.superclass()),
250                                         0, ResolvedTypeX.VOID, "<init>", TypeX.NONE));
251                 }
252                 return new AjAttribute.TypeMunger(munger);
253         }
254         
255         
256         public void generateCode(ClassScope classScope, ClassFile classFile) {
257                 if (ignoreFurtherInvestigation) return;
258                 EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
259                 classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute(world)));
260                 super.generateCode(classScope, classFile);
261                 
262                 preMethod.generateCode(classScope, classFile);
263         }
264         protected Shadow.Kind getShadowKindForBody() {
265                 return Shadow.ConstructorExecution;
266         }
267         
268 }