]> source.dussan.org Git - aspectj.git/commitdiff
fixes and improved tests for 117622
authoraclement <aclement>
Fri, 25 Nov 2005 09:39:43 +0000 (09:39 +0000)
committeraclement <aclement>
Fri, 25 Nov 2005 09:39:43 +0000 (09:39 +0000)
weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java
weaver/src/org/aspectj/weaver/World.java
weaver/testsrc/BcweaverModuleTests15.java
weaver5/java5-src/org/aspectj/weaver/reflect/Java15ReflectionBasedReferenceTypeDelegate.java
weaver5/java5-testsrc/org/aspectj/weaver/TestJava5ReflectionBasedReferenceTypeDelegate.java

index 4a3d6ebc8943c02df687838bcd415ec65e4cb6a4..dbc48f1255f75a24c0a9d325f628a14b3e26d13c 100644 (file)
@@ -602,7 +602,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno
        public ResolvedMemberImpl parameterizedWith(UnresolvedType[] typeParameters,ResolvedType newDeclaringType, boolean isParameterized,List aliases) {
                if (//isParameterized &&  <-- might need this bit...
                                !getDeclaringType().isGenericType()) {
-                       throw new IllegalStateException("Can't ask to parameterize a member of a non-generic type");
+                       throw new IllegalStateException("Can't ask to parameterize a member of non-generic type: "+getDeclaringType()+"  kind("+getDeclaringType().typeKind+")");
                }
                TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
                if (isParameterized && (typeVariables.length != typeParameters.length)) {
index d5df39a19cebfcaa78395af25546342c7961d436..31db56be9308b2ec92272c6c9e4f6adccf5ac99b 100644 (file)
@@ -23,7 +23,6 @@ import java.util.Set;
 import java.util.WeakHashMap;
 
 import org.aspectj.asm.IHierarchy;
-import org.aspectj.bridge.IMessage;
 import org.aspectj.bridge.IMessageHandler;
 import org.aspectj.bridge.ISourceLocation;
 import org.aspectj.bridge.Message;
@@ -50,6 +49,7 @@ public abstract class World implements Dump.INode {
        
        /** The heart of the world, a map from type signatures to resolved types */
     protected TypeMap typeMap = new TypeMap(); // Signature to ResolvedType
+    
 
     /** Calculator for working out aspect precedence */
     private AspectPrecedenceCalculator precedenceCalculator;
@@ -831,5 +831,23 @@ public abstract class World implements Dump.INode {
        }
 
        public void validateType(UnresolvedType type) { }
+
+    // --- with java5 we can get into a recursive mess if we aren't careful when resolving types (*cough* java.lang.Enum) ---
+       
+    // --- this first map is for java15 delegates which may try and recursively access the same type variables.
+       // --- I would rather stash this against a reference type - but we don't guarantee referencetypes are unique for
+       //     so we can't :(
+       private Map workInProgress1 = new HashMap();
+       public TypeVariable[] getTypeVariablesCurrentlyBeingProcessed(Class baseClass) {
+               return (TypeVariable[])workInProgress1.get(baseClass);
+       }
+       public void recordTypeVariablesCurrentlyBeingProcessed(Class baseClass, TypeVariable[] typeVariables) {
+               workInProgress1.put(baseClass,typeVariables);
+       }
+       public void forgetTypeVariablesCurrentlyBeingProcessed(Class baseClass) {
+               workInProgress1.remove(baseClass);
+       }
+
+    // ---
        
 }
index 7523fb85b825f448140038774f453598a9f059dc..55f118d3c24805097d4e4b7acb3b38b9dc7b4d2d 100644 (file)
@@ -35,6 +35,7 @@ public class BcweaverModuleTests15 extends TestCase {
                suite.addTestSuite(WildTypePatternResolutionTestCase.class);
                if (LangUtil.is15VMOrGreater()) {
                    TestUtil.loadTestsReflectively(suite, "org.aspectj.weaver.tools.Java15PointcutExpressionTest", false);
+                   TestUtil.loadTestsReflectively(suite, "org.aspectj.weaver.TestJava5ReflectionBasedReferenceTypeDelegate", false);
                }
                return suite;
            }
index 47f4918ccb434aa8b3708b141a440a12b286ef5f..a26fc6252a6e8cca85d3a5e115b485366fefe011 100644 (file)
@@ -20,6 +20,8 @@ import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.lang.reflect.WildcardType;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.reflect.AjType;
@@ -133,13 +135,33 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
                 return superclass;
        }
        
+       
        public TypeVariable[] getTypeVariables() {
+               TypeVariable[] workInProgressSetOfVariables = (TypeVariable[])getResolvedTypeX().getWorld().getTypeVariablesCurrentlyBeingProcessed(getBaseClass());
+               if (workInProgressSetOfVariables!=null) {
+                       return workInProgressSetOfVariables;
+               }
                if (this.typeVariables == null) {
                        java.lang.reflect.TypeVariable[] tVars = this.getBaseClass().getTypeParameters();
                        this.typeVariables = new TypeVariable[tVars.length];
+                       // basic initialization
+                       for (int i = 0; i < tVars.length; i++) {
+                               typeVariables[i] = new TypeVariable(tVars[i].getName());
+                       }
+                       // stash it
+                       this.getResolvedTypeX().getWorld().recordTypeVariablesCurrentlyBeingProcessed(getBaseClass(),typeVariables);
+                       // now fill in the details...
                        for (int i = 0; i < tVars.length; i++) {
-                               this.typeVariables[i] = ((TypeVariableReferenceType) fromType(tVars[i])).getTypeVariable();
+                               TypeVariableReferenceType tvrt = ((TypeVariableReferenceType) fromType(tVars[i]));
+                               TypeVariable tv = tvrt.getTypeVariable();
+                               typeVariables[i].setUpperBound(tv.getUpperBound());
+                               typeVariables[i].setAdditionalInterfaceBounds(tv.getAdditionalInterfaceBounds());
+                               typeVariables[i].setDeclaringElement(tv.getDeclaringElement());
+                               typeVariables[i].setDeclaringElementKind(tv.getDeclaringElementKind());
+                               typeVariables[i].setRank(tv.getRank());
+                               typeVariables[i].setLowerBound(tv.getLowerBound());
                        }
+                       this.getResolvedTypeX().getWorld().forgetTypeVariablesCurrentlyBeingProcessed(getBaseClass());
                }               
                return this.typeVariables;
        }
@@ -162,10 +184,19 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
                return methods;
        }
        
