summaryrefslogtreecommitdiffstats
path: root/org.aspectj.ajdt.core
diff options
context:
space:
mode:
authoraclement <aclement>2005-08-22 16:53:16 +0000
committeraclement <aclement>2005-08-22 16:53:16 +0000
commit84cc03d325e7662f1bfe6381a060cf36a829388b (patch)
tree1dc577fa9b1039ddbbaa87292d2aeb20543e0377 /org.aspectj.ajdt.core
parente4714fa267754554f6788c434cea03fb748d5a65 (diff)
downloadaspectj-84cc03d325e7662f1bfe6381a060cf36a829388b.tar.gz
aspectj-84cc03d325e7662f1bfe6381a060cf36a829388b.zip
genericitds: An ITD now records the set of aliases used for type variables on a target type, and has the ability to modify the scope hierarchy for some member earlier than in resolve (required when using tvar references in ITD ontypes)
Diffstat (limited to 'org.aspectj.ajdt.core')
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java182
1 files changed, 126 insertions, 56 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java
index b8eeb4a85..f48c1cc24 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java
@@ -26,9 +26,9 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
-import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -46,12 +46,23 @@ import org.aspectj.weaver.Shadow;
public abstract class InterTypeDeclaration extends AjMethodDeclaration {
protected TypeReference onType;
protected ReferenceBinding onTypeBinding;
- protected List phantomTypeVariableToRealIndex;
-
protected ResolvedTypeMunger munger;
protected int declaredModifiers;
protected char[] declaredSelector;
+ /**
+ * If targetting a generic type and wanting to use its type variables, an ITD can use an alternative name for
+ * them. This is a list of strings representing the alternative names - the position in the list is used to
+ * match it to the real type variable in the target generic type.
+ */
+ protected List typeVariableAliases;
+
+ /**
+ * When set to true, the scope hierarchy for the field/method declaration has been correctly modified to
+ * include an intertypescope which resolves things relative to the targetted type.
+ */
+ private boolean scopeSetup = false;
+
// XXXAJ5 - When the compiler is changed, these will exist somewhere in it...
private final static short ACC_ANNOTATION = 0x2000;
private final static short ACC_ENUM = 0x4000;
@@ -59,9 +70,14 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration {
public InterTypeDeclaration(CompilationResult result, TypeReference onType) {
super(result);
- this.onType = onType;
+ setOnType(onType);
modifiers = AccPublic | AccStatic;
}
+
+ public void setOnType(TypeReference onType) {
+ this.onType = onType;
+ determineTypeVariableAliases();
+ }
public void setDeclaredModifiers(int modifiers) {
this.declaredModifiers = modifiers;
@@ -108,14 +124,16 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration {
public void resolve(ClassScope upperScope) {
if (ignoreFurtherInvestigation) return;
-
- ClassScope newParent = new InterTypeScope(upperScope, onTypeBinding);
- scope.parent = newParent;
- this.scope.isStatic = Modifier.isStatic(declaredModifiers);
+ if (!scopeSetup) {
+ ClassScope newParent = new InterTypeScope(upperScope, onTypeBinding,typeVariableAliases);
+ scope.parent = newParent;
+ this.scope.isStatic = Modifier.isStatic(declaredModifiers);
+ scopeSetup = true;
+ }
fixSuperCallsForInterfaceContext(upperScope);
if (ignoreFurtherInvestigation) return;
- super.resolve(newParent);
+ super.resolve((ClassScope)scope.parent);//newParent);
fixSuperCallsInBody();
}
@@ -140,7 +158,9 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration {
}
protected void resolveOnType(ClassScope classScope) {
- checkSpec();
+ checkSpec();
+ // If they did supply a parameterized single type reference, we need to do
+ // some extra checks...
if (onType instanceof ParameterizedSingleTypeReference) {
resolveTypeParametersForITDOnGenericType(classScope);
} else {
@@ -153,23 +173,15 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration {
}
/**
- * Here we build a map from the 'names' the user specified in the target type for their
- * ITD to the positions of the real type variables in the target generic type. This will
- * enable us later (when parameterizing the ITD in the InterTypeMemberFinder) to modify
- * anywhere else the declaration uses these same letters to the correct type variable
- * in the generic type.
- *
- * This method also performs some checks to verify the ITD is well-formed.
+ * Transform the parameterized type binding (e.g. SomeType<A,B,C>) to a
+ * real type (e.g. SomeType). The only kind of parameterization allowed
+ * is with type variables and those are references to type variables on
+ * the target type. Once we have worked out the base generic type intended
+ * then we do lots of checks to verify the declaration was well formed.
*/
private void resolveTypeParametersForITDOnGenericType(ClassScope classScope) {
- // we have to resolve this to the base type, and in the process
- // check that the number of type variables matches.
- // Then we work out how the letters in the ITD map onto the letters in
- // the type declaration and swap them.
-
- // we need to build a map from type variable names to arguments in the real generic type
-
- TypeReference original = onType;
+
+ // Collapse the parameterized reference to its generic type
ParameterizedSingleTypeReference pref = (ParameterizedSingleTypeReference) onType;
long pos = (((long)pref.sourceStart) << 32) | pref.sourceEnd;
onType = new SingleTypeReference(pref.token,pos);
@@ -180,9 +192,11 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration {
ignoreFurtherInvestigation = true;
}
+ int aliasCount = (typeVariableAliases==null?0:typeVariableAliases.size());
+
// Cannot specify a parameterized target type for the ITD if the target
// type is not generic.
- if (typeParameters.length!=0 && !onTypeBinding.isGenericType()) {
+ if (aliasCount!=0 && !onTypeBinding.isGenericType()) {
scope.problemReporter().signalError(sourceStart,sourceEnd,
"Type parameters can not be specified in the ITD target type - the target type "+onTypeBinding.debugName()+" is not generic.");
ignoreFurtherInvestigation = true;
@@ -190,38 +204,42 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration {
}
// Check they have supplied the right number of type parameters on the ITD target type
- if (onTypeBinding.typeVariables().length != typeParameters.length) {
- scope.problemReporter().signalError(sourceStart, sourceEnd,
- "Incorrect number of type parameters supplied. The generic type "+onTypeBinding.debugName()+" has "+
- onTypeBinding.typeVariables().length+" type parameters, not "+typeParameters.length+".");
- ignoreFurtherInvestigation = true;
- return;
- }
-
- // check if they used stupid names for type variables
- for (int i = 0; i < typeParameters.length; i++) {
- TypeParameter array_element = typeParameters[i];
- SingleTypeReference str = new SingleTypeReference(array_element.name,0);
- TypeBinding tb = str.getTypeBindingPublic(classScope);
- if (tb!=null && !(tb instanceof ProblemReferenceBinding)) {
- scope.problemReporter().signalError(sourceStart,sourceEnd,
- "Intertype declarations can only be made on the generic type, not on a parameterized type. The name '"+
- CharOperation.charToString(array_element.name)+"' cannot be used as a type parameter, since it refers to a real type.");
+ if (aliasCount>0) {
+ if (onTypeBinding.typeVariables().length != aliasCount) { // typeParameters.length) { phantom contains the fake ones from the ontype, typeparameters will also include extra things if it is a generic method
+ scope.problemReporter().signalError(sourceStart, sourceEnd,
+ "Incorrect number of type parameters supplied. The generic type "+onTypeBinding.debugName()+" has "+
+ onTypeBinding.typeVariables().length+" type parameters, not "+aliasCount+".");
ignoreFurtherInvestigation = true;
return;
-
}
}
- TypeVariableBinding[] tVarsInGenericType = onTypeBinding.typeVariables();
- phantomTypeVariableToRealIndex = new ArrayList(); /* Name>GenericTypeVariablePosition */
- TypeReference[] targs = pref.typeArguments;
- if (targs!=null) {
- for (int i = 0; i < targs.length; i++) {
- TypeReference tref = targs[i];
- phantomTypeVariableToRealIndex.add(CharOperation.toString(tref.getTypeName()));//tVarsInGenericType[i]);
- }
+ // check if they used stupid names for type variables
+ if (aliasCount>0) {
+ for (int i = 0; i < aliasCount; i++) {
+ String array_element = (String)typeVariableAliases.get(i);
+ SingleTypeReference str = new SingleTypeReference(array_element.toCharArray(),0);
+ TypeBinding tb = str.getTypeBindingPublic(classScope);
+ if (tb!=null && !(tb instanceof ProblemReferenceBinding)) {
+ scope.problemReporter().signalError(sourceStart,sourceEnd,
+ "Intertype declarations can only be made on the generic type, not on a parameterized type. The name '"+
+ array_element+"' cannot be used as a type parameter, since it refers to a real type.");
+ ignoreFurtherInvestigation = true;
+ return;
+
+ }
+ }
}
+
+// TypeVariableBinding[] tVarsInGenericType = onTypeBinding.typeVariables();
+// typeVariableAliases = new ArrayList(); /* Name>GenericTypeVariablePosition */ // FIXME ASC DONT THINK WE NEED TO BUILD IT HERE AS WELL...
+// TypeReference[] targs = pref.typeArguments;
+// if (targs!=null) {
+// for (int i = 0; i < targs.length; i++) {
+// TypeReference tref = targs[i];
+// typeVariableAliases.add(CharOperation.toString(tref.getTypeName()));//tVarsInGenericType[i]);
+// }
+// }
}
@@ -274,12 +292,64 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration {
return declaredSelector;
}
- public void setOnType(TypeReference onType) {
- this.onType = onType;
- }
-
public TypeReference getOnType() {
return onType;
}
+
+ /**
+ * Create the list of aliases based on what was supplied as parameters for the ontype.
+ * For example, if the declaration is 'List<N> SomeType<N>.foo' then the alias list
+ * will simply contain 'N' and 'N' will mean 'the first type variable declared for
+ * type SomeType'
+ */
+ public void determineTypeVariableAliases() {
+ if (onType!=null && onType instanceof ParameterizedSingleTypeReference) {
+ ParameterizedSingleTypeReference paramRef = (ParameterizedSingleTypeReference) onType;
+ TypeReference[] rb = paramRef.typeArguments;
+ typeVariableAliases = new ArrayList();
+ for (int i = 0; i < rb.length; i++) {
+ typeVariableAliases.add(CharOperation.toString(rb[i].getTypeName()));
+ }
+ }
+ }
+
+ /**
+ * Called just before the compiler is going to start resolving elements of a declaration, this method
+ * adds an intertypescope between the methodscope and classscope so that elements of the type targetted
+ * by the ITD can be resolved. For example, if type variables are referred to in the ontype for the ITD,
+ * they have to be resolved against the ontype, not the aspect containing the ITD.
+ */
+ public void ensureScopeSetup() {
+ if (scopeSetup) return; // don't do it agai
+ MethodScope scope = this.scope;
+
+ TypeReference ot = onType;
+
+ // Work out the real base type
+ if (ot instanceof ParameterizedSingleTypeReference) {
+ ParameterizedSingleTypeReference pref = (ParameterizedSingleTypeReference) ot;
+ long pos = (((long)pref.sourceStart) << 32) | pref.sourceEnd;
+ ot = new SingleTypeReference(pref.token,pos);
+ }
+
+ // resolve it
+ ReferenceBinding rb = (ReferenceBinding)ot.getTypeBindingPublic(scope.parent);
+
+ // if resolution failed, give up - someone else is going to report an error
+ if (rb instanceof ProblemReferenceBinding) return;
+
+ ClassScope newParent = new InterTypeScope(scope.parent, rb, typeVariableAliases);
+ // FIXME asc verify the choice of lines here...
+ // Two versions of this next line.
+ // First one tricks the JDT variable processing code so that it won't complain if
+ // you refer to a type variable from a static ITD - it *is* a problem and it *will* be caught, but later and
+ // by the AJDT code so we can put out a much nicer message.
+ scope.isStatic = (typeVariableAliases!=null?false:Modifier.isStatic(declaredModifiers));
+ // this is the original version in case tricking the JDT causes grief (if you reinstate this variant, you
+ // will need to change the expected messages output for some of the generic ITD tests)
+ // scope.isStatic = Modifier.isStatic(declaredModifiers);
+ scope.parent = newParent;
+ scopeSetup = true;
+ }
}