]> source.dussan.org Git - aspectj.git/commitdiff
246125: pulled tests from weaver into matcher and created bcel subtypes of matcher...
authoraclement <aclement>
Tue, 28 Oct 2008 20:33:12 +0000 (20:33 +0000)
committeraclement <aclement>
Tue, 28 Oct 2008 20:33:12 +0000 (20:33 +0000)
29 files changed:
org.aspectj.matcher/src/org/aspectj/weaver/patterns/WildTypePattern.java
org.aspectj.matcher/testsrc/org/aspectj/weaver/CommonReferenceTypeTests.java [deleted file]
org.aspectj.matcher/testsrc/org/aspectj/weaver/MatcherModuleTests.java
org.aspectj.matcher/testsrc/org/aspectj/weaver/TestShadow.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/TestUtils.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/AndOrNotTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ArgsTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DeclareErrorOrWarningTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/DumpPointcutVisitor.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ModifiersPatternTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/NamePatternParserTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/NamePatternTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PatternsTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PatternsTests.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/PointcutRewriterTest.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/SignaturePatternTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TestScope.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/ThisOrTargetTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternListTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/TypePatternTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/VisitorTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/WildTypePatternResolutionTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/patterns/WithinTestCase.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/reflect/ReflectionWorldReferenceTypeTest.java [deleted file]
org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Aspect.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Base.java [new file with mode: 0644]
org.aspectj.matcher/testsrc/org/aspectj/weaver/testcode/Derived.java [new file with mode: 0644]

index 73e36177d43d608a9e3005aef315518870ccef21..ab72026a120e4b4b729f976c37e79dbb00b86a97 100644 (file)
@@ -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 (file)
index c843697..0000000
+++ /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());
-       }
-
-}
index c0d52183b4d76bfa458cf9c6be6adfb38185bcd6..acb04c03f9d8b1ffe419c2fac357bf272a3ba25c 100644 (file)
@@ -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 (file)
index 0000000..761281a
--- /dev/null
@@ -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 (file)
index 0000000..456cd2b
--- /dev/null
@@ -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 (file)
index 0000000..70e192a
--- /dev/null
@@ -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 (file)
index 0000000..af16d09
--- /dev/null
@@ -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 (file)
index 0000000..7303191
--- /dev/null
@@ -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 (file)
index 0000000..bece962
--- /dev/null
@@ -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 (file)
index 0000000..ab3fdda
--- /dev/null
@@ -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 (file)
index 0000000..b680376
--- /dev/null
@@ -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 (file)
index 0000000..e6c5d39
--- /dev/null
@@ -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 (file)
index 0000000..91858de
--- /dev/null
@@ -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 (file)
index 0000000..27e3c8a
--- /dev/null
@@ -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 (file)
index 0000000..62a3c05
--- /dev/null
@@ -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 (file)
index 0000000..452f6a2
--- /dev/null
@@ -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 (file)
index 0000000..43a2620
--- /dev/null
@@ -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 (file)
index 0000000..433a440
--- /dev/null
@@ -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 (file)
index 0000000..e65bf27
--- /dev/null
@@ -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 (file)
index 0000000..c2bb0a5
--- /dev/null
@@ -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 (file)
index 0000000..fd3e8f2
--- /dev/null
@@ -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 (file)
index 0000000..15ccbbd
--- /dev/null
@@ -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 (file)
index 0000000..40d3935
--- /dev/null
@@ -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 (file)
index 0000000..35520fd
--- /dev/null
@@ -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 (file)
index 0000000..ccc117b
--- /dev/null
@@ -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 (file)
index 8f1fc07..0000000
+++ /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 (file)
index 0000000..95140c7
--- /dev/null
@@ -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 (file)
index 0000000..e580242
--- /dev/null
@@ -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 (file)
index 0000000..5d616d7
--- /dev/null
@@ -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() {
+       }
+
+}