]> source.dussan.org Git - aspectj.git/commitdiff
this set of commits teaches the TypeX world about parameterized types. it handles...
authoracolyer <acolyer>
Wed, 20 Apr 2005 19:24:30 +0000 (19:24 +0000)
committeracolyer <acolyer>
Wed, 20 Apr 2005 19:24:30 +0000 (19:24 +0000)
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseFactory.java
tests/java5/generics/ITDReturningParameterizedType.aj
tests/src/org/aspectj/systemtest/ajc150/AllTestsAspectJ150.java
weaver/src/org/aspectj/weaver/TypeX.java
weaver/src/org/aspectj/weaver/World.java
weaver/testsrc/org/aspectj/weaver/TypeXTestCase.java

index 5aeedd62e40026349cc446698b38f6260976b051..931c7db1557214eab958b17942d117d79c498642 100644 (file)
@@ -47,11 +47,13 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
+import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
  
 /**
  * @author Jim Hugunin
@@ -165,6 +167,19 @@ public class EclipseFactory {
                        TypeVariableBinding tvb = (TypeVariableBinding) binding;
                        return TypeX.forName(getName(tvb.firstBound)); // XXX needs more investigation as to whether this is correct in all cases
                }
+               if (binding instanceof ParameterizedTypeBinding) {
+                       ParameterizedTypeBinding ptb = (ParameterizedTypeBinding) binding;
+                       String[] arguments = new String[ptb.arguments.length];
+                       for (int i = 0; i < arguments.length; i++) {
+                               if (ptb.arguments[i] instanceof WildcardBinding) {
+                                       WildcardBinding wcb = (WildcardBinding) ptb.arguments[i];
+                                       arguments[i] = getName(((TypeVariableBinding)wcb.typeVariable()).firstBound);
+                               }  else {
+                                       arguments[i] = getName(ptb.arguments[i]);
+                               }
+                       }
+                       return TypeX.forParameterizedTypeNames(getName(binding), arguments);
+               }
                return TypeX.forName(getName(binding));
        }
 
@@ -307,21 +322,32 @@ public class EclipseFactory {
                                typeX = typeX.getComponentType();
                        }
                        return lookupEnvironment.createArrayType(makeTypeBinding(typeX), dim);
+               } else if (typeX.isParameterized()){
+                       TypeX[] typeParameters = typeX.getTypeParameters();
+                       ReferenceBinding baseTypeBinding = lookupBinding(typeX.getBaseName());
+                       ReferenceBinding[] argumentBindings = new ReferenceBinding[typeParameters.length];
+                       for (int i = 0; i < argumentBindings.length; i++) {
+                               argumentBindings[i] = lookupBinding(typeParameters[i].getName());
+                       }
+                       ParameterizedTypeBinding ptb = 
+                               lookupEnvironment.createParameterizedType(baseTypeBinding,argumentBindings,baseTypeBinding.enclosingType());
+                       return ptb;
                } else {
-                       String n = typeX.getName();
-                       char[][] name = CharOperation.splitOn('.', n.toCharArray());
-                       ReferenceBinding rb = lookupEnvironment.getType(name);
-                       // XXX We do this because the pertypewithin aspectOf(Class) generated method needs it.  Without this
-                       // we don't get a 'rawtype' as the argument type for a messagesend to aspectOf() and this leads to 
-                       // a compile error if some client class calls aspectOf(A.class) or similar as it says Class<A> isn't
-                       // compatible with Class<T>
-                       if (n.equals("java.lang.Class")) 
-                               rb = lookupEnvironment.createRawType(rb,rb.enclosingType());
-                       return rb;
+                       return lookupBinding(typeX.getName());
                }
        }
        
-       
+       private ReferenceBinding lookupBinding(String sname) {
+               char[][] name = CharOperation.splitOn('.', sname.toCharArray());
+               ReferenceBinding rb = lookupEnvironment.getType(name);
+               // XXX We do this because the pertypewithin aspectOf(Class) generated method needs it.  Without this
+               // we don't get a 'rawtype' as the argument type for a messagesend to aspectOf() and this leads to 
+               // a compile error if some client class calls aspectOf(A.class) or similar as it says Class<A> isn't
+               // compatible with Class<T>
+               if (sname.equals("java.lang.Class")) 
+                       rb = lookupEnvironment.createRawType(rb,rb.enclosingType());
+               return rb;              
+       }
        
        public TypeBinding[] makeTypeBindings(TypeX[] types) {
                int len = types.length;
index aa5f3e97801ada054e1d061ed265094e56e02dc2..4495e8042d1afea8d750105d056ad035336e4514 100644 (file)
@@ -2,6 +2,8 @@ import java.util.*;
 
 public aspect ITDReturningParameterizedType {
        
+       private List<String> myStrings = new ArrayList<String>();
+       
        private List<String> C.strings = new ArrayList<String>();
        
        public List<String> C.getStrings() {
index 52e285c83c6bebae6f04f042b7e38d8d11c5efc0..1f0ad25f989b8e8c7583838ff7535d1d78848dde 100644 (file)
@@ -42,7 +42,7 @@ public class AllTestsAspectJ150 {
                
                suite.addTest(SuppressedWarnings.suite());
                suite.addTest(DeclareAnnotationTests.suite());
-               
+               suite.addTest(GenericsTests.suite());
                suite.addTest(AtAjSyntaxTests.suite());
                //$JUnit-END$
                return suite;
index 2b046a3709c8569d900fa6c74802d4153787f593..cd9e352f32f86775bf024c8909c2e86efa963d00 100644 (file)
@@ -23,6 +23,11 @@ public class TypeX implements AnnotatedElement {
         * This is the bytecode string representation of this Type
         */
     protected String signature;
