From: aclement Date: Thu, 19 Feb 2009 21:04:10 +0000 (+0000) Subject: 148508, 265418: tests and fixes: array and varargs subtype patterns X-Git-Tag: pre268419~94 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=bb6a294312282d7caaf8a85d79b35a94e3f3c2d6;p=aspectj.git 148508, 265418: tests and fixes: array and varargs subtype patterns --- diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactTypePattern.java index 859e8316f..6f34590c5 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactTypePattern.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/ExactTypePattern.java @@ -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); + } } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java index 4c714b90c..5abdc7491 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/PatternParser.java @@ -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); } } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java index ed4f1ddf0..a5f7f0759 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/TypePattern.java @@ -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. + * + *

+ * Then we call resolveBindings() during compilation During concretization of enclosing pointcuts, we call remapAdviceFormals * - *

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. - *

-     * pointcut foo(String name): args(name);
-     * --> This makes a BindingTypePattern(0) pointing to the 0th formal
-     * 
-     * before(Foo f, String n): this(f) && foo(n) { ... }
-     * --> when resolveReferences is called on the args from the above, it
-     *     will return a BindingTypePattern(1)
-     * 
-     * before(Foo f): this(f) && foo(*) { ... }
-     * --> when resolveReferences is called on the args from the above, it
-     *     will return an ExactTypePattern(String)
-     * 
- */ + /** + * 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. + * + *
+	 * pointcut foo(String name): args(name);
+	 * --> This makes a BindingTypePattern(0) pointing to the 0th formal
+	 * 
+	 * before(Foo f, String n): this(f) && foo(n) { ... }
+	 * --> when resolveReferences is called on the args from the above, it
+	 *     will return a BindingTypePattern(1)
+	 * 
+	 * before(Foo f): this(f) && foo(*) { ... }
+	 * --> when resolveReferences is called on the args from the above, it
+	 *     will return an ExactTypePattern(String)
+	 * 
+ */ 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 ""; }//FIXME AV - bad! toString() cannot be parsed back (not idempotent) - - /* (non-Javadoc) + + public String toString() { + return ""; + }// 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; + } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java index 15ccbbd03..e4f5a4dbf 100644 --- a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java @@ -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) {