]> source.dussan.org Git - aspectj.git/commitdiff
generics: fixes for decp testcases involving generic types targeted by parameterized...
authoraclement <aclement>
Thu, 21 Jul 2005 10:01:29 +0000 (10:01 +0000)
committeraclement <aclement>
Thu, 21 Jul 2005 10:01:29 +0000 (10:01 +0000)
15 files changed:
tests/java5/generics/decp/Basic4.aj
tests/java5/generics/decp/Basic5.aj
tests/src/org/aspectj/systemtest/ajc150/GenericsTests.java
tests/src/org/aspectj/systemtest/ajc150/ajc150.xml
weaver/src/org/aspectj/weaver/Member.java
weaver/src/org/aspectj/weaver/ReferenceType.java
weaver/src/org/aspectj/weaver/ResolvedType.java
weaver/src/org/aspectj/weaver/TypeVariable.java
weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java
weaver/src/org/aspectj/weaver/UnresolvedType.java
weaver/src/org/aspectj/weaver/World.java
weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
weaver/src/org/aspectj/weaver/patterns/DeclareParents.java
weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
weaver/testsrc/org/aspectj/weaver/bcel/BcelGenericSignatureToTypeXTestCase.java

index 10ccc56a7b14854eb7551800e2d05aed6f4b43a1..6d88ffc761dd84e1b2c792d4d3ae6f8de39a2cab 100644 (file)
@@ -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 {
index 991eda6c2d45d11e859bf703622b37004431c498..6fb3d80ec1eb154a14c019c0d537e8a31f1bcbef 100644 (file)
@@ -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>;
 }
index 6f794910bca20f44198c732852363f45177f0988..24b027b7ea6eb04024653841f8cbc0628a61fbab 100644 (file)
@@ -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");
 //     }
index 07345574dbb86a9e5f3f96770361d2cf4c0c65d9..109c05a0f1ffbed3dff67c1fdbf207ca8f861eaa 100644 (file)
    <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&lt;T extends Number&gt;"/>
+     </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&lt;java.lang.Integer&gt;' (Basic6.aj)"/>
+     </compile>
+     <run class="Basic6"/>
+   </ajc-test>
+
    <!-- end of generic decps -->
    
    <!-- generics and  pointcuts -->
index c29355f34cc275fe323b0219196bed9824da7ce8..345d7e0a3ded092e7440caaab3e11349a286454d 100644 (file)
@@ -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()]);
index 84dbb9865751fd4cfecb5d0946631634e70ff7d1..c377daf506b7d1e7cb5a82400a0777db140fda8e 100644 (file)
@@ -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
index f6fc35210b14b0082c5a4f6853120f564320bb05..20ecf94edc87993741e19876b9085e01cb770a9a 100644 (file)
@@ -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");
+       }
 
            
 }
index c64267109e11b00509f8c3250896d0bf214bb9e3..042f4425f2e7770bf545cbef4ffadb930e85ee0c 100644 (file)
@@ -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();
+       }
+       
 }
index 18179557b14650d9b61ba78f3d784a1dacad3a0a..c37bd63699f9c5ba05ce6febe4fd7fd954b9c834 100644 (file)
@@ -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();
+       }
 }
index 6accec459e3f322d00b4022b917588396face1bc..1d07588b0b7e038b71ae442d685cb66cc2af3d32 100644 (file)
@@ -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;
+       }
        
 }
 
index 901e0571163511ae2ba97bdf77c6116939584ee8..d54ebfb57b4ffdc6f100866e4577c905b479a2f1 100644 (file)
@@ -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) {
index f791f567a0a7c7c5de98a56222b6d795f5c08549..81490d5eb5f5877bb933d6289d6ab912e012bca2 100644 (file)
@@ -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()));
                }
index b143af4c95d648da7e69737b12d2b40d410f8f68..926a9fcb6964f2720c60db28d931141b1340e10d 100644 (file)
@@ -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();
index f008ef19b64d70c5ef6c0c3d452d23666819916c..9238caa418d7487dc194d92bdc703ae1ce25d99f 100644 (file)
@@ -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;
index f36b86023867004e3a224e39674611b09b8075fd..35ea06360b75ac7bd0ad78598ef3d84470636a19 100644 (file)
@@ -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],