+       
+       /**
+        * If this is a parameterized type, these are its parameters
+        */
+       protected TypeX[] typeParameters;
 
        /**
         * @param      signature   the bytecode string representation of this Type
@@ -101,7 +106,29 @@ public class TypeX implements AnnotatedElement {
         }
         return ret;
     }  
-    
+       
+       /**
+        * Makes a parameterized type with the given name
+        * and parameterized type names.
+        */
+    public static TypeX forParameterizedTypeNames(String name, String[] paramTypeNames) {
+               TypeX ret = TypeX.forName(name);
+               ret.typeParameters = new TypeX[paramTypeNames.length];
+               for (int i = 0; i < paramTypeNames.length; i++) {
+                       ret.typeParameters[i] = TypeX.forName(paramTypeNames[i]);
+               }
+               // sig for e.g. List<String> is Ljava/util/List<Ljava/lang/String;>;
+               StringBuffer sigAddition = new StringBuffer();
+               sigAddition.append("<");
+               for (int i = 0; i < ret.typeParameters.length; i++) {
+                       sigAddition.append(ret.typeParameters[i].signature);
+                       sigAddition.append(">");
+                       sigAddition.append(";");
+               }
+               ret.signature = ret.signature + sigAddition.toString();
+               return ret;
+    }
+       
        /**
         * Creates a new type array with a fresh type appended to the end.
         * 
@@ -205,6 +232,15 @@ public class TypeX implements AnnotatedElement {
     public String getName() {
         return signatureToName(signature);
     }
+       
+       public String getBaseName() {
+               String name = getName();
+               if (isParameterized()) {
+                       return name.substring(0,name.indexOf("<"));
+               } else {
+                       return name;
+               }
+       }
 
     /**
      * Returns an array of strings representing the java langauge names of 
@@ -250,6 +286,14 @@ public class TypeX implements AnnotatedElement {
     public final boolean isArray() {
         return signature.startsWith("[");
     }
+       
+       /**
+        * Determines if this represents a parameterized type.
+        */
+       public final boolean isParameterized() {
+               return signature.indexOf("<") != -1; 
+               //(typeParameters != null) && (typeParameters.length > 0);
+       }
     
     /**
      * Returns a TypeX object representing the effective outermost enclosing type
@@ -603,7 +647,48 @@ public class TypeX implements AnnotatedElement {
             case 'I': return "int";
             case 'J': return "long";
             case 'L':
-                return signature.substring(1, signature.length() - 1).replace('/', '.');
+                String name =  signature.substring(1, signature.length() - 1).replace('/', '.');
+                               if (name.indexOf("<") == -1) return name;
+                               // signature for parameterized types is e.g.
+                               // List<String> -> Ljava/util/List<Ljava/lang/String;>;
+                               // Map<String,List<Integer>> -> Ljava/util/Map<java/lang/String;Ljava/util/List<Ljava/lang/Integer;>;>;
+                               StringBuffer nameBuff = new StringBuffer();
+                               boolean justSeenLeftArrowChar = false;
+                               boolean justSeenSemiColon= false;
+                               int paramNestLevel = 0;
+                               for (int i = 0 ; i < name.length(); i++) {
+                                       char c = name.charAt(i);
+                                       switch (c) {
+                                               case '<' : 
+                                                       justSeenLeftArrowChar = true;
+                                                       paramNestLevel++;
+                                                       nameBuff.append(c); 
+                                                       break;
+                                               case ';' :
+                                                       justSeenSemiColon = true;
+                                                       break;
+                                               case '>' :
+                                                       paramNestLevel--;
+                                                       nameBuff.append(c);
+                                                       break;
+                                               case 'L' :
+                                                       if (justSeenLeftArrowChar) {
+                                                               justSeenLeftArrowChar = false;
+                                                               break;
+                                                       }
+                                                       if (justSeenSemiColon) {
+                                                               nameBuff.append(",");
+                                                       } else {
+                                                               nameBuff.append("L");
+                                                       }
+                                                       break;
+                                               default: 
+                                                       justSeenSemiColon = false;
+                                                       justSeenLeftArrowChar = false;
+                                                       nameBuff.append(c);
+                                       }
+                               }
+                               return nameBuff.toString();
             case 'S': return "short";
             case 'V': return "void";
             case 'Z': return "boolean";
@@ -631,7 +716,27 @@ public class TypeX implements AnnotatedElement {
                
                // 1) If it is already an array type, do not mess with it.
                if (name.charAt(0)=='[' && name.charAt(name.length()-1)==';') return name;
-               else return "L" + name.replace('.', '/') + ";";
+               else {
+                               if (name.indexOf("<") == -1) {
+                                       // not parameterised
+                                       return "L" + name.replace('.', '/') + ";";
+                               } else {
+                                       StringBuffer nameBuff = new StringBuffer();
+                                       nameBuff.append("L");
+                                       for (int i = 0; i < name.length(); i++) {
+                                               char c = name.charAt(i);
+                                               switch (c) {
+                                               case '.' : nameBuff.append('/'); break;
+                                               case '<' : nameBuff.append("<L"); break;
+                                               case '>' : nameBuff.append(";>"); break;
+                                               case ',' : nameBuff.append(";L"); break;
+                                               default: nameBuff.append(c);
+                                               }
+                                       }
+                                       nameBuff.append(";");
+                                       return nameBuff.toString();
+                               }
+               }
         }
         else 
             throw new BCException("Bad type name: " + name);
@@ -721,6 +826,10 @@ public class TypeX implements AnnotatedElement {
                }
        }
        
+       public TypeX[] getTypeParameters() {
+               return typeParameters == null ? new TypeX[0] : typeParameters;
+       }
+       
        /**
         * Doesn't include the package
         */
