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