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);
}
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(); }
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;
}
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;
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;
+ }
+ }
}
// 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;
return null;
}
+ public ResolvedTypeX parameterizedWith(TypeX[] typeParameters) {
+ return this;
+ }
}