]> source.dussan.org Git - aspectj.git/commitdiff
give back parameterized versions of members for parameterized types
authoracolyer <acolyer>
Fri, 8 Jul 2005 16:03:21 +0000 (16:03 +0000)
committeracolyer <acolyer>
Fri, 8 Jul 2005 16:03:21 +0000 (16:03 +0000)
weaver/src/org/aspectj/weaver/ReferenceType.java
weaver/src/org/aspectj/weaver/ResolvedMember.java
weaver/src/org/aspectj/weaver/ResolvedTypeX.java

index e541084b7df3bb7d0f0332ae1d0b433acbe84bea..6f922a005de8cebf55cc7cddc940bc4ee91017f8 100644 (file)
@@ -40,6 +40,12 @@ public class ReferenceType extends ResolvedTypeX {
        int startPos = 0;
        int endPos = 0;
 
+       // cached values for members
+       ResolvedMember[] parameterizedMethods = null;
+       ResolvedMember[] parameterizedFields = null;
+       ResolvedMember[] parameterizedPointcuts = null;
+       ResolvedTypeX[] parameterizedInterfaces = null;
+       
        //??? should set delegate before any use
     public ReferenceType(String signature, World world) {
         super(signature, world);
@@ -159,21 +165,65 @@ public class ReferenceType extends ResolvedTypeX {
        }
 
        public ResolvedMember[] getDeclaredFields() {
-               return delegate.getDeclaredFields();
+               if (parameterizedFields != null) return parameterizedFields;
+               if (isParameterized()) {
+                       ResolvedMember[] delegateFields = delegate.getDeclaredFields();
+                       parameterizedFields = new ResolvedMember[delegateFields.length];
+                       for (int i = 0; i < delegateFields.length; i++) {
+                               parameterizedFields[i] = delegateFields[i].parameterizedWith(getTypeParameters());
+                       }
+                       return parameterizedFields;
+               } else {
+                       return delegate.getDeclaredFields();
+               }
        }
 
        public ResolvedTypeX[] getDeclaredInterfaces() {
-               return delegate.getDeclaredInterfaces();
+               if (parameterizedInterfaces != null) return parameterizedInterfaces;
+               if (isParameterized()) {
+                       ResolvedTypeX[] delegateInterfaces = delegate.getDeclaredInterfaces();
+                       parameterizedInterfaces = new ResolvedTypeX[delegateInterfaces.length];
+                       for (int i = 0; i < delegateInterfaces.length; i++) {
+                               parameterizedInterfaces[i] = delegateInterfaces[i].parameterizedWith(getTypeParameters());
+                       }
+                       return parameterizedInterfaces;
+               } else {
+                       return delegate.getDeclaredInterfaces();
+               }
        }
 
        public ResolvedMember[] getDeclaredMethods() {
-               return delegate.getDeclaredMethods();
+               if (parameterizedMethods != null) return parameterizedMethods;
+               if (isParameterized()) {
+                       ResolvedMember[] delegateMethods = delegate.getDeclaredMethods();
+                       parameterizedMethods = new ResolvedMember[delegateMethods.length];
+                       for (int i = 0; i < delegateMethods.length; i++) {
+                               parameterizedMethods[i] = delegateMethods[i].parameterizedWith(getTypeParameters());
+                       }
+                       return parameterizedMethods;
+               } else {
+                       return delegate.getDeclaredMethods();
+               }
        }
 
        public ResolvedMember[] getDeclaredPointcuts() {
-               return delegate.getDeclaredPointcuts();
+               if (parameterizedPointcuts != null) return parameterizedPointcuts;
+               if (isParameterized()) {
+                       ResolvedMember[] delegatePointcuts = delegate.getDeclaredPointcuts();
+                       parameterizedPointcuts = new ResolvedMember[delegatePointcuts.length];
+                       for (int i = 0; i < delegatePointcuts.length; i++) {
+                               parameterizedPointcuts[i] = delegatePointcuts[i].parameterizedWith(getTypeParameters());
+                       }
+                       return parameterizedPointcuts;
+               } else {
+                       return delegate.getDeclaredPointcuts();
+               }
        }
 
+       public TypeVariable[] getTypeVariables() {
+               return delegate.getTypeVariables();
+       }
+       
        public PerClause getPerClause() { return delegate.getPerClause(); }
        protected Collection getDeclares() { return delegate.getDeclares(); }
        protected Collection getTypeMungers() { return delegate.getTypeMungers(); }
@@ -196,8 +246,16 @@ public class ReferenceType extends ResolvedTypeX {
 
        public void setDelegate(ReferenceTypeDelegate delegate) {
                this.delegate = delegate;
+               clearParameterizationCaches();
        }
     
+       private void clearParameterizationCaches() {
+               parameterizedFields = null;
+               parameterizedInterfaces = null;
+               parameterizedMethods = null;
+               parameterizedPointcuts = null;
+       }
+
        public int getEndPos() {
                return endPos;
        }
index 64f6d0e974ad6c1d7ef0a4a24cad5250dd3e6f82..4af534b164450f9318fc4564d14ffd9f4bcd551e 100644 (file)
@@ -17,8 +17,10 @@ import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.lang.reflect.Modifier;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
 import org.aspectj.bridge.ISourceLocation;
@@ -294,5 +296,62 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
        public boolean isAnnotatedElsewhere() {
                return isAnnotatedElsewhere;
        }
+       
+       /**
+        * Get the TypeX for the return type, taking generic signature into account
+        */
+       public TypeX getGenericReturnType() {
+               return getReturnType();
+       }
+       
+       /**
+        * Get the TypeXs of the parameter types, taking generic signature into account
+        */
+       public TypeX[] getGenericParameterTypes() {
+               return getParameterTypes();
+       }
+       
+       // return a resolved member in which all type variables in the signature of this
+       // member have been replaced with the given bindings.
+       public ResolvedMember parameterizedWith(TypeX[] typeParameters) {
+               if (!this.getDeclaringType().isGeneric()) {
+                       throw new IllegalStateException("Can't ask to parameterize a member of a non-generic type");
+               }
+               TypeVariable[] typeVariables = getDeclaringType().getTypeVariables();
+               if (typeVariables.length != typeParameters.length) {
+                       throw new IllegalStateException("Wrong number of type parameters supplied");
+               }
+               Map typeMap = new HashMap();
+               for (int i = 0; i < typeVariables.length; i++) {
+                       typeMap.put(typeVariables[i].getName(), typeParameters[i]);
+               }
+               TypeX parameterizedReturnType = parameterize(getGenericReturnType(),typeMap);
+               TypeX[] parameterizedParameterTypes = new TypeX[getGenericParameterTypes().length];
+               for (int i = 0; i < parameterizedParameterTypes.length; i++) {
+                       parameterizedParameterTypes[i] = 
+                               parameterize(getGenericParameterTypes()[i], typeMap);
+               }
+               return new ResolvedMember(
+                                       getKind(),
+                                       getDeclaringType(),
+                                       getModifiers(),
+                                       parameterizedReturnType,
+                                       getName(),
+                                       parameterizedParameterTypes,
+                                       getExceptions()
+                               );
+       }
+       
+       private TypeX parameterize(TypeX aType, Map typeVariableMap) {
+               if (aType instanceof TypeVariableReferenceType) {
+                       String variableName = ((TypeVariableReferenceType)aType).getTypeVariable().getName();
+                       if (!typeVariableMap.containsKey(variableName)) {
+                               throw new IllegalStateException("Type variable " + variableName + " not bound in type map");
+                       }
+                       return (TypeX) typeVariableMap.get(variableName);
+               } else {
+                       return aType;
+               }
+       }
 }
    
index 77afa2c38f3ca18e676b80a41185b1fd78de037b..b183a95adda32950ab8a775a500ad9c88a803f45 100644 (file)
@@ -328,10 +328,31 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
 
         // If they aren't the same, we need to allow for covariance ... where one sig might be ()LCar; and 
         // the subsig might be ()LFastCar; - where FastCar is a subclass of Car
-        boolean equalParamSignatures = m1.getParameterSignature().equals(m2.getParameterSignature());
-        return equalParamSignatures;
+        boolean equalCovariantSignatures = m1.getParameterSignature().equals(m2.getParameterSignature());
+        if (equalCovariantSignatures) return true;
+        
+        // If they aren't the same, we need to allow for generics... where one sig might be a parameterization
+        // of another sig.
+        if (m1.canBeParameterized()) {
+               boolean m2MatchesParameterizationOfm1 =
+                       matchesGenericMethod(m1,m2);  
+               if (m2MatchesParameterizationOfm1) return true;
+        } 
+        if (m2.canBeParameterized()) {
+               boolean m1MatchesParameterizationOfm2 =
+                       matchesGenericMethod(m2,m1);
+               if (m1MatchesParameterizationOfm2) return true;
+        }
+        return false;
     }
     
+    /**
+     * This method is only called from matches(m1,m2)
+     * We know that the names match, but that's it.
+     */
+    private static boolean matchesGenericMethod(Member aGenericMember, Member possibleParameterizationMember) {
+       return false;
+    }
     
     public static boolean conflictingSignature(Member m1, Member m2) {
        if (m1 == null || m2 == null) return false;
@@ -1422,4 +1443,7 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
                return null;
        }
 
+       public ResolvedTypeX parameterizedWith(TypeX[] typeParameters) {
+               return this;
+       }
 }