diff options
author | aclement <aclement> | 2005-08-04 16:11:03 +0000 |
---|---|---|
committer | aclement <aclement> | 2005-08-04 16:11:03 +0000 |
commit | 900a3e81d5b09c55e4044451f311f0566c025ec6 (patch) | |
tree | 6c1f9e5e84d9edb9fb8f8728a8a701555b10db75 /weaver | |
parent | a26f850c10f1790682ff9d1f13a4f8d5253f5e71 (diff) | |
download | aspectj-900a3e81d5b09c55e4044451f311f0566c025ec6.tar.gz aspectj-900a3e81d5b09c55e4044451f311f0566c025ec6.zip |
genericitds: lots of new support for recursive type variables and ITD ctors.
Diffstat (limited to 'weaver')
10 files changed, 138 insertions, 35 deletions
diff --git a/weaver/src/org/aspectj/weaver/BoundedReferenceType.java b/weaver/src/org/aspectj/weaver/BoundedReferenceType.java index dfb8efc30..48ec7f927 100644 --- a/weaver/src/org/aspectj/weaver/BoundedReferenceType.java +++ b/weaver/src/org/aspectj/weaver/BoundedReferenceType.java @@ -19,17 +19,23 @@ import org.aspectj.weaver.patterns.PerClause; /** * A BoundedReferenceType is the result of a generics wildcard expression * ? extends String, ? super Foo etc.. + * * The "signature" for a bounded reference type follows the generic signature - * specification in section 4.4 of JVM spec: *,+,- plus signature strings + * specification in section 4.4 of JVM spec: *,+,- plus signature strings. + * + * The bound may be a type variable (e.g. ? super T) */ public class BoundedReferenceType extends ReferenceType { + protected ReferenceType[] additionalInterfaceBounds = new ReferenceType[0]; + protected boolean isExtends = true; - protected boolean isSuper = false; + protected boolean isSuper = false; public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world) { super((isExtends ? "+" : "-") + aBound.signature,world); - this.isExtends = isExtends; this.isSuper=!isExtends; + this.isExtends = isExtends; + this.isSuper = !isExtends; if (isExtends) { setUpperBound(aBound); } else { @@ -38,7 +44,7 @@ public class BoundedReferenceType extends ReferenceType { } setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)getUpperBound())); } - + public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world, ReferenceType[] additionalInterfaces) { this(aBound,isExtends,world); this.additionalInterfaceBounds = additionalInterfaces; @@ -51,20 +57,22 @@ public class BoundedReferenceType extends ReferenceType { /** * only for use when resolving GenericsWildcardTypeX or a TypeVariableReferenceType */ - BoundedReferenceType(String sig, World world) { + protected BoundedReferenceType(String sig, World world) { super(sig,world); setUpperBound(world.resolve(UnresolvedType.OBJECT)); setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)getUpperBound())); } - public ReferenceType[] getInterfaceBounds() { return additionalInterfaceBounds; } + public ReferenceType[] getInterfaceBounds() { + return additionalInterfaceBounds; + } public boolean hasLowerBound() { return getLowerBound() != null; } public boolean isExtends() { return isExtends; } - public boolean isSuper() { return isSuper; } + public boolean isSuper() { return isSuper; } // override to include additional interface bounds... public ResolvedType[] getDeclaredInterfaces() { diff --git a/weaver/src/org/aspectj/weaver/JoinPointSignature.java b/weaver/src/org/aspectj/weaver/JoinPointSignature.java index 12f66fca1..9fefcdf23 100644 --- a/weaver/src/org/aspectj/weaver/JoinPointSignature.java +++ b/weaver/src/org/aspectj/weaver/JoinPointSignature.java @@ -17,6 +17,7 @@ import java.util.Collection; import org.aspectj.bridge.ISourceLocation; import org.aspectj.weaver.AjAttribute.EffectiveSignatureAttribute; +import org.aspectj.weaver.Member.Kind; /** * @author colyer @@ -351,4 +352,20 @@ public class JoinPointSignature implements ResolvedMember { return buf.toString(); } + public void resetName(String newName) { + realMember.resetName(newName); + } + + public void resetKind(Kind newKind) { + realMember.resetKind(newKind); + } + + public void resetModifiers(int newModifiers) { + realMember.resetModifiers(newModifiers); + } + + public void resetReturnTypeToObjectArray() { + realMember.resetReturnTypeToObjectArray(); + } + } diff --git a/weaver/src/org/aspectj/weaver/MemberImpl.java b/weaver/src/org/aspectj/weaver/MemberImpl.java index cf2a16548..96a4478b2 100644 --- a/weaver/src/org/aspectj/weaver/MemberImpl.java +++ b/weaver/src/org/aspectj/weaver/MemberImpl.java @@ -21,14 +21,14 @@ import java.util.Iterator; import java.util.List; -public class MemberImpl implements Comparable, AnnotatedElement, Member { +public class MemberImpl implements Comparable, AnnotatedElement,Member { - private final Kind kind; + protected Kind kind; protected UnresolvedType declaringType; - protected final int modifiers; // protected because ResolvedMember uses it - private final UnresolvedType returnType; - private final String name; - private final UnresolvedType[] parameterTypes; + protected int modifiers; + protected UnresolvedType returnType; + protected String name; + protected UnresolvedType[] parameterTypes; private final String signature; private final String declaredSignature; // TODO asc Is this redundant? Is it needed for generics? private String paramSignature; diff --git a/weaver/src/org/aspectj/weaver/ResolvedMember.java b/weaver/src/org/aspectj/weaver/ResolvedMember.java index 6fd6c0a7c..17b1e2930 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedMember.java +++ b/weaver/src/org/aspectj/weaver/ResolvedMember.java @@ -17,6 +17,7 @@ import java.io.DataOutputStream; import java.io.IOException; import org.aspectj.bridge.ISourceLocation; +import org.aspectj.weaver.Member.Kind; public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDeclaringElement { @@ -135,5 +136,9 @@ public interface ResolvedMember extends Member, AnnotatedElement, TypeVariableDe * variable to match any other type variable regardless of bounds. */ public boolean matches(ResolvedMember aCandidateMatch); - + + public void resetName(String newName); + public void resetKind(Kind newKind); + public void resetModifiers(int newModifiers); + public void resetReturnTypeToObjectArray(); }
\ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java b/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java index de94d3c55..1acebd584 100644 --- a/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java +++ b/weaver/src/org/aspectj/weaver/ResolvedMemberImpl.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; import org.aspectj.bridge.ISourceLocation; +import org.aspectj.weaver.Member.Kind; /** * This is the declared member, i.e. it will always correspond to an @@ -266,7 +267,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno } public boolean hasAnnotation(UnresolvedType ofType) { - // The ctors don't allow annotations to be specified ... yet - but + // The ctors don't allow annotations to be specified ... yet - but // that doesn't mean it is an error to call this method. // Normally the weaver will be working with subtypes of // this type - BcelField/BcelMethod @@ -372,7 +373,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno public ResolvedMember resolve(World world) { - // FIXME asc guard with a check on resolution having happened ! + // make sure all the pieces of a resolvedmember really are resolved if (annotationTypes!=null) { Set r = new HashSet(); for (Iterator iter = annotationTypes.iterator(); iter.hasNext();) { @@ -383,7 +384,20 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno } declaringType = declaringType.resolve(world); if (declaringType.isRawType()) declaringType = ((ReferenceType)declaringType).getGenericType(); - return this; + if (typeVariables!=null && typeVariables.length>0) { + for (int i = 0; i < typeVariables.length; i++) { + UnresolvedType array_element = typeVariables[i]; + typeVariables[i] = typeVariables[i].resolve(world); + } + } + if (parameterTypes!=null && parameterTypes.length>0) { + for (int i = 0; i < parameterTypes.length; i++) { + UnresolvedType array_element = parameterTypes[i]; + parameterTypes[i] = parameterTypes[i].resolve(world); + } + } + + returnType = returnType.resolve(world);return this; } public ISourceContext getSourceContext(World world) { @@ -587,7 +601,20 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno private ResolvedMember myErasure = null; private boolean calculatedMyErasure = false; - + + + /** + * For ITDs, we use the default factory methods to build a resolved member, then alter a couple of characteristics + * using this method - this is safe. + */ + public void resetName(String newName) {this.name = newName;} + public void resetKind(Kind newKind) {this.kind=newKind; } + public void resetModifiers(int newModifiers) {this.modifiers=newModifiers;} + + public void resetReturnTypeToObjectArray() { + returnType = UnresolvedType.OBJECTARRAY; + } + /** * Returns a copy of this member but with the declaring type swapped. * Copy only needs to be shallow. diff --git a/weaver/src/org/aspectj/weaver/TypeFactory.java b/weaver/src/org/aspectj/weaver/TypeFactory.java index e81d63238..465747b4d 100644 --- a/weaver/src/org/aspectj/weaver/TypeFactory.java +++ b/weaver/src/org/aspectj/weaver/TypeFactory.java @@ -38,7 +38,7 @@ public class TypeFactory { ResolvedType baseType = aBaseType; if (!aBaseType.isGenericType()) { // try and find the generic type... - if (someTypeParameters != null) { + if (someTypeParameters != null && someTypeParameters.length>0) { if (!aBaseType.isRawType()) throw new IllegalStateException("Expecting raw type"); baseType = baseType.getGenericType(); if (baseType == null) throw new IllegalStateException("Raw type does not have generic type set"); @@ -50,6 +50,13 @@ public class TypeFactory { return (ReferenceType) pType.resolve(inAWorld); } + /** + * Create an *unresolved* parameterized version of a generic type. + */ + public static UnresolvedType createUnresolvedParameterizedType(String sig,String erasuresig,UnresolvedType[] arguments) { + return new UnresolvedType(sig,erasuresig,arguments); + } + public static ReferenceType createRawType( ResolvedType aBaseType, World inAWorld diff --git a/weaver/src/org/aspectj/weaver/TypeVariable.java b/weaver/src/org/aspectj/weaver/TypeVariable.java index 66f9a2a0f..35623d7bd 100644 --- a/weaver/src/org/aspectj/weaver/TypeVariable.java +++ b/weaver/src/org/aspectj/weaver/TypeVariable.java @@ -25,6 +25,9 @@ public class TypeVariable { */ private boolean isResolved = false; + + private boolean beingResolved = false; + /** * the name of the type variable as recorded in the generic signature */ @@ -93,6 +96,8 @@ public class TypeVariable { * resolve all the bounds of this type variable */ public void resolve(World inSomeWorld) { + if (beingResolved) { return; } // avoid spiral of death + beingResolved = true; if (isResolved) return; upperBound = upperBound.resolve(inSomeWorld); @@ -103,6 +108,7 @@ public class TypeVariable { } isResolved = true; + beingResolved = false; } /** diff --git a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java index c77e36cd7..9c47db1aa 100644 --- a/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java +++ b/weaver/src/org/aspectj/weaver/TypeVariableReferenceType.java @@ -23,18 +23,29 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T World aWorld) { super(aTypeVariable.getUpperBound().getSignature(),aWorld); this.typeVariable = aTypeVariable; - this.isExtends = false; - this.isSuper = false; - setUpperBound(aTypeVariable.getUpperBound()); - setLowerBound(aTypeVariable.getLowerBound()); - UnresolvedType[] ifBounds = aTypeVariable.getAdditionalInterfaceBounds(); - if (ifBounds.length > 0) { - this.additionalInterfaceBounds = new ReferenceType[ifBounds.length]; + this.isExtends = false; + this.isSuper = false; + setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)aTypeVariable.getUpperBound())); + } + + public UnresolvedType getUpperBound() { + if (typeVariable==null) return super.getUpperBound(); + return typeVariable.getUpperBound(); + } + + public UnresolvedType getLowerBound() { + return typeVariable.getLowerBound(); + } + + public ReferenceType[] getAdditionalBounds() { + if (additionalInterfaceBounds ==null && typeVariable.getAdditionalInterfaceBounds()!=null) { + UnresolvedType [] ifBounds = typeVariable.getAdditionalInterfaceBounds(); + additionalInterfaceBounds = new ReferenceType[ifBounds.length]; for (int i = 0; i < ifBounds.length; i++) { - this.additionalInterfaceBounds[i] = (ReferenceType) ifBounds[i]; + additionalInterfaceBounds[i] = (ReferenceType) ifBounds[i]; } } - setDelegate(new ReferenceTypeReferenceTypeDelegate((ReferenceType)aTypeVariable.getUpperBound())); + return additionalInterfaceBounds; } public TypeVariable getTypeVariable() { @@ -45,6 +56,10 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T return true; } +// public ResolvedType resolve(World world) { + // return super.resolve(world); + //} + /** * return the signature for a *REFERENCE* to a type variable, which is simply: * Tname; diff --git a/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java b/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java index 667c10c43..cf8494ea4 100644 --- a/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java +++ b/weaver/src/org/aspectj/weaver/UnresolvedTypeVariableReferenceType.java @@ -37,7 +37,9 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen } public ResolvedType resolve(World world) { - if (typeVariable == null) return ResolvedType.MISSING; + if (typeVariable == null) { + throw new BCException("Cannot resolve this type variable reference, the type variable has not been set!"); + } typeVariable.resolve(world); return new TypeVariableReferenceType(typeVariable,world); } diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java index 13c0e4889..053a3c10d 100644 --- a/weaver/src/org/aspectj/weaver/World.java +++ b/weaver/src/org/aspectj/weaver/World.java @@ -249,7 +249,7 @@ public abstract class World implements Dump.INode { /** * Resolve to a ReferenceType - simple, raw, parameterized, or generic. - * Raw, parmeterized, and generic versions of a type share a delegate. + * Raw, parameterized, and generic versions of a type share a delegate. */ private final ResolvedType resolveToReferenceType(UnresolvedType ty) { if (ty.isParameterizedType()) { @@ -309,6 +309,17 @@ public abstract class World implements Dump.INode { // raw type from a source type, it won't if its been created just through // being referenced, e.g. java.util.List ResolvedType genericType = rawType.getGenericType(); + + // There is a special case to consider here (testGenericsBang_pr95993 highlights it) + // You may have an unresolvedType for a parameterized type but it + // is backed by a simple type rather than a generic type. This occurs for + // inner types of generic types that inherit their enclosing types + // type variables. + if (rawType.isSimpleType() && anUnresolvedType.typeParameters.length==0) { + rawType.world = this; + return rawType; + } + if (genericType != null) { genericType.world = this; return genericType; @@ -324,18 +335,23 @@ public abstract class World implements Dump.INode { } } - // we have a generic wildcard with either extends or super, resolves to a - // BoundedReferenceType + /** + * Go from an unresolved generic wildcard (represented by UnresolvedType) to a resolved version (BoundedReferenceType). + */ private ReferenceType resolveGenericWildcardFor(UnresolvedType aType) { BoundedReferenceType ret = null; + // FIXME asc isExtends? isGenericWildcardExtends? I dont like having two + // FIXME asc doesnt take account of additional interface bounds (e.g. ? super R & Serializable - can you do that?) if (aType.isGenericWildcardExtends()) { - ReferenceType upperBound = (ReferenceType) resolve(aType.getUpperBound()); + ReferenceType upperBound = (ReferenceType)resolve(aType.getUpperBound()); ret = new BoundedReferenceType(upperBound,true,this); - } else { + } else { ReferenceType lowerBound = (ReferenceType) resolve(aType.getLowerBound()); ret = new BoundedReferenceType(lowerBound,false,this); } - typeMap.put(aType.getSignature(),ret); + // FIXME asc verify: I don't think these go in the typemap, it makes it potentially impossible to differentiate different uses of 'T', + // for example '? super T' where T is representing different things in two places would have the same sig (-TT;) + // typeMap.put(aType.getSignature(),ret); return ret; } |