From: aclement Date: Thu, 21 Jul 2005 10:01:29 +0000 (+0000) Subject: generics: fixes for decp testcases involving generic types targeted by parameterized... X-Git-Tag: V1_5_0M3~288 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=314bd5f7977ebe80b65a27c2c4df56c7b2e77d24;p=aspectj.git 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. --- 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 { } 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 { } +interface I { } public class Basic5 { } aspect X { - declare parents: Basic5 implements I; + declare parents: Basic5 implements I; } 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;PI;"); + verifyClassSignature("Basic","Ljava/lang/Object;LJ;LI;"); } // 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","Ljava/lang/Object;LI;LK;"); + } -// // 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 @@ - - - + + + + + + + @@ -2459,14 +2463,18 @@ - - + + + - - + + + + + + + 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/**/ 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;>;",comparable.getSignature()); + ); + assertEquals("Pjava/lang/Comparable;",comparable.getSignature()); UnresolvedType serializable = BcelGenericSignatureToTypeXConverter.classTypeSignature2TypeX( cSig.superInterfaceSignatures[1],