1 /* *******************************************************************
2 * Copyright (c) 2010 Contributors
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
10 * Andy Clement - SpringSource
11 * ******************************************************************/
12 package org.aspectj.ajdt.internal.compiler.ast;
14 import java.lang.reflect.Modifier;
15 import java.util.Collections;
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;
31 * Represents an intertype member class declaration.
33 * @author Andy Clement
36 public class IntertypeMemberClassDeclaration extends TypeDeclaration {
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;
46 public IntertypeMemberClassDeclaration(CompilationResult compilationResult) {
47 super(compilationResult);
51 public void resolve(ClassScope aspectScope) {
52 resolveOnType(aspectScope);
54 super.resolve(aspectScope);
58 public void resolve() {
63 public void resolve(BlockScope blockScope) {
64 throw new IllegalStateException();
68 public void resolve(CompilationUnitScope upperScope) {
69 throw new IllegalStateException();
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.
77 public void ensureScopeSetup() {
79 return; // don't do it again
81 ClassScope scope = this.scope;
83 // TODO [inner] ton of stuff related to parameterization support
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;
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);
107 // this.ignoreFurtherInvestigation = true;
108 // ReferenceBinding closestMatch = null;
109 // rb = new ProblemReferenceBinding(ot.getParameterizedTypeName(), closestMatch, 0);
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);
129 // rb = (ReferenceBinding) ot.getTypeBindingPublic(scope.parent);
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;
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);
146 // this.ignoreFurtherInvestigation = true;
147 // ReferenceBinding closestMatch = null;
148 // if (((TypeVariableBinding) rb).firstBound != null) {
149 // closestMatch = ((TypeVariableBinding) rb).firstBound.enclosingType();
151 // rb = new ProblemReferenceBinding(rb.compoundName, closestMatch, 0);
154 // if resolution failed, give up - someone else is going to report an error
155 // if (rb instanceof ProblemReferenceBinding) {
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;
173 public void setOnType(TypeReference onType) {
174 this.onType = onType;
177 private void resolveOnType(ClassScope cuScope) {
178 if (onType == null || onTypeResolvedBinding != null) {
180 } // error reported elsewhere.
182 onTypeResolvedBinding = (ReferenceBinding) onType.getTypeBindingPublic(cuScope);
183 if (!onTypeResolvedBinding.isValidBinding()) {
184 cuScope.problemReporter().invalidType(onType, onTypeResolvedBinding);
185 ignoreFurtherInvestigation = true;
189 public EclipseTypeMunger build(ClassScope classScope) {
190 EclipseFactory world = EclipseFactory.fromScopeLookupEnvironment(classScope);
191 resolveOnType(classScope);
194 if (ignoreFurtherInvestigation) {
198 if (onTypeResolvedBinding.isInterface() || onTypeResolvedBinding.isEnum() || onTypeResolvedBinding.isAnnotationType()) {
199 scope.problemReporter().signalError(
202 "Cannot declare new member type on '" + onType.toString()
203 + "'. New member types can only be specified on classes (compiler limitation)");
207 if (!Modifier.isStatic(modifiers)) {
208 scope.problemReporter().signalError(sourceStart, sourceEnd,
209 "Intertype declared member types can only be static (compiler limitation)");
213 ResolvedType declaringType = world.fromBinding(onTypeResolvedBinding).resolve(world.getWorld());
214 if (declaringType.isRawType() || declaringType.isParameterizedType()) {
215 declaringType = declaringType.getGenericType();
218 if (interTypeScope == null) {
219 return null; // We encountered a problem building the scope, don't continue - error already reported
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);