diff options
author | aclement <aclement> | 2005-07-21 10:01:29 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-07-21 10:01:29 +0000 |
commit | 314bd5f7977ebe80b65a27c2c4df56c7b2e77d24 (patch) | |
tree | 40ae2ab595d68341554da09dd9450eb2d48b3a55 | |
parent | e59d3c8559ab260fff18b12af97cb5de92157c06 (diff) | |
download | aspectj-314bd5f7977ebe80b65a27c2c4df56c7b2e77d24.tar.gz aspectj-314bd5f7977ebe80b65a27c2c4df56c7b2e77d24.zip |
generics: fixes for decp testcases involving generic types targeted by parameterized decps. Type variables now persist in the system for longer... also LazyClassGen generates correct generic signatures for modified types.
15 files changed, 190 insertions, 69 deletions
diff --git a/tests/java5/generics/decp/Basic4.aj b/tests/java5/generics/decp/Basic4.aj index 10ccc56a7..6d88ffc76 100644 --- a/tests/java5/generics/decp/Basic4.aj +++ b/tests/java5/generics/decp/Basic4.aj @@ -2,6 +2,11 @@ interface I<T extends Number> { } public class Basic4 { + public static void main(String[] argv) { + Basic4 b4 = new Basic4(); + if (!(b4 instanceof I)) + throw new RuntimeException("Should be instanceof I!"); + } } aspect X { diff --git a/tests/java5/generics/decp/Basic5.aj b/tests/java5/generics/decp/Basic5.aj index 991eda6c2..6fb3d80ec 100644 --- a/tests/java5/generics/decp/Basic5.aj +++ b/tests/java5/generics/decp/Basic5.aj @@ -1,9 +1,8 @@ -// fails, Number is not a subclass of double! -interface I<T super Number> { } +interface I<T extends Number> { } public class Basic5 { } aspect X { - declare parents: Basic5 implements I<Double>; + declare parents: Basic5 implements I<String>; } diff --git a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java index 6f794910b..24b027b7e 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java +++ b/tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java @@ -178,7 +178,7 @@ public class GenericsTests extends XMLBasedAjcTestCase { public void testPR96220_GenericDecp() { runTest("generic decp - simple"); - verifyClassSignature("Basic","Ljava/lang/Object;PJ<Ljava/lang/Double;>;PI<Ljava/lang/Double;>;"); + verifyClassSignature("Basic","Ljava/lang/Object;LJ<Ljava/lang/Double;>;LI<Ljava/lang/Double;>;"); } // Both the existing type decl and the one adding via decp are parameterized @@ -219,16 +219,20 @@ public class GenericsTests extends XMLBasedAjcTestCase { public void testGenericDecpMultipleVariantsOfAParameterizedType4_binaryWeaving() { runTest("generic decp binary - implementing two variants #4"); } + + public void testGenericDecpParameterized() { + runTest("generic decp - with parameterized on the target"); + verifyClassSignature("Basic6","<J:Ljava/lang/Object;>Ljava/lang/Object;LI<TJ;>;LK<Ljava/lang/Integer;>;"); + } -// // public void testGenericDecpIncorrectNumberOfTypeParams() { // runTest("generic decp - incorrect number of type parameters"); // } -// -// public void testGenericDecpSpecifyingBounds() { -// runTest("generic decp - specifying bounds"); -// } -// + + public void testGenericDecpSpecifyingBounds() { + runTest("generic decp - specifying bounds"); + } + // public void testGenericDecpViolatingBounds() { // runTest("generic decp - specifying bounds but breaking them"); // } diff --git a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml index 07345574d..109c05a0f 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml @@ -2445,13 +2445,17 @@ <ajc-test dir="java5/generics/decp/binary" title="generic decp binary - implementing two variants #4"> <weave classesFiles="Base4.java" aspectsFiles="Asp4.aj" options="-1.5,-showWeaveInfo"/> </ajc-test> - -<!-- --> - <ajc-test dir="java5/generics/decp" title="generic decp - incorrect number of type parameters"> + <ajc-test dir="java5/generics/decp" title="generic decp - incorrect number of type parameters"> <compile files="Basic3.aj" options="-1.5"/> <run class="Basic3"/> </ajc-test> + + <ajc-test dir="java5/generics/decp" title="generic decp - incorrect number of type parameters"> + <compile files="Basic3.aj" options="-1.5"> + <message kind="error" line="10" text="Wrong number of type arguments; Type I requires 1"/> + </compile> + </ajc-test> <ajc-test dir="java5/generics/decp" title="generic decp - specifying bounds"> <compile files="Basic4.aj" options="-1.5"/> @@ -2459,14 +2463,18 @@ </ajc-test> <ajc-test dir="java5/generics/decp" title="generic decp - specifying bounds but breaking them"> - <compile files="Basic5.aj" options="-1.5"/> - <run class="Basic5"/> + <compile files="Basic5.aj" options="-1.5"> + <message kind="error" line="7" text="Type String does not meet the specification for type parameter 1 in generic type I<T extends Number>"/> + </compile> </ajc-test> - - <!--ajc-test dir="java5/generics/decp" title="illegal generic decp"> - <compile files="Basic2.aj" options="-1.5"/> - </ajc-test--> + <ajc-test dir="java5/generics/decp" title="generic decp - with parameterized on the target"> + <compile files="Basic6.aj" options="-1.5,-showWeaveInfo"> + <message kind="weave" text="Extending interface set for type 'Basic6' (Basic6.aj) to include 'K<java.lang.Integer>' (Basic6.aj)"/> + </compile> + <run class="Basic6"/> + </ajc-test> + <!-- end of generic decps --> <!-- generics and pointcuts --> diff --git a/weaver/src/org/aspectj/weaver/Member.java b/weaver/src/org/aspectj/weaver/Member.java index c29355f34..345d7e0a3 100644 --- a/weaver/src/org/aspectj/weaver/Member.java +++ b/weaver/src/org/aspectj/weaver/Member.java @@ -182,8 +182,14 @@ public class Member implements Comparable, AnnotatedElement { UnresolvedType tx = UnresolvedType.forSignature(toProcess); l.add(tx); } + } else if (c=='T') { // assumed 'reference' to a type variable, so just "Tname;" + int nextSemicolon = sig.indexOf(';',start); + String nextbit = sig.substring(start,nextSemicolon); + l.add(UnresolvedType.forSignature(nextbit)); + i=nextSemicolon+1; } else { - l.add(UnresolvedType.forSignature(sig.substring(start, ++i))); + i++; + l.add(UnresolvedType.forSignature(sig.substring(start, i))); } } UnresolvedType[] paramTypes = (UnresolvedType[]) l.toArray(new UnresolvedType[l.size()]); diff --git a/weaver/src/org/aspectj/weaver/ReferenceType.java b/weaver/src/org/aspectj/weaver/ReferenceType.java index 84dbb9865..c377daf50 100644 --- a/weaver/src/org/aspectj/weaver/ReferenceType.java +++ b/weaver/src/org/aspectj/weaver/ReferenceType.java @@ -71,9 +71,13 @@ public class ReferenceType extends ResolvedType { ReferenceType genericReferenceType = (ReferenceType) theGenericType; this.typeParameters = theParameters; this.genericType = genericReferenceType; - this.typeKind = PARAMETERIZED; + this.typeKind = TypeKind.PARAMETERIZED; this.delegate = genericReferenceType.getDelegate(); } + + public String getSignatureForAttribute() { + return makeDeclaredSignature(genericType,typeParameters); + } /** * Create a reference type for a generic type @@ -81,7 +85,7 @@ public class ReferenceType extends ResolvedType { public ReferenceType(UnresolvedType genericType, World world) { super(genericType.getSignature(),world); genericSignature=genericType.genericSignature; - typeKind=GENERIC; + typeKind=TypeKind.GENERIC; } public final boolean isClass() { @@ -304,6 +308,12 @@ public class ReferenceType extends ResolvedType { public void setDelegate(ReferenceTypeDelegate delegate) { this.delegate = delegate; + + // If we are raw, we have a generic type - we should ensure it uses the + // same delegate + if (isRawType() && getGenericType()!=null) { + ((ReferenceType)getGenericType()).setDelegate(delegate); + } clearParameterizationCaches(); } @@ -346,8 +356,8 @@ public class ReferenceType extends ResolvedType { genericType = rt; // Should we 'promote' this reference type from simple to raw? // makes sense if someone is specifying that it has a generic form - if ( typeKind == UnresolvedType.SIMPLE ) { - typeKind = UnresolvedType.RAW; + if ( typeKind == TypeKind.SIMPLE ) { + typeKind = TypeKind.RAW; signatureErasure = signature; } } @@ -378,4 +388,16 @@ public class ReferenceType extends ResolvedType { return ret.toString(); } + private static String makeDeclaredSignature(ResolvedType aGenericType, UnresolvedType[] someParameters) { + StringBuffer ret = new StringBuffer(); + String rawSig = aGenericType.getRawTypeSignature(); + ret.append(rawSig.substring(0,rawSig.length()-1)); + ret.append("<"); + for (int i = 0; i < someParameters.length; i++) { + ret.append(someParameters[i].getSignature()); + } + ret.append(">;"); + return ret.toString(); + } + }
\ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/ResolvedType.java b/weaver/src/org/aspectj/weaver/ResolvedType.java index f6fc35210..20ecf94ed 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedType.java +++ b/weaver/src/org/aspectj/weaver/ResolvedType.java @@ -1543,6 +1543,13 @@ public abstract class ResolvedType extends UnresolvedType implements AnnotatedEl public boolean needsNoConversionFrom(ResolvedType o) { return isAssignableFrom(o); } + + /** + * Implemented by ReferenceTypes + */ + public String getSignatureForAttribute() { + throw new RuntimeException("Cannot ask this type "+this+" for a generic sig attribute"); + } } diff --git a/weaver/src/org/aspectj/weaver/TypeVariable.java b/weaver/src/org/aspectj/weaver/TypeVariable.java index c64267109..042f4425f 100644 --- a/weaver/src/org/aspectj/weaver/TypeVariable.java +++ b/weaver/src/org/aspectj/weaver/TypeVariable.java @@ -138,4 +138,22 @@ public class TypeVariable { public String toString() { return "T" + upperBound.getSignature(); } + + /** + * Return *full* signature for insertion in signature attribute, e.g. "T extends Number" would return "T:Ljava/lang/Number;" + */ + public String getSignature() { + StringBuffer sb = new StringBuffer(); + sb.append(name); + sb.append(":"); + sb.append(upperBound.getSignature()); + if (additionalInterfaceBounds!=null) { + for (int i = 0; i < additionalInterfaceBounds.length; i++) { + UnresolvedType iBound = additionalInterfaceBounds[i]; + sb.append(iBound.getSignature()); + } + } + return sb.toString(); + } + } diff --git a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java index 18179557b..c37bd6369 100644 --- a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java +++ b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java @@ -45,4 +45,16 @@ public class TypeVariableReferenceType extends BoundedReferenceType { return true; } + /** + * return the signature for a *REFERENCE* to a type variable, which is simply: + * Tname; + * there is no bounds info included, that is in the signature of the type variable itself + */ + public String getSignature() { + StringBuffer sb = new StringBuffer(); + sb.append("T"); + sb.append(typeVariable.getName()); + sb.append(";"); + return sb.toString(); + } } diff --git a/weaver/src/org/aspectj/weaver/UnresolvedType.java b/weaver/src/org/aspectj/weaver/UnresolvedType.java index 6accec459..1d07588b0 100644 --- a/weaver/src/org/aspectj/weaver/UnresolvedType.java +++ b/weaver/src/org/aspectj/weaver/UnresolvedType.java @@ -121,31 +121,8 @@ public class UnresolvedType { public static final String MISSING_NAME = "@missing@"; - // constants indicating the base kind of the type - // Note: It is not sufficient to say that a parameterized type with no type parameters in fact - // represents a raw type - a parameterized type with no type parameters can represent - // an inner type of a parameterized type that specifies no type parameters of its own. - public final static int PRIMITIVE = 0; - public final static int SIMPLE =1; // a type with NO type parameters/vars - public final static int RAW =2; // the erasure of a generic type - public final static int GENERIC =3; // a generic type - public final static int PARAMETERIZED=4; // a parameterized type - public final static int TYPE_VARIABLE = 5; // a type variable - public final static int WILDCARD = 6; // a generic wildcard type - - public String getKind() { - switch (typeKind) { - case PRIMITIVE: return "PRIMITIVE"; - case SIMPLE: return "SIMPLE"; - case RAW: return "RAW"; - case GENERIC: return "GENERIC"; - case PARAMETERIZED: return "PARAMETERIZED"; - case TYPE_VARIABLE: return "TYPE_VARIABLE"; - case WILDCARD: return "WILDCARD"; - default: return null; - } - } - protected int typeKind = SIMPLE; // what kind of type am I? + + protected TypeKind typeKind = TypeKind.SIMPLE; // what kind of type am I? /** * THE SIGNATURE - see the comments above for how this is defined @@ -171,7 +148,7 @@ public class UnresolvedType { */ protected TypeVariable[] typeVariables; - /** + /** * Determines if this represents a primitive type. A primitive type * is one of nine predefined resolved types. * @@ -187,13 +164,13 @@ public class UnresolvedType { * @see ResolvedType#Double * @see ResolvedType#Void */ - public boolean isPrimitiveType() { return typeKind == PRIMITIVE; } - public boolean isSimpleType() { return typeKind == SIMPLE; } - public boolean isRawType() { return typeKind == RAW; } - public boolean isGenericType() { return typeKind == GENERIC; } - public boolean isParameterizedType() { return typeKind == PARAMETERIZED; } - public boolean isTypeVariable() { return typeKind == TYPE_VARIABLE; } - public boolean isGenericWildcard() { return typeKind == WILDCARD; } + 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 isTypeVariable() { return typeKind == TypeKind.TYPE_VARIABLE; } + public boolean isGenericWildcard() { return typeKind == TypeKind.WILDCARD; } // for any reference type, we can get some extra information... public final boolean isArray() { return signature.startsWith("["); } @@ -273,7 +250,7 @@ public class UnresolvedType { this.signature = signature; this.signatureErasure = signatureErasure; this.typeParameters = typeParams; - if (typeParams != null) this.typeKind = PARAMETERIZED; + if (typeParams != null) this.typeKind = TypeKind.PARAMETERIZED; } // ---- Things we can do without a world @@ -335,7 +312,7 @@ public class UnresolvedType { // TODO asc generics needs a declared sig String sig = nameToSignature(name); UnresolvedType ret = UnresolvedType.forSignature(sig); - ret.typeKind=GENERIC; + ret.typeKind=TypeKind.GENERIC; ret.typeVariables = tvbs; ret.signatureErasure = sig; ret.genericSignature = genericSig; @@ -344,7 +321,7 @@ public class UnresolvedType { public static UnresolvedType forGenericTypeSignature(String sig,String declaredGenericSig) { UnresolvedType ret = UnresolvedType.forSignature(sig); - ret.typeKind=GENERIC; + ret.typeKind=TypeKind.GENERIC; ClassSignature csig = new GenericSignatureParser().parseAsClassSignature(declaredGenericSig); @@ -363,7 +340,7 @@ public class UnresolvedType { public static UnresolvedType forRawTypeNames(String name) { UnresolvedType ret = UnresolvedType.forName(name); - ret.typeKind = RAW; + ret.typeKind = TypeKind.RAW; return ret; } @@ -431,6 +408,7 @@ public class UnresolvedType { case '+': return new UnresolvedType(signature); case '-' : return new UnresolvedType(signature); case '?' : return GenericsWildcardTypeX.GENERIC_WILDCARD; + case 'T' : return new UnresolvedTypeVariableReferenceType(new TypeVariable(signature.substring(1))); default: throw new BCException("Bad type signature " + signature); } } @@ -521,10 +499,11 @@ public class UnresolvedType { public String getSignature() { return signature; } - - public String getParameterizedSignature() { - return signature; - } + + +// public String getParameterizedSignature() { +// return signature; +// } /** * For parameterized types, return the signature for the raw type @@ -605,6 +584,12 @@ public class UnresolvedType { case 'L': String name = signature.substring(1, signature.length() - 1).replace('/', '.'); return name; + case 'T': + StringBuffer nameBuff2 = new StringBuffer(); + int colon = signature.indexOf(";"); + String tvarName = signature.substring(1,colon); + nameBuff2.append(tvarName); + return nameBuff2.toString(); case 'P': // it's one of our parameterized type sigs StringBuffer nameBuff = new StringBuffer(); // signature for parameterized types is e.g. @@ -793,6 +778,28 @@ public class UnresolvedType { } + public static class TypeKind { + // Note: It is not sufficient to say that a parameterized type with no type parameters in fact + // represents a raw type - a parameterized type with no type parameters can represent + // an inner type of a parameterized type that specifies no type parameters of its own. + public final static TypeKind PRIMITIVE = new TypeKind("primitive"); + public final static TypeKind SIMPLE = new TypeKind("simple"); // a type with NO type parameters/vars + public final static TypeKind RAW = new TypeKind("raw"); // the erasure of a generic type + public final static TypeKind GENERIC = new TypeKind("generic"); // a generic type + public final static TypeKind PARAMETERIZED= new TypeKind("parameterized"); // a parameterized type + public final static TypeKind TYPE_VARIABLE= new TypeKind("type_variable"); // a type variable + public final static TypeKind WILDCARD = new TypeKind("wildcard"); // a generic wildcard type + + public String toString() { + return type; + } + + private TypeKind(String type) { + this.type = type; + } + + private final String type; + } } diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java index 901e05711..d54ebfb57 100644 --- a/weaver/src/org/aspectj/weaver/World.java +++ b/weaver/src/org/aspectj/weaver/World.java @@ -18,6 +18,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.WeakHashMap; import org.aspectj.asm.IHierarchy; @@ -645,6 +646,25 @@ public abstract class World implements Dump.INode { (!type.isPrimitiveType()) ); } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("types:\n"); + sb.append(dumpthem(tMap)); + sb.append("expendables:\n"); + sb.append(dumpthem(expendableMap)); + return sb.toString(); + } + + private String dumpthem(Map m) { + StringBuffer sb = new StringBuffer(); + Set keys = m.keySet(); + for (Iterator iter = keys.iterator(); iter.hasNext();) { + String k = (String) iter.next(); + sb.append(k+"="+m.get(k)).append("\n"); + } + return sb.toString(); + } } public void setBehaveInJava5Way(boolean b) { diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java index f791f567a..81490d5eb 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java +++ b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java @@ -62,6 +62,7 @@ import org.aspectj.weaver.NameMangler; import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedType; import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.TypeVariable; import org.aspectj.weaver.UnresolvedType; import org.aspectj.weaver.WeaverMessages; import org.aspectj.weaver.WeaverStateInfo; @@ -515,12 +516,22 @@ public final class LazyClassGen { if (needAttribute) { StringBuffer signature = new StringBuffer(); // first, the type variables... - // TODO asc generics implement this! + TypeVariable[] tVars = myType.getTypeVariables(); + if (tVars.length>0) { + signature.append("<"); + for (int i = 0; i < tVars.length; i++) { + TypeVariable variable = tVars[i]; + if (i!=0) signature.append(","); + signature.append(variable.getSignature()); + } + signature.append(">"); + } // now the supertype signature.append(myType.getSuperclass().getSignature()); ResolvedType[] interfaceRTXs = myType.getDeclaredInterfaces(); for (int i = 0; i < interfaceRTXs.length; i++) { - signature.append(interfaceRTXs[i].getSignature()); + String s = interfaceRTXs[i].getSignatureForAttribute(); + signature.append(s); } myGen.addAttribute(createSignatureAttribute(signature.toString())); } diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java b/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java index b143af4c9..926a9fcb6 100644 --- a/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java +++ b/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java @@ -302,6 +302,7 @@ public class DeclareParents extends Declare { public List/*<ResolvedType>*/ findMatchingNewParents(ResolvedType onType,boolean reportErrors) { + if (onType.isRawType()) onType = onType.getGenericType(); if (!match(onType)) return Collections.EMPTY_LIST; List ret = new ArrayList(); diff --git a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java index f008ef19b..9238caa41 100644 --- a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java @@ -311,6 +311,7 @@ public class SignaturePattern extends PatternNode { if (!checkReturnType) return true; ResolvedMember rm = type.lookupMethod(member); if (rm==null) rm = type.lookupMethodInITDs(member); // It must be in here, or we have *real* problems + if (rm==null) continue; // might be currently looking at the generic type and we need to continue searching in case we hit a parameterized version of this same type... UnresolvedType returnTypeX = rm.getReturnType(); ResolvedType returnType = returnTypeX.resolve(world); if (returnTypePattern.matchesStatically(returnType)) return true; diff --git a/weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java b/weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java index f36b86023..35ea06360 100644 --- a/weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java +++ b/weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java @@ -44,8 +44,8 @@ public class BcelGenericSignatureToTypeXTestCase extends TestCase { cSig.superInterfaceSignatures[0], cSig.formalTypeParameters, world - ); - assertEquals("Pjava/lang/Comparable<Pjava/lang/Enum<Ljava/lang/Object;>;>;",comparable.getSignature()); + ); + assertEquals("Pjava/lang/Comparable<TE;>;",comparable.getSignature()); UnresolvedType serializable = BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX( cSig.superInterfaceSignatures[1], |