index ca7e0a211a2d523897341c39f98816282a2f7c3e..04ec34815fc3f18b3a10dc3b9c3f4650e8fad79a 100644 (file)
@@ -137,6 +137,11 @@ public abstract class World implements Dump.INode {
                 dumpState_cantFindTypeExceptions.add(new RuntimeException("Can't find type "+ty.getName()));
             }
         }
+               if (ty.isParameterized()) {
+                       for (int i = 0; i < ty.typeParameters.length; i++) {
+                               ty.typeParameters[i] = resolve(ty.typeParameters[i],allowMissing);
+                       }
+               }
         //System.out.println("ret: " + ret);
         typeMap.put(signature, ret);
         return ret;
@@ -147,7 +152,14 @@ public abstract class World implements Dump.INode {
        return resolve(TypeX.forName(name));
     }
     protected final ResolvedTypeX resolveObjectType(TypeX ty) {
-       ResolvedTypeX.Name name = new ResolvedTypeX.Name(ty.getSignature(), this);
+               String signature = ty.getSignature();
+               if (signature.indexOf("<") != -1) {
+                       // extract the raw type...
+                       // XXX - might need to do more in the future to propagate full parameterized info...
+                       signature = signature.substring(0,signature.indexOf("<"));
+               }
+
+       ResolvedTypeX.Name name = new ResolvedTypeX.Name(signature, this);
        ResolvedTypeX.ConcreteName concreteName = resolveObjectType(name);
        if (concreteName == null) return ResolvedTypeX.MISSING;
        name.setDelegate(concreteName);
index 3219b2f150d05e42891b6904941b17fbf14462ce..1ba812845f646b58390022c4cc45fe25b1be0891 100644 (file)
@@ -61,6 +61,21 @@ public class TypeXTestCase extends TestCase {
        assertEquals(t.getOutermostType(), TypeX.forName("java.util.Map"));
        assertEquals(TypeX.forName("java.util.Map").getOutermostType(), TypeX.forName("java.util.Map"));
     }
+       
+       public void testNameAndSigWithParameters() {
+               TypeX t = TypeX.forName("java.util.List<java.lang.String>");
+               assertEquals(t.getName(),"java.util.List<java.lang.String>");
+               assertEquals(t.getSignature(),"Ljava/util/List<Ljava/lang/String;>;");
+               t = new TypeX("Ljava/util/List<Ljava/lang/String;>;");
+               assertEquals(t.getName(),"java.util.List<java.lang.String>");
+               assertEquals(t.getSignature(),"Ljava/util/List<Ljava/lang/String;>;");
+               t = TypeX.forName("java.util.Map<java.util.String,java.util.List<java.lang.Integer>>");
+               assertEquals(t.getName(),"java.util.Map<java.util.String,java.util.List<java.lang.Integer>>");
+               assertEquals(t.getSignature(),"Ljava/util/Map<Ljava/util/String;Ljava/util/List<Ljava/lang/Integer;>;>;");
+               t = new TypeX("Ljava/util/Map<Ljava/util/String;Ljava/util/List<Ljava/lang/Integer;>;>;");
+               assertEquals(t.getName(),"java.util.Map<java.util.String,java.util.List<java.lang.Integer>>");
+               assertEquals(t.getSignature(),"Ljava/util/Map<Ljava/util/String;Ljava/util/List<Ljava/lang/Integer;>;>;");
+       }
 
     private void isPrimitiveTest(TypeX[] types, boolean[] isPrimitives) {
         for (int i = 0, len = types.length; i < len; i++) {