]> source.dussan.org Git - aspectj.git/commitdiff
parameterized members remember their erasure and this is used in member matching...
authoracolyer <acolyer>
Tue, 12 Jul 2005 11:09:22 +0000 (11:09 +0000)
committeracolyer <acolyer>
Tue, 12 Jul 2005 11:09:22 +0000 (11:09 +0000)
weaver/src/org/aspectj/weaver/Member.java
weaver/src/org/aspectj/weaver/ResolvedMember.java
weaver/src/org/aspectj/weaver/ResolvedTypeX.java
weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java

index 20d9e62231b2247a4cfb85d53acfc5b8edcb0199..9fe5a35a72e579aa164d70d4db7a64ca24175dd5 100644 (file)
@@ -607,6 +607,10 @@ public class Member implements Comparable, AnnotatedElement {
                        b |= walkUp(acc, (ResolvedTypeX)i.next());
                }
                
+               if (!b && curr.isParameterized()) {
+                       b = walkUp(acc,curr.getGenericType());
+               }
+               
                if (!b) {
                        b = curr.lookupMemberNoSupers(this) != null;
                } 
@@ -623,6 +627,9 @@ public class Member implements Comparable, AnnotatedElement {
                        for (Iterator i = curr.getDirectSupertypes(); i.hasNext(); ) {
                                b |= walkUpStatic(acc, (ResolvedTypeX)i.next());
                        }
+                       if (!b && curr.isParameterized()) {
+                               b = walkUpStatic(acc,curr.getGenericType());
+                       }
                        if (b) acc.add(curr);
                        return b;
                }
index cd033478061a33f039c5d9552e0e262a2e627ce4..77bc6e933ed30da37ae5da91fd9b9cb6f147a267 100644 (file)
@@ -17,6 +17,7 @@ import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.lang.reflect.Modifier;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -33,6 +34,11 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
     
     public String[] parameterNames = null;
     protected TypeX[] checkedExceptions = TypeX.NONE;
+    /**
+     * if this member is a parameterized version of a member in a generic type,
+     * then this field holds a reference to the member we parameterize.
+     */
+    protected ResolvedMember backingGenericMember = null;
     private Set annotationTypes = null;
        // Some members are 'created' to represent other things (for example ITDs).  These
        // members have their annotations stored elsewhere, and this flag indicates that is
@@ -72,6 +78,20 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
                this.checkedExceptions = checkedExceptions;
        }
     
+       public ResolvedMember(
+                       Kind kind,
+                       TypeX declaringType,
+                       int modifiers,
+                       TypeX returnType,
+                       String name,
+                       TypeX[] parameterTypes,
+                       TypeX[] checkedExceptions,
+                       ResolvedMember backingGenericMember) 
+               {
+                       this(kind, declaringType, modifiers, returnType, name, parameterTypes,checkedExceptions);
+                       this.backingGenericMember = backingGenericMember;
+               }
+       
        public ResolvedMember(
                Kind kind,
                TypeX declaringType,
@@ -338,7 +358,8 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
                                        parameterizedReturnType,
                                        getName(),
                                        parameterizedParameterTypes,
-                                       getExceptions()
+                                       getExceptions(),
+                                       this
                                );
        }
        
@@ -353,5 +374,49 @@ public class ResolvedMember extends Member implements IHasPosition, AnnotatedEle
                        return aType;
                }
        }
+       
+       
+       /**
+        * If this member is defined by a parameterized super-type, return the erasure
+        * of that member.
+        * For example:
+        * interface I<T> { T foo(T aTea); }
+        * class C implements I<String> {
+        *   String foo(String aString) { return "something"; }
+        * }
+        * The resolved member for C.foo has signature String foo(String). The
+        * erasure of that member is Object foo(Object)  -- use upper bound of type
+        * variable.
+        * A type is a supertype of itself.
+        */
+       public ResolvedMember getErasure() {
+               if (calculatedMyErasure) return myErasure;
+               calculatedMyErasure = true;
+               ResolvedTypeX resolvedDeclaringType = (ResolvedTypeX) getDeclaringType();
+               // this next test is fast, and the result is cached.
+               if (!resolvedDeclaringType.hasParameterizedSuperType()) {
+                       return null;
+               } else {
+                       // we have one or more parameterized super types.
+                       // this member may be defined by one of them... we need to find out.
+                       Collection declaringTypes = this.getDeclaringTypes(resolvedDeclaringType.getWorld());
+                       for (Iterator iter = declaringTypes.iterator(); iter.hasNext();) {
+                               ResolvedTypeX aDeclaringType = (ResolvedTypeX) iter.next();
+                               if (aDeclaringType.isParameterized()) {
+                                       // we've found the (a?) parameterized type that defines this member.
+                                       // now get the erasure of it
+                                       ResolvedMember matchingMember = aDeclaringType.lookupMemberNoSupers(this);
+                                       if (matchingMember != null && matchingMember.backingGenericMember != null) {
+                                               myErasure = matchingMember.backingGenericMember;
+                                               return myErasure;
+                                       }
+                               }
+                       }
+               }
+               return null;
+       }
+       
+       private ResolvedMember myErasure = null;
+       private boolean calculatedMyErasure = false;
 }
    
