]> source.dussan.org Git - aspectj.git/blob
717197dc2a1004a3d6ada60b9e123119e24f01b2
[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                 resolveOnType(classScope);
191                 if (ignoreFurtherInvestigation) return null;
192                 
193                 binding = classScope.referenceContext.binding.resolveTypesFor(binding);
194                                 
195                 if (onTypeBinding.isInterface()) {
196                         classScope.problemReporter().signalError(sourceStart, sourceEnd,
197                                                         "can't define constructors on interfaces");
198                         ignoreFurtherInvestigation = true;
199                         return null;
200                 }
201                 
202                 if (onTypeBinding.isNestedType()) {
203                         classScope.problemReporter().signalError(sourceStart, sourceEnd,
204                                 "can't define constructors on nested types (compiler limitation)");
205                         ignoreFurtherInvestigation = true;
206                         return null;
207                 }       
208                 
209                 ResolvedTypeX declaringTypeX = world.fromEclipse(onTypeBinding);
210                 ResolvedTypeX aspectType = world.fromEclipse(classScope.referenceContext.binding);
211                 
212                 ResolvedMember bindingAsMember = EclipseFactory.makeResolvedMember(binding);
213                 
214                 ResolvedMember signature =
215                         new ResolvedMember(Member.CONSTRUCTOR, declaringTypeX, declaredModifiers, 
216                                         ResolvedTypeX.VOID, "<init>", bindingAsMember.getParameterTypes(),
217                                         world.fromEclipse(binding.thrownExceptions));                   
218                 ResolvedMember syntheticInterMember =
219                         AjcMemberMaker.interConstructor(declaringTypeX,  signature, aspectType);
220                 
221                 NewConstructorTypeMunger myMunger = 
222                         new NewConstructorTypeMunger(signature, syntheticInterMember, null, null);
223                 setMunger(myMunger);
224                 myMunger.check(world.getWorld());
225                 
226                 this.selector = binding.selector =
227                         NameMangler.postIntroducedConstructor(
228                                 EclipseFactory.fromBinding(binding.declaringClass),
229                                 declaringTypeX).toCharArray();
230                 
231                 return new EclipseTypeMunger(world, myMunger, aspectType, this);
232         }
233         
234         
235         private AjAttribute makeAttribute(EclipseFactory world) {
236                 if (explicitConstructorCall != null && !(explicitConstructorCall.binding instanceof ProblemMethodBinding)) {
237                         MethodBinding explicitConstructor = explicitConstructorCall.binding;
238                         if (explicitConstructor.alwaysNeedsAccessMethod()) {
239                                 explicitConstructor = explicitConstructor.getAccessMethod(true);
240                         }
241                         
242                         
243                         ((NewConstructorTypeMunger)munger).setExplicitConstructor(
244                                 EclipseFactory.makeResolvedMember(explicitConstructor));
245                 } else {
246                         ((NewConstructorTypeMunger)munger).setExplicitConstructor(
247                                 new ResolvedMember(Member.CONSTRUCTOR, 
248                                         EclipseFactory.fromBinding(onTypeBinding.superclass()),
249                                         0, ResolvedTypeX.VOID, "<init>", TypeX.NONE));
250                 }
251                 return new AjAttribute.TypeMunger(munger);
252         }
253         
254         
255         public void generateCode(ClassScope classScope, ClassFile classFile) {
256                 if (ignoreFurtherInvestigation) return;
257                 EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
258                 classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute(world)));
259                 super.generateCode(classScope, classFile);
260                 
261                 preMethod.generateCode(classScope, classFile);
262         }
263         protected Shadow.Kind getShadowKindForBody() {
264                 return Shadow.ConstructorExecution;
265         }
266         
267 }