aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraclement <aclement>2005-08-04 16:11:03 +0000
committeraclement <aclement>2005-08-04 16:11:03 +0000
commit900a3e81d5b09c55e4044451f311f0566c025ec6 (patch)
tree6c1f9e5e84d9edb9fb8f8728a8a701555b10db75
parenta26f850c10f1790682ff9d1f13a4f8d5253f5e71 (diff)
downloadaspectj-900a3e81d5b09c55e4044451f311f0566c025ec6.tar.gz
aspectj-900a3e81d5b09c55e4044451f311f0566c025ec6.zip
genericitds: lots of new support for recursive type variables and ITD ctors.
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java26
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java31
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java171
-rw-r--r--tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java51
-rw-r--r--tests/src/org/aspectj/systemtest/ajc150/ajc150.xml65
-rw-r--r--weaver/src/org/aspectj/weaver/BoundedReferenceType.java22
-rw-r--r--weaver/src/org/aspectj/weaver/JoinPointSignature.java17
-rw-r--r--weaver/src/org/aspectj/weaver/MemberImpl.java12
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedMember.java7
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java35
-rw-r--r--weaver/src/org/aspectj/weaver/TypeFactory.java9
-rw-r--r--weaver/src/org/aspectj/weaver/TypeVariable.java6
-rw-r--r--weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java33
-rw-r--r--weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java4
-rw-r--r--weaver/src/org/aspectj/weaver/World.java28
15 files changed, 386 insertions, 131 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java
index d524dcfbd..0f0cf78b2 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeConstructorDeclaration.java
@@ -13,6 +13,7 @@
package org.aspectj.ajdt.internal.compiler.ast;
+import java.lang.reflect.Modifier;
import org.aspectj.ajdt.internal.compiler.lookup.*;
import org.aspectj.weaver.*;
import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
@@ -94,9 +95,16 @@ public class InterTypeConstructorDeclaration extends InterTypeDeclaration {
pre.scope = new MethodScope(scope, pre, true);
//??? do we need to do anything with scope???
- pre.binding = world.makeMethodBinding(
- AjcMemberMaker.preIntroducedConstructor(aspectTypeX, targetTypeX,
- world.fromBindings(binding.parameters)));
+
+
+ // Use the factory to build a semi-correct resolvedmember - then patch it up with
+ // reset calls. This is SAFE
+ ResolvedMember preIntroducedConstructorRM = world.makeResolvedMember(binding);
+ preIntroducedConstructorRM.resetName(NameMangler.preIntroducedConstructor(aspectTypeX, targetTypeX));
+ preIntroducedConstructorRM.resetModifiers(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
+ preIntroducedConstructorRM.resetReturnTypeToObjectArray();
+
+ pre.binding = world.makeMethodBinding(preIntroducedConstructorRM);
pre.bindArguments();
pre.bindThrownExceptions();
@@ -218,12 +226,14 @@ public class InterTypeConstructorDeclaration extends InterTypeDeclaration {
ResolvedType declaringTypeX = world.fromEclipse(onTypeBinding);
ResolvedType aspectType = world.fromEclipse(classScope.referenceContext.binding);
- ResolvedMember bindingAsMember = world.makeResolvedMember(binding);
- ResolvedMember signature =
- new ResolvedMemberImpl(Member.CONSTRUCTOR, declaringTypeX, declaredModifiers,
- ResolvedType.VOID, "<init>", bindingAsMember.getParameterTypes(),
- world.fromEclipse(binding.thrownExceptions));
+
+ // This signature represents what we want consumers of the targetted type to 'see'
+ ResolvedMember signature = world.makeResolvedMember(binding,onTypeBinding);
+ signature.resetKind(Member.CONSTRUCTOR);
+ signature.resetName("<init>");
+ signature.resetModifiers(declaredModifiers);
+
ResolvedMember syntheticInterMember =
AjcMemberMaker.interConstructor(declaringTypeX, signature, aspectType);
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java
index f20476fdd..21c5f2106 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeMethodDeclaration.java
@@ -17,16 +17,6 @@ import java.lang.reflect.Modifier;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseFactory;
import org.aspectj.ajdt.internal.compiler.lookup.EclipseTypeMunger;
-import org.aspectj.weaver.AjAttribute;
-import org.aspectj.weaver.AjcMemberMaker;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.NameMangler;
-import org.aspectj.weaver.NewMethodTypeMunger;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedMemberImpl;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.UnresolvedType;
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.CompilationUnitDeclaration;
@@ -39,6 +29,14 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.Parser;
import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
+import org.aspectj.weaver.AjAttribute;
+import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.NewMethodTypeMunger;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
/**
* An inter-type method declaration.
@@ -125,12 +123,13 @@ public class InterTypeMethodDeclaration extends InterTypeDeclaration {
if (isTargetAnnotation(classScope,"method")) return null; // Error message output in isTargetAnnotation
if (isTargetEnum(classScope,"method")) return null; // Error message output in isTargetEnum
- ResolvedMemberImpl sig = new ResolvedMemberImpl(Member.METHOD, world.fromBinding(onTypeBinding),
- declaredModifiers, world.fromBinding(binding.returnType), new String(declaredSelector),
- world.fromBindings(binding.parameters),
- world.fromEclipse(binding.thrownExceptions));
-
- sig.setTypeVariables(world.fromBindings(binding.typeVariables));
+
+ // This signature represents what we want consumers of the targetted type to 'see'
+ // must use the factory method to build it since there may be typevariables from the binding
+ // referred to in the parameters/returntype
+ ResolvedMember sig = world.makeResolvedMember(binding,onTypeBinding);
+ sig.resetName(new String(declaredSelector));
+ sig.resetModifiers(declaredModifiers);
NewMethodTypeMunger myMunger = new NewMethodTypeMunger(sig, null);
setMunger(myMunger);
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java
index b853c14a0..85810decc 100644
--- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java
+++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java
@@ -24,26 +24,8 @@ import java.util.Map;
import org.aspectj.ajdt.internal.compiler.ast.AspectDeclaration;
import org.aspectj.ajdt.internal.compiler.ast.AstUtil;
import org.aspectj.ajdt.internal.core.builder.AjBuildManager;
-import org.aspectj.ajdt.internal.core.builder.AsmHierarchyBuilder;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.IMessage.Kind;
-import org.aspectj.weaver.BoundedReferenceType;
-import org.aspectj.weaver.ConcreteTypeMunger;
-import org.aspectj.weaver.IHasPosition;
-import org.aspectj.weaver.Member;
-import org.aspectj.weaver.ReferenceType;
-import org.aspectj.weaver.ResolvedMember;
-import org.aspectj.weaver.ResolvedMemberImpl;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.Shadow;
-import org.aspectj.weaver.TypeFactory;
-import org.aspectj.weaver.TypeVariable;
-import org.aspectj.weaver.TypeVariableDeclaringElement;
-import org.aspectj.weaver.TypeVariableReference;
-import org.aspectj.weaver.TypeVariableReferenceType;
-import org.aspectj.weaver.UnresolvedType;
-import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
-import org.aspectj.weaver.World;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
@@ -64,9 +46,24 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
+import org.aspectj.weaver.BoundedReferenceType;
+import org.aspectj.weaver.ConcreteTypeMunger;
+import org.aspectj.weaver.IHasPosition;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.ReferenceType;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedMemberImpl;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.TypeFactory;
+import org.aspectj.weaver.TypeVariable;
+import org.aspectj.weaver.TypeVariableDeclaringElement;
+import org.aspectj.weaver.TypeVariableReference;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.UnresolvedTypeVariableReferenceType;
+import org.aspectj.weaver.World;
/**
* @author Jim Hugunin
@@ -231,10 +228,14 @@ public class EclipseFactory {
}
}
ResolvedType baseType = UnresolvedType.forName(getName(binding)).resolve(getWorld());
- return TypeFactory.createParameterizedType(
- baseType,
- arguments,
- getWorld());
+
+ // Create an unresolved parameterized type. We can't create a resolved one as the
+ // act of resolution here may cause recursion problems since the parameters may
+ // be type variables that we haven't fixed up yet.
+ if (!baseType.isGenericType() && arguments!=null) baseType = baseType.getGenericType();
+ if (arguments==null) arguments=new UnresolvedType[0];
+ String parameterizedSig = ResolvedType.PARAMETERIZED_TYPE_IDENTIFIER+CharOperation.charToString(binding.genericTypeSignature()).substring(1);
+ return TypeFactory.createUnresolvedParameterizedType(parameterizedSig,baseType.getErasureSignature(),arguments);
}
// Convert the source type binding for a generic type into a generic UnresolvedType
@@ -261,27 +262,47 @@ public class EclipseFactory {
return UnresolvedType.forName(getName(binding));
}
+ /**
+ * Some type variables refer to themselves recursively, this enables us to avoid
+ * recursion problems.
+ */
private static Map typeVariableBindingsInProgress = new HashMap();
+
+ /**
+ * Convert from the eclipse form of type variable (TypeVariableBinding) to the AspectJ
+ * form (TypeVariable).
+ */
private UnresolvedType fromTypeVariableBinding(TypeVariableBinding aTypeVariableBinding) {
+ // first, check for recursive call to this method for the same tvBinding
if (typeVariableBindingsInProgress.containsKey(aTypeVariableBinding)) {
return (UnresolvedType) typeVariableBindingsInProgress.get(aTypeVariableBinding);
}
+ if (typeVariablesForThisMember.containsKey(new Integer(aTypeVariableBinding.rank))) {
+ return (UnresolvedType)typeVariablesForThisMember.get(new Integer(aTypeVariableBinding.rank));
+ }
+ // Create the UnresolvedTypeVariableReferenceType for the type variable
+ String name = CharOperation.charToString(aTypeVariableBinding.sourceName());
+
UnresolvedTypeVariableReferenceType ret = new UnresolvedTypeVariableReferenceType();
typeVariableBindingsInProgress.put(aTypeVariableBinding,ret);
+
+ // Dont set any bounds here, you'll get in a recursive mess
// TODO -- what about lower bounds??
- String name = new String(aTypeVariableBinding.sourceName());
- UnresolvedType superclassType = fromBinding(aTypeVariableBinding.superclass());
+ UnresolvedType superclassType = fromBinding(aTypeVariableBinding.superclass());
UnresolvedType[] superinterfaces = new UnresolvedType[aTypeVariableBinding.superInterfaces.length];
for (int i = 0; i < superinterfaces.length; i++) {
superinterfaces[i] = fromBinding(aTypeVariableBinding.superInterfaces[i]);
}
TypeVariable tv = new TypeVariable(name,superclassType,superinterfaces);
+ tv.setUpperBound(superclassType);
+ tv.setAdditionalInterfaceBounds(superinterfaces);
tv.setRank(aTypeVariableBinding.rank);
- // getting things right for method declaring elements is tricky...
- if (!(aTypeVariableBinding.declaringElement instanceof MethodBinding)) {
- tv.setDeclaringElement(fromBinding(aTypeVariableBinding.declaringElement));
- }
- tv.resolve(world);
+// dont need the declaring element yet...
+// if (aTypeVariableBinding.declaringElement instanceof MethodBinding) {
+// tv.setDeclaringElement(fromBinding((MethodBinding)aTypeVariableBinding.declaringElement);
+// } else {
+// // tv.setDeclaringElement(fromBinding(aTypeVariableBinding.declaringElement));
+// }
ret.setTypeVariable(tv);
typeVariableBindingsInProgress.remove(aTypeVariableBinding);
return ret;
@@ -369,8 +390,30 @@ public class EclipseFactory {
return makeResolvedMember(binding, binding.declaringClass);
}
+ /**
+ * Conversion from a methodbinding (eclipse) to a resolvedmember (aspectj) is now done
+ * in the scope of some type variables. Before converting the parts of a methodbinding
+ * (params, return type) we store the type variables in this structure, then should any
+ * component of the method binding refer to them, we grab them from the map.
+ */
+ // FIXME asc convert to array, indexed by rank
+ private Map typeVariablesForThisMember = new HashMap();
+
public ResolvedMember makeResolvedMember(MethodBinding binding, TypeBinding declaringType) {
//System.err.println("member for: " + binding + ", " + new String(binding.declaringClass.sourceName));
+
+ // Convert the type variables and store them
+ UnresolvedType[] ajTypeRefs = null;
+
+ // This is the set of type variables available whilst building the resolved member...
+ if (binding.typeVariables!=null) {
+ ajTypeRefs = new UnresolvedType[binding.typeVariables.length];
+ for (int i = 0; i < binding.typeVariables.length; i++) {
+ ajTypeRefs[i] = fromBinding(binding.typeVariables[i]);
+ typeVariablesForThisMember.put(new Integer(binding.typeVariables[i].rank),ajTypeRefs[i]);
+ }
+ }
+
// AMC these next two lines shouldn't be needed once we sort out generic types properly in the world map
ResolvedType realDeclaringType = world.resolve(fromBinding(declaringType));
if (realDeclaringType.isRawType()) realDeclaringType = realDeclaringType.getGenericType();
@@ -378,10 +421,14 @@ public class EclipseFactory {
binding.isConstructor() ? Member.CONSTRUCTOR : Member.METHOD,
realDeclaringType,
binding.modifiers,
- world.resolve(fromBinding(binding.returnType)),
+ fromBinding(binding.returnType),
new String(binding.selector),
- world.resolve(fromBindings(binding.parameters)),
- world.resolve(fromBindings(binding.thrownExceptions)));
+ fromBindings(binding.parameters),
+ fromBindings(binding.thrownExceptions)
+ );
+ if (ajTypeRefs!=null) ret.setTypeVariables(ajTypeRefs);
+ typeVariablesForThisMember.clear();
+ ret.resolve(world);
return ret;
}
@@ -407,7 +454,7 @@ public class EclipseFactory {
if (ret == null) {
ret = makeTypeBinding1(typeX);
// FIXME asc keep type variables *out* of the map for now, they go in typeVariableToTypeBinding
- if (!(typeX instanceof TypeVariableReference))
+ if (!(typeX instanceof BoundedReferenceType))
typexToBinding.put(typeX, ret);
}
if (ret == null) {
@@ -457,8 +504,8 @@ public class EclipseFactory {
BoundedReferenceType brt = (BoundedReferenceType)typeX;
// Work out 'kind' for the WildcardBinding
int boundkind = Wildcard.UNBOUND;
- if (brt.isGenericWildcardExtends()) boundkind = Wildcard.EXTENDS;
- if (brt.isGenericWildcardSuper()) boundkind = Wildcard.SUPER;
+ if (brt.isExtends()) boundkind = Wildcard.EXTENDS;
+ if (brt.isSuper()) boundkind = Wildcard.SUPER;
// get the bound right
TypeBinding bound = null;
if (brt.isGenericWildcardExtends()) bound = makeTypeBinding(brt.getUpperBound());
@@ -518,46 +565,48 @@ public class EclipseFactory {
public MethodBinding makeMethodBinding(ResolvedMember member) {
typeVariableToTypeBinding.clear();
- ReferenceBinding declaringType = (ReferenceBinding)makeTypeBinding(member.getDeclaringType());
- MethodBinding mb = new MethodBinding(member.getModifiers(),
- member.getName().toCharArray(),
- makeTypeBinding(member.getReturnType()),
- makeTypeBindings(member.getParameterTypes()),
- makeReferenceBindings(member.getExceptions()),
- declaringType);
+ TypeVariableBinding[] tvbs = null;
+
if (member.getTypeVariables()!=null) {
if (member.getTypeVariables().length==0) {
- mb.typeVariables = MethodBinding.NoTypeVariables;
+ tvbs = MethodBinding.NoTypeVariables;
} else {
- TypeVariableBinding[] tvbs = makeTypeVariableBindings(member.getTypeVariables());
+ tvbs = makeTypeVariableBindings(member.getTypeVariables());
// fixup the declaring element, we couldn't do it whilst processing the typevariables as we'll end up in recursion.
for (int i = 0; i < tvbs.length; i++) {
TypeVariableBinding binding = tvbs[i];
- if (binding.declaringElement==null && ((TypeVariableReference)member.getTypeVariables()[i]).getTypeVariable().getDeclaringElement() instanceof Member) {
- tvbs[i].declaringElement = mb;
- } else {
- tvbs[i].declaringElement = declaringType;
- }
+// if (binding.declaringElement==null && ((TypeVariableReference)member.getTypeVariables()[i]).getTypeVariable().getDeclaringElement() instanceof Member) {
+// tvbs[i].declaringElement = mb;
+// } else {
+// tvbs[i].declaringElement = declaringType;
+// }
}
- mb.typeVariables = tvbs;
}
- }
+ }
+
+ ReferenceBinding declaringType = (ReferenceBinding)makeTypeBinding(member.getDeclaringType());
+ MethodBinding mb = new MethodBinding(member.getModifiers(),
+ member.getName().toCharArray(),
+ makeTypeBinding(member.getReturnType()),
+ makeTypeBindings(member.getParameterTypes()),
+ makeReferenceBindings(member.getExceptions()),
+ declaringType);
+
+ if (tvbs!=null) mb.typeVariables = tvbs;
typeVariableToTypeBinding.clear();
+
return mb;
}
-
+ /**
+ * Convert a bunch of type variables in one go, from AspectJ form to Eclipse form.
+ */
private TypeVariableBinding[] makeTypeVariableBindings(UnresolvedType[] typeVariables) {
int len = typeVariables.length;
TypeVariableBinding[] ret = new TypeVariableBinding[len];
for (int i = 0; i < len; i++) {
- TypeVariableReference tvReference = (TypeVariableReference)typeVariables[i];
- TypeVariableBinding tvb = (TypeVariableBinding)typeVariableToTypeBinding.get(tvReference.getTypeVariable().getName());
- if (tvb==null) {
- tvb = makeTypeVariableBinding(tvReference);
- }
- ret[i] = tvb;
+ ret[i] = makeTypeVariableBinding((TypeVariableReference)typeVariables[i]);
}
return ret;
}
@@ -575,7 +624,7 @@ public class EclipseFactory {
*/
private TypeVariableBinding makeTypeVariableBinding(TypeVariableReference tvReference) {
TypeVariable tVar = tvReference.getTypeVariable();
- TypeVariableBinding tvBinding = (TypeVariableBinding)typeVariableToTypeBinding.get(tVar);
+ TypeVariableBinding tvBinding = (TypeVariableBinding)typeVariableToTypeBinding.get(tVar.getName());
if (tvBinding==null) {
Binding declaringElement = null;
// this will cause an infinite loop or NPE... not required yet luckily.
@@ -585,6 +634,7 @@ public class EclipseFactory {
// declaringElement = makeTypeBinding((UnresolvedType)tVar.getDeclaringElement());
// }
tvBinding = new TypeVariableBinding(tVar.getName().toCharArray(),declaringElement,tVar.getRank());
+ typeVariableToTypeBinding.put(tVar.getName(),tvBinding);
tvBinding.superclass=(ReferenceBinding)makeTypeBinding(tVar.getUpperBound());
tvBinding.firstBound=tvBinding.superclass; // FIXME asc is this correct? possibly it could be first superinterface
if (tVar.getAdditionalInterfaceBounds()==null) {
@@ -596,7 +646,6 @@ public class EclipseFactory {
rbs[i] = (ReferenceBinding)tbs[i];
}
tvBinding.superInterfaces=rbs;
- typeVariableToTypeBinding.put(tVar.getName(),tvBinding);
}
}
return tvBinding;
diff --git a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java
index ab4e34add..f38a45198 100644
--- a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java
+++ b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java
@@ -99,6 +99,29 @@ public class GenericsTests extends XMLBasedAjcTestCase {
* - wait till we get there!
*/
+ /* ==========================================
+ * Generics test plan for ITDs.
+ *
+ * think about:
+ * - source/binary weaving
+ * - visibility default/private/public
+ * - static/nonstatic
+ * - parameterized ITDs (methods/ctors/fields)
+ * - ITD target: interface/class/aspect
+ * - multiple type variables
+ * - generic ITDs (like generic methods)
+ * - constructor ITDs, method ITDs
+ * - ITDs sharing type variables with generic types
+ * - relating to above point, this makes generic ITD fields possible
+ * - signature attributes for generic ITDs (required? required only for public ITDs?)
+ * - binary weaving when target type changes over time (might start out 'simple' then sometime later be 'generic')
+ * - bridge methods - when to create them
+ * - multiple 'separate' ITDs in a file that share a type variable by 'name'
+ * - wildcards '?' 'extends' 'super' '&'
+ * - do type variables assigned to members need to persist across serialization
+ * - recursive type variable definitions eg. <R extends Comparable<? super R>>
+ */
+
public static Test suite() {
return XMLBasedAjcTestCase.loadSuite(GenericsTests.class);
}
@@ -182,12 +205,21 @@ public class GenericsTests extends XMLBasedAjcTestCase {
// non static
- public void testGenericMethodITD1() {runTest("generic method itd - 1");} // <E> ... (List<? extends E>)
- public void testGenericMethodITD2() {runTest("generic method itd - 2");} // <E extends Number> ... (List<? extends E>) called incorrectly
- public void testGenericMethodITD3() {runTest("generic method itd - 3");} // <E> ... (List<E>,List<E>)
- public void testGenericMethodITD4() {runTest("generic method itd - 4");} // <A,B> ... (List<A>,List<B>)
- public void testGenericMethodITD5() {runTest("generic method itd - 5");} // <E> ... (List<E>,List<E>) called incorrectly
- public void testGenericMethodITD6() {runTest("generic method itd - 6");} // <E extends Number> ... (List<? extends E>)
+ public void testGenericMethodITD1() {runTest("generic method itd - 1"); } // <E> ... (List<? extends E>)
+ public void testGenericMethodITD2() {runTest("generic method itd - 2"); } // <E extends Number> ... (List<? extends E>) called incorrectly
+ public void testGenericMethodITD3() {runTest("generic method itd - 3"); } // <E> ... (List<E>,List<E>)
+ public void testGenericMethodITD4() {runTest("generic method itd - 4"); } // <A,B> ... (List<A>,List<B>)
+ public void testGenericMethodITD5() {runTest("generic method itd - 5"); } // <E> ... (List<E>,List<E>) called incorrectly
+ public void testGenericMethodITD6() {runTest("generic method itd - 6"); } // <E extends Number> ... (List<? extends E>)
+ public void testGenericMethodITD7() {runTest("generic method itd - 7"); } // <E> ... (List<E>,List<? extends E>)
+ public void testGenericMethodITD8() {runTest("generic method itd - 8"); } // <E> ... (List<E>,List<? extends E>) called incorrectly
+ public void testGenericMethodITD9() {runTest("generic method itd - 9"); } // <R extends Comparable<? super R>> ... (List<R>)
+ public void testGenericMethodITD10() {runTest("generic method itd - 10");} // <R extends Comparable<? super R>> ... (List<R>) called incorrectly
+ public void testGenericMethodITD11() {runTest("generic method itd - 11");} // <R extends Comparable<? extends R>> ... (List<R>)
+ public void testGenericMethodITD12() {runTest("generic method itd - 12");} // <R extends Comparable<? extends R>> ... (List<R>) called incorrectly
+ public void testGenericMethodITD13() {runTest("generic method itd - 13");} // <R extends Comparable<? extends R>> ... (List<R>) called correctly in a clever way ;)
+ public void testGenericMethodITD14() {runTest("generic method itd - 14");} // <R extends Comparable<? super R>> ... (List<R>) called incorrectly in a clever way
+ public void testGenericMethodITD15() {runTest("generic method itd - 15");} // <R extends Comparable<? super R>> ... (List<R>) called correctly in a clever way
public void testParameterizedMethodITD1() {runTest("parameterized method itd - 1");} // (List<? extends Super>)
@@ -196,8 +228,11 @@ public class GenericsTests extends XMLBasedAjcTestCase {
public void testParameterizedMethodITD4() {runTest("parameterized method itd - 4");} // (List<? super B>)
-// public void testNonStaticGenericCtorITD1() {runTest("generic ctor itd - 1");}
-// public void testGenericITFSharingTypeVariable() {
+ public void testGenericCtorITD1() {runTest("generic ctor itd - 1");} // <T> new(List<T>)
+ public void testGenericCtorITD2() {runTest("generic ctor itd - 2");} // <T> new(List<T>,List<? extends T>)
+ public void testGenericCtorITD3() {runTest("generic ctor itd - 3");} // <T> new(List<T>,Comparator<? super T>)
+
+ // public void testGenericITFSharingTypeVariable() {
// runTest("generic intertype field declaration, sharing type variable");
// }
diff --git a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml
index 0d7143caa..d3e7cfd85 100644
--- a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml
+++ b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml
@@ -2386,9 +2386,19 @@
</run>
</ajc-test>
- <ajc-test dir="java5/generics/itds" title="non static generic ctor itd - 1">
- <compile files="NonstaticGenericCtorITD1.aj" options="-1.5"/>
- <run class="NonstaticGenericCtorITD1"/>
+ <ajc-test dir="java5/generics/itds" title="generic ctor itd - 1">
+ <compile files="GenericCtorITD1.aj" options="-1.5"/>
+ <run class="GenericCtorITD1"/>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic ctor itd - 2">
+ <compile files="GenericCtorITD2.aj" options="-1.5"/>
+ <run class="GenericCtorITD2"/>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic ctor itd - 3">
+ <compile files="GenericCtorITD3.aj" options="-1.5"/>
+ <run class="GenericCtorITD3"/>
</ajc-test>
<ajc-test dir="java5/generics/itds" title="parameterized method itd - 1">
@@ -2447,6 +2457,55 @@
<run class="GenericMethodITD6"/>
</ajc-test>
+ <ajc-test dir="java5/generics/itds" title="generic method itd - 7">
+ <compile files="GenericMethodITD7.aj" options="-1.5"/>
+ <run class="GenericMethodITD7"/>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic method itd - 8">
+ <compile files="GenericMethodITD8.aj" options="-1.5">
+ <message kind="error" line="10" text="The method simple(List&lt;E&gt;, List&lt;? extends E&gt;) in the type X is not applicable for the arguments (List&lt;Number&gt;, List&lt;String&gt;)"/>
+ </compile>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic method itd - 9">
+ <compile files="GenericMethodITD9.aj" options="-1.5"/>
+ <run class="GenericMethodITD9"/>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic method itd - 10">
+ <compile files="GenericMethodITD10.aj" options="-1.5">
+ <message kind="error" line="10" text="Bound mismatch: The generic method crazy(List&lt;R&gt;) of type X is not applicable for the arguments (List&lt;A&gt;) since the type A is not a valid substitute for the bounded parameter &lt;R extends Object &amp; Comparable&lt;? super R&gt;&gt;"/>
+ </compile>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic method itd - 11">
+ <compile files="GenericMethodITD11.aj" options="-1.5"/>
+ <run class="GenericMethodITD11"/>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic method itd - 12">
+ <compile files="GenericMethodITD12.aj" options="-1.5">
+ <message kind="error" line="10" text="Bound mismatch: The generic method crazy(List&lt;R&gt;) of type X is not applicable for the arguments (List&lt;A&gt;) since the type A is not a valid substitute for the bounded parameter &lt;R extends Object &amp; Foo&lt;? extends R&gt;&gt;"/>
+ </compile>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic method itd - 13">
+ <compile files="GenericMethodITD13.aj" options="-1.5"/>
+ <run class="GenericMethodITD13"/>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic method itd - 14">
+ <compile files="GenericMethodITD14.aj" options="-1.5">
+ <message kind="error" line="10" text="Bound mismatch: The generic method crazy(List&lt;R&gt;) of type X is not applicable for the arguments (List&lt;A&gt;) since the type A is not a valid substitute for the bounded parameter &lt;R extends Object &amp; Foo&lt;? super R&gt;&gt;"/>
+ </compile>
+ </ajc-test>
+
+ <ajc-test dir="java5/generics/itds" title="generic method itd - 15">
+ <compile files="GenericMethodITD15.aj" options="-1.5"/>
+ <run class="GenericMethodITD15"/>
+ </ajc-test>
+
<ajc-test dir="java5/generics/itds" title="non static generic method itd - 2">
<compile files="NonstaticGenericCtorITD2.aj" options="-1.5"/>
<run class="NonstaticGenericCtorITD2"/>
diff --git a/weaver/src/org/aspectj/weaver/BoundedReferenceType.java b/weaver/src/org/aspectj/weaver/BoundedReferenceType.java
index dfb8efc30..48ec7f927 100644
--- a/weaver/src/org/aspectj/weaver/BoundedReferenceType.java
+++ b/weaver/src/org/aspectj/weaver/BoundedReferenceType.java
@@ -19,17 +19,23 @@ import org.aspectj.weaver.patterns.PerClause;
/**
* A BoundedReferenceType is the result of a generics wildcard expression
* ? extends String, ? super Foo etc..
+ *
* The "signature" for a bounded reference type follows the generic signature
- * specification in section 4.4 of JVM spec: *,+,- plus signature strings
+ * specification in section 4.4 of JVM spec: *,+,- plus signature strings.
+ *
+ * The bound may be a type variable (e.g. ? super T)
*/
public class BoundedReferenceType extends ReferenceType {
+
protected ReferenceType[] additionalInterfaceBounds = new ReferenceType[0];
+
protected boolean isExtends = true;
- protected boolean isSuper = false;
+ protected boolean isSuper = false;
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world) {
super((isExtends ? "+" : "-") + aBound.signature,world);
- this.isExtends = isExtends; this.isSuper=!isExtends;
+ this.isExtends = isExtends;
+ this.isSuper = !isExtends;
if (isExtends) {
setUpperBound(aBound);
} else {
@@ -38,7 +44,7 @@ public class BoundedReferenceType extends ReferenceType {
}
setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)getUpperBound()));
}
-
+
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world, ReferenceType[] additionalInterfaces) {
this(aBound,isExtends,world);
this.additionalInterfaceBounds = additionalInterfaces;
@@ -51,20 +57,22 @@ public class BoundedReferenceType extends ReferenceType {
/**
* only for use when resolving GenericsWildcardTypeX or a TypeVariableReferenceType
*/
- BoundedReferenceType(String sig, World world) {
+ protected BoundedReferenceType(String sig, World world) {
super(sig,world);
setUpperBound(world.resolve(UnresolvedType.OBJECT));
setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)getUpperBound()));
}
- public ReferenceType[] getInterfaceBounds() { return additionalInterfaceBounds; }
+ public ReferenceType[] getInterfaceBounds() {
+ return additionalInterfaceBounds;
+ }
public boolean hasLowerBound() {
return getLowerBound() != null;
}
public boolean isExtends() { return isExtends; }
- public boolean isSuper() { return isSuper; }
+ public boolean isSuper() { return isSuper; }
// override to include additional interface bounds...
public ResolvedType[] getDeclaredInterfaces() {
diff --git a/weaver/src/org/aspectj/weaver/JoinPointSignature.java b/weaver/src/org/aspectj/weaver/JoinPointSignature.java
index 12f66fca1..9fefcdf23 100644
--- a/weaver/src/org/aspectj/weaver/JoinPointSignature.java
+++ b/weaver/src/org/aspectj/weaver/JoinPointSignature.java
@@ -17,6 +17,7 @@ import java.util.Collection;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute;
+import org.aspectj.weaver.Member.Kind;
/**
* @author colyer
@@ -351,4 +352,20 @@ public class JoinPointSignature implements ResolvedMember {
return buf.toString();
}
+ public void resetName(String newName) {
+ realMember.resetName(newName);
+ }
+
+ public void resetKind(Kind newKind) {
+ realMember.resetKind(newKind);
+ }
+
+ public void resetModifiers(int newModifiers) {
+ realMember.resetModifiers(newModifiers);
+ }
+
+ public void resetReturnTypeToObjectArray() {
+ realMember.resetReturnTypeToObjectArray();
+ }
+
}
diff --git a/weaver/src/org/aspectj/weaver/MemberImpl.java b/weaver/src/org/aspectj/weaver/MemberImpl.java
index cf2a16548..96a4478b2 100644
--- a/weaver/src/org/aspectj/weaver/MemberImpl.java
+++ b/weaver/src/org/aspectj/weaver/MemberImpl.java
@@ -21,14 +21,14 @@ import java.util.Iterator;
import java.util.List;
-public class MemberImpl implements Comparable, AnnotatedElement, Member {
+public class MemberImpl implements Comparable, AnnotatedElement,Member {
- private final Kind kind;
+ protected Kind kind;
protected UnresolvedType declaringType;
- protected final int modifiers; // protected because ResolvedMember uses it
- private final UnresolvedType returnType;
- private final String name;
- private final UnresolvedType[] parameterTypes;
+ protected int modifiers;
+ protected UnresolvedType returnType;
+ protected String name;
+ protected UnresolvedType[] parameterTypes;
private final String signature;
private final String declaredSignature; // TODO asc Is this redundant? Is it needed for generics?
private String paramSignature;
diff --git a/weaver/src/org/aspectj/weaver/ResolvedMember.java b/weaver/src/org/aspectj/weaver/ResolvedMember.java
index 6fd6c0a7c..17b1e2930 100644
--- a/weaver/src/org/aspectj/weaver/ResolvedMember.java
+++ b/weaver/src/org/aspectj/weaver/ResolvedMember.java
@@ -17,6 +17,7 @@ import java.io.DataOutputStream;
import java.io.IOException;
import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.Member.Kind;
public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDeclaringElement {
@@ -135,5 +136,9 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe
* variable to match any other type variable regardless of bounds.
*/
public boolean matches(ResolvedMember aCandidateMatch);
-
+
+ public void resetName(String newName);
+ public void resetKind(Kind newKind);
+ public void resetModifiers(int newModifiers);
+ public void resetReturnTypeToObjectArray();
} \ No newline at end of file
diff --git a/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java b/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java
index de94d3c55..1acebd584 100644
--- a/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java
+++ b/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java
@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Set;
import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.Member.Kind;
/**
* This is the declared member, i.e. it will always correspond to an
@@ -266,7 +267,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno
}
public boolean hasAnnotation(UnresolvedType ofType) {
- // The ctors don't allow annotations to be specified ... yet - but
+ // The ctors don't allow annotations to be specified ... yet - but
// that doesn't mean it is an error to call this method.
// Normally the weaver will be working with subtypes of
// this type - BcelField/BcelMethod
@@ -372,7 +373,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno
public ResolvedMember resolve(World world) {
- // FIXME asc guard with a check on resolution having happened !
+ // make sure all the pieces of a resolvedmember really are resolved
if (annotationTypes!=null) {
Set r = new HashSet();
for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) {
@@ -383,7 +384,20 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno
}
declaringType = declaringType.resolve(world);
if (declaringType.isRawType()) declaringType = ((ReferenceType)declaringType).getGenericType();
- return this;
+ if (typeVariables!=null && typeVariables.length>0) {
+ for (int i = 0; i < typeVariables.length; i++) {
+ UnresolvedType array_element = typeVariables[i];
+ typeVariables[i] = typeVariables[i].resolve(world);
+ }
+ }
+ if (parameterTypes!=null && parameterTypes.length>0) {
+ for (int i = 0; i < parameterTypes.length; i++) {
+ UnresolvedType array_element = parameterTypes[i];
+ parameterTypes[i] = parameterTypes[i].resolve(world);
+ }
+ }
+
+ returnType = returnType.resolve(world);return this;
}
public ISourceContext getSourceContext(World world) {
@@ -587,7 +601,20 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno
private ResolvedMember myErasure = null;
private boolean calculatedMyErasure = false;
-
+
+
+ /**
+ * For ITDs, we use the default factory methods to build a resolved member, then alter a couple of characteristics
+ * using this method - this is safe.
+ */
+ public void resetName(String newName) {this.name = newName;}
+ public void resetKind(Kind newKind) {this.kind=newKind; }
+ public void resetModifiers(int newModifiers) {this.modifiers=newModifiers;}
+
+ public void resetReturnTypeToObjectArray() {
+ returnType = UnresolvedType.OBJECTARRAY;
+ }
+
/**
* Returns a copy of this member but with the declaring type swapped.
* Copy only needs to be shallow.
diff --git a/weaver/src/org/aspectj/weaver/TypeFactory.java b/weaver/src/org/aspectj/weaver/TypeFactory.java
index e81d63238..465747b4d 100644
--- a/weaver/src/org/aspectj/weaver/TypeFactory.java
+++ b/weaver/src/org/aspectj/weaver/TypeFactory.java
@@ -38,7 +38,7 @@ public class TypeFactory {
ResolvedType baseType = aBaseType;
if (!aBaseType.isGenericType()) {
// try and find the generic type...
- if (someTypeParameters != null) {
+ if (someTypeParameters != null && someTypeParameters.length>0) {
if (!aBaseType.isRawType()) throw new IllegalStateException("Expecting raw type");
baseType = baseType.getGenericType();
if (baseType == null) throw new IllegalStateException("Raw type does not have generic type set");
@@ -50,6 +50,13 @@ public class TypeFactory {
return (ReferenceType) pType.resolve(inAWorld);
}
+ /**
+ * Create an *unresolved* parameterized version of a generic type.
+ */
+ public static UnresolvedType createUnresolvedParameterizedType(String sig,String erasuresig,UnresolvedType[] arguments) {
+ return new UnresolvedType(sig,erasuresig,arguments);
+ }
+
public static ReferenceType createRawType(
ResolvedType aBaseType,
World inAWorld
diff --git a/weaver/src/org/aspectj/weaver/TypeVariable.java b/weaver/src/org/aspectj/weaver/TypeVariable.java
index 66f9a2a0f..35623d7bd 100644
--- a/weaver/src/org/aspectj/weaver/TypeVariable.java
+++ b/weaver/src/org/aspectj/weaver/TypeVariable.java
@@ -25,6 +25,9 @@ public class TypeVariable {
*/
private boolean isResolved = false;
+
+ private boolean beingResolved = false;
+
/**
* the name of the type variable as recorded in the generic signature
*/
@@ -93,6 +96,8 @@ public class TypeVariable {
* resolve all the bounds of this type variable
*/
public void resolve(World inSomeWorld) {
+ if (beingResolved) { return; } // avoid spiral of death
+ beingResolved = true;
if (isResolved) return;
upperBound = upperBound.resolve(inSomeWorld);
@@ -103,6 +108,7 @@ public class TypeVariable {
}
isResolved = true;
+ beingResolved = false;
}
/**
diff --git a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java
index c77e36cd7..9c47db1aa 100644
--- a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java
+++ b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java
@@ -23,18 +23,29 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T
World aWorld) {
super(aTypeVariable.getUpperBound().getSignature(),aWorld);
this.typeVariable = aTypeVariable;
- this.isExtends = false;
- this.isSuper = false;
- setUpperBound(aTypeVariable.getUpperBound());
- setLowerBound(aTypeVariable.getLowerBound());
- UnresolvedType[] ifBounds = aTypeVariable.getAdditionalInterfaceBounds();
- if (ifBounds.length > 0) {
- this.additionalInterfaceBounds = new ReferenceType[ifBounds.length];
+ this.isExtends = false;
+ this.isSuper = false;
+ setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)aTypeVariable.getUpperBound()));
+ }
+
+ public UnresolvedType getUpperBound() {
+ if (typeVariable==null) return super.getUpperBound();
+ return typeVariable.getUpperBound();
+ }
+
+ public UnresolvedType getLowerBound() {
+ return typeVariable.getLowerBound();
+ }
+
+ public ReferenceType[] getAdditionalBounds() {
+ if (additionalInterfaceBounds ==null && typeVariable.getAdditionalInterfaceBounds()!=null) {
+ UnresolvedType [] ifBounds = typeVariable.getAdditionalInterfaceBounds();
+ additionalInterfaceBounds = new ReferenceType[ifBounds.length];
for (int i = 0; i < ifBounds.length; i++) {
- this.additionalInterfaceBounds[i] = (ReferenceType) ifBounds[i];
+ additionalInterfaceBounds[i] = (ReferenceType) ifBounds[i];
}
}
- setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)aTypeVariable.getUpperBound()));
+ return additionalInterfaceBounds;
}
public TypeVariable getTypeVariable() {
@@ -45,6 +56,10 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T
return true;
}
+// public ResolvedType resolve(World world) {
+ // return super.resolve(world);
+ //}
+
/**
* return the signature for a *REFERENCE* to a type variable, which is simply:
* Tname;
diff --git a/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java b/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java
index 667c10c43..cf8494ea4 100644
--- a/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java
+++ b/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java
@@ -37,7 +37,9 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen
}
public ResolvedType resolve(World world) {
- if (typeVariable == null) return ResolvedType.MISSING;
+ if (typeVariable == null) {
+ throw new BCException("Cannot resolve this type variable reference, the type variable has not been set!");
+ }
typeVariable.resolve(world);
return new TypeVariableReferenceType(typeVariable,world);
}
diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java
index 13c0e4889..053a3c10d 100644
--- a/weaver/src/org/aspectj/weaver/World.java
+++ b/weaver/src/org/aspectj/weaver/World.java
@@ -249,7 +249,7 @@ public abstract class World implements Dump.INode {
/**
* Resolve to a ReferenceType - simple, raw, parameterized, or generic.
- * Raw, parmeterized, and generic versions of a type share a delegate.
+ * Raw, parameterized, and generic versions of a type share a delegate.
*/
private final ResolvedType resolveToReferenceType(UnresolvedType ty) {
if (ty.isParameterizedType()) {
@@ -309,6 +309,17 @@ public abstract class World implements Dump.INode {
// raw type from a source type, it won't if its been created just through
// being referenced, e.g. java.util.List
ResolvedType genericType = rawType.getGenericType();
+
+ // There is a special case to consider here (testGenericsBang_pr95993 highlights it)
+ // You may have an unresolvedType for a parameterized type but it
+ // is backed by a simple type rather than a generic type. This occurs for
+ // inner types of generic types that inherit their enclosing types
+ // type variables.
+ if (rawType.isSimpleType() && anUnresolvedType.typeParameters.length==0) {
+ rawType.world = this;
+ return rawType;
+ }
+
if (genericType != null) {
genericType.world = this;
return genericType;
@@ -324,18 +335,23 @@ public abstract class World implements Dump.INode {
}
}
- // we have a generic wildcard with either extends or super, resolves to a
- // BoundedReferenceType
+ /**
+ * Go from an unresolved generic wildcard (represented by UnresolvedType) to a resolved version (BoundedReferenceType).
+ */
private ReferenceType resolveGenericWildcardFor(UnresolvedType aType) {
BoundedReferenceType ret = null;
+ // FIXME asc isExtends? isGenericWildcardExtends? I dont like having two
+ // FIXME asc doesnt take account of additional interface bounds (e.g. ? super R & Serializable - can you do that?)
if (aType.isGenericWildcardExtends()) {
- ReferenceType upperBound = (ReferenceType) resolve(aType.getUpperBound());
+ ReferenceType upperBound = (ReferenceType)resolve(aType.getUpperBound());
ret = new BoundedReferenceType(upperBound,true,this);
- } else {
+ } else {
ReferenceType lowerBound = (ReferenceType) resolve(aType.getLowerBound());
ret = new BoundedReferenceType(lowerBound,false,this);
}
- typeMap.put(aType.getSignature(),ret);
+ // FIXME asc verify: I don't think these go in the typemap, it makes it potentially impossible to differentiate different uses of 'T',
+ // for example '? super T' where T is representing different things in two places would have the same sig (-TT;)
+ // typeMap.put(aType.getSignature(),ret);
return ret;
}