+       /**
+        * Returns the generic type, regardless of the resolvedType we 'know about'
+        */
+       public ResolvedType getGenericResolvedType() {
+               ResolvedType rt = getResolvedTypeX();
+               if (rt.isParameterizedType() || rt.isRawType()) return rt.getGenericType();
+               return rt;
+       }
+       
        private ResolvedMember createGenericMethodMember(Method forMethod) {
                ReflectionBasedResolvedMemberImpl ret = 
                new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.METHOD,
-                       getResolvedTypeX(),
+                       getGenericResolvedType(),
                        forMethod.getModifiers(),
                        fromType(forMethod.getGenericReturnType()),
                        forMethod.getName(),
@@ -180,9 +211,9 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
        private ResolvedMember createGenericConstructorMember(Constructor forConstructor) {
                ReflectionBasedResolvedMemberImpl ret = 
                new ReflectionBasedResolvedMemberImpl(org.aspectj.weaver.Member.METHOD,
-                       getResolvedTypeX(),
+                       getGenericResolvedType(),
                        forConstructor.getModifiers(),
-                       getResolvedTypeX(),
+                       getGenericResolvedType(),
                        "init",
                        fromTypes(forConstructor.getGenericParameterTypes()),
                        fromTypes(forConstructor.getGenericExceptionTypes()),
@@ -196,7 +227,7 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
                ReflectionBasedResolvedMemberImpl ret =
                        new ReflectionBasedResolvedMemberImpl(
                                org.aspectj.weaver.Member.FIELD,
-                               getResolvedTypeX(),
+                               getGenericResolvedType(),
                                forField.getModifiers(),
                                fromType(forField.getGenericType()),
                                forField.getName(),
@@ -266,6 +297,9 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
                return getBaseClass().getTypeParameters().length > 0;
        }
        
+       // Used to prevent recursion - we record what we are working on and return it if asked again *whilst* working on it
+       private Map /*java.lang.reflect.TypeVariable > TypeVariableReferenceType */typeVariablesInProgress = new HashMap();
+       
        private ResolvedType fromType(Type aType) {
                if (aType instanceof Class) {
                        Class clazz = (Class)aType;
@@ -293,7 +327,15 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
                        ResolvedType[] resolvedArgs = fromTypes(args);
                        return TypeFactory.createParameterizedType(baseType, resolvedArgs, getWorld());
                } else if (aType instanceof java.lang.reflect.TypeVariable) {
+                       if (typeVariablesInProgress.get(aType)!=null) // check if we are already working on this type
+                               return (TypeVariableReferenceType)typeVariablesInProgress.get(aType);
+
                        java.lang.reflect.TypeVariable tv = (java.lang.reflect.TypeVariable) aType;
+                       TypeVariable rt_tv = new TypeVariable(tv.getName());
+                       TypeVariableReferenceType tvrt = new TypeVariableReferenceType(rt_tv,getWorld());
+                       
+                       typeVariablesInProgress.put(aType,tvrt); // record what we are working on, for recursion case
+                       
                        Type[] bounds = tv.getBounds();
                        ResolvedType[] resBounds = fromTypes(bounds);
                        ResolvedType upperBound = resBounds[0];
@@ -302,8 +344,12 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
                                additionalBounds = new ResolvedType[resBounds.length - 1];
                                System.arraycopy(resBounds,1,additionalBounds,0,additionalBounds.length);
                        }
-                       TypeVariable rt_tv = new TypeVariable(tv.getName(),upperBound,additionalBounds);
-                       return new TypeVariableReferenceType(rt_tv,getWorld());
+                       rt_tv.setUpperBound(upperBound);
+                       rt_tv.setAdditionalInterfaceBounds(additionalBounds);
+                       
+                       typeVariablesInProgress.remove(aType); // we have finished working on it
+                       
+                       return tvrt;
                } else if (aType instanceof WildcardType) {
                        WildcardType wildType = (WildcardType) aType;
                        Type[] lowerBounds = wildType.getLowerBounds();
@@ -319,7 +365,7 @@ public class Java15ReflectionBasedReferenceTypeDelegate extends
                } else if (aType instanceof GenericArrayType) {
                        GenericArrayType gt = (GenericArrayType) aType;
                        Type componentType = gt.getGenericComponentType();
-                       UnresolvedType.makeArray(fromType(componentType),1);
+                       return UnresolvedType.makeArray(fromType(componentType),1).resolve(getWorld());
                }
                return ResolvedType.MISSING;
        }
index 450d00c6dbd5f45c15800903ec82d43b6f7fbd3e..aadfd525b08b0ea7d8e98f82b124058da2f3f257 100644 (file)
@@ -4,22 +4,35 @@ import org.aspectj.weaver.reflect.ReflectionBasedReferenceTypeDelegateTest;
 
 public class TestJava5ReflectionBasedReferenceTypeDelegate extends ReflectionBasedReferenceTypeDelegateTest {
        
+       /**
+        * Let's play about with a generic type and ensure we can work with it in a reflective world.
+        */
        public void testResolveGeneric() {
-               UnresolvedType collectionType = UnresolvedType.forName("java.util.Collection<E>");
-//             ResolvedType rt= world.resolve(collectionType);
-//             ResolvedMember[] methods = world.resolve(collectionType).getDeclaredMethods();
-//             assertTrue(findMethod("toArray", methods) != -1);               
+               UnresolvedType collectionType = UnresolvedType.forName("java.util.Collection");
+               ResolvedType rt= world.resolve(collectionType).getRawType().resolve(world);
+               ResolvedMember[] methods = world.resolve(collectionType).getDeclaredMethods();
+               int i = findMethod("toArray", methods);
+               assertTrue("Couldn't find 'toArray' in the set of methods? "+methods,i != -1);
+               String expectedSignature = "T[] java.util.Collection.toArray(T[])";
+               assertTrue("Expected signature of '"+expectedSignature+"' but it was '"+methods[i],methods[i].toString().equals(expectedSignature));
+       }
+
+       /**
+        * Can we resolve the dreaded Enum type...
+        */
+       public void testResolveEnum() {
+               ResolvedType enumType = world.resolve("java.lang.Enum");
+               assertTrue("Should be the raw type but is "+enumType.typeKind,enumType.isRawType());
+               ResolvedType theGenericEnumType = enumType.getGenericType();
+               assertTrue("Should have a type variable ",theGenericEnumType.getTypeVariables().length>0);
+               TypeVariable tv = theGenericEnumType.getTypeVariables()[0];
+               String expected = "TypeVar E extends java.lang.Enum<E>";
+               assertTrue("Type variable should be '"+expected+"' but is '"+tv+"'",tv.toString().equals(expected));
        }
        
        public void testResolveClass() {
-               //stack overflow
-               world.resolve("java.lang.Class");               
+               world.resolve("java.lang.Class").getGenericType();              
        }
        
-       // just here to override the super one so it doesnt run in this case ;)
-       public void testGetDeclaredMethods() {
-               
-       }
-
-
+       
 }