@@ -23,28 +23,26 @@ import java.util.Map; | |||
*/ | |||
public class BoundedReferenceType extends ReferenceType { | |||
// possible kinds of BoundedReferenceType | |||
public static final int UNBOUND = 0; | |||
public static final int EXTENDS = 1; | |||
public static final int SUPER = 2; | |||
public int kind; | |||
private ResolvedType lowerBound; | |||
private ResolvedType upperBound; | |||
protected ReferenceType[] additionalInterfaceBounds = ReferenceType.EMPTY_ARRAY; | |||
protected boolean isExtends = true; | |||
protected boolean isSuper = false; | |||
public UnresolvedType getUpperBound() { | |||
return upperBound; | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return lowerBound; | |||
} | |||
public BoundedReferenceType(ReferenceType aBound, boolean isExtends, World world) { | |||
super((isExtends ? "+" : "-") + aBound.signature, aBound.signatureErasure, world); | |||
this.isExtends = isExtends; | |||
this.isSuper = !isExtends; | |||
if (isExtends) { | |||
this.kind = EXTENDS; | |||
} else { | |||
this.kind = SUPER; | |||
} | |||
if (isExtends) { | |||
upperBound = aBound; | |||
} else { | |||
@@ -59,48 +57,78 @@ public class BoundedReferenceType extends ReferenceType { | |||
this.additionalInterfaceBounds = additionalInterfaces; | |||
} | |||
/** | |||
* only for use when resolving GenericsWildcardTypeX or a TypeVariableReferenceType | |||
*/ | |||
protected BoundedReferenceType(String signature, String erasedSignature, World world) { | |||
super(signature, erasedSignature, world); | |||
if (signature.equals("*")) { | |||
// pure wildcard | |||
this.kind = UNBOUND; | |||
upperBound = world.resolve(UnresolvedType.OBJECT); | |||
} else { | |||
upperBound = world.resolve(forSignature(erasedSignature)); | |||
} | |||
setDelegate(new BoundedReferenceTypeDelegate((ReferenceType) upperBound)); | |||
} | |||
/** | |||
* Constructs the BoundedReferenceType representing an unbounded wildcard '?'. In this situation the signature is '*' and the | |||
* erased signature is Ljava/lang/Object; | |||
*/ | |||
public BoundedReferenceType(World world) { | |||
super("*", "Ljava/lang/Object;", world); | |||
this.kind = UNBOUND; | |||
upperBound = world.resolve(UnresolvedType.OBJECT); | |||
setDelegate(new BoundedReferenceTypeDelegate((ReferenceType)upperBound)); | |||
} | |||
public UnresolvedType getUpperBound() { | |||
return upperBound; | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return lowerBound; | |||
} | |||
public ReferenceType[] getAdditionalBounds() { | |||
return additionalInterfaceBounds; | |||
} | |||
@Override | |||
public UnresolvedType parameterize(Map typeBindings) { | |||
if (this.kind == UNBOUND) { | |||
return this; | |||
} | |||
ReferenceType[] parameterizedAdditionalInterfaces = new ReferenceType[additionalInterfaceBounds == null ? 0 | |||
: additionalInterfaceBounds.length]; | |||
for (int i = 0; i < parameterizedAdditionalInterfaces.length; i++) { | |||
parameterizedAdditionalInterfaces[i] = (ReferenceType) additionalInterfaceBounds[i].parameterize(typeBindings); | |||
} | |||
if (isExtends) { | |||
return new BoundedReferenceType((ReferenceType) getUpperBound().parameterize(typeBindings), isExtends, world, | |||
if (this.kind == EXTENDS) { | |||
return new BoundedReferenceType((ReferenceType) getUpperBound().parameterize(typeBindings), true, world, | |||
parameterizedAdditionalInterfaces); | |||
} else { | |||
return new BoundedReferenceType((ReferenceType) getLowerBound().parameterize(typeBindings), isExtends, world, | |||
// (this.kind == SUPER) | |||
return new BoundedReferenceType((ReferenceType) getLowerBound().parameterize(typeBindings), false, world, | |||
parameterizedAdditionalInterfaces); | |||
} | |||
} | |||
/** | |||
* only for use when resolving GenericsWildcardTypeX or a TypeVariableReferenceType | |||
*/ | |||
protected BoundedReferenceType(String sig, String sigErasure, World world) { | |||
super(sig, sigErasure, world); | |||
upperBound = world.resolve(UnresolvedType.OBJECT); | |||
setDelegate(new BoundedReferenceTypeDelegate((ReferenceType) getUpperBound())); | |||
} | |||
public ReferenceType[] getInterfaceBounds() { | |||
return additionalInterfaceBounds; | |||
} | |||
public boolean hasLowerBound() { | |||
return getLowerBound() != null; | |||
return lowerBound != null; | |||
} | |||
public boolean isExtends() { | |||
return (isExtends && !getUpperBound().getSignature().equals("Ljava/lang/Object;")); | |||
return (this.kind == EXTENDS && !getUpperBound().getSignature().equals("Ljava/lang/Object;")); | |||
} | |||
public boolean isSuper() { | |||
return isSuper; | |||
return this.kind == SUPER; | |||
} | |||
public boolean isUnbound() { | |||
return this.kind == UNBOUND; | |||
} | |||
public boolean alwaysMatches(ResolvedType aCandidateType) { | |||
@@ -117,8 +145,9 @@ public class BoundedReferenceType extends ReferenceType { | |||
// this "maybe matches" that | |||
public boolean canBeCoercedTo(ResolvedType aCandidateType) { | |||
if (alwaysMatches(aCandidateType)) | |||
if (alwaysMatches(aCandidateType)) { | |||
return true; | |||
} | |||
if (aCandidateType.isGenericWildcard()) { | |||
BoundedReferenceType boundedRT = (BoundedReferenceType) aCandidateType; | |||
ResolvedType myUpperBound = (ResolvedType) getUpperBound(); | |||
@@ -147,9 +176,11 @@ public class BoundedReferenceType extends ReferenceType { | |||
} | |||
} | |||
@Override | |||
public String getSimpleName() { | |||
if (!isExtends() && !isSuper()) | |||
if (!isExtends() && !isSuper()) { | |||
return "?"; | |||
} | |||
if (isExtends()) { | |||
return ("? extends " + getUpperBound().getSimpleName()); | |||
} else { | |||
@@ -158,6 +189,7 @@ public class BoundedReferenceType extends ReferenceType { | |||
} | |||
// override to include additional interface bounds... | |||
@Override | |||
public ResolvedType[] getDeclaredInterfaces() { | |||
ResolvedType[] interfaces = super.getDeclaredInterfaces(); | |||
if (additionalInterfaceBounds.length > 0) { | |||
@@ -170,6 +202,7 @@ public class BoundedReferenceType extends ReferenceType { | |||
} | |||
} | |||
@Override | |||
public boolean isGenericWildcard() { | |||
return true; | |||
} |
@@ -134,27 +134,27 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public boolean isClass() { | |||
return delegate.isClass(); | |||
return getDelegate().isClass(); | |||
} | |||
@Override | |||
public int getCompilerVersion() { | |||
return delegate.getCompilerVersion(); | |||
return getDelegate().getCompilerVersion(); | |||
} | |||
@Override | |||
public boolean isGenericType() { | |||
return !isParameterizedType() && !isRawType() && delegate.isGeneric(); | |||
return !isParameterizedType() && !isRawType() && getDelegate().isGeneric(); | |||
} | |||
public String getGenericSignature() { | |||
String sig = delegate.getDeclaredGenericSignature(); | |||
String sig = getDelegate().getDeclaredGenericSignature(); | |||
return (sig == null) ? "" : sig; | |||
} | |||
@Override | |||
public AnnotationAJ[] getAnnotations() { | |||
return delegate.getAnnotations(); | |||
return getDelegate().getAnnotations(); | |||
} | |||
@Override | |||
@@ -172,7 +172,7 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
public boolean hasAnnotation(UnresolvedType ofType) { | |||
boolean onDelegate = delegate.hasAnnotation(ofType); | |||
boolean onDelegate = getDelegate().hasAnnotation(ofType); | |||
if (onDelegate) { | |||
return true; | |||
} | |||
@@ -200,14 +200,14 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public ResolvedType[] getAnnotationTypes() { | |||
if (delegate == null) { | |||
if (getDelegate() == null) { | |||
throw new BCException("Unexpected null delegate for type " + this.getName()); | |||
} | |||
if (annotationTypes == null) { | |||
// there are no extras: | |||
return delegate.getAnnotationTypes(); | |||
return getDelegate().getAnnotationTypes(); | |||
} else { | |||
ResolvedType[] delegateAnnotationTypes = delegate.getAnnotationTypes(); | |||
ResolvedType[] delegateAnnotationTypes = getDelegate().getAnnotationTypes(); | |||
ResolvedType[] result = new ResolvedType[annotationTypes.length + delegateAnnotationTypes.length]; | |||
System.arraycopy(delegateAnnotationTypes, 0, result, 0, delegateAnnotationTypes.length); | |||
System.arraycopy(annotationTypes, 0, result, delegateAnnotationTypes.length, annotationTypes.length); | |||
@@ -222,7 +222,7 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public AnnotationAJ getAnnotationOfType(UnresolvedType ofType) { | |||
AnnotationAJ[] axs = delegate.getAnnotations(); | |||
AnnotationAJ[] axs = getDelegate().getAnnotations(); | |||
if (axs == null) { | |||
if (annotations != null) { | |||
String searchSig = ofType.getSignature(); | |||
@@ -244,55 +244,55 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public boolean isAspect() { | |||
return delegate.isAspect(); | |||
return getDelegate().isAspect(); | |||
} | |||
@Override | |||
public boolean isAnnotationStyleAspect() { | |||
return delegate.isAnnotationStyleAspect(); | |||
return getDelegate().isAnnotationStyleAspect(); | |||
} | |||
@Override | |||
public boolean isEnum() { | |||
return delegate.isEnum(); | |||
return getDelegate().isEnum(); | |||
} | |||
@Override | |||
public boolean isAnnotation() { | |||
return delegate.isAnnotation(); | |||
return getDelegate().isAnnotation(); | |||
} | |||
@Override | |||
public boolean isAnonymous() { | |||
return delegate.isAnonymous(); | |||
return getDelegate().isAnonymous(); | |||
} | |||
@Override | |||
public boolean isNested() { | |||
return delegate.isNested(); | |||
return getDelegate().isNested(); | |||
} | |||
public ResolvedType getOuterClass() { | |||
return delegate.getOuterClass(); | |||
return getDelegate().getOuterClass(); | |||
} | |||
public String getRetentionPolicy() { | |||
return delegate.getRetentionPolicy(); | |||
return getDelegate().getRetentionPolicy(); | |||
} | |||
@Override | |||
public boolean isAnnotationWithRuntimeRetention() { | |||
return delegate.isAnnotationWithRuntimeRetention(); | |||
return getDelegate().isAnnotationWithRuntimeRetention(); | |||
} | |||
@Override | |||
public boolean canAnnotationTargetType() { | |||
return delegate.canAnnotationTargetType(); | |||
return getDelegate().canAnnotationTargetType(); | |||
} | |||
@Override | |||
public AnnotationTargetKind[] getAnnotationTargetKinds() { | |||
return delegate.getAnnotationTargetKinds(); | |||
return getDelegate().getAnnotationTargetKinds(); | |||
} | |||
// true iff the statement "this = (ThisType) other" would compile | |||
@@ -579,23 +579,23 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public ISourceContext getSourceContext() { | |||
return delegate.getSourceContext(); | |||
return getDelegate().getSourceContext(); | |||
} | |||
@Override | |||
public ISourceLocation getSourceLocation() { | |||
ISourceContext isc = delegate.getSourceContext(); | |||
ISourceContext isc = getDelegate().getSourceContext(); | |||
return isc.makeSourceLocation(new Position(startPos, endPos)); | |||
} | |||
@Override | |||
public boolean isExposedToWeaver() { | |||
return (delegate == null) || delegate.isExposedToWeaver(); | |||
return (getDelegate() == null) || delegate.isExposedToWeaver(); | |||
} | |||
@Override | |||
public WeaverStateInfo getWeaverState() { | |||
return delegate.getWeaverState(); | |||
return getDelegate().getWeaverState(); | |||
} | |||
@Override | |||
@@ -604,7 +604,7 @@ public class ReferenceType extends ResolvedType { | |||
return parameterizedFields; | |||
} | |||
if (isParameterizedType() || isRawType()) { | |||
ResolvedMember[] delegateFields = delegate.getDeclaredFields(); | |||
ResolvedMember[] delegateFields = getDelegate().getDeclaredFields(); | |||
parameterizedFields = new ResolvedMember[delegateFields.length]; | |||
for (int i = 0; i < delegateFields.length; i++) { | |||
parameterizedFields[i] = delegateFields[i].parameterizedWith(getTypesForMemberParameterization(), this, | |||
@@ -612,7 +612,7 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
return parameterizedFields; | |||
} else { | |||
return delegate.getDeclaredFields(); | |||
return getDelegate().getDeclaredFields(); | |||
} | |||
} | |||
@@ -626,7 +626,7 @@ public class ReferenceType extends ResolvedType { | |||
if (interfaces != null) { | |||
return interfaces; | |||
} | |||
ResolvedType[] delegateInterfaces = delegate.getDeclaredInterfaces(); | |||
ResolvedType[] delegateInterfaces = getDelegate().getDeclaredInterfaces(); | |||
if (newInterfaces != null) { | |||
// OPTIMIZE does this part of the method trigger often? | |||
ResolvedType[] extraInterfaces = new ResolvedType[delegateInterfaces.length + newInterfaces.length]; | |||
@@ -670,7 +670,7 @@ public class ReferenceType extends ResolvedType { | |||
parameterizedInterfaces = new WeakReference<ResolvedType[]>(interfaces); | |||
return interfaces; | |||
} | |||
if (delegate.isCacheable()) { | |||
if (getDelegate().isCacheable()) { | |||
parameterizedInterfaces = new WeakReference<ResolvedType[]>(delegateInterfaces); | |||
} | |||
return delegateInterfaces; | |||
@@ -765,7 +765,7 @@ public class ReferenceType extends ResolvedType { | |||
return parameterizedMethods; | |||
} | |||
if (isParameterizedType() || isRawType()) { | |||
ResolvedMember[] delegateMethods = delegate.getDeclaredMethods(); | |||
ResolvedMember[] delegateMethods = getDelegate().getDeclaredMethods(); | |||
UnresolvedType[] parameters = getTypesForMemberParameterization(); | |||
parameterizedMethods = new ResolvedMember[delegateMethods.length]; | |||
for (int i = 0; i < delegateMethods.length; i++) { | |||
@@ -773,7 +773,7 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
return parameterizedMethods; | |||
} else { | |||
return delegate.getDeclaredMethods(); | |||
return getDelegate().getDeclaredMethods(); | |||
} | |||
} | |||
@@ -783,7 +783,7 @@ public class ReferenceType extends ResolvedType { | |||
return parameterizedPointcuts; | |||
} | |||
if (isParameterizedType()) { | |||
ResolvedMember[] delegatePointcuts = delegate.getDeclaredPointcuts(); | |||
ResolvedMember[] delegatePointcuts = getDelegate().getDeclaredPointcuts(); | |||
parameterizedPointcuts = new ResolvedMember[delegatePointcuts.length]; | |||
for (int i = 0; i < delegatePointcuts.length; i++) { | |||
parameterizedPointcuts[i] = delegatePointcuts[i].parameterizedWith(getTypesForMemberParameterization(), this, | |||
@@ -791,7 +791,7 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
return parameterizedPointcuts; | |||
} else { | |||
return delegate.getDeclaredPointcuts(); | |||
return getDelegate().getDeclaredPointcuts(); | |||
} | |||
} | |||
@@ -813,7 +813,7 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public TypeVariable[] getTypeVariables() { | |||
if (this.typeVariables == null) { | |||
this.typeVariables = delegate.getTypeVariables(); | |||
this.typeVariables = getDelegate().getTypeVariables(); | |||
for (int i = 0; i < this.typeVariables.length; i++) { | |||
this.typeVariables[i].resolve(world); | |||
} | |||
@@ -823,7 +823,7 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public PerClause getPerClause() { | |||
PerClause pclause = delegate.getPerClause(); | |||
PerClause pclause = getDelegate().getPerClause(); | |||
if (isParameterizedType()) { // could cache the result here... | |||
Map parameterizationMap = getAjMemberParameterizationMap(); | |||
pclause = (PerClause) pclause.parameterizeWith(parameterizationMap, world); | |||
@@ -838,7 +838,7 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
Collection<Declare> declares = null; | |||
if (ajMembersNeedParameterization()) { | |||
Collection<Declare> genericDeclares = delegate.getDeclares(); | |||
Collection<Declare> genericDeclares = getDelegate().getDeclares(); | |||
parameterizedDeclares = new ArrayList<Declare>(); | |||
Map<String, UnresolvedType> parameterizationMap = getAjMemberParameterizationMap(); | |||
for (Declare declareStatement : genericDeclares) { | |||
@@ -846,7 +846,7 @@ public class ReferenceType extends ResolvedType { | |||
} | |||
declares = parameterizedDeclares; | |||
} else { | |||
declares = delegate.getDeclares(); | |||
declares = getDelegate().getDeclares(); | |||
} | |||
for (Declare d : declares) { | |||
d.setDeclaringType(this); | |||
@@ -856,7 +856,7 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public Collection<ConcreteTypeMunger> getTypeMungers() { | |||
return delegate.getTypeMungers(); | |||
return getDelegate().getTypeMungers(); | |||
} | |||
// GENERICITDFIX | |||
@@ -882,12 +882,12 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public Collection getPrivilegedAccesses() { | |||
return delegate.getPrivilegedAccesses(); | |||
return getDelegate().getPrivilegedAccesses(); | |||
} | |||
@Override | |||
public int getModifiers() { | |||
return delegate.getModifiers(); | |||
return getDelegate().getModifiers(); | |||
} | |||
WeakReference<ResolvedType> superclassReference = new WeakReference<ResolvedType>(null); | |||
@@ -902,21 +902,21 @@ public class ReferenceType extends ResolvedType { | |||
if (this.isParameterizedType() && newSuperclass.isParameterizedType()) { | |||
return newSuperclass.parameterize(getMemberParameterizationMap()).resolve(getWorld()); | |||
} | |||
if (delegate.isCacheable()) { | |||
if (getDelegate().isCacheable()) { | |||
superclassReference = new WeakReference<ResolvedType>(ret); | |||
} | |||
return newSuperclass; | |||
} | |||
try { | |||
world.setTypeVariableLookupScope(this); | |||
ret = delegate.getSuperclass(); | |||
ret = getDelegate().getSuperclass(); | |||
} finally { | |||
world.setTypeVariableLookupScope(null); | |||
} | |||
if (this.isParameterizedType() && ret.isParameterizedType()) { | |||
ret = ret.parameterize(getMemberParameterizationMap()).resolve(getWorld()); | |||
} | |||
if (delegate.isCacheable()) { | |||
if (getDelegate().isCacheable()) { | |||
superclassReference = new WeakReference<ResolvedType>(ret); | |||
} | |||
return ret; | |||
@@ -977,11 +977,11 @@ public class ReferenceType extends ResolvedType { | |||
@Override | |||
public boolean doesNotExposeShadowMungers() { | |||
return delegate.doesNotExposeShadowMungers(); | |||
return getDelegate().doesNotExposeShadowMungers(); | |||
} | |||
public String getDeclaredGenericSignature() { | |||
return delegate.getDeclaredGenericSignature(); | |||
return getDelegate().getDeclaredGenericSignature(); | |||
} | |||
public void setGenericType(ReferenceType rt) { | |||
@@ -1048,7 +1048,7 @@ public class ReferenceType extends ResolvedType { | |||
newInterfaces = null; | |||
parameterizedInterfaces.clear(); | |||
superclassReference = new WeakReference<ResolvedType>(null); | |||
if (delegate != null) { | |||
if (getDelegate() != null) { | |||
delegate.ensureConsistent(); | |||
} | |||
} | |||
@@ -1063,7 +1063,7 @@ public class ReferenceType extends ResolvedType { | |||
newInterfaces = new ResolvedType[1]; | |||
newInterfaces[0] = newParent; | |||
} else { | |||
ResolvedType[] existing = delegate.getDeclaredInterfaces(); | |||
ResolvedType[] existing = getDelegate().getDeclaredInterfaces(); | |||
if (existing != null) { | |||
for (int i = 0; i < existing.length; i++) { | |||
if (existing[i].equals(newParent)) { |
@@ -1022,7 +1022,7 @@ public class ResolvedMemberImpl extends MemberImpl implements IHasPosition, Anno | |||
toBuffer.append("..."); | |||
} else { | |||
alreadyUsedTypeVars.add(aType); | |||
appendSigWithTypeVarBoundsRemoved(typeVariableRT.getUpperBound(), toBuffer, alreadyUsedTypeVars); | |||
appendSigWithTypeVarBoundsRemoved(typeVariableRT.getTypeVariable().getUpperBound(), toBuffer, alreadyUsedTypeVars); | |||
} | |||
// toBuffer.append("T;"); | |||
} else if (aType.isParameterizedType()) { |
@@ -1,13 +1,10 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* Copyright (c) 2005-2010 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
@@ -15,92 +12,82 @@ import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
/** | |||
* Represents a type variable with bounds | |||
* Represents a type variable with possible bounds. | |||
* | |||
* @author Adrian Colyer | |||
* @author Andy Clement | |||
*/ | |||
public class TypeVariable { | |||
public static final TypeVariable[] NONE = new TypeVariable[0]; | |||
/** | |||
* whether or not the bounds of this type variable have been resolved | |||
*/ | |||
private boolean isResolved = false; | |||
private boolean beingResolved = false; | |||
/** | |||
* the name of the type variable as recorded in the generic signature | |||
*/ | |||
// the name of the type variable as recorded in the generic signature | |||
private String name; | |||
// index | |||
private int rank; | |||
// computed as required: either ==superclass or ==superInterfaces[0] or is OBJECT | |||
private UnresolvedType firstbound; | |||
// the upper bound of the type variable. From the extends clause, eg. T extends Number | |||
private UnresolvedType superclass; | |||
// any additional upper (interface) bounds. from the extends clause, e.g. T extends Number & Comparable | |||
private UnresolvedType[] superInterfaces = UnresolvedType.NONE; | |||
// It would be nice to push this field onto the TypeVariableDeclaringElement | |||
// interface (a getKind()) but at the moment we don't always guarantee | |||
// to set the declaring element (eclipse seems to utilise the knowledge of | |||
// what declared the type variable, but we dont yet...) | |||
/** | |||
* What kind of element declared this type variable? | |||
*/ | |||
private int declaringElementKind = UNKNOWN; | |||
public static final int UNKNOWN = -1; | |||
public static final int METHOD = 1; | |||
public static final int TYPE = 2; | |||
// What kind of element declared this type variable? | |||
private int declaringElementKind = UNKNOWN; | |||
private TypeVariableDeclaringElement declaringElement; | |||
// whether or not the bounds of this type variable have been resolved | |||
private boolean isResolved = false; | |||
// Is this type variable in the process of being resolved (allows for something self-referential like Enum) | |||
private boolean beingResolved = false; | |||
/** | |||
* the upper bound of the type variable (default to Object). From the extends clause, eg. T extends Number. | |||
*/ | |||
private UnresolvedType upperBound = UnresolvedType.OBJECT; | |||
/** | |||
* any additional upper (interface) bounds. from the extends clause, e.g. T extends Number & Comparable | |||
*/ | |||
private UnresolvedType[] additionalInterfaceBounds = new UnresolvedType[0]; | |||
/** | |||
* any lower bound. from the super clause, eg T super Foo | |||
* Constructor for an unbound type variable, eg. 'T' | |||
*/ | |||
private UnresolvedType lowerBound = null; | |||
public TypeVariable(String aName) { | |||
this.name = aName; | |||
} | |||
public TypeVariable(String aName, UnresolvedType anUpperBound) { | |||
this(aName); | |||
this.upperBound = anUpperBound; | |||
public TypeVariable(String name) { | |||
this.name = name; | |||
} | |||
public TypeVariable(String aName, UnresolvedType anUpperBound, UnresolvedType[] someAdditionalInterfaceBounds) { | |||
this(aName, anUpperBound); | |||
this.additionalInterfaceBounds = someAdditionalInterfaceBounds; | |||
public TypeVariable(String name, UnresolvedType anUpperBound) { | |||
this(name); | |||
this.superclass = anUpperBound; | |||
} | |||
public TypeVariable(String aName, UnresolvedType anUpperBound, UnresolvedType[] someAdditionalInterfaceBounds, | |||
UnresolvedType aLowerBound) { | |||
this(aName, anUpperBound, someAdditionalInterfaceBounds); | |||
this.lowerBound = aLowerBound; | |||
public TypeVariable(String name, UnresolvedType anUpperBound, UnresolvedType[] superInterfaces) { | |||
this(name, anUpperBound); | |||
this.superInterfaces = superInterfaces; | |||
} | |||
// First bound is the first 'real' bound, this can be an interface if | |||
// no class bound was specified (it will default to object) | |||
/** | |||
* @return the first bound, either the superclass or if non is specified the first interface or if non are specified then OBJECT | |||
*/ | |||
public UnresolvedType getFirstBound() { | |||
if (upperBound.equals(UnresolvedType.OBJECT) && additionalInterfaceBounds != null && additionalInterfaceBounds.length != 0) { | |||
return additionalInterfaceBounds[0]; | |||
if (firstbound != null) { | |||
return firstbound; | |||
} | |||
return upperBound; | |||
if (superclass == null || superclass.getSignature().equals("Ljava/lang/Object;")) { | |||
if (superInterfaces.length > 0) { | |||
firstbound = superInterfaces[0]; | |||
} else { | |||
firstbound = UnresolvedType.OBJECT; | |||
} | |||
} else { | |||
firstbound = superclass; | |||
} | |||
return firstbound; | |||
} | |||
public UnresolvedType getUpperBound() { | |||
return upperBound; | |||
return superclass; | |||
} | |||
public UnresolvedType[] getAdditionalInterfaceBounds() { | |||
return additionalInterfaceBounds; | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return lowerBound; | |||
public UnresolvedType[] getSuperInterfaces() { | |||
return superInterfaces; | |||
} | |||
public String getName() { | |||
@@ -110,13 +97,14 @@ public class TypeVariable { | |||
/** | |||
* resolve all the bounds of this type variable | |||
*/ | |||
public TypeVariable resolve(World inSomeWorld) { | |||
public TypeVariable resolve(World world) { | |||
if (isResolved) { | |||
return this; | |||
} | |||
if (beingResolved) { | |||
return this; | |||
} // avoid spiral of death | |||
} | |||
beingResolved = true; | |||
if (isResolved) | |||
return this; | |||
TypeVariable resolvedTVar = null; | |||
@@ -124,7 +112,7 @@ public class TypeVariable { | |||
// resolve by finding the real type var that we refer to... | |||
if (declaringElementKind == TYPE) { | |||
UnresolvedType declaring = (UnresolvedType) declaringElement; | |||
ReferenceType rd = (ReferenceType) declaring.resolve(inSomeWorld); | |||
ReferenceType rd = (ReferenceType) declaring.resolve(world); | |||
TypeVariable[] tVars = rd.getTypeVariables(); | |||
for (int i = 0; i < tVars.length; i++) { | |||
if (tVars[i].getName().equals(getName())) { | |||
@@ -137,38 +125,42 @@ public class TypeVariable { | |||
ResolvedMember declaring = (ResolvedMember) declaringElement; | |||
TypeVariable[] tvrts = declaring.getTypeVariables(); | |||
for (int i = 0; i < tvrts.length; i++) { | |||
if (tvrts[i].getName().equals(getName())) | |||
if (tvrts[i].getName().equals(getName())) { | |||
resolvedTVar = tvrts[i]; | |||
// if (tvrts[i].isTypeVariableReference()) { | |||
// TypeVariableReferenceType tvrt = (TypeVariableReferenceType) tvrts[i].resolve(inSomeWorld); | |||
// TypeVariable tv = tvrt.getTypeVariable(); | |||
// if (tv.getName().equals(getName())) resolvedTVar = tv; | |||
// } | |||
// if (tvrts[i].isTypeVariableReference()) { | |||
// TypeVariableReferenceType tvrt = (TypeVariableReferenceType) tvrts[i].resolve(inSomeWorld); | |||
// TypeVariable tv = tvrt.getTypeVariable(); | |||
// if (tv.getName().equals(getName())) resolvedTVar = tv; | |||
// } | |||
} | |||
} | |||
} | |||
if (resolvedTVar == null) { | |||
throw new IllegalStateException(); | |||
// well, this is bad... we didn't find the type variable on the member | |||
// could be a separate compilation issue... | |||
// should issue message, this is a workaround to get us going... | |||
resolvedTVar = this; | |||
// resolvedTVar = this; | |||
} | |||
} else { | |||
resolvedTVar = this; | |||
} | |||
upperBound = resolvedTVar.upperBound; | |||
lowerBound = resolvedTVar.lowerBound; | |||
additionalInterfaceBounds = resolvedTVar.additionalInterfaceBounds; | |||
superclass = resolvedTVar.superclass; | |||
superInterfaces = resolvedTVar.superInterfaces; | |||
upperBound = upperBound.resolve(inSomeWorld); | |||
if (lowerBound != null) | |||
lowerBound = lowerBound.resolve(inSomeWorld); | |||
if (additionalInterfaceBounds != null) { | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
additionalInterfaceBounds[i] = additionalInterfaceBounds[i].resolve(inSomeWorld); | |||
if (superclass != null) { | |||
ResolvedType rt = superclass.resolve(world); | |||
if (!superclass.isTypeVariableReference() && rt.isInterface()) { | |||
throw new IllegalStateException("Why is the type an interface? " + rt); | |||
} | |||
superclass = rt; | |||
} | |||
firstbound = getFirstBound().resolve(world); | |||
for (int i = 0; i < superInterfaces.length; i++) { | |||
superInterfaces[i] = superInterfaces[i].resolve(world); | |||
} | |||
isResolved = true; | |||
beingResolved = false; | |||
@@ -179,30 +171,28 @@ public class TypeVariable { | |||
* answer true if the given type satisfies all of the bound constraints of this type variable. If type variable has not been | |||
* resolved then throws IllegalStateException | |||
*/ | |||
public boolean canBeBoundTo(ResolvedType aCandidateType) { | |||
if (!isResolved) | |||
public boolean canBeBoundTo(ResolvedType candidate) { | |||
if (!isResolved) { | |||
throw new IllegalStateException("Can't answer binding questions prior to resolving"); | |||
} | |||
// wildcard can accept any binding | |||
if (aCandidateType.isGenericWildcard()) { // AMC - need a more robust test! | |||
if (candidate.isGenericWildcard()) { | |||
return true; | |||
} | |||
// otherwise can be bound iff... | |||
// aCandidateType is a subtype of upperBound | |||
if (!isASubtypeOf(upperBound, aCandidateType)) { | |||
// candidate is a subtype of upperBound | |||
if (superclass != null && !isASubtypeOf(superclass, candidate)) { | |||
return false; | |||
} | |||
// aCandidateType is a subtype of all additionalInterfaceBounds | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
if (!isASubtypeOf(additionalInterfaceBounds[i], aCandidateType)) { | |||
// candidate is a subtype of all superInterfaces | |||
for (int i = 0; i < superInterfaces.length; i++) { | |||
if (!isASubtypeOf(superInterfaces[i], candidate)) { | |||
return false; | |||
} | |||
} | |||
// lowerBound is a subtype of aCandidateType | |||
if ((lowerBound != null) && (!isASubtypeOf(aCandidateType, lowerBound))) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
@@ -213,18 +203,21 @@ public class TypeVariable { | |||
} | |||
// only used when resolving | |||
public void setUpperBound(UnresolvedType aTypeX) { | |||
this.upperBound = aTypeX; | |||
} | |||
// only used when resolving | |||
public void setLowerBound(UnresolvedType aTypeX) { | |||
this.lowerBound = aTypeX; | |||
public void setUpperBound(UnresolvedType superclass) { | |||
// if (isResolved) { | |||
// throw new IllegalStateException("Why set this late?"); | |||
// } | |||
this.firstbound = null; | |||
this.superclass = superclass; | |||
} | |||
// only used when resolving | |||
public void setAdditionalInterfaceBounds(UnresolvedType[] someTypeXs) { | |||
this.additionalInterfaceBounds = someTypeXs; | |||
public void setAdditionalInterfaceBounds(UnresolvedType[] superInterfaces) { | |||
if (isResolved) { | |||
throw new IllegalStateException("Why set this late?"); | |||
} | |||
this.firstbound = null; | |||
this.superInterfaces = superInterfaces; | |||
} | |||
public String toDebugString() { | |||
@@ -237,23 +230,19 @@ public class TypeVariable { | |||
if (!getFirstBound().getName().equals("java.lang.Object")) { | |||
ret.append(" extends "); | |||
ret.append(getFirstBound().getName()); | |||
if (additionalInterfaceBounds != null) { | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
if (!getFirstBound().equals(additionalInterfaceBounds[i])) { | |||
if (superInterfaces != null) { | |||
for (int i = 0; i < superInterfaces.length; i++) { | |||
if (!getFirstBound().equals(superInterfaces[i])) { | |||
ret.append(" & "); | |||
ret.append(additionalInterfaceBounds[i].getName()); | |||
ret.append(superInterfaces[i].getName()); | |||
} | |||
} | |||
} | |||
} | |||
if (lowerBound != null) { | |||
ret.append(" super "); | |||
ret.append(lowerBound.getName()); | |||
} | |||
return ret.toString(); | |||
} | |||
// good enough approximation | |||
@Override | |||
public String toString() { | |||
return "TypeVar " + getDisplayName(); | |||
} | |||
@@ -266,11 +255,11 @@ public class TypeVariable { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(name); | |||
sb.append(":"); | |||
sb.append(upperBound.getSignature()); | |||
if (additionalInterfaceBounds != null && additionalInterfaceBounds.length != 0) { | |||
sb.append(superclass.getSignature()); | |||
if (superInterfaces.length != 0) { | |||
sb.append(":"); | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
UnresolvedType iBound = additionalInterfaceBounds[i]; | |||
for (int i = 0; i < superInterfaces.length; i++) { | |||
UnresolvedType iBound = superInterfaces[i]; | |||
sb.append(iBound.getSignature()); | |||
} | |||
} | |||
@@ -284,11 +273,11 @@ public class TypeVariable { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(name); | |||
sb.append(":"); | |||
sb.append(((ResolvedType) upperBound).getSignatureForAttribute()); | |||
if (additionalInterfaceBounds != null && additionalInterfaceBounds.length != 0) { | |||
sb.append(((ResolvedType) superclass).getSignatureForAttribute()); | |||
if (superInterfaces.length != 0) { | |||
sb.append(":"); | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
ResolvedType iBound = (ResolvedType) additionalInterfaceBounds[i]; | |||
for (int i = 0; i < superInterfaces.length; i++) { | |||
ResolvedType iBound = (ResolvedType) superInterfaces[i]; | |||
sb.append(iBound.getSignatureForAttribute()); | |||
} | |||
} | |||
@@ -328,13 +317,13 @@ public class TypeVariable { | |||
public void write(DataOutputStream s) throws IOException { | |||
// name, upperbound, additionalInterfaceBounds, lowerbound | |||
s.writeUTF(name); | |||
upperBound.write(s); | |||
if (additionalInterfaceBounds == null || additionalInterfaceBounds.length == 0) { | |||
superclass.write(s); | |||
if (superInterfaces.length == 0) { | |||
s.writeInt(0); | |||
} else { | |||
s.writeInt(additionalInterfaceBounds.length); | |||
for (int i = 0; i < additionalInterfaceBounds.length; i++) { | |||
UnresolvedType ibound = additionalInterfaceBounds[i]; | |||
s.writeInt(superInterfaces.length); | |||
for (int i = 0; i < superInterfaces.length; i++) { | |||
UnresolvedType ibound = superInterfaces[i]; | |||
ibound.write(s); | |||
} | |||
} | |||
@@ -361,11 +350,19 @@ public class TypeVariable { | |||
public String getGenericSignature() { | |||
return "T" + name + ";"; | |||
// return "T"+getSignature(); | |||
} | |||
public String getErasureSignature() { | |||
return getFirstBound().getErasureSignature(); | |||
} | |||
public UnresolvedType getSuperclass() { | |||
return superclass; | |||
} | |||
public void setSuperclass(UnresolvedType superclass) { | |||
this.firstbound = null; | |||
this.superclass = superclass; | |||
} | |||
} |
@@ -1,24 +1,23 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* Copyright (c) 2005-2010 Contributors. | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* http://eclipse.org/legal/epl-v10.html | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
import java.util.Map; | |||
/** | |||
* Represents a type variable in a type or generic method declaration | |||
* ReferenceType representing a type variable. The delegate for this reference type is the upperbound on the type variable (so | |||
* Object if not otherwise specified). | |||
* | |||
* @author Adrian Colyer | |||
* @author Andy Clement | |||
*/ | |||
public class TypeVariableReferenceType extends BoundedReferenceType implements TypeVariableReference { | |||
public class TypeVariableReferenceType extends ReferenceType implements TypeVariableReference { | |||
private TypeVariable typeVariable; | |||
private boolean resolvedIfBounds = false; | |||
@@ -29,60 +28,32 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T | |||
// at the right time). Wonder if we can fix it up late? | |||
boolean fixedUp = false; | |||
public TypeVariableReferenceType(TypeVariable aTypeVariable, World aWorld) { | |||
super(aTypeVariable.getGenericSignature(), aTypeVariable.getErasureSignature(), aWorld); | |||
this.typeVariable = aTypeVariable; | |||
this.isExtends = false; | |||
this.isSuper = false; | |||
public TypeVariableReferenceType(TypeVariable typeVariable, World world) { | |||
super(typeVariable.getGenericSignature(), typeVariable.getErasureSignature(), world); | |||
this.typeVariable = typeVariable; | |||
// setDelegate(new BoundedReferenceTypeDelegate(backing)); | |||
// this.isExtends = false; | |||
// this.isSuper = false; | |||
} | |||
/** | |||
* For a TypeVariableReferenceType the delegate is the delegate for the first bound. | |||
*/ | |||
@Override | |||
public ReferenceTypeDelegate getDelegate() { | |||
if (delegate == null) | |||
setDelegate(new BoundedReferenceTypeDelegate((ReferenceType) typeVariable.getFirstBound())); | |||
return delegate; | |||
} | |||
public UnresolvedType getUpperBound() { | |||
if (typeVariable == null) | |||
return super.getUpperBound(); | |||
return typeVariable.getUpperBound(); | |||
} | |||
public UnresolvedType getFirstBound() { | |||
if (typeVariable == null) | |||
return super.getUpperBound(); | |||
return typeVariable.getFirstBound(); | |||
} | |||
public UnresolvedType getLowerBound() { | |||
return typeVariable.getLowerBound(); | |||
} | |||
private void setAdditionalInterfaceBoundsFromTypeVar() { | |||
if (typeVariable.getAdditionalInterfaceBounds() == null) { | |||
return; | |||
} else { | |||
UnresolvedType[] ifBounds = typeVariable.getAdditionalInterfaceBounds(); | |||
additionalInterfaceBounds = new ReferenceType[ifBounds.length]; | |||
for (int i = 0; i < ifBounds.length; i++) { | |||
additionalInterfaceBounds[i] = (ReferenceType) ifBounds[i].resolve(getWorld()); | |||
} | |||
if (this.delegate == null) { | |||
setDelegate(new BoundedReferenceTypeDelegate((ReferenceType) typeVariable.getFirstBound().resolve(world))); | |||
} | |||
return this.delegate; | |||
} | |||
@Override | |||
public UnresolvedType parameterize(Map typeBindings) { | |||
UnresolvedType ut = (UnresolvedType) typeBindings.get(getName()); | |||
if (ut != null) | |||
if (ut != null) { | |||
return world.resolve(ut); | |||
return this; | |||
} | |||
public ReferenceType[] getAdditionalBounds() { | |||
if (!resolvedIfBounds) { | |||
setAdditionalInterfaceBoundsFromTypeVar(); | |||
resolvedIfBounds = true; | |||
} | |||
return super.getAdditionalBounds(); | |||
return this; | |||
} | |||
public TypeVariable getTypeVariable() { | |||
@@ -90,33 +61,38 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T | |||
return typeVariable; | |||
} | |||
@Override | |||
public boolean isTypeVariableReference() { | |||
return true; | |||
} | |||
@Override | |||
public String toString() { | |||
return typeVariable.getName(); | |||
} | |||
@Override | |||
public boolean isGenericWildcard() { | |||
return false; | |||
} | |||
// public ResolvedType resolve(World world) { | |||
// return super.resolve(world); | |||
// } | |||
@Override | |||
public boolean isAnnotation() { | |||
World world = ((ReferenceType) getUpperBound()).getWorld(); | |||
ResolvedType annotationType = ResolvedType.ANNOTATION.resolve(world); | |||
if (getUpperBound() != null && ((ReferenceType) getUpperBound()).isAnnotation()) | |||
ReferenceType upper = (ReferenceType) typeVariable.getUpperBound(); | |||
if (upper.isAnnotation()) { | |||
return true; | |||
ReferenceType[] ifBounds = getAdditionalBounds(); | |||
} | |||
World world = upper.getWorld(); | |||
typeVariable.resolve(world); | |||
ResolvedType annotationType = ResolvedType.ANNOTATION.resolve(world); | |||
UnresolvedType[] ifBounds = typeVariable.getSuperInterfaces();// AdditionalBounds(); | |||
for (int i = 0; i < ifBounds.length; i++) { | |||
if (ifBounds[i].isAnnotation()) | |||
if (((ReferenceType) ifBounds[i]).isAnnotation()) { | |||
return true; | |||
if (ifBounds[i] == annotationType) | |||
} | |||
if (ifBounds[i].equals(annotationType)) { | |||
return true; // annotation itself does not have the annotation flag set in Java! | |||
} | |||
} | |||
return false; | |||
} | |||
@@ -125,6 +101,7 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T | |||
* return the signature for a *REFERENCE* to a type variable, which is simply: Tname; there is no bounds info included, that is | |||
* in the signature of the type variable itself | |||
*/ | |||
@Override | |||
public String getSignature() { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append("T"); | |||
@@ -133,19 +110,15 @@ public class TypeVariableReferenceType extends BoundedReferenceType implements T | |||
return sb.toString(); | |||
} | |||
public void write(DataOutputStream s) throws IOException { | |||
super.write(s); | |||
// TypeVariableDeclaringElement tvde = typeVariable.getDeclaringElement(); | |||
// if (tvde == null) { | |||
// s.writeInt(TypeVariable.UNKNOWN); | |||
// } else { | |||
// s.writeInt(typeVariable.getDeclaringElementKind()); | |||
// if (typeVariable.getDeclaringElementKind() == TypeVariable.TYPE) { | |||
// ((UnresolvedType)tvde).write(s); | |||
// } else if (typeVariable.getDeclaringElementKind() == TypeVariable.METHOD){ | |||
// // it's a method | |||
// ((ResolvedMember)tvde).write(s); | |||
// } | |||
// } | |||
/** | |||
* @return the name of the type variable | |||
*/ | |||
public String getTypeVariableName() { | |||
return typeVariable.getName(); | |||
} | |||
public ReferenceType getUpperBound() { | |||
return (ReferenceType) typeVariable.resolve(world).getUpperBound(); | |||
} | |||
} |
@@ -1,13 +1,10 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 2005 Contributors. | |||
* Copyright (c) 2005-2010 Contributors | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Eclipse Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://eclipse.org/legal/epl-v10.html | |||
* | |||
* Contributors: | |||
* Adrian Colyer Initial implementation | |||
* http://eclipse.org/legal/epl-v10.html | |||
* ******************************************************************/ | |||
package org.aspectj.weaver; | |||
@@ -15,8 +12,8 @@ import java.io.DataOutputStream; | |||
import java.io.IOException; | |||
/** | |||
* @author colyer Represents a type variable encountered in the Eclipse Source world, which when resolved will turn into a | |||
* TypeVariableReferenceType | |||
* @author Adrian Colyer | |||
* @author Andy Clement | |||
*/ | |||
public class UnresolvedTypeVariableReferenceType extends UnresolvedType implements TypeVariableReference { | |||
@@ -39,6 +36,7 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen | |||
this.typeKind = TypeKind.TYPE_VARIABLE; | |||
} | |||
@Override | |||
public ResolvedType resolve(World world) { | |||
TypeVariableDeclaringElement typeVariableScope = world.getTypeVariableLookupScope(); | |||
TypeVariable resolvedTypeVariable = null; | |||
@@ -64,6 +62,7 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen | |||
return tvrt; | |||
} | |||
@Override | |||
public boolean isTypeVariableReference() { | |||
return true; | |||
} | |||
@@ -72,11 +71,7 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen | |||
return typeVariable; | |||
} | |||
// public String getName() { | |||
// if (typeVariable == null) return "<type variable not set!>"; | |||
// return typeVariable.getDisplayName(); | |||
// } | |||
@Override | |||
public String toString() { | |||
if (typeVariable == null) { | |||
return "<type variable not set!>"; | |||
@@ -85,14 +80,17 @@ public class UnresolvedTypeVariableReferenceType extends UnresolvedType implemen | |||
} | |||
} | |||
@Override | |||
public String toDebugString() { | |||
return typeVariable.getName(); | |||
} | |||
@Override | |||
public void write(DataOutputStream s) throws IOException { | |||
super.write(s); | |||
} | |||
@Override | |||
public String getErasureSignature() { | |||
return typeVariable.getFirstBound().getSignature(); | |||
} |
@@ -23,9 +23,7 @@ public class WildcardedUnresolvedType extends UnresolvedType { | |||
// TODO does not cope with extra bounds '? extends A & B & C' | |||
public static final int UNBOUND = 0; | |||
public static final int EXTENDS = 1; | |||
public static final int SUPER = 2; | |||
public static final WildcardedUnresolvedType QUESTIONMARK = new WildcardedUnresolvedType("*", UnresolvedType.OBJECT, null); | |||
@@ -41,10 +39,12 @@ public class WildcardedUnresolvedType extends UnresolvedType { | |||
this.typeKind = TypeKind.WILDCARD; | |||
this.upperBound = upperBound; | |||
this.lowerBound = lowerBound; | |||
if (signature.charAt(0) == '-') | |||
if (signature.charAt(0) == '-') { | |||
boundKind = SUPER; | |||
if (signature.charAt(0) == '+') | |||
} | |||
if (signature.charAt(0) == '+') { | |||
boundKind = EXTENDS; | |||
} | |||
} | |||
public UnresolvedType getUpperBound() { |
@@ -282,7 +282,7 @@ public abstract class World implements Dump.INode { | |||
// fault in generic wildcard, can't be done earlier because of init | |||
// issues | |||
// TODO ought to be shared single instance representing this | |||
ResolvedType something = new BoundedReferenceType("*", "Ljava/lang/Object", this); | |||
ResolvedType something = getWildcard(); | |||
typeMap.put("?", something); | |||
return something; | |||
} | |||
@@ -316,6 +316,16 @@ public abstract class World implements Dump.INode { | |||
} | |||
} | |||
// Only need one representation of '?' in a world - can be shared | |||
private BoundedReferenceType wildcard; | |||
private BoundedReferenceType getWildcard() { | |||
if (wildcard == null) { | |||
wildcard = new BoundedReferenceType(this); | |||
} | |||
return wildcard; | |||
} | |||
/** | |||
* Called when a type is resolved - enables its type hierarchy to be finished off before we proceed | |||
*/ | |||
@@ -541,7 +551,7 @@ public abstract class World implements Dump.INode { | |||
ret = new BoundedReferenceType(lowerBound, false, this); | |||
} else { | |||
// must be ? on its own! | |||
ret = new BoundedReferenceType("*", "Ljava/lang/Object", this); | |||
ret = getWildcard(); | |||
} | |||
return ret; | |||
} | |||
@@ -726,6 +736,10 @@ public abstract class World implements Dump.INode { | |||
return crosscuttingMembersSet.getDeclareAnnotationOnMethods(); | |||
} | |||
// public List<DeclareTypeErrorOrWarning> getDeclareTypeEows() { | |||
// return crosscuttingMembersSet.getDeclareTypeEows(); | |||
// } | |||
public List<DeclareSoft> getDeclareSoft() { | |||
return crosscuttingMembersSet.getDeclareSofts(); | |||
} |
@@ -34,10 +34,12 @@ public class DeclareSoft extends Declare { | |||
this.pointcut = pointcut; | |||
} | |||
@Override | |||
public Object accept(PatternNodeVisitor visitor, Object data) { | |||
return visitor.visit(this, data); | |||
} | |||
@Override | |||
public Declare parameterizeWith(Map typeVariableBindingMap, World w) { | |||
DeclareSoft ret = new DeclareSoft(exception.parameterizeWith(typeVariableBindingMap, w), pointcut.parameterizeWith( | |||
typeVariableBindingMap, w)); | |||
@@ -45,6 +47,7 @@ public class DeclareSoft extends Declare { | |||
return ret; | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append("declare soft: "); | |||
@@ -55,13 +58,16 @@ public class DeclareSoft extends Declare { | |||
return buf.toString(); | |||
} | |||
@Override | |||
public boolean equals(Object other) { | |||
if (!(other instanceof DeclareSoft)) | |||
if (!(other instanceof DeclareSoft)) { | |||
return false; | |||
} | |||
DeclareSoft o = (DeclareSoft) other; | |||
return o.pointcut.equals(pointcut) && o.exception.equals(exception); | |||
} | |||
@Override | |||
public int hashCode() { | |||
int result = 19; | |||
result = 37 * result + pointcut.hashCode(); | |||
@@ -69,6 +75,7 @@ public class DeclareSoft extends Declare { | |||
return result; | |||
} | |||
@Override | |||
public void write(DataOutputStream s) throws IOException { | |||
s.writeByte(Declare.SOFT); | |||
exception.write(s); | |||
@@ -90,6 +97,7 @@ public class DeclareSoft extends Declare { | |||
return exception; | |||
} | |||
@Override | |||
public void resolve(IScope scope) { | |||
exception = exception.resolveBindings(scope, null, false, true); | |||
ResolvedType excType = exception.getExactType().resolve(scope.getWorld()); | |||
@@ -97,7 +105,8 @@ public class DeclareSoft extends Declare { | |||
if (excType.isTypeVariableReference()) { | |||
TypeVariableReferenceType typeVariableRT = (TypeVariableReferenceType) excType; | |||
// a declare soft in a generic abstract aspect, we need to check the upper bound | |||
excType = typeVariableRT.getUpperBound().resolve(scope.getWorld()); | |||
// WIBBLE | |||
excType = typeVariableRT.getTypeVariable().getFirstBound().resolve(scope.getWorld()); | |||
} | |||
if (!scope.getWorld().getCoreType(UnresolvedType.THROWABLE).isAssignableFrom(excType)) { | |||
scope.getWorld() | |||
@@ -118,10 +127,12 @@ public class DeclareSoft extends Declare { | |||
pointcut = pointcut.resolve(scope); | |||
} | |||
@Override | |||
public boolean isAdviceLike() { | |||
return false; | |||
} | |||
@Override | |||
public String getNameSuffix() { | |||
return "soft"; | |||
} |
@@ -138,7 +138,7 @@ public class ReferencePointcut extends Pointcut { | |||
searchType = scope.getEnclosingType(); | |||
} | |||
if (searchType.isTypeVariableReference()) { | |||
searchType = ((TypeVariableReference) searchType).getTypeVariable().getUpperBound().resolve(scope.getWorld()); | |||
searchType = ((TypeVariableReference) searchType).getTypeVariable().getFirstBound().resolve(scope.getWorld()); | |||
} | |||
arguments.resolveBindings(scope, bindings, true, true); |
@@ -972,10 +972,7 @@ public class WildTypePattern extends TypePattern { | |||
if (canCreateExactTypePattern) { | |||
TypeVariable tv = tvrType.getTypeVariable(); | |||
if (upperBound != null) { | |||
tv.setUpperBound(upperBound.getExactType()); | |||
} | |||
if (lowerBound != null) { | |||
tv.setLowerBound(lowerBound.getExactType()); | |||
tv.setSuperclass(upperBound.getExactType()); | |||
} | |||
if (additionalInterfaceBounds != null) { | |||
UnresolvedType[] ifBounds = new UnresolvedType[additionalInterfaceBounds.length]; |