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 {
-// 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>;
}
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
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");
// }
<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"/>
</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 -->
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()]);
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
public ReferenceType(UnresolvedType genericType, World world) {
super(genericType.getSignature(),world);
genericSignature=genericType.genericSignature;
- typeKind=GENERIC;
+ typeKind=TypeKind.GENERIC;
}
public final boolean isClass() {
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();
}
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;
}
}
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
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");
+ }
}
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();
+ }
+
}
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();
+ }
}
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
*/
protected TypeVariable[] typeVariables;
- /**
+ /**
* Determines if this represents a primitive type. A primitive type
* is one of nine predefined resolved types.
*
* @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("["); }
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
// 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;
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);
public static UnresolvedType forRawTypeNames(String name) {
UnresolvedType ret = UnresolvedType.forName(name);
- ret.typeKind = RAW;
+ ret.typeKind = TypeKind.RAW;
return ret;
}
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);
}
}
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
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.
}
+ 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;
+ }
}
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;
(!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) {
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;
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()));
}
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();
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;
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],