aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java25
-rw-r--r--tests/java5/generics/itds/MethodITDOnGeneric.aj5
-rw-r--r--tests/java5/generics/itds/ParameterizedMethodITD5.aj18
-rw-r--r--tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java110
-rw-r--r--tests/src/org/aspectj/systemtest/ajc150/ajc150.xml10
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedType.java67
-rw-r--r--weaver/src/org/aspectj/weaver/TypeVariable.java21
-rw-r--r--weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java2
-rw-r--r--weaver/src/org/aspectj/weaver/UnresolvedType.java42
-rw-r--r--weaver/src/org/aspectj/weaver/World.java47
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java4
-rw-r--r--weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java6
12 files changed, 271 insertions, 86 deletions
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 85810decc..5c803b132 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
@@ -206,8 +206,8 @@ public class EclipseFactory {
// case let's set it correctly based on the one in the eclipse WildcardBinding
if (eWB.bound instanceof TypeVariableBinding) {
UnresolvedType tVar = fromTypeVariableBinding((TypeVariableBinding)eWB.bound);
- if (ut.isGenericWildcardSuper()) ut.setLowerBound(tVar);
- if (ut.isGenericWildcardExtends()) ut.setUpperBound(tVar);
+ if (ut.isGenericWildcard() && ut.isSuper()) ut.setLowerBound(tVar);
+ if (ut.isGenericWildcard() && ut.isExtends()) ut.setUpperBound(tVar);
}
return ut;
}
@@ -297,12 +297,13 @@ public class EclipseFactory {
tv.setUpperBound(superclassType);
tv.setAdditionalInterfaceBounds(superinterfaces);
tv.setRank(aTypeVariableBinding.rank);
-// dont need the declaring element yet...
-// if (aTypeVariableBinding.declaringElement instanceof MethodBinding) {
+ if (aTypeVariableBinding.declaringElement instanceof MethodBinding) {
+ tv.setDeclaringElementKind(TypeVariable.METHOD);
// tv.setDeclaringElement(fromBinding((MethodBinding)aTypeVariableBinding.declaringElement);
-// } else {
+ } else {
+ tv.setDeclaringElementKind(TypeVariable.TYPE);
// // tv.setDeclaringElement(fromBinding(aTypeVariableBinding.declaringElement));
-// }
+ }
ret.setTypeVariable(tv);
typeVariableBindingsInProgress.remove(aTypeVariableBinding);
return ret;
@@ -504,12 +505,14 @@ public class EclipseFactory {
BoundedReferenceType brt = (BoundedReferenceType)typeX;
// Work out 'kind' for the WildcardBinding
int boundkind = Wildcard.UNBOUND;
- 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());
- if (brt.isGenericWildcardSuper()) bound = makeTypeBinding(brt.getLowerBound());
+ if (brt.isExtends()) {
+ boundkind = Wildcard.EXTENDS;
+ bound = makeTypeBinding(brt.getUpperBound());
+ } else if (brt.isSuper()) {
+ boundkind = Wildcard.SUPER;
+ bound = makeTypeBinding(brt.getLowerBound());
+ }
TypeBinding[] otherBounds = null;
if (brt.getAdditionalBounds()!=null && brt.getAdditionalBounds().length!=0) otherBounds = makeTypeBindings(brt.getAdditionalBounds());
// FIXME asc rank should not always be 0 ...
diff --git a/tests/java5/generics/itds/MethodITDOnGeneric.aj b/tests/java5/generics/itds/MethodITDOnGeneric.aj
deleted file mode 100644
index ce024337d..000000000
--- a/tests/java5/generics/itds/MethodITDOnGeneric.aj
+++ /dev/null
@@ -1,5 +0,0 @@
-class C<A,B> { public B getB(A a) { return null; } }
-
-aspect X {
- public List<C> C<D,C>.getBs(D ds) { return null; }
-}
diff --git a/tests/java5/generics/itds/ParameterizedMethodITD5.aj b/tests/java5/generics/itds/ParameterizedMethodITD5.aj
new file mode 100644
index 000000000..d41667d23
--- /dev/null
+++ b/tests/java5/generics/itds/ParameterizedMethodITD5.aj
@@ -0,0 +1,18 @@
+class C<A,B> { public B getB(A a) { return null; } }
+
+aspect X {
+ public List<C> C<D,C>.getBs(D ds) { return null; }
+}
+
+public class ParameterizedMethodITD5 {
+
+ public static void main(String[]argv) {
+ C instance = new C<Integer,String>();
+
+ Integer i = instance.getB("hello");
+
+ List<String> ls = instance.getBs(3);
+
+ }
+
+}
diff --git a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java
index 53a7d5f36..593a66679 100644
--- a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java
+++ b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java
@@ -114,7 +114,6 @@ public class GenericsTests extends XMLBasedAjcTestCase {
* - 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
@@ -126,8 +125,32 @@ public class GenericsTests extends XMLBasedAjcTestCase {
* - do type variables assigned to members need to persist across serialization
* - recursive type variable definitions eg. <R extends Comparable<? super R>>
* - super/extends with parameterized types <? extends List<String>>
- * - source/binary weaving
* - multiple ITDs defined in one type that reuse type variable letters, specifying different bounds
+ * - generic aspects
+ *
+ * PASS parsing generic ITDs
+ * PASS generic methods
+ * PASS generic constructors
+ * PASS ITD visibility
+ * PASS static/nonstatic
+ * PASS parameterizedITDs
+ * PASS differing targets (interface/class/aspect)
+ * PASS multiple type variables in an ITD
+ * TODO using type variables from the target type in your ITD (no type vars of your own)
+ * TODO parsing ITDs that share type variables with target type
+ * TODO sharing type variables (methods)
+ * TODO sharing type variables (fields)
+ * TODO sharing type variables (constructors)
+ * TODO sharing type variables and having your own type variables (methods/constructors)
+ * TODO signature attributes for generic ITDs (public only?)
+ * TODO binary weaving with changing types (moving between generic and simple)
+ * TODO bridge method creation
+ * TODO reusing type variable letter but differing spec across multiple ITDs in one aspect
+ * PASS wildcards
+ * TODO exotic class/interface bounds ('? extends List<String>')
+ * PASS recursive type variable definitions
+ * TODO generic aspects
+ * TODO parameterizing ITDs with type variables
*/
public static Test suite() {
@@ -171,44 +194,33 @@ public class GenericsTests extends XMLBasedAjcTestCase {
}
// generic aspects
- public void testPR96220_GenericAspects1() {
- runTest("generic aspects - 1");
- }
-
- public void testPR96220_GenericAspects2() {
- runTest("generic aspects - 2");
- }
+ public void testPR96220_GenericAspects1() {runTest("generic aspects - 1");}
+ public void testPR96220_GenericAspects2() {runTest("generic aspects - 2");}
+ public void testPR96220_GenericAspects3() {runTest("generic aspects - 3");}
+// public void testGenericAspects4() {runTest("generic aspects - 4");}
+// public void testGenericAspects5() {runTest("generic aspects - 5 (ajdk)");}
- public void testPR96220_GenericAspects3() {
- runTest("generic aspects - 3");
- }
+ //////////////////////////////////////////////////////////////////////////////
+ // Generic/Parameterized ITDs - includes scenarios from developers notebook //
+ //////////////////////////////////////////////////////////////////////////////
- // Developers notebook
// parsing of generic ITD members
-
public void testParseItdNonStaticMethod() {runTest("Parsing generic ITDs - 1");}
public void testParseItdStaticMethod() {runTest("Parsing generic ITDs - 2");}
public void testParseItdCtor() {runTest("Parsing generic ITDs - 3");}
public void testParseItdComplexMethod() {runTest("Parsing generic ITDs - 4");}
// public void testParseItdSharingVars1() {runTest("Parsing generic ITDs - 5");}
// public void testParseItdSharingVars2() {runTest("Parsing generic ITDs - 6");}
-
- public void testItdNonStaticMember() {runTest("itd of non static member");}
- public void testItdStaticMember() {runTest("itd of static member");}
-
- public void testStaticGenericMethodITD() {
- runTest("static generic method itd");
- }
+
// 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>)
@@ -220,30 +232,48 @@ public class GenericsTests extends XMLBasedAjcTestCase {
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>)
- public void testParameterizedMethodITD2() {runTest("parameterized method itd - 2");} // (List<? extends Number>) called incorrectly
- public void testParameterizedMethodITD3() {runTest("parameterized method itd - 3");} // (List<? super A>) called incorrectly
- public void testParameterizedMethodITD4() {runTest("parameterized method itd - 4");} // (List<? super B>)
-
+ // generic ctors
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 testMultipleGenericITDsInOneFile() { runTest("multiple generic itds in one file");}
+ // parameterized ITDs
+ public void testParameterizedMethodITD1() {runTest("parameterized method itd - 1");} // (List<? extends Super>)
+ public void testParameterizedMethodITD2() {runTest("parameterized method itd - 2");} // (List<? extends Number>) called incorrectly
+ public void testParameterizedMethodITD3() {runTest("parameterized method itd - 3");} // (List<? super A>) called incorrectly
+ public void testParameterizedMethodITD4() {runTest("parameterized method itd - 4");} // (List<? super B>)
+
- // ITDs of differing visibilities
+ // differing visibilities
public void testPublicITDs() {runTest("public itds");}
public void testPublicITDsErrors() {runTest("public itds with errors");}
public void testPrivateITDs() {runTest("private itds");}
public void testPackageITDs() {runTest("package itds");}
- // ITDs that share a type variable with the target generic type
- public void testMethodITDsSharingTvar() {runTest("method itd sharing type variable with generic type");}
- public void testFieldITDsSharingTvar() {runTest("field itd sharing type variable with generic type");}
-*/
+
+ // targetting different types (interface/class/aspect)
+ public void testTargettingInterface() {runTest("targetting interface");}
+ public void testTargettingAspect() {runTest("targetting aspect");}
+ public void testTargettingClass() {runTest("targetting class");}
+
+
+
+ // sharing a type variable between the ITD and the target generic type
+// public void testMethodITDsSharingTvar() {runTest("method itd sharing type variable with generic type");}
+// public void testFieldITDsSharingTvar() {runTest("field itd sharing type variable with generic type");}
+
+
+ // general tests ... usually just more complex scenarios
+ public void testReusingTypeVariableLetters() {runTest("reusing type variable letters");}
+ public void testMultipleGenericITDsInOneFile() {runTest("multiple generic itds in one file");}
+ public void testItdNonStaticMember() {runTest("itd of non static member");}
+ public void testItdStaticMember() {runTest("itd of static member");}
+ public void testStaticGenericMethodITD() {runTest("static generic method itd");}
+
+
+
// 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 08f164614..958df1395 100644
--- a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml
+++ b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml
@@ -2327,6 +2327,16 @@
</run>
</ajc-test>
+ <ajc-test dir="java5/generics/genericaspects" title="generic aspects - 4">
+ <compile files="ParentChildRelationship.aj" options="-1.5"/>
+ </ajc-test>
+
+ <!-- ajdk example -->
+ <ajc-test dir="java5/generics/genericaspects" title="generic aspects - 5 (ajdk)">
+ <compile files="Blob.java,BlobContainment.aj,ParentChildRelationship.aj" options="-1.5"/>
+ <run class="BlobContainment"/>
+ </ajc-test>
+
<!-- end of generic aspects -->
<!-- generic ITDs -->
diff --git a/weaver/src/org/aspectj/weaver/ResolvedType.java b/weaver/src/org/aspectj/weaver/ResolvedType.java
index a8b942c94..185c1d9fe 100644
--- a/weaver/src/org/aspectj/weaver/ResolvedType.java
+++ b/weaver/src/org/aspectj/weaver/ResolvedType.java
@@ -18,7 +18,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -29,6 +28,7 @@ import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.bridge.Message;
import org.aspectj.bridge.MessageUtil;
+import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.patterns.Declare;
import org.aspectj.weaver.patterns.PerClause;
@@ -1609,6 +1609,69 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl
public String getSignatureForAttribute() {
throw new RuntimeException("Cannot ask this type "+this+" for a generic sig attribute");
}
-
+
+ private FuzzyBoolean parameterizedWithAMemberTypeVariable = FuzzyBoolean.MAYBE;
+
+ /**
+ * return true if the parameterization of this type includes a member type variable. Member
+ * type variables occur in generic methods/ctors.
+ */
+ public boolean isParameterizedWithAMemberTypeVariable() {
+ // MAYBE means we haven't worked it out yet...
+ if (parameterizedWithAMemberTypeVariable==FuzzyBoolean.MAYBE) {
+
+ // if there are no type parameters then we cant be...
+ if (typeParameters==null || typeParameters.length==0) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.NO;
+ return false;
+ }
+
+ for (int i = 0; i < typeParameters.length; i++) {
+ UnresolvedType aType = (ResolvedType)typeParameters[i];
+ if (aType.isTypeVariableReference() && ((TypeVariableReference)aType).getTypeVariable().getDeclaringElementKind()==TypeVariable.METHOD) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
+ return true;
+ }
+ if (aType.isParameterizedType()) {
+ boolean b = aType.isParameterizedWithAMemberTypeVariable();
+ if (b) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
+ return true;
+ }
+ }
+ if (aType.isGenericWildcard()) {
+ if (aType.isExtends()) {
+ boolean b = false;
+ UnresolvedType upperBound = aType.getUpperBound();
+ if (upperBound.isParameterizedType()) {
+ b = upperBound.isParameterizedWithAMemberTypeVariable();
+ } else if (upperBound.isTypeVariableReference() && ((TypeVariableReference)upperBound).getTypeVariable().getDeclaringElementKind()==TypeVariable.METHOD) {
+ b = true;
+ }
+ if (b) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
+ return true;
+ }
+ // FIXME asc need to check additional interface bounds
+ }
+ if (aType.isSuper()) {
+ boolean b = false;
+ UnresolvedType lowerBound = aType.getLowerBound();
+ if (lowerBound.isParameterizedType()) {
+ b = lowerBound.isParameterizedWithAMemberTypeVariable();
+ } else if (lowerBound.isTypeVariableReference() && ((TypeVariableReference)lowerBound).getTypeVariable().getDeclaringElementKind()==TypeVariable.METHOD) {
+ b = true;
+ }
+ if (b) {
+ parameterizedWithAMemberTypeVariable = FuzzyBoolean.YES;
+ return true;
+ }
+ }
+ }
+ }
+ parameterizedWithAMemberTypeVariable=FuzzyBoolean.NO;
+ }
+ return parameterizedWithAMemberTypeVariable.alwaysTrue();
+ }
}
diff --git a/weaver/src/org/aspectj/weaver/TypeVariable.java b/weaver/src/org/aspectj/weaver/TypeVariable.java
index 35623d7bd..f450d8b76 100644
--- a/weaver/src/org/aspectj/weaver/TypeVariable.java
+++ b/weaver/src/org/aspectj/weaver/TypeVariable.java
@@ -34,7 +34,17 @@ public class TypeVariable {
private String name;
private int rank;
-
+
+ // It would be nice to push this field onto the TypeVariableDeclaringElement
+ // interface (a getKind()) but at the moment we don't always guarantee
+ // to set the declaring element (eclipse seems to utilise the knowledge of
+ // what declared the type variable, but we dont yet...)
+ /**
+ * What kind of element declared this type variable?
+ */
+ private int declaringElementKind = TYPE;
+ public static final int METHOD = 1;
+ public static final int TYPE = 2;
private TypeVariableDeclaringElement declaringElement;
/**
@@ -254,4 +264,13 @@ public class TypeVariable {
return declaringElement;
}
+ public void setDeclaringElementKind(int kind) {
+ this.declaringElementKind = kind;
+ }
+
+ public int getDeclaringElementKind() {
+// if (declaringElementKind==UNKNOWN) throw new RuntimeException("Dont know declarer of this tvar : "+this);
+ return declaringElementKind;
+ }
+
}
diff --git a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java
index 9c47db1aa..17941318a 100644
--- a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java
+++ b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java
@@ -56,7 +56,7 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T
return true;
}
-// public ResolvedType resolve(World world) {
+ //public ResolvedType resolve(World world) {
// return super.resolve(world);
//}
diff --git a/weaver/src/org/aspectj/weaver/UnresolvedType.java b/weaver/src/org/aspectj/weaver/UnresolvedType.java
index 320d93e5c..5efa8c423 100644
--- a/weaver/src/org/aspectj/weaver/UnresolvedType.java
+++ b/weaver/src/org/aspectj/weaver/UnresolvedType.java
@@ -156,6 +156,12 @@ public class UnresolvedType implements TypeVariableDeclaringElement {
*/
private UnresolvedType lowerBound;
+ /**
+ * for wildcards '? extends' or for type variables 'T extends'
+ */
+ private boolean isSuper = false;
+ private boolean isExtends = false;
+
/**
* Determines if this represents a primitive type. A primitive type
* is one of nine predefined resolved types.
@@ -172,16 +178,16 @@ public class UnresolvedType implements TypeVariableDeclaringElement {
* @see ResolvedType#Double
* @see ResolvedType#Void
*/
- public boolean isPrimitiveType() { return typeKind == TypeKind.PRIMITIVE; }
- public boolean isSimpleType() { return typeKind == TypeKind.SIMPLE; }
- public boolean isRawType() { return typeKind == TypeKind.RAW; }
- public boolean isGenericType() { return typeKind == TypeKind.GENERIC; }
- public boolean isParameterizedType() { return typeKind == TypeKind.PARAMETERIZED; }
- public boolean isTypeVariableReference() { return typeKind == TypeKind.TYPE_VARIABLE; }
- public boolean isGenericWildcard() { return typeKind == TypeKind.WILDCARD; }
- public boolean isGenericWildcardExtends() { return isGenericWildcard() && upperBound != null; }
- public boolean isGenericWildcardSuper() { return isGenericWildcard() && lowerBound != null; }
-
+ public boolean isPrimitiveType() { return typeKind == TypeKind.PRIMITIVE; }
+ public boolean isSimpleType() { return typeKind == TypeKind.SIMPLE; }
+ public boolean isRawType() { return typeKind == TypeKind.RAW; }
+ public boolean isGenericType() { return typeKind == TypeKind.GENERIC; }
+ public boolean isParameterizedType() { return typeKind == TypeKind.PARAMETERIZED; }
+ public boolean isTypeVariableReference() { return typeKind == TypeKind.TYPE_VARIABLE; }
+ public boolean isGenericWildcard() { return typeKind == TypeKind.WILDCARD; }
+ public boolean isExtends() { return isExtends;}
+ public boolean isSuper() { return isSuper; }
+
// for any reference type, we can get some extra information...
public final boolean isArray() { return signature.startsWith("["); }
@@ -241,14 +247,17 @@ public class UnresolvedType implements TypeVariableDeclaringElement {
*/
protected UnresolvedType(String signature) {
super();
- // if (signature.indexOf('<') != -1) throw new IllegalStateException("Shouldn't be calling simple signature based type constructor with generic info in signature");
this.signature = signature;
this.signatureErasure = signature;
+ if (signature.charAt(0)=='-') isSuper = true;
+ if (signature.charAt(0)=='+') isExtends = true;
}
protected UnresolvedType(String signature, String signatureErasure) {
this.signature = signature;
this.signatureErasure = signatureErasure;
+ if (signature.charAt(0)=='-') isSuper = true;
+ if (signature.charAt(0)=='+') isExtends = true;
}
// called from TypeFactory
@@ -825,7 +834,7 @@ public class UnresolvedType implements TypeVariableDeclaringElement {
public String toString() {
return type;
-}
+ }
private TypeKind(String type) {
this.type = type;
@@ -834,5 +843,14 @@ public class UnresolvedType implements TypeVariableDeclaringElement {
private final String type;
}
+ /**
+ * Will return true if the type being represented is parameterized with a type variable
+ * from a generic method/ctor rather than a type variable from a generic type.
+ * Only subclasses know the answer...
+ */
+ public boolean isParameterizedWithAMemberTypeVariable() {
+ throw new RuntimeException("I dont know - you should ask a resolved version of me: "+this);
+ }
+
}
diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java
index 053a3c10d..c94090ebb 100644
--- a/weaver/src/org/aspectj/weaver/World.java
+++ b/weaver/src/org/aspectj/weaver/World.java
@@ -340,18 +340,16 @@ public abstract class World implements Dump.INode {
*/
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()) {
+ if (aType.isExtends()) {
ReferenceType upperBound = (ReferenceType)resolve(aType.getUpperBound());
ret = new BoundedReferenceType(upperBound,true,this);
- } else {
+ } else if (aType.isSuper()) {
ReferenceType lowerBound = (ReferenceType) resolve(aType.getLowerBound());
ret = new BoundedReferenceType(lowerBound,false,this);
+ } else {
+ // must be ? on its own!
}
- // 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;
}
@@ -593,9 +591,42 @@ public abstract class World implements Dump.INode {
private Map tMap = new HashMap();
/** Map of types that may be ejected from the cache if we need space */
private Map expendableMap = new WeakHashMap();
-
- /** Add a new type into the map, the key is the type signature */
+
+ private static final boolean debug = false;
+ /**
+ * Add a new type into the map, the key is the type signature.
+ * Some types do *not* go in the map, these are ones involving
+ * *member* type variables. The reason is that when all you have is the
+ * signature which gives you a type variable name, you cannot
+ * guarantee you are using the type variable in the same way
+ * as someone previously working with a similarly
+ * named type variable. So, these do not go into the map:
+ * - TypeVariableReferenceType.
+ * - ParameterizedType where a member type variable is involved.
+ * - BoundedReferenceType when one of the bounds is a type variable.
+ *
+ * definition: "member type variables" - a tvar declared on a generic
+ * method/ctor as opposed to those you see declared on a generic type.
+ */
public ResolvedType put(String key, ResolvedType type) {
+ if (type.isParameterizedType() && type.isParameterizedWithAMemberTypeVariable()) {
+ if (debug)
+ System.err.println("Not putting a parameterized type that utilises member declared type variables into the typemap: key="+key+" type="+type);
+ return type;
+ }
+ if (type.isTypeVariableReference()) {
+ if (debug)
+ System.err.println("Not putting a type variable reference type into the typemap: key="+key+" type="+type);
+ return type;
+ }
+ // this test should be improved - only avoid putting them in if one of the
+ // bounds is a member type variable
+ if (type instanceof BoundedReferenceType) {
+ if (debug)
+ System.err.println("Not putting a bounded reference type into the typemap: key="+key+" type="+type);
+ return type;
+ }
+
if (isExpendable(type)) {
return (ResolvedType) expendableMap.put(key,type);
} else {
diff --git a/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java
index 834168bfb..01983f3f7 100644
--- a/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java
+++ b/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java
@@ -253,13 +253,13 @@ public class WildTypePattern extends TypePattern {
if (lowerBound == null && aType.getLowerBound() != null) return false;
if (upperBound != null) {
// match ? extends
- if (aType.isGenericWildcardSuper()) return false;
+ if (aType.isGenericWildcard() && aType.isSuper()) return false;
if (aType.getUpperBound() == null) return false;
return upperBound.matches((ResolvedType)aType.getUpperBound(),staticOrDynamic).alwaysTrue();
}
if (lowerBound != null) {
// match ? super
- if (!aType.isGenericWildcardSuper()) return false;
+ if (!(aType.isGenericWildcard() && aType.isSuper())) return false;
return lowerBound.matches((ResolvedType)aType.getLowerBound(),staticOrDynamic).alwaysTrue();
}
return true;
diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java
index 35ea06360..a51ffdc2c 100644
--- a/weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java
+++ b/weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java
@@ -11,16 +11,14 @@
* ******************************************************************/
package org.aspectj.weaver.bcel;
+import junit.framework.TestCase;
+
import org.aspectj.apache.bcel.Repository;
import org.aspectj.apache.bcel.classfile.GenericSignatureParser;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Signature;
-import org.aspectj.weaver.ResolvedType;
-import org.aspectj.weaver.TypeVariable;
import org.aspectj.weaver.UnresolvedType;
-import junit.framework.TestCase;
-
/**
* @author colyer
*