]> source.dussan.org Git - aspectj.git/blob
8ee80bdc269869559ad24840c666c81741f72360
[aspectj.git] /
1 /* *******************************************************************
2  * Copyright (c) 2010 Contributors
3  * All rights reserved. 
4  * This program and the accompanying materials are made available 
5  * under the terms of the Eclipse Public License v1.0 
6  * which accompanies this distribution and is available at 
7  * http://www.eclipse.org/legal/epl-v10.html 
8  *  
9  * Contributors: 
10  *     Andy Clement - SpringSource
11  * ******************************************************************/
12 package org.aspectj.ajdt.internal.compiler.ast;
13
14 import java.lang.reflect.Modifier;
15 import java.util.Collections;
16
17 import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
18 import org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceLocation;
19 import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
20 import org.aspectj.ajdt.internal.compiler.lookup.InterTypeScope;
21 import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
22 import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
23 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
24 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
25 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BlockScope;
26 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
27 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
28 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
29 import org.aspectj.weaver.AjAttribute;
30 import org.aspectj.weaver.NewMemberClassTypeMunger;
31 import org.aspectj.weaver.ResolvedType;
32 import org.aspectj.weaver.ResolvedTypeMunger;
33
34 /**
35  * Represents an intertype member class declaration.
36  * 
37  * @author Andy Clement
38  * @since 1.6.9
39  */
40 public class IntertypeMemberClassDeclaration extends TypeDeclaration {
41
42         // The target type for this inner class
43         private TypeReference onType;
44         private ReferenceBinding onTypeResolvedBinding;
45         private NewMemberClassTypeMunger newMemberClassTypeMunger;
46         protected InterTypeScope interTypeScope;
47         // When set to true, the scope hierarchy for the field/method declaration has been correctly modified to include an intertype
48         // scope which resolves things relative to the targeted type.
49         private boolean scopeSetup = false;
50
51         public IntertypeMemberClassDeclaration(CompilationResult compilationResult) {
52                 super(compilationResult);
53         }
54
55         public ResolvedTypeMunger getMunger() {
56                 return newMemberClassTypeMunger;
57         }
58
59         @Override
60         public void resolve(ClassScope aspectScope) {
61                 resolveOnType(aspectScope);
62                 ensureScopeSetup();
63                 super.resolve(aspectScope);
64         }
65
66         @Override
67         public void resolve() {
68                 super.resolve();
69         }
70
71         @Override
72         public void resolve(BlockScope blockScope) {
73                 throw new IllegalStateException();
74         }
75
76         @Override
77         public void resolve(CompilationUnitScope upperScope) {
78                 throw new IllegalStateException();
79         }
80
81         @SuppressWarnings("unchecked")
82         @Override
83         protected void generateAttributes(ClassFile classFile) {
84                 // classFile.extraAttributes.add(new EclipseAttributeAdapter(makeAttribute()));
85                 super.generateAttributes(classFile);
86         }
87
88         public AjAttribute getAttribute() {
89                 // if there were problems then there is nothing to return
90                 if (newMemberClassTypeMunger == null) {
91                         return null;
92                 }
93                 return new AjAttribute.TypeMunger(newMemberClassTypeMunger);
94         }
95
96         /**
97          * Called just before the compiler is going to start resolving elements of a declaration, this method adds an intertype scope so
98          * that elements of the type targeted by the ITD can be resolved. For example, if type variables are referred to in the ontype
99          * for the ITD, they have to be resolved against the ontype, not the aspect containing the ITD.
100          */
101         public void ensureScopeSetup() {
102                 if (scopeSetup) {
103                         return; // don't do it again
104                 }
105                 ClassScope scope = this.scope;
106
107                 // TODO [inner] ton of stuff related to parameterization support
108
109                 // if (ot instanceof ParameterizedQualifiedTypeReference) { // pr132349
110                 // ParameterizedQualifiedTypeReference pref = (ParameterizedQualifiedTypeReference) ot;
111                 // if (pref.typeArguments != null && pref.typeArguments.length != 0) {
112                 // boolean usingNonTypeVariableInITD = false;
113                 // // Check if any of them are not type variables
114                 // for (int i = 0; i < pref.typeArguments.length; i++) {
115                 // TypeReference[] refs = pref.typeArguments[i];
116                 // for (int j = 0; refs != null && j < refs.length; j++) {
117                 // TypeBinding tb = refs[j].getTypeBindingPublic(scope.parent);
118                 // if (!tb.isTypeVariable() && !(tb instanceof ProblemReferenceBinding)) {
119                 // usingNonTypeVariableInITD = true;
120                 // }
121                 //
122                 // }
123                 // }
124                 // if (usingNonTypeVariableInITD) {
125                 // scope.problemReporter().signalError(sourceStart, sourceEnd,
126                 // "Cannot make inter-type declarations on parameterized types");
127                 // // to prevent disgusting cascading errors after this problem - lets null out what leads to them (pr105038)
128                 // this.arguments = null;
129                 // this.returnType = new SingleTypeReference(TypeReference.VOID, 0L);
130                 //
131                 // this.ignoreFurtherInvestigation = true;
132                 // ReferenceBinding closestMatch = null;
133                 // rb = new ProblemReferenceBinding(ot.getParameterizedTypeName(), closestMatch, 0);
134                 // onType = null;
135                 // }
136                 // }
137                 //
138                 // }
139
140                 // // Work out the real base type
141                 // if (onType instanceof ParameterizedSingleTypeReference) {
142                 // ParameterizedSingleTypeReference pref = (ParameterizedSingleTypeReference) ot;
143                 // long pos = (((long) pref.sourceStart) << 32) | pref.sourceEnd;
144                 // ot = new SingleTypeReference(pref.token, pos);
145                 // } else if (ot instanceof ParameterizedQualifiedTypeReference) {
146                 // ParameterizedQualifiedTypeReference pref = (ParameterizedQualifiedTypeReference) ot;
147                 // long pos = (((long) pref.sourceStart) << 32) | pref.sourceEnd;
148                 // ot = new QualifiedTypeReference(pref.tokens, new long[] { pos });// SingleTypeReference(pref.Quatoken,pos);
149                 // }
150
151                 // resolve it
152                 // if (rb == null) {
153                 // rb = (ReferenceBinding) ot.getTypeBindingPublic(scope.parent);
154                 // }
155
156                 // pr203646 - if we have ended up with the raw type, get back to the underlying generic one.
157                 // if (rb.isRawType() && rb.isMemberType()) {
158                 // // if the real target type used a type variable alias then we can do this OK, but need to switch things around, we want
159                 // // the generic type
160                 // rb = ((RawTypeBinding) rb).type;
161                 // }
162
163                 // if (rb instanceof TypeVariableBinding) {
164                 // scope.problemReporter().signalError(sourceStart, sourceEnd,
165                 // "Cannot make inter-type declarations on type variables, use an interface and declare parents");
166                 // // to prevent disgusting cascading errors after this problem - lets null out what leads to them (pr105038)
167                 // this.arguments = null;
168                 // this.returnType = new SingleTypeReference(TypeReference.VOID, 0L);
169                 //
170                 // this.ignoreFurtherInvestigation = true;
171                 // ReferenceBinding closestMatch = null;
172                 // if (((TypeVariableBinding) rb).firstBound != null) {
173                 // closestMatch = ((TypeVariableBinding) rb).firstBound.enclosingType();
174                 // }
175                 // rb = new ProblemReferenceBinding(rb.compoundName, closestMatch, 0);
176                 // }
177
178                 // if resolution failed, give up - someone else is going to report an error
179                 // if (rb instanceof ProblemReferenceBinding) {
180                 // return;
181                 // }
182
183                 interTypeScope = new InterTypeScope(scope.parent, onTypeResolvedBinding, Collections.emptyList());
184                 // FIXME asc verify the choice of lines here...
185                 // Two versions of this next line.
186                 // First one tricks the JDT variable processing code so that it won't complain if
187                 // you refer to a type variable from a static ITD - it *is* a problem and it *will* be caught, but later and
188                 // by the AJDT code so we can put out a much nicer message.
189                 // scope.isStatic = (typeVariableAliases != null ? false : Modifier.isStatic(declaredModifiers));
190                 // this is the original version in case tricking the JDT causes grief (if you reinstate this variant, you
191                 // will need to change the expected messages output for some of the generic ITD tests)
192                 // scope.isStatic = Modifier.isStatic(declaredModifiers);
193                 scope.parent = interTypeScope;
194                 scopeSetup = true;
195         }
196
197         public void setOnType(TypeReference onType) {
198                 this.onType = onType;
199         }
200
201         private void resolveOnType(ClassScope cuScope) {
202                 if (onType == null || onTypeResolvedBinding != null) {
203                         return;
204                 } // error reported elsewhere.
205
206                 onTypeResolvedBinding = (ReferenceBinding) onType.getTypeBindingPublic(cuScope);
207                 if (!onTypeResolvedBinding.isValidBinding()) {
208                         cuScope.problemReporter().invalidType(onType, onTypeResolvedBinding);
209                         ignoreFurtherInvestigation = true;
210                 }
211         }
212
213         public EclipseTypeMunger build(ClassScope classScope) {
214                 EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
215                 resolveOnType(classScope);
216                 ensureScopeSetup();
217
218                 if (ignoreFurtherInvestigation) {
219                         return null;
220                 }
221
222                 if (onTypeResolvedBinding.isInterface() || onTypeResolvedBinding.isEnum() || onTypeResolvedBinding.isAnnotationType()) {
223                         scope.problemReporter().signalError(
224                                         sourceStart,
225                                         sourceEnd,
226                                         "Cannot declare new member type on '" + onType.toString()
227                                                         + "'. New member types can only be specified on classes (compiler limitation)");
228                         return null;
229                 }
230
231                 if (!Modifier.isStatic(modifiers)) {
232                         scope.problemReporter().signalError(sourceStart, sourceEnd,
233                                         "Intertype declared member types can only be static (compiler limitation)");
234                         return null;
235                 }
236
237                 ResolvedType declaringType = world.fromBinding(onTypeResolvedBinding).resolve(world.getWorld());
238                 if (declaringType.isRawType() || declaringType.isParameterizedType()) {
239                         declaringType = declaringType.getGenericType();
240                 }
241
242                 if (interTypeScope == null) {
243                         return null; // We encountered a problem building the scope, don't continue - error already reported
244                 }
245
246                 // TODO [inner] use the interTypeScope.getRecoveryAliases
247                 // TODO [inner] should mark it in the aspect as unreachable - it is not to be considered part of the aspect
248                 newMemberClassTypeMunger = new NewMemberClassTypeMunger(declaringType, new String(this.name));
249                 newMemberClassTypeMunger.setSourceLocation(new EclipseSourceLocation(compilationResult, sourceStart, sourceEnd));
250                 ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding);
251                 return new EclipseTypeMunger(world, newMemberClassTypeMunger, aspectType, null);
252         }
253 }