diff options
author | acolyer <acolyer> | 2005-08-09 12:57:56 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2005-08-09 12:57:56 +0000 |
commit | 23c9276e9c021d686376e57ae8cd255eeed5853c (patch) | |
tree | bfdccc2deebf6acdd449d9955590caffaa731f56 | |
parent | b071637d68f41a406ab00f15bbd6d729a5545763 (diff) | |
download | aspectj-23c9276e9c021d686376e57ae8cd255eeed5853c.tar.gz aspectj-23c9276e9c021d686376e57ae8cd255eeed5853c.zip |
support for coercion testing with parameterized types
-rw-r--r-- | weaver/src/org/aspectj/weaver/ReferenceType.java | 90 |
1 files changed, 88 insertions, 2 deletions
diff --git a/weaver/src/org/aspectj/weaver/ReferenceType.java b/weaver/src/org/aspectj/weaver/ReferenceType.java index fc2069a1a..28e11519f 100644 --- a/weaver/src/org/aspectj/weaver/ReferenceType.java +++ b/weaver/src/org/aspectj/weaver/ReferenceType.java @@ -146,12 +146,18 @@ public class ReferenceType extends ResolvedType { return delegate.isAnnotationWithRuntimeRetention(); } + // true iff the statement "this = (ThisType) other" would compile public final boolean isCoerceableFrom(ResolvedType o) { ResolvedType other = o.resolve(world); if (this.isAssignableFrom(other) || other.isAssignableFrom(this)) { return true; } + + if (this.isParameterizedType() && other.isParameterizedType()) { + return isCoerceableFromParameterizedType(other); + } + if (!this.isInterface() && !other.isInterface()) { return false; } @@ -169,12 +175,92 @@ public class ReferenceType extends ResolvedType { return true; } + private final boolean isCoerceableFromParameterizedType(ResolvedType other) { + if (!other.isParameterizedType()) return false; + ResolvedType myRawType = (ResolvedType) getRawType(); + ResolvedType theirRawType = (ResolvedType) other.getRawType(); + if (myRawType == theirRawType) { + if (getTypeParameters().length == other.getTypeParameters().length) { + // there's a chance it can be done + ResolvedType[] myTypeParameters = getResolvedTypeParameters(); + ResolvedType[] theirTypeParameters = other.getResolvedTypeParameters(); + for (int i = 0; i < myTypeParameters.length; i++) { + if (myTypeParameters[i] != theirTypeParameters[i]) { + // thin ice now... but List<String> may still be coerceable from e.g. List<T> + if (myTypeParameters[i].isGenericWildcard()) { + BoundedReferenceType wildcard = (BoundedReferenceType) myTypeParameters[i]; + if (!wildcard.canBeCoercedTo(theirTypeParameters[i])) return false; + } else if (myTypeParameters[i].isTypeVariableReference()) { + TypeVariableReferenceType tvrt = (TypeVariableReferenceType) myTypeParameters[i]; + TypeVariable tv = tvrt.getTypeVariable(); + tv.resolve(world); + if (!tv.canBeBoundTo(theirTypeParameters[i])) return false; + } else { + return false; + } + } + } + return true; + } + } else { + // we do this walk for situations like the following: + // Base<T>, Sub<S,T> extends Base<S> + // is Sub<Y,Z> coerceable from Base<X> ??? + for(Iterator i = getDirectSupertypes(); i.hasNext(); ) { + ReferenceType parent = (ReferenceType) i.next(); + if (parent.isCoerceableFromParameterizedType(other)) return true; + } + } + return false; + } + + // true iff the statement "this = other" would compile. public final boolean isAssignableFrom(ResolvedType other) { if (other.isPrimitiveType()) { if (!world.isInJava5Mode()) return false; if (ResolvedType.validBoxing.contains(this.getSignature()+other.getSignature())) return true; } if (this == other) return true; + + if (this.isRawType() && other.isParameterizedType()) { + if (isAssignableFrom((ResolvedType)other.getRawType())) return true; + } + + if (this.isParameterizedType()) { + // look at wildcards... + if (((ReferenceType)this.getRawType()).isAssignableFrom(other)) { + boolean wildcardsAllTheWay = true; + ResolvedType[] myParameters = this.getResolvedTypeParameters(); + for (int i = 0; i < myParameters.length; i++) { + if (!myParameters[i].isGenericWildcard()) { + wildcardsAllTheWay = false; + } else if (myParameters[i].isExtends() || myParameters[i].isSuper()) { + wildcardsAllTheWay = false; + } + } + if (wildcardsAllTheWay && !other.isParameterizedType()) return true; + // we have to match by parameters one at a time + ResolvedType[] theirParameters = other.getResolvedTypeParameters(); + boolean parametersAssignable = true; + if (myParameters.length == theirParameters.length) { + for (int i = 0; i < myParameters.length; i++) { + if (myParameters[i] == theirParameters[i]) continue; + if (!myParameters[i].isGenericWildcard()) { + parametersAssignable = false; + break; + } else { + BoundedReferenceType wildcardType = (BoundedReferenceType) myParameters[i]; + if (!wildcardType.alwaysMatches(theirParameters[i])) { + parametersAssignable = false; + break; + } + } + } + } + if (parametersAssignable) return true; + } + } + for(Iterator i = other.getDirectSupertypes(); i.hasNext(); ) { if (this.isAssignableFrom((ResolvedType) i.next())) return true; } @@ -257,7 +343,7 @@ public class ReferenceType extends ResolvedType { UnresolvedType[] parameters = getTypesForMemberParameterization(); parameterizedMethods = new ResolvedMember[delegateMethods.length]; for (int i = 0; i < delegateMethods.length; i++) { - parameterizedMethods[i] = delegateMethods[i].parameterizedWith(parameters,this,isRawType()); + parameterizedMethods[i] = delegateMethods[i].parameterizedWith(parameters,this,isParameterizedType()); } return parameterizedMethods; } else { @@ -271,7 +357,7 @@ public class ReferenceType extends ResolvedType { ResolvedMember[] delegatePointcuts = delegate.getDeclaredPointcuts(); parameterizedPointcuts = new ResolvedMember[delegatePointcuts.length]; for (int i = 0; i < delegatePointcuts.length; i++) { - parameterizedPointcuts[i] = delegatePointcuts[i].parameterizedWith(getTypesForMemberParameterization(),this,isRawType()); + parameterizedPointcuts[i] = delegatePointcuts[i].parameterizedWith(getTypesForMemberParameterization(),this,isParameterizedType()); } return parameterizedPointcuts; } else { |