* PARC initial implementation
* ******************************************************************/
-
package org.aspectj.weaver.patterns;
import java.io.DataOutputStream;
import org.aspectj.weaver.World;
/**
- * The PatternParser always creates WildTypePatterns for type patterns in pointcut
- * expressions (apart from *, which is sometimes directly turned into TypePattern.ANY).
- * resolveBindings() tries to work out what we've really got and turn it into a type
- * pattern that we can use for matching. This will normally be either an ExactTypePattern
- * or a WildTypePattern.
+ * The PatternParser always creates WildTypePatterns for type patterns in pointcut expressions (apart from *, which is sometimes
+ * directly turned into TypePattern.ANY). resolveBindings() tries to work out what we've really got and turn it into a type pattern
+ * that we can use for matching. This will normally be either an ExactTypePattern or a WildTypePattern.
+ *
+ * Here's how the process pans out for various generic and parameterized patterns: (see GenericsWildTypePatternResolvingTestCase)
*
- * Here's how the process pans out for various generic and parameterized patterns:
- * (see GenericsWildTypePatternResolvingTestCase)
+ * Foo where Foo exists and is generic Parser creates WildTypePattern namePatterns={Foo} resolveBindings resolves Foo to RT(Foo -
+ * raw) return ExactTypePattern(LFoo;)
*
- * Foo where Foo exists and is generic
- * Parser creates WildTypePattern namePatterns={Foo}
- * resolveBindings resolves Foo to RT(Foo - raw)
- * return ExactTypePattern(LFoo;)
+ * Foo<String> where Foo exists and String meets the bounds Parser creates WildTypePattern namePatterns = {Foo},
+ * typeParameters=WTP{String} resolveBindings resolves typeParameters to ExactTypePattern(String) resolves Foo to RT(Foo) returns
+ * ExactTypePattern(PFoo<String>; - parameterized)
*
- * Foo<String> where Foo exists and String meets the bounds
- * Parser creates WildTypePattern namePatterns = {Foo}, typeParameters=WTP{String}
- * resolveBindings resolves typeParameters to ExactTypePattern(String)
- * resolves Foo to RT(Foo)
- * returns ExactTypePattern(PFoo<String>; - parameterized)
- *
- * Foo<Str*> where Foo exists and takes one bound
- * Parser creates WildTypePattern namePatterns = {Foo}, typeParameters=WTP{Str*}
- * resolveBindings resolves typeParameters to WTP{Str*}
- * resolves Foo to RT(Foo)
- * returns WildTypePattern(name = Foo, typeParameters = WTP{Str*} isGeneric=false)
+ * Foo<Str*> where Foo exists and takes one bound Parser creates WildTypePattern namePatterns = {Foo}, typeParameters=WTP{Str*}
+ * resolveBindings resolves typeParameters to WTP{Str*} resolves Foo to RT(Foo) returns WildTypePattern(name = Foo, typeParameters =
+ * WTP{Str*} isGeneric=false)
+ *
+ * Fo*<String> Parser creates WildTypePattern namePatterns = {Fo*}, typeParameters=WTP{String} resolveBindings resolves
+ * typeParameters to ETP{String} returns WildTypePattern(name = Fo*, typeParameters = ETP{String} isGeneric=false)
*
- * Fo*<String>
- * Parser creates WildTypePattern namePatterns = {Fo*}, typeParameters=WTP{String}
- * resolveBindings resolves typeParameters to ETP{String}
- * returns WildTypePattern(name = Fo*, typeParameters = ETP{String} isGeneric=false)
- *
*
* Foo<?>
*
String[] importedPrefixes;
String[] knownMatches;
int dim;
-
+
// SECRETAPI - just for testing, turns off boundschecking temporarily...
public static boolean boundscheckingoff = false;
-
+
// these next three are set if the type pattern is constrained by extends or super clauses, in which case the
// namePatterns must have length 1
// TODO AMC: read/write/resolve of these fields
- TypePattern upperBound; // extends Foo
- TypePattern[] additionalInterfaceBounds; // extends Foo & A,B,C
- TypePattern lowerBound; // super Foo
+ TypePattern upperBound; // extends Foo
+ TypePattern[] additionalInterfaceBounds; // extends Foo & A,B,C
+ TypePattern lowerBound; // super Foo
// if we have type parameters, these fields indicate whether we should be a generic type pattern or a parameterized
// type pattern. We can only tell during resolve bindings.
private boolean isGeneric = true;
-
+
WildTypePattern(NamePattern[] namePatterns, boolean includeSubtypes, int dim, boolean isVarArgs, TypePatternList typeParams) {
- super(includeSubtypes,isVarArgs,typeParams);
+ super(includeSubtypes, isVarArgs, typeParams);
this.namePatterns = namePatterns;
this.dim = dim;
ellipsisCount = 0;
- for (int i=0; i<namePatterns.length; i++) {
- if (namePatterns[i] == NamePattern.ELLIPSIS) ellipsisCount++;
+ for (int i = 0; i < namePatterns.length; i++) {
+ if (namePatterns[i] == NamePattern.ELLIPSIS)
+ ellipsisCount++;
}
- setLocation(namePatterns[0].getSourceContext(), namePatterns[0].getStart(), namePatterns[namePatterns.length-1].getEnd());
+ setLocation(namePatterns[0].getSourceContext(), namePatterns[0].getStart(), namePatterns[namePatterns.length - 1].getEnd());
}
public WildTypePattern(List names, boolean includeSubtypes, int dim) {
- this((NamePattern[])names.toArray(new NamePattern[names.size()]), includeSubtypes, dim,false,TypePatternList.EMPTY);
+ this((NamePattern[]) names.toArray(new NamePattern[names.size()]), includeSubtypes, dim, false, TypePatternList.EMPTY);
}
-
+
public WildTypePattern(List names, boolean includeSubtypes, int dim, int endPos) {
this(names, includeSubtypes, dim);
this.end = endPos;
this.end = endPos;
this.isVarArgs = isVarArg;
}
-
- public WildTypePattern(
- List names,
- boolean includeSubtypes,
- int dim,
- int endPos,
- boolean isVarArg,
- TypePatternList typeParams,
- TypePattern upperBound,
- TypePattern[] additionalInterfaceBounds,
- TypePattern lowerBound) {
- this((NamePattern[])names.toArray(new NamePattern[names.size()]),includeSubtypes,dim,isVarArg,typeParams);
+
+ public WildTypePattern(List names, boolean includeSubtypes, int dim, int endPos, boolean isVarArg, TypePatternList typeParams,
+ TypePattern upperBound, TypePattern[] additionalInterfaceBounds, TypePattern lowerBound) {
+ this((NamePattern[]) names.toArray(new NamePattern[names.size()]), includeSubtypes, dim, isVarArg, typeParams);
this.end = endPos;
this.upperBound = upperBound;
this.lowerBound = lowerBound;
this.additionalInterfaceBounds = additionalInterfaceBounds;
}
-
- public WildTypePattern(
- List names,
- boolean includeSubtypes,
- int dim,
- int endPos,
- boolean isVarArg,
- TypePatternList typeParams)
- {
- this((NamePattern[])names.toArray(new NamePattern[names.size()]),includeSubtypes,dim,isVarArg,typeParams);
- this.end = endPos;
+
+ public WildTypePattern(List names, boolean includeSubtypes, int dim, int endPos, boolean isVarArg, TypePatternList typeParams) {
+ this((NamePattern[]) names.toArray(new NamePattern[names.size()]), includeSubtypes, dim, isVarArg, typeParams);
+ this.end = endPos;
+ }
+
+ public NamePattern[] getNamePatterns() {
+ return namePatterns;
+ }
+
+ public TypePattern getUpperBound() {
+ return upperBound;
+ }
+
+ public TypePattern getLowerBound() {
+ return lowerBound;
+ }
+
+ public TypePattern[] getAdditionalIntefaceBounds() {
+ return additionalInterfaceBounds;
}
-
- public NamePattern[] getNamePatterns() {
- return namePatterns;
- }
-
- public TypePattern getUpperBound() { return upperBound; }
- public TypePattern getLowerBound() { return lowerBound; }
- public TypePattern[] getAdditionalIntefaceBounds() { return additionalInterfaceBounds; }
// called by parser after parsing a type pattern, must bump dim as well as setting flag
public void setIsVarArgs(boolean isVarArgs) {
this.isVarArgs = isVarArgs;
- if (isVarArgs) this.dim += 1;
+ if (isVarArgs)
+ this.dim += 1;
}
-
- /* (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)) {
if (namePatterns.length > 0) {
- if (!namePatterns[0].matches(otherType.getName())) return false;
+ if (!namePatterns[0].matches(otherType.getName()))
+ return false;
}
- }
+ }
if (other instanceof WildTypePattern) {
WildTypePattern owtp = (WildTypePattern) other;
String mySimpleName = namePatterns[0].maybeGetSimpleName();
String yourSimpleName = owtp.namePatterns[0].maybeGetSimpleName();
if (mySimpleName != null && yourSimpleName != null) {
- return (mySimpleName.startsWith(yourSimpleName) ||
- yourSimpleName.startsWith(mySimpleName));
+ return (mySimpleName.startsWith(yourSimpleName) || yourSimpleName.startsWith(mySimpleName));
}
}
return true;
}
-
- //XXX inefficient implementation
+
+ // XXX inefficient implementation
// we don't know whether $ characters are from nested types, or were
// part of the declared type name (generated code often uses $s in type
// names). More work required on our part to get this right...
List ret = new ArrayList();
int startIndex = 0;
while (true) {
- int breakIndex = s.indexOf('.', startIndex); // what about /
- if (convertDollar && (breakIndex == -1)) breakIndex = s.indexOf('$', startIndex); // we treat $ like . here
- if (breakIndex == -1) break;
- char[] name = s.substring(startIndex, breakIndex).toCharArray();
- ret.add(name);
- startIndex = breakIndex+1;
+ int breakIndex = s.indexOf('.', startIndex); // what about /
+ if (convertDollar && (breakIndex == -1))
+ breakIndex = s.indexOf('$', startIndex); // we treat $ like . here
+ if (breakIndex == -1)
+ break;
+ char[] name = s.substring(startIndex, breakIndex).toCharArray();
+ ret.add(name);
+ startIndex = breakIndex + 1;
}
ret.add(s.substring(startIndex).toCharArray());
- return (char[][])ret.toArray(new char[ret.size()][]);
- }
-
+ return (char[][]) ret.toArray(new char[ret.size()][]);
+ }
/**
* @see org.aspectj.weaver.TypePattern#matchesExactly(IType)
*/
protected boolean matchesExactly(ResolvedType type) {
- return matchesExactly(type,type);
+ return matchesExactly(type, type);
}
protected boolean matchesExactly(ResolvedType type, ResolvedType annotatedType) {
String targetTypeName = type.getName();
-
- //System.err.println("match: " + targetTypeName + ", " + knownMatches); //Arrays.asList(importedPrefixes));
+
+ // System.err.println("match: " + targetTypeName + ", " + knownMatches); //Arrays.asList(importedPrefixes));
// Ensure the annotation pattern is resolved
annotationPattern.resolve(type.getWorld());
-
- return matchesExactlyByName(targetTypeName,type.isAnonymous(),type.isNested()) &&
- matchesParameters(type,STATIC) &&
- matchesBounds(type,STATIC) &&
- annotationPattern.matches(annotatedType,type.temporaryAnnotationTypes).alwaysTrue();
+
+ return matchesExactlyByName(targetTypeName, type.isAnonymous(), type.isNested()) && matchesParameters(type, STATIC)
+ && matchesBounds(type, STATIC)
+ && annotationPattern.matches(annotatedType, type.temporaryAnnotationTypes).alwaysTrue();
}
-
-
+
// we've matched against the base (or raw) type, but if this type pattern specifies parameters or
// type variables we need to make sure we match against them too
private boolean matchesParameters(ResolvedType aType, MatchKind staticOrDynamic) {
if (!isGeneric && typeParameters.size() > 0) {
- if(!aType.isParameterizedType()) return false;
+ if (!aType.isParameterizedType())
+ return false;
// we have to match type parameters
return typeParameters.matches(aType.getResolvedTypeParameters(), staticOrDynamic).alwaysTrue();
}
return true;
}
-
+
// we've matched against the base (or raw) type, but if this type pattern specifies bounds because
// it is a ? extends or ? super deal then we have to match them too.
private boolean matchesBounds(ResolvedType aType, MatchKind staticOrDynamic) {
- if (!(aType instanceof BoundedReferenceType)) return true;
- BoundedReferenceType boundedRT = (BoundedReferenceType) aType;
+ if (!(aType instanceof BoundedReferenceType))
+ return true;
+ BoundedReferenceType boundedRT = (BoundedReferenceType) aType;
if (upperBound == null && boundedRT.getUpperBound() != null) {
// for upper bound, null can also match against Object - but anything else and we're out.
if (!boundedRT.getUpperBound().getName().equals(UnresolvedType.OBJECT.getName())) {
return false;
}
}
- if (lowerBound == null && boundedRT.getLowerBound() != null) return false;
+ if (lowerBound == null && boundedRT.getLowerBound() != null)
+ return false;
if (upperBound != null) {
// match ? extends
- if (aType.isGenericWildcard() && boundedRT.isSuper()) return false;
- if (boundedRT.getUpperBound() == null) return false;
- return upperBound.matches((ResolvedType) boundedRT.getUpperBound(), staticOrDynamic).alwaysTrue();
+ if (aType.isGenericWildcard() && boundedRT.isSuper())
+ return false;
+ if (boundedRT.getUpperBound() == null)
+ return false;
+ return upperBound.matches((ResolvedType) boundedRT.getUpperBound(), staticOrDynamic).alwaysTrue();
}
if (lowerBound != null) {
// match ? super
- if (!(boundedRT.isGenericWildcard() && boundedRT.isSuper())) return false;
- return lowerBound.matches((ResolvedType) boundedRT.getLowerBound(), staticOrDynamic).alwaysTrue();
+ if (!(boundedRT.isGenericWildcard() && boundedRT.isSuper()))
+ return false;
+ return lowerBound.matches((ResolvedType) boundedRT.getLowerBound(), staticOrDynamic).alwaysTrue();
}
return true;
}
-
+
/**
- * Used in conjunction with checks on 'isStar()' to tell you if this pattern represents '*' or '*[]' which are
- * different !
+ * Used in conjunction with checks on 'isStar()' to tell you if this pattern represents '*' or '*[]' which are different !
*/
public int getDimensions() {
return dim;
}
-
+
public boolean isArray() {
return dim > 1;
}
-
- /**
+
+ /**
* @param targetTypeName
* @return
*/
private boolean matchesExactlyByName(String targetTypeName, boolean isAnonymous, boolean isNested) {
// we deal with parameter matching separately...
if (targetTypeName.indexOf('<') != -1) {
- targetTypeName = targetTypeName.substring(0,targetTypeName.indexOf('<'));
+ targetTypeName = targetTypeName.substring(0, targetTypeName.indexOf('<'));
}
// we deal with bounds matching separately too...
if (targetTypeName.startsWith(GENERIC_WILDCARD_CHARACTER)) {
targetTypeName = GENERIC_WILDCARD_CHARACTER;
}
- //XXX hack
+ // XXX hack
if (knownMatches == null && importedPrefixes == null) {
return innerMatchesExactly(targetTypeName, isAnonymous, isNested);
}
-
+
if (isNamePatternStar()) {
// we match if the dimensions match
int numDimensionsInTargetType = 0;
if (dim > 0) {
int index;
- while((index = targetTypeName.indexOf('[')) != -1) {
+ while ((index = targetTypeName.indexOf('[')) != -1) {
numDimensionsInTargetType++;
- targetTypeName = targetTypeName.substring(index+1);
+ targetTypeName = targetTypeName.substring(index + 1);
}
if (numDimensionsInTargetType == dim) {
return true;
}
}
}
-
+
// if our pattern is length 1, then known matches are exact matches
// if it's longer than that, then known matches are prefixes of a sort
if (namePatterns.length == 1) {
// we've already ruled out "*", and no other name pattern should match an anonymous type
return false;
}
- for (int i=0, len=knownMatches.length; i < len; i++) {
- if (knownMatches[i].equals(targetTypeName)) return true;
+ for (int i = 0, len = knownMatches.length; i < len; i++) {
+ if (knownMatches[i].equals(targetTypeName))
+ return true;
}
} else {
- for (int i=0, len=knownMatches.length; i < len; i++) {
+ for (int i = 0, len = knownMatches.length; i < len; i++) {
String knownPrefix = knownMatches[i] + "$";
if (targetTypeName.startsWith(knownPrefix)) {
int pos = lastIndexOfDotOrDollar(knownMatches[i]);
- if (innerMatchesExactly(targetTypeName.substring(pos+1),isAnonymous,isNested)) {
+ if (innerMatchesExactly(targetTypeName.substring(pos + 1), isAnonymous, isNested)) {
return true;
}
}
}
}
-
// if any prefixes match, strip the prefix and check that the rest matches
// assumes that prefixes have a dot at the end
- for (int i=0, len=importedPrefixes.length; i < len; i++) {
+ for (int i = 0, len = importedPrefixes.length; i < len; i++) {
String prefix = importedPrefixes[i];
- //System.err.println("prefix match? " + prefix + " to " + targetTypeName);
+ // System.err.println("prefix match? " + prefix + " to " + targetTypeName);
if (targetTypeName.startsWith(prefix)) {
-
- if (innerMatchesExactly(targetTypeName.substring(prefix.length()),isAnonymous,isNested)) {
+
+ if (innerMatchesExactly(targetTypeName.substring(prefix.length()), isAnonymous, isNested)) {
return true;
}
}
}
-
- return innerMatchesExactly(targetTypeName,isAnonymous,isNested);
+
+ return innerMatchesExactly(targetTypeName, isAnonymous, isNested);
}
private int lastIndexOfDotOrDollar(String string) {
- int dot = string.lastIndexOf('.');
- int dollar = string.lastIndexOf('$');
- return Math.max(dot, dollar);
- }
-
-
-
- private boolean innerMatchesExactly(String s, boolean isAnonymous, boolean convertDollar /*isNested*/) {
-
- List ret = new ArrayList();
- int startIndex = 0;
- while (true) {
- int breakIndex = s.indexOf('.', startIndex); // what about /
- if (convertDollar && (breakIndex == -1)) breakIndex = s.indexOf('$', startIndex); // we treat $ like . here
- if (breakIndex == -1) break;
- char[] name = s.substring(startIndex, breakIndex).toCharArray();
- ret.add(name);
- startIndex = breakIndex+1;
- }
- ret.add(s.substring(startIndex).toCharArray());
-
- int namesLength = ret.size();
- int patternsLength = namePatterns.length;
-
- int namesIndex = 0;
- int patternsIndex = 0;
-
- if ((!namePatterns[patternsLength-1].isAny()) && isAnonymous) return false;
-
- if (ellipsisCount == 0) {
- if (namesLength != patternsLength) return false;
- while (patternsIndex < patternsLength) {
- if (!namePatterns[patternsIndex++].matches((char[])ret.get(namesIndex++))) {
- return false;
- }
- }
- return true;
- } else if (ellipsisCount == 1) {
- if (namesLength < patternsLength-1) return false;
- while (patternsIndex < patternsLength) {
- NamePattern p = namePatterns[patternsIndex++];
- if (p == NamePattern.ELLIPSIS) {
- namesIndex = namesLength - (patternsLength-patternsIndex);
- } else {
- if (!p.matches((char[])ret.get(namesIndex++))) {
- return false;
- }
- }
- }
- return true;
- } else {
- // System.err.print("match(\"" + Arrays.asList(namePatterns) + "\", \"" + Arrays.asList(names) + "\") -> ");
- boolean b = outOfStar(namePatterns, (char[][])ret.toArray(new char[ret.size()][]), 0, 0, patternsLength - ellipsisCount, namesLength, ellipsisCount);
- // System.err.println(b);
- return b;
- }
- }
- private static boolean outOfStar(final NamePattern[] pattern, final char[][] target,
- int pi, int ti,
- int pLeft, int tLeft,
- final int starsLeft) {
- if (pLeft > tLeft) return false;
- while (true) {
- // invariant: if (tLeft > 0) then (ti < target.length && pi < pattern.length)
- if (tLeft == 0) return true;
- if (pLeft == 0) {
- return (starsLeft > 0);
- }
- if (pattern[pi] == NamePattern.ELLIPSIS) {
- return inStar(pattern, target, pi+1, ti, pLeft, tLeft, starsLeft-1);
- }
- if (! pattern[pi].matches(target[ti])) {
- return false;
- }
- pi++; ti++; pLeft--; tLeft--;
- }
- }
- private static boolean inStar(final NamePattern[] pattern, final char[][] target,
- int pi, int ti,
- final int pLeft, int tLeft,
- int starsLeft) {
- // invariant: pLeft > 0, so we know we'll run out of stars and find a real char in pattern
- // of course, we probably can't parse multiple ..'s in a row, but this keeps the algorithm
- // exactly parallel with that in NamePattern
- NamePattern patternChar = pattern[pi];
- while (patternChar == NamePattern.ELLIPSIS) {
- starsLeft--;
- patternChar = pattern[++pi];
- }
- while (true) {
- // invariant: if (tLeft > 0) then (ti < target.length)
- if (pLeft > tLeft) return false;
- if (patternChar.matches(target[ti])) {
- if (outOfStar(pattern, target, pi+1, ti+1, pLeft-1, tLeft-1, starsLeft)) return true;
- }
- ti++; tLeft--;
- }
- }
-
+ int dot = string.lastIndexOf('.');
+ int dollar = string.lastIndexOf('$');
+ return Math.max(dot, dollar);
+ }
+
+ private boolean innerMatchesExactly(String s, boolean isAnonymous, boolean convertDollar /* isNested */) {
+
+ List ret = new ArrayList();
+ int startIndex = 0;
+ while (true) {
+ int breakIndex = s.indexOf('.', startIndex); // what about /
+ if (convertDollar && (breakIndex == -1))
+ breakIndex = s.indexOf('$', startIndex); // we treat $ like . here
+ if (breakIndex == -1)
+ break;
+ char[] name = s.substring(startIndex, breakIndex).toCharArray();
+ ret.add(name);
+ startIndex = breakIndex + 1;
+ }
+ ret.add(s.substring(startIndex).toCharArray());
+
+ int namesLength = ret.size();
+ int patternsLength = namePatterns.length;
+
+ int namesIndex = 0;
+ int patternsIndex = 0;
+
+ if ((!namePatterns[patternsLength - 1].isAny()) && isAnonymous)
+ return false;
+
+ if (ellipsisCount == 0) {
+ if (namesLength != patternsLength)
+ return false;
+ while (patternsIndex < patternsLength) {
+ if (!namePatterns[patternsIndex++].matches((char[]) ret.get(namesIndex++))) {
+ return false;
+ }
+ }
+ return true;
+ } else if (ellipsisCount == 1) {
+ if (namesLength < patternsLength - 1)
+ return false;
+ while (patternsIndex < patternsLength) {
+ NamePattern p = namePatterns[patternsIndex++];
+ if (p == NamePattern.ELLIPSIS) {
+ namesIndex = namesLength - (patternsLength - patternsIndex);
+ } else {
+ if (!p.matches((char[]) ret.get(namesIndex++))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ } else {
+ // System.err.print("match(\"" + Arrays.asList(namePatterns) + "\", \"" + Arrays.asList(names) + "\") -> ");
+ boolean b = outOfStar(namePatterns, (char[][]) ret.toArray(new char[ret.size()][]), 0, 0, patternsLength
+ - ellipsisCount, namesLength, ellipsisCount);
+ // System.err.println(b);
+ return b;
+ }
+ }
+
+ private static boolean outOfStar(final NamePattern[] pattern, final char[][] target, int pi, int ti, int pLeft, int tLeft,
+ final int starsLeft) {
+ if (pLeft > tLeft)
+ return false;
+ while (true) {
+ // invariant: if (tLeft > 0) then (ti < target.length && pi < pattern.length)
+ if (tLeft == 0)
+ return true;
+ if (pLeft == 0) {
+ return (starsLeft > 0);
+ }
+ if (pattern[pi] == NamePattern.ELLIPSIS) {
+ return inStar(pattern, target, pi + 1, ti, pLeft, tLeft, starsLeft - 1);
+ }
+ if (!pattern[pi].matches(target[ti])) {
+ return false;
+ }
+ pi++;
+ ti++;
+ pLeft--;
+ tLeft--;
+ }
+ }
+
+ private static boolean inStar(final NamePattern[] pattern, final char[][] target, int pi, int ti, final int pLeft, int tLeft,
+ int starsLeft) {
+ // invariant: pLeft > 0, so we know we'll run out of stars and find a real char in pattern
+ // of course, we probably can't parse multiple ..'s in a row, but this keeps the algorithm
+ // exactly parallel with that in NamePattern
+ NamePattern patternChar = pattern[pi];
+ while (patternChar == NamePattern.ELLIPSIS) {
+ starsLeft--;
+ patternChar = pattern[++pi];
+ }
+ while (true) {
+ // invariant: if (tLeft > 0) then (ti < target.length)
+ if (pLeft > tLeft)
+ return false;
+ if (patternChar.matches(target[ti])) {
+ if (outOfStar(pattern, target, pi + 1, ti + 1, pLeft - 1, tLeft - 1, starsLeft))
+ return true;
+ }
+ ti++;
+ tLeft--;
+ }
+ }
+
/**
* @see org.aspectj.weaver.TypePattern#matchesInstanceof(IType)
*/
public FuzzyBoolean matchesInstanceof(ResolvedType type) {
- //XXX hack to let unmatched types just silently remain so
- if (maybeGetSimpleName() != null) return
- FuzzyBoolean.NO;
-
+ // XXX hack to let unmatched types just silently remain so
+ if (maybeGetSimpleName() != null) {
+ return FuzzyBoolean.NO;
+ }
+
type.getWorld().getMessageHandler().handleMessage(
- new Message("can't do instanceof matching on patterns with wildcards",
- IMessage.ERROR, null, getSourceLocation()));
+ new Message("can't do instanceof matching on patterns with wildcards", IMessage.ERROR, null, getSourceLocation()));
return FuzzyBoolean.NO;
}
// it is not ok to treat Foo as a method name!
return null;
}
- //System.err.println("extract from : " + Arrays.asList(namePatterns));
+ // System.err.println("extract from : " + Arrays.asList(namePatterns));
int len = namePatterns.length;
- if (len ==1 && !annotationPattern.isAny()) return null; // can't extract
- NamePattern ret = namePatterns[len-1];
- NamePattern[] newNames = new NamePattern[len-1];
- System.arraycopy(namePatterns, 0, newNames, 0, len-1);
+ if (len == 1 && !annotationPattern.isAny())
+ return null; // can't extract
+ NamePattern ret = namePatterns[len - 1];
+ NamePattern[] newNames = new NamePattern[len - 1];
+ System.arraycopy(namePatterns, 0, newNames, 0, len - 1);
namePatterns = newNames;
- //System.err.println(" left : " + Arrays.asList(namePatterns));
+ // System.err.println(" left : " + Arrays.asList(namePatterns));
return ret;
}
-
+
/**
* Method maybeExtractName.
+ *
* @param string
* @return boolean
*/
public boolean maybeExtractName(String string) {
int len = namePatterns.length;
- NamePattern ret = namePatterns[len-1];
+ NamePattern ret = namePatterns[len - 1];
String simple = ret.maybeGetSimpleName();
if (simple != null && simple.equals(string)) {
extractName();
}
return false;
}
-
+
/**
- * If this type pattern has no '.' or '*' in it, then
- * return a simple string
+ * If this type pattern has no '.' or '*' in it, then return a simple string
*
* otherwise, this will return null;
*/
}
return null;
}
-
+
/**
* If this type pattern has no '*' or '..' in it
*/
if (namePatterns.length == 0) {
throw new RuntimeException("bad name: " + namePatterns);
}
- //System.out.println("get clean: " + this);
+ // System.out.println("get clean: " + this);
StringBuffer buf = new StringBuffer();
- for (int i=0, len=namePatterns.length; i < len; i++) {
+ for (int i = 0, len = namePatterns.length; i < len; i++) {
NamePattern p = namePatterns[i];
String simpleName = p.maybeGetSimpleName();
- if (simpleName == null) return null;
- if (i > 0) buf.append(".");
+ if (simpleName == null)
+ return null;
+ if (i > 0)
+ buf.append(".");
buf.append(simpleName);
}
- //System.out.println(buf);
+ // System.out.println(buf);
return buf.toString();
- }
+ }
- public TypePattern parameterizeWith(Map typeVariableMap,World w) {
+ public TypePattern parameterizeWith(Map typeVariableMap, World w) {
NamePattern[] newNamePatterns = new NamePattern[namePatterns.length];
- for(int i=0; i<namePatterns.length;i++) { newNamePatterns[i] = namePatterns[i]; }
+ for (int i = 0; i < namePatterns.length; i++) {
+ newNamePatterns[i] = namePatterns[i];
+ }
if (newNamePatterns.length == 1) {
String simpleName = newNamePatterns[0].maybeGetSimpleName();
if (simpleName != null) {
if (typeVariableMap.containsKey(simpleName)) {
- String newName = ((ReferenceType)typeVariableMap.get(simpleName)).getName().replace('$','.');
- StringTokenizer strTok = new StringTokenizer(newName,".");
+ String newName = ((ReferenceType) typeVariableMap.get(simpleName)).getName().replace('$', '.');
+ StringTokenizer strTok = new StringTokenizer(newName, ".");
newNamePatterns = new NamePattern[strTok.countTokens()];
int index = 0;
- while(strTok.hasMoreTokens()) {
+ while (strTok.hasMoreTokens()) {
newNamePatterns[index++] = new NamePattern(strTok.nextToken());
- }
+ }
}
}
}
- WildTypePattern ret = new WildTypePattern(
- newNamePatterns,
- includeSubtypes,
- dim,
- isVarArgs,
- typeParameters.parameterizeWith(typeVariableMap,w)
- );
- ret.annotationPattern = this.annotationPattern.parameterizeWith(typeVariableMap,w);
+ WildTypePattern ret = new WildTypePattern(newNamePatterns, includeSubtypes, dim, isVarArgs, typeParameters
+ .parameterizeWith(typeVariableMap, w));
+ ret.annotationPattern = this.annotationPattern.parameterizeWith(typeVariableMap, w);
if (additionalInterfaceBounds == null) {
ret.additionalInterfaceBounds = null;
} else {
ret.additionalInterfaceBounds = new TypePattern[additionalInterfaceBounds.length];
for (int i = 0; i < additionalInterfaceBounds.length; i++) {
- ret.additionalInterfaceBounds[i] = additionalInterfaceBounds[i].parameterizeWith(typeVariableMap,w);
+ ret.additionalInterfaceBounds[i] = additionalInterfaceBounds[i].parameterizeWith(typeVariableMap, w);
}
}
- ret.upperBound = upperBound != null ? upperBound.parameterizeWith(typeVariableMap,w) : null;
- ret.lowerBound = lowerBound != null ? lowerBound.parameterizeWith(typeVariableMap,w) : null;
+ ret.upperBound = upperBound != null ? upperBound.parameterizeWith(typeVariableMap, w) : null;
+ ret.lowerBound = lowerBound != null ? lowerBound.parameterizeWith(typeVariableMap, w) : null;
ret.isGeneric = isGeneric;
ret.knownMatches = knownMatches;
ret.importedPrefixes = importedPrefixes;
*
* We will be replaced by what we return
*/
- public TypePattern resolveBindings(IScope scope, Bindings bindings,
- boolean allowBinding, boolean requireExactType)
- {
- if (isNamePatternStar()) {
- TypePattern anyPattern = maybeResolveToAnyPattern(scope, bindings, allowBinding, requireExactType);
- if (anyPattern != null) {
- if (requireExactType) {
- scope.getWorld().getMessageHandler().handleMessage(
- MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED),
- getSourceLocation()));
+ public TypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
+ if (isNamePatternStar()) {
+ TypePattern anyPattern = maybeResolveToAnyPattern(scope, bindings, allowBinding, requireExactType);
+ if (anyPattern != null) {
+ if (requireExactType) {
+ scope.getWorld().getMessageHandler().handleMessage(
+ MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED), getSourceLocation()));
return NO;
- } else {
- return anyPattern;
- }
- }
+ } else {
+ return anyPattern;
+ }
+ }
}
- TypePattern bindingTypePattern = maybeResolveToBindingTypePattern(scope, bindings, allowBinding, requireExactType);
- if (bindingTypePattern != null) return bindingTypePattern;
-
- annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
-
+ TypePattern bindingTypePattern = maybeResolveToBindingTypePattern(scope, bindings, allowBinding, requireExactType);
+ if (bindingTypePattern != null)
+ return bindingTypePattern;
+
+ annotationPattern = annotationPattern.resolveBindings(scope, bindings, allowBinding);
+
// resolve any type parameters
- if (typeParameters!=null && typeParameters.size()>0) {
- typeParameters.resolveBindings(scope,bindings,allowBinding,requireExactType);
+ if (typeParameters != null && typeParameters.size() > 0) {
+ typeParameters.resolveBindings(scope, bindings, allowBinding, requireExactType);
isGeneric = false;
}
-
+
// resolve any bounds
- if (upperBound != null) upperBound = upperBound.resolveBindings(scope, bindings, allowBinding, requireExactType);
- if (lowerBound != null) lowerBound = lowerBound.resolveBindings(scope, bindings, allowBinding, requireExactType);
+ if (upperBound != null)
+ upperBound = upperBound.resolveBindings(scope, bindings, allowBinding, requireExactType);
+ if (lowerBound != null)
+ lowerBound = lowerBound.resolveBindings(scope, bindings, allowBinding, requireExactType);
// amc - additional interface bounds only needed if we support type vars again.
-
+
String fullyQualifiedName = maybeGetCleanName();
if (fullyQualifiedName != null) {
return resolveBindingsFromFullyQualifiedTypeName(fullyQualifiedName, scope, bindings, allowBinding, requireExactType);
} else {
if (requireExactType) {
scope.getWorld().getMessageHandler().handleMessage(
- MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED),
- getSourceLocation()));
+ MessageUtil.error(WeaverMessages.format(WeaverMessages.WILDCARD_NOT_ALLOWED), getSourceLocation()));
return NO;
}
importedPrefixes = scope.getImportedPrefixes();
- knownMatches = preMatch(scope.getImportedNames());
- return this; // pattern contains wildcards so can't be resolved to an ExactTypePattern...
- //XXX need to implement behavior for Lint.invalidWildcardTypeName
- }
+ knownMatches = preMatch(scope.getImportedNames());
+ return this; // pattern contains wildcards so can't be resolved to an ExactTypePattern...
+ // XXX need to implement behavior for Lint.invalidWildcardTypeName
+ }
}
-
- private TypePattern maybeResolveToAnyPattern(IScope scope, Bindings bindings,
- boolean allowBinding, boolean requireExactType) {
- // If there is an annotation specified we have to
- // use a special variant of Any TypePattern called
- // AnyWithAnnotation
+
+ private TypePattern maybeResolveToAnyPattern(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
+ // If there is an annotation specified we have to
+ // use a special variant of Any TypePattern called
+ // AnyWithAnnotation
if (annotationPattern == AnnotationTypePattern.ANY) {
- if (dim == 0 && !isVarArgs && upperBound == null && lowerBound == null && (additionalInterfaceBounds == null || additionalInterfaceBounds.length==0)) { // pr72531
- return TypePattern.ANY; //??? loses source location
- }
- } else if (!isVarArgs){
- annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding);
- AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annotationPattern);
- ret.setLocation(sourceContext,start,end);
+ if (dim == 0 && !isVarArgs && upperBound == null && lowerBound == null
+ && (additionalInterfaceBounds == null || additionalInterfaceBounds.length == 0)) { // pr72531
+ return TypePattern.ANY; // ??? loses source location
+ }
+ } else if (!isVarArgs) {
+ annotationPattern = annotationPattern.resolveBindings(scope, bindings, allowBinding);
+ AnyWithAnnotationTypePattern ret = new AnyWithAnnotationTypePattern(annotationPattern);
+ ret.setLocation(sourceContext, start, end);
return ret;
}
return null; // can't resolve to a simple "any" pattern
}
-
- private TypePattern maybeResolveToBindingTypePattern(IScope scope, Bindings bindings,
- boolean allowBinding, boolean requireExactType) {
+
+ private TypePattern maybeResolveToBindingTypePattern(IScope scope, Bindings bindings, boolean allowBinding,
+ boolean requireExactType) {
String simpleName = maybeGetSimpleName();
if (simpleName != null) {
FormalBinding formalBinding = scope.lookupFormal(simpleName);
return this;
}
if (!allowBinding) {
- scope.message(IMessage.ERROR, this,
- "name binding only allowed in target, this, and args pcds");
+ scope.message(IMessage.ERROR, this, "name binding only allowed in target, this, and args pcds");
return this;
}
-
- BindingTypePattern binding = new BindingTypePattern(formalBinding,isVarArgs);
+
+ BindingTypePattern binding = new BindingTypePattern(formalBinding, isVarArgs);
binding.copyLocationFrom(this);
bindings.register(binding, scope);
-
+
return binding;
}
}
return null; // not possible to resolve to a binding type pattern
}
-
- private TypePattern resolveBindingsFromFullyQualifiedTypeName(String fullyQualifiedName, IScope scope, Bindings bindings,
+
+ private TypePattern resolveBindingsFromFullyQualifiedTypeName(String fullyQualifiedName, IScope scope, Bindings bindings,
boolean allowBinding, boolean requireExactType) {
String originalName = fullyQualifiedName;
ResolvedType resolvedTypeInTheWorld = null;
UnresolvedType type;
-
- //System.out.println("resolve: " + cleanName);
- //??? this loop has too many inefficiencies to count
- resolvedTypeInTheWorld = lookupTypeInWorldIncludingPrefixes(scope.getWorld(), fullyQualifiedName, scope.getImportedPrefixes());
+
+ // System.out.println("resolve: " + cleanName);
+ // ??? this loop has too many inefficiencies to count
+ resolvedTypeInTheWorld = lookupTypeInWorldIncludingPrefixes(scope.getWorld(), fullyQualifiedName, scope
+ .getImportedPrefixes());
if (resolvedTypeInTheWorld.isGenericWildcard()) {
type = resolvedTypeInTheWorld;
} else {
type = lookupTypeInScope(scope, fullyQualifiedName, this);
}
- if ((type instanceof ResolvedType) && ((ResolvedType)type).isMissing()) {
- return resolveBindingsForMissingType(resolvedTypeInTheWorld, originalName, scope, bindings, allowBinding, requireExactType);
+ if ((type instanceof ResolvedType) && ((ResolvedType) type).isMissing()) {
+ return resolveBindingsForMissingType(resolvedTypeInTheWorld, originalName, scope, bindings, allowBinding,
+ requireExactType);
} else {
- return resolveBindingsForExactType(scope,type,fullyQualifiedName,requireExactType);
+ return resolveBindingsForExactType(scope, type, fullyQualifiedName, requireExactType);
}
}
-
-
-
+
private UnresolvedType lookupTypeInScope(IScope scope, String typeName, IHasPosition location) {
UnresolvedType type = null;
while (ResolvedType.isMissing(type = scope.lookupType(typeName, location))) {
int lastDot = typeName.lastIndexOf('.');
- if (lastDot == -1) break;
- typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot+1);
+ if (lastDot == -1)
+ break;
+ typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot + 1);
}
return type;
}
-
+
/**
- * Searches the world for the ResolvedType with the given typeName. If one
- * isn't found then for each of the supplied prefixes, it prepends the typeName
- * with the prefix and searches the world for the ResolvedType with this new name.
- * If one still isn't found then a MissingResolvedTypeWithKnownSignature is
- * returned with the originally requested typeName (this ensures the typeName
- * makes sense).
+ * Searches the world for the ResolvedType with the given typeName. If one isn't found then for each of the supplied prefixes,
+ * it prepends the typeName with the prefix and searches the world for the ResolvedType with this new name. If one still isn't
+ * found then a MissingResolvedTypeWithKnownSignature is returned with the originally requested typeName (this ensures the
+ * typeName makes sense).
*/
private ResolvedType lookupTypeInWorldIncludingPrefixes(World world, String typeName, String[] prefixes) {
ResolvedType ret = lookupTypeInWorld(world, typeName);
- if (!ret.isMissing()) return ret;
+ if (!ret.isMissing())
+ return ret;
ResolvedType retWithPrefix = ret;
int counter = 0;
while (retWithPrefix.isMissing() && (counter < prefixes.length)) {
- retWithPrefix = lookupTypeInWorld(world,prefixes[counter] + typeName);
+ retWithPrefix = lookupTypeInWorld(world, prefixes[counter] + typeName);
counter++;
}
- if (!retWithPrefix.isMissing()) return retWithPrefix;
+ if (!retWithPrefix.isMissing())
+ return retWithPrefix;
return ret;
}
-
+
private ResolvedType lookupTypeInWorld(World world, String typeName) {
UnresolvedType ut = UnresolvedType.forName(typeName);
- ResolvedType ret = world.resolve(ut,true);
+ ResolvedType ret = world.resolve(ut, true);
while (ret.isMissing()) {
int lastDot = typeName.lastIndexOf('.');
- if (lastDot == -1) break;
- typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot+1);
- ret = world.resolve(UnresolvedType.forName(typeName),true);
+ if (lastDot == -1)
+ break;
+ typeName = typeName.substring(0, lastDot) + '$' + typeName.substring(lastDot + 1);
+ ret = world.resolve(UnresolvedType.forName(typeName), true);
}
return ret;
}
-
- private TypePattern resolveBindingsForExactType(IScope scope, UnresolvedType aType, String fullyQualifiedName,boolean requireExactType) {
+
+ private TypePattern resolveBindingsForExactType(IScope scope, UnresolvedType aType, String fullyQualifiedName,
+ boolean requireExactType) {
TypePattern ret = null;
if (aType.isTypeVariableReference()) {
// we have to set the bounds on it based on the bounds of this pattern
ret = resolveBindingsForTypeVariable(scope, (UnresolvedTypeVariableReferenceType) aType);
- } else if (typeParameters.size()>0) {
+ } else if (typeParameters.size() > 0) {
ret = resolveParameterizedType(scope, aType, requireExactType);
} else if (upperBound != null || lowerBound != null) {
// this must be a generic wildcard with bounds
- ret = resolveGenericWildcard(scope, aType);
+ ret = resolveGenericWildcard(scope, aType);
} else {
- if (dim != 0) aType = UnresolvedType.makeArray(aType, dim);
- ret = new ExactTypePattern(aType,includeSubtypes,isVarArgs);
+ if (dim != 0)
+ aType = UnresolvedType.makeArray(aType, dim);
+ ret = new ExactTypePattern(aType, includeSubtypes, isVarArgs);
}
ret.setAnnotationTypePattern(annotationPattern);
ret.copyLocationFrom(this);
}
private TypePattern resolveGenericWildcard(IScope scope, UnresolvedType aType) {
- if (!aType.getSignature().equals(GENERIC_WILDCARD_SIGNATURE_CHARACTER)) throw new IllegalStateException("Can only have bounds for a generic wildcard");
+ if (!aType.getSignature().equals(GENERIC_WILDCARD_SIGNATURE_CHARACTER))
+ throw new IllegalStateException("Can only have bounds for a generic wildcard");
boolean canBeExact = true;
- if ((upperBound != null) && ResolvedType.isMissing(upperBound.getExactType())) canBeExact = false;
- if ((lowerBound != null) && ResolvedType.isMissing(lowerBound.getExactType())) canBeExact = false;
+ if ((upperBound != null) && ResolvedType.isMissing(upperBound.getExactType()))
+ canBeExact = false;
+ if ((lowerBound != null) && ResolvedType.isMissing(lowerBound.getExactType()))
+ canBeExact = false;
if (canBeExact) {
ResolvedType type = null;
if (upperBound != null) {
- if (upperBound.isIncludeSubtypes()) {
+ if (upperBound.isIncludeSubtypes()) {
canBeExact = false;
} else {
ReferenceType upper = (ReferenceType) upperBound.getExactType().resolve(scope.getWorld());
- type = new BoundedReferenceType(upper,true,scope.getWorld());
+ type = new BoundedReferenceType(upper, true, scope.getWorld());
}
} else {
if (lowerBound.isIncludeSubtypes()) {
canBeExact = false;
} else {
ReferenceType lower = (ReferenceType) lowerBound.getExactType().resolve(scope.getWorld());
- type = new BoundedReferenceType(lower,false,scope.getWorld());
+ type = new BoundedReferenceType(lower, false, scope.getWorld());
}
}
if (canBeExact) {
// might have changed if we find out include subtypes is set on one of the bounds...
- return new ExactTypePattern(type,includeSubtypes,isVarArgs);
+ return new ExactTypePattern(type, includeSubtypes, isVarArgs);
}
- }
-
+ }
+
// we weren't able to resolve to an exact type pattern...
// leave as wild type pattern
importedPrefixes = scope.getImportedPrefixes();
knownMatches = preMatch(scope.getImportedNames());
- return this;
+ return this;
}
private TypePattern resolveParameterizedType(IScope scope, UnresolvedType aType, boolean requireExactType) {
ResolvedType rt = aType.resolve(scope.getWorld());
- if (!verifyTypeParameters(rt,scope,requireExactType)) return TypePattern.NO; // messages already isued
- // Only if the type is exact *and* the type parameters are exact should we create an
- // ExactTypePattern for this WildTypePattern
+ if (!verifyTypeParameters(rt, scope, requireExactType))
+ return TypePattern.NO; // messages already isued
+ // Only if the type is exact *and* the type parameters are exact should we create an
+ // ExactTypePattern for this WildTypePattern
if (typeParameters.areAllExactWithNoSubtypesAllowed()) {
TypePattern[] typePats = typeParameters.getTypePatterns();
UnresolvedType[] typeParameterTypes = new UnresolvedType[typePats.length];
for (int i = 0; i < typeParameterTypes.length; i++) {
- typeParameterTypes[i] = ((ExactTypePattern)typePats[i]).getExactType();
+ typeParameterTypes[i] = ((ExactTypePattern) typePats[i]).getExactType();
}
// rt could be a parameterized type 156058
if (rt.isParameterizedType()) {
rt = rt.getGenericType();
}
ResolvedType type = TypeFactory.createParameterizedType(rt, typeParameterTypes, scope.getWorld());
- if (isGeneric) type = type.getGenericType();
-// UnresolvedType tx = UnresolvedType.forParameterizedTypes(aType,typeParameterTypes);
-// UnresolvedType type = scope.getWorld().resolve(tx,true);
- if (dim != 0) type = ResolvedType.makeArray(type, dim);
- return new ExactTypePattern(type,includeSubtypes,isVarArgs);
+ if (isGeneric)
+ type = type.getGenericType();
+ // UnresolvedType tx = UnresolvedType.forParameterizedTypes(aType,typeParameterTypes);
+ // UnresolvedType type = scope.getWorld().resolve(tx,true);
+ if (dim != 0)
+ type = ResolvedType.makeArray(type, dim);
+ return new ExactTypePattern(type, includeSubtypes, isVarArgs);
} else {
// AMC... just leave it as a wild type pattern then?
importedPrefixes = scope.getImportedPrefixes();
return this;
}
}
-
- private TypePattern resolveBindingsForMissingType(ResolvedType typeFoundInWholeWorldSearch, String nameWeLookedFor, IScope scope, Bindings bindings,
- boolean allowBinding, boolean requireExactType) {
+
+ private TypePattern resolveBindingsForMissingType(ResolvedType typeFoundInWholeWorldSearch, String nameWeLookedFor,
+ IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) {
if (requireExactType) {
if (!allowBinding) {
scope.getWorld().getMessageHandler().handleMessage(
- MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_BIND_TYPE,nameWeLookedFor),
- getSourceLocation()));
+ MessageUtil.error(WeaverMessages.format(WeaverMessages.CANT_BIND_TYPE, nameWeLookedFor),
+ getSourceLocation()));
} else if (scope.getWorld().getLint().invalidAbsoluteTypeName.isEnabled()) {
scope.getWorld().getLint().invalidAbsoluteTypeName.signal(nameWeLookedFor, getSourceLocation());
}
} else if (scope.getWorld().getLint().invalidAbsoluteTypeName.isEnabled()) {
// Only put the lint warning out if we can't find it in the world
if (typeFoundInWholeWorldSearch.isMissing()) {
- scope.getWorld().getLint().invalidAbsoluteTypeName.signal(nameWeLookedFor, getSourceLocation());
+ scope.getWorld().getLint().invalidAbsoluteTypeName.signal(nameWeLookedFor, getSourceLocation());
}
}
importedPrefixes = scope.getImportedPrefixes();
knownMatches = preMatch(scope.getImportedNames());
- return this;
+ return this;
}
-
+
/**
- * We resolved the type to a type variable declared in the pointcut designator.
- * Now we have to create either an exact type pattern or a wild type pattern for it,
- * with upper and lower bounds set accordingly.
- * XXX none of this stuff gets serialized yet
+ * We resolved the type to a type variable declared in the pointcut designator. Now we have to create either an exact type
+ * pattern or a wild type pattern for it, with upper and lower bounds set accordingly. XXX none of this stuff gets serialized
+ * yet
+ *
* @param scope
* @param tvrType
* @return
if (additionalInterfaceBounds != null) {
TypePattern[] resolvedIfBounds = new TypePattern[additionalInterfaceBounds.length];
for (int i = 0; i < resolvedIfBounds.length; i++) {
- resolvedIfBounds[i] = additionalInterfaceBounds[i].resolveBindings(scope, emptyBindings, false, false);
+ resolvedIfBounds[i] = additionalInterfaceBounds[i].resolveBindings(scope, emptyBindings, false, false);
}
additionalInterfaceBounds = resolvedIfBounds;
}
- if ( upperBound == null && lowerBound == null && additionalInterfaceBounds == null) {
+ if (upperBound == null && lowerBound == null && additionalInterfaceBounds == null) {
// no bounds to worry about...
ResolvedType rType = tvrType.resolve(scope.getWorld());
- if (dim != 0) rType = ResolvedType.makeArray(rType, dim);
- return new ExactTypePattern(rType,includeSubtypes,isVarArgs);
+ if (dim != 0)
+ rType = ResolvedType.makeArray(rType, dim);
+ return new ExactTypePattern(rType, includeSubtypes, isVarArgs);
} else {
// we have to set bounds on the TypeVariable held by tvrType before resolving it
boolean canCreateExactTypePattern = true;
- if (upperBound != null && ResolvedType.isMissing(upperBound.getExactType())) canCreateExactTypePattern = false;
- if (lowerBound != null && ResolvedType.isMissing(lowerBound.getExactType())) canCreateExactTypePattern = false;
+ if (upperBound != null && ResolvedType.isMissing(upperBound.getExactType()))
+ canCreateExactTypePattern = false;
+ if (lowerBound != null && ResolvedType.isMissing(lowerBound.getExactType()))
+ canCreateExactTypePattern = false;
if (additionalInterfaceBounds != null) {
for (int i = 0; i < additionalInterfaceBounds.length; i++) {
- if (ResolvedType.isMissing(additionalInterfaceBounds[i].getExactType())) canCreateExactTypePattern = false;
+ if (ResolvedType.isMissing(additionalInterfaceBounds[i].getExactType()))
+ canCreateExactTypePattern = false;
}
}
if (canCreateExactTypePattern) {
TypeVariable tv = tvrType.getTypeVariable();
- if (upperBound != null) tv.setUpperBound(upperBound.getExactType());
- if (lowerBound != null) tv.setLowerBound(lowerBound.getExactType());
+ if (upperBound != null)
+ tv.setUpperBound(upperBound.getExactType());
+ if (lowerBound != null)
+ tv.setLowerBound(lowerBound.getExactType());
if (additionalInterfaceBounds != null) {
UnresolvedType[] ifBounds = new UnresolvedType[additionalInterfaceBounds.length];
for (int i = 0; i < ifBounds.length; i++) {
tv.setAdditionalInterfaceBounds(ifBounds);
}
ResolvedType rType = tvrType.resolve(scope.getWorld());
- if (dim != 0) rType = ResolvedType.makeArray(rType, dim);
- return new ExactTypePattern(rType,includeSubtypes,isVarArgs);
+ if (dim != 0)
+ rType = ResolvedType.makeArray(rType, dim);
+ return new ExactTypePattern(rType, includeSubtypes, isVarArgs);
}
- return this; // leave as wild type pattern then
+ return this; // leave as wild type pattern then
}
}
-
+
/**
- * When this method is called, we have resolved the base type to an exact type.
- * We also have a set of type patterns for the parameters.
- * Time to perform some basic checks:
- * - can the base type be parameterized? (is it generic)
- * - can the type parameter pattern list match the number of parameters on the base type
- * - do all parameter patterns meet the bounds of the respective type variables
- * If any of these checks fail, a warning message is issued and we return false.
+ * When this method is called, we have resolved the base type to an exact type. We also have a set of type patterns for the
+ * parameters. Time to perform some basic checks: - can the base type be parameterized? (is it generic) - can the type parameter
+ * pattern list match the number of parameters on the base type - do all parameter patterns meet the bounds of the respective
+ * type variables If any of these checks fail, a warning message is issued and we return false.
+ *
* @return
*/
- private boolean verifyTypeParameters(ResolvedType baseType,IScope scope, boolean requireExactType) {
+ private boolean verifyTypeParameters(ResolvedType baseType, IScope scope, boolean requireExactType) {
ResolvedType genericType = baseType.getGenericType();
if (genericType == null) {
// issue message "does not match because baseType.getName() is not generic"
- scope.message(MessageUtil.warn(
- WeaverMessages.format(WeaverMessages.NOT_A_GENERIC_TYPE,baseType.getName()),
+ scope.message(MessageUtil.warn(WeaverMessages.format(WeaverMessages.NOT_A_GENERIC_TYPE, baseType.getName()),
getSourceLocation()));
return false;
}
}
}
TypeVariable[] tvs = genericType.getTypeVariables();
- if ((tvs.length < minRequiredTypeParameters) ||
- (!foundEllipsis && minRequiredTypeParameters != tvs.length))
- {
+ if ((tvs.length < minRequiredTypeParameters) || (!foundEllipsis && minRequiredTypeParameters != tvs.length)) {
// issue message "does not match because wrong no of type params"
- String msg = WeaverMessages.format(WeaverMessages.INCORRECT_NUMBER_OF_TYPE_ARGUMENTS,
- genericType.getName(),new Integer(tvs.length));
- if (requireExactType) scope.message(MessageUtil.error(msg,getSourceLocation()));
- else scope.message(MessageUtil.warn(msg,getSourceLocation()));
+ String msg = WeaverMessages.format(WeaverMessages.INCORRECT_NUMBER_OF_TYPE_ARGUMENTS, genericType.getName(),
+ new Integer(tvs.length));
+ if (requireExactType)
+ scope.message(MessageUtil.error(msg, getSourceLocation()));
+ else
+ scope.message(MessageUtil.warn(msg, getSourceLocation()));
return false;
- }
-
+ }
+
// now check that each typeParameter pattern, if exact, matches the bounds
// of the type variable.
-
+
// pr133307 - delay verification until type binding completion, these next few lines replace
// the call to checkBoundsOK
if (!boundscheckingoff) {
- VerifyBoundsForTypePattern verification =
- new VerifyBoundsForTypePattern(scope,genericType,requireExactType,typeParameters,getSourceLocation());
+ VerifyBoundsForTypePattern verification = new VerifyBoundsForTypePattern(scope, genericType, requireExactType,
+ typeParameters, getSourceLocation());
scope.getWorld().getCrosscuttingMembersSet().recordNecessaryCheck(verification);
}
-// return checkBoundsOK(scope,genericType,requireExactType);
-
- return true;
+ // return checkBoundsOK(scope,genericType,requireExactType);
+
+ return true;
}
-
+
/**
- * By capturing the verification in this class, rather than performing it in verifyTypeParameters(),
- * we can cope with situations where the interactions between generics and declare parents would
- * otherwise cause us problems. For example, if verifying as we go along we may report a problem
- * which would have been fixed by a declare parents that we haven't looked at yet. If we
- * create and store a verification object, we can verify this later when the type system is
- * considered 'complete'
+ * By capturing the verification in this class, rather than performing it in verifyTypeParameters(), we can cope with situations
+ * where the interactions between generics and declare parents would otherwise cause us problems. For example, if verifying as
+ * we go along we may report a problem which would have been fixed by a declare parents that we haven't looked at yet. If we
+ * create and store a verification object, we can verify this later when the type system is considered 'complete'
*/
static class VerifyBoundsForTypePattern implements IVerificationRequired {
-
- private IScope scope;
- private ResolvedType genericType;
- private boolean requireExactType;
+
+ private final IScope scope;
+ private final ResolvedType genericType;
+ private final boolean requireExactType;
private TypePatternList typeParameters = TypePatternList.EMPTY;
- private ISourceLocation sLoc;
-
+ private final ISourceLocation sLoc;
+
public VerifyBoundsForTypePattern(IScope scope, ResolvedType genericType, boolean requireExactType,
TypePatternList typeParameters, ISourceLocation sLoc) {
this.scope = scope;
this.typeParameters = typeParameters;
this.sLoc = sLoc;
}
-
+
public void verify() {
TypeVariable[] tvs = genericType.getTypeVariables();
TypePattern[] typeParamPatterns = typeParameters.getTypePatterns();
for (int i = 0; i < tvs.length; i++) {
UnresolvedType ut = typeParamPatterns[i].getExactType();
boolean continueCheck = true;
- // FIXME asc dont like this but ok temporary measure. If the type parameter
+ // FIXME asc dont like this but ok temporary measure. If the type parameter
// is itself a type variable (from the generic aspect) then assume it'll be
- // ok... (see pr112105) Want to break this? Run GenericAspectK test.
+ // ok... (see pr112105) Want to break this? Run GenericAspectK test.
if (ut.isTypeVariableReference()) {
continueCheck = false;
}
-
- //System.err.println("Verifying "+ut.getName()+" meets bounds for "+tvs[i]);
- if (continueCheck &&
- !tvs[i].canBeBoundTo(ut.resolve(scope.getWorld()))) {
+
+ // System.err.println("Verifying "+ut.getName()+" meets bounds for "+tvs[i]);
+ if (continueCheck && !tvs[i].canBeBoundTo(ut.resolve(scope.getWorld()))) {
// issue message that type parameter does not meet specification
String parameterName = ut.getName();
- if (ut.isTypeVariableReference()) parameterName = ((TypeVariableReference)ut).getTypeVariable().getDisplayName();
- String msg =
- WeaverMessages.format(
- WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS,
- parameterName,
- new Integer(i+1),
- tvs[i].getDisplayName(),
- genericType.getName());
- if (requireExactType) scope.message(MessageUtil.error(msg,sLoc));
- else scope.message(MessageUtil.warn(msg,sLoc));
+ if (ut.isTypeVariableReference())
+ parameterName = ((TypeVariableReference) ut).getTypeVariable().getDisplayName();
+ String msg = WeaverMessages.format(WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS, parameterName,
+ new Integer(i + 1), tvs[i].getDisplayName(), genericType.getName());
+ if (requireExactType)
+ scope.message(MessageUtil.error(msg, sLoc));
+ else
+ scope.message(MessageUtil.warn(msg, sLoc));
}
}
}
}
// pr133307 - moved to verification object
-// public boolean checkBoundsOK(IScope scope,ResolvedType genericType,boolean requireExactType) {
-// if (boundscheckingoff) return true;
-// TypeVariable[] tvs = genericType.getTypeVariables();
-// TypePattern[] typeParamPatterns = typeParameters.getTypePatterns();
-// if (typeParameters.areAllExactWithNoSubtypesAllowed()) {
-// for (int i = 0; i < tvs.length; i++) {
-// UnresolvedType ut = typeParamPatterns[i].getExactType();
-// boolean continueCheck = true;
-// // FIXME asc dont like this but ok temporary measure. If the type parameter
-// // is itself a type variable (from the generic aspect) then assume it'll be
-// // ok... (see pr112105) Want to break this? Run GenericAspectK test.
-// if (ut.isTypeVariableReference()) {
-// continueCheck = false;
-// }
-//
-// if (continueCheck &&
-// !tvs[i].canBeBoundTo(ut.resolve(scope.getWorld()))) {
-// // issue message that type parameter does not meet specification
-// String parameterName = ut.getName();
-// if (ut.isTypeVariableReference()) parameterName = ((TypeVariableReference)ut).getTypeVariable().getDisplayName();
-// String msg =
-// WeaverMessages.format(
-// WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS,
-// parameterName,
-// new Integer(i+1),
-// tvs[i].getDisplayName(),
-// genericType.getName());
-// if (requireExactType) scope.message(MessageUtil.error(msg,getSourceLocation()));
-// else scope.message(MessageUtil.warn(msg,getSourceLocation()));
-// return false;
-// }
-// }
-// }
-// return true;
-// }
-
+ // public boolean checkBoundsOK(IScope scope,ResolvedType genericType,boolean requireExactType) {
+ // if (boundscheckingoff) return true;
+ // TypeVariable[] tvs = genericType.getTypeVariables();
+ // TypePattern[] typeParamPatterns = typeParameters.getTypePatterns();
+ // if (typeParameters.areAllExactWithNoSubtypesAllowed()) {
+ // for (int i = 0; i < tvs.length; i++) {
+ // UnresolvedType ut = typeParamPatterns[i].getExactType();
+ // boolean continueCheck = true;
+ // // FIXME asc dont like this but ok temporary measure. If the type parameter
+ // // is itself a type variable (from the generic aspect) then assume it'll be
+ // // ok... (see pr112105) Want to break this? Run GenericAspectK test.
+ // if (ut.isTypeVariableReference()) {
+ // continueCheck = false;
+ // }
+ //
+ // if (continueCheck &&
+ // !tvs[i].canBeBoundTo(ut.resolve(scope.getWorld()))) {
+ // // issue message that type parameter does not meet specification
+ // String parameterName = ut.getName();
+ // if (ut.isTypeVariableReference()) parameterName = ((TypeVariableReference)ut).getTypeVariable().getDisplayName();
+ // String msg =
+ // WeaverMessages.format(
+ // WeaverMessages.VIOLATES_TYPE_VARIABLE_BOUNDS,
+ // parameterName,
+ // new Integer(i+1),
+ // tvs[i].getDisplayName(),
+ // genericType.getName());
+ // if (requireExactType) scope.message(MessageUtil.error(msg,getSourceLocation()));
+ // else scope.message(MessageUtil.warn(msg,getSourceLocation()));
+ // return false;
+ // }
+ // }
+ // }
+ // return true;
+ // }
+
public boolean isStar() {
boolean annPatternStar = annotationPattern == AnnotationTypePattern.ANY;
return (isNamePatternStar() && annPatternStar);
}
-
+
private boolean isNamePatternStar() {
return namePatterns.length == 1 && namePatterns[0].isAny();
}
* returns those possible matches which I match exactly the last element of
*/
private String[] preMatch(String[] possibleMatches) {
- //if (namePatterns.length != 1) return CollectionUtil.NO_STRINGS;
-
+ // if (namePatterns.length != 1) return CollectionUtil.NO_STRINGS;
+
List ret = new ArrayList();
- for (int i=0, len=possibleMatches.length; i < len; i++) {
- char[][] names = splitNames(possibleMatches[i],true); //??? not most efficient
- if (namePatterns[0].matches(names[names.length-1])) {
+ for (int i = 0, len = possibleMatches.length; i < len; i++) {
+ char[][] names = splitNames(possibleMatches[i], true); // ??? not most efficient
+ if (namePatterns[0].matches(names[names.length - 1])) {
ret.add(possibleMatches[i]);
continue;
}
if (possibleMatches[i].indexOf("$") != -1) {
- names = splitNames(possibleMatches[i],false); //??? not most efficient
- if (namePatterns[0].matches(names[names.length-1])) {
+ names = splitNames(possibleMatches[i], false); // ??? not most efficient
+ if (namePatterns[0].matches(names[names.length - 1])) {
ret.add(possibleMatches[i]);
}
}
}
- return (String[])ret.toArray(new String[ret.size()]);
+ return (String[]) ret.toArray(new String[ret.size()]);
}
-
-
-// public void postRead(ResolvedType enclosingType) {
-// this.importedPrefixes = enclosingType.getImportedPrefixes();
-// this.knownNames = prematch(enclosingType.getImportedNames());
-// }
-
-
- public String toString() {
- StringBuffer buf = new StringBuffer();
- if (annotationPattern != AnnotationTypePattern.ANY) {
- buf.append('(');
- buf.append(annotationPattern.toString());
- buf.append(' ');
- }
- for (int i=0, len=namePatterns.length; i < len; i++) {
- NamePattern name = namePatterns[i];
- if (name == null) {
- buf.append(".");
- } else {
- if (i > 0) buf.append(".");
- buf.append(name.toString());
- }
- }
- if (upperBound != null) {
- buf.append(" extends ");
- buf.append(upperBound.toString());
- }
- if (lowerBound != null) {
- buf.append(" super ");
- buf.append(lowerBound.toString());
- }
- if (typeParameters!=null && typeParameters.size()!=0) {
+
+ // public void postRead(ResolvedType enclosingType) {
+ // this.importedPrefixes = enclosingType.getImportedPrefixes();
+ // this.knownNames = prematch(enclosingType.getImportedNames());
+ // }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ if (annotationPattern != AnnotationTypePattern.ANY) {
+ buf.append('(');
+ buf.append(annotationPattern.toString());
+ buf.append(' ');
+ }
+ for (int i = 0, len = namePatterns.length; i < len; i++) {
+ NamePattern name = namePatterns[i];
+ if (name == null) {
+ buf.append(".");
+ } else {
+ if (i > 0)
+ buf.append(".");
+ buf.append(name.toString());
+ }
+ }
+ if (upperBound != null) {
+ buf.append(" extends ");
+ buf.append(upperBound.toString());
+ }
+ if (lowerBound != null) {
+ buf.append(" super ");
+ buf.append(lowerBound.toString());
+ }
+ if (typeParameters != null && typeParameters.size() != 0) {
buf.append("<");
buf.append(typeParameters.toString());
buf.append(">");
}
- if (includeSubtypes) buf.append('+');
- if (isVarArgs) buf.append("...");
- if (annotationPattern != AnnotationTypePattern.ANY) {
- buf.append(')');
- }
- return buf.toString();
- }
-
- public boolean equals(Object other) {
- if (!(other instanceof WildTypePattern)) return false;
- WildTypePattern o = (WildTypePattern)other;
- int len = o.namePatterns.length;
- if (len != this.namePatterns.length) return false;
- if (this.includeSubtypes != o.includeSubtypes) return false;
- if (this.dim != o.dim) return false;
- if (this.isVarArgs != o.isVarArgs) return false;
- if (this.upperBound != null) {
- if (o.upperBound == null) return false;
- if (!this.upperBound.equals(o.upperBound)) return false;
- } else {
- if (o.upperBound != null) return false;
- }
- if (this.lowerBound != null) {
- if (o.lowerBound == null) return false;
- if (!this.lowerBound.equals(o.lowerBound)) return false;
- } else {
- if (o.lowerBound != null) return false;
- }
- if (!typeParameters.equals(o.typeParameters)) return false;
- for (int i=0; i < len; i++) {
- if (!o.namePatterns[i].equals(this.namePatterns[i])) return false;
- }
- return (o.annotationPattern.equals(this.annotationPattern));
+ if (includeSubtypes)
+ buf.append('+');
+ if (isVarArgs)
+ buf.append("...");
+ if (annotationPattern != AnnotationTypePattern.ANY) {
+ buf.append(')');
+ }
+ return buf.toString();
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof WildTypePattern))
+ return false;
+ WildTypePattern o = (WildTypePattern) other;
+ int len = o.namePatterns.length;
+ if (len != this.namePatterns.length)
+ return false;
+ if (this.includeSubtypes != o.includeSubtypes)
+ return false;
+ if (this.dim != o.dim)
+ return false;
+ if (this.isVarArgs != o.isVarArgs)
+ return false;
+ if (this.upperBound != null) {
+ if (o.upperBound == null)
+ return false;
+ if (!this.upperBound.equals(o.upperBound))
+ return false;
+ } else {
+ if (o.upperBound != null)
+ return false;
+ }
+ if (this.lowerBound != null) {
+ if (o.lowerBound == null)
+ return false;
+ if (!this.lowerBound.equals(o.lowerBound))
+ return false;
+ } else {
+ if (o.lowerBound != null)
+ return false;
+ }
+ if (!typeParameters.equals(o.typeParameters))
+ return false;
+ for (int i = 0; i < len; i++) {
+ if (!o.namePatterns[i].equals(this.namePatterns[i]))
+ return false;
+ }
+ return (o.annotationPattern.equals(this.annotationPattern));
}
- public int hashCode() {
- int result = 17;
- for (int i = 0, len = namePatterns.length; i < len; i++) {
- result = 37*result + namePatterns[i].hashCode();
- }
- result = 37*result + annotationPattern.hashCode();
- if (upperBound != null) result = 37*result + upperBound.hashCode();
- if (lowerBound != null) result = 37*result + lowerBound.hashCode();
- return result;
- }
-
- private static final byte VERSION = 1; // rev on change
+ public int hashCode() {
+ int result = 17;
+ for (int i = 0, len = namePatterns.length; i < len; i++) {
+ result = 37 * result + namePatterns[i].hashCode();
+ }
+ result = 37 * result + annotationPattern.hashCode();
+ if (upperBound != null)
+ result = 37 * result + upperBound.hashCode();
+ if (lowerBound != null)
+ result = 37 * result + lowerBound.hashCode();
+ return result;
+ }
+
+ private static final byte VERSION = 1; // rev on change
+
/**
* @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream)
*/
s.writeBoolean(includeSubtypes);
s.writeInt(dim);
s.writeBoolean(isVarArgs);
- typeParameters.write(s); // ! change from M2
- //??? storing this information with every type pattern is wasteful of .class
- // file size. Storing it on enclosing types would be more efficient
+ typeParameters.write(s); // ! change from M2
+ // ??? storing this information with every type pattern is wasteful of .class
+ // file size. Storing it on enclosing types would be more efficient
FileUtil.writeStringArray(knownMatches, s);
FileUtil.writeStringArray(importedPrefixes, s);
writeLocation(s);
// generics info, new in M3
s.writeBoolean(isGeneric);
s.writeBoolean(upperBound != null);
- if (upperBound != null) upperBound.write(s);
+ if (upperBound != null)
+ upperBound.write(s);
s.writeBoolean(lowerBound != null);
- if (lowerBound != null) lowerBound.write(s);
+ if (lowerBound != null)
+ lowerBound.write(s);
s.writeInt(additionalInterfaceBounds == null ? 0 : additionalInterfaceBounds.length);
if (additionalInterfaceBounds != null) {
for (int i = 0; i < additionalInterfaceBounds.length; i++) {
}
}
}
-
+
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);
- }
- }
-
- public static TypePattern readTypePattern150(VersionedDataInputStream s, ISourceContext context) throws IOException {
- byte version = s.readByte();
- if (version > VERSION) {
- throw new BCException("WildTypePattern was written by a more recent version of AspectJ, cannot read");
- }
- int len = s.readShort();
- NamePattern[] namePatterns = new NamePattern[len];
- for (int i=0; i < len; i++) {
- namePatterns[i] = NamePattern.read(s);
- }
- boolean includeSubtypes = s.readBoolean();
- int dim = s.readInt();
- boolean varArg = s.readBoolean();
- TypePatternList typeParams = TypePatternList.read(s, context);
- WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, varArg,typeParams);
- ret.knownMatches = FileUtil.readStringArray(s);
- ret.importedPrefixes = FileUtil.readStringArray(s);
- ret.readLocation(context, s);
- ret.setAnnotationTypePattern(AnnotationTypePattern.read(s,context));
- // generics info, new in M3
- ret.isGeneric = s.readBoolean();
- if (s.readBoolean()) {
- ret.upperBound = TypePattern.read(s,context);
- }
- if (s.readBoolean()) {
- ret.lowerBound = TypePattern.read(s,context);
- }
- int numIfBounds = s.readInt();
- if (numIfBounds > 0) {
- ret.additionalInterfaceBounds = new TypePattern[numIfBounds];
- for (int i = 0; i < numIfBounds; i++) {
- ret.additionalInterfaceBounds[i] = TypePattern.read(s,context);
- }
- }
- return ret;
+ return readTypePatternOldStyle(s, context);
+ }
}
-
+
+ public static TypePattern readTypePattern150(VersionedDataInputStream s, ISourceContext context) throws IOException {
+ byte version = s.readByte();
+ if (version > VERSION) {
+ throw new BCException("WildTypePattern was written by a more recent version of AspectJ, cannot read");
+ }
+ int len = s.readShort();
+ NamePattern[] namePatterns = new NamePattern[len];
+ for (int i = 0; i < len; i++) {
+ namePatterns[i] = NamePattern.read(s);
+ }
+ boolean includeSubtypes = s.readBoolean();
+ int dim = s.readInt();
+ boolean varArg = s.readBoolean();
+ TypePatternList typeParams = TypePatternList.read(s, context);
+ WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, varArg, typeParams);
+ ret.knownMatches = FileUtil.readStringArray(s);
+ ret.importedPrefixes = FileUtil.readStringArray(s);
+ ret.readLocation(context, s);
+ ret.setAnnotationTypePattern(AnnotationTypePattern.read(s, context));
+ // generics info, new in M3
+ ret.isGeneric = s.readBoolean();
+ if (s.readBoolean()) {
+ ret.upperBound = TypePattern.read(s, context);
+ }
+ if (s.readBoolean()) {
+ ret.lowerBound = TypePattern.read(s, context);
+ }
+ int numIfBounds = s.readInt();
+ if (numIfBounds > 0) {
+ ret.additionalInterfaceBounds = new TypePattern[numIfBounds];
+ for (int i = 0; i < numIfBounds; i++) {
+ ret.additionalInterfaceBounds[i] = TypePattern.read(s, context);
+ }
+ }
+ return ret;
+ }
+
public static TypePattern readTypePatternOldStyle(VersionedDataInputStream s, ISourceContext context) throws IOException {
int len = s.readShort();
NamePattern[] namePatterns = new NamePattern[len];
- for (int i=0; i < len; i++) {
+ for (int i = 0; i < len; i++) {
namePatterns[i] = NamePattern.read(s);
}
boolean includeSubtypes = s.readBoolean();
int dim = s.readInt();
- WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, false,null);
+ WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, false, null);
ret.knownMatches = FileUtil.readStringArray(s);
ret.importedPrefixes = FileUtil.readStringArray(s);
ret.readLocation(context, s);
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);
+ }
}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2005 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;
-
-import junit.framework.TestCase;
-
-// test cases for Adrian's additions to ReferenceType
-// XXX - couldn't find any unit test cases for the rest of the ReferenceType class
-public abstract class CommonReferenceTypeTests extends TestCase {
-
- private World world;
-
- public abstract World getWorld();
-
- public void setUp() {
- world = getWorld();
- }
-
- public void testUnresolvedTypeSignatureProcessing() {
- world.setBehaveInJava5Way(true);
- UnresolvedType ut = null;
- ut = UnresolvedType.forName("java.util.List<java.util.List<java.lang.String>>[]").resolve(world);
- ut = UnresolvedType.forSignature("[Pjava/util/List<Pjava/util/List<Ljava/lang/String;>;>;").resolve(world);
- assertEquals("Signatures not equal ", "[Pjava/util/List<Pjava/util/List<Ljava/lang/String;>;>;", ut.getSignature());
- assertEquals("Names not equal ", "java.util.List<java.util.List<java.lang.String>>[]", ut.getName());
- }
-
- public void testIsRawTrue() {
- world.setBehaveInJava5Way(true);
- UnresolvedType javaLangClass = UnresolvedType.forName("java.lang.Class");
- ResolvedType rtx = world.resolve(javaLangClass);
- assertTrue("Resolves to reference type", (rtx instanceof ReferenceType));
- ReferenceType rt = (ReferenceType) rtx;
- assertTrue("java.lang.Class is raw", rt.isRawType());
- }
-
- public void testIsRawFalse() {
- world.setBehaveInJava5Way(true);
- UnresolvedType javaLangObject = UnresolvedType.forName("java.lang.Object");
- ResolvedType rtx = world.resolve(javaLangObject);
- assertTrue("Resolves to reference type", (rtx instanceof ReferenceType));
- ReferenceType rt = (ReferenceType) rtx;
- assertFalse("java.lang.Object is not raw", rt.isRawType());
- }
-
- public void testIsGenericTrue() {
- world.setBehaveInJava5Way(true);
- UnresolvedType javaLangClass = UnresolvedType.forName("java.lang.Class");
- ResolvedType rtx = world.resolve(javaLangClass);
- assertTrue("java.lang.Class has underpinning generic type", rtx.getGenericType().isGenericType());
- }
-
- public void testIsGenericFalse() {
- world.setBehaveInJava5Way(true);
- UnresolvedType javaLangObject = UnresolvedType.forName("java.lang.Object");
- ResolvedType rtx = world.resolve(javaLangObject);
- assertFalse(rtx.isGenericType());
- }
-
-}
import junit.framework.TestCase;
import junit.framework.TestSuite;
+import org.aspectj.weaver.patterns.PatternsTests;
import org.aspectj.weaver.reflect.ReflectionWorldBasicTest;
-import org.aspectj.weaver.reflect.ReflectionWorldReferenceTypeTest;
import org.aspectj.weaver.reflect.ReflectionWorldSpecificTest;
public class MatcherModuleTests extends TestCase {
+ public MatcherModuleTests(String name) {
+ super(name);
+ }
+
public static Test suite() {
TestSuite suite = new TestSuite(MatcherModuleTests.class.getName());
suite.addTestSuite(ReflectionWorldSpecificTest.class);
- suite.addTestSuite(ReflectionWorldReferenceTypeTest.class);
suite.addTestSuite(ReflectionWorldBasicTest.class);
+ suite.addTest(PatternsTests.suite());
return suite;
}
- public MatcherModuleTests(String name) {
- super(name);
- }
-
}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver;
+
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.weaver.ast.Var;
+
+public class TestShadow extends Shadow {
+
+ private final World world;
+ private final UnresolvedType thisType;
+
+ public TestShadow(Kind kind, Member signature, UnresolvedType thisType, World world) {
+ super(kind, signature, null);
+ this.world = world;
+ this.thisType = thisType;
+ }
+
+ public World getIWorld() {
+ return world;
+ }
+
+ /** this is subtly wrong. ha ha */
+ public UnresolvedType getEnclosingType() {
+ return thisType;
+ }
+
+ public Var getThisVar() {
+ // we should thorw if we don't have a this
+ return new Var(getThisType().resolve(world));
+ }
+
+ public Var getTargetVar() {
+ if (! hasTarget()) throw new RuntimeException("bad");
+ return new Var(getTargetType().resolve(world));
+ }
+
+ public Var getArgVar(int i) {
+ return new Var(getArgType(i).resolve(world));
+ }
+
+ public Var getThisEnclosingJoinPointStaticPartVar() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public Var getThisJoinPointStaticPartVar() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public Var getThisJoinPointVar() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public ISourceLocation getSourceLocation() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ public Member getEnclosingCodeSignature() {
+ throw new RuntimeException("unimplemented");
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.Shadow#getKindedAnnotationVar()
+ */
+ public Var getKindedAnnotationVar(UnresolvedType annotationType) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.Shadow#getWithinAnnotationVar()
+ */
+ public Var getWithinAnnotationVar(UnresolvedType annotationType) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.Shadow#getWithinCodeAnnotationVar()
+ */
+ public Var getWithinCodeAnnotationVar(UnresolvedType annotationType) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.Shadow#getThisAnnotationVar()
+ */
+ public Var getThisAnnotationVar(UnresolvedType annotationType) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.Shadow#getTargetAnnotationVar()
+ */
+ public Var getTargetAnnotationVar(UnresolvedType annotationType) {
+ throw new RuntimeException("unimplemented");
+ }
+
+ /* (non-Javadoc)
+ * @see org.aspectj.weaver.Shadow#getArgAnnotationVar(int)
+ */
+ public Var getArgAnnotationVar(int i,UnresolvedType annotationType) {
+ throw new RuntimeException("unimplemented");
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2008 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andy Clement initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver;
+
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TestUtils {
+ private static final String[] ZERO_STRINGS = new String[0];
+
+ // For stringifying a delegate - extracted from AbstractReferenceTypeDelegate, not fixed up
+ // /**
+ // * Create the string representation for a delegate, allowing us to
+ // * more easily compare delegate implementations.
+ // */
+ // public String stringifyDelegate() {
+ //
+ // StringBuffer result = new StringBuffer();
+ // result.append("=== Delegate for "+getResolvedTypeX().getName()+"\n");
+ //
+ // result.append("isAspect?"+isAspect()+"\n");
+ // result.append("isAnnotationStyleAspect?"+isAnnotationStyleAspect()+"\n");
+ // result.append("isInterface?"+isInterface()+"\n");
+ // result.append("isEnum?"+isEnum()+"\n");
+ // result.append("isClass?"+isClass()+"\n");
+ // result.append("-\n");
+ // result.append("isAnnotation?"+isAnnotation()+"\n");
+ // result.append("retentionPolicy="+getRetentionPolicy()+"\n");
+ // result.append("canAnnotationTargetType?"+canAnnotationTargetType()+"\n");
+ // AnnotationTargetKind[] kinds = getAnnotationTargetKinds();
+ // if (kinds!=null && kinds.length>0) {
+ // result.append("annotationTargetKinds:[");
+ // for (int i = 0; i < kinds.length; i++) {
+ // AnnotationTargetKind kind = kinds[i];
+ // result.append(kind);
+ // if ((i+1)<kinds.length) result.append(" ");
+ // }
+ // result.append("]\n");
+ // }
+ // result.append("isAnnotationWithRuntimeRetention?"+isAnnotationWithRuntimeRetention()+"\n");
+ // result.append("-\n");
+ //
+ // result.append("isAnonymous?"+isAnonymous()+"\n");
+ // result.append("isNested?"+isNested()+"\n");
+ // result.append("-\n");
+ //
+ // result.append("isGeneric?"+isGeneric()+"\n");
+ // result.append("declaredGenericSignature="+getDeclaredGenericSignature()+"\n");
+ // result.append("-\n");
+ //
+ // AnnotationX[] axs = getAnnotations();
+ // if (axs!=null && axs.length>0) {
+ // result.append("getAnnotations() returns: "+axs.length+" annotations\n");
+ // for (int i = 0; i < axs.length; i++) {
+ // AnnotationX annotationX = axs[i];
+ // result.append(" #"+i+") "+annotationX+"\n");
+ // }
+ // } else {
+ // result.append("getAnnotations() returns nothing\n");
+ // }
+ // ResolvedType[] axtypes = getAnnotationTypes();
+ // if (axtypes!=null && axtypes.length>0) {
+ // result.append("getAnnotationTypes() returns: "+axtypes.length+" annotations\n");
+ // for (int i = 0; i < axtypes.length; i++) {
+ // ResolvedType annotation = axtypes[i];
+ // result.append(" #"+i+") "+annotation+":"+annotation.getClass()+"\n");
+ // }
+ // } else {
+ // result.append("getAnnotationTypes() returns nothing\n");
+ // }
+ //
+ // result.append("isExposedToWeaver?"+isExposedToWeaver()+"\n");
+ // result.append("getSuperclass?"+getSuperclass()+"\n");
+ // result.append("getResolvedTypeX?"+getResolvedTypeX()+"\n");
+ // result.append("--\n");
+ //
+ // ResolvedMember[] fields = getDeclaredFields();
+ // if (fields!=null && fields.length>0) {
+ // result.append("The fields: "+fields.length+"\n");
+ // for (int i = 0; i < fields.length; i++) {
+ // ResolvedMember member = fields[i];
+ // result.append("f"+i+") "+member.toDebugString()+"\n");
+ // }
+ // }
+ // ResolvedMember[] methods = getDeclaredMethods();
+ // if (methods!=null && methods.length>0) {
+ // result.append("The methods: "+methods.length+"\n");
+ // for (int i = 0; i < methods.length; i++) {
+ // ResolvedMember member = methods[i];
+ // result.append("m"+i+") "+member.toDebugString()+"\n");
+ // }
+ // }
+ // ResolvedType[] interfaces = getDeclaredInterfaces();
+ // if (interfaces!=null && interfaces.length>0) {
+ // result.append("The interfaces: "+interfaces.length+"\n");
+ // for (int i = 0; i < interfaces.length; i++) {
+ // ResolvedType member = interfaces[i];
+ // result.append("i"+i+") "+member+"\n");
+ // }
+ // }
+ //
+ // result.append("getModifiers?"+getModifiers()+"\n");
+ //
+ // result.append("perclause="+getPerClause()+"\n");
+ //
+ // result.append("aj:weaverstate="+getWeaverState()+"\n");
+ //
+ // ResolvedMember[] pointcuts = getDeclaredPointcuts();
+ // if (pointcuts!=null && pointcuts.length>0) {
+ // result.append("The pointcuts: "+pointcuts.length+"\n");
+ //
+ // // Sort the damn things
+ // List sortedSetOfPointcuts = new ArrayList();
+ // for (int i = 0; i < pointcuts.length; i++) {sortedSetOfPointcuts.add(pointcuts[i]);}
+ // Collections.sort(sortedSetOfPointcuts);
+ //
+ // int i =0;
+ // for (Iterator iter = sortedSetOfPointcuts.iterator(); iter.hasNext();) {
+ // ResolvedMember member = (ResolvedMember) iter.next();
+ // result.append("p"+i+") "+member.toDebugString()+"\n");
+ // i++;
+ // }
+ // }
+ //
+ // Collection declares = getDeclares();
+ // if (declares.size()>0) {
+ // result.append("The declares: "+declares.size()+"\n");
+ //
+ // // // Sort the damn things
+ // // List sortedSetOfPointcuts = new ArrayList();
+ // // for (int i = 0; i < pointcuts.length; i++) {sortedSetOfPointcuts.add(pointcuts[i]);}
+ // // Collections.sort(sortedSetOfPointcuts);
+ //
+ // int i=0;
+ // for (Iterator iter = declares.iterator(); iter.hasNext();) {
+ // Declare dec = (Declare) iter.next();
+ // result.append("d"+i+") "+dec.toString()+"\n");
+ // i++;
+ // }
+ // }
+ //
+ // TypeVariable[] tv = getTypeVariables();
+ // if (tv!=null && tv.length>0) {
+ // result.append("The type variables: "+tv.length+"\n");
+ // for (int i = 0; i < tv.length; i++) {
+ // result.append("tv"+i+") "+tv[i]+"\n");
+ // }
+ // }
+ //
+ // Collection tmungers = getTypeMungers();
+ // if (tmungers.size()>0) {
+ // List sorted = new ArrayList();
+ // sorted.addAll(tmungers);
+ // Collections.sort(sorted,new Comparator() {
+ // public int compare(Object arg0, Object arg1) {
+ // return arg0.toString().compareTo(arg1.toString());
+ // }
+ // });
+ // result.append("The type mungers: "+tmungers.size()+"\n");
+ // int i=0;
+ // for (Iterator iter = sorted.iterator(); iter.hasNext();) {
+ // ConcreteTypeMunger mun = (ConcreteTypeMunger) iter.next();
+ // result.append("tm"+i+") "+mun.toString()+"\n");
+ // i++;
+ // }
+ // }
+ //
+ // result.append("doesNotExposeShadowMungers?"+doesNotExposeShadowMungers()+"\n");
+ //
+ // Collection pas = getPrivilegedAccesses();
+ // if (pas!=null && pas.size()>0) {
+ // // List sorted = new ArrayList();
+ // // sorted.addAll(tmungers);
+ // // Collections.sort(sorted,new Comparator() {
+ // // public int compare(Object arg0, Object arg1) {
+ // // return arg0.toString().compareTo(arg1.toString());
+ // // }
+ // // });
+ // result.append("The privileged accesses: "+pas.size()+"\n");
+ // int i=0;
+ // for (Iterator iter = pas.iterator(); iter.hasNext();) {
+ // ResolvedMember mun = (ResolvedMember) iter.next();
+ // result.append("tm"+i+") "+mun.toDebugString()+"\n");
+ // i++;
+ // }
+ // }
+ //
+ // // public Collection getPrivilegedAccesses();
+ // // public boolean hasAnnotation(UnresolvedType ofType);
+ // result.append("===");
+ // return result.toString();
+ // }
+
+ /**
+ * Build a member from a string representation: <blockquote>
+ *
+ * <pre>
+ * static? TypeName TypeName.Id
+ * </pre>
+ *
+ * </blockquote>
+ */
+ public static MemberImpl fieldFromString(String str) {
+ str = str.trim();
+ final int len = str.length();
+ int i = 0;
+ int mods = 0;
+ if (str.startsWith("static", i)) {
+ mods = Modifier.STATIC;
+ i += 6;
+ while (Character.isWhitespace(str.charAt(i)))
+ i++;
+ }
+ int start = i;
+ while (!Character.isWhitespace(str.charAt(i)))
+ i++;
+ UnresolvedType retTy = UnresolvedType.forName(str.substring(start, i));
+
+ start = i;
+ i = str.lastIndexOf('.');
+ UnresolvedType declaringTy = UnresolvedType.forName(str.substring(start, i).trim());
+ start = ++i;
+ String name = str.substring(start, len).trim();
+ return new MemberImpl(Member.FIELD, declaringTy, mods, retTy, name, UnresolvedType.NONE);
+ }
+
+ /**
+ * Build a member from a string representation: <blockquote>
+ *
+ * <pre>
+ * (static|interface|private)? TypeName TypeName . Id ( TypeName , ...)
+ * </pre>
+ *
+ * </blockquote>
+ */
+
+ public static Member methodFromString(String str) {
+ str = str.trim();
+ // final int len = str.length();
+ int i = 0;
+
+ int mods = 0;
+ if (str.startsWith("static", i)) {
+ mods = Modifier.STATIC;
+ i += 6;
+ } else if (str.startsWith("interface", i)) {
+ mods = Modifier.INTERFACE;
+ i += 9;
+ } else if (str.startsWith("private", i)) {
+ mods = Modifier.PRIVATE;
+ i += 7;
+ }
+ while (Character.isWhitespace(str.charAt(i)))
+ i++;
+
+ int start = i;
+ while (!Character.isWhitespace(str.charAt(i)))
+ i++;
+ UnresolvedType returnTy = UnresolvedType.forName(str.substring(start, i));
+
+ start = i;
+ i = str.indexOf('(', i);
+ i = str.lastIndexOf('.', i);
+ UnresolvedType declaringTy = UnresolvedType.forName(str.substring(start, i).trim());
+
+ start = ++i;
+ i = str.indexOf('(', i);
+ String name = str.substring(start, i).trim();
+ start = ++i;
+ i = str.indexOf(')', i);
+
+ String[] paramTypeNames = parseIds(str.substring(start, i).trim());
+
+ return MemberImpl.method(declaringTy, mods, returnTy, name, UnresolvedType.forNames(paramTypeNames));
+ }
+
+ public static String[] parseIds(String str) {
+ if (str.length() == 0)
+ return ZERO_STRINGS;
+ List l = new ArrayList();
+ int start = 0;
+ while (true) {
+ int i = str.indexOf(',', start);
+ if (i == -1) {
+ l.add(str.substring(start).trim());
+ break;
+ }
+ l.add(str.substring(start, i).trim());
+ start = i + 1;
+ }
+ return (String[]) l.toArray(new String[l.size()]);
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.AndPointcut;
+import org.aspectj.weaver.patterns.NotPointcut;
+import org.aspectj.weaver.patterns.OrPointcut;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+
+/**
+ * @author hugunin
+ *
+ */
+public class AndOrNotTestCase extends PatternsTestCase {
+
+ public World getWorld() {
+ return new ReflectionWorld(this.getClass().getClassLoader());
+ }
+
+ public void testMatchBooleanOperatorPointcutMatching() throws IOException {
+
+ Pointcut foo = makePointcut("this(Foo)");
+ Pointcut bar = makePointcut("this(Bar)");
+ Pointcut c = makePointcut("this(C)");
+
+ checkEquals("this(Foo) && this(Bar)", new AndPointcut(foo, bar));
+ checkEquals("this(Foo) && this(Bar) && this(C)", new AndPointcut(foo, new AndPointcut(bar, c)));
+
+ checkEquals("this(Foo) || this(Bar)", new OrPointcut(foo, bar));
+ checkEquals("this(Foo) || this(Bar) || this(C)", new OrPointcut(foo, new OrPointcut(bar, c)));
+
+ checkEquals("this(Foo) && this(Bar) || this(C)", new OrPointcut(new AndPointcut(foo, bar), c));
+ checkEquals("this(Foo) || this(Bar) && this(C)", new OrPointcut(foo, new AndPointcut(bar, c)));
+ checkEquals("(this(Foo) || this(Bar)) && this(C)", new AndPointcut(new OrPointcut(foo, bar), c));
+ checkEquals("this(Foo) || (this(Bar) && this(C))", new OrPointcut(foo, new AndPointcut(bar, c)));
+
+ checkEquals("!this(Foo)", new NotPointcut(foo));
+ checkEquals("!this(Foo) && this(Bar)", new AndPointcut(new NotPointcut(foo), bar));
+ checkEquals("!(this(Foo) && this(Bar)) || this(C)", new OrPointcut(new NotPointcut(new AndPointcut(foo, bar)), c));
+ checkEquals("!!this(Foo)", new NotPointcut(new NotPointcut(foo)));
+ }
+
+ private static class Foo {
+ }
+
+ private static class Bar {
+ }
+
+ private static class C {
+ }
+
+ static {
+ new Foo();
+ new Bar();
+ new C(); // just to touch them and so eclipse thinks they are used
+ }
+
+ private Pointcut makePointcut(String pattern) {
+ return new PatternParser(pattern).parsePointcut();
+ }
+
+ private void checkEquals(String pattern, Pointcut p) throws IOException {
+ assertEquals(pattern, p, makePointcut(pattern));
+ checkSerialization(pattern);
+ }
+
+ private void checkSerialization(String string) throws IOException {
+ Pointcut p = makePointcut(string);
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ VersionedDataInputStream in = new VersionedDataInputStream(bi);
+ Pointcut newP = Pointcut.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.aspectj.util.LangUtil;
+import org.aspectj.weaver.tools.JoinPointMatch;
+import org.aspectj.weaver.tools.PointcutExpression;
+import org.aspectj.weaver.tools.PointcutParameter;
+import org.aspectj.weaver.tools.PointcutParser;
+import org.aspectj.weaver.tools.ShadowMatch;
+
+/**
+ * @author colyer
+ *
+ */
+public class ArgsTestCase extends TestCase {
+
+ PointcutExpression wildcardArgs;
+ PointcutExpression oneA;
+ PointcutExpression oneAandaC;
+ PointcutExpression BthenAnything;
+ PointcutExpression singleArg;
+
+ public void testMatchJP() throws Exception {
+ if (needToSkip)
+ return;
+
+ Method oneAArg = B.class.getMethod("x", new Class[] { A.class });
+ Method oneBArg = B.class.getMethod("y", new Class[] { B.class });
+ Method acArgs = C.class.getMethod("z", new Class[] { A.class, C.class });
+ Method baArgs = C.class.getMethod("t", new Class[] { B.class, A.class });
+
+ checkMatches(wildcardArgs.matchesMethodExecution(oneAArg), new B(), new B(), new Object[] { new A() });
+ checkMatches(wildcardArgs.matchesMethodExecution(oneBArg), new B(), new B(), new Object[] { new B() });
+ checkMatches(wildcardArgs.matchesMethodExecution(acArgs), new C(), new C(), new Object[] { new B(), new C() });
+ checkMatches(wildcardArgs.matchesMethodExecution(baArgs), new C(), new C(), new Object[] { new B(), new B() });
+
+ checkMatches(oneA.matchesMethodExecution(oneAArg), new B(), new B(), new Object[] { new A() });
+ checkMatches(oneA.matchesMethodExecution(oneBArg), new B(), new B(), new Object[] { new B() });
+ checkNoMatch(oneA.matchesMethodExecution(acArgs), new C(), new C(), new Object[] { new B(), new C() });
+ checkNoMatch(oneA.matchesMethodExecution(baArgs), new C(), new C(), new Object[] { new B(), new B() });
+
+ checkNoMatch(oneAandaC.matchesMethodExecution(oneAArg), new B(), new B(), new Object[] { new A() });
+ checkNoMatch(oneAandaC.matchesMethodExecution(oneBArg), new B(), new B(), new Object[] { new B() });
+ checkMatches(oneAandaC.matchesMethodExecution(acArgs), new C(), new C(), new Object[] { new B(), new C() });
+ checkNoMatch(oneAandaC.matchesMethodExecution(baArgs), new C(), new C(), new Object[] { new B(), new B() });
+
+ checkNoMatch(BthenAnything.matchesMethodExecution(oneAArg), new B(), new B(), new Object[] { new A() });
+ checkMatches(BthenAnything.matchesMethodExecution(oneBArg), new B(), new B(), new Object[] { new B() });
+ checkNoMatch(BthenAnything.matchesMethodExecution(acArgs), new C(), new C(), new Object[] { new A(), new C() });
+ checkMatches(BthenAnything.matchesMethodExecution(baArgs), new C(), new C(), new Object[] { new B(), new B() });
+
+ checkMatches(singleArg.matchesMethodExecution(oneAArg), new B(), new B(), new Object[] { new A() });
+ checkMatches(singleArg.matchesMethodExecution(oneBArg), new B(), new B(), new Object[] { new B() });
+ checkNoMatch(singleArg.matchesMethodExecution(acArgs), new C(), new C(), new Object[] { new B(), new C() });
+ checkNoMatch(singleArg.matchesMethodExecution(baArgs), new C(), new C(), new Object[] { new B(), new B() });
+
+ }
+
+ public void testBinding() throws Exception {
+ if (needToSkip)
+ return;
+
+ PointcutParser parser = PointcutParser
+ .getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(A.class.getClassLoader());
+ PointcutParameter a = parser.createPointcutParameter("a", A.class);
+ A theParameter = new A();
+ PointcutExpression bindA = parser.parsePointcutExpression("args(a,*)", A.class, new PointcutParameter[] { a });
+
+ Method acArgs = C.class.getMethod("z", new Class[] { A.class, C.class });
+ ShadowMatch sMatch = bindA.matchesMethodExecution(acArgs);
+ JoinPointMatch jpMatch = sMatch.matchesJoinPoint(new A(), new A(), new Object[] { theParameter });
+ assertTrue("should match", jpMatch.matches());
+ PointcutParameter[] bindings = jpMatch.getParameterBindings();
+ assertTrue("one parameter", bindings.length == 1);
+ assertEquals("should be bound to the arg value", theParameter, bindings[0].getBinding());
+
+ PointcutParameter c = parser.createPointcutParameter("c", C.class);
+ C cParameter = new C();
+ PointcutExpression bindAandC = parser.parsePointcutExpression("args(a,c)", A.class, new PointcutParameter[] { a, c });
+ sMatch = bindAandC.matchesMethodExecution(acArgs);
+ jpMatch = sMatch.matchesJoinPoint(new A(), new A(), new Object[] { theParameter, cParameter });
+ assertTrue("should match", jpMatch.matches());
+ bindings = jpMatch.getParameterBindings();
+ assertTrue("two parameters", bindings.length == 2);
+ assertEquals("should be bound to the a arg value", theParameter, bindings[0].getBinding());
+ assertEquals("should be bound to the c arg value", cParameter, bindings[1].getBinding());
+ assertEquals("a", bindings[0].getName());
+ assertEquals("c", bindings[1].getName());
+ }
+
+ public void testMatchJPWithPrimitiveTypes() throws Exception {
+ if (needToSkip)
+ return;
+
+ try {
+
+ PointcutParser parser = PointcutParser
+ .getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(A.class.getClassLoader());
+ PointcutExpression oneInt = parser.parsePointcutExpression("args(int)");
+ PointcutExpression oneInteger = parser.parsePointcutExpression("args(Integer)");
+
+ Method oneIntM = A.class.getMethod("anInt", new Class[] { int.class });
+ Method oneIntegerM = A.class.getMethod("anInteger", new Class[] { Integer.class });
+
+ if (LangUtil.is15VMOrGreater()) {
+ checkMatches(oneInt.matchesMethodExecution(oneIntM), new A(), new A(), new Object[] { new Integer(5) });
+ checkMatches(oneInt.matchesMethodExecution(oneIntegerM), new A(), new A(), new Object[] { new Integer(5) });
+ checkMatches(oneInteger.matchesMethodExecution(oneIntM), new A(), new A(), new Object[] { new Integer(5) });
+ checkMatches(oneInteger.matchesMethodExecution(oneIntegerM), new A(), new A(), new Object[] { new Integer(5) });
+ } else {
+ checkMatches(oneInt.matchesMethodExecution(oneIntM), new A(), new A(), new Object[] { new Integer(5) });
+ checkNoMatch(oneInt.matchesMethodExecution(oneIntegerM), new A(), new A(), new Object[] { new Integer(5) });
+ checkNoMatch(oneInteger.matchesMethodExecution(oneIntM), new A(), new A(), new Object[] { new Integer(5) });
+ checkMatches(oneInteger.matchesMethodExecution(oneIntegerM), new A(), new A(), new Object[] { new Integer(5) });
+ }
+
+ } catch (Exception ex) {
+ fail("Unexpected exception " + ex);
+ }
+
+ }
+
+ private void checkMatches(ShadowMatch sMatch, Object thisOjb, Object targetObj, Object[] args) {
+ assertTrue("match expected", sMatch.matchesJoinPoint(thisOjb, targetObj, args).matches());
+ }
+
+ private void checkNoMatch(ShadowMatch sMatch, Object thisOjb, Object targetObj, Object[] args) {
+ assertFalse("no match expected", sMatch.matchesJoinPoint(thisOjb, targetObj, args).matches());
+ }
+
+ private static class A {
+ public void anInt(int i) {
+ }
+
+ public void anInteger(Integer i) {
+ }
+
+ }
+
+ private static class B extends A {
+ public void x(A a) {
+ }
+
+ public void y(B b) {
+ }
+ }
+
+ private static class C {
+ public void z(A a, C c) {
+ }
+
+ public void t(B b, A a) {
+ }
+ }
+
+ private boolean needToSkip = false;
+
+ /** this condition can occur on the build machine only, and is way too complex to fix right now... */
+ private boolean needToSkipPointcutParserTests() {
+ if (!LangUtil.is15VMOrGreater())
+ return false;
+ try {
+ Class.forName("org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate", false, this.getClass()
+ .getClassLoader());// ReflectionBasedReferenceTypeDelegate.class.getClassLoader());
+ } catch (ClassNotFoundException cnfEx) {
+ return true;
+ }
+ return false;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ needToSkip = needToSkipPointcutParserTests();
+ if (needToSkip)
+ return;
+ PointcutParser parser = PointcutParser
+ .getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(A.class.getClassLoader());
+ wildcardArgs = parser.parsePointcutExpression("args(..)");
+ oneA = parser.parsePointcutExpression("args(org.aspectj.weaver.patterns.ArgsTestCase.A)");
+ oneAandaC = parser
+ .parsePointcutExpression("args(org.aspectj.weaver.patterns.ArgsTestCase.A,org.aspectj.weaver.patterns.ArgsTestCase.C)");
+ BthenAnything = parser.parsePointcutExpression("args(org.aspectj.weaver.patterns.ArgsTestCase.B,..)");
+ singleArg = parser.parsePointcutExpression("args(*)");
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.bridge.AbortException;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.BindingTypePattern;
+import org.aspectj.weaver.patterns.Bindings;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.TestScope;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+
+public class BindingTestCase extends PatternsTestCase {
+
+ public World getWorld() {
+ return new ReflectionWorld(true, this.getClass().getClassLoader());
+ }
+
+ public void testResolveBindings() {
+ BindingTypePattern at = new BindingTypePattern(world.resolve("java.lang.Object"), 0, false);
+ BindingTypePattern bt = new BindingTypePattern(world.resolve("java.lang.Object"), 1, false);
+
+ BindingTypePattern[] all = new BindingTypePattern[] { at, bt };
+ BindingTypePattern[] none = new BindingTypePattern[] { null, null };
+ BindingTypePattern[] a = new BindingTypePattern[] { at, null };
+ BindingTypePattern[] b = new BindingTypePattern[] { null, bt };
+
+ checkBindings("this(b)", b);
+ checkBindings("this(java.lang.String)", none);
+ checkBindings("this(*)", none);
+ checkBindings("this(a)", a);
+
+ try {
+ checkBindings("args(.., a,..,b)", all);
+ // checkBindings("args(a,..,b, ..)", all);
+ fail("shouldn't be implemented yet");
+ } catch (Throwable ae) {
+ // // diff world implementations may exit by different means
+ // } catch (Exception e) {
+ // // diff world implementations may exit by different means
+ }
+
+ checkBindings("args(a,..,b)", all);
+ checkBindings("args(b)", b);
+
+ checkBindings("args()", none);
+
+ checkBindings("this(a) && this(b)", all);
+
+ checkBindingFailure("this(a) && this(a)", "multiple");
+ // checkBindingFailure("this(a) && this(b)");
+
+ checkBindingFailure("this(a) || this(b)", "inconsistent");
+ checkBindingFailure("this(java.lang.String) || this(b)", "inconsistent");
+ checkBindingFailure("this(a) || this(java.lang.String)", "inconsistent");
+ checkBindings("this(a) || this(a)", a);
+
+ checkBindings("!this(java.lang.String)", none);
+ checkBindings("!this(java.lang.String) && this(a)", a);
+ checkBindingFailure("!this(a)", "negation");
+ // checkBindingFailure("this(a)");
+
+ checkBindings("cflow(this(a))", a);
+ checkBindings("cflow(this(a)) && this(b)", all);
+
+ checkBindingFailure("cflow(this(a)) || this(b)", "inconsistent");
+ checkBindingFailure("cflow(this(a)) && this(a)", "multiple");
+
+ checkBindingFailure("!cflow(this(a))", "negation");
+
+ // todo
+ // this should fail since a isn't visible to if
+ // checkBindingFailure("cflow(if(a != null)) && this(a)");
+ // checkBinding("cflow(if(a != null) && this(a))", a);
+
+ }
+
+ /**
+ * Method checkBindingFailure. (assumes an env where "a" and "b" are formals).
+ *
+ * @param string
+ */
+ private void checkBindingFailure(String pattern, String prefix) {
+ PatternParser parser = new PatternParser(pattern);
+ Pointcut p = parser.parsePointcut();
+ Bindings actualBindings = new Bindings(2);
+ try {
+ p.resolveBindings(makeSimpleScope(), actualBindings);
+ } catch (AbortException re) {
+ assertEquals(prefix, re.getIMessage().getMessage().substring(0, prefix.length()));
+ // System.out.println("expected exception: " + re);
+ return;
+ } catch (Throwable t) {
+ assertTrue(prefix, t.getMessage().indexOf(prefix) != -1);
+ return;
+ }
+ assertTrue("should have failed", false);
+ }
+
+ /**
+ * Method checkBindings.
+ *
+ * @param string
+ * @param i
+ */
+ private void checkBindings(String pattern, BindingTypePattern[] expectedBindings) {
+ PatternParser parser = new PatternParser(pattern);
+ Pointcut p = parser.parsePointcut();
+ Bindings actualBindings = new Bindings(expectedBindings.length);
+
+ TestScope simpleScope = makeSimpleScope();
+ p.resolveBindings(simpleScope, actualBindings);
+ // System.out.println(actualBindings);
+
+ new Bindings(expectedBindings).checkEquals(actualBindings, simpleScope);
+ }
+
+ public TestScope makeSimpleScope() {
+ return new TestScope(new String[] { "int", "java.lang.String" }, new String[] { "a", "b" }, world);
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.aspectj.weaver.VersionedDataInputStream;
+
+public class DeclareErrorOrWarningTestCase extends TestCase {
+
+ public void testParse() throws IOException {
+ DeclareErrorOrWarning d = parse("declare error: call(void foo()): \"that is bad\";");
+ assertTrue(d.isError());
+ assertEquals(d.getPointcut(), new PatternParser("call(void foo())").parsePointcut());
+ assertEquals("that is bad", d.getMessage());
+ checkSerialization(d);
+
+ d = parse("declare warning: bar() && baz(): \"boo!\";");
+ assertTrue(!d.isError());
+ assertEquals(d.getPointcut(), new PatternParser("bar() && baz()").parsePointcut());
+ assertEquals("boo!", d.getMessage());
+ checkSerialization(d);
+
+ }
+
+ public void testStartAndEndPositionSet() throws IOException {
+ DeclareErrorOrWarning d = parse("declare error: call(void foo()): \"that is bad\";");
+ assertEquals("start position should be 0", 0, d.getStart());
+ assertEquals("end position should be 46", 46, d.getEnd());
+ }
+
+ private DeclareErrorOrWarning parse(String string) {
+ return (DeclareErrorOrWarning) new PatternParser(string).parseDeclare();
+ }
+
+ private void checkSerialization(Declare declare) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ declare.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ VersionedDataInputStream in = new VersionedDataInputStream(bi);
+ Declare newDeclare = Declare.read(in, null);
+
+ assertEquals("write/read", declare, newDeclare);
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2007-2008 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Alexandre Vasseur
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.patterns.AndAnnotationTypePattern;
+import org.aspectj.weaver.patterns.AndPointcut;
+import org.aspectj.weaver.patterns.AndTypePattern;
+import org.aspectj.weaver.patterns.AnnotationPatternList;
+import org.aspectj.weaver.patterns.AnnotationPointcut;
+import org.aspectj.weaver.patterns.AnnotationTypePattern;
+import org.aspectj.weaver.patterns.AnyAnnotationTypePattern;
+import org.aspectj.weaver.patterns.AnyTypePattern;
+import org.aspectj.weaver.patterns.AnyWithAnnotationTypePattern;
+import org.aspectj.weaver.patterns.ArgsAnnotationPointcut;
+import org.aspectj.weaver.patterns.ArgsPointcut;
+import org.aspectj.weaver.patterns.BindingAnnotationTypePattern;
+import org.aspectj.weaver.patterns.BindingTypePattern;
+import org.aspectj.weaver.patterns.CflowPointcut;
+import org.aspectj.weaver.patterns.ConcreteCflowPointcut;
+import org.aspectj.weaver.patterns.DeclareAnnotation;
+import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
+import org.aspectj.weaver.patterns.DeclareParents;
+import org.aspectj.weaver.patterns.DeclarePrecedence;
+import org.aspectj.weaver.patterns.DeclareSoft;
+import org.aspectj.weaver.patterns.DumpPointcutVisitor;
+import org.aspectj.weaver.patterns.EllipsisAnnotationTypePattern;
+import org.aspectj.weaver.patterns.EllipsisTypePattern;
+import org.aspectj.weaver.patterns.ExactAnnotationTypePattern;
+import org.aspectj.weaver.patterns.ExactTypePattern;
+import org.aspectj.weaver.patterns.HandlerPointcut;
+import org.aspectj.weaver.patterns.HasMemberTypePattern;
+import org.aspectj.weaver.patterns.IfPointcut;
+import org.aspectj.weaver.patterns.KindedPointcut;
+import org.aspectj.weaver.patterns.ModifiersPattern;
+import org.aspectj.weaver.patterns.NamePattern;
+import org.aspectj.weaver.patterns.NoTypePattern;
+import org.aspectj.weaver.patterns.NotAnnotationTypePattern;
+import org.aspectj.weaver.patterns.NotPointcut;
+import org.aspectj.weaver.patterns.NotTypePattern;
+import org.aspectj.weaver.patterns.OrAnnotationTypePattern;
+import org.aspectj.weaver.patterns.OrPointcut;
+import org.aspectj.weaver.patterns.OrTypePattern;
+import org.aspectj.weaver.patterns.ParserException;
+import org.aspectj.weaver.patterns.PatternNode;
+import org.aspectj.weaver.patterns.PatternNodeVisitor;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.PerCflow;
+import org.aspectj.weaver.patterns.PerFromSuper;
+import org.aspectj.weaver.patterns.PerObject;
+import org.aspectj.weaver.patterns.PerSingleton;
+import org.aspectj.weaver.patterns.PerTypeWithin;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.ReferencePointcut;
+import org.aspectj.weaver.patterns.SignaturePattern;
+import org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut;
+import org.aspectj.weaver.patterns.ThisOrTargetPointcut;
+import org.aspectj.weaver.patterns.ThrowsPattern;
+import org.aspectj.weaver.patterns.TypePattern;
+import org.aspectj.weaver.patterns.TypePatternList;
+import org.aspectj.weaver.patterns.TypeVariablePattern;
+import org.aspectj.weaver.patterns.TypeVariablePatternList;
+import org.aspectj.weaver.patterns.WildAnnotationTypePattern;
+import org.aspectj.weaver.patterns.WildTypePattern;
+import org.aspectj.weaver.patterns.WithinAnnotationPointcut;
+import org.aspectj.weaver.patterns.WithinCodeAnnotationPointcut;
+import org.aspectj.weaver.patterns.WithinPointcut;
+import org.aspectj.weaver.patterns.WithincodePointcut;
+
+/**
+ * A sample toString like visitor that helps understanding the AST tree structure organization
+ *
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class DumpPointcutVisitor implements PatternNodeVisitor {
+
+ private StringBuffer sb = new StringBuffer();
+ public String get() {
+ return sb.toString();
+ }
+
+ private void append(Object o) {
+ sb.append(o.toString());
+ }
+
+ private void append(char c) {
+ sb.append(c);
+ }
+
+ /**
+ * This method helps maintaining the API and raises warning when PatternNode subclasses do not
+ * implement the visitor pattern
+ *
+ * @param node
+ * @param data
+ * @return
+ */
+ public Object visit(PatternNode node, Object data) {
+ System.err.println("Should implement: " + node.getClass());
+ return null;
+ }
+
+ public Object visit(AnyTypePattern node, Object data) {
+ append('*');
+ return null;
+ }
+
+ public Object visit(NoTypePattern node, Object data) {
+ append(node.toString());//TODO no idea when this one is used
+ return null;
+ }
+
+ public Object visit(EllipsisTypePattern node, Object data) {
+ append(node.toString());
+ return null;
+ }
+
+ public Object visit(AnyWithAnnotationTypePattern node, Object data) {
+ node.annotationPattern.accept(this, data);
+ append(" *");
+ return null;
+ }
+
+ public Object visit(AnyAnnotationTypePattern node, Object data) {
+ //@ANY : ignore
+ append('*');
+ return null;
+ }
+
+ public Object visit(EllipsisAnnotationTypePattern node, Object data) {
+ append("..");
+ return null;
+ }
+
+ public Object visit(AndAnnotationTypePattern node, Object data) {
+ node.getLeft().accept(this, data);
+ append(' ');
+ node.getRight().accept(this, data);
+ return null;
+ }
+
+ public Object visit(AndPointcut node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" && ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(AndTypePattern node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" && ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(AnnotationPatternList node, Object data) {
+ AnnotationTypePattern[] annotations = node.getAnnotationPatterns();
+ for (int i = 0; i < annotations.length; i++) {
+ if (i>0) append(", ");//Note: list is ",", and is " " separated for annotations
+ annotations[i].accept(this, data);
+ }
+ return null;
+ }
+
+ public Object visit(AnnotationPointcut node, Object data) {
+ append("@annotation(");
+ node.getAnnotationTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ArgsAnnotationPointcut node, Object data) {
+ append("@args(");
+ node.getArguments().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ArgsPointcut node, Object data) {
+ append("args(");
+ node.getArguments().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(BindingAnnotationTypePattern node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(BindingTypePattern node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(CflowPointcut node, Object data) {
+ append(node.isCflowBelow()?"cflowbelow(":"cflow(");
+ node.getEntry().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ExactAnnotationTypePattern node, Object data) {
+ //append('@'); // since @annotation(@someAnno) cannot be parsed anymore
+ append(node.getAnnotationType().getName());
+ return null;
+ }
+
+ public Object visit(ExactTypePattern node, Object data) {
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ append('(');
+ node.getAnnotationPattern().accept(this, data);
+ append(' ');
+ }
+
+ String typeString = node.getType().toString();
+ if (node.isVarArgs()) typeString = typeString.substring(0, typeString.lastIndexOf('['));//TODO AV - ugly
+ append(typeString);
+ if (node.isIncludeSubtypes()) append('+');
+ if (node.isVarArgs()) append("...");
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ append(')');
+ }
+ return null;
+ }
+
+ public Object visit(KindedPointcut node, Object data) {
+ append(node.getKind().getSimpleName());
+ append('(');
+ node.getSignature().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ModifiersPattern node, Object data) {
+ append(node.toString());//note: node takes care of forbidden mods
+ return null;
+ }
+
+ public Object visit(NamePattern node, Object data) {
+ append(node.toString());
+ return null;
+ }
+
+ public Object visit(NotAnnotationTypePattern node, Object data) {
+ append("!");
+ node.getNegatedPattern().accept(this, data);
+ return null;
+ }
+
+ public Object visit(NotPointcut node, Object data) {
+ append("!(");
+ node.getNegatedPointcut().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(NotTypePattern node, Object data) {
+ append("!(");
+ node.getNegatedPattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(OrAnnotationTypePattern node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" || ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(OrPointcut node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" || ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(OrTypePattern node, Object data) {
+ append('(');
+ node.getLeft().accept(this, data);
+ append(" || ");
+ node.getRight().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ReferencePointcut node, Object data) {
+ append(node.toString());
+ return null;
+ }
+
+ public Object visit(SignaturePattern node, Object data) {
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ node.getAnnotationPattern().accept(this, data);
+ append(' ');
+ }
+
+ if (node.getModifiers() != ModifiersPattern.ANY) {
+ node.getModifiers().accept(this, data);
+ append(' ');
+ }
+
+ if (node.getKind() == Member.STATIC_INITIALIZATION) {
+ node.getDeclaringType().accept(this, data);
+ } else if (node.getKind() == Member.HANDLER) {
+ append("handler(");
+ node.getParameterTypes().get(0).accept(this, data);//Note: we know we have 1 child
+ append(')');
+ } else {
+ if (!(node.getKind() == Member.CONSTRUCTOR)) {
+ node.getReturnType().accept(this, data);
+ append(' ');
+ }
+ if (node.getDeclaringType() != TypePattern.ANY) {
+ node.getDeclaringType().accept(this, data);
+ append('.');
+ }
+ if (node.getKind() == Member.CONSTRUCTOR) {
+ append("new");
+ } else {
+ node.getName().accept(this, data);
+ }
+ if (node.getKind() == Member.METHOD || node.getKind() == Member.CONSTRUCTOR) {
+ append('(');
+ node.getParameterTypes().accept(this, data);
+ append(')');
+ }
+ if (node.getThrowsPattern() != null) {
+ append(' ');
+ node.getThrowsPattern().accept(this, data);
+ }
+ }
+ return null;
+ }
+
+ public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
+ append(node.isThis() ? "@this(" : "@target(");
+ node.getAnnotationTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(ThisOrTargetPointcut node, Object data) {
+ append(node.isThis() ? "this(" : "target(");
+ node.getType().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ // Note: a visitor instance is not thread safe so should not be shared
+ private boolean inThrowsForbidden = false;
+
+ public Object visit(ThrowsPattern node, Object data) {
+ if (node == ThrowsPattern.ANY) return null;
+
+ append("throws ");
+ node.getRequired().accept(this, data);
+ if (node.getForbidden().size() > 0) {
+ // a hack since throws !(A, B) cannot be parsed
+ try {
+ inThrowsForbidden = true;
+ node.getForbidden().accept(this, data);
+ } finally {
+ inThrowsForbidden = false;
+ }
+ }
+ return null;
+ }
+
+ public Object visit(TypePatternList node, Object data) {
+ if (node.getTypePatterns().length == 0) return null;
+
+ TypePattern[] typePatterns = node.getTypePatterns();
+ for (int i = 0; i < typePatterns.length; i++) {
+ TypePattern typePattern = typePatterns[i];
+ if (i > 0) append(", ");
+ if (inThrowsForbidden) append('!');
+ typePattern.accept(this, data);
+ }
+ return null;
+ }
+
+ public Object visit(WildAnnotationTypePattern node, Object data) {
+ append("@(");
+ node.getTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(WildTypePattern node, Object data) {
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ append('(');
+ node.getAnnotationPattern().accept(this, data);
+ append(' ');
+ }
+ NamePattern[] namePatterns = node.getNamePatterns();
+ for (int i=0; i < namePatterns.length; i++) {
+ if (namePatterns[i] == null) {
+ append('.');//FIXME mh, error prone, can't we have a nullNamePattern ?
+ } else {
+ if (i > 0) append('.');
+ namePatterns[i].accept(this, data);
+ }
+ }
+ if (node.isIncludeSubtypes()) append('+');
+ if (node.isVarArgs()) append("...");
+ if (node.getAnnotationPattern() != AnnotationTypePattern.ANY) {
+ append(')');
+ }
+ return null;
+ }
+
+ public Object visit(WithinAnnotationPointcut node, Object data) {
+ append("@within(");
+ node.getAnnotationTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(WithinCodeAnnotationPointcut node, Object data) {
+ append("@withincode(");
+ node.getAnnotationTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(WithinPointcut node, Object data) {
+ append("within(");
+ node.getTypePattern().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(WithincodePointcut node, Object data) {
+ append("withincode(");
+ node.getSignature().accept(this, data);
+ append(')');
+ return null;
+ }
+
+ public Object visit(Pointcut.MatchesNothingPointcut node, Object data) {
+ append("");//TODO shouldn't that be a "false" ?
+ return null;
+ }
+
+
+ //-------------- perX
+
+ public Object visit(PerCflow node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(PerFromSuper node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(PerObject node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(PerSingleton node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(PerTypeWithin node, Object data) {
+ append(node);
+ return null;
+ }
+
+ // ------------- declare X
+
+ public Object visit(DeclareAnnotation node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(DeclareErrorOrWarning node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(DeclareParents node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(DeclarePrecedence node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(DeclareSoft node, Object data) {
+ append(node);
+ return null;
+ }
+
+ // ----------- misc
+
+ public Object visit(ConcreteCflowPointcut node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(HandlerPointcut node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(IfPointcut node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(TypeVariablePattern node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(TypeVariablePatternList node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public Object visit(HasMemberTypePattern node, Object data) {
+ append(node);
+ return null;
+ }
+
+ public static void check(String s) {
+ check(Pointcut.fromString(s), false);
+ }
+
+ public static void check(PatternNode pc, boolean isTypePattern) {
+ DumpPointcutVisitor v1 = new DumpPointcutVisitor();
+ pc.accept(v1, null);
+
+ DumpPointcutVisitor v2 = new DumpPointcutVisitor();
+ final PatternNode pc2;
+ if (isTypePattern) {
+ pc2 = new PatternParser(v1.get()).parseTypePattern();
+ } else {
+ pc2 = Pointcut.fromString(v1.get());
+ }
+ pc2.accept(v2, null);
+
+ // at second parsing, the String form stay stable when parsed and parsed again
+ if (! v1.get().equals(v2.get())) {
+ throw new ParserException("Unstable back parsing for '"+pc+"', got '" + v1.get() + "' and '" + v2.get() + "'", null);
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ String[] s = new String[]{
+ //"@args(Foo, Goo, *, .., Moo)",
+ //"execution(* *())",
+ //"call(* *(int, Integer...))",
+ //"staticinitialization(@(Foo) @(Boo) @(Goo) Moo)",
+ "(if(true) && set(int BaseApp.i))"
+
+ };
+ for (int i = 0; i < s.length; i++) {
+ check(s[i]);
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.ModifiersPattern;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+
+public class ModifiersPatternTestCase extends PatternsTestCase {
+
+ public void testMatch() {
+ int[] publicMatches = new int[] { Modifier.PUBLIC, Modifier.PUBLIC | Modifier.STATIC,
+ Modifier.PUBLIC | Modifier.STATIC | Modifier.STRICT | Modifier.FINAL, };
+
+ int[] publicFailures = new int[] { Modifier.PRIVATE, 0, Modifier.STATIC | Modifier.STRICT | Modifier.FINAL, };
+
+ int[] publicStaticMatches = new int[] { Modifier.PUBLIC | Modifier.STATIC,
+ Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL | Modifier.STRICT, };
+
+ int[] publicStaticFailures = new int[] { 0, Modifier.PUBLIC, Modifier.STATIC, };
+
+ int[] trickMatches = new int[] { Modifier.PRIVATE, Modifier.PRIVATE | Modifier.ABSTRACT, Modifier.PRIVATE | Modifier.FINAL, };
+
+ int[] trickFailures = new int[] { Modifier.PUBLIC, Modifier.PRIVATE | Modifier.STATIC, Modifier.PRIVATE | Modifier.STRICT, };
+
+ int[] none = new int[0];
+
+ checkMatch("", publicMatches, none);
+ checkMatch("", publicFailures, none);
+ checkMatch("!public", publicFailures, publicMatches);
+ checkMatch("public", publicMatches, publicFailures);
+ checkMatch("public static", none, publicFailures);
+ checkMatch("public static", publicStaticMatches, publicStaticFailures);
+
+ checkMatch("private !static !strictfp", trickMatches, trickFailures);
+ checkMatch("private !static !strictfp", none, publicMatches);
+ checkMatch("private !static !strictfp", none, publicStaticMatches);
+ }
+
+ private ModifiersPattern makeModifiersPattern(String pattern) {
+ return new PatternParser(pattern).parseModifiersPattern();
+ }
+
+ private void checkMatch(String pattern, int[] shouldMatch, int[] shouldFail) {
+ ModifiersPattern p = makeModifiersPattern(pattern);
+ checkMatch(p, shouldMatch, true);
+ checkMatch(p, shouldFail, false);
+ }
+
+ private void checkMatch(ModifiersPattern p, int[] matches, boolean shouldMatch) {
+ for (int i = 0; i < matches.length; i++) {
+ boolean result = p.matches(matches[i]);
+ String msg = "matches " + p + " to " + Modifier.toString(matches[i]) + " expected ";
+ if (shouldMatch) {
+ assertTrue(msg + shouldMatch, result);
+ } else {
+ assertTrue(msg + shouldMatch, !result);
+ }
+ }
+ }
+
+ public void testSerialization() throws IOException {
+ String[] patterns = new String[] { "", "!public", "public", "public static", "private !static !strictfp", };
+
+ for (int i = 0, len = patterns.length; i < len; i++) {
+ checkSerialization(patterns[i]);
+ }
+ }
+
+ /**
+ * Method checkSerialization.
+ *
+ * @param string
+ */
+ private void checkSerialization(String string) throws IOException {
+ ModifiersPattern p = makeModifiersPattern(string);
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ VersionedDataInputStream in = new VersionedDataInputStream(bi);
+ ModifiersPattern newP = ModifiersPattern.read(in);
+
+ assertEquals("write/read", p, newP);
+ }
+
+ public World getWorld() {
+ return new ReflectionWorld(true, this.getClass().getClassLoader());
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.patterns.BasicTokenSource;
+import org.aspectj.weaver.patterns.IToken;
+import org.aspectj.weaver.patterns.ITokenSource;
+import org.aspectj.weaver.patterns.NamePattern;
+import org.aspectj.weaver.patterns.NamePatternTestCase;
+import org.aspectj.weaver.patterns.PatternParser;
+
+import junit.framework.TestCase;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class NamePatternParserTestCase extends TestCase {
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public NamePatternParserTestCase(String name) {
+ super(name);
+ }
+
+ public void testMatch() {
+ checkMatch(NamePatternTestCase.matchAll);
+ checkMatch(NamePatternTestCase.match1);
+ checkMatch(NamePatternTestCase.match2);
+
+
+ NamePattern p = new PatternParser("abc *").parseNamePattern();
+ assertEquals(new NamePattern("abc"), p);
+ }
+
+ /**
+ * Method checkMatch.
+ * @param string
+ * @param matchAll
+ * @param b
+ */
+ private void checkMatch(String[] patterns) {
+ for (int i=0, len=patterns.length; i < len; i++) {
+ String pattern = patterns[i];
+ ITokenSource tokenSource = BasicTokenSource.makeTokenSource(pattern,null);
+ NamePattern p1 = new PatternParser(tokenSource).parseNamePattern();
+ NamePattern p2 = new NamePattern(pattern);
+ assertEquals("pattern: " + pattern, p2, p1);
+ assertEquals("eof", IToken.EOF, tokenSource.next());
+ }
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.patterns.NamePattern;
+
+import junit.framework.TestCase;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class NamePatternTestCase extends TestCase {
+ static String[] matchAll = new String[] {
+ "*****",
+ "*"
+ };
+
+
+ static String[] match1 = new String[] {
+ "abcde", "abc*", "abcd*", "abcde*",
+ "*e", "*cde", "*abcde",
+ "a*e", "ab*e", "abc*de",
+ "*a*b*c*d*e*", "a*c*e", "a***bcde",
+ "*d*",
+ };
+
+ static String[] match2 = new String[] {
+ "abababab",
+ "aba*", "abab*", "abababab*",
+ "*b", "*ab", "*ababab", "*abababab",
+ "a*b", "ab*b", "abab*abab",
+ "*a*b*a*b*a*b*a*b*", "a*****b", "a**b", "ab*b*b",
+ };
+
+ /**
+ * Constructor for PatternTestCase.
+ * @param name
+ */
+ public NamePatternTestCase(String name) {
+ super(name);
+ }
+
+ public void testMatch() {
+ checkMatch("abcde", matchAll, true);
+ checkMatch("abcde", match1, true);
+ checkMatch("abcde", match2, false);
+
+ checkMatch("abababab", matchAll, true);
+ checkMatch("abababab", match1, false);
+ checkMatch("abababab", match2, true);
+
+ }
+
+ /**
+ * Method checkMatch.
+ * @param string
+ * @param matchAll
+ * @param b
+ */
+ private void checkMatch(String string, String[] patterns, boolean shouldMatch) {
+ for (int i=0, len=patterns.length; i < len; i++) {
+ NamePattern p = new NamePattern(patterns[i]);
+ checkMatch(string, p, shouldMatch);
+ }
+ }
+
+ private void checkMatch(String string, NamePattern p, boolean shouldMatch) {
+ String msg = "matching " + string + " to " + p;
+ assertEquals(msg, shouldMatch, p.matches(string));
+ }
+
+
+ public void testSerialization() throws IOException {
+ checkSerialization(matchAll);
+ checkSerialization(match1);
+ checkSerialization(match2);
+ }
+
+ private void checkSerialization(String[] patterns) throws IOException {
+ for (int i=0, len=patterns.length; i < len; i++) {
+ NamePattern p = new NamePattern(patterns[i]);
+ checkSerialization(p);
+ }
+ }
+
+
+ private void checkSerialization(NamePattern p) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ VersionedDataInputStream in = new VersionedDataInputStream(bi);
+ NamePattern newP = NamePattern.read(in);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.AnnotationPointcut;
+import org.aspectj.weaver.patterns.AnnotationTypePattern;
+import org.aspectj.weaver.patterns.ExactTypePattern;
+import org.aspectj.weaver.patterns.KindedPointcut;
+import org.aspectj.weaver.patterns.ParserException;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.TestScope;
+import org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut;
+import org.aspectj.weaver.patterns.TypePattern;
+import org.aspectj.weaver.patterns.TypePatternList;
+import org.aspectj.weaver.patterns.TypeVariablePattern;
+import org.aspectj.weaver.patterns.TypeVariablePatternList;
+import org.aspectj.weaver.patterns.WildAnnotationTypePattern;
+import org.aspectj.weaver.patterns.WildTypePattern;
+import org.aspectj.weaver.patterns.WithinAnnotationPointcut;
+import org.aspectj.weaver.patterns.WithinCodeAnnotationPointcut;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment": Window>Preferences>Java>Templates. To enable
+ * and disable the creation of type comments go to Window>Preferences>Java>Code Generation.
+ */
+public class ParserTestCase extends PatternsTestCase {
+
+ public World getWorld() {
+ return new ReflectionWorld(true, getClassLoaderForFile(getTestDataJar()));
+ }
+
+ public void testNamePatterns() {
+
+ // checkNoMatch("abc *", "abcd");
+ // checkNoMatch("* d", "abcd");
+ }
+
+ public void testParse() {
+ PatternParser parser = new PatternParser("execution(void Hello.*(..))");
+ KindedPointcut p = (KindedPointcut) parser.parsePointcut();
+ // System.out.println(p);
+ assertEquals(p.kind, Shadow.MethodExecution);
+ assertTrue(p.getSignature().getName().matches("foobar"));
+
+ try {
+ new PatternParser("initialization(void foo())").parsePointcut();
+ fail("should have been a parse error");
+ } catch (ParserException pe) {
+ // good
+ }
+ }
+
+ // public void testParseExecutionWithAnnotation() {
+ // PatternParser parser = new PatternParser("execution(@SimpleAnnotation void Hello.*(..))");
+ // KindedPointcut p = (KindedPointcut) parser.parsePointcut();
+ // // XXX - needs finishing...
+ // p.resolveBindings(makeSimpleScope(), new Bindings(3));
+ // assertEquals("execution(@p.SimpleAnnotation void Hello.*(..))", p.toString());
+ // assertEquals(p.kind, Shadow.MethodExecution);
+ // assertTrue(p.getSignature().getName().matches("foobar"));
+ // }
+
+ // note... toString on a pointcut is a very quick and easy way to test a successful parse
+ public void testParseExecutionWithMultipleAnnotations() {
+ PatternParser parser = new PatternParser("execution(@SimpleAnnotation (@Foo Integer) (@Goo Hello).*(..))");
+ KindedPointcut p = (KindedPointcut) parser.parsePointcut();
+ assertEquals("execution(@(SimpleAnnotation) (@(Foo) Integer) (@(Goo) Hello).*(..))", p.toString());
+ }
+
+ public void testParseCallWithMultipleAnnotations() {
+ PatternParser parser = new PatternParser("call(@SimpleAnnotation (@Foo Integer) (@Goo Hello).*(..))");
+ KindedPointcut p = (KindedPointcut) parser.parsePointcut();
+ assertEquals("call(@(SimpleAnnotation) (@(Foo) Integer) (@(Goo) Hello).*(..))", p.toString());
+ }
+
+ public void testParseGetWithAnnotations() {
+ PatternParser parser = new PatternParser("get(@Foo (@SimpleAnnotation ReturnType) (@Foo @Goo Hello).*)");
+ KindedPointcut p = (KindedPointcut) parser.parsePointcut();
+ assertEquals("get(@(Foo) (@(SimpleAnnotation) ReturnType) (@(Foo) @(Goo) Hello).*)", p.toString());
+ }
+
+ public void testParseBadGetWithAnnotations() {
+ PatternParser parser = new PatternParser("get(@Foo (@Foo @Goo Hello).*)");
+ try {
+ // KindedPointcut p = (KindedPointcut)
+ parser.parsePointcut();
+ fail("Expected parser exception");
+ } catch (ParserException pEx) {
+ assertEquals("name pattern", pEx.getMessage());
+ }
+ }
+
+ public void testParseGetWithAndAggregationAnnotations() {
+ PatternParser parser = new PatternParser("get(@Foo @SimpleAnnotation ReturnType (@Foo @Goo Hello).*)");
+ KindedPointcut p = (KindedPointcut) parser.parsePointcut();
+ assertEquals("get(@(Foo) @(SimpleAnnotation) ReturnType (@(Foo) @(Goo) Hello).*)", p.toString());
+ }
+
+ public void testParseSetWithAnnotations() {
+ PatternParser parser = new PatternParser("set(@Foo (@SimpleAnnotation ReturnType) (@Foo @Goo Hello).*)");
+ KindedPointcut p = (KindedPointcut) parser.parsePointcut();
+ assertEquals("set(@(Foo) (@(SimpleAnnotation) ReturnType) (@(Foo) @(Goo) Hello).*)", p.toString());
+ }
+
+ public void testParseHandlerWithAnnotations() {
+ PatternParser parser = new PatternParser("handler(@Critical Exception+)");
+ Pointcut p = parser.parsePointcut();
+ assertEquals("handler((@(Critical) Exception+))", p.toString());
+ }
+
+ public void testParseInitializationWithAnnotations() {
+ PatternParser parser = new PatternParser("initialization(@Foo (@Goo Hello).new(@Foo Integer))");
+ Pointcut p = parser.parsePointcut();
+ assertEquals("initialization(@(Foo) (@(Goo) Hello).new((@(Foo) Integer)))", p.toString());
+
+ }
+
+ public void testParsePreInitializationWithAnnotations() {
+ PatternParser parser = new PatternParser("preinitialization(@Foo (@Goo Hello).new(@Foo Integer))");
+ Pointcut p = parser.parsePointcut();
+ assertEquals("preinitialization(@(Foo) (@(Goo) Hello).new((@(Foo) Integer)))", p.toString());
+ }
+
+ public void testStaticInitializationWithAnnotations() {
+ PatternParser parser = new PatternParser("staticinitialization(@Foo @Boo @Goo Moo)");
+ Pointcut p = parser.parsePointcut();
+ assertEquals("staticinitialization((@(Foo) @(Boo) @(Goo) Moo).<clinit>())", p.toString());
+ }
+
+ public void testWithinWithAnnotations() {
+ PatternParser parser = new PatternParser("within(@Foo *)");
+ Pointcut p = parser.parsePointcut();
+ assertEquals("within((@(Foo) *))", p.toString());
+ }
+
+ public void testWithinCodeWithAnnotations() {
+ PatternParser parser = new PatternParser("withincode(@Foo * *.*(..))");
+ Pointcut p = parser.parsePointcut();
+ assertEquals("withincode(@(Foo) * *.*(..))", p.toString());
+ }
+
+ public void testAtAnnotation() {
+ PatternParser parser = new PatternParser("@annotation(Foo)");
+ AnnotationPointcut p = (AnnotationPointcut) parser.parsePointcut();
+ assertEquals("@annotation(Foo)", p.toString());
+ }
+
+ public void testBadAtAnnotation() {
+ PatternParser parser = new PatternParser("@annotation(!Foo)");
+ try {
+ // Pointcut p =
+ parser.parsePointcut();
+ fail("Expected parser exception");
+ } catch (ParserException pEx) {
+ assertEquals("identifier", pEx.getMessage());
+ }
+ }
+
+ public void testAtAnnotationWithBinding() {
+ PatternParser parser = new PatternParser("@annotation(foo)");
+ AnnotationPointcut p = (AnnotationPointcut) parser.parsePointcut();
+ assertEquals("@annotation(foo)", p.toString());
+ }
+
+ public void testDoubleAtAnnotation() {
+ PatternParser parser = new PatternParser("@annotation(Foo Goo)");
+ try {
+ // Pointcut p =
+ parser.parsePointcut();
+ fail("Expected parser exception");
+ } catch (ParserException pEx) {
+ assertEquals(")", pEx.getMessage());
+ }
+ }
+
+ public void testAtWithin() {
+ PatternParser parser = new PatternParser("@within(foo)");
+ WithinAnnotationPointcut p = (WithinAnnotationPointcut) parser.parsePointcut();
+ assertEquals("@within(foo)", p.toString());
+ parser = new PatternParser("@within(Foo))");
+ p = (WithinAnnotationPointcut) parser.parsePointcut();
+ assertEquals("@within(Foo)", p.toString());
+ }
+
+ public void testAtWithinCode() {
+ PatternParser parser = new PatternParser("@withincode(foo)");
+ WithinCodeAnnotationPointcut p = (WithinCodeAnnotationPointcut) parser.parsePointcut();
+ assertEquals("@withincode(foo)", p.toString());
+ parser = new PatternParser("@withincode(Foo))");
+ p = (WithinCodeAnnotationPointcut) parser.parsePointcut();
+ assertEquals("@withincode(Foo)", p.toString());
+ }
+
+ public void testAtThis() {
+ PatternParser parser = new PatternParser("@this(foo)");
+ ThisOrTargetAnnotationPointcut p = (ThisOrTargetAnnotationPointcut) parser.parsePointcut();
+ assertEquals("@this(foo)", p.toString());
+ assertTrue("isThis", p.isThis());
+ parser = new PatternParser("@this(Foo))");
+ p = (ThisOrTargetAnnotationPointcut) parser.parsePointcut();
+ assertTrue("isThis", p.isThis());
+ assertEquals("@this(Foo)", p.toString());
+ }
+
+ public void testAtTarget() {
+ PatternParser parser = new PatternParser("@target(foo)");
+ ThisOrTargetAnnotationPointcut p = (ThisOrTargetAnnotationPointcut) parser.parsePointcut();
+ assertEquals("@target(foo)", p.toString());
+ assertTrue("isTarget", !p.isThis());
+ parser = new PatternParser("@target(Foo))");
+ p = (ThisOrTargetAnnotationPointcut) parser.parsePointcut();
+ assertTrue("isTarget", !p.isThis());
+ assertEquals("@target(Foo)", p.toString());
+ }
+
+ public void testAtArgs() {
+ PatternParser parser = new PatternParser("@args(Foo,Goo,*,..,Moo)");
+ Pointcut p = parser.parsePointcut();
+ assertEquals("@args(Foo, Goo, ANY, .., Moo)", p.toString());
+ }
+
+ public void testParseSimpleTypeVariable() {
+ PatternParser parser = new PatternParser("T");
+ TypeVariablePattern tv = parser.parseTypeVariable();
+ TypeVariablePattern expected = new TypeVariablePattern("T");
+ assertEquals("Expected simple type variable T", expected, tv);
+ }
+
+ public void testParseExtendingTypeVariable() {
+ PatternParser parser = new PatternParser("T extends Number");
+ TypeVariablePattern tv = parser.parseTypeVariable();
+ TypeVariablePattern expected = new TypeVariablePattern("T", new PatternParser("Number").parseTypePattern());
+ assertEquals("Expected type variable T extends Number", expected, tv);
+ }
+
+ public void testParseExtendingTypeVariableWithPattern() {
+ PatternParser parser = new PatternParser("T extends Number+");
+ TypeVariablePattern tv = parser.parseTypeVariable();
+ TypeVariablePattern expected = new TypeVariablePattern("T", new PatternParser("Number+").parseTypePattern());
+ assertEquals("Expected type variable T extends Number+", expected, tv);
+ }
+
+ public void testParseExtendingTypeVariableWithInterface() {
+ PatternParser parser = new PatternParser("T extends Number & Comparable");
+ TypeVariablePattern tv = parser.parseTypeVariable();
+ TypeVariablePattern expected = new TypeVariablePattern("T", new PatternParser("Number").parseTypePattern(),
+ new TypePattern[] { new PatternParser("Comparable").parseTypePattern() }, null);
+ assertEquals("Expected type variable T extends Number", expected, tv);
+ }
+
+ public void testParseExtendingTypeVariableWithInterfaceList() {
+ PatternParser parser = new PatternParser("T extends Number & Comparable & Cloneable");
+ TypeVariablePattern tv = parser.parseTypeVariable();
+ TypeVariablePattern expected = new TypeVariablePattern("T", new PatternParser("Number").parseTypePattern(),
+ new TypePattern[] { new PatternParser("Comparable").parseTypePattern(),
+ new PatternParser("Cloneable").parseTypePattern() }, null);
+ assertEquals("Expected type variable T extends Number", expected, tv);
+ }
+
+ public void testParseTypeParameterList() {
+ PatternParser parser = new PatternParser("<T>");
+ TypeVariablePatternList list = parser.maybeParseTypeVariableList();
+ TypeVariablePattern[] patterns = list.getTypeVariablePatterns();
+ TypeVariablePattern expected = new TypeVariablePattern("T");
+ assertEquals("Expected simple type variable T", expected, patterns[0]);
+ assertEquals("One pattern in list", 1, patterns.length);
+ }
+
+ public void testParseTypeParameterListWithSeveralTypeParameters() {
+ PatternParser parser = new PatternParser("<T,S extends Number, R>");
+ TypeVariablePatternList list = parser.maybeParseTypeVariableList();
+ TypeVariablePattern[] patterns = list.getTypeVariablePatterns();
+ TypeVariablePattern expected0 = new TypeVariablePattern("T");
+ assertEquals("Expected simple type variable T", expected0, patterns[0]);
+ TypeVariablePattern expected1 = new TypeVariablePattern("S", new PatternParser("Number").parseTypePattern());
+ assertEquals("Expected type variable S extends Number", expected1, patterns[1]);
+ TypeVariablePattern expected2 = new TypeVariablePattern("R");
+ assertEquals("Expected simple type variable R", expected2, patterns[2]);
+
+ assertEquals("3 patterns in list", 3, patterns.length);
+ }
+
+ public void testParseAllowedSuperInTypeVariable() {
+ PatternParser parser = new PatternParser("T super Number+");
+ TypeVariablePattern tv = parser.parseTypeVariable();
+ TypeVariablePattern expected = new TypeVariablePattern("T", new ExactTypePattern(UnresolvedType.OBJECT, false, false),
+ null, new PatternParser("Number+").parseTypePattern());
+ assertEquals("Expected type variable T super Number+", expected, tv);
+ }
+
+ public void testParseAnythingTypeVariable() {
+ PatternParser parser = new PatternParser("?");
+ WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true, false);
+ assertEquals("Expected type variable ?", "?", tp.maybeGetSimpleName());
+ }
+
+ public void testParseAnythingExtendsTypeVariable() {
+ PatternParser parser = new PatternParser("? extends Number");
+ WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true, false);
+ assertEquals("Expected type variable ?", "?", tp.maybeGetSimpleName());
+ assertEquals("upper Bound of Number", new PatternParser("Number").parseTypePattern(), tp.getUpperBound());
+ }
+
+ public void testParseAnythingSuperTypeVariable() {
+ PatternParser parser = new PatternParser("? super Number+");
+ WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true, false);
+ assertEquals("Expected type variable ?", "?", tp.maybeGetSimpleName());
+ assertEquals("lower Bound of Number+", new PatternParser("Number+").parseTypePattern(), tp.getLowerBound());
+ }
+
+ public void testParseDeclareParentsWithTypeParameterList() {
+ try {
+ PatternParser parser = new PatternParser("declare parents<T> : Foo<T> implements IveGoneMad");
+ // DeclareParents decp = (DeclareParents)
+ parser.parseDeclare();
+ // String[] tvp = decp.getTypeParameterNames();
+ // assertEquals("one type parameter",1,tvp.length);
+ // assertEquals("expecting T","T",tvp[0]);
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals(":", pEx.getMessage());
+ }
+ }
+
+ public void testParameterizedTypePatternsAny() {
+ try {
+ PatternParser parser = new PatternParser("*<T,S extends Number>");
+ // WildTypePattern wtp = (WildTypePattern)
+ parser.parseTypePattern(false, false);
+ // TypePatternList tvs = wtp.getTypeParameters();
+ // assertEquals("2 type parameters",2,tvs.getTypePatterns().length);
+ // assertEquals("T",new PatternParser("T").parseTypePattern(),tvs.getTypePatterns()[0]);
+ // assertEquals("S extends Number",new
+ // PatternParser("S extends Number").parseTypePattern(false),tvs.getTypePatterns()[1]);
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals(">", pEx.getMessage());
+ }
+ }
+
+ public void testParameterizedTypePatternsSimple() {
+ PatternParser parser = new PatternParser("List<String>");
+ WildTypePattern wtp = (WildTypePattern) parser.parseTypePattern();
+ TypePatternList tvs = wtp.getTypeParameters();
+ assertEquals("1 type parameter", 1, tvs.getTypePatterns().length);
+ assertEquals("String", new PatternParser("String").parseTypePattern(), tvs.getTypePatterns()[0]);
+ assertEquals("List", wtp.getNamePatterns()[0].toString());
+ }
+
+ public void testNestedParameterizedTypePatterns() {
+ PatternParser parser = new PatternParser("List<List<List<String>>>");
+ WildTypePattern wtp = (WildTypePattern) parser.parseTypePattern();
+ TypePatternList typeParameters = wtp.getTypeParameters();
+ WildTypePattern expected = (WildTypePattern) typeParameters.getTypePatterns()[0];
+ assertEquals("expecting a List", "List", expected.maybeGetSimpleName());
+ typeParameters = expected.getTypeParameters();
+ expected = (WildTypePattern) typeParameters.getTypePatterns()[0];
+ assertEquals("expecting a List", "List", expected.maybeGetSimpleName());
+ typeParameters = expected.getTypeParameters();
+ expected = (WildTypePattern) typeParameters.getTypePatterns()[0];
+ assertEquals("expecting a String", "String", expected.maybeGetSimpleName());
+ }
+
+ public void testSimpleTypeVariableList() {
+ PatternParser parser = new PatternParser("<T,S,V>");
+ String[] tl = parser.maybeParseSimpleTypeVariableList();
+ assertEquals("3 patterns", 3, tl.length);
+ assertEquals("T", tl[0]);
+ assertEquals("S", tl[1]);
+ assertEquals("V", tl[2]);
+ }
+
+ public void testSimpleTypeVariableListError() {
+ PatternParser parser = new PatternParser("<T extends Number>");
+ try {
+ // String[] tl =
+ parser.maybeParseSimpleTypeVariableList();
+ fail();
+ } catch (ParserException ex) {
+ assertEquals("Expecting ',' or '>'", "',' or '>'", ex.getMessage());
+ }
+ }
+
+ // test cases for pointcuts involving type variable specification.
+ public void testParseCallPCDWithTypeVariables() {
+ PatternParser parser = new PatternParser("call<T>(* Foo<T>.*(T))");
+ try {
+ parser.parsePointcut();
+ // String[] tvps = pc.getTypeVariablesInScope();
+ // assertEquals("1 type variable",1,tvps.length);
+ // assertEquals("T",tvps[0]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testParseCallPCDWithIllegalBounds() {
+ PatternParser parser = new PatternParser("call<T extends Number>(* Foo<T>.*(T))");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForHandler() {
+ PatternParser parser = new PatternParser("handler<T>(Exception<T>)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForThis() {
+ PatternParser parser = new PatternParser("this<T>(Exception<T>)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForTarget() {
+ PatternParser parser = new PatternParser("target<T>(Exception<T>)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForArgs() {
+ PatternParser parser = new PatternParser("args<T>(Exception<T>)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForIf() {
+ PatternParser parser = new PatternParser("if<T>(true)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForCflow() {
+ PatternParser parser = new PatternParser("cflow<T>(call(* *(..)))");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForCflowbelow() {
+ PatternParser parser = new PatternParser("cflowbelow<T>(call(* *(..)))");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForAtWithin() {
+ PatternParser parser = new PatternParser("@within<T>(Foo<T>)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForAtAnnotation() {
+ PatternParser parser = new PatternParser("@annotation<T>(Foo<T>)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForAtWithinCode() {
+ PatternParser parser = new PatternParser("@withincode<T>(* Foo<T>.*(..))");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForAtThis() {
+ PatternParser parser = new PatternParser("@this<T>(Exception<T>)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForAtTarget() {
+ PatternParser parser = new PatternParser("@target<T>(Exception<T>)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testNoTypeVarsForAtArgs() {
+ PatternParser parser = new PatternParser("@args<T>(Exception<T>)");
+ try {
+ parser.parsePointcut();
+ fail("Expecting parse exception");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testExecutionWithTypeVariables() {
+ PatternParser parser = new PatternParser("execution<T>(T Bar<T>.doSomething())");
+ try {
+ // Pointcut pc =
+ parser.parsePointcut();
+ // String[] tvs = pc.getTypeVariablesInScope();
+ // assertEquals("1 type pattern",1,tvs.length);
+ // assertEquals("T",tvs[0]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testInitializationWithTypeVariables() {
+ PatternParser parser = new PatternParser("initialization<T>(Bar<T>.new())");
+ try {
+ // Pointcut pc =
+ parser.parsePointcut();
+ // String[] tvs = pc.getTypeVariablesInScope();
+ // assertEquals("1 type pattern",1,tvs.length);
+ // assertEquals("T",tvs[0]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testPreInitializationWithTypeVariables() {
+ PatternParser parser = new PatternParser("preinitialization<T>(Bar<T>.new())");
+ try {
+ // Pointcut pc =
+ parser.parsePointcut();
+ // String[] tvs = pc.getTypeVariablesInScope();
+ // assertEquals("1 type pattern",1,tvs.length);
+ // assertEquals("T",tvs[0]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testStaticInitializationWithTypeVariables() {
+ PatternParser parser = new PatternParser("staticinitialization<T>(Bar<T>)");
+ try {
+ parser.parsePointcut();
+ // String[] tvs = pc.getTypeVariablesInScope();
+ // assertEquals("1 type pattern",1,tvs.length);
+ // assertEquals("T",tvs[0]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testWithinWithTypeVariables() {
+ PatternParser parser = new PatternParser("within<T>(Bar<T>)");
+ try {
+ parser.parsePointcut();
+ // String[] tvs = pc.getTypeVariablesInScope();
+ // assertEquals("1 type pattern",1,tvs.length);
+ // assertEquals("T",tvs[0]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testTypeParamList() {
+ PatternParser parser = new PatternParser("Bar<T,S extends T, R extends S>");
+ try {
+ parser.parseTypePattern(false, false);
+ // TypePattern[] tps = tp.getTypeParameters().getTypePatterns();
+ // assertEquals("3 type patterns",3,tps.length);
+ // assertEquals("T",tps[0].toString());
+ // assertEquals("S",tps[1].toString());
+ // assertEquals("R",tps[2].toString());
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals(">", pEx.getMessage());
+ }
+ }
+
+ public void testWithinCodeWithTypeVariables() {
+ PatternParser parser = new PatternParser("withincode<T,S,R>(Bar<T,S extends T, R extends S>.new())");
+ try {
+ parser.parsePointcut();
+ // String[] tvs = pc.getTypeVariablesInScope();
+ // assertEquals("3 type patterns",3,tvs.length);
+ // assertEquals("T",tvs[0]);
+ // assertEquals("S",tvs[1]);
+ // assertEquals("R",tvs[2]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testCallWithTypeVariables() {
+ PatternParser parser = new PatternParser("call<T>(* Bar<T>.*(..))");
+ try {
+ // Pointcut pc =
+ parser.parsePointcut();
+ // String[] tvs = pc.getTypeVariablesInScope();
+ // assertEquals("1 type pattern",1,tvs.length);
+ // assertEquals("T",tvs[0]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testGetWithTypeVariables() {
+ PatternParser parser = new PatternParser("get<T>(* Bar<T>.*)");
+ try {
+ // Pointcut pc =
+ parser.parsePointcut();
+ // String[] tvs = pc.getTypeVariablesInScope();
+ // assertEquals("1 type pattern",1,tvs.length);
+ // assertEquals("T",tvs[0]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testSetWithTypeVariables() {
+ PatternParser parser = new PatternParser("set<T>(* Bar<T>.*)");
+ try {
+ // Pointcut pc =
+ parser.parsePointcut();
+ // String[] tvs = pc.getTypeVariablesInScope();
+ // assertEquals("1 type pattern",1,tvs.length);
+ // assertEquals("T",tvs[0]);
+ fail("should have been a parse error");
+ } catch (ParserException pEx) {
+ assertEquals("(", pEx.getMessage());
+ }
+ }
+
+ public void testIntAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(ival=5) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found", "ival=5", getValueString(pc));
+ }
+
+ private String getValueString(Pointcut pc) {
+ if (!(pc instanceof KindedPointcut))
+ fail("Expected KindedPointcut but was " + pc.getClass());
+ KindedPointcut kpc = (KindedPointcut) pc;
+ AnnotationTypePattern atp = kpc.getSignature().getAnnotationPattern();
+ if (!(atp instanceof WildAnnotationTypePattern))
+ fail("Expected WildAnnotationTypePattern but was " + atp.getClass());
+ WildAnnotationTypePattern watp = (WildAnnotationTypePattern) atp;
+ Map m = watp.annotationValues;
+ Set keys = m.keySet();
+ List orderedKeys = new ArrayList();
+ orderedKeys.addAll(keys);
+ Collections.sort(orderedKeys);
+ StringBuffer sb = new StringBuffer();
+ for (Iterator iterator = orderedKeys.iterator(); iterator.hasNext();) {
+ String object = (String) iterator.next();
+ sb.append(object).append("=").append(m.get(object));
+ if (iterator.hasNext())
+ sb.append(",");
+ }
+ return sb.toString();
+ }
+
+ public void testByteAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(bval=5) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found", "bval=5", getValueString(pc));
+ }
+
+ public void testCharAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(cval='5') * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found", "cval='5'", getValueString(pc));
+ }
+
+ public void testLongAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(jval=123123) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found", "jval=123123", getValueString(pc));
+ }
+
+ public void testDoubleAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(dval=123.3) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found", "dval=123.3", getValueString(pc));
+ }
+
+ public void testBooleanAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(zval=true) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found", "zval=true", getValueString(pc));
+ }
+
+ public void testShortAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(sval=43) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found", "sval=43", getValueString(pc));
+ }
+
+ public void testEnumAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(enumval=Color.GREEN) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found", "enumval=Color.GREEN", getValueString(pc));
+ }
+
+ public void testStringAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(strval=\"abc\") * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ // notice quotes stripped...
+ assertEquals("Expected annotation value not found", "strval=abc", getValueString(pc));
+ }
+
+ public void testClassAnnotationVal() {
+ PatternParser parser = new PatternParser("execution(@ComplexAnnotation(classval=String.class) * *(..))");
+ Pointcut pc = parser.parsePointcut();
+ assertEquals("Expected annotation value not found", "classval=String.class", getValueString(pc));
+ }
+
+ // failing as {1 is treated as a single token and so we don't realise the , is within the curlies
+ // public void testArrayAnnotationVal() {
+ // PatternParser parser = new PatternParser("execution(@ComplexAnnotation(arrayval={1,2,3}) * *(..))");
+ // Pointcut pc = parser.parsePointcut();
+ // assertEquals("Expected annotation value not found","arrayval={1,2,3}",getValueString(pc));
+ // }
+
+ // ---
+
+ public TestScope makeSimpleScope() {
+ world.setBehaveInJava5Way(true);
+ TestScope s = new TestScope(new String[] { "int", "java.lang.String" }, new String[] { "a", "b" }, world);
+ s.setImportedPrefixes(new String[] { "p." });
+ return s;
+ }
+
+}
--- /dev/null
+package org.aspectj.weaver.patterns;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import junit.framework.TestCase;
+
+import org.aspectj.weaver.World;
+
+public abstract class PatternsTestCase extends TestCase {
+
+ protected World world;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ world = getWorld();
+ }
+
+ protected File getTestDataJar() {
+ return new File("../weaver/testdata/testcode.jar");
+ }
+
+ public URLClassLoader getClassLoaderForFile(File f) {
+ try {
+ URLClassLoader ucl = new URLClassLoader(new URL[] { f.toURL() }, this.getClass().getClassLoader());
+ return ucl;
+ } catch (MalformedURLException mue) {
+ throw new RuntimeException(mue);
+ }
+ }
+
+ public abstract World getWorld();
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.patterns.AndOrNotTestCase;
+import org.aspectj.weaver.patterns.ArgsTestCase;
+import org.aspectj.weaver.patterns.BindingTestCase;
+import org.aspectj.weaver.patterns.DeclareErrorOrWarningTestCase;
+import org.aspectj.weaver.patterns.ModifiersPatternTestCase;
+import org.aspectj.weaver.patterns.NamePatternParserTestCase;
+import org.aspectj.weaver.patterns.NamePatternTestCase;
+import org.aspectj.weaver.patterns.ParserTestCase;
+import org.aspectj.weaver.patterns.PatternsTests;
+import org.aspectj.weaver.patterns.PointcutRewriterTest;
+import org.aspectj.weaver.patterns.SignaturePatternTestCase;
+import org.aspectj.weaver.patterns.ThisOrTargetTestCase;
+import org.aspectj.weaver.patterns.TypePatternListTestCase;
+import org.aspectj.weaver.patterns.TypePatternTestCase;
+import org.aspectj.weaver.patterns.VisitorTestCase;
+import org.aspectj.weaver.patterns.WithinTestCase;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class PatternsTests extends TestCase {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(PatternsTests.class.getName());
+ // $JUnit-BEGIN$
+ suite.addTestSuite(AndOrNotTestCase.class);
+ suite.addTestSuite(BindingTestCase.class);
+ suite.addTestSuite(DeclareErrorOrWarningTestCase.class);
+ suite.addTestSuite(ModifiersPatternTestCase.class);
+ suite.addTestSuite(NamePatternParserTestCase.class);
+ suite.addTestSuite(NamePatternTestCase.class);
+ suite.addTestSuite(ParserTestCase.class);
+ suite.addTestSuite(SignaturePatternTestCase.class);
+ suite.addTestSuite(ThisOrTargetTestCase.class);
+ suite.addTestSuite(TypePatternListTestCase.class);
+ suite.addTestSuite(TypePatternTestCase.class);
+ suite.addTestSuite(WithinTestCase.class);
+ suite.addTestSuite(ArgsTestCase.class);
+ // suite.addTestSuite(AnnotationPatternTestCase.class);
+ // suite.addTestSuite(AnnotationPatternMatchingTestCase.class);
+ suite.addTestSuite(PointcutRewriterTest.class);
+ suite.addTestSuite(VisitorTestCase.class);
+ // $JUnit-END$
+ return suite;
+ }
+
+ public PatternsTests(String name) {
+ super(name);
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.util.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.patterns.AndPointcut;
+import org.aspectj.weaver.patterns.IfPointcut;
+import org.aspectj.weaver.patterns.NotPointcut;
+import org.aspectj.weaver.patterns.OrPointcut;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.PointcutRewriter;
+
+import junit.framework.TestCase;
+
+/**
+ * @author colyer
+ *
+ * TODO To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Style - Code Templates
+ */
+public class PointcutRewriterTest extends TestCase {
+
+ private PointcutRewriter prw;
+
+ public void testDistributeNot() {
+ Pointcut plain = getPointcut("this(Foo)");
+ assertEquals("Unchanged",plain,prw.rewrite(plain));
+ Pointcut not = getPointcut("!this(Foo)");
+ assertEquals("Unchanged",not,prw.rewrite(not));
+ Pointcut notNot = getPointcut("!!this(Foo)");
+ assertEquals("this(Foo)",prw.rewrite(notNot).toString());
+ Pointcut notNotNOT = getPointcut("!!!this(Foo)");
+ assertEquals("!this(Foo)",prw.rewrite(notNotNOT).toString());
+ Pointcut and = getPointcut("!(this(Foo) && this(Goo))");
+ assertEquals("(!this(Foo) || !this(Goo))",prw.rewrite(and,true).toString());
+ Pointcut or = getPointcut("!(this(Foo) || this(Goo))");
+ assertEquals("(!this(Foo) && !this(Goo))",prw.rewrite(or,true).toString());
+ Pointcut nestedNot = getPointcut("!(this(Foo) && !this(Goo))");
+ assertEquals("(!this(Foo) || this(Goo))",prw.rewrite(nestedNot,true).toString());
+ }
+
+ public void testPullUpDisjunctions() {
+ Pointcut aAndb = getPointcut("this(Foo) && this(Goo)");
+ assertEquals("Unchanged",aAndb,prw.rewrite(aAndb));
+ Pointcut aOrb = getPointcut("this(Foo) || this(Moo)");
+ assertEquals("Unchanged",aOrb,prw.rewrite(aOrb));
+
+ Pointcut leftOr = getPointcut("this(Foo) || (this(Goo) && this(Boo))");
+ assertEquals("or%anyorder%this(Foo)%and%anyorder%this(Boo)%this(Goo)",prw.rewrite(leftOr));
+ //assertEquals("(this(Foo) || (this(Boo) && this(Goo)))",prw.rewrite(leftOr).toString());
+
+ Pointcut rightOr = getPointcut("(this(Goo) && this(Boo)) || this(Foo)");
+// assertEquals("(this(Foo) || (this(Boo) && this(Goo)))",prw.rewrite(rightOr).toString());
+ assertEquals("or%anyorder%this(Foo)%and%anyorder%this(Goo)%this(Boo)",prw.rewrite(rightOr));
+
+ Pointcut leftAnd = getPointcut("this(Foo) && (this(Goo) || this(Boo))");
+// assertEquals("((this(Boo) && this(Foo)) || (this(Foo) && this(Goo)))",prw.rewrite(leftAnd).toString());
+ assertEquals("or%anyorder%and%anyorder%this(Boo)%this(Foo)%and%anyorder%this(Foo)%this(Goo)",prw.rewrite(leftAnd));
+
+ Pointcut rightAnd = getPointcut("(this(Goo) || this(Boo)) && this(Foo)");
+// assertEquals("((this(Boo) && this(Foo)) || (this(Foo) && this(Goo)))",prw.rewrite(rightAnd).toString());
+ assertEquals("or%anyorder%and%anyorder%this(Boo)%this(Foo)%and%anyorder%this(Foo)%this(Goo)",prw.rewrite(rightAnd));
+
+ Pointcut nestedOrs = getPointcut("this(Foo) || this(Goo) || this(Boo)");
+// assertEquals("((this(Boo) || this(Foo)) || this(Goo))",prw.rewrite(nestedOrs).toString());
+ assertEquals("or%anyorder%this(Goo)%or%anyorder%this(Boo)%this(Foo)",prw.rewrite(nestedOrs));
+
+ Pointcut nestedAnds = getPointcut("(this(Foo) && (this(Boo) && (this(Goo) || this(Moo))))");
+ // t(F) && (t(B) && (t(G) || t(M)))
+ // ==> t(F) && ((t(B) && t(G)) || (t(B) && t(M)))
+ // ==> (t(F) && (t(B) && t(G))) || (t(F) && (t(B) && t(M)))
+// assertEquals("(((this(Boo) && this(Foo)) && this(Goo)) || ((this(Boo) && this(Foo)) && this(Moo)))",
+// prw.rewrite(nestedAnds).toString());
+ assertEquals("or%anyorder%and%anyorder%and%anyorder%this(Boo)%this(Foo)%this(Goo)%and%anyorder%and%anyorder%this(Boo)%this(Foo)%this(Moo)",prw.rewrite(nestedAnds));
+ }
+
+ /**
+ * spec is reverse polish notation with operators and, or , not, anyorder,
+ * delimiter is "%" (not whitespace).
+ * @param spec
+ * @param pc
+ */
+ private void assertEquals(String spec, Pointcut pc) {
+ StringTokenizer strTok = new StringTokenizer(spec,"%");
+ String[] tokens = new String[strTok.countTokens()];
+ for (int i = 0; i < tokens.length; i++) {
+ tokens[i] = strTok.nextToken();
+ }
+ tokenIndex = 0;
+ assertTrue(spec,equals(pc,tokens));
+ }
+
+ private int tokenIndex = 0;
+ private boolean equals(Pointcut pc, String[] tokens) {
+ if (tokens[tokenIndex].equals("and")) {
+ tokenIndex++;
+ if (!(pc instanceof AndPointcut)) return false;
+ AndPointcut apc = (AndPointcut) pc;
+ Pointcut left = apc.getLeft();
+ Pointcut right = apc.getRight();
+ if (tokens[tokenIndex].equals("anyorder")) {
+ tokenIndex++;
+ int restorePoint = tokenIndex;
+ boolean leftMatchFirst = equals(left,tokens) &&
+ equals(right,tokens);
+ if (leftMatchFirst) return true;
+ tokenIndex = restorePoint;
+ boolean rightMatchFirst = equals(right,tokens) &&
+ equals(left,tokens);
+ return rightMatchFirst;
+ } else {
+ return equals(left,tokens) &&
+ equals(right,tokens);
+ }
+ } else if (tokens[tokenIndex].equals("or")) {
+ tokenIndex++;
+ if (!(pc instanceof OrPointcut)) return false;
+ OrPointcut opc = (OrPointcut) pc;
+ Pointcut left = opc.getLeft();
+ Pointcut right = opc.getRight();
+ if (tokens[tokenIndex].equals("anyorder")) {
+ tokenIndex++;
+ int restorePoint = tokenIndex;
+ boolean leftMatchFirst = equals(left,tokens) &&
+ equals(right,tokens);
+ if (leftMatchFirst) return true;
+ tokenIndex = restorePoint;
+ boolean rightMatchFirst = equals(right,tokens) &&
+ equals(left,tokens);
+ return rightMatchFirst;
+ } else {
+ return equals(left,tokens) &&
+ equals(right,tokens);
+ }
+
+ } else if (tokens[tokenIndex].equals("not")) {
+ if (!(pc instanceof NotPointcut)) return false;
+ tokenIndex++;
+ NotPointcut np = (NotPointcut) pc;
+ return equals(np.getNegatedPointcut(),tokens);
+ } else {
+ return tokens[tokenIndex++].equals(pc.toString());
+ }
+ }
+
+// public void testSplitOutWithins() {
+// Pointcut simpleExecution = getPointcut("execution(* *.*(..))");
+// assertEquals("Unchanged",simpleExecution,prw.rewrite(simpleExecution));
+// Pointcut simpleWithinCode = getPointcut("withincode(* *.*(..))");
+// assertEquals("Unchanged",simpleWithinCode,prw.rewrite(simpleWithinCode));
+// Pointcut execution = getPointcut("execution(@Foo Foo (@Goo org.xyz..*).m*(Foo,Boo))");
+// assertEquals("(within((@(Goo) org.xyz..*)) && execution(@(Foo) Foo m*(Foo, Boo)))",
+// prw.rewrite(execution).toString());
+// Pointcut withincode = getPointcut("withincode(@Foo Foo (@Goo org.xyz..*).m*(Foo,Boo))");
+// assertEquals("(within((@(Goo) org.xyz..*)) && withincode(@(Foo) Foo m*(Foo, Boo)))",
+// prw.rewrite(withincode).toString());
+// Pointcut notExecution = getPointcut("!execution(Foo BankAccount+.*(..))");
+// assertEquals("(!within(BankAccount+) || !execution(Foo *(..)))",
+// prw.rewrite(notExecution).toString());
+// Pointcut andWithincode = getPointcut("withincode(Foo.new(..)) && this(Foo)");
+// assertEquals("((within(Foo) && withincode(new(..))) && this(Foo))",
+// prw.rewrite(andWithincode).toString());
+// Pointcut orExecution = getPointcut("this(Foo) || execution(Goo Foo.moo(Baa))");
+// assertEquals("((within(Foo) && execution(Goo moo(Baa))) || this(Foo))",
+// prw.rewrite(orExecution).toString());
+// }
+
+
+ public void testRemoveDuplicatesInAnd() {
+ Pointcut dupAnd = getPointcut("this(Foo) && this(Foo)");
+ assertEquals("this(Foo)",prw.rewrite(dupAnd).toString());
+ Pointcut splitdupAnd = getPointcut("(this(Foo) && target(Boo)) && this(Foo)");
+ assertEquals("(target(Boo) && this(Foo))",prw.rewrite(splitdupAnd).toString());
+ }
+
+ public void testNotRemoveNearlyDuplicatesInAnd() {
+ Pointcut toAndto = getPointcut("this(Object+) && this(Object)");
+// Pointcut rewritten =
+ prw.rewrite(toAndto);
+ }
+
+ public void testAAndNotAinAnd() {
+ Pointcut aAndNota = getPointcut("this(Foo)&& !this(Foo)");
+ assertEquals("Matches nothing","",prw.rewrite(aAndNota).toString());
+ Pointcut aAndBAndNota = getPointcut("this(Foo) && execution(* *.*(..)) && !this(Foo)");
+ assertEquals("Matches nothing","",prw.rewrite(aAndBAndNota).toString());
+ }
+
+ public void testIfFalseInAnd() {
+ Pointcut ifFalse = IfPointcut.makeIfFalsePointcut(Pointcut.CONCRETE);
+ Pointcut p = getPointcut("this(A)");
+ assertEquals("Matches nothing","",prw.rewrite(new AndPointcut(ifFalse,p)).toString());
+ }
+
+ public void testMatchesNothinginAnd() {
+ Pointcut nothing = Pointcut.makeMatchesNothing(Pointcut.CONCRETE);
+ Pointcut p = getPointcut("this(A)");
+ assertEquals("Matches nothing","",prw.rewrite(new AndPointcut(nothing,p)).toString());
+ }
+
+ public void testMixedKindsInAnd() {
+ Pointcut mixedKinds = getPointcut("call(* *(..)) && execution(* *(..))");
+ assertEquals("Matches nothing","",prw.rewrite(mixedKinds).toString());
+ Pointcut ok = getPointcut("call(* *(..)) && this(Foo)");
+ assertEquals(ok,prw.rewrite(ok));
+ }
+
+ public void testDetermineKindSetOfAnd() {
+ Pointcut oneKind = getPointcut("execution(* foo(..)) && this(Boo)");
+ AndPointcut rewritten = (AndPointcut) prw.rewrite(oneKind);
+ assertEquals("Only one kind",1,Shadow.howMany(rewritten.couldMatchKinds()));
+ assertTrue("It's Shadow.MethodExecution",Shadow.MethodExecution.isSet(rewritten.couldMatchKinds()));
+ }
+
+ public void testKindSetOfExecution() {
+ Pointcut p = getPointcut("execution(* foo(..))");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.MethodExecution",Shadow.MethodExecution.isSet(p.couldMatchKinds()));
+ p = getPointcut("execution(new(..))");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.ConstructorExecution",Shadow.ConstructorExecution.isSet(p.couldMatchKinds()));
+ }
+
+ public void testKindSetOfCall() {
+ Pointcut p = getPointcut("call(* foo(..))");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.MethodCall",Shadow.MethodCall.isSet(p.couldMatchKinds()));
+ p = getPointcut("call(new(..))");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.ConstructorCall",Shadow.ConstructorCall.isSet(p.couldMatchKinds()));
+ }
+
+ public void testKindSetOfAdviceExecution() {
+ Pointcut p = getPointcut("adviceexecution()");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.AdviceExecution",Shadow.AdviceExecution.isSet(p.couldMatchKinds()));
+ }
+
+ public void testKindSetOfGet() {
+ Pointcut p = getPointcut("get(* *)");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.FieldGet",Shadow.FieldGet.isSet(p.couldMatchKinds()));
+ }
+
+ public void testKindSetOfSet() {
+ Pointcut p = getPointcut("set(* *)");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.FieldSet",Shadow.FieldSet.isSet(p.couldMatchKinds()));
+ }
+
+ public void testKindSetOfHandler() {
+ Pointcut p = getPointcut("handler(*)");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.ExceptionHandler",Shadow.ExceptionHandler.isSet(p.couldMatchKinds()));
+ }
+
+ public void testKindSetOfInitialization() {
+ Pointcut p = getPointcut("initialization(new (..))");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.Initialization",Shadow.Initialization.isSet(p.couldMatchKinds()));
+ }
+
+ public void testKindSetOfPreInitialization() {
+ Pointcut p = getPointcut("preinitialization(new (..))");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.PreInitialization",Shadow.PreInitialization.isSet(p.couldMatchKinds()));
+ }
+
+ public void testKindSetOfStaticInitialization() {
+ Pointcut p = getPointcut("staticinitialization(*)");
+ assertEquals("Only one kind",1,Shadow.howMany(p.couldMatchKinds()));
+ assertTrue("It's Shadow.StaticInitialization",Shadow.StaticInitialization.isSet(p.couldMatchKinds()));
+ }
+
+ public void testKindSetOfThis() {
+ Pointcut p = getPointcut("this(Foo)");
+ Set matches = Shadow.toSet(p.couldMatchKinds());
+ for (Iterator iter = matches.iterator(); iter.hasNext();) {
+ Shadow.Kind kind = (Shadow.Kind) iter.next();
+ assertFalse("No kinds that don't have a this",kind.neverHasThis());
+ }
+ for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+ if (!Shadow.SHADOW_KINDS[i].neverHasThis()) {
+ assertTrue("All kinds that do have this",matches.contains(Shadow.SHADOW_KINDS[i]));
+ }
+ }
+ // + @
+ p = getPointcut("@this(Foo)");
+ matches = Shadow.toSet(p.couldMatchKinds());
+ for (Iterator iter = matches.iterator(); iter.hasNext();) {
+ Shadow.Kind kind = (Shadow.Kind) iter.next();
+ assertFalse("No kinds that don't have a this",kind.neverHasThis());
+ }
+ for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+ if (!Shadow.SHADOW_KINDS[i].neverHasThis()) {
+ assertTrue("All kinds that do have this",matches.contains(Shadow.SHADOW_KINDS[i]));
+ }
+ }
+ }
+
+ public void testKindSetOfTarget() {
+ Pointcut p = getPointcut("target(Foo)");
+ Set matches = Shadow.toSet(p.couldMatchKinds());
+ for (Iterator iter = matches.iterator(); iter.hasNext();) {
+ Shadow.Kind kind = (Shadow.Kind) iter.next();
+ assertFalse("No kinds that don't have a target",kind.neverHasTarget());
+ }
+ for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+ if (!Shadow.SHADOW_KINDS[i].neverHasTarget()) {
+ assertTrue("All kinds that do have target",matches.contains(Shadow.SHADOW_KINDS[i]));
+ }
+ }
+ // + @
+ p = getPointcut("@target(Foo)");
+ matches = Shadow.toSet(p.couldMatchKinds());
+ for (Iterator iter = matches.iterator(); iter.hasNext();) {
+ Shadow.Kind kind = (Shadow.Kind) iter.next();
+ assertFalse("No kinds that don't have a target",kind.neverHasTarget());
+ }
+ for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+ if (!Shadow.SHADOW_KINDS[i].neverHasTarget()) {
+ assertTrue("All kinds that do have target",matches.contains(Shadow.SHADOW_KINDS[i]));
+ }
+ }
+ }
+
+ public void testKindSetOfArgs() {
+ Pointcut p = getPointcut("args(..)");
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ // + @
+ p = getPointcut("@args(..)");
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ }
+
+ public void testKindSetOfAnnotation() {
+ Pointcut p = getPointcut("@annotation(Foo)");
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ }
+
+ public void testKindSetOfWithin() {
+ Pointcut p = getPointcut("within(*)");
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ // + @
+ p = getPointcut("@within(Foo)");
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ }
+
+ public void testKindSetOfWithinCode() {
+ Pointcut p = getPointcut("withincode(* foo(..))");
+ Set matches = Shadow.toSet(p.couldMatchKinds());
+ for (Iterator iter = matches.iterator(); iter.hasNext();) {
+ Shadow.Kind kind = (Shadow.Kind) iter.next();
+ assertFalse("No kinds that are themselves enclosing",
+ (kind.isEnclosingKind() && kind != Shadow.ConstructorExecution && kind != Shadow.Initialization));
+ }
+ for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+ if (!Shadow.SHADOW_KINDS[i].isEnclosingKind()) {
+ assertTrue("All kinds that are not enclosing",matches.contains(Shadow.SHADOW_KINDS[i]));
+ }
+ }
+ assertTrue("Need cons-exe for inlined field inits",matches.contains(Shadow.ConstructorExecution));
+ assertTrue("Need init for inlined field inits",matches.contains(Shadow.Initialization));
+ // + @
+ p = getPointcut("@withincode(Foo)");
+ matches = Shadow.toSet(p.couldMatchKinds());
+ for (Iterator iter = matches.iterator(); iter.hasNext();) {
+ Shadow.Kind kind = (Shadow.Kind) iter.next();
+ assertFalse("No kinds that are themselves enclosing",kind.isEnclosingKind());
+ }
+ for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
+ if (!Shadow.SHADOW_KINDS[i].isEnclosingKind()) {
+ assertTrue("All kinds that are not enclosing",matches.contains(Shadow.SHADOW_KINDS[i]));
+ }
+ }
+ }
+
+ public void testKindSetOfIf() {
+ Pointcut p = new IfPointcut(null,0);
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ p = IfPointcut.makeIfTruePointcut(Pointcut.CONCRETE);
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ p = IfPointcut.makeIfFalsePointcut(Pointcut.CONCRETE);
+ assertTrue("Nothing",p.couldMatchKinds()==Shadow.NO_SHADOW_KINDS_BITS);
+ }
+
+ public void testKindSetOfCflow() {
+ Pointcut p = getPointcut("cflow(this(Foo))");
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ // [below]
+ p = getPointcut("cflowbelow(this(Foo))");
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ }
+
+ public void testKindSetInNegation() {
+ Pointcut p = getPointcut("!execution(new(..))");
+ assertTrue("All kinds",p.couldMatchKinds()==Shadow.ALL_SHADOW_KINDS_BITS);
+ }
+
+ public void testKindSetOfOr() {
+ Pointcut p = getPointcut("execution(new(..)) || get(* *)");
+ Set matches = Shadow.toSet(p.couldMatchKinds());
+ assertEquals("2 kinds",2,matches.size());
+ assertTrue("ConstructorExecution",matches.contains(Shadow.ConstructorExecution));
+ assertTrue("FieldGet",matches.contains(Shadow.FieldGet));
+ }
+
+ public void testOrderingInAnd() {
+ Pointcut bigLongPC = getPointcut("cflow(this(Foo)) && @args(X) && args(X) && @this(Foo) && @target(Boo) && this(Moo) && target(Boo) && @annotation(Moo) && @withincode(Boo) && withincode(new(..)) && set(* *)&& @within(Foo) && within(Foo)");
+ Pointcut rewritten = prw.rewrite(bigLongPC);
+ assertEquals("((((((((((((within(Foo) && @within(Foo)) && set(* *)) && withincode(new(..))) && @withincode(Boo)) && @annotation(Moo)) && target(Boo)) && this(Moo)) && @target(Boo)) && @this(Foo)) && args(X)) && @args(X)) && cflow(this(Foo)))",rewritten.toString());
+ }
+
+ public void testOrderingInSimpleOr() {
+ OrPointcut opc = (OrPointcut) getPointcut("execution(new(..)) || get(* *)");
+ assertEquals("reordered","(get(* *) || execution(new(..)))",prw.rewrite(opc).toString());
+ }
+
+ public void testOrderingInNestedOrs() {
+ OrPointcut opc = (OrPointcut) getPointcut("(execution(new(..)) || get(* *)) || within(abc)");
+ assertEquals("reordered","((within(abc) || get(* *)) || execution(new(..)))",
+ prw.rewrite(opc).toString());
+ }
+
+ public void testOrderingInOrsWithNestedAnds() {
+ OrPointcut opc = (OrPointcut) getPointcut("get(* *) || (execution(new(..)) && within(abc))");
+ assertEquals("reordered","((within(abc) && execution(new(..))) || get(* *))",
+ prw.rewrite(opc).toString());
+ }
+
+ private Pointcut getPointcut(String s) {
+ return new PatternParser(s).parsePointcut();
+ }
+
+ /*
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ prw = new PointcutRewriter();
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 2005 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.TestUtils;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.Bindings;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.SignaturePattern;
+import org.aspectj.weaver.patterns.TestScope;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+
+public class SignaturePatternTestCase extends PatternsTestCase {
+
+ public World getWorld() {
+ return new ReflectionWorld(true, this.getClass().getClassLoader());
+ }
+
+ public void testThrowsMatch() throws IOException {
+ Member onlyDerivedOnDerived = TestUtils.methodFromString("static void org.aspectj.weaver.testcode.Derived.onlyDerived()");
+ Member mOnBase = TestUtils.methodFromString("void org.aspectj.weaver.testcode.Base.m()");
+ Member mOnDerived = TestUtils.methodFromString("void org.aspectj.weaver.testcode.Derived.m()");
+
+ checkMatch(makeMethodPat("* org.aspectj.weaver.testcode.Base.*(..) throws java.lang.CloneNotSupportedException"),
+ new Member[] { mOnBase }, new Member[] { mOnDerived });
+
+ checkMatch(makeMethodPat("* org.aspectj.weaver.testcode.Derived.*(..) throws java.lang.CloneNotSupportedException"),
+ new Member[] {}, new Member[] { mOnBase, mOnDerived });
+
+ // XXX need pattern checks
+ Member[] NONE = new Member[] {};
+ Member[] M = new Member[] { onlyDerivedOnDerived };
+ Member[] NO_EXCEPTIONS = new Member[] { mOnDerived };
+ Member[] BOTH = new Member[] { mOnDerived, onlyDerivedOnDerived };
+
+ checkMatch(makeMethodPat("* *(..)"), M, NONE);
+ checkMatch(makeMethodPat("* *(..) throws !*"), NO_EXCEPTIONS, M);
+ checkMatch(makeMethodPat("* *(..) throws *"), M, NO_EXCEPTIONS);
+ checkMatch(makeMethodPat("* *(..) throws *, !*"), NONE, BOTH);
+
+ checkMatch(makeMethodPat("* *(..) throws (!*)"), NONE, BOTH);
+ checkMatch(makeMethodPat("* *(..) throws !(!*)"), BOTH, NONE);
+
+ checkMatch(makeMethodPat("* *(..) throws *..IOException"), M, NO_EXCEPTIONS);
+ checkMatch(makeMethodPat("* *(..) throws *..IOException, *..Clone*"), M, NO_EXCEPTIONS);
+ checkMatch(makeMethodPat("* *(..) throws *..IOException, !*..Clone*"), NONE, BOTH);
+ checkMatch(makeMethodPat("* *(..) throws !*..IOException"), NO_EXCEPTIONS, M);
+ }
+
+ public void testInstanceMethodMatch() throws IOException {
+ Member objectToString = TestUtils.methodFromString("java.lang.String java.lang.Object.toString()");
+ Member integerToString = TestUtils.methodFromString("java.lang.String java.lang.Integer.toString()");
+ Member integerIntValue = TestUtils.methodFromString("int java.lang.Integer.intValue()");
+ // Member objectToString = Member.methodFromString("java.lang.String java.lang.Object.toString()");
+
+ checkMatch(makeMethodPat("* java.lang.Object.*(..)"), new Member[] { objectToString, integerToString },
+ new Member[] { integerIntValue });
+
+ checkMatch(makeMethodPat("* java.lang.Integer.*(..)"), new Member[] { integerIntValue, integerToString },
+ new Member[] { objectToString });
+ }
+
+ public void testStaticMethodMatch() throws IOException {
+ Member onlyBaseOnBase = TestUtils.methodFromString("static void org.aspectj.weaver.testcode.Base.onlyBase()");
+ Member onlyBaseOnDerived = TestUtils.methodFromString("static void org.aspectj.weaver.testcode.Derived.onlyBase()");
+ Member onlyDerivedOnDerived = TestUtils.methodFromString("static void org.aspectj.weaver.testcode.Derived.onlyDerived()");
+ Member bothOnBase = TestUtils.methodFromString("static void org.aspectj.weaver.testcode.Base.both()");
+ Member bothOnDerived = TestUtils.methodFromString("static void org.aspectj.weaver.testcode.Derived.both()");
+
+ checkMatch(makeMethodPat("* org.aspectj.weaver.testcode.Base.*(..)"), new Member[] { onlyBaseOnBase, onlyBaseOnDerived,
+ bothOnBase }, new Member[] { onlyDerivedOnDerived, bothOnDerived });
+
+ checkMatch(makeMethodPat("* org.aspectj.weaver.testcode.Derived.*(..)"), new Member[] { onlyBaseOnDerived, bothOnDerived,
+ onlyDerivedOnDerived }, new Member[] { onlyBaseOnBase, bothOnBase });
+ }
+
+ public void testFieldMatch() throws IOException {
+ Member onlyBaseOnBase = TestUtils.fieldFromString("int org.aspectj.weaver.testcode.Base.onlyBase");
+ Member onlyBaseOnDerived = TestUtils.fieldFromString("int org.aspectj.weaver.testcode.Derived.onlyBase");
+ Member onlyDerivedOnDerived = TestUtils.fieldFromString("int org.aspectj.weaver.testcode.Derived.onlyDerived");
+ Member bothOnBase = TestUtils.fieldFromString("int org.aspectj.weaver.testcode.Base.both");
+ Member bothOnDerived = TestUtils.fieldFromString("int org.aspectj.weaver.testcode.Derived.both");
+
+ checkMatch(makeFieldPat("* org.aspectj.weaver.testcode.Base.*"), new Member[] { onlyBaseOnBase, onlyBaseOnDerived,
+ bothOnBase }, new Member[] { onlyDerivedOnDerived, bothOnDerived });
+
+ checkMatch(makeFieldPat("* org.aspectj.weaver.testcode.Derived.*"), new Member[] { onlyBaseOnDerived, bothOnDerived,
+ onlyDerivedOnDerived }, new Member[] { onlyBaseOnBase, bothOnBase });
+ }
+
+ public void testConstructorMatch() throws IOException {
+ Member onBase = TestUtils.methodFromString("void org.aspectj.weaver.testcode.Base.<init>()");
+ Member onDerived = TestUtils.methodFromString("void org.aspectj.weaver.testcode.Derived.<init>()");
+ Member onBaseWithInt = TestUtils.methodFromString("void org.aspectj.weaver.testcode.Base.<init>(int)");
+
+ checkMatch(makeMethodPat("org.aspectj.weaver.testcode.Base.new(..)"), new Member[] { onBase, onBaseWithInt },
+ new Member[] { onDerived });
+
+ checkMatch(makeMethodPat("org.aspectj.weaver.testcode.Derived.new(..)"), new Member[] { onDerived }, new Member[] { onBase,
+ onBaseWithInt });
+ }
+
+ public void checkMatch(SignaturePattern p, Member[] yes, Member[] no) throws IOException {
+ p = p.resolveBindings(new TestScope(world, new FormalBinding[0]), new Bindings(0));
+
+ for (int i = 0; i < yes.length; i++) {
+ checkMatch(p, yes[i], true);
+ }
+
+ for (int i = 0; i < no.length; i++) {
+ checkMatch(p, no[i], false);
+ }
+
+ checkSerialization(p);
+ }
+
+ private void checkMatch(SignaturePattern p, Member member, boolean b) {
+ boolean matches = p.matches(member, world, false);
+ assertEquals(p.toString() + " matches " + member.toString(), b, matches);
+ }
+
+ private SignaturePattern makeMethodPat(String pattern) {
+ return new PatternParser(pattern).parseMethodOrConstructorSignaturePattern();
+ }
+
+ private SignaturePattern makeFieldPat(String pattern) {
+ return new PatternParser(pattern).parseFieldSignaturePattern();
+ }
+
+ private void checkSerialization(SignaturePattern p) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ VersionedDataInputStream in = new VersionedDataInputStream(bi);
+ SignaturePattern newP = SignaturePattern.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.*;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.SimpleScope;
+
+public class TestScope extends SimpleScope {
+
+ public TestScope(
+ World world,
+ FormalBinding[] bindings)
+ {
+ super(world, bindings);
+ }
+
+ public TestScope(String[] formalTypes, String[] formalNames, World world) {
+ super(world, SimpleScope.makeFormalBindings(UnresolvedType.forNames(formalTypes), formalNames));
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 2005 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * Adrian Colyer, runtime reflection extensions
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.aspectj.util.LangUtil;
+import org.aspectj.weaver.tools.JoinPointMatch;
+import org.aspectj.weaver.tools.PointcutExpression;
+import org.aspectj.weaver.tools.PointcutParameter;
+import org.aspectj.weaver.tools.PointcutParser;
+import org.aspectj.weaver.tools.ShadowMatch;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment": Window>Preferences>Java>Templates. To enable
+ * and disable the creation of type comments go to Window>Preferences>Java>Code Generation.
+ */
+public class ThisOrTargetTestCase extends TestCase {
+
+ private boolean needToSkip = false;
+
+ /** this condition can occur on the build machine only, and is way too complex to fix right now... */
+ private boolean needToSkipPointcutParserTests() {
+ if (!LangUtil.is15VMOrGreater())
+ return false;
+ try {
+ Class.forName("org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate", false, this.getClass()
+ .getClassLoader());// ReflectionBasedReferenceTypeDelegate.class.getClassLoader());
+ } catch (ClassNotFoundException cnfEx) {
+ return true;
+ }
+ return false;
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ needToSkip = needToSkipPointcutParserTests();
+ }
+
+ /**
+ * Constructor for PatternTestCase.
+ *
+ * @param name
+ */
+ public ThisOrTargetTestCase(String name) {
+ super(name);
+ }
+
+ public void testMatchJP() throws Exception {
+ if (needToSkip)
+ return;
+
+ PointcutParser parser = PointcutParser
+ .getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
+ PointcutExpression thisEx = parser.parsePointcutExpression("this(Exception)");
+ PointcutExpression thisIOEx = parser.parsePointcutExpression("this(java.io.IOException)");
+
+ PointcutExpression targetEx = parser.parsePointcutExpression("target(Exception)");
+ PointcutExpression targetIOEx = parser.parsePointcutExpression("target(java.io.IOException)");
+
+ Method toString = Object.class.getMethod("toString", new Class[0]);
+
+ checkMatches(thisEx.matchesMethodCall(toString, toString), new Exception(), null, null);
+ checkNoMatch(thisIOEx.matchesMethodCall(toString, toString), new Exception(), null, null);
+ checkNoMatch(targetEx.matchesMethodCall(toString, toString), new Exception(), new Object(), null);
+ checkNoMatch(targetIOEx.matchesMethodCall(toString, toString), new Exception(), new Exception(), null);
+
+ checkMatches(thisEx.matchesMethodCall(toString, toString), new IOException(), null, null);
+ checkMatches(thisIOEx.matchesMethodCall(toString, toString), new IOException(), null, null);
+
+ checkNoMatch(thisEx.matchesMethodCall(toString, toString), new Object(), null, null);
+ checkNoMatch(thisIOEx.matchesMethodCall(toString, toString), new Exception(), null, null);
+ checkMatches(targetEx.matchesMethodCall(toString, toString), new Exception(), new Exception(), null);
+ checkNoMatch(targetIOEx.matchesMethodCall(toString, toString), new Exception(), new Exception(), null);
+
+ checkMatches(targetIOEx.matchesMethodCall(toString, toString), new Exception(), new IOException(), null);
+ }
+
+ public void testBinding() throws Exception {
+ if (needToSkip)
+ return;
+ PointcutParser parser = PointcutParser
+ .getPointcutParserSupportingAllPrimitivesAndUsingSpecifiedClassloaderForResolution(this.getClass().getClassLoader());
+ PointcutParameter ex = parser.createPointcutParameter("ex", Exception.class);
+ PointcutParameter ioEx = parser.createPointcutParameter("ioEx", IOException.class);
+
+ PointcutExpression thisEx = parser.parsePointcutExpression("this(ex)", Exception.class, new PointcutParameter[] { ex });
+
+ PointcutExpression targetIOEx = parser.parsePointcutExpression("target(ioEx)", Exception.class,
+ new PointcutParameter[] { ioEx });
+
+ Method toString = Object.class.getMethod("toString", new Class[0]);
+
+ ShadowMatch sMatch = thisEx.matchesMethodCall(toString, toString);
+ Exception exceptionParameter = new Exception();
+ IOException ioExceptionParameter = new IOException();
+ JoinPointMatch jpMatch = sMatch.matchesJoinPoint(exceptionParameter, null, null);
+ assertTrue("should match", jpMatch.matches());
+ PointcutParameter[] bindings = jpMatch.getParameterBindings();
+ assertEquals("one binding", 1, bindings.length);
+ assertEquals("should be exceptionParameter", exceptionParameter, bindings[0].getBinding());
+ assertEquals("ex", bindings[0].getName());
+
+ sMatch = targetIOEx.matchesMethodCall(toString, toString);
+ jpMatch = sMatch.matchesJoinPoint(exceptionParameter, ioExceptionParameter, null);
+ assertTrue("should match", jpMatch.matches());
+ bindings = jpMatch.getParameterBindings();
+ assertEquals("one binding", 1, bindings.length);
+ assertEquals("should be ioExceptionParameter", ioExceptionParameter, bindings[0].getBinding());
+ assertEquals("ioEx", bindings[0].getName());
+
+ }
+
+ private void checkMatches(ShadowMatch sMatch, Object thisObj, Object targetObj, Object[] args) {
+ assertTrue("match expected", sMatch.matchesJoinPoint(thisObj, targetObj, args).matches());
+ }
+
+ private void checkNoMatch(ShadowMatch sMatch, Object thisObj, Object targetObj, Object[] args) {
+ assertFalse("no match expected", sMatch.matchesJoinPoint(thisObj, targetObj, args).matches());
+ }
+
+ /**
+ * Method checkSerialization.
+ *
+ * @param string
+ */
+ // private void checkSerialization(String string) throws IOException {
+ // Pointcut p = makePointcut(string);
+ // ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ // DataOutputStream out = new DataOutputStream(bo);
+ // p.write(out);
+ // out.close();
+ //
+ // ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ // DataInputStream in = new DataInputStream(bi);
+ // Pointcut newP = Pointcut.read(in, null);
+ //
+ // assertEquals("write/read", p, newP);
+ // }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+
+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.TypePatternList;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+
+/**
+ * @author hugunin
+ *
+ * To change this generated comment edit the template variable "typecomment": Window>Preferences>Java>Templates. To enable
+ * and disable the creation of type comments go to Window>Preferences>Java>Code Generation.
+ */
+public class TypePatternListTestCase extends PatternsTestCase {
+ public World getWorld() {
+ return new ReflectionWorld(true, this.getClass().getClassLoader());
+ }
+
+ // XXX when instanceof matching works add tests for that here
+
+ public void testMatch() {
+
+ checkStaticMatch("()", new String[] {}, FuzzyBoolean.YES);
+ checkStaticMatch("()", new String[] { "java.lang.Object" }, FuzzyBoolean.NO);
+
+ checkStaticMatch("(java.lang.Object)", new String[] { "java.lang.Object" }, FuzzyBoolean.YES);
+
+ checkStaticMatch("(java.lang.String)", new String[] { "java.lang.Object" }, FuzzyBoolean.NO);
+
+ checkStaticMatch("(java.lang.Object)", new String[] { "java.lang.String" }, FuzzyBoolean.NO);
+
+ checkStaticMatch("()", new String[] { "java.lang.Object" }, FuzzyBoolean.NO);
+
+ checkStaticMatch("(..)", new String[] {}, FuzzyBoolean.YES);
+ checkStaticMatch("(..)", new String[] { "int", "char" }, FuzzyBoolean.YES);
+
+ checkStaticMatch("(int,..,int)", new String[] { "int", "int" }, FuzzyBoolean.YES);
+
+ checkStaticMatch("(int,..)", new String[] {}, FuzzyBoolean.NO);
+ checkStaticMatch("(int,..)", new String[] { "int" }, FuzzyBoolean.YES);
+
+ checkStaticMatch("(..,int,..)", new String[] { "int" }, FuzzyBoolean.YES);
+
+ // these checks are taken from new/ExpandedDotPattern.java
+ stupidCheck("( .., .., ..)", new boolean[] { true, true, true, true, true });
+ stupidCheck("( .., .., int)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., int, ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., int, int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, .., ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("(int, .., int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, int, ..)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, int, int)", new boolean[] { false, false, false, true, false });
+
+ stupidCheck("( .., .., .., ..)", new boolean[] { true, true, true, true, true });
+ stupidCheck("( .., .., .., int)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., .., int, ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., .., int, int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("( .., int, .., ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("( .., int, .., int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("( .., int, int, ..)", new boolean[] { false, false, true, true, true });
+ stupidCheck("( .., int, int, int)", new boolean[] { false, false, false, true, true });
+
+ stupidCheck("(int, .., .., ..)", new boolean[] { false, true, true, true, true });
+ stupidCheck("(int, .., .., int)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, .., int, ..)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, .., int, int)", new boolean[] { false, false, false, true, true });
+ stupidCheck("(int, int, .., ..)", new boolean[] { false, false, true, true, true });
+ stupidCheck("(int, int, .., int)", new boolean[] { false, false, false, true, true });
+ stupidCheck("(int, int, int, ..)", new boolean[] { false, false, false, true, true });
+ stupidCheck("(int, int, int, int)", new boolean[] { false, false, false, false, true });
+ }
+
+ private TypePatternList makeArgumentsPattern(String pattern) {
+ return new PatternParser(pattern).parseArgumentsPattern(false);
+ }
+
+ private void checkStaticMatch(String pattern, String[] names, FuzzyBoolean shouldMatchStatically) {
+ // We're only doing TypePattern.STATIC matching here because my intent was
+ // to test the wildcarding, and we don't do DYNAMIC matching on wildcarded things.
+
+ TypePatternList p = makeArgumentsPattern(pattern);
+ ResolvedType[] types = new ResolvedType[names.length];
+ for (int i = 0; i < names.length; i++) {
+ types[i] = world.resolve(names[i]);
+ }
+
+ p.resolveBindings(makeTestScope(), Bindings.NONE, false, false);
+ // System.out.println("type: " + type);
+ FuzzyBoolean result = p.matches(types, TypePattern.STATIC);
+ String msg = "matches statically " + pattern + " to " + Arrays.asList(types);
+ assertEquals(msg, shouldMatchStatically, result);
+ }
+
+ public static final String[] NO_STRINGS = new String[0];
+
+ private TestScope makeTestScope() {
+ TestScope scope = new TestScope(NO_STRINGS, NO_STRINGS, world);
+ return scope;
+ }
+
+ public void stupidCheck(String pattern, boolean[] matches) {
+ TypePatternList p = makeArgumentsPattern(pattern);
+ p.resolveBindings(makeTestScope(), Bindings.NONE, false, false);
+
+ int len = matches.length;
+
+ for (int j = 0; j < len; j++) {
+
+ ResolvedType[] types = new ResolvedType[j];
+ for (int i = 0; i < j; i++) {
+ types[i] = world.resolve("int");
+ }
+
+ FuzzyBoolean result = p.matches(types, TypePattern.STATIC);
+ String msg = "matches statically " + pattern + " to " + Arrays.asList(types);
+ assertEquals(msg, FuzzyBoolean.fromBoolean(matches[j]), result);
+ }
+ }
+
+ public void testSerialization() throws IOException {
+ String[] patterns = new String[] { "( .., .., .., int)", "( .., .., int, ..)", "( .., .., int, int)",
+ "( .., int, .., ..)", "( .., int, .., int)", "( .., int, int, ..)", "( .., int, int, int)",
+
+ "(int, .., .., ..)", "(int, .., .., int)", "(int, .., int, ..)", "(int, .., int, int)",
+ "(int, int, .., ..)", "(int, int, .., int)", "(int, int, int, ..)", "(int, int, int, int)" };
+
+ for (int i = 0, len = patterns.length; i < len; i++) {
+ checkSerialization(patterns[i]);
+ }
+ }
+
+ /**
+ * Method checkSerialization.
+ *
+ * @param string
+ */
+ private void checkSerialization(String string) throws IOException {
+ TypePatternList p = makeArgumentsPattern(string);
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ VersionedDataInputStream in = new VersionedDataInputStream(bi);
+ TypePatternList newP = TypePatternList.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+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 {
+
+ public World getWorld() {
+ return new ReflectionWorld(true, this.getClass().getClassLoader());
+ }
+
+ public void testStaticMatch() {
+ checkMatch("java.lang.Object", "java.lang.Object", true);
+ checkMatch("java.lang.Object+", "java.lang.Object", true);
+ checkMatch("java.lang.Object+", "java.lang.String", true);
+ checkMatch("java.lang.String+", "java.lang.Object", false);
+ checkMatch("java.lang.Integer", "java.lang.String", false);
+
+ checkMatch("java.lang.Integer", "int", false);
+
+ checkMatch("java.lang.Number+", "java.lang.Integer", true);
+
+ checkMatch("java..*", "java.lang.Integer", true);
+ checkMatch("java..*", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*", "int", false);
+ checkMatch("java..*", "javax.swing.Action", false);
+ checkMatch("java..*+", "javax.swing.Action", true);
+
+ checkMatch("*.*.Object", "java.lang.Object", true);
+ checkMatch("*.Object", "java.lang.Object", false);
+ checkMatch("*..*", "java.lang.Object", true);
+ checkMatch("*..*", "int", false);
+ checkMatch("java..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java.lang.reflect.Mod..ifier", "java.lang.reflect.Modifier", false);
+
+ checkMatch("java..reflect..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..lang..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*..*..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*..*..*..Modifier", "java.lang.reflect.Modifier", false);
+ // checkMatch("java..reflect..Modifier", "java.lang.reflect.Modxifier", false);
+ checkMatch("ja*va..Modifier", "java.lang.reflect.Modifier", true);
+ checkMatch("java..*..Mod*ifier", "java.lang.reflect.Modifier", true);
+
+ }
+
+ // three levels:
+ // 0. defined in current compilation unit, or imported by name
+ // 1. defined in current package/type/whatever
+ // 2. defined in package imported by *
+ /**
+ * We've decided not to test this here, but rather in any compilers
+ */
+ public void testImportResolve() {
+ // checkIllegalImportResolution("List", new String[] { "java.util", "java.awt", },
+ // ZERO_STRINGS);
+
+ }
+
+ // Assumption for bcweaver: Already resolved type patterns with no *s or ..'s into exact type
+ // patterns. Exact type patterns don't have import lists. non-exact-type pattens don't
+ // care about precedence, so the current package can be included with all the other packages,
+ // and we don't care about compilation units, and we don't care about ordering.
+
+ // only giving this wild-type patterns
+ public void testImportMatch() {
+
+ checkImportMatch("*List", new String[] { "java.awt.", }, ZERO_STRINGS, "java.awt.List", true);
+ checkImportMatch("*List", new String[] { "java.awt.", }, ZERO_STRINGS, "java.awt.List", true);
+ checkImportMatch("*List", new String[] { "java.awt.", }, ZERO_STRINGS, "java.util.List", false);
+ checkImportMatch("*List", new String[] { "java.util.", }, ZERO_STRINGS, "java.awt.List", false);
+ checkImportMatch("*List", new String[] { "java.util.", }, ZERO_STRINGS, "java.util.List", true);
+
+ checkImportMatch("*List", ZERO_STRINGS, new String[] { "java.awt.List", }, "java.awt.List", true);
+
+ checkImportMatch("awt.*List", ZERO_STRINGS, new String[] { "java.awt.List", }, "java.awt.List", false);
+ checkImportMatch("*Foo", ZERO_STRINGS, new String[] { "java.awt.List", }, "java.awt.List", false);
+
+ checkImportMatch("*List", new String[] { "java.util.", "java.awt.", }, ZERO_STRINGS, "java.util.List", true);
+ checkImportMatch("*List", new String[] { "java.util.", "java.awt.", }, ZERO_STRINGS, "java.awt.List", true);
+
+ checkImportMatch("*..List", new String[] { "java.util." }, ZERO_STRINGS, "java.util.List", true);
+ checkImportMatch("*..List", new String[] { "java.util." }, ZERO_STRINGS, "java.awt.List", true);
+
+ }
+
+ public void testImportMatchWithInners() {
+ checkImportMatch("*Entry", new String[] { "java.util.", "java.util.Map$" }, ZERO_STRINGS, "java.util.Map$Entry", true);
+
+ checkImportMatch("java.util.Map.*Entry", ZERO_STRINGS, ZERO_STRINGS, "java.util.Map$Entry", true);
+
+ checkImportMatch("*Entry", new String[] { "java.util.", }, ZERO_STRINGS, "java.util.Map$Entry", false);
+
+ checkImportMatch("*.Entry", new String[] { "java.util.", }, ZERO_STRINGS, "java.util.Map$Entry", true);
+
+ checkImportMatch("Map.*", new String[] { "java.util.", }, ZERO_STRINGS, "java.util.Map$Entry", true);
+
+ checkImportMatch("Map.*", ZERO_STRINGS, new String[] { "java.util.Map" }, "java.util.Map$Entry", true);
+ }
+
+ private void checkImportMatch(String wildPattern, String[] importedPackages, String[] importedNames, String matchName,
+ boolean shouldMatch) {
+ WildTypePattern p = makeResolvedWildTypePattern(wildPattern, importedPackages, importedNames);
+ checkPatternMatch(p, matchName, shouldMatch);
+ }
+
+ private WildTypePattern makeResolvedWildTypePattern(String wildPattern, String[] importedPackages, String[] importedNames) {
+ WildTypePattern unresolved = (WildTypePattern) new PatternParser(wildPattern).parseTypePattern();
+
+ WildTypePattern resolved = resolve(unresolved, importedPackages, importedNames);
+ return resolved;
+
+ }
+
+ private WildTypePattern resolve(WildTypePattern unresolved, String[] importedPrefixes, String[] importedNames) {
+
+ TestScope scope = makeTestScope();
+ scope.setImportedPrefixes(importedPrefixes);
+ scope.setImportedNames(importedNames);
+ return (WildTypePattern) unresolved.resolveBindings(scope, Bindings.NONE, false, false);
+ }
+
+ public static final String[] ZERO_STRINGS = new String[0];
+
+ public void testInstanceofMatch() {
+
+ checkInstanceofMatch("java.lang.Object", "java.lang.Object", FuzzyBoolean.YES);
+
+ checkIllegalInstanceofMatch("java.lang.Object+", "java.lang.Object");
+ checkIllegalInstanceofMatch("java.lang.Object+", "java.lang.String");
+ checkIllegalInstanceofMatch("java.lang.String+", "java.lang.Object");
+ checkIllegalInstanceofMatch("java.lang.*", "java.lang.Object");
+ checkInstanceofMatch("java.lang.Integer", "java.lang.String", FuzzyBoolean.NO);
+
+ checkInstanceofMatch("java.lang.Number", "java.lang.Integer", FuzzyBoolean.YES);
+ checkInstanceofMatch("java.lang.Integer", "java.lang.Number", FuzzyBoolean.MAYBE);
+
+ checkIllegalInstanceofMatch("java..Integer", "java.lang.Integer");
+
+ checkInstanceofMatch("*", "java.lang.Integer", FuzzyBoolean.YES);
+
+ }
+
+ public void testArrayMatch() {
+ checkMatch("*[][]", "java.lang.Object", false);
+ checkMatch("*[]", "java.lang.Object[]", true);
+ checkMatch("*[][]", "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);
+ }
+
+ private void checkIllegalInstanceofMatch(String pattern, String name) {
+ try {
+ TypePattern p = makeTypePattern(pattern);
+ ResolvedType type = world.resolve(name);
+ p.matchesInstanceof(type);
+ } catch (Throwable e) {
+ return;
+ }
+ assertTrue("matching " + pattern + " with " + name + " should fail", false);
+ }
+
+ private void checkInstanceofMatch(String pattern, String name, FuzzyBoolean shouldMatch) {
+ TypePattern p = makeTypePattern(pattern);
+ ResolvedType type = world.resolve(name);
+
+ p = p.resolveBindings(makeTestScope(), null, false, false);
+
+ // System.out.println("type: " + p);
+ FuzzyBoolean result = p.matchesInstanceof(type);
+ String msg = "matches " + pattern + " to " + type;
+ assertEquals(msg, shouldMatch, result);
+ }
+
+ private TestScope makeTestScope() {
+ TestScope scope = new TestScope(ZERO_STRINGS, ZERO_STRINGS, world);
+ return scope;
+ }
+
+ private TypePattern makeTypePattern(String pattern) {
+ return new PatternParser(pattern).parseSingleTypePattern();
+ }
+
+ private void checkMatch(String pattern, String name, boolean shouldMatch) {
+ TypePattern p = makeTypePattern(pattern);
+ p = p.resolveBindings(makeTestScope(), null, false, false);
+ checkPatternMatch(p, name, shouldMatch);
+ }
+
+ private void checkPatternMatch(TypePattern p, String name, boolean shouldMatch) {
+ ResolvedType type = world.resolve(name);
+ // System.out.println("type: " + type);
+ boolean result = p.matchesStatically(type);
+ String msg = "matches " + p + " to " + type + " expected ";
+ if (shouldMatch) {
+ assertTrue(msg + shouldMatch, result);
+ } else {
+ assertTrue(msg + shouldMatch, !result);
+ }
+ }
+
+ public void testSerialization() throws IOException {
+ String[] patterns = new String[] { "java.lang.Object", "java.lang.Object+", "java.lang.Integer", "int", "java..*",
+ "java..util..*", "*.*.Object", "*", };
+
+ for (int i = 0, len = patterns.length; i < len; i++) {
+ checkSerialization(patterns[i]);
+ }
+ }
+
+ /**
+ * Method checkSerialization.
+ *
+ * @param string
+ */
+ private void checkSerialization(String string) throws IOException {
+ TypePattern p = makeTypePattern(string);
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ VersionedDataInputStream in = new VersionedDataInputStream(bi);
+ TypePattern newP = TypePattern.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2005 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:
+ * Alexandre Vasseur initial implementation
+ *******************************************************************************/
+package org.aspectj.weaver.patterns;
+
+import junit.framework.TestCase;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Iterator;
+import java.io.LineNumberReader;
+import java.io.FileReader;
+
+import org.aspectj.weaver.patterns.DumpPointcutVisitor;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.TypePattern;
+
+/**
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public class VisitorTestCase extends TestCase {
+
+ private Set pointcuts = new HashSet();
+ private Set typePatterns = new HashSet();
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ LineNumberReader rp = new LineNumberReader(new FileReader("../weaver/testdata/visitor.pointcuts.txt"));
+ feed(rp, pointcuts);
+ rp.close();
+ LineNumberReader rt = new LineNumberReader(new FileReader("../weaver/testdata/visitor.typepatterns.txt"));
+ feed(rt, typePatterns);
+ rt.close();
+ }
+
+ private void feed(LineNumberReader r, Set set) throws Exception {
+ for (String line = r.readLine(); line != null; line = r.readLine()) {
+ set.add(line);
+ }
+ }
+
+ public void testPointcuts() {
+ if (pointcuts.isEmpty()) {
+ fail("Empty pointcuts file!");
+ }
+ for (Iterator iterator = pointcuts.iterator(); iterator.hasNext();) {
+ String pointcut = (String) iterator.next();
+ try {
+ DumpPointcutVisitor.check(pointcut);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ fail("Failed on '"+pointcut+"': " +t.toString());
+ }
+ }
+ }
+
+ public void testTypePatterns() {
+ if (typePatterns.isEmpty()) {
+ fail("Empty typePatterns file!");
+ }
+ for (Iterator iterator = typePatterns.iterator(); iterator.hasNext();) {
+ String tp = (String) iterator.next();
+ try {
+ TypePattern p = new PatternParser(tp).parseTypePattern();
+ DumpPointcutVisitor.check(p, true);
+ } catch (Throwable t) {
+ fail("Failed on '"+tp+"': " +t.toString());
+ }
+ }
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2005 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Adrian Colyer initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.aspectj.weaver.BoundedReferenceType;
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.TypeFactory;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
+import org.aspectj.weaver.patterns.Bindings;
+import org.aspectj.weaver.patterns.ExactTypePattern;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.PatternParser;
+import org.aspectj.weaver.patterns.SimpleScope;
+import org.aspectj.weaver.patterns.TypePattern;
+import org.aspectj.weaver.patterns.WildTypePattern;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+
+// TODO write test cases for instanceof matching
+
+public class WildTypePatternResolutionTestCase extends TestCase {
+
+ private World world;
+ private Bindings bindings;
+ private SimpleScope scope;
+ private ResolvedType javaUtilList;
+ private ResolvedType javaLangString;
+ private ResolvedType javaUtilListOfString;
+ private ResolvedType javaUtilListOfDouble;
+ private ResolvedType javaUtilListOfSomething;
+
+ /**
+ * Foo where Foo exists and is generic Parser creates WildTypePattern namePatterns={Foo} resolveBindings resolves Foo to RT(Foo
+ * - raw) return ExactTypePattern(LFoo;)
+ */
+ public void testSimpleFoo() {
+ TypePattern rtp = resolveWildTypePattern("List", false);
+
+ assertTrue("resolves to exact type", rtp instanceof ExactTypePattern);
+ UnresolvedType exactType = rtp.getExactType();
+ assertTrue(exactType.isRawType());
+ assertEquals("Ljava/util/List;", exactType.getSignature());
+
+ ResolvedType rt = exactType.resolve(world);
+ assertEquals("Ljava/util/List;", rt.getSignature());
+ assertTrue(rt.isRawType());
+
+ ExactTypePattern etp = (ExactTypePattern) writeAndRead(rtp);
+ exactType = etp.getExactType();
+
+ assertEquals("Ljava/util/List;", exactType.getSignature());
+
+ rt = exactType.resolve(world);
+ assertEquals("Ljava/util/List;", rt.getSignature());
+ assertTrue(rt.isRawType());
+
+ assertTrue("matches List", etp.matches(javaUtilList, TypePattern.STATIC).alwaysTrue());
+ assertTrue("matches generic List", etp.matches(javaUtilList.getGenericType(), TypePattern.STATIC).alwaysTrue());
+ assertTrue("matches parameterized list", etp.matches(javaUtilListOfString, TypePattern.STATIC).alwaysTrue());
+ assertTrue("does not match String", etp.matches(javaLangString, TypePattern.STATIC).alwaysFalse());
+ }
+
+ /**
+ * Foo<String> where Foo exists and String meets the bounds Parser creates WildTypePattern namePatterns = {Foo},
+ * typeParameters=WTP{String} resolveBindings resolves typeParameters to ExactTypePattern(String) resolves Foo to RT(Foo)
+ * returns ExactTypePattern(PFoo<String>; - parameterized)
+ */
+ public void testParameterized() {
+ TypePattern rtp = resolveWildTypePattern("List<String>", false);
+
+ assertTrue("resolves to exact type", rtp instanceof ExactTypePattern);
+ UnresolvedType exactType = rtp.getExactType();
+ assertTrue(exactType.isParameterizedType());
+ assertEquals("Pjava/util/List<Ljava/lang/String;>;", exactType.getSignature());
+
+ ResolvedType rt = exactType.resolve(world);
+ assertEquals("Pjava/util/List<Ljava/lang/String;>;", rt.getSignature());
+ assertTrue(rt.isParameterizedType());
+
+ ExactTypePattern etp = (ExactTypePattern) writeAndRead(rtp);
+ exactType = etp.getExactType();
+
+ assertEquals("Pjava/util/List<Ljava/lang/String;>;", rt.getSignature());
+ assertTrue(rt.isParameterizedType());
+
+ rt = exactType.resolve(world);
+ assertEquals("Pjava/util/List<Ljava/lang/String;>;", rt.getSignature());
+ assertTrue(rt.isParameterizedType());
+
+ assertFalse("does not match List", etp.matches(javaUtilList, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match generic List", etp.matches(javaUtilList.getGenericType(), TypePattern.STATIC).alwaysTrue());
+ assertTrue("matches parameterized list", etp.matches(javaUtilListOfString, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list of double", etp.matches(javaUtilListOfDouble, TypePattern.STATIC)
+ .alwaysTrue());
+ assertTrue("does not match String", etp.matches(javaLangString, TypePattern.STATIC).alwaysFalse());
+
+ }
+
+ /**
+ * Foo<Str*> where Foo exists and takes one bound Parser creates WildTypePattern namePatterns = {Foo}, typeParameters=WTP{Str*}
+ * resolveBindings resolves typeParameters to WTP{Str*} resolves Foo to RT(Foo) returns WildTypePattern(name = Foo,
+ * typeParameters = WTP{Str*} isGeneric=false)
+ */
+ public void testParameterizedWildCard() {
+ TypePattern rtp = resolveWildTypePattern("List<Str*>", false);
+
+ assertTrue("resolves to WildTypePattern", rtp instanceof WildTypePattern);
+ assertTrue("one type parameter", rtp.typeParameters.size() == 1);
+ assertTrue("missing", ResolvedType.isMissing(rtp.getExactType()));
+
+ WildTypePattern wtp = (WildTypePattern) writeAndRead(rtp);
+ assertTrue("one type parameter", wtp.typeParameters.size() == 1);
+ assertTrue("missing", ResolvedType.isMissing(wtp.getExactType()));
+ assertEquals("Str*", wtp.getTypeParameters().getTypePatterns()[0].toString());
+
+ assertFalse("does not match List", wtp.matches(javaUtilList, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match generic List", wtp.matches(javaUtilList.getGenericType(), TypePattern.STATIC).alwaysTrue());
+ assertTrue("matches parameterized list", wtp.matches(javaUtilListOfString, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list of double", wtp.matches(javaUtilListOfDouble, TypePattern.STATIC)
+ .alwaysTrue());
+ assertTrue("does not match String", wtp.matches(javaLangString, TypePattern.STATIC).alwaysFalse());
+ }
+
+ /**
+ * Fo*<String> Parser creates WildTypePattern namePatterns = {Fo*}, typeParameters=WTP{String} resolveBindings resolves
+ * typeParameters to ETP{String} returns WildTypePattern(name = Fo*, typeParameters = ETP{String} isGeneric=false)
+ */
+ public void testWildcardParameterized() {
+ TypePattern rtp = resolveWildTypePattern("Li*<String>", false);
+
+ assertTrue("resolves to WildTypePattern", rtp instanceof WildTypePattern);
+ assertTrue("one type parameter", rtp.typeParameters.size() == 1);
+ assertEquals("Ljava/lang/String;", rtp.typeParameters.getTypePatterns()[0].getExactType().getSignature());
+
+ WildTypePattern wtp = (WildTypePattern) writeAndRead(rtp);
+ assertTrue("one type parameter", wtp.typeParameters.size() == 1);
+ assertEquals("Ljava/lang/String;", wtp.typeParameters.getTypePatterns()[0].getExactType().getSignature());
+
+ assertFalse("does not match List", wtp.matches(javaUtilList, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match generic List", wtp.matches(javaUtilList.getGenericType(), TypePattern.STATIC).alwaysTrue());
+ assertTrue("matches parameterized list", wtp.matches(javaUtilListOfString, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list of double", wtp.matches(javaUtilListOfDouble, TypePattern.STATIC)
+ .alwaysTrue());
+ assertTrue("does not match String", wtp.matches(javaLangString, TypePattern.STATIC).alwaysFalse());
+ }
+
+ /**
+ * Foo<?>
+ */
+ public void testSomething() {
+ TypePattern rtp = resolveWildTypePattern("List<?>", false);
+
+ assertTrue("resolves to exact type", rtp instanceof ExactTypePattern);
+ UnresolvedType exactType = rtp.getExactType();
+ assertTrue(exactType.isParameterizedType());
+ assertEquals("Pjava/util/List<*>;", exactType.getSignature());
+
+ ExactTypePattern etp = (ExactTypePattern) writeAndRead(rtp);
+ exactType = etp.getExactType();
+ assertTrue(exactType.isParameterizedType());
+ assertEquals("Pjava/util/List<*>;", exactType.getSignature());
+
+ assertFalse("does not match List", etp.matches(javaUtilList, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match generic List", etp.matches(javaUtilList.getGenericType(), TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list", etp.matches(javaUtilListOfString, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list of double", etp.matches(javaUtilListOfDouble, TypePattern.STATIC)
+ .alwaysTrue());
+ assertTrue("does not match String", etp.matches(javaLangString, TypePattern.STATIC).alwaysFalse());
+
+ assertTrue("matches list of something", etp.matches(javaUtilListOfSomething, TypePattern.STATIC).alwaysTrue());
+ }
+
+ /**
+ * Foo<? extends Number>
+ */
+ public void testSomethingExtends() {
+ TypePattern rtp = resolveWildTypePattern("List<? extends Number>", false);
+
+ assertTrue("resolves to exact type", rtp instanceof ExactTypePattern);
+ UnresolvedType exactType = rtp.getExactType();
+ assertTrue(exactType.isParameterizedType());
+ assertEquals("Pjava/util/List<+Ljava/lang/Number;>;", exactType.getSignature());
+ assertTrue("got a bounded reference type", exactType.getTypeParameters()[0] instanceof BoundedReferenceType);
+
+ ExactTypePattern etp = (ExactTypePattern) writeAndRead(rtp);
+ exactType = etp.getExactType();
+ exactType = exactType.resolve(world);
+ assertTrue(exactType.isParameterizedType());
+ assertEquals("Pjava/util/List<+Ljava/lang/Number;>;", exactType.getSignature());
+ assertTrue("got a bounded reference type", exactType.getTypeParameters()[0] instanceof BoundedReferenceType);
+
+ assertFalse("does not match List", etp.matches(javaUtilList, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match generic List", etp.matches(javaUtilList.getGenericType(), TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list", etp.matches(javaUtilListOfString, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list of double", etp.matches(javaUtilListOfDouble, TypePattern.STATIC)
+ .alwaysTrue());
+ assertTrue("does not match String", etp.matches(javaLangString, TypePattern.STATIC).alwaysFalse());
+ assertFalse("does not match list of something", etp.matches(javaUtilListOfSomething, TypePattern.STATIC).alwaysTrue());
+
+ ResolvedType listOfNumber = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { UnresolvedType
+ .forName("java.lang.Number").resolve(world) }, world);
+
+ ResolvedType listOfDouble = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { UnresolvedType
+ .forName("java.lang.Double").resolve(world) }, world);
+
+ assertFalse("does not match list of number", etp.matches(listOfNumber, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match list of double", etp.matches(listOfDouble, TypePattern.STATIC).alwaysTrue());
+
+ ResolvedType extendsNumber = TypeFactory.createTypeFromSignature("+Ljava/lang/Number;").resolve(world);
+ ResolvedType listOfExtendsNumber = TypeFactory.createParameterizedType(javaUtilList,
+ new UnresolvedType[] { extendsNumber }, world);
+
+ assertTrue("matches list of ? extends number", etp.matches(listOfExtendsNumber, TypePattern.STATIC).alwaysTrue());
+
+ }
+
+ /**
+ * Foo<? extends Number+>
+ */
+ public void testSomethingExtendsPattern() {
+ TypePattern rtp = resolveWildTypePattern("List<? extends Number+>", false);
+
+ assertTrue("resolves to wild type pattern", rtp instanceof WildTypePattern);
+ assertEquals("one type parameter", 1, rtp.getTypeParameters().size());
+ TypePattern tp = rtp.getTypeParameters().getTypePatterns()[0];
+ assertTrue("parameter is wild", tp instanceof WildTypePattern);
+ WildTypePattern tpwtp = (WildTypePattern) tp;
+ assertEquals("?", tpwtp.getNamePatterns()[0].maybeGetSimpleName());
+ assertEquals("java.lang.Number+", tpwtp.upperBound.toString());
+
+ WildTypePattern wtp = (WildTypePattern) writeAndRead(rtp);
+ assertEquals("one type parameter", 1, wtp.getTypeParameters().size());
+ tp = rtp.getTypeParameters().getTypePatterns()[0];
+ assertTrue("parameter is wild", tp instanceof WildTypePattern);
+ tpwtp = (WildTypePattern) tp;
+ assertEquals("?", tpwtp.getNamePatterns()[0].maybeGetSimpleName());
+ assertEquals("java.lang.Number+", tpwtp.upperBound.toString());
+
+ assertFalse("does not match List", wtp.matches(javaUtilList, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match generic List", wtp.matches(javaUtilList.getGenericType(), TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list", wtp.matches(javaUtilListOfString, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list of double", wtp.matches(javaUtilListOfDouble, TypePattern.STATIC)
+ .alwaysTrue());
+ assertTrue("does not match String", wtp.matches(javaLangString, TypePattern.STATIC).alwaysFalse());
+ assertFalse("does not match list of something", wtp.matches(javaUtilListOfSomething, TypePattern.STATIC).alwaysTrue());
+
+ ResolvedType listOfNumber = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { UnresolvedType
+ .forName("java.lang.Number").resolve(world) }, world);
+
+ ResolvedType listOfDouble = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { UnresolvedType
+ .forName("java.lang.Double").resolve(world) }, world);
+
+ assertFalse("does not match list of number", wtp.matches(listOfNumber, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match list of double", wtp.matches(listOfDouble, TypePattern.STATIC).alwaysTrue());
+
+ ResolvedType extendsNumber = TypeFactory.createTypeFromSignature("+Ljava/lang/Number;").resolve(world);
+ ResolvedType listOfExtendsNumber = TypeFactory.createParameterizedType(javaUtilList,
+ new UnresolvedType[] { extendsNumber }, world);
+
+ assertTrue("matches list of ? extends number", wtp.matches(listOfExtendsNumber, TypePattern.STATIC).alwaysTrue());
+
+ ResolvedType extendsDouble = TypeFactory.createTypeFromSignature("+Ljava/lang/Double;").resolve(world);
+ ResolvedType listOfExtendsDouble = TypeFactory.createParameterizedType(javaUtilList,
+ new UnresolvedType[] { extendsDouble }, world);
+
+ assertTrue("matches list of ? extends double", wtp.matches(listOfExtendsDouble, TypePattern.STATIC).alwaysTrue());
+
+ }
+
+ /**
+ * Foo<? extends Num*>
+ */
+ public void testSomethingExtendsPatternv2() {
+ TypePattern rtp = resolveWildTypePattern("List<? extends Num*>", false);
+
+ assertTrue("resolves to wild type pattern", rtp instanceof WildTypePattern);
+ assertEquals("one type parameter", 1, rtp.getTypeParameters().size());
+ TypePattern tp = rtp.getTypeParameters().getTypePatterns()[0];
+ assertTrue("parameter is wild", tp instanceof WildTypePattern);
+ WildTypePattern tpwtp = (WildTypePattern) tp;
+ assertEquals("?", tpwtp.getNamePatterns()[0].maybeGetSimpleName());
+ assertEquals("Num*", tpwtp.upperBound.toString());
+
+ WildTypePattern wtp = (WildTypePattern) writeAndRead(rtp);
+ assertEquals("one type parameter", 1, wtp.getTypeParameters().size());
+ tp = rtp.getTypeParameters().getTypePatterns()[0];
+ assertTrue("parameter is wild", tp instanceof WildTypePattern);
+ tpwtp = (WildTypePattern) tp;
+ assertEquals("?", tpwtp.getNamePatterns()[0].maybeGetSimpleName());
+ assertEquals("Num*", tpwtp.upperBound.toString());
+
+ assertFalse("does not match List", wtp.matches(javaUtilList, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match generic List", wtp.matches(javaUtilList.getGenericType(), TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list", wtp.matches(javaUtilListOfString, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list of double", wtp.matches(javaUtilListOfDouble, TypePattern.STATIC)
+ .alwaysTrue());
+ assertTrue("does not match String", wtp.matches(javaLangString, TypePattern.STATIC).alwaysFalse());
+ assertFalse("does not match list of something", wtp.matches(javaUtilListOfSomething, TypePattern.STATIC).alwaysTrue());
+
+ ResolvedType listOfNumber = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { UnresolvedType
+ .forName("java.lang.Number").resolve(world) }, world);
+
+ ResolvedType listOfDouble = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { UnresolvedType
+ .forName("java.lang.Double").resolve(world) }, world);
+
+ boolean matchesListOfNumber = wtp.matches(listOfNumber, TypePattern.STATIC).alwaysTrue();
+ assertFalse("does not match list of number", matchesListOfNumber);
+ assertFalse("does not match list of double", wtp.matches(listOfDouble, TypePattern.STATIC).alwaysTrue());
+
+ ResolvedType extendsNumber = TypeFactory.createTypeFromSignature("+Ljava/lang/Number;").resolve(world);
+ ResolvedType listOfExtendsNumber = TypeFactory.createParameterizedType(javaUtilList,
+ new UnresolvedType[] { extendsNumber }, world);
+
+ boolean matchesListOfQmarkExtendsNumber = wtp.matches(listOfExtendsNumber, TypePattern.STATIC).alwaysTrue();
+ assertTrue("failed to correctly match list of ? extends number", matchesListOfQmarkExtendsNumber);
+
+ ResolvedType extendsDouble = TypeFactory.createTypeFromSignature("+Ljava/lang/Double;").resolve(world);
+ ResolvedType listOfExtendsDouble = TypeFactory.createParameterizedType(javaUtilList,
+ new UnresolvedType[] { extendsDouble }, world);
+
+ assertFalse("does not match list of ? extends double", wtp.matches(listOfExtendsDouble, TypePattern.STATIC).alwaysTrue());
+ }
+
+ /**
+ * Foo<? super Number>
+ *
+ */
+ public void testSomethingSuper() {
+ TypePattern rtp = resolveWildTypePattern("List<? super Double>", false);
+
+ assertTrue("resolves to exact type", rtp instanceof ExactTypePattern);
+ UnresolvedType exactType = rtp.getExactType();
+ assertTrue(exactType.isParameterizedType());
+ assertEquals("Pjava/util/List<-Ljava/lang/Double;>;", exactType.getSignature());
+ assertTrue("got a bounded reference type", exactType.getTypeParameters()[0] instanceof BoundedReferenceType);
+
+ ExactTypePattern etp = (ExactTypePattern) writeAndRead(rtp);
+ exactType = etp.getExactType();
+ exactType = exactType.resolve(world);
+ assertTrue(exactType.isParameterizedType());
+ assertEquals("Pjava/util/List<-Ljava/lang/Double;>;", exactType.getSignature());
+ assertTrue("got a bounded reference type", exactType.getTypeParameters()[0] instanceof BoundedReferenceType);
+
+ assertFalse("does not match List", etp.matches(javaUtilList, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match generic List", etp.matches(javaUtilList.getGenericType(), TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list", etp.matches(javaUtilListOfString, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match parameterized list of double", etp.matches(javaUtilListOfDouble, TypePattern.STATIC)
+ .alwaysTrue());
+ assertTrue("does not match String", etp.matches(javaLangString, TypePattern.STATIC).alwaysFalse());
+ assertFalse("does not match list of something", etp.matches(javaUtilListOfSomething, TypePattern.STATIC).alwaysTrue());
+
+ ResolvedType listOfNumber = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { UnresolvedType
+ .forName("java.lang.Number").resolve(world) }, world);
+
+ ResolvedType listOfDouble = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { UnresolvedType
+ .forName("java.lang.Double").resolve(world) }, world);
+
+ assertFalse("does not match list of number", etp.matches(listOfNumber, TypePattern.STATIC).alwaysTrue());
+ assertFalse("does not match list of double", etp.matches(listOfDouble, TypePattern.STATIC).alwaysTrue());
+
+ ResolvedType superDouble = TypeFactory.createTypeFromSignature("-Ljava/lang/Double;").resolve(world);
+ ResolvedType listOfSuperDouble = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { superDouble },
+ world);
+
+ assertTrue("matches list of ? super double", etp.matches(listOfSuperDouble, TypePattern.STATIC).alwaysTrue());
+ }
+
+ private TypePattern resolveWildTypePattern(String source, boolean requireExact) {
+ WildTypePattern wtp = makeWildTypePattern(source);
+ return wtp.resolveBindings(scope, bindings, false, requireExact);
+ }
+
+ private WildTypePattern makeWildTypePattern(String source) {
+ PatternParser parser = new PatternParser(source);
+ return (WildTypePattern) parser.parseTypePattern();
+ }
+
+ private TypePattern writeAndRead(TypePattern etp) {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream dos = new DataOutputStream(baos);
+ etp.write(dos);
+ dos.flush();
+ dos.close();
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ VersionedDataInputStream in = new VersionedDataInputStream(bais);
+ in.setVersion(new WeaverVersionInfo());
+ TypePattern ret = TypePattern.read(in, null);
+ return ret;
+ } catch (IOException ioEx) {
+ fail(ioEx + " thrown during serialization");
+ }
+ return null;
+ }
+
+ public World getWorld() {
+ return new ReflectionWorld(true, this.getClass().getClassLoader());
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.world.setBehaveInJava5Way(true);
+ this.bindings = new Bindings(0);
+ this.scope = new SimpleScope(world, new FormalBinding[] {});
+ this.scope.setImportedPrefixes(new String[] { "java.io.", "java.util.", "java.lang." });
+ this.javaLangString = UnresolvedType.forName("java.lang.String").resolve(world);
+ this.javaUtilList = UnresolvedType.forName("java.util.List").resolve(world);
+ this.javaUtilListOfString = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { javaLangString },
+ world);
+ this.javaUtilListOfDouble = TypeFactory.createParameterizedType(javaUtilList, new UnresolvedType[] { UnresolvedType
+ .forName("java.lang.Double").resolve(world) }, world);
+ this.javaUtilListOfSomething = TypeFactory.createParameterizedType(javaUtilList,
+ new UnresolvedType[] { UnresolvedType.SOMETHING.resolve(world) }, world);
+ }
+}
--- /dev/null
+/* *******************************************************************
+ * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 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://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * PARC initial implementation
+ * ******************************************************************/
+
+package org.aspectj.weaver.patterns;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.TestShadow;
+import org.aspectj.weaver.TestUtils;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.VersionedDataInputStream;
+import org.aspectj.weaver.World;
+import org.aspectj.weaver.patterns.Bindings;
+import org.aspectj.weaver.patterns.FormalBinding;
+import org.aspectj.weaver.patterns.IScope;
+import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.SimpleScope;
+import org.aspectj.weaver.reflect.ReflectionWorld;
+
+public class WithinTestCase extends PatternsTestCase {
+
+ public World getWorld() {
+ return new ReflectionWorld(true, this.getClass().getClassLoader());
+ }
+
+ public void testMatch() throws IOException {
+ Shadow getOutFromArrayList = new TestShadow(Shadow.FieldGet, TestUtils
+ .fieldFromString("java.io.PrintStream java.lang.System.out"), UnresolvedType.forName("java.util.ArrayList"), world);
+
+ checkMatch(makePointcut("within(*)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.*)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.lang.*)"), getOutFromArrayList, FuzzyBoolean.NO);
+ checkMatch(makePointcut("within(java.util.List+)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.uti*.List+)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.uti*..*)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.*List)"), getOutFromArrayList, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.List*)"), getOutFromArrayList, FuzzyBoolean.NO);
+
+ Shadow getOutFromEntry = new TestShadow(Shadow.FieldGet, TestUtils
+ .fieldFromString("java.io.PrintStream java.lang.System.out"), UnresolvedType.forName("java.util.Map$Entry"), world);
+
+ checkMatch(makePointcut("within(*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.Map.*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util..*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.util.Map..*)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.lang.*)"), getOutFromEntry, FuzzyBoolean.NO);
+ checkMatch(makePointcut("within(java.util.List+)"), getOutFromEntry, FuzzyBoolean.NO);
+ checkMatch(makePointcut("within(java.util.Map+)"), getOutFromEntry, FuzzyBoolean.YES);
+ checkMatch(makePointcut("within(java.lang.Object+)"), getOutFromEntry, FuzzyBoolean.YES);
+
+ // this is something we should in type patterns tests
+ // checkMatch(makePointcut("within(*List)"), getOut, FuzzyBoolean.NO);
+
+ }
+
+ // public void testMatchJP() {
+ // Factory f = new Factory("WithinTestCase.java",WithinTestCase.class);
+ //
+ // JoinPoint.StaticPart inString = f.makeSJP(JoinPoint.CONSTRUCTOR_EXECUTION,f.makeConstructorSig(0,String.class,new Class[]
+ // {String.class},new String[]{"s"},new Class[0]),1);
+ // JoinPoint.StaticPart inObject = f.makeSJP(JoinPoint.CONSTRUCTOR_EXECUTION,f.makeConstructorSig(0,Object.class,new Class[]
+ // {},new String[]{},new Class[0]),1);
+ //
+ // Pointcut withinString = new PatternParser("within(String)").parsePointcut().resolve();
+ // Pointcut withinObject = new PatternParser("within(Object)").parsePointcut().resolve();
+ // Pointcut withinObjectPlus = new PatternParser("within(Object+)").parsePointcut().resolve();
+ //
+ // checkMatches(withinString,inString,FuzzyBoolean.YES);
+ // checkMatches(withinString,inObject,FuzzyBoolean.NO);
+ // checkMatches(withinObject,inString,FuzzyBoolean.NO);
+ // checkMatches(withinObject,inObject, FuzzyBoolean.YES);
+ // checkMatches(withinObjectPlus,inString,FuzzyBoolean.YES);
+ // checkMatches(withinObjectPlus,inObject,FuzzyBoolean.YES);
+ // }
+ //
+ // private void checkMatches(Pointcut p, JoinPoint.StaticPart jpsp, FuzzyBoolean expected) {
+ // assertEquals(expected,p.match(null,jpsp));
+ // }
+ //
+ public Pointcut makePointcut(String pattern) {
+ Pointcut pointcut0 = Pointcut.fromString(pattern);
+
+ Bindings bindingTable = new Bindings(0);
+ IScope scope = new SimpleScope(world, FormalBinding.NONE);
+
+ pointcut0.resolveBindings(scope, bindingTable);
+ Pointcut pointcut1 = pointcut0;
+ return pointcut1.concretize1(null, null, new IntMap());
+ }
+
+ private void checkMatch(Pointcut p, Shadow s, FuzzyBoolean shouldMatch) throws IOException {
+ FuzzyBoolean doesMatch = p.match(s);
+ assertEquals(p + " matches " + s, shouldMatch, doesMatch);
+ checkSerialization(p);
+ }
+
+ private void checkSerialization(Pointcut p) throws IOException {
+ ByteArrayOutputStream bo = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bo);
+ p.write(out);
+ out.close();
+
+ ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
+ VersionedDataInputStream in = new VersionedDataInputStream(bi);
+ Pointcut newP = Pointcut.read(in, null);
+
+ assertEquals("write/read", p, newP);
+ }
+
+}
+++ /dev/null
-/* *******************************************************************
- * Copyright (c) 2002-2008 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://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Andy Clement
- * ******************************************************************/
-package org.aspectj.weaver.reflect;
-
-import org.aspectj.weaver.CommonReferenceTypeTests;
-import org.aspectj.weaver.World;
-
-public class ReflectionWorldReferenceTypeTest extends CommonReferenceTypeTests {
-
- protected boolean getSupportsAutoboxing() {
- return false;
- }
-
- public World getWorld() {
- return new ReflectionWorld(false, getClass().getClassLoader());
- }
-
-}
--- /dev/null
+package org.aspectj.weaver.testcode;
+
+public class Aspect {
+
+ public static void ignoreMe() {
+ }
+
+ public static void before_method_call() {
+ System.out.println("before");
+ }
+
+ public static void afterReturning_method_call() {
+ System.out.println("afterReturning");
+ }
+
+ public static void afterThrowing_method_execution(Throwable t) {
+ System.out.println("afterThrowing " + t);
+ t.printStackTrace();
+ }
+
+}
--- /dev/null
+package org.aspectj.weaver.testcode;
+
+public class Base {
+
+ public static void onlyBase() {
+ }
+
+ public static void both() {
+ }
+
+ public void onlyBaseNonStatic() {
+ }
+
+ public void bothNonStatic() {
+ }
+
+ public int onlyBase;
+ public int both;
+
+ public Base() {
+ }
+
+ public Base(int i) {
+ }
+
+ public void m() throws CloneNotSupportedException {
+ }
+}
--- /dev/null
+package org.aspectj.weaver.testcode;
+
+import java.io.IOException;
+
+public class Derived extends Base {
+
+ public static void onlyDerived() throws IOException, CloneNotSupportedException {
+ }
+
+ public static void both() {
+ }
+
+ public void onlyDerivedNonStatic() {
+ }
+
+ public void bothNonStatic() {
+ }
+
+ public int onlyDerived;
+ public int both;
+
+ public Derived() {
+ }
+
+ public void m() {
+ }
+
+}