From 3ee4abe289e3a701080057fd79805f8be1115646 Mon Sep 17 00:00:00 2001 From: acolyer Date: Fri, 8 Jul 2005 16:03:21 +0000 Subject: [PATCH] give back parameterized versions of members for parameterized types --- .../src/org/aspectj/weaver/ReferenceType.java | 66 +++++++++++++++++-- .../org/aspectj/weaver/ResolvedMember.java | 59 +++++++++++++++++ .../src/org/aspectj/weaver/ResolvedTypeX.java | 28 +++++++- 3 files changed, 147 insertions(+), 6 deletions(-) diff --git a/weaver/src/org/aspectj/weaver/ReferenceType.java b/weaver/src/org/aspectj/weaver/ReferenceType.java index e541084b7..6f922a005 100644 --- a/weaver/src/org/aspectj/weaver/ReferenceType.java +++ b/weaver/src/org/aspectj/weaver/ReferenceType.java @@ -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; } diff --git a/weaver/src/org/aspectj/weaver/ResolvedMember.java b/weaver/src/org/aspectj/weaver/ResolvedMember.java index 64f6d0e97..4af534b16 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedMember.java +++ b/weaver/src/org/aspectj/weaver/ResolvedMember.java @@ -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; + } + } } diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeX.java b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java index 77afa2c38..b183a95ad 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedTypeX.java +++ b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java @@ -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; + } } -- 2.39.5