index b183a95adda32950ab8a775a500ad9c88a803f45..752cba7a24a61f8dfaade4ce4bee0793d8fa68ce 100644 (file)
@@ -331,29 +331,9 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
         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;
        
@@ -1446,4 +1426,36 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
        public ResolvedTypeX parameterizedWith(TypeX[] typeParameters) {
                return this;
        }
+       
+       public boolean hasParameterizedSuperType() {
+               getParameterizedSuperTypes();
+               return parameterizedSuperTypes.length > 0;
+       }
+       
+       private ResolvedTypeX[] parameterizedSuperTypes = null;
+       /**
+        * Similar to the above method, but accumulates the super types
+        * @return
+        */
+       public ResolvedTypeX[] getParameterizedSuperTypes() {
+               if (parameterizedSuperTypes != null) return parameterizedSuperTypes;
+               List accumulatedTypes = new ArrayList();
+               accumulateParameterizedSuperTypes(this,accumulatedTypes);
+               ResolvedTypeX[] ret = new ResolvedTypeX[accumulatedTypes.size()];
+               parameterizedSuperTypes = (ResolvedTypeX[]) accumulatedTypes.toArray(ret);
+               return parameterizedSuperTypes;
+       }
+       
+       private void accumulateParameterizedSuperTypes(ResolvedTypeX forType, List parameterizedTypeList) {
+               if (forType.isParameterized()) {
+                       parameterizedTypeList.add(forType);
+               }
+               if (forType.getSuperclass() != null) {
+                       accumulateParameterizedSuperTypes(forType.getSuperclass(), parameterizedTypeList);
+               }
+               ResolvedTypeX[] interfaces = forType.getDeclaredInterfaces();
+               for (int i = 0; i < interfaces.length; i++) {
+                       accumulateParameterizedSuperTypes(interfaces[i], parameterizedTypeList);
+               }
+       }
 }
index 012d7c99ac60779457ec17979010999075fa296b..c981aa79850d1181037b370da0c5ffd8660543e4 100644 (file)
@@ -222,8 +222,27 @@ public class SignaturePattern extends PatternNode {
                        if (!name.matches(sig.getName())) return false;
                        
                        // Check the parameters
-                       if (!parameterTypes.matches(world.resolve(sig.getParameterTypes()), TypePattern.STATIC).alwaysTrue()) {
-                               return false;
+                       // AMC parameterized types make this more complex. Suppose I have a 
+               // type that implements a parameterized interface. It might declare a method
+                       // foo(Double). If foo is defined in I<T> and the type implements I<Double>,
+                       // then the signature pattern I.foo(Object) (the erasure) *should* match.
+                       // But [Object] does not match [Double] so we have some work to do...
+                       ResolvedTypeX[] resolvedParameters = world.resolve(sig.getParameterTypes());
+                       if (!parameterTypes.matches(resolvedParameters, TypePattern.STATIC).alwaysTrue()) {
+                               // It could still be a match based on the erasure of a parameterized type
+                               // method in our hierarchy.
+                               // We need to find out as cheaply as possible.
+                               ResolvedMember sigErasure = sig.getErasure();
+                               if (sigErasure != null) {
+                                       ResolvedTypeX[] erasureParameters = world.resolve(sigErasure.getParameterTypes());
+                                       if (!parameterTypes.matches(erasureParameters,TypePattern.STATIC).alwaysTrue()) {
+                                               // fail if we don't match the erasure either
+                                               return false;
+                                       } 
+                               } else {
+                                       // fail if there is no erasure as the params don't match
+                                       return false;
+                               }
                        }
                        
                        // If we have matched on parameters, let's just check it isn't because the last parameter in the pattern