Browse Source

148508, 265418: tests and fixes: array and varargs subtype patterns

tags/pre268419
aclement 15 years ago
parent
commit
bb6a294312

+ 138
- 112
org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactTypePattern.java View File

@@ -10,7 +10,6 @@
* PARC initial implementation
* ******************************************************************/


package org.aspectj.weaver.patterns;

import java.io.DataInputStream;
@@ -36,57 +35,74 @@ public class ExactTypePattern extends TypePattern {
public static final Map primitiveTypesMap;
public static final Map boxedPrimitivesMap;
private static final Map boxedTypesMap;
static {
primitiveTypesMap = new HashMap();
primitiveTypesMap.put("int",int.class);
primitiveTypesMap.put("short",short.class);
primitiveTypesMap.put("long",long.class);
primitiveTypesMap.put("byte",byte.class);
primitiveTypesMap.put("char",char.class);
primitiveTypesMap.put("float",float.class);
primitiveTypesMap.put("double",double.class);
primitiveTypesMap.put("int", int.class);
primitiveTypesMap.put("short", short.class);
primitiveTypesMap.put("long", long.class);
primitiveTypesMap.put("byte", byte.class);
primitiveTypesMap.put("char", char.class);
primitiveTypesMap.put("float", float.class);
primitiveTypesMap.put("double", double.class);

boxedPrimitivesMap = new HashMap();
boxedPrimitivesMap.put("java.lang.Integer",Integer.class);
boxedPrimitivesMap.put("java.lang.Short",Short.class);
boxedPrimitivesMap.put("java.lang.Long",Long.class);
boxedPrimitivesMap.put("java.lang.Byte",Byte.class);
boxedPrimitivesMap.put("java.lang.Character",Character.class);
boxedPrimitivesMap.put("java.lang.Float",Float.class);
boxedPrimitivesMap.put("java.lang.Double",Double.class);

boxedPrimitivesMap.put("java.lang.Integer", Integer.class);
boxedPrimitivesMap.put("java.lang.Short", Short.class);
boxedPrimitivesMap.put("java.lang.Long", Long.class);
boxedPrimitivesMap.put("java.lang.Byte", Byte.class);
boxedPrimitivesMap.put("java.lang.Character", Character.class);
boxedPrimitivesMap.put("java.lang.Float", Float.class);
boxedPrimitivesMap.put("java.lang.Double", Double.class);

boxedTypesMap = new HashMap();
boxedTypesMap.put("int",Integer.class);
boxedTypesMap.put("short",Short.class);
boxedTypesMap.put("long",Long.class);
boxedTypesMap.put("byte",Byte.class);
boxedTypesMap.put("char",Character.class);
boxedTypesMap.put("float",Float.class);
boxedTypesMap.put("double",Double.class);
boxedTypesMap.put("int", Integer.class);
boxedTypesMap.put("short", Short.class);
boxedTypesMap.put("long", Long.class);
boxedTypesMap.put("byte", Byte.class);
boxedTypesMap.put("char", Character.class);
boxedTypesMap.put("float", Float.class);
boxedTypesMap.put("double", Double.class);

}
public ExactTypePattern(UnresolvedType type, boolean includeSubtypes,boolean isVarArgs) {
super(includeSubtypes,isVarArgs);

protected boolean matchesSubtypes(ResolvedType type) {
boolean match = super.matchesSubtypes(type);
if (match) {
return match;
}
// are we dealing with array funkyness - pattern might be jlObject[]+ and type jlString[]
if (type.isArray() && this.type.isArray()) {
ResolvedType componentType = type.getComponentType().resolve(type.getWorld());
UnresolvedType newPatternType = this.type.getComponentType();
ExactTypePattern etp = new ExactTypePattern(newPatternType, includeSubtypes, false);
return etp.matchesSubtypes(componentType, type);
}
return match;
}

public ExactTypePattern(UnresolvedType type, boolean includeSubtypes, boolean isVarArgs) {
super(includeSubtypes, isVarArgs);
this.type = type;
}
public boolean isArray() {
public boolean isArray() {
return type.isArray();
}
/* (non-Javadoc)

/*
* (non-Javadoc)
*
* @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
*/
protected boolean couldEverMatchSameTypesAs(TypePattern other) {
if (super.couldEverMatchSameTypesAs(other)) return true;
if (super.couldEverMatchSameTypesAs(other))
return true;
// false is necessary but not sufficient
UnresolvedType otherType = other.getExactType();
if (!ResolvedType.isMissing(otherType)) {
return type.equals(otherType);
}
}
if (other instanceof WildTypePattern) {
WildTypePattern owtp = (WildTypePattern) other;
String yourSimpleNamePrefix = owtp.getNamePatterns()[0].maybeGetSimpleName();
@@ -96,91 +112,99 @@ public class ExactTypePattern extends TypePattern {
}
return true;
}
protected boolean matchesExactly(ResolvedType matchType) {
boolean typeMatch = this.type.equals(matchType);
if (!typeMatch && (matchType.isParameterizedType() || matchType.isGenericType())) {
typeMatch = this.type.equals(matchType.getRawType());
}
if (!typeMatch && matchType.isTypeVariableReference()) {
typeMatch = matchesTypeVariable((TypeVariableReferenceType)matchType);
typeMatch = matchesTypeVariable((TypeVariableReferenceType) matchType);
}
annotationPattern.resolve(matchType.getWorld());
boolean annMatch = false;
if (matchType.temporaryAnnotationTypes!=null) {
annMatch = annotationPattern.matches(matchType,matchType.temporaryAnnotationTypes).alwaysTrue();
} else {
annMatch = annotationPattern.matches(matchType).alwaysTrue();
}
if (matchType.temporaryAnnotationTypes != null) {
annMatch = annotationPattern.matches(matchType, matchType.temporaryAnnotationTypes).alwaysTrue();
} else {
annMatch = annotationPattern.matches(matchType).alwaysTrue();
}
return (typeMatch && annMatch);
}
private boolean matchesTypeVariable(TypeVariableReferenceType matchType) {
// was this method previously coded to return false *on purpose* ?? pr124808
return this.type.equals(((TypeVariableReference)matchType).getTypeVariable().getFirstBound());
//return false;
// was this method previously coded to return false *on purpose* ?? pr124808
return this.type.equals(((TypeVariableReference) matchType).getTypeVariable().getFirstBound());
// return false;
}
protected boolean matchesExactly(ResolvedType matchType, ResolvedType annotatedType) {
boolean typeMatch = this.type.equals(matchType);
if (!typeMatch && (matchType.isParameterizedType() || matchType.isGenericType())) {
typeMatch = this.type.equals(matchType.getRawType());
}
if (!typeMatch && matchType.isTypeVariableReference()) {
typeMatch = matchesTypeVariable((TypeVariableReferenceType)matchType);
typeMatch = matchesTypeVariable((TypeVariableReferenceType) matchType);
}
annotationPattern.resolve(matchType.getWorld());
boolean annMatch = false;
if (annotatedType.temporaryAnnotationTypes!=null) {
annMatch = annotationPattern.matches(annotatedType,annotatedType.temporaryAnnotationTypes).alwaysTrue();
} else {
annMatch = annotationPattern.matches(annotatedType).alwaysTrue();
}
return (typeMatch && annMatch);
boolean annMatch = false;
if (annotatedType.temporaryAnnotationTypes != null) {
annMatch = annotationPattern.matches(annotatedType, annotatedType.temporaryAnnotationTypes).alwaysTrue();
} else {
annMatch = annotationPattern.matches(annotatedType).alwaysTrue();
}
return (typeMatch && annMatch);
}

public UnresolvedType getType() {
return type;
}
public UnresolvedType getType() { return type; }

// true if (matchType instanceof this.type)
public FuzzyBoolean matchesInstanceof(ResolvedType matchType) {
// in our world, Object is assignable from anything
annotationPattern.resolve(matchType.getWorld());
if (type.equals(ResolvedType.OBJECT))
return FuzzyBoolean.YES.and(annotationPattern.matches(matchType));
if (type.equals(ResolvedType.OBJECT))
return FuzzyBoolean.YES.and(annotationPattern.matches(matchType));
if (type.resolve(matchType.getWorld()).isAssignableFrom(matchType)) {
return FuzzyBoolean.YES.and(annotationPattern.matches(matchType));
}
// fix for PR 64262 - shouldn't try to coerce primitives
if (type.isPrimitiveType()) {
return FuzzyBoolean.NO;
} else {
return matchType.isCoerceableFrom(type.resolve(matchType.getWorld())) ? FuzzyBoolean.MAYBE : FuzzyBoolean.NO;
return matchType.isCoerceableFrom(type.resolve(matchType.getWorld())) ? FuzzyBoolean.MAYBE : FuzzyBoolean.NO;
}
}
public boolean equals(Object other) {
if (!(other instanceof ExactTypePattern)) return false;
if (other instanceof BindingTypePattern) return false;
ExactTypePattern o = (ExactTypePattern)other;
if (includeSubtypes != o.includeSubtypes) return false;
if (isVarArgs != o.isVarArgs) return false;
if (!typeParameters.equals(o.typeParameters)) return false;
return (o.type.equals(this.type) && o.annotationPattern.equals(this.annotationPattern));
}
public int hashCode() {
int result = 17;
result = 37*result + type.hashCode();
result = 37*result + new Boolean(includeSubtypes).hashCode();
result = 37*result + new Boolean(isVarArgs).hashCode();
result = 37*result + typeParameters.hashCode();
result = 37*result + annotationPattern.hashCode();
return result;
}

private static final byte EXACT_VERSION = 1; // rev if changed

public boolean equals(Object other) {
if (!(other instanceof ExactTypePattern))
return false;
if (other instanceof BindingTypePattern)
return false;
ExactTypePattern o = (ExactTypePattern) other;
if (includeSubtypes != o.includeSubtypes)
return false;
if (isVarArgs != o.isVarArgs)
return false;
if (!typeParameters.equals(o.typeParameters))
return false;
return (o.type.equals(this.type) && o.annotationPattern.equals(this.annotationPattern));
}

public int hashCode() {
int result = 17;
result = 37 * result + type.hashCode();
result = 37 * result + new Boolean(includeSubtypes).hashCode();
result = 37 * result + new Boolean(isVarArgs).hashCode();
result = 37 * result + typeParameters.hashCode();
result = 37 * result + annotationPattern.hashCode();
return result;
}

private static final byte EXACT_VERSION = 1; // rev if changed

public void write(DataOutputStream out) throws IOException {
out.writeByte(TypePattern.EXACT);
out.writeByte(EXACT_VERSION);
@@ -191,27 +215,28 @@ public class ExactTypePattern extends TypePattern {
typeParameters.write(out);
writeLocation(out);
}
public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
return readTypePattern150(s,context);
if (s.getMajorVersion() >= AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
return readTypePattern150(s, context);
} else {
return readTypePatternOldStyle(s,context);
}
}
return readTypePatternOldStyle(s, context);
}
}
public static TypePattern readTypePattern150(VersionedDataInputStream s, ISourceContext context) throws IOException {
byte version = s.readByte();
if (version > EXACT_VERSION) throw new BCException("ExactTypePattern was written by a more recent version of AspectJ");
if (version > EXACT_VERSION)
throw new BCException("ExactTypePattern was written by a more recent version of AspectJ");
TypePattern ret = new ExactTypePattern(UnresolvedType.read(s), s.readBoolean(), s.readBoolean());
ret.setAnnotationTypePattern(AnnotationTypePattern.read(s,context));
ret.setTypeParameters(TypePatternList.read(s,context));
ret.setAnnotationTypePattern(AnnotationTypePattern.read(s, context));
ret.setTypeParameters(TypePatternList.read(s, context));
ret.readLocation(context, s);
return ret;
}

public static TypePattern readTypePatternOldStyle(DataInputStream s, ISourceContext context) throws IOException {
TypePattern ret = new ExactTypePattern(UnresolvedType.read(s), s.readBoolean(),false);
TypePattern ret = new ExactTypePattern(UnresolvedType.read(s), s.readBoolean(), false);
ret.readLocation(context, s);
return ret;
}
@@ -224,27 +249,28 @@ public class ExactTypePattern extends TypePattern {
buff.append(' ');
}
String typeString = type.toString();
if (isVarArgs) typeString = typeString.substring(0,typeString.lastIndexOf('['));
if (isVarArgs)
typeString = typeString.substring(0, typeString.lastIndexOf('['));
buff.append(typeString);
if (includeSubtypes) buff.append('+');
if (isVarArgs) buff.append("...");
if (includeSubtypes)
buff.append('+');
if (isVarArgs)
buff.append("...");
if (annotationPattern != AnnotationTypePattern.ANY) {
buff.append(')');
}
return buff.toString();
}
public TypePattern resolveBindings(IScope scope, Bindings bindings,
boolean allowBinding, boolean requireExactType)
{
}

public TypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
throw new BCException("trying to re-resolve");
}
/**
* return a version of this type pattern with all type variables references replaced
* by the corresponding entry in the map.
* return a version of this type pattern with all type variables references replaced by the corresponding entry in the map.
*/
public TypePattern parameterizeWith(Map typeVariableMap,World w) {
public TypePattern parameterizeWith(Map typeVariableMap, World w) {
UnresolvedType newType = type;
if (type.isTypeVariableReference()) {
TypeVariableReference t = (TypeVariableReference) type;
@@ -255,14 +281,14 @@ public class ExactTypePattern extends TypePattern {
} else if (type.isParameterizedType()) {
newType = w.resolve(type).parameterize(typeVariableMap);
}
ExactTypePattern ret = new ExactTypePattern(newType,includeSubtypes,isVarArgs);
ret.annotationPattern = annotationPattern.parameterizeWith(typeVariableMap,w);
ExactTypePattern ret = new ExactTypePattern(newType, includeSubtypes, isVarArgs);
ret.annotationPattern = annotationPattern.parameterizeWith(typeVariableMap, w);
ret.copyLocationFrom(this);
return ret;
}
public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}
public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}

}

+ 9
- 3
org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java View File

@@ -864,10 +864,16 @@ public class PatternParser {
TypePatternList typeParameters = maybeParseTypeParameterList();
int endPos = tokenSource.peek(-1).getEnd();

boolean isVarArgs = maybeEat("...");

boolean includeSubtypes = maybeEat("+");

// TODO do we need to associate the + with either the type or the array?
while (maybeEat("[")) {
eat("]");
dim++;
}

boolean isVarArgs = maybeEat("...");

// ??? what about the source location of any's????
if (names.size() == 1 && ((NamePattern) names.get(0)).isAny() && dim == 0 && !isVarArgs && typeParameters == null)
return TypePattern.ANY;
@@ -1599,7 +1605,7 @@ public class PatternParser {
public void checkEof() {
IToken last = tokenSource.next();
if (last != IToken.EOF) {
throw new ParserException("unexpected pointcut element", last);
throw new ParserException("unexpected pointcut element: " + last.toString(), last);
}
}


+ 274
- 234
org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java View File

@@ -10,7 +10,6 @@
* PARC initial implementation
* ******************************************************************/


package org.aspectj.weaver.patterns;

import java.io.DataOutputStream;
@@ -30,90 +29,99 @@ import org.aspectj.weaver.UnresolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.WeaverMessages;
import org.aspectj.weaver.World;

/**
* On creation, type pattern only contains WildTypePattern nodes, not BindingType or ExactType.
* On creation, type pattern only contains WildTypePattern nodes, not BindingType or ExactType.
*
* <p>
* Then we call resolveBindings() during compilation During concretization of enclosing pointcuts, we call remapAdviceFormals
*
* <p>Then we call resolveBindings() during compilation
* During concretization of enclosing pointcuts, we call remapAdviceFormals
*
* @author Erik Hilsdale
* @author Jim Hugunin
*/
public abstract class TypePattern extends PatternNode {
public static class MatchKind {
private String name;
public MatchKind(String name) { this.name = name; }
public String toString() { return name; }

public MatchKind(String name) {
this.name = name;
}

public String toString() {
return name;
}
}
public static final MatchKind STATIC = new MatchKind("STATIC");
public static final MatchKind DYNAMIC = new MatchKind("DYNAMIC");
public static final TypePattern ELLIPSIS = new EllipsisTypePattern();
public static final TypePattern ANY = new AnyTypePattern();
public static final TypePattern NO = new NoTypePattern();

protected boolean includeSubtypes;
protected boolean isVarArgs = false;
protected AnnotationTypePattern annotationPattern = AnnotationTypePattern.ANY;
protected TypePatternList typeParameters = TypePatternList.EMPTY;
protected TypePattern(boolean includeSubtypes,boolean isVarArgs,TypePatternList typeParams) {
protected TypePattern(boolean includeSubtypes, boolean isVarArgs, TypePatternList typeParams) {
this.includeSubtypes = includeSubtypes;
this.isVarArgs = isVarArgs;
this.typeParameters = (typeParams == null ? TypePatternList.EMPTY : typeParams);
}
protected TypePattern(boolean includeSubtypes, boolean isVarArgs) {
this(includeSubtypes,isVarArgs,null);
this(includeSubtypes, isVarArgs, null);
}

public AnnotationTypePattern getAnnotationPattern() {
return annotationPattern;
}
public AnnotationTypePattern getAnnotationPattern() {
return annotationPattern;
}

public boolean isVarArgs() {
return isVarArgs;
}
public boolean isVarArgs() {
return isVarArgs;
}

public boolean isStarAnnotation() {
return annotationPattern == AnnotationTypePattern.ANY;
}
public boolean isArray() {
return false;
}
protected TypePattern(boolean includeSubtypes) {
this(includeSubtypes,false);
this(includeSubtypes, false);
}
public void setAnnotationTypePattern(AnnotationTypePattern annPatt) {
this.annotationPattern = annPatt;
}
public void setTypeParameters(TypePatternList typeParams) {
this.typeParameters = typeParams;
}
public TypePatternList getTypeParameters() {
return this.typeParameters;
}
public void setIsVarArgs(boolean isVarArgs) {
this.isVarArgs = isVarArgs;
}
// answer conservatively...
protected boolean couldEverMatchSameTypesAs(TypePattern other) {
if (this.includeSubtypes || other.includeSubtypes) return true;
if (this.annotationPattern != AnnotationTypePattern.ANY) return true;
if (other.annotationPattern != AnnotationTypePattern.ANY) return true;
if (this.includeSubtypes || other.includeSubtypes)
return true;
if (this.annotationPattern != AnnotationTypePattern.ANY)
return true;
if (other.annotationPattern != AnnotationTypePattern.ANY)
return true;
return false;
}
//XXX non-final for Not, && and ||
// XXX non-final for Not, && and ||
public boolean matchesStatically(ResolvedType type) {
if (includeSubtypes) {
return matchesSubtypes(type);
@@ -121,64 +129,66 @@ public abstract class TypePattern extends PatternNode {
return matchesExactly(type);
}
}
public abstract FuzzyBoolean matchesInstanceof(ResolvedType type);

public abstract FuzzyBoolean matchesInstanceof(ResolvedType type);

public final FuzzyBoolean matches(ResolvedType type, MatchKind kind) {
// FuzzyBoolean typeMatch = null;
//??? This is part of gracefully handling missing references
if (type.isMissing()) return FuzzyBoolean.NO;
// FuzzyBoolean typeMatch = null;
// ??? This is part of gracefully handling missing references
if (type.isMissing())
return FuzzyBoolean.NO;

if (kind == STATIC) {
// typeMatch = FuzzyBoolean.fromBoolean(matchesStatically(type));
// return typeMatch.and(annotationPattern.matches(type));
return FuzzyBoolean.fromBoolean(matchesStatically(type));
// typeMatch = FuzzyBoolean.fromBoolean(matchesStatically(type));
// return typeMatch.and(annotationPattern.matches(type));
return FuzzyBoolean.fromBoolean(matchesStatically(type));
} else if (kind == DYNAMIC) {
//System.err.println("matching: " + this + " with " + type);
// typeMatch = matchesInstanceof(type);
//System.err.println(" got: " + ret);
// return typeMatch.and(annotationPattern.matches(type));
return matchesInstanceof(type);
// System.err.println("matching: " + this + " with " + type);
// typeMatch = matchesInstanceof(type);
// System.err.println(" got: " + ret);
// return typeMatch.and(annotationPattern.matches(type));
return matchesInstanceof(type);
} else {
throw new IllegalArgumentException("kind must be DYNAMIC or STATIC");
}
}
protected abstract boolean matchesExactly(ResolvedType type);
protected abstract boolean matchesExactly(ResolvedType type, ResolvedType annotatedType);

protected boolean matchesSubtypes(ResolvedType type) {
//System.out.println("matching: " + this + " to " + type);
// System.out.println("matching: " + this + " to " + type);
if (matchesExactly(type)) {
//System.out.println(" true");
return true;
}

// pr124808
Iterator typesIterator = null;
if (type.isTypeVariableReference()) {
typesIterator = ((TypeVariableReference)type).getTypeVariable().getFirstBound().resolve(type.getWorld()).getDirectSupertypes();
typesIterator = ((TypeVariableReference) type).getTypeVariable().getFirstBound().resolve(type.getWorld())
.getDirectSupertypes();
} else {
// pr223605
if (type.isRawType()) {
type = type.getGenericType();
}
typesIterator = type.getDirectSupertypes();
// pr223605
if (type.isRawType()) {
type = type.getGenericType();
}
typesIterator = type.getDirectSupertypes();
}
// FuzzyBoolean ret = FuzzyBoolean.NO; // ??? -eh
for (Iterator i = typesIterator; i.hasNext(); ) {
ResolvedType superType = (ResolvedType)i.next();
// TODO asc generics, temporary whilst matching isnt aware..
//if (superType.isParameterizedType()) superType = superType.getRawType().resolve(superType.getWorld());
if (matchesSubtypes(superType,type)) return true;

for (Iterator i = typesIterator; i.hasNext();) {
ResolvedType superType = (ResolvedType) i.next();
if (matchesSubtypes(superType, type)) {
return true;
}
}
return false;
}
protected boolean matchesSubtypes(ResolvedType superType, ResolvedType annotatedType) {
//System.out.println("matching: " + this + " to " + type);
if (matchesExactly(superType,annotatedType)) {
//System.out.println(" true");
// System.out.println("matching2: " + this + " to " + superType);
if (matchesExactly(superType, annotatedType)) {
// System.out.println(" true");
return true;
}
// If an ITD is applied, it will be put onto the generic type, not the parameterized or raw form
@@ -186,95 +196,94 @@ public abstract class TypePattern extends PatternNode {
superType = superType.getGenericType();
}
// FuzzyBoolean ret = FuzzyBoolean.NO; // ??? -eh
for (Iterator i = superType.getDirectSupertypes(); i.hasNext(); ) {
ResolvedType superSuperType = (ResolvedType)i.next();
if (matchesSubtypes(superSuperType,annotatedType)) return true;
for (Iterator i = superType.getDirectSupertypes(); i.hasNext();) {
ResolvedType superSuperType = (ResolvedType) i.next();
if (matchesSubtypes(superSuperType, annotatedType))
return true;
}
return false;
}
public UnresolvedType resolveExactType(IScope scope, Bindings bindings) {
TypePattern p = resolveBindings(scope, bindings, false, true);
if (!(p instanceof ExactTypePattern)) return ResolvedType.MISSING;
return ((ExactTypePattern)p).getType();
if (!(p instanceof ExactTypePattern))
return ResolvedType.MISSING;
return ((ExactTypePattern) p).getType();
}
public UnresolvedType getExactType() {
if (this instanceof ExactTypePattern) return ((ExactTypePattern)this).getType();
else return ResolvedType.MISSING;
if (this instanceof ExactTypePattern)
return ((ExactTypePattern) this).getType();
else
return ResolvedType.MISSING;
}
protected TypePattern notExactType(IScope s) {
s.getMessageHandler().handleMessage(MessageUtil.error(
WeaverMessages.format(WeaverMessages.EXACT_TYPE_PATTERN_REQD), getSourceLocation()));
s.getMessageHandler().handleMessage(
MessageUtil.error(WeaverMessages.format(WeaverMessages.EXACT_TYPE_PATTERN_REQD), getSourceLocation()));
return NO;
}
// public boolean assertExactType(IMessageHandler m) {
// if (this instanceof ExactTypePattern) return true;
//
// //XXX should try harder to avoid multiple errors for one problem
// m.handleMessage(MessageUtil.error("exact type pattern required", getSourceLocation()));
// return false;
// }
// public boolean assertExactType(IMessageHandler m) {
// if (this instanceof ExactTypePattern) return true;
//
// //XXX should try harder to avoid multiple errors for one problem
// m.handleMessage(MessageUtil.error("exact type pattern required", getSourceLocation()));
// return false;
// }

/**
* This can modify in place, or return a new TypePattern if the type changes.
*/
public TypePattern resolveBindings(IScope scope, Bindings bindings,
boolean allowBinding, boolean requireExactType)
{
annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
return this;
}
public void resolve(World world) {
annotationPattern.resolve(world);
}
/**
* return a version of this type pattern in which all type variable references have been
* replaced by their corresponding entry in the map.
*/
public abstract TypePattern parameterizeWith(Map typeVariableMap,World w);
public TypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
annotationPattern = annotationPattern.resolveBindings(scope, bindings, allowBinding);
return this;
}

public void resolve(World world) {
annotationPattern.resolve(world);
}

/**
* return a version of this type pattern in which all type variable references have been replaced by their corresponding entry
* in the map.
*/
public abstract TypePattern parameterizeWith(Map typeVariableMap, World w);

public void postRead(ResolvedType enclosingType) {
}
public boolean isStar() {
return false;
}

/**
* This is called during concretization of pointcuts, it is used by BindingTypePattern
* to return a new BindingTypePattern with a formal index appropiate for the advice,
* rather than for the lexical declaration, i.e. this handles transforamtions through
* named pointcuts.
* <pre>
* pointcut foo(String name): args(name);
* --&gt; This makes a BindingTypePattern(0) pointing to the 0th formal
*
* before(Foo f, String n): this(f) && foo(n) { ... }
* --&gt; when resolveReferences is called on the args from the above, it
* will return a BindingTypePattern(1)
*
* before(Foo f): this(f) && foo(*) { ... }
* --&gt; when resolveReferences is called on the args from the above, it
* will return an ExactTypePattern(String)
* </pre>
*/
/**
* This is called during concretization of pointcuts, it is used by BindingTypePattern to return a new BindingTypePattern with a
* formal index appropiate for the advice, rather than for the lexical declaration, i.e. this handles transforamtions through
* named pointcuts.
*
* <pre>
* pointcut foo(String name): args(name);
* --&gt; This makes a BindingTypePattern(0) pointing to the 0th formal
*
* before(Foo f, String n): this(f) &amp;&amp; foo(n) { ... }
* --&gt; when resolveReferences is called on the args from the above, it
* will return a BindingTypePattern(1)
*
* before(Foo f): this(f) &amp;&amp; foo(*) { ... }
* --&gt; when resolveReferences is called on the args from the above, it
* will return an ExactTypePattern(String)
* </pre>
*/
public TypePattern remapAdviceFormals(IntMap bindings) {
return this;
}


public static final byte WILD = 1;
public static final byte EXACT = 2;
public static final byte BINDING = 3;
public static final byte ELLIPSIS_KEY = 4;
public static final byte ANY_KEY = 5;
public static final byte ELLIPSIS_KEY = 4;
public static final byte ANY_KEY = 5;
public static final byte NOT = 6;
public static final byte OR = 7;
public static final byte AND = 8;
@@ -284,18 +293,29 @@ public abstract class TypePattern extends PatternNode {

public static TypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
byte key = s.readByte();
switch(key) {
case WILD: return WildTypePattern.read(s, context);
case EXACT: return ExactTypePattern.read(s, context);
case BINDING: return BindingTypePattern.read(s, context);
case ELLIPSIS_KEY: return ELLIPSIS;
case ANY_KEY: return ANY;
case NO_KEY: return NO;
case NOT: return NotTypePattern.read(s, context);
case OR: return OrTypePattern.read(s, context);
case AND: return AndTypePattern.read(s, context);
case ANY_WITH_ANNO: return AnyWithAnnotationTypePattern.read(s,context);
case HAS_MEMBER: return HasMemberTypePattern.read(s,context);
switch (key) {
case WILD:
return WildTypePattern.read(s, context);
case EXACT:
return ExactTypePattern.read(s, context);
case BINDING:
return BindingTypePattern.read(s, context);
case ELLIPSIS_KEY:
return ELLIPSIS;
case ANY_KEY:
return ANY;
case NO_KEY:
return NO;
case NOT:
return NotTypePattern.read(s, context);
case OR:
return OrTypePattern.read(s, context);
case AND:
return AndTypePattern.read(s, context);
case ANY_WITH_ANNO:
return AnyWithAnnotationTypePattern.read(s, context);
case HAS_MEMBER:
return HasMemberTypePattern.read(s, context);
}
throw new BCException("unknown TypePattern kind: " + key);
}
@@ -307,28 +327,32 @@ public abstract class TypePattern extends PatternNode {
}

class EllipsisTypePattern extends TypePattern {
/**
* Constructor for EllipsisTypePattern.
*
* @param includeSubtypes
*/
public EllipsisTypePattern() {
super(false,false,new TypePatternList());
super(false, false, new TypePatternList());
}

/* (non-Javadoc)
/*
* (non-Javadoc)
*
* @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
*/
protected boolean couldEverMatchSameTypesAs(TypePattern other) {
return true;
}

/**
* @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
*/
protected boolean matchesExactly(ResolvedType type) {
return false;
}
protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
return false;
}
@@ -346,50 +370,59 @@ class EllipsisTypePattern extends TypePattern {
public void write(DataOutputStream s) throws IOException {
s.writeByte(ELLIPSIS_KEY);
}
public String toString() { return ".."; }
/* (non-Javadoc)

public String toString() {
return "..";
}

/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return (obj instanceof EllipsisTypePattern);
}
/* (non-Javadoc)

/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return 17 * 37;
}

public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}
public TypePattern parameterizeWith(Map typeVariableMap,World w) {
return this;
}
public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}

public TypePattern parameterizeWith(Map typeVariableMap, World w) {
return this;
}

}

class AnyTypePattern extends TypePattern {
/**
* Constructor for EllipsisTypePattern.
*
* @param includeSubtypes
*/
public AnyTypePattern() {
super(false,false,new TypePatternList());
super(false, false, new TypePatternList());
}

/* (non-Javadoc)
/*
* (non-Javadoc)
*
* @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
*/
protected boolean couldEverMatchSameTypesAs(TypePattern other) {
return true;
}

/**
* @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
*/
@@ -400,7 +433,7 @@ class AnyTypePattern extends TypePattern {
protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
return true;
}
/**
* @see org.aspectj.weaver.patterns.TypePattern#matchesInstanceof(IType)
*/
@@ -418,56 +451,55 @@ class AnyTypePattern extends TypePattern {
/**
* @see org.aspectj.weaver.patterns.TypePattern#matches(IType, MatchKind)
*/
// public FuzzyBoolean matches(IType type, MatchKind kind) {
// return FuzzyBoolean.YES;
// }

// public FuzzyBoolean matches(IType type, MatchKind kind) {
// return FuzzyBoolean.YES;
// }
/**
* @see org.aspectj.weaver.patterns.TypePattern#matchesSubtypes(IType)
*/
protected boolean matchesSubtypes(ResolvedType type) {
return true;
}

public boolean isStar() {
return true;
}
public String toString() { return "*"; }

public String toString() {
return "*";
}

public boolean equals(Object obj) {
return (obj instanceof AnyTypePattern);
}
public int hashCode() {
return 37;
}

public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}
public TypePattern parameterizeWith(Map arg0,World w) {
return this;
}
public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}
public TypePattern parameterizeWith(Map arg0, World w) {
return this;
}
}

/**
* This type represents a type pattern of '*' but with an annotation specified,
* e.g. '@Color *'
* This type represents a type pattern of '*' but with an annotation specified, e.g. '@Color *'
*/
class AnyWithAnnotationTypePattern extends TypePattern {
public AnyWithAnnotationTypePattern(AnnotationTypePattern atp) {
super(false,false);
super(false, false);
annotationPattern = atp;
}

public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this,data);
return visitor.visit(this, data);
}
protected boolean couldEverMatchSameTypesAs(TypePattern other) {
return true;
}
@@ -475,18 +507,17 @@ class AnyWithAnnotationTypePattern extends TypePattern {
protected boolean matchesExactly(ResolvedType type) {
annotationPattern.resolve(type.getWorld());
boolean b = false;
if (type.temporaryAnnotationTypes!=null) {
b = annotationPattern.matches(type,type.temporaryAnnotationTypes).alwaysTrue();
if (type.temporaryAnnotationTypes != null) {
b = annotationPattern.matches(type, type.temporaryAnnotationTypes).alwaysTrue();
} else {
b = annotationPattern.matches(type).alwaysTrue();
}
return b;
}

protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
annotationPattern.resolve(type.getWorld());
return annotationPattern.matches(annotatedType).alwaysTrue();
return annotationPattern.matches(annotatedType).alwaysTrue();
}

public FuzzyBoolean matchesInstanceof(ResolvedType type) {
@@ -496,70 +527,76 @@ class AnyWithAnnotationTypePattern extends TypePattern {
return FuzzyBoolean.MAYBE;
}

public TypePattern parameterizeWith(Map typeVariableMap,World w) {
AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(this.annotationPattern.parameterizeWith(typeVariableMap,w));
public TypePattern parameterizeWith(Map typeVariableMap, World w) {
AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(this.annotationPattern.parameterizeWith(
typeVariableMap, w));
ret.copyLocationFrom(this);
return ret;
}
public void write(DataOutputStream s) throws IOException {
s.writeByte(TypePattern.ANY_WITH_ANNO);
annotationPattern.write(s);
writeLocation(s);
}
public static TypePattern read(VersionedDataInputStream s,ISourceContext c) throws IOException {
AnnotationTypePattern annPatt = AnnotationTypePattern.read(s,c);
AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annPatt);
ret.readLocation(c, s);
return ret;
public static TypePattern read(VersionedDataInputStream s, ISourceContext c) throws IOException {
AnnotationTypePattern annPatt = AnnotationTypePattern.read(s, c);
AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annPatt);
ret.readLocation(c, s);
return ret;
}

// public FuzzyBoolean matches(IType type, MatchKind kind) {
// return FuzzyBoolean.YES;
// }
// public FuzzyBoolean matches(IType type, MatchKind kind) {
// return FuzzyBoolean.YES;
// }

protected boolean matchesSubtypes(ResolvedType type) {
return true;
}
public boolean isStar() {
return false;
}
public String toString() { return annotationPattern+" *"; }

public String toString() {
return annotationPattern + " *";
}

public boolean equals(Object obj) {
if (!(obj instanceof AnyWithAnnotationTypePattern)) return false;
if (!(obj instanceof AnyWithAnnotationTypePattern))
return false;
AnyWithAnnotationTypePattern awatp = (AnyWithAnnotationTypePattern) obj;
return (annotationPattern.equals(awatp.annotationPattern));
}
public int hashCode() {
return annotationPattern.hashCode();
}
}

class NoTypePattern extends TypePattern {
public NoTypePattern() {
super(false,false,new TypePatternList());
super(false, false, new TypePatternList());
}

/* (non-Javadoc)
/*
* (non-Javadoc)
*
* @see org.aspectj.weaver.patterns.TypePattern#couldEverMatchSameTypesAs(org.aspectj.weaver.patterns.TypePattern)
*/
protected boolean couldEverMatchSameTypesAs(TypePattern other) {
return false;
}

/**
* @see org.aspectj.weaver.patterns.TypePattern#matchesExactly(IType)
*/
protected boolean matchesExactly(ResolvedType type) {
return false;
}
protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
return false;
}
@@ -581,44 +618,47 @@ class NoTypePattern extends TypePattern {
/**
* @see org.aspectj.weaver.patterns.TypePattern#matches(IType, MatchKind)
*/
// public FuzzyBoolean matches(IType type, MatchKind kind) {
// return FuzzyBoolean.YES;
// }

// public FuzzyBoolean matches(IType type, MatchKind kind) {
// return FuzzyBoolean.YES;
// }
/**
* @see org.aspectj.weaver.patterns.TypePattern#matchesSubtypes(IType)
*/
protected boolean matchesSubtypes(ResolvedType type) {
return false;
}

public boolean isStar() {
return false;
}
public String toString() { return "<nothing>"; }//FIXME AV - bad! toString() cannot be parsed back (not idempotent)
/* (non-Javadoc)

public String toString() {
return "<nothing>";
}// FIXME AV - bad! toString() cannot be parsed back (not idempotent)

/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
return (obj instanceof NoTypePattern);
}
/* (non-Javadoc)

/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return 17 * 37 * 37;
}

public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}
public TypePattern parameterizeWith(Map arg0,World w) {
return this;
}
}
public Object accept(PatternNodeVisitor visitor, Object data) {
return visitor.visit(this, data);
}

public TypePattern parameterizeWith(Map arg0, World w) {
return this;
}
}

+ 8
- 6
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java View File

@@ -21,11 +21,6 @@ import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.VersionedDataInputStream;
import org.aspectj.weaver.World;
import org.aspectj.weaver.patterns.Bindings;
import org.aspectj.weaver.patterns.PatternParser;
import org.aspectj.weaver.patterns.TestScope;
import org.aspectj.weaver.patterns.TypePattern;
import org.aspectj.weaver.patterns.WildTypePattern;
import org.aspectj.weaver.reflect.ReflectionWorld;

public class TypePatternTestCase extends PatternsTestCase {
@@ -170,13 +165,17 @@ public class TypePatternTestCase extends PatternsTestCase {
checkMatch("*[][]", "java.lang.Object", false);
checkMatch("*[]", "java.lang.Object[]", true);
checkMatch("*[][]", "java.lang.Object[][]", true);
checkMatch("java.lang.Object+", "java.lang.Object[]", true);
checkMatch("java.lang.Object[]", "java.lang.Object", false);
checkMatch("java.lang.Object[]", "java.lang.Object[]", true);
checkMatch("java.lang.Object[][]", "java.lang.Object[][]", true);
checkMatch("java.lang.String[]", "java.lang.Object", false);
checkMatch("java.lang.String[]", "java.lang.Object[]", false);
checkMatch("java.lang.String[][]", "java.lang.Object[][]", false);
checkMatch("java.lang.Object+[]", "java.lang.String[][]", true);
checkMatch("java.lang.Object+[]", "java.lang.String[]", true);
checkMatch("java.lang.Object+[]", "int[][]", true);
checkMatch("java.lang.Object+[]", "int[]", false);
}

private void checkIllegalInstanceofMatch(String pattern, String name) {
@@ -208,7 +207,10 @@ public class TypePatternTestCase extends PatternsTestCase {
}

private TypePattern makeTypePattern(String pattern) {
return new PatternParser(pattern).parseSingleTypePattern();
PatternParser pp = new PatternParser(pattern);
TypePattern tp = pp.parseSingleTypePattern();
pp.checkEof();
return tp;
}

private void checkMatch(String pattern, String name, boolean shouldMatch) {

Loading…
Cancel
Save