diff options
author | aclement <aclement> | 2008-10-28 20:33:12 +0000 |
---|---|---|
committer | aclement <aclement> | 2008-10-28 20:33:12 +0000 |
commit | ad94bf289fb25c8425f59a051a8493a9c7771541 (patch) | |
tree | 325697c9a342556c0ccf34966398245c4f84ddcb | |
parent | f36c8f063502df6870ee70c43fe0b7443835390f (diff) | |
download | aspectj-ad94bf289fb25c8425f59a051a8493a9c7771541.tar.gz aspectj-ad94bf289fb25c8425f59a051a8493a9c7771541.zip |
246125: pulled tests from weaver into matcher and created bcel subtypes of matcher tests where appropriate
29 files changed, 5326 insertions, 737 deletions
diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildTypePattern.java b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildTypePattern.java index 73e36177d..ab72026a1 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildTypePattern.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildTypePattern.java @@ -10,7 +10,6 @@ * PARC initial implementation * ******************************************************************/ - package org.aspectj.weaver.patterns; import java.io.DataOutputStream; @@ -43,37 +42,26 @@ import org.aspectj.weaver.WeaverMessages; 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<?> * @@ -92,37 +80,38 @@ public class WildTypePattern extends TypePattern { 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; @@ -133,75 +122,72 @@ public class WildTypePattern extends TypePattern { 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... @@ -209,114 +195,118 @@ public class WildTypePattern extends TypePattern { 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; @@ -325,7 +315,7 @@ public class WildTypePattern extends TypePattern { } } } - + // 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) { @@ -333,149 +323,159 @@ public class WildTypePattern extends TypePattern { // 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; } @@ -485,25 +485,27 @@ public class WildTypePattern extends TypePattern { // 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(); @@ -511,10 +513,9 @@ public class WildTypePattern extends TypePattern { } 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; */ @@ -524,7 +525,7 @@ public class WildTypePattern extends TypePattern { } return null; } - + /** * If this type pattern has no '*' or '..' in it */ @@ -532,54 +533,53 @@ public class WildTypePattern extends TypePattern { 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; @@ -594,76 +594,75 @@ public class WildTypePattern extends TypePattern { * * 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); @@ -673,101 +672,104 @@ public class WildTypePattern extends TypePattern { 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); @@ -775,61 +777,67 @@ public class WildTypePattern extends TypePattern { } 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(); @@ -837,14 +845,14 @@ public class WildTypePattern extends TypePattern { 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()); } @@ -852,19 +860,19 @@ public class WildTypePattern extends TypePattern { } 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 @@ -880,29 +888,35 @@ public class WildTypePattern extends TypePattern { 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++) { @@ -911,29 +925,27 @@ public class WildTypePattern extends TypePattern { 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; } @@ -950,48 +962,46 @@ public class WildTypePattern extends TypePattern { } } 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; @@ -1000,7 +1010,7 @@ public class WildTypePattern extends TypePattern { this.typeParameters = typeParameters; this.sLoc = sLoc; } - + public void verify() { TypeVariable[] tvs = genericType.getTypeVariables(); TypePattern[] typeParamPatterns = typeParameters.getTypePatterns(); @@ -1008,28 +1018,25 @@ public class WildTypePattern extends TypePattern { 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)); } } } @@ -1037,47 +1044,47 @@ public class WildTypePattern extends TypePattern { } // 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(); } @@ -1086,108 +1093,125 @@ public class WildTypePattern extends TypePattern { * 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) */ @@ -1201,9 +1225,9 @@ public class WildTypePattern extends TypePattern { 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); @@ -1211,9 +1235,11 @@ public class WildTypePattern extends TypePattern { // 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++) { @@ -1221,69 +1247,69 @@ public class WildTypePattern extends TypePattern { } } } - + 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); + } } diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/CommonReferenceTypeTests.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/CommonReferenceTypeTests.java deleted file mode 100644 index c84369758..000000000 --- a/org.aspectj.matcher/testsrc/org/aspectj/weaver/CommonReferenceTypeTests.java +++ /dev/null @@ -1,69 +0,0 @@ -/* ******************************************************************* - * 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()); - } - -} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/MatcherModuleTests.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/MatcherModuleTests.java index c0d52183b..acb04c03f 100644 --- a/org.aspectj.matcher/testsrc/org/aspectj/weaver/MatcherModuleTests.java +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/MatcherModuleTests.java @@ -17,22 +17,22 @@ import junit.framework.Test; 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); - } - } diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/TestShadow.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/TestShadow.java new file mode 100644 index 000000000..761281a48 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/TestShadow.java @@ -0,0 +1,115 @@ +/* ******************************************************************* + * 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"); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/TestUtils.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/TestUtils.java new file mode 100644 index 000000000..456cd2bfc --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/TestUtils.java @@ -0,0 +1,304 @@ +/* ******************************************************************* + * 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()]); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/AndOrNotTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/AndOrNotTestCase.java new file mode 100644 index 000000000..70e192afe --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/AndOrNotTestCase.java @@ -0,0 +1,100 @@ +/* ******************************************************************* + * 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); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ArgsTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ArgsTestCase.java new file mode 100644 index 000000000..af16d09f6 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ArgsTestCase.java @@ -0,0 +1,198 @@ +/******************************************************************************* + * 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(*)"); + } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java new file mode 100644 index 000000000..7303191dd --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java @@ -0,0 +1,132 @@ +/* ******************************************************************* + * 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); + } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DeclareErrorOrWarningTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DeclareErrorOrWarningTestCase.java new file mode 100644 index 000000000..bece96251 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DeclareErrorOrWarningTestCase.java @@ -0,0 +1,63 @@ +/* ******************************************************************* + * 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); + } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DumpPointcutVisitor.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DumpPointcutVisitor.java new file mode 100644 index 000000000..ab3fddab0 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DumpPointcutVisitor.java @@ -0,0 +1,588 @@ +/* ******************************************************************* + * 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 diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ModifiersPatternTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ModifiersPatternTestCase.java new file mode 100644 index 000000000..b680376d7 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ModifiersPatternTestCase.java @@ -0,0 +1,111 @@ +/* ******************************************************************* + * 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()); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/NamePatternParserTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/NamePatternParserTestCase.java new file mode 100644 index 000000000..e6c5d3910 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/NamePatternParserTestCase.java @@ -0,0 +1,68 @@ +/* ******************************************************************* + * 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()); + } + } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/NamePatternTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/NamePatternTestCase.java new file mode 100644 index 000000000..91858de88 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/NamePatternTestCase.java @@ -0,0 +1,122 @@ +/* ******************************************************************* + * 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); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java new file mode 100644 index 000000000..27e3c8a22 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java @@ -0,0 +1,802 @@ +/* ******************************************************************* + * 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; + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PatternsTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PatternsTestCase.java new file mode 100644 index 000000000..62a3c0566 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PatternsTestCase.java @@ -0,0 +1,35 @@ +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(); +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PatternsTests.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PatternsTests.java new file mode 100644 index 000000000..452f6a26e --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PatternsTests.java @@ -0,0 +1,66 @@ +/* ******************************************************************* + * 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); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PointcutRewriterTest.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PointcutRewriterTest.java new file mode 100644 index 000000000..43a26208c --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PointcutRewriterTest.java @@ -0,0 +1,454 @@ +/* ******************************************************************* + * 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(); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/SignaturePatternTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/SignaturePatternTestCase.java new file mode 100644 index 000000000..433a44070 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/SignaturePatternTestCase.java @@ -0,0 +1,162 @@ +/* ******************************************************************* + * 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); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TestScope.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TestScope.java new file mode 100644 index 000000000..e65bf2797 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TestScope.java @@ -0,0 +1,32 @@ +/* ******************************************************************* + * 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)); + } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ThisOrTargetTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ThisOrTargetTestCase.java new file mode 100644 index 000000000..c2bb0a5d0 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ThisOrTargetTestCase.java @@ -0,0 +1,157 @@ +/* ******************************************************************* + * 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); + // } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternListTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternListTestCase.java new file mode 100644 index 000000000..fd3e8f23e --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternListTestCase.java @@ -0,0 +1,175 @@ +/* ******************************************************************* + * 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); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java new file mode 100644 index 000000000..15ccbbd03 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java @@ -0,0 +1,260 @@ +/* ******************************************************************* + * 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); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/VisitorTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/VisitorTestCase.java new file mode 100644 index 000000000..40d39359e --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/VisitorTestCase.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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()); + } + } + } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/WildTypePatternResolutionTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/WildTypePatternResolutionTestCase.java new file mode 100644 index 000000000..35520fd91 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/WildTypePatternResolutionTestCase.java @@ -0,0 +1,433 @@ +/* ******************************************************************* + * 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); + } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/WithinTestCase.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/WithinTestCase.java new file mode 100644 index 000000000..ccc117b02 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/WithinTestCase.java @@ -0,0 +1,126 @@ +/* ******************************************************************* + * 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); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/reflect/ReflectionWorldReferenceTypeTest.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/reflect/ReflectionWorldReferenceTypeTest.java deleted file mode 100644 index 8f1fc07a2..000000000 --- a/org.aspectj.matcher/testsrc/org/aspectj/weaver/reflect/ReflectionWorldReferenceTypeTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/* ******************************************************************* - * 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()); - } - -} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Aspect.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Aspect.java new file mode 100644 index 000000000..95140c792 --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Aspect.java @@ -0,0 +1,21 @@ +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(); + } + +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Base.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Base.java new file mode 100644 index 000000000..e580242be --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Base.java @@ -0,0 +1,28 @@ +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 { + } +} diff --git a/org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Derived.java b/org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Derived.java new file mode 100644 index 000000000..5d616d79d --- /dev/null +++ b/org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Derived.java @@ -0,0 +1,28 @@ +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() { + } + +} |