]> source.dussan.org Git - aspectj.git/commitdiff
first batch of updates for generics :- largely parsing plus storage of type variable...
authoracolyer <acolyer>
Thu, 9 Jun 2005 14:44:30 +0000 (14:44 +0000)
committeracolyer <acolyer>
Thu, 9 Jun 2005 14:44:30 +0000 (14:44 +0000)
81 files changed:
weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java
weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java
weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/AndPointcut.java
weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java
weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java
weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java
weaver/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java
weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java
weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java
weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java
weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java
weaver/src/org/aspectj/weaver/patterns/DeclareAnnotation.java
weaver/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java
weaver/src/org/aspectj/weaver/patterns/DeclareParents.java
weaver/src/org/aspectj/weaver/patterns/DeclarePrecedence.java
weaver/src/org/aspectj/weaver/patterns/DeclareSoft.java
weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java
weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java
weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java
weaver/src/org/aspectj/weaver/patterns/IfPointcut.java
weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java
weaver/src/org/aspectj/weaver/patterns/ModifiersPattern.java
weaver/src/org/aspectj/weaver/patterns/NamePattern.java
weaver/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/NotPointcut.java
weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java
weaver/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/OrPointcut.java
weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java
weaver/src/org/aspectj/weaver/patterns/PatternNode.java
weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/patterns/PatternParser.java
weaver/src/org/aspectj/weaver/patterns/PerCflow.java
weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java
weaver/src/org/aspectj/weaver/patterns/PerObject.java
weaver/src/org/aspectj/weaver/patterns/PerSingleton.java
weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java
weaver/src/org/aspectj/weaver/patterns/Pointcut.java
weaver/src/org/aspectj/weaver/patterns/PointcutVisitor.java [deleted file]
weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java
weaver/src/org/aspectj/weaver/patterns/ScopeWithTypeVariables.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java
weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java
weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java
weaver/src/org/aspectj/weaver/patterns/TypePattern.java
weaver/src/org/aspectj/weaver/patterns/TypePatternList.java
weaver/src/org/aspectj/weaver/patterns/TypeVariable.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/patterns/TypeVariablePatternList.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java
weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java
weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java
weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java
weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java
weaver/src/org/aspectj/weaver/tools/PointcutExpression.java
weaver/src/org/aspectj/weaver/tools/PointcutPrimitive.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/tools/PointcutPrimitives.java [deleted file]
weaver/src/org/aspectj/weaver/tools/UnsupportedPointcutPrimitiveException.java [new file with mode: 0644]
weaver/testdata/dummyAspect.jar
weaver/testdata/ltw-acaspects.jar
weaver/testdata/ltw-aspects.jar
weaver/testdata/ltw-classes.jar
weaver/testdata/ltw-deaspects.jar
weaver/testdata/ltw-dwaspects.jar
weaver/testdata/ltw-itdaspects.jar
weaver/testdata/ltw-peraspects.jar
weaver/testdata/ltw-woven.jar
weaver/testdata/megatrace.jar
weaver/testdata/megatrace0easy.jar
weaver/testdata/megatrace0hard.jar
weaver/testdata/megatraceNoweave.jar
weaver/testdata/tracing.jar
weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java
weaver/testsrc/org/aspectj/weaver/patterns/PointcutTestCase.java
weaver/testsrc/org/aspectj/weaver/patterns/VisitorTestCase.java
weaver/testsrc/org/aspectj/weaver/tools/PointcutExpressionTest.java

index a310f083802423db88238af964b1f72288309614..f3a8cf88f30b34716a86dc049a3a222869eaf2d9 100644 (file)
  *******************************************************************************/
 package org.aspectj.weaver.bcel;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
 import org.aspectj.apache.bcel.classfile.Attribute;
 import org.aspectj.apache.bcel.classfile.Field;
 import org.aspectj.apache.bcel.classfile.JavaClass;
@@ -24,46 +30,38 @@ import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations;
 import org.aspectj.apache.bcel.generic.Type;
 import org.aspectj.bridge.IMessage;
 import org.aspectj.bridge.IMessageHandler;
-import org.aspectj.bridge.Message;
 import org.aspectj.bridge.ISourceLocation;
-import org.aspectj.bridge.SourceLocation;
+import org.aspectj.bridge.Message;
 import org.aspectj.weaver.Advice;
 import org.aspectj.weaver.AdviceKind;
 import org.aspectj.weaver.AjAttribute;
 import org.aspectj.weaver.AjcMemberMaker;
+import org.aspectj.weaver.IHasPosition;
 import org.aspectj.weaver.ISourceContext;
 import org.aspectj.weaver.NameMangler;
 import org.aspectj.weaver.ResolvedPointcutDefinition;
 import org.aspectj.weaver.ResolvedTypeX;
 import org.aspectj.weaver.TypeX;
-import org.aspectj.weaver.IHasPosition;
+import org.aspectj.weaver.patterns.AndPointcut;
 import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
 import org.aspectj.weaver.patterns.DeclarePrecedence;
 import org.aspectj.weaver.patterns.FormalBinding;
 import org.aspectj.weaver.patterns.IScope;
+import org.aspectj.weaver.patterns.IdentityPointcutVisitor;
+import org.aspectj.weaver.patterns.IfPointcut;
+import org.aspectj.weaver.patterns.NotPointcut;
+import org.aspectj.weaver.patterns.OrPointcut;
 import org.aspectj.weaver.patterns.ParserException;
 import org.aspectj.weaver.patterns.PatternParser;
 import org.aspectj.weaver.patterns.PerCflow;
 import org.aspectj.weaver.patterns.PerClause;
+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.SimpleScope;
 import org.aspectj.weaver.patterns.TypePattern;
-import org.aspectj.weaver.patterns.PerFromSuper;
-import org.aspectj.weaver.patterns.PointcutVisitor;
-import org.aspectj.weaver.patterns.IdentityPointcutVisitor;
-import org.aspectj.weaver.patterns.IfPointcut;
-import org.aspectj.weaver.patterns.AndPointcut;
-import org.aspectj.weaver.patterns.NotPointcut;
-import org.aspectj.weaver.patterns.OrPointcut;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
 
 /**
  * Annotation defined aspect reader.
index 046cf5a61fae26023eb17cc8f99c4cb3ff138184..8757cae3feb75d058cd7f9bc06b11dcba49f62c0 100644 (file)
@@ -15,7 +15,17 @@ import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 
 import org.aspectj.lang.JoinPoint;
+import org.aspectj.weaver.patterns.AbstractPatternNodeVisitor;
+import org.aspectj.weaver.patterns.ArgsAnnotationPointcut;
+import org.aspectj.weaver.patterns.ArgsPointcut;
+import org.aspectj.weaver.patterns.CflowPointcut;
+import org.aspectj.weaver.patterns.FastMatchInfo;
+import org.aspectj.weaver.patterns.IfPointcut;
+import org.aspectj.weaver.patterns.NotAnnotationTypePattern;
+import org.aspectj.weaver.patterns.NotPointcut;
 import org.aspectj.weaver.patterns.Pointcut;
+import org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut;
+import org.aspectj.weaver.patterns.ThisOrTargetPointcut;
 import org.aspectj.weaver.tools.FuzzyBoolean;
 import org.aspectj.weaver.tools.PointcutExpression;
 
@@ -31,6 +41,16 @@ public class PointcutExpressionImpl implements PointcutExpression {
                this.pointcut = pointcut;
                this.expression = expression;
        }
+       
+       public boolean couldMatchJoinPointsInType(Class aClass) {
+               return pointcut.fastMatch(aClass).maybeTrue();
+       }
+       
+       public boolean mayNeedDynamicTest() {
+               HasPossibleDynamicContentVisitor visitor = new HasPossibleDynamicContentVisitor();
+               pointcut.traverse(visitor, null);
+               return visitor.hasDynamicContent();
+       }
 
        /* (non-Javadoc)
         * @see org.aspectj.weaver.tools.PointcutExpression#matchesMethodCall(java.lang.reflect.Method, java.lang.Class, java.lang.Class, java.lang.reflect.Member)
@@ -193,6 +213,50 @@ public class PointcutExpressionImpl implements PointcutExpression {
                throw new IllegalArgumentException("Cant match FuzzyBoolean " + fb);
        }
        
+       private static class HasPossibleDynamicContentVisitor extends AbstractPatternNodeVisitor {
+               private boolean hasDynamicContent = false;
+               
+               public boolean hasDynamicContent() { return hasDynamicContent; }
+               
+               public Object visit(ArgsAnnotationPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(ArgsPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+
+               public Object visit(CflowPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(IfPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(NotAnnotationTypePattern node, Object data) {
+                       return node.getNegatedPattern().accept(this, data);
+               }
+               
+               public Object visit(NotPointcut node, Object data) {
+                       return node.getNegatedPointcut().accept(this, data);
+               }
+               
+               public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+               
+               public Object visit(ThisOrTargetPointcut node, Object data) {
+                       hasDynamicContent = true;
+                       return null;
+               }
+       }
+       
        public static class Handler implements Member {
 
                private Class decClass;
diff --git a/weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java b/weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java
new file mode 100644 (file)
index 0000000..11c4ea6
--- /dev/null
@@ -0,0 +1,407 @@
+/* *******************************************************************
+ * 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.patterns;
+
+import org.aspectj.weaver.patterns.Pointcut.MatchesNothingPointcut;
+
+/**
+ * @author colyer
+ *
+ */
+public abstract class AbstractPatternNodeVisitor implements PatternNodeVisitor {
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.AnyTypePattern, java.lang.Object)
+        */
+       public Object visit(AnyTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.NoTypePattern, java.lang.Object)
+        */
+       public Object visit(NoTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.EllipsisTypePattern, java.lang.Object)
+        */
+       public Object visit(EllipsisTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.AnyWithAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(AnyWithAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.AnyAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(AnyAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.EllipsisAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(EllipsisAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.AndAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(AndAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.AndPointcut, java.lang.Object)
+        */
+       public Object visit(AndPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.AndTypePattern, java.lang.Object)
+        */
+       public Object visit(AndTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.AnnotationPatternList, java.lang.Object)
+        */
+       public Object visit(AnnotationPatternList node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.AnnotationPointcut, java.lang.Object)
+        */
+       public Object visit(AnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ArgsAnnotationPointcut, java.lang.Object)
+        */
+       public Object visit(ArgsAnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ArgsPointcut, java.lang.Object)
+        */
+       public Object visit(ArgsPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.BindingAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(BindingAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.BindingTypePattern, java.lang.Object)
+        */
+       public Object visit(BindingTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.CflowPointcut, java.lang.Object)
+        */
+       public Object visit(CflowPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ConcreteCflowPointcut, java.lang.Object)
+        */
+       public Object visit(ConcreteCflowPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclareAnnotation, java.lang.Object)
+        */
+       public Object visit(DeclareAnnotation node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclareErrorOrWarning, java.lang.Object)
+        */
+       public Object visit(DeclareErrorOrWarning node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclareParents, java.lang.Object)
+        */
+       public Object visit(DeclareParents node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclarePrecedence, java.lang.Object)
+        */
+       public Object visit(DeclarePrecedence node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.DeclareSoft, java.lang.Object)
+        */
+       public Object visit(DeclareSoft node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ExactAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(ExactAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ExactTypePattern, java.lang.Object)
+        */
+       public Object visit(ExactTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.HandlerPointcut, java.lang.Object)
+        */
+       public Object visit(HandlerPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.IfPointcut, java.lang.Object)
+        */
+       public Object visit(IfPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.KindedPointcut, java.lang.Object)
+        */
+       public Object visit(KindedPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ModifiersPattern, java.lang.Object)
+        */
+       public Object visit(ModifiersPattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.NamePattern, java.lang.Object)
+        */
+       public Object visit(NamePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.NotAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(NotAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.NotPointcut, java.lang.Object)
+        */
+       public Object visit(NotPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.NotTypePattern, java.lang.Object)
+        */
+       public Object visit(NotTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.OrAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(OrAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.OrPointcut, java.lang.Object)
+        */
+       public Object visit(OrPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.OrTypePattern, java.lang.Object)
+        */
+       public Object visit(OrTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerCflow, java.lang.Object)
+        */
+       public Object visit(PerCflow node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerFromSuper, java.lang.Object)
+        */
+       public Object visit(PerFromSuper node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerObject, java.lang.Object)
+        */
+       public Object visit(PerObject node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerSingleton, java.lang.Object)
+        */
+       public Object visit(PerSingleton node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PerTypeWithin, java.lang.Object)
+        */
+       public Object visit(PerTypeWithin node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.PatternNode, java.lang.Object)
+        */
+       public Object visit(PatternNode node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ReferencePointcut, java.lang.Object)
+        */
+       public Object visit(ReferencePointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.SignaturePattern, java.lang.Object)
+        */
+       public Object visit(SignaturePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ThisOrTargetAnnotationPointcut, java.lang.Object)
+        */
+       public Object visit(ThisOrTargetAnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ThisOrTargetPointcut, java.lang.Object)
+        */
+       public Object visit(ThisOrTargetPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.ThrowsPattern, java.lang.Object)
+        */
+       public Object visit(ThrowsPattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.TypePatternList, java.lang.Object)
+        */
+       public Object visit(TypePatternList node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WildAnnotationTypePattern, java.lang.Object)
+        */
+       public Object visit(WildAnnotationTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WildTypePattern, java.lang.Object)
+        */
+       public Object visit(WildTypePattern node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WithinAnnotationPointcut, java.lang.Object)
+        */
+       public Object visit(WithinAnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WithinCodeAnnotationPointcut, java.lang.Object)
+        */
+       public Object visit(WithinCodeAnnotationPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WithinPointcut, java.lang.Object)
+        */
+       public Object visit(WithinPointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.WithincodePointcut, java.lang.Object)
+        */
+       public Object visit(WithincodePointcut node, Object data) {
+               return node;
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.PointcutVisitor#visit(org.aspectj.weaver.patterns.Pointcut.MatchesNothingPointcut, java.lang.Object)
+        */
+       public Object visit(MatchesNothingPointcut node, Object data) {
+               return node;
+       }
+
+       public Object visit(TypeVariable node, Object data) {
+               return node;
+       }
+       
+       public Object visit(TypeVariablePatternList node, Object data) {
+               return node;
+       }
+}
index 077840632d1c6f81206a4bfce58870f150f9b773..4635051b234d815d5d792d634bcc58ae611e4881 100644 (file)
@@ -89,7 +89,14 @@ public class AndAnnotationTypePattern extends AnnotationTypePattern {
        public AnnotationTypePattern getLeft() { return left; }
        public AnnotationTypePattern getRight() { return right; }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor,ret);
+               right.traverse(visitor,ret);
+               return ret;
+       }
 }
index a688e66b9f41780a1bbd599f2c7fced7409e3506..e389d5a256c1fe79d25686f510c093fade0c6b01 100644 (file)
@@ -51,6 +51,10 @@ public class AndPointcut extends Pointcut {
        public FuzzyBoolean fastMatch(FastMatchInfo type) {
                return left.fastMatch(type).and(right.fastMatch(type));
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return left.fastMatch(targetType).and(right.fastMatch(targetType));
+       }
 
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                FuzzyBoolean leftMatch = left.match(shadow);
@@ -146,7 +150,14 @@ public class AndPointcut extends Pointcut {
                return right;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor,ret);
+               right.traverse(visitor,ret);
+               return ret;
+       }
 }
index cf547c2358a0e0b01a289c82061d64e6403d92ed..bc150b1d32b739c027f3b03921370efb033b048b 100644 (file)
@@ -169,8 +169,15 @@ public class AndTypePattern extends TypePattern {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor, ret);
+               right.traverse(visitor, ret);
+               return ret;
+       }
 
 }
index 75dbb73a8a5a43bd5f66335ef2c658a2ff4cd8a3..d9cbd07d6b221144850278ef029668ae9687d268 100644 (file)
@@ -177,8 +177,16 @@ public class AnnotationPatternList extends PatternNode {
                writeLocation(s);
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor, data);
+               for (int i = 0; i < typePatterns.length; i++) {
+                       typePatterns[i].traverse(visitor,ret);
+               }
+               return ret;
+       }
 
 }
index 586056a240c54e599ca5ed6bcd6da735f08afca9..17a6da36f77eab33bb9b27ebec950abbab93382a 100644 (file)
@@ -92,6 +92,11 @@ public class AnnotationPointcut extends NameBindingPointcut {
                        return FuzzyBoolean.MAYBE;
                }
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               // TODO AMC
+               return FuzzyBoolean.MAYBE;
+       }
 
        /* (non-Javadoc)
         * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
@@ -266,7 +271,7 @@ public class AnnotationPointcut extends NameBindingPointcut {
                return buf.toString();
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 
index 831c6f8c46d5d1384ab207a970b44a26b175470b..c814ba0dfeef2f41b562c893f41d5916d7edf268 100644 (file)
@@ -100,7 +100,7 @@ class AnyAnnotationTypePattern extends AnnotationTypePattern {
        
        public String toString() { return "@ANY"; }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
     
@@ -121,7 +121,7 @@ class EllipsisAnnotationTypePattern extends AnnotationTypePattern {
 
        public String toString() { return ".."; }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
     
index f60f644465a23ac72ec1112c4dd4682cae2d2e31..de271b5f500751e25d493efc2b876a121fef36a7 100644 (file)
@@ -63,6 +63,10 @@ public class ArgsAnnotationPointcut extends NameBindingPointcut {
        public FuzzyBoolean fastMatch(FastMatchInfo info) {
                return FuzzyBoolean.MAYBE;
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
 
        /* (non-Javadoc)
         * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
@@ -221,7 +225,7 @@ public class ArgsAnnotationPointcut extends NameBindingPointcut {
         return buf.toString();
     }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index eebacd0840f90092758f8c3bf30ef2a92c38f4a3..5001fd06cd381ced5cad5771621f4ea8e0c68c20 100644 (file)
@@ -69,6 +69,10 @@ public class ArgsPointcut extends NameBindingPointcut {
     public FuzzyBoolean fastMatch(FastMatchInfo type) {
                return FuzzyBoolean.MAYBE;
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
 
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                FuzzyBoolean ret =
@@ -308,7 +312,7 @@ public class ArgsPointcut extends NameBindingPointcut {
                return "args" + arguments.toString() + "";
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index a1141353913fcc6ee8324ebc2f8a450ff0d051ef..1ae2c38fecbdf125fa598fe18c83dda88ef8d010 100644 (file)
@@ -104,6 +104,9 @@ public class BasicTokenSource implements ITokenSource {
                                case '!':
                                case ':':
                                case '@':
+                               case '<':
+                               case '>':
+                               case    '?':
                                    tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1));
                                    continue;
                                case '.':
@@ -123,6 +126,11 @@ public class BasicTokenSource implements ITokenSource {
                                        }
                                        continue;
                                case '&':
+                                       if ((i+1) <= chars.length && chars[i] != '&') {
+                                               tokens.add(BasicToken.makeOperator(makeString(ch),i-1,i-1));
+                                               continue;
+                                       }
+                                       // fall-through
                                case '|':
                                    if (i == chars.length) {
                                        throw new BCException("bad " + ch);
index 4c1c13d7b8893fbb4a51fa1b6dcdb7e2186735c4..13ed1b6f6f4bb2027a57a575462053ddd977ba46 100644 (file)
@@ -44,7 +44,7 @@ import org.aspectj.weaver.ast.Test;
 
 public class CflowPointcut extends Pointcut {
        private Pointcut entry; // The pointcut inside the cflow() that represents the 'entry' point
-       private boolean isBelow;// Is this cflowbelow?
+       boolean isBelow;// Is this cflowbelow?
        private int[] freeVars;
        
        private static Hashtable cflowFields = new Hashtable();
@@ -68,9 +68,12 @@ public class CflowPointcut extends Pointcut {
                this.pointcutKind = CFLOW;
        }
 
-    public boolean isBelow() {
-        return isBelow;
-    }
+       /**
+        * @return Returns true is this is a cflowbelow pointcut
+        */
+       public boolean isCflowBelow() {
+               return isBelow;
+       }
 
        public Set couldMatchKinds() {
                return Shadow.ALL_SHADOW_KINDS;
@@ -84,6 +87,10 @@ public class CflowPointcut extends Pointcut {
     public FuzzyBoolean fastMatch(FastMatchInfo type) {
                return FuzzyBoolean.MAYBE;
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
     
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                //??? this is not maximally efficient
@@ -312,8 +319,7 @@ public class CflowPointcut extends Pointcut {
                }
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
-    }
-
+       }
 }
index 360b6456f8f68b19fd3acad45d3b6c873f936167..f704d7305b9469a32f316060452f114499bf29e2 100644 (file)
@@ -51,6 +51,10 @@ public class ConcreteCflowPointcut extends Pointcut {
     public FuzzyBoolean fastMatch(FastMatchInfo type) {
                return FuzzyBoolean.MAYBE;
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
     
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                //??? this is not maximally efficient
@@ -140,7 +144,7 @@ public class ConcreteCflowPointcut extends Pointcut {
                throw new RuntimeException("unimplemented");
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 
index 55db910a7d6a935c963cd0420a037a81d8985399..a3913f7357aefb262f28999aa60fbb14f0f4e0f9 100644 (file)
@@ -99,6 +99,10 @@ public class DeclareAnnotation extends Declare {
                return ret.toString();
        }
        
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public void resolve(IScope scope) {
                if (typePattern != null) {
                        typePattern = typePattern.resolveBindings(scope,Bindings.NONE,false,false);
index a3bebe50c7105094e8a24e01959405a0ce723427..a053ae8e1d94000118adf844e82746926068258d 100644 (file)
@@ -58,7 +58,10 @@ public class DeclareErrorOrWarning extends Declare {
         return result;
     }
 
-
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public void write(DataOutputStream s) throws IOException {
                s.writeByte(Declare.ERROR_OR_WARNING);
                s.writeBoolean(isError);
index 3607afe7df571942bf16c4c726e01d7929336df7..ef228d43d192c99bd17dae729282a5b422041cd4 100644 (file)
@@ -20,6 +20,7 @@ import java.util.Collections;
 import java.util.List;
 
 import org.aspectj.bridge.IMessage;
+import org.aspectj.weaver.AjAttribute;
 import org.aspectj.weaver.ISourceContext;
 import org.aspectj.weaver.ResolvedTypeX;
 import org.aspectj.weaver.TypeX;
@@ -31,6 +32,7 @@ public class DeclareParents extends Declare {
        private TypePattern child;
        private TypePatternList parents;
        private boolean isWildChild = false;
+       private TypeVariablePatternList typeVariablesInScope = TypeVariablePatternList.EMPTY; // AspectJ 5 extension for generic types
        
 
        public DeclareParents(TypePattern child, List parents) {
@@ -43,6 +45,14 @@ public class DeclareParents extends Declare {
                if (child instanceof WildTypePattern) isWildChild = true;
        }
        
+       public TypeVariablePatternList getTypeParameters() {
+               return this.typeVariablesInScope;
+       }
+       
+       public void setTypeParameters(TypeVariablePatternList typeParameters) {
+               this.typeVariablesInScope = typeParameters;
+       }
+       
        public boolean match(ResolvedTypeX typeX) {
                if (!child.matchesStatically(typeX)) return false;
                if (typeX.getWorld().getLint().typeNotExposedToWeaver.isEnabled() &&
@@ -54,6 +64,10 @@ public class DeclareParents extends Declare {
                return true;
        }
        
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public String toString() {
                StringBuffer buf = new StringBuffer();
                buf.append("declare parents: ");
@@ -83,11 +97,15 @@ public class DeclareParents extends Declare {
                s.writeByte(Declare.PARENTS);
                child.write(s);
                parents.write(s);
+               typeVariablesInScope.write(s);  // change to binary form in AJ 5
                writeLocation(s);
        }
 
        public static Declare read(VersionedDataInputStream s, ISourceContext context) throws IOException {
-               Declare ret = new DeclareParents(TypePattern.read(s, context), TypePatternList.read(s, context));
+               DeclareParents ret = new DeclareParents(TypePattern.read(s, context), TypePatternList.read(s, context));
+               if (s.getMajorVersion()>=AjAttribute.WeaverVersionInfo.WEAVER_VERSION_MAJOR_AJ150) {
+                       ret.setTypeParameters(TypeVariablePatternList.read(s,context));
+               }
                ret.readLocation(context, s);
                return ret;
        }
@@ -106,8 +124,9 @@ public class DeclareParents extends Declare {
        }
        
     public void resolve(IScope scope) {
-       child = child.resolveBindings(scope, Bindings.NONE, false, false);
-       parents = parents.resolveBindings(scope, Bindings.NONE, false, true); 
+               ScopeWithTypeVariables resolutionScope = new ScopeWithTypeVariables(typeVariablesInScope,scope);
+       child = child.resolveBindings(resolutionScope, Bindings.NONE, false, false);
+       parents = parents.resolveBindings(resolutionScope, Bindings.NONE, false, true); 
 
 //      Could assert this ...
 //             for (int i=0; i < parents.size(); i++) {
index 0bc548c8c49a60ceb7a52d98ada4f47e33300820..2dd5fb83d21afa68f46e5970d41232f2b7ccd9f2 100644 (file)
@@ -35,6 +35,10 @@ public class DeclarePrecedence extends Declare {
                this.patterns = patterns;
        }
        
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public String toString() {
                StringBuffer buf = new StringBuffer();
                buf.append("declare precedence: ");
index a7bb8fade57e72bbb1b4fafbdf41eabd34043316..9ed15111fde07432646a894d6165f7074f376643 100644 (file)
@@ -32,6 +32,10 @@ public class DeclareSoft extends Declare {
                this.pointcut = pointcut;
        }
        
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public String toString() {
                StringBuffer buf = new StringBuffer();
                buf.append("declare soft: ");
index 8e980203e35b5ef2d2ccaba1f17cfebaa24fb8b6..a93cab6bbd3514785152658fc693345cbf7168eb 100644 (file)
@@ -226,7 +226,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index eb3cececa88a97572d6de51d0809bff76d6eee91..5703251a8a2c246e9c19dc3981176c74f69da1f5 100644 (file)
@@ -208,6 +208,7 @@ public class ExactTypePattern extends TypePattern {
                out.writeBoolean(includeSubtypes);
                out.writeBoolean(isVarArgs);
                annotationPattern.write(out);
+               typeParameters.write(out);
                writeLocation(out);
        }
        
@@ -224,6 +225,7 @@ public class ExactTypePattern extends TypePattern {
                if (version > EXACT_VERSION) throw new BCException("ExactTypePattern was written by a more recent version of AspectJ");
                TypePattern ret = new ExactTypePattern(TypeX.read(s), s.readBoolean(), s.readBoolean());
                ret.setAnnotationTypePattern(AnnotationTypePattern.read(s,context));
+               ret.setTypeParameters(TypePatternList.read(s,context));
                ret.readLocation(context, s);
                return ret;
        }
@@ -262,7 +264,7 @@ public class ExactTypePattern extends TypePattern {
                throw new IllegalStateException("trying to re-resolve");
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 
index 8cc32353c6ba928338296aca34275206bc4df2b2..9f8752ad11af358dffeed6da133aaa526319fff4 100644 (file)
@@ -58,6 +58,10 @@ public class HandlerPointcut extends Pointcut {
                return FuzzyBoolean.MAYBE;
        }
        
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
+       
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                if (shadow.getKind() != Shadow.ExceptionHandler) return FuzzyBoolean.NO;
                
@@ -157,7 +161,7 @@ public class HandlerPointcut extends Pointcut {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index a05fe013f5c296da0ce098fde3edb3e04b9b7f62..90a302d1b0838998ca3a7596a597ec760ac56c1b 100644 (file)
@@ -14,7 +14,7 @@ package org.aspectj.weaver.patterns;
 /**
  * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
  */
-public class IdentityPointcutVisitor implements PointcutVisitor {
+public class IdentityPointcutVisitor implements PatternNodeVisitor {
 
     public Object visit(AnyTypePattern node, Object data) {
         return node;
@@ -231,4 +231,12 @@ public class IdentityPointcutVisitor implements PointcutVisitor {
     public Object visit(Pointcut.MatchesNothingPointcut node, Object data) {
         return node;
     }
+
+       public Object visit(TypeVariable node, Object data) {
+               return node;
+       }
+
+       public Object visit(TypeVariablePatternList node, Object data) {
+               return node;
+       }
 }
index 9aa1246f2e4c927b13c80a60825e24b24b6d380b..d6cf9fa84f05b95385dccc2c15a57468bfbdb94b 100644 (file)
@@ -79,6 +79,10 @@ public class IfPointcut extends Pointcut {
        public FuzzyBoolean fastMatch(FastMatchInfo type) {
                return FuzzyBoolean.MAYBE;
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
     
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                //??? this is not maximally efficient
@@ -383,7 +387,7 @@ public class IfPointcut extends Pointcut {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 
index 8951931f6cf3bf16bda8b5735253420cafec39a0..f6c4ef83517ce4d3cd77648965a45606432052ee 100644 (file)
@@ -98,6 +98,11 @@ public class KindedPointcut extends Pointcut {
                return FuzzyBoolean.MAYBE;
        }       
        
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.fromBoolean(signature.couldMatch(targetType));
+       }
+
+       
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                if (shadow.getKind() != kind) return FuzzyBoolean.NO;
 
@@ -314,7 +319,7 @@ public class KindedPointcut extends Pointcut {
                return kind;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index a3f5eedcee7a9a08e890091c5dcb3d553a8e0dd5..f1543af1e2f2c6fdbef76097cdb074ec8c140b57 100644 (file)
@@ -93,7 +93,7 @@ public class ModifiersPattern extends PatternNode {
                return flag.intValue();
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index a2879b1ea14587919bb2c41d16cb6be3ab6ac050..45f4b154ac31032c21697c74b7d872e50e9b9822 100644 (file)
@@ -158,7 +158,7 @@ public class NamePattern extends PatternNode {
                return starCount == 1 && pattern.length == 1;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index 37acaa16b0a831f0ef012694e885a20932d7c1b2..5e02931583a5772d763921b64443ba79fc74163c 100644 (file)
@@ -84,7 +84,13 @@ public class NotAnnotationTypePattern extends AnnotationTypePattern {
                return negatedPattern;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               negatedPattern.traverse(visitor,ret);
+               return ret;
+       }
 }
index 47baa7acfeb31f98a5aeb6b283aa4c6ef7e3281b..f042f0f8240ade9f10e103b7823d9a724d8fb749 100644 (file)
@@ -49,6 +49,10 @@ public class NotPointcut extends Pointcut {
        public FuzzyBoolean fastMatch(FastMatchInfo type) {
                return body.fastMatch(type).not();
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return body.fastMatch(targetType).not();
+       }
 
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                return body.match(shadow).not();
@@ -133,8 +137,14 @@ public class NotPointcut extends Pointcut {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               this.body.traverse(visitor,ret);
+               return ret;
+       }
 
 }
index e8dba6cb211078221ff3ccf9b2d6e7e9d50fc918..7affe0aa3e2f0d33f23c923aa8f21cb756fc7e1d 100644 (file)
@@ -150,7 +150,14 @@ public class NotTypePattern extends TypePattern {
                return 17 + 37 * negatedPattern.hashCode();
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               negatedPattern.traverse(visitor, ret);
+               return ret;
+       }
+
 }
index 6bdf616e418fb4567e02b9fd40d0921fad6b2bc9..562fafe0038ba28384c4a860fe38271b23d7c3e3 100644 (file)
@@ -48,6 +48,17 @@ public class OrAnnotationTypePattern extends AnnotationTypePattern {
                return this;
        }
 
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor,ret);
+               right.traverse(visitor,ret);
+               return ret;
+       }
+       
        public static AnnotationTypePattern read(VersionedDataInputStream s, ISourceContext context) throws IOException {
                AnnotationTypePattern p = new OrAnnotationTypePattern(
                                AnnotationTypePattern.read(s,context),
index 12abd441b3ec57698cdba62833abd18e3c92a996..13317fe3849350a018ad8b488a5fdebccd57c361 100644 (file)
@@ -50,6 +50,10 @@ public class OrPointcut extends Pointcut {
                return left.fastMatch(type).or(right.fastMatch(type));
        }
 
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return left.fastMatch(targetType).or(right.fastMatch(targetType));
+       }
+       
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                FuzzyBoolean leftMatch = left.match(shadow);
                if (leftMatch.alwaysTrue()) return leftMatch;
@@ -148,7 +152,14 @@ public class OrPointcut extends Pointcut {
                return right;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor, ret);
+               right.traverse(visitor,ret);
+               return ret;
+       }
 }
index 16fe35872efd52b667b61d64ed1270d87ee58dc1..3355ea5083ee621171f69f00e71af85c76eedb25 100644 (file)
@@ -176,7 +176,15 @@ public class OrTypePattern extends TypePattern {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               left.traverse(visitor, ret);
+               right.traverse(visitor, ret);
+               return ret;
+       }
+
 }
index 817064123455d61c746e77e9f5001407f04f49ab..518446a041758caec0ee910983ae1a1c8dbd5166 100644 (file)
@@ -81,7 +81,9 @@ public abstract class PatternNode implements IHasSourceLocation {
                this.sourceContext = context;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
-        return visitor.visit(this, data);
-    }
+    public abstract Object accept(PatternNodeVisitor visitor, Object data);
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               return accept(visitor,data);
+       }
 }
diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java b/weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java
new file mode 100644 (file)
index 0000000..87a61a6
--- /dev/null
@@ -0,0 +1,601 @@
+/*******************************************************************************
+ * 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
+ *   Adrian Colyer                refactoring for traversal and grouping by kind
+ *******************************************************************************/
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.weaver.Member;
+
+/**
+ * A Pointcut or TypePattern visitor
+ *
+ * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
+ */
+public interface PatternNodeVisitor {
+
+       // Annotation type patterns
+       Object visit(AndAnnotationTypePattern node, Object data);
+    Object visit(AnyAnnotationTypePattern node, Object data);
+    Object visit(EllipsisAnnotationTypePattern node, Object data);
+    Object visit(ExactAnnotationTypePattern node, Object data);
+    Object visit(BindingAnnotationTypePattern node, Object data);
+    Object visit(NotAnnotationTypePattern node, Object data);
+    Object visit(OrAnnotationTypePattern node, Object data);
+    Object visit(WildAnnotationTypePattern node, Object data);
+    Object visit(AnnotationPatternList node, Object data);
+
+    // Regular type patterns   
+    Object visit(AndTypePattern node, Object data);    
+    Object visit(AnyTypePattern node, Object data);
+    Object visit(AnyWithAnnotationTypePattern node, Object data);
+    Object visit(EllipsisTypePattern node, Object data);
+    Object visit(ExactTypePattern node, Object data);
+    Object visit(BindingTypePattern node, Object data);
+    Object visit(NotTypePattern node, Object data);
+    Object visit(NoTypePattern node, Object data);
+    Object visit(OrTypePattern node, Object data);
+    Object visit(WildTypePattern node, Object data);
+    Object visit(TypePatternList node, Object data);
+
+    // Pointcuts
+       Object visit(AndPointcut node, Object data);
+    Object visit(CflowPointcut node, Object data);
+    Object visit(ConcreteCflowPointcut node, Object data);
+    Object visit(HandlerPointcut node, Object data);
+    Object visit(IfPointcut node, Object data);
+    Object visit(KindedPointcut node, Object data);
+    Object visit(Pointcut.MatchesNothingPointcut node, Object data);
+    Object visit(AnnotationPointcut node, Object data);
+    Object visit(ArgsAnnotationPointcut node, Object data);
+    Object visit(ArgsPointcut node, Object data);
+    Object visit(ThisOrTargetAnnotationPointcut node, Object data);
+    Object visit(ThisOrTargetPointcut node, Object data);
+    Object visit(WithinAnnotationPointcut node, Object data);
+    Object visit(WithinCodeAnnotationPointcut node, Object data);
+    Object visit(NotPointcut node, Object data);
+    Object visit(OrPointcut node, Object data);
+    Object visit(ReferencePointcut node, Object data);
+    Object visit(WithinPointcut node, Object data);
+    Object visit(WithincodePointcut node, Object data);
+
+       // Per-clauses
+    Object visit(PerCflow node, Object data);
+    Object visit(PerFromSuper node, Object data);
+    Object visit(PerObject node, Object data);
+    Object visit(PerSingleton node, Object data);
+    Object visit(PerTypeWithin node, Object data);
+
+       
+       // Declares
+    Object visit(DeclareAnnotation node, Object data);
+    Object visit(DeclareErrorOrWarning node, Object data);
+    Object visit(DeclareParents node, Object data);
+    Object visit(DeclarePrecedence node, Object data);
+    Object visit(DeclareSoft node, Object data);
+
+       // Miscellaneous patterns
+    Object visit(ModifiersPattern node, Object data);
+    Object visit(NamePattern node, Object data);
+    Object visit(SignaturePattern node, Object data);
+    Object visit(ThrowsPattern node, Object data);
+       Object visit(TypeVariable node, Object data);
+       Object visit(TypeVariablePatternList node,Object data);
+
+       // Catch-all
+    Object visit(PatternNode node, Object data);
+
+    /**
+     * 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>
+     */
+    static 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(TypeVariable node, Object data) {
+                       append(node);
+                       return null;
+               }
+               
+               public Object visit(TypeVariablePatternList 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]);
+            }
+        }
+
+    }
+
+}
index d63484e0fa15637b7a715fefc62aca5349a72e62..deb98242f569082f985ba60e46d8971d4157f7f8 100644 (file)
@@ -179,7 +179,8 @@ public class PatternParser {
        }
 
        private Declare parseParents() {
-               TypePattern p = parseTypePattern();
+               TypeVariablePatternList typeParameters = maybeParseTypeVariableList();
+               TypePattern p = parseTypePattern(false,false);
                IToken t = tokenSource.next();
                if (!(t.getString().equals("extends") || t.getString().equals("implements"))) {
                        throw new ParserException("extends or implements", t);
@@ -192,7 +193,11 @@ public class PatternParser {
                
                //XXX somewhere in the chain we need to enforce that we have only ExactTypePatterns
                
-               return new DeclareParents(p, l);
+               DeclareParents decp = new DeclareParents(p, l);
+               if (typeParameters != null) {
+                       decp.setTypeParameters(typeParameters);
+               }
+               return decp;
        }
 
        private Declare parseSoft() {
@@ -269,26 +274,28 @@ public class PatternParser {
                }
                
                String kind = parseIdentifier();
+               IToken possibleTypeVariableToken = tokenSource.peek();
+               TypeVariablePatternList typeVariables = maybeParseSimpleTypeVariableList();
                tokenSource.setIndex(start);
                if (kind.equals("execution") || kind.equals("call") || 
                                                kind.equals("get") || kind.equals("set")) {
-                       return parseKindedPointcut();
+                       p = parseKindedPointcut();
                } else if (kind.equals("args")) {
-                       return parseArgsPointcut();
+                       p = parseArgsPointcut();
                } else if (kind.equals("this") || kind.equals("target")) {
-                       return parseThisOrTargetPointcut();
+                       p = parseThisOrTargetPointcut();
                } else if (kind.equals("within")) {
-                       return parseWithinPointcut();
+                       p = parseWithinPointcut();
                } else if (kind.equals("withincode")) {
-                       return parseWithinCodePointcut();
+                       p = parseWithinCodePointcut();
                } else if (kind.equals("cflow")) {
-                       return parseCflowPointcut(false);
+                       p = parseCflowPointcut(false);
                } else if (kind.equals("cflowbelow")) {
-                       return parseCflowPointcut(true);
+                       p = parseCflowPointcut(true);
                } else  if (kind.equals("adviceexecution")) {
                        parseIdentifier(); eat("(");
                        eat(")");
-                       return new KindedPointcut(Shadow.AdviceExecution,
+                       p = new KindedPointcut(Shadow.AdviceExecution,
                                new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY, 
                                        TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, 
                                        TypePatternList.ANY, 
@@ -296,57 +303,50 @@ public class PatternParser {
                                        AnnotationTypePattern.ANY));
                } else  if (kind.equals("handler")) {
                        parseIdentifier(); eat("(");
-                       TypePattern typePat = parseTypePattern();
+                       TypePattern typePat = parseTypePattern(false,true);
                        eat(")");
-                       return new HandlerPointcut(typePat);
+                       p = new HandlerPointcut(typePat);
                } else  if (kind.equals("initialization")) {
                        parseIdentifier(); eat("(");
                        SignaturePattern sig = parseConstructorSignaturePattern();
                        eat(")");
-                       return new KindedPointcut(Shadow.Initialization, sig);
+                       p = new KindedPointcut(Shadow.Initialization, sig);
                } else  if (kind.equals("staticinitialization")) {
                        parseIdentifier(); eat("(");
-                       TypePattern typePat = parseTypePattern();
+                       TypePattern typePat = parseTypePattern(false,true);
                        eat(")");
-                       return new KindedPointcut(Shadow.StaticInitialization,
+                       p = new KindedPointcut(Shadow.StaticInitialization,
                                        new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY, 
                                        TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY, 
                                        ThrowsPattern.ANY,AnnotationTypePattern.ANY));
-               } else  if (kind.equals("preinitialization")) {
+               }  else  if (kind.equals("preinitialization")) {
                        parseIdentifier(); eat("(");
                        SignaturePattern sig = parseConstructorSignaturePattern();
                        eat(")");
-                       return new KindedPointcut(Shadow.PreInitialization, sig);
-        } else if (kind.equals("if")) {
-            //@style support
-            parseIdentifier();
-            eat("(");
-            if (maybeEat("true")) {
-                eat(")");
-                return new IfPointcut.IfTruePointcut();
-            } else if (maybeEat("false")) {
-                eat(")");
-                return new IfPointcut.IfFalsePointcut();
-            } else {
-                //TODO AV - true/false stuff needed ? What are the token here ?
-                eat(")");
-                // build a readable pointcut as an hint (toString() dumps raw token array into an horrible thing)
-                StringBuffer sb = new StringBuffer();
-                int currentIndex = tokenSource.getIndex();
-                try {
-                    tokenSource.setIndex(0);
-                    for (int i = 0; !IToken.EOF.equals(tokenSource.peek(i)); i++) {
-                        if (i > 0) sb.append(' ');
-                        sb.append(tokenSource.peek(i).getString());
-                    }
-                } finally {
-                    tokenSource.setIndex(currentIndex);
-                }
-                return new IfPointcut(sb.toString());
-            }
-               } else {
-                       return parseReferencePointcut();
+                       p = new KindedPointcut(Shadow.PreInitialization, sig);
+               } else  if (kind.equals("if")) {
+                       // @style support allows if(), if(true), if(false)
+                       parseIdentifier(); 
+                       eat("(");
+                       if (maybeEatIdentifier("true")) {
+                               eat(")");
+                               p = new IfPointcut.IfTruePointcut();
+                       } else if (maybeEatIdentifier("false")) {
+                           eat(")");
+                               p = new IfPointcut.IfFalsePointcut();
+                       } else {
+                               eat(")");
+                               // TODO - Alex has some token stuff going on here to get a readable name in place of ""...
+                               p = new IfPointcut("");
+                       }
                }
+               else {
+                       p = parseReferencePointcut();
+                       if (typeVariables != null) 
+                               throw new ParserException("type variable specification not allowed for reference pointcuts",possibleTypeVariableToken);
+               }
+               if (typeVariables != null) p.setTypeVariables(typeVariables);
+               return p;
        }
 
        public Pointcut parseAnnotationPointcut() {             
@@ -538,36 +538,40 @@ public class PatternParser {
        }
        
        public TypePattern parseTypePattern() {
-               TypePattern p = parseAtomicTypePattern(); 
+               return parseTypePattern(false,false);
+       }
+       
+       public TypePattern parseTypePattern(boolean insideTypeParameters, boolean allowTypeVariableDeclarations) {
+               TypePattern p = parseAtomicTypePattern(insideTypeParameters,allowTypeVariableDeclarations); 
                if (maybeEat("&&")) {
-                       p = new AndTypePattern(p, parseNotOrTypePattern());
+                       p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters,allowTypeVariableDeclarations));
                }  
                
                if (maybeEat("||")) {
-                       p = new OrTypePattern(p, parseTypePattern());
+                       p = new OrTypePattern(p, parseTypePattern(insideTypeParameters,allowTypeVariableDeclarations));
                }               
                return p;
        }
        
-       private TypePattern parseNotOrTypePattern() {
-               TypePattern p = parseAtomicTypePattern();
+       private TypePattern parseNotOrTypePattern(boolean insideTypeParameters,boolean allowTypeVariableDeclarations) {
+               TypePattern p = parseAtomicTypePattern(insideTypeParameters,allowTypeVariableDeclarations);
                if (maybeEat("&&")) {                   
-                       p = new AndTypePattern(p, parseTypePattern());
+                       p = new AndTypePattern(p, parseTypePattern(insideTypeParameters,allowTypeVariableDeclarations));
                } 
                return p;               
        }
        
-       private TypePattern parseAtomicTypePattern() {
+       private TypePattern parseAtomicTypePattern(boolean insideTypeParameters, boolean allowTypeVariableDeclarations) {
                AnnotationTypePattern ap = maybeParseAnnotationPattern();
                if (maybeEat("!")) {
                        //int startPos = tokenSource.peek(-1).getStart();
                        //??? we lose source location for true start of !type
-                       TypePattern p = new NotTypePattern(parseAtomicTypePattern());
+                       TypePattern p = new NotTypePattern(parseAtomicTypePattern(insideTypeParameters,allowTypeVariableDeclarations));
                        p = setAnnotationPatternForTypePattern(p,ap);
                        return p;                       
                }
                if (maybeEat("(")) {
-                       TypePattern p = parseTypePattern();
+                       TypePattern p = parseTypePattern(insideTypeParameters,allowTypeVariableDeclarations);
                        p = setAnnotationPatternForTypePattern(p,ap);
                        eat(")");
                        boolean isVarArgs = maybeEat("...");
@@ -575,7 +579,7 @@ public class PatternParser {
                        return p;
                }
                int startPos = tokenSource.peek().getStart();
-           TypePattern p = parseSingleTypePattern();
+           TypePattern p = parseSingleTypePattern(insideTypeParameters,allowTypeVariableDeclarations);
            int endPos = tokenSource.peek(-1).getEnd();
            p = setAnnotationPatternForTypePattern(p,ap);
            p.setLocation(sourceContext, startPos, endPos);
@@ -586,7 +590,7 @@ public class PatternParser {
                TypePattern ret = t;
                if (ap != AnnotationTypePattern.ANY) {
                        if (t == TypePattern.ANY) {
-                               ret = new WildTypePattern(new NamePattern[] {NamePattern.ANY},false,0,false);
+                               ret = new WildTypePattern(new NamePattern[] {NamePattern.ANY},false,0,false,null);
                        }
                        if (t.annotationPattern == AnnotationTypePattern.ANY) {
                                ret.setAnnotationTypePattern(ap);                               
@@ -649,17 +653,27 @@ public class PatternParser {
        }
        
        public TypePattern parseSingleTypePattern() {
+               return parseSingleTypePattern(false, false);
+       }
+       
+       public TypePattern parseSingleTypePattern(boolean insideTypeParameters, boolean allowTypeVariableDeclarations) {
+               if (insideTypeParameters && maybeEat("?")) return parseGenericsWildcardTypePattern();
+               
                List names = parseDottedNamePattern(); 
-//             new ArrayList();
-//             NamePattern p1 = parseNamePattern();
-//             names.add(p1);
-//             while (maybeEat(".")) {
-//                     if (maybeEat(".")) {
-//                             names.add(NamePattern.ELLIPSIS);
-//                     }
-//                     NamePattern p2 = parseNamePattern();
-//                     names.add(p2);
-//             }
+               
+               TypePattern upperBound = null;
+               TypePattern[] additionalInterfaceBounds = new TypePattern[0];
+               TypePattern lowerBound = null;
+               if ((names.size() == 1) && allowTypeVariableDeclarations) {
+                       if (maybeEatIdentifier("extends")) {
+                               upperBound = parseTypePattern(false,false);
+                               additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
+                       }
+                       if (maybeEatIdentifier("super")) {
+                               lowerBound = parseTypePattern(false,false);
+                       }
+               }
+
                int dim = 0;
                while (maybeEat("[")) {
                        eat("]");
@@ -669,10 +683,14 @@ public class PatternParser {
         boolean isVarArgs = maybeEat("...");
 
                boolean includeSubtypes = maybeEat("+");
+               
+               TypePatternList typeParameters = maybeParseTypeParameterList(allowTypeVariableDeclarations);
                int endPos = tokenSource.peek(-1).getEnd();
                
                //??? what about the source location of any's????
-               if (names.size() == 1 && ((NamePattern)names.get(0)).isAny() && dim == 0 && !isVarArgs) return TypePattern.ANY;
+               if (names.size() == 1 && ((NamePattern)names.get(0)).isAny() && 
+                               dim == 0 && !isVarArgs && typeParameters == null && upperBound == null &&
+                               lowerBound == null) return TypePattern.ANY;
                
                // Notice we increase the dimensions if varargs is set.  this is to allow type matching to
                // succeed later: The actual signature at runtime of a method declared varargs is an array type of
@@ -680,10 +698,26 @@ public class PatternParser {
                // pattern 'Integer...' we create a WildTypePattern 'Integer[]' with varargs set.  If this matches
                // during shadow matching, we confirm that the varargs flags match up before calling it a successful
                // match.
-               return new WildTypePattern(names, includeSubtypes, dim+(isVarArgs?1:0), endPos,isVarArgs);
+               return new WildTypePattern(names, includeSubtypes, dim+(isVarArgs?1:0), endPos,isVarArgs,typeParameters,
+                               upperBound,additionalInterfaceBounds,lowerBound);
        }
        
-
+       public TypePattern parseGenericsWildcardTypePattern() {
+               List names = new ArrayList();
+               names.add(new NamePattern("?"));
+               TypePattern upperBound = null;
+               TypePattern[] additionalInterfaceBounds = new TypePattern[0];
+               TypePattern lowerBound = null;
+               if (maybeEatIdentifier("extends")) {
+                       upperBound = parseTypePattern(false,false);
+                       additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
+               }
+               if (maybeEatIdentifier("super")) {
+                       lowerBound = parseTypePattern(false,false);
+               }
+               int endPos = tokenSource.peek(-1).getEnd();
+               return new WildTypePattern(names,false,0,endPos,false,null,upperBound,additionalInterfaceBounds,lowerBound);
+       }
        
 //     private AnnotationTypePattern completeAnnotationPattern(AnnotationTypePattern p) {
 //             if (maybeEat("&&")) {
@@ -797,9 +831,9 @@ public class PatternParser {
                                if (previous != null) {
                                        if (!isAdjacent(previous, tok)) break;
                                }
-                               if ("*".equals(tok.getString()) || (tok.isIdentifier() && !"...".equals(tok.getString()))) {
+                               if (tok.getString() == "*" || (tok.isIdentifier() && tok.getString()!="...")) {
                                        buf.append(tok.getString());
-                               } else if ("...".equals(tok.getString())) {
+                               } else if (tok.getString()=="...") {
                                        break;
                                } else if (tok.getLiteralKind() != null) {
                                        //System.err.println("literal kind: " + tok.getString());
@@ -869,7 +903,7 @@ public class PatternParser {
                        if (previous != null) {
                                if (!isAdjacent(previous, tok)) break;
                        }
-                       if (tok.getString().equals("*") || tok.isIdentifier()) {
+                       if (tok.getString() == "*" || tok.isIdentifier()) {
                                buf.append(tok.getString());
                        } else if (tok.getLiteralKind() != null) {
                                //System.err.println("literal kind: " + tok.getString());
@@ -1067,6 +1101,9 @@ public class PatternParser {
        
        public SignaturePattern parseFieldSignaturePattern() {
                int startPos = tokenSource.peek().getStart();
+               
+       //      TypePatternList followMe = TypePatternList.ANY;
+               
                AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern();
                ModifiersPattern modifiers = parseModifiersPattern();
                TypePattern returnType = parseTypePattern();
@@ -1100,6 +1137,82 @@ public class PatternParser {
                    return null;
                }
        }
+       
+       /**
+        * Parse type variable declarations for a generic method or at the start of a signature pointcut to identify
+        * type variable names in a generic type.
+        * @param includeParameterizedTypes
+        * @return
+        */
+       public TypeVariablePatternList maybeParseTypeVariableList() {
+               if (!maybeEat("<")) return null;
+               List typeVars = new ArrayList();
+               TypeVariable t = parseTypeVariable();
+               typeVars.add(t);
+               while (maybeEat(",")) {
+                       TypeVariable nextT = parseTypeVariable();
+                       typeVars.add(nextT);
+               }
+               eat(">");
+               TypeVariable[] tvs = new TypeVariable[typeVars.size()];
+               typeVars.toArray(tvs);
+               return new TypeVariablePatternList(tvs);
+       }
+       
+       // of the form execution<T,S,V> - allows identifiers only
+       public TypeVariablePatternList maybeParseSimpleTypeVariableList() {
+               if (!maybeEat("<")) return null;
+               List typeVars = new ArrayList();
+               do {
+                       String typeVarName = parseIdentifier();
+                       TypeVariable tv = new TypeVariable(typeVarName);
+                       typeVars.add(tv);
+               } while (maybeEat(","));
+               eat(">");
+               TypeVariable[] tvs = new TypeVariable[typeVars.size()];
+               typeVars.toArray(tvs);
+               return new TypeVariablePatternList(tvs);                
+       }
+       
+       public TypePatternList maybeParseTypeParameterList(boolean allowTypeVariables) {
+               if (!maybeEat("<")) return null;
+               List typePats = new ArrayList();
+               do {
+                       TypePattern tp = parseTypePattern(true,allowTypeVariables);
+                       typePats.add(tp);
+               } while(maybeEat(","));
+               eat(">");
+               TypePattern[] tps = new TypePattern[typePats.size()];
+               typePats.toArray(tps);
+               return new TypePatternList(tps);                
+       }
+       
+       public TypeVariable parseTypeVariable() {
+               TypePattern upperBound = null;
+               TypePattern[] additionalInterfaceBounds = null;
+               TypePattern lowerBound = null;
+               String typeVariableName = null;
+               if (typeVariableName == null) typeVariableName = parseIdentifier();
+               if (maybeEatIdentifier("extends")) {
+                       upperBound = parseTypePattern();
+                       additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds();
+               } else if (maybeEatIdentifier("super")) {
+                       lowerBound = parseTypePattern();
+               }
+               return new TypeVariable(typeVariableName,upperBound,additionalInterfaceBounds,lowerBound);
+       }
+       
+       private TypePattern[] maybeParseAdditionalInterfaceBounds() {
+               List boundsList = new ArrayList();
+               while (maybeEat("&")) {
+                       TypePattern tp = parseTypePattern();
+                       boundsList.add(tp);
+               }
+               if (boundsList.size() == 0) return null;
+               TypePattern[] ret = new TypePattern[boundsList.size()];
+               boundsList.toArray(ret);
+               return ret;
+       }
 
        public String parsePossibleStringSequence(boolean shouldEnd) {
                StringBuffer result = new StringBuffer();
@@ -1130,7 +1243,7 @@ public class PatternParser {
        public String parseStringLiteral() {
                IToken token = tokenSource.next();
                String literalKind = token.getLiteralKind();
-               if (literalKind.equals("string")) {
+               if (literalKind == "string") {
                        return token.getString();
                }
 
@@ -1169,7 +1282,7 @@ public class PatternParser {
        
        public boolean maybeEat(String token) {
                IToken next = tokenSource.peek();
-               if (next.getString().equals(token)) {
+               if (next.getString() == token) {
                        tokenSource.next();
                        return true;
                } else {
@@ -1189,7 +1302,7 @@ public class PatternParser {
                
        public boolean peek(String token) {
                IToken next = tokenSource.peek();
-               return next.getString().equals(token);
+               return next.getString() == token;
        }
 
        
index b61223ccfa6b116fa37cc6493c02afefa2b29357..c66d3e43abbb2e98bab2bc09acbc8680d9670e7a 100644 (file)
@@ -49,6 +49,10 @@ public class PerCflow extends PerClause {
        
        // -----
        
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public Set couldMatchKinds() {
                return Shadow.ALL_SHADOW_KINDS;
        }
@@ -57,6 +61,10 @@ public class PerCflow extends PerClause {
                return FuzzyBoolean.MAYBE;
        }
        
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
+       
     protected FuzzyBoolean matchInternal(Shadow shadow) {
         return FuzzyBoolean.YES;
     }
index 63131f5ad4a84f8b2f817e0508c1fab419126caa..6b963df1a81099753e2cd273c9586dbd0374798f 100644 (file)
@@ -33,6 +33,10 @@ public class PerFromSuper extends PerClause {
                this.kind = kind;
        }
 
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public Set couldMatchKinds() {
                return Shadow.ALL_SHADOW_KINDS;
        }
@@ -41,6 +45,10 @@ public class PerFromSuper extends PerClause {
                throw new RuntimeException("unimplemented");
        }
        
+       public FuzzyBoolean fastMatch(Class targetType) {
+               throw new RuntimeException("unimplemented");
+       }
+       
     protected FuzzyBoolean matchInternal(Shadow shadow) {
         throw new RuntimeException("unimplemented");
     }
index a9294e85307b76bfe88e83c7456eb2228af19c22..b3494cd85276d8ffe80dfcb1701c8de642ad4359 100644 (file)
@@ -52,6 +52,10 @@ public class PerObject extends PerClause {
                this.isThis = isThis;
        }
 
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public Set couldMatchKinds() {
                return isThis ? thisKindSet : targetKindSet;
        }
@@ -61,6 +65,10 @@ public class PerObject extends PerClause {
                return FuzzyBoolean.MAYBE;
        }
        
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
+       
        
     protected FuzzyBoolean matchInternal(Shadow shadow) {
        //System.err.println("matches " + this + " ? " + shadow + ", " + shadow.hasTarget());
index 5b3b9f954e5280944d36c32723a7a5e43452f57c..6554e41570369179a16bf3e5dbfad6719e62cbe1 100644 (file)
@@ -32,6 +32,10 @@ public class PerSingleton extends PerClause {
        public PerSingleton() {
        }
 
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public Set couldMatchKinds() {
                return Shadow.ALL_SHADOW_KINDS;
        }
@@ -40,6 +44,10 @@ public class PerSingleton extends PerClause {
                return FuzzyBoolean.YES;
        }
        
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.YES;
+       }
+       
     protected FuzzyBoolean matchInternal(Shadow shadow) {
         return FuzzyBoolean.YES;
     }
index bd8873e27568829a8ec6b8b37b971c49e1fc45ac..b3c6cdd92148bdab50d9396ed98c8cc52a3d77be 100644 (file)
@@ -54,6 +54,10 @@ public class PerTypeWithin extends PerClause {
                this.typePattern = p;
        }
 
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        public Set couldMatchKinds() {
                return kindSet;
        }
@@ -66,6 +70,10 @@ public class PerTypeWithin extends PerClause {
                return FuzzyBoolean.MAYBE;
        }
        
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
+       
        
     protected FuzzyBoolean matchInternal(Shadow shadow) {
        ResolvedTypeX enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true);
index 886d1af9db34d693fc80d69b7daa47738f300782..402c4ad471501f70958d72f7b10bb108503d56e3 100644 (file)
@@ -104,6 +104,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
        protected int lastMatchedShadowId;
        private FuzzyBoolean lastMatchedShadowResult;
        private Test lastMatchedShadowResidue;
+       private TypeVariablePatternList typeVariables = TypeVariablePatternList.EMPTY;
        
        /**
         * Constructor for Pattern.
@@ -118,12 +119,25 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
         * Could I match any shadows in the code defined within this type?
         */
        public abstract FuzzyBoolean fastMatch(FastMatchInfo info);
+       
+       /**
+        * Could I match any shadows defined in this type?
+        */
+       public abstract FuzzyBoolean fastMatch(Class targetType);
 
        /**
         * The set of ShadowKinds that this Pointcut could possibly match  
         */
        public abstract /*Enum*/Set/*<Shadow.Kind>*/ couldMatchKinds();
        
+       public TypeVariablePatternList getTypeVariables() {
+               return typeVariables;
+       }
+       
+       public void setTypeVariables(TypeVariablePatternList typeVars) {
+               this.typeVariables = typeVars;
+       }
+       
        /**
         * Do I really match this shadow?
         * XXX implementors need to handle state
@@ -366,6 +380,10 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
                        return FuzzyBoolean.NO;
                }
                
+               public FuzzyBoolean fastMatch(Class targetType) {
+                       return FuzzyBoolean.NO;
+               }
+               
                protected FuzzyBoolean matchInternal(Shadow shadow) {
                        return FuzzyBoolean.NO;
                }
@@ -413,7 +431,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
                
                public String toString() { return ""; }
 
-        public Object accept(PointcutVisitor visitor, Object data) {
+        public Object accept(PatternNodeVisitor visitor, Object data) {
             return visitor.visit(this, data);
         }
        }
diff --git a/weaver/src/org/aspectj/weaver/patterns/PointcutVisitor.java b/weaver/src/org/aspectj/weaver/patterns/PointcutVisitor.java
deleted file mode 100644 (file)
index 1abf102..0000000
+++ /dev/null
@@ -1,629 +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:
- *   Alexandre Vasseur         initial implementation
- *******************************************************************************/
-package org.aspectj.weaver.patterns;
-
-import org.aspectj.weaver.Member;
-
-/**
- * A Pointcut or TypePattern visitor
- *
- * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
- */
-public interface PointcutVisitor {
-
-    Object visit(AnyTypePattern node, Object data);
-
-    Object visit(NoTypePattern node, Object data);
-
-    Object visit(EllipsisTypePattern node, Object data);
-
-    Object visit(AnyWithAnnotationTypePattern node, Object data);
-
-    Object visit(AnyAnnotationTypePattern node, Object data);
-
-    Object visit(EllipsisAnnotationTypePattern node, Object data);
-
-    Object visit(AndAnnotationTypePattern node, Object data);
-
-    Object visit(AndPointcut node, Object data);
-
-    Object visit(AndTypePattern node, Object data);
-
-    Object visit(AnnotationPatternList node, Object data);
-
-    Object visit(AnnotationPointcut node, Object data);
-
-    Object visit(ArgsAnnotationPointcut node, Object data);
-
-    Object visit(ArgsPointcut node, Object data);
-
-    Object visit(BindingAnnotationTypePattern node, Object data);
-
-    Object visit(BindingTypePattern node, Object data);
-
-    Object visit(CflowPointcut node, Object data);
-
-    Object visit(ConcreteCflowPointcut node, Object data);
-
-    Object visit(DeclareAnnotation node, Object data);
-
-    Object visit(DeclareErrorOrWarning node, Object data);
-
-    Object visit(DeclareParents node, Object data);
-
-    Object visit(DeclarePrecedence node, Object data);
-
-    Object visit(DeclareSoft node, Object data);
-
-    Object visit(ExactAnnotationTypePattern node, Object data);
-
-    Object visit(ExactTypePattern node, Object data);
-
-    Object visit(HandlerPointcut node, Object data);
-
-    Object visit(IfPointcut node, Object data);
-
-    Object visit(KindedPointcut node, Object data);
-
-    Object visit(ModifiersPattern node, Object data);
-
-    Object visit(NamePattern node, Object data);
-
-    Object visit(NotAnnotationTypePattern node, Object data);
-
-    Object visit(NotPointcut node, Object data);
-
-    Object visit(NotTypePattern node, Object data);
-
-    Object visit(OrAnnotationTypePattern node, Object data);
-
-    Object visit(OrPointcut node, Object data);
-
-    Object visit(OrTypePattern node, Object data);
-
-    Object visit(PerCflow node, Object data);
-
-    Object visit(PerFromSuper node, Object data);
-
-    Object visit(PerObject node, Object data);
-
-    Object visit(PerSingleton node, Object data);
-
-    Object visit(PerTypeWithin node, Object data);
-
-    Object visit(PatternNode node, Object data);
-
-    Object visit(ReferencePointcut node, Object data);
-
-    Object visit(SignaturePattern node, Object data);
-
-    Object visit(ThisOrTargetAnnotationPointcut node, Object data);
-
-    Object visit(ThisOrTargetPointcut node, Object data);
-
-    Object visit(ThrowsPattern node, Object data);
-
-    Object visit(TypePatternList node, Object data);
-
-    Object visit(WildAnnotationTypePattern node, Object data);
-
-    Object visit(WildTypePattern node, Object data);
-
-    Object visit(WithinAnnotationPointcut node, Object data);
-
-    Object visit(WithinCodeAnnotationPointcut node, Object data);
-
-    Object visit(WithinPointcut node, Object data);
-
-    Object visit(WithincodePointcut node, Object data);
-
-    Object visit(Pointcut.MatchesNothingPointcut node, Object data);
-
-    /**
-     * 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>
-     */
-    static class DumpPointcutVisitor implements PointcutVisitor {
-
-        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.isBelow()?"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 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)",
-//                "staticinitialization(!@(Immutable) *)"
-//                "execution(* *()) && if()",
-                "(if(true) && set(int BaseApp.i))"
-
-            };
-            for (int i = 0; i < s.length; i++) {
-                check(s[i]);
-            }
-        }
-
-    }
-
-}
index 1b18cced89d3c79a9cc73ef47156d760fe13a0ee..1dab1b0ba0f51838b5518868d7567d2116009c1b 100644 (file)
@@ -69,6 +69,10 @@ public class ReferencePointcut extends Pointcut {
                return FuzzyBoolean.MAYBE;
        }
        
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
+       
        /**
         * Do I really match this shadow?
         */
@@ -312,7 +316,7 @@ public class ReferencePointcut extends Pointcut {
         return result;
     }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
diff --git a/weaver/src/org/aspectj/weaver/patterns/ScopeWithTypeVariables.java b/weaver/src/org/aspectj/weaver/patterns/ScopeWithTypeVariables.java
new file mode 100644 (file)
index 0000000..dcab3ba
--- /dev/null
@@ -0,0 +1,118 @@
+/* *******************************************************************
+ * 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.patterns;
+
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.IMessage.Kind;
+import org.aspectj.weaver.IHasPosition;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.World;
+
+/**
+ * A scope that also considers type variables when looking up a type.
+ *
+ */
+public class ScopeWithTypeVariables implements IScope {
+
+       private IScope delegateScope;
+       private TypeVariablePatternList typeVariables;
+       
+       public ScopeWithTypeVariables(TypeVariablePatternList typeVars, IScope delegate) {
+               this.delegateScope = delegate;
+               this.typeVariables = typeVars;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#lookupType(java.lang.String, org.aspectj.weaver.IHasPosition)
+        */
+       public TypeX lookupType(String name, IHasPosition location) {
+               TypeVariable typeVariableMatch = typeVariables.lookupTypeVariable(name);
+               if (typeVariableMatch != null) {
+                       return typeVariableMatch.resolvedType();
+               } else {
+                       return delegateScope.lookupType(name, location);
+               }               
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getWorld()
+        */
+       public World getWorld() {
+               return delegateScope.getWorld();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getEnclosingType()
+        */
+       public ResolvedTypeX getEnclosingType() {
+               return delegateScope.getEnclosingType();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getMessageHandler()
+        */
+       public IMessageHandler getMessageHandler() {
+               return delegateScope.getMessageHandler();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#lookupFormal(java.lang.String)
+        */
+       public FormalBinding lookupFormal(String name) {
+               return delegateScope.lookupFormal(name);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getFormal(int)
+        */
+       public FormalBinding getFormal(int i) {
+               return delegateScope.getFormal(i);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getFormalCount()
+        */
+       public int getFormalCount() {
+               return delegateScope.getFormalCount();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getImportedPrefixes()
+        */
+       public String[] getImportedPrefixes() {
+               return delegateScope.getImportedPrefixes();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#getImportedNames()
+        */
+       public String[] getImportedNames() {
+               return delegateScope.getImportedNames();
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#message(org.aspectj.bridge.IMessage.Kind, org.aspectj.weaver.IHasPosition, java.lang.String)
+        */
+       public void message(Kind kind, IHasPosition location, String message) {
+               delegateScope.message(kind, location, message);
+       }
+
+       /* (non-Javadoc)
+        * @see org.aspectj.weaver.patterns.IScope#message(org.aspectj.bridge.IMessage.Kind, org.aspectj.weaver.IHasPosition, org.aspectj.weaver.IHasPosition, java.lang.String)
+        */
+       public void message(Kind kind, IHasPosition location1,
+                       IHasPosition location2, String message) {
+               delegateScope.message(kind,location1,location2,message);
+       }
+
+}
index 0cdd94decbc7c7cd692d3e7d91d66a81ef9415e7..012d7c99ac60779457ec17979010999075fa296b 100644 (file)
@@ -353,6 +353,10 @@ public class SignaturePattern extends PatternNode {
                return false;
        }
        
+       public boolean couldMatch(Class declaringClass) {
+               return declaringTypeMatch(declaringClass);
+       }
+       
        public boolean matches(Class declaringClass, java.lang.reflect.Member member) {
            if (kind == Member.ADVICE) return true;
            if (kind == Member.POINTCUT) return false;
@@ -625,7 +629,7 @@ public class SignaturePattern extends PatternNode {
                return annotationPattern == AnnotationTypePattern.ANY;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index be281ffc47fa568f750ea8c26c24527fe210831a..da45228ea1e86bac114d24194ed35ff15b0bb336 100644 (file)
@@ -83,6 +83,10 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
        public FuzzyBoolean fastMatch(FastMatchInfo info) {
                return FuzzyBoolean.MAYBE;
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
 
        /* (non-Javadoc)
         * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
@@ -271,7 +275,7 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
                return buf.toString();   
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index 2a2d6786b802e5b4037faba7bdd47db8f586180e..958c9d8ba58acb1a4fa4f7e90cb10af7489e7689 100644 (file)
@@ -84,6 +84,10 @@ public class ThisOrTargetPointcut extends NameBindingPointcut {
        public FuzzyBoolean fastMatch(FastMatchInfo type) {
                return FuzzyBoolean.MAYBE;
        }
+
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
        
        private boolean couldMatch(Shadow shadow) {
                return isThis ? shadow.hasThis() : shadow.hasTarget();
@@ -232,7 +236,7 @@ public class ThisOrTargetPointcut extends NameBindingPointcut {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index 9977c3c5e3f1e544e33ff9c9ad032741d8fe00ad..db3981040811db8b0d395677fa31889a64f10767 100644 (file)
@@ -152,7 +152,7 @@ public class ThrowsPattern extends PatternNode {
                //XXXwriteLocation(s);
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index e541b3946b3c6a6c0d89ecec9c86c000978a1a9b..a99f05ed89811cb51dda883f192100d2bf2f1184 100644 (file)
@@ -54,10 +54,16 @@ public abstract class TypePattern extends PatternNode {
        protected boolean includeSubtypes;
        protected boolean isVarArgs = false;
        protected AnnotationTypePattern annotationPattern = AnnotationTypePattern.ANY;
+       protected TypePatternList typeParameters = TypePatternList.EMPTY;
        
-       protected TypePattern(boolean includeSubtypes,boolean isVarArgs) {
+       protected TypePattern(boolean includeSubtypes,boolean isVarArgs,TypePatternList typeParams) {
                this.includeSubtypes = includeSubtypes;
                this.isVarArgs = isVarArgs;
+               this.typeParameters = (typeParams == null ? TypePatternList.EMPTY : typeParams);
+       }
+       
+       protected TypePattern(boolean includeSubtypes, boolean isVarArgs) {
+               this(includeSubtypes,isVarArgs,null);
        }
 
     public AnnotationTypePattern getAnnotationPattern() {
@@ -84,6 +90,14 @@ public abstract class TypePattern extends PatternNode {
                this.annotationPattern = annPatt;
        }
        
+       public void setTypeParameters(TypePatternList typeParams) {
+               this.typeParameters = typeParams;
+       }
+       
+       public TypePatternList getTypeParameters() {
+               return this.typeParameters;
+       }
+       
        public void setIsVarArgs(boolean isVarArgs) {
                this.isVarArgs = isVarArgs;
        }
@@ -335,7 +349,7 @@ class EllipsisTypePattern extends TypePattern {
         * @param includeSubtypes
         */
        public EllipsisTypePattern() {
-               super(false,false);
+               super(false,false,new TypePatternList());
        }
 
        /* (non-Javadoc)
@@ -398,7 +412,7 @@ class EllipsisTypePattern extends TypePattern {
                return 17 * 37;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 
@@ -412,7 +426,7 @@ class AnyTypePattern extends TypePattern {
         * @param includeSubtypes
         */
        public AnyTypePattern() {
-               super(false,false);
+               super(false,false,new TypePatternList());
        }
 
        /* (non-Javadoc)
@@ -488,7 +502,7 @@ class AnyTypePattern extends TypePattern {
                return 37;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
@@ -504,6 +518,10 @@ class AnyWithAnnotationTypePattern extends TypePattern {
                annotationPattern = atp;
        }
 
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
        protected boolean couldEverMatchSameTypesAs(TypePattern other) {
                return true;
        }
@@ -571,7 +589,7 @@ class AnyWithAnnotationTypePattern extends TypePattern {
 class NoTypePattern extends TypePattern {
        
        public NoTypePattern() {
-               super(false,false);
+               super(false,false,new TypePatternList());
        }
 
        
@@ -654,7 +672,7 @@ class NoTypePattern extends TypePattern {
                return 17 * 37 * 37;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index 67327aa3d255147360637dee4338bc53e2cd1d15..33bdca15033488a6d76828d2ed70cf2232de28c1 100644 (file)
@@ -34,7 +34,7 @@ public class TypePatternList extends PatternNode {
                new TypePatternList(new TypePattern[] {});
        
        public static final TypePatternList ANY =
-           new TypePatternList(new TypePattern[] {TypePattern.ELLIPSIS});
+           new TypePatternList(new TypePattern[] {new EllipsisTypePattern()});  //can't use TypePattern.ELLIPSIS because of circular static dependency that introduces
        
        public TypePatternList() {
                typePatterns = new TypePattern[0];
@@ -503,7 +503,15 @@ public class TypePatternList extends PatternNode {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               for (int i = 0; i < typePatterns.length; i++) {
+                       typePatterns[i].traverse(visitor,ret);
+               }
+               return ret;
+       }
 }
diff --git a/weaver/src/org/aspectj/weaver/patterns/TypeVariable.java b/weaver/src/org/aspectj/weaver/patterns/TypeVariable.java
new file mode 100644 (file)
index 0000000..8c667f0
--- /dev/null
@@ -0,0 +1,216 @@
+/* *******************************************************************
+ * 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.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.VersionedDataInputStream;
+
+/**
+ * @author colyer
+ * Represents a type variable as declared as part of a type declaration, parameter declaration,
+ * or type parameter specification.
+ * <p>For example:</p>
+ * <ul>
+ * <li>&lt;T&gt; T genericMethod(T t) {...}</li>
+ * <li>static &lt;T extends Foo&gt; T staticGenericMethod(T t) {...}</li>
+ * <li>Foo&lt;T extends Bar &amp; IGoo&gt;
+ * </ul>
+ */
+public class TypeVariable extends PatternNode {
+
+       private static final String anything = "?";
+       
+       private String name;  // eg. "T"
+       private TypePattern upperBound; // default is object unless of the form T extends Bar
+       private TypePattern[] interfaceBounds; // additional upper bounds (must be interfaces) arising from
+                                                           // declarations of the form T extends Bar & IGoo, IDoo
+       private TypePattern lowerBound; // only set if type variable is of the form T super Bar
+       private ResolvedTypeX resolvedType; // only set if resolved
+       
+       /**
+        * Create a named type variable with upper bound Object and no lower bounds.
+        * Use this constructor for the simple "T" case
+        */
+       public TypeVariable(String variableName) {
+               this.name = variableName;
+               this.upperBound = new ExactTypePattern(TypeX.OBJECT,false,false);
+               this.lowerBound = null;
+               this.interfaceBounds = null;
+       }
+       
+       /**
+        * Create a named type variable with the given upper bound and no lower bounds
+        * Use this constructor for the T extends Foo case
+        * @param variableName
+        * @param upperBound
+        */
+       public TypeVariable(String variableName, TypePattern upperBound) {
+               this.name = variableName;
+               this.upperBound = upperBound;
+               this.lowerBound = null;
+               this.interfaceBounds = null;
+       }
+       
+       public TypeVariable(String variableName, TypePattern upperLimit, TypePattern[] interfaceBounds, TypePattern lowerBound) {
+               this.name = variableName;
+               this.upperBound = upperLimit;
+               if (upperBound == null) upperBound = new ExactTypePattern(TypeX.OBJECT,false,false);
+               this.interfaceBounds = interfaceBounds;
+               this.lowerBound = lowerBound;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public String getName() {
+               return name;
+       }
+       
+       public boolean isAnythingPattern() {
+               return name.equals(anything);
+       }
+       
+       public TypePattern getRawTypePattern() {
+               return upperBound;
+       }
+       
+       public TypePattern getUpperBound() {
+               return upperBound;
+       }
+       
+       public boolean hasLowerBound() { return (lowerBound != null); }
+       
+       public TypePattern getLowerBound() {
+               return lowerBound;
+       }
+       
+       public boolean hasAdditionalInterfaceBounds() {
+               return (interfaceBounds != null);
+       }
+       
+       public TypePattern[] getAdditionalInterfaceBounds() {
+               if (interfaceBounds != null) {
+                       return interfaceBounds;
+               } else {
+                       return new TypePattern[0];
+               }
+       }
+       
+       public ResolvedTypeX resolvedType() {
+               throw new UnsupportedOperationException("Haven't implement ResolvedTypeX for TypeVariables yet...");
+               //return this.resolvedType;
+       }
+       
+       public boolean equals(Object obj) {
+               if (!(obj instanceof TypeVariable)) return false;
+               TypeVariable other = (TypeVariable) obj;
+               if (!name.equals(other.name)) return false;
+               if (!upperBound.equals(other.upperBound)) return false;
+               if (lowerBound != null) {
+                       if (other.lowerBound == null) return false;
+                       if (!lowerBound.equals(other.lowerBound)) return false;
+               } else {
+                       if (other.lowerBound != null) return false;
+               }
+               if (interfaceBounds != null) {
+                       if (other.interfaceBounds == null) return false;
+                       if (interfaceBounds.length != other.interfaceBounds.length) return false;
+                       for (int i = 0; i < interfaceBounds.length; i++) {
+                               if (!interfaceBounds[i].equals(other.interfaceBounds[i])) return false;
+                       }
+               } else {
+                       if (other.interfaceBounds != null) return false;
+               }
+               return true;
+       }
+       
+       public int hashCode() {
+               int hashCode = 17 + (37 * name.hashCode());
+               hashCode = hashCode * 37 + upperBound.hashCode();
+               if (lowerBound != null) hashCode = hashCode * 37 + lowerBound.hashCode();
+               if (interfaceBounds != null) {
+                       for (int i = 0; i < interfaceBounds.length; i++) {
+                               hashCode = 37*hashCode + interfaceBounds[i].hashCode();
+                       }
+               }
+               return hashCode;
+       }
+       
+       public String toString() {
+               StringBuffer sb = new StringBuffer();
+               sb.append(name);
+               sb.append(getExtendsClause());
+               if (interfaceBounds != null) {
+                       sb.append(" & ");
+                       for (int i = 0; i < interfaceBounds.length; i++) {
+                               sb.append(interfaceBounds[i].toString());
+                               if (i < interfaceBounds.length) sb.append(",");
+                       }
+               }
+               if (lowerBound != null) {
+                       sb.append(" super ");
+                       sb.append(lowerBound.toString());
+               }
+               return sb.toString();
+       }
+       
+       private String getExtendsClause() {
+               if (upperBound instanceof ExactTypePattern) {
+                       ExactTypePattern bound = (ExactTypePattern) upperBound;
+                       if (bound.type == TypeX.OBJECT) return "";
+               }
+               return " extends " + upperBound.toString();
+       }
+       
+       public void write(DataOutputStream s) throws IOException {
+               s.writeUTF(name);
+               upperBound.write(s);
+               if (interfaceBounds == null) {
+                       s.writeInt(0);
+               } else {
+                       s.writeInt(interfaceBounds.length);
+                       for (int i = 0; i < interfaceBounds.length; i++) {
+                               interfaceBounds[i].write(s);
+                       }
+               }
+               s.writeBoolean(hasLowerBound());
+               if (hasLowerBound()) lowerBound.write(s);
+               writeLocation(s);               
+       }
+       
+       public static TypeVariable read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               TypeVariable tv = null;
+               String name = s.readUTF();
+               TypePattern upperBound = TypePattern.read(s, context);
+               TypePattern[] additionalInterfaceBounds = null;
+               int numInterfaceBounds = s.readInt();
+               if (numInterfaceBounds > 0) {
+                       additionalInterfaceBounds = new TypePattern[numInterfaceBounds];
+                       for (int i = 0; i < additionalInterfaceBounds.length; i++) {
+                               additionalInterfaceBounds[i] = TypePattern.read(s, context);
+                       }
+               }
+               boolean hasLowerBound = s.readBoolean();
+               TypePattern lowerBound = null;
+               if (hasLowerBound) lowerBound = TypePattern.read(s,context);
+               tv = new TypeVariable(name,upperBound,additionalInterfaceBounds,lowerBound);
+               tv.readLocation(context, s);
+               return tv;
+       }
+       
+}
diff --git a/weaver/src/org/aspectj/weaver/patterns/TypeVariablePatternList.java b/weaver/src/org/aspectj/weaver/patterns/TypeVariablePatternList.java
new file mode 100644 (file)
index 0000000..1107d4e
--- /dev/null
@@ -0,0 +1,81 @@
+/* *******************************************************************
+ * 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.patterns;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.VersionedDataInputStream;
+
+/**
+ * @author colyer
+ * A list of type variable specifications, eg. &lt;T,S&gt; 
+ */
+public class TypeVariablePatternList extends PatternNode {
+
+       public static final TypeVariablePatternList EMPTY = new TypeVariablePatternList(new TypeVariable[0]);
+       
+       private TypeVariable[] patterns;
+       
+       public TypeVariablePatternList(TypeVariable[] typeVars) {
+               this.patterns = typeVars;
+       }
+       
+       public TypeVariable[] getTypeVariablePatterns() {
+               return this.patterns;
+       }
+       
+       public TypeVariable lookupTypeVariable(String name) {
+               for (int i = 0; i < patterns.length; i++) {
+                       if (patterns[i].getName().equals(name)) {
+                               return patterns[i];
+                       }
+               }
+               return null;
+       }
+
+       public void write(DataOutputStream s) throws IOException {
+               s.writeInt(patterns.length);
+               for (int i = 0; i < patterns.length; i++) {
+                       patterns[i].write(s);
+               }
+               writeLocation(s);
+       }
+
+       public static TypeVariablePatternList read(VersionedDataInputStream s, ISourceContext context) throws IOException {
+               TypeVariablePatternList ret = EMPTY;
+               int length = s.readInt();
+               if (length > 0) {
+                       TypeVariable[] patterns = new TypeVariable[length];
+                       for (int i = 0; i < patterns.length; i++) {
+                               patterns[i] = TypeVariable.read(s,context);
+                       }
+                       ret = new TypeVariablePatternList(patterns);
+               }
+               ret.readLocation(context, s);  // redundant but safe to read location for EMPTY
+               return ret;
+       }
+
+       public Object accept(PatternNodeVisitor visitor, Object data) {
+               return visitor.visit(this,data);
+       }
+       
+       public Object traverse(PatternNodeVisitor visitor, Object data) {
+               Object ret = accept(visitor,data);
+               for (int i = 0; i < patterns.length; i++) {
+                       patterns[i].traverse(visitor,ret);
+               }
+               return ret;
+       }
+       
+}
index c75924b1d302e060bb759b283483f64037269302..124e4508f2d959869fb309f75107e5c09b941578 100644 (file)
@@ -142,7 +142,7 @@ public class WildAnnotationTypePattern extends AnnotationTypePattern {
                return "@(" + typePattern.toString() + ")";
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index 2e5b98f5d1910546ac181ec35ec03f7cccc68642..31df81d09d309526588a617451b37967a9841c85 100644 (file)
@@ -38,9 +38,16 @@ public class WildTypePattern extends TypePattern {
        String[] importedPrefixes;
        String[] knownMatches;
        int dim;
-
-       WildTypePattern(NamePattern[] namePatterns, boolean includeSubtypes, int dim, boolean isVarArgs) {
-               super(includeSubtypes,isVarArgs);
+       
+       // 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
+
+       WildTypePattern(NamePattern[] namePatterns, boolean includeSubtypes, int dim, boolean isVarArgs, TypePatternList typeParams) {
+               super(includeSubtypes,isVarArgs,typeParams);
                this.namePatterns = namePatterns;
                this.dim = dim;
                ellipsisCount = 0;
@@ -51,7 +58,7 @@ public class WildTypePattern extends TypePattern {
        }
 
        public WildTypePattern(List names, boolean includeSubtypes, int dim) {
-               this((NamePattern[])names.toArray(new NamePattern[names.size()]), includeSubtypes, dim,false);
+               this((NamePattern[])names.toArray(new NamePattern[names.size()]), includeSubtypes, dim,false,TypePatternList.EMPTY);
 
        }
        
@@ -65,10 +72,31 @@ 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);
+               this.end = endPos;
+               this.upperBound = upperBound;
+               this.lowerBound = lowerBound;
+               this.additionalInterfaceBounds = 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) {
@@ -638,6 +666,7 @@ 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
                FileUtil.writeStringArray(knownMatches, s);
@@ -667,7 +696,8 @@ public class WildTypePattern extends TypePattern {
          boolean includeSubtypes = s.readBoolean();
          int dim = s.readInt();
          boolean varArg = s.readBoolean();
-         WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, varArg);
+         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);
@@ -683,14 +713,14 @@ public class WildTypePattern extends TypePattern {
                }
                boolean includeSubtypes = s.readBoolean();
                int dim = s.readInt();
-               WildTypePattern ret = new WildTypePattern(namePatterns, includeSubtypes, dim, false);
+               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(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 
index a00734b1d0d9a9f0443d837b9804539ca8743c14..e66e9c67642bc2e4bfe2f7afbb413cb4abc306a9 100644 (file)
@@ -72,6 +72,11 @@ public class WithinAnnotationPointcut extends NameBindingPointcut {
            return annotationTypePattern.fastMatches(info.getType());
        }
 
+       public FuzzyBoolean fastMatch(Class targetType) {
+               // TODO AMC
+               return FuzzyBoolean.MAYBE;
+       }
+
        /* (non-Javadoc)
         * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
         */
@@ -209,7 +214,7 @@ public class WithinAnnotationPointcut extends NameBindingPointcut {
                return buf.toString();
     }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index b1eae06cc63584e1c26391f446441674f531b495..8ee9fdd6415b16753b2b59c9a3cdfc83cf95129b 100644 (file)
@@ -79,6 +79,10 @@ public class WithinCodeAnnotationPointcut extends NameBindingPointcut {
                return FuzzyBoolean.MAYBE;
        }
 
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
+
        /* (non-Javadoc)
         * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
         */
@@ -216,7 +220,7 @@ public class WithinCodeAnnotationPointcut extends NameBindingPointcut {
                return buf.toString();
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index 142c97825af58addc47e4aa6f1aaf2887b80877d..18c58a5d6cdf00ae1e3016e9ce5391a0cd11096e 100644 (file)
@@ -64,6 +64,10 @@ public class WithinPointcut extends Pointcut {
            }
            return FuzzyBoolean.MAYBE;
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
     
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                ResolvedTypeX enclosingType = shadow.getIWorld().resolve(shadow.getEnclosingType(),true);
@@ -174,7 +178,7 @@ public class WithinPointcut extends Pointcut {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index 04d0230b988b535ab3a521d85fac125787a91fda..e3f64f9de9747c0c881575a333b7eea6e7d1f194 100644 (file)
@@ -60,6 +60,11 @@ public class WithincodePointcut extends Pointcut {
        public FuzzyBoolean fastMatch(FastMatchInfo type) {
                return FuzzyBoolean.MAYBE;
        }
+       
+       public FuzzyBoolean fastMatch(Class targetType) {
+               return FuzzyBoolean.MAYBE;
+       }
+
     
        protected FuzzyBoolean matchInternal(Shadow shadow) {
                //This will not match code in local or anonymous classes as if
@@ -139,7 +144,7 @@ public class WithincodePointcut extends Pointcut {
                return ret;
        }
 
-    public Object accept(PointcutVisitor visitor, Object data) {
+    public Object accept(PatternNodeVisitor visitor, Object data) {
         return visitor.visit(this, data);
     }
 }
index 2da27a24607e9204892ed6d7f78516521d870823..2f3a09e4a599a000e41ce27d2041d7d44fe61fa8 100644 (file)
@@ -22,6 +22,19 @@ import java.lang.reflect.Method;
  */
 public interface PointcutExpression {
 
+       /**
+        * Determine whether or not this pointcut could ever match a join point in the given class.
+        * @param aClass  the candidate class
+        * @return true iff this pointcut <i>may</i> match a join point within(aClass), and false otherwise 
+        */
+       boolean couldMatchJoinPointsInType(Class aClass);
+       
+       /**
+        * Returns true iff this pointcut contains any expression that might necessitate a dynamic test
+        * at some join point (e.g. args)
+        */
+       boolean mayNeedDynamicTest();
+       
        /**
         * Determine whether or not this pointcut matches a method call to the given method.
         * @param aMethod the method being called
diff --git a/weaver/src/org/aspectj/weaver/tools/PointcutPrimitive.java b/weaver/src/org/aspectj/weaver/tools/PointcutPrimitive.java
new file mode 100644 (file)
index 0000000..cd357e7
--- /dev/null
@@ -0,0 +1,44 @@
+/* *******************************************************************
+ * Copyright (c) 2004 IBM Corporation.
+ * All rights reserved. 
+ * This program and the accompanying materials are made available 
+ * under the terms of the Common Public License v1.0 
+ * which accompanies this distribution and is available at 
+ * http://www.eclipse.org/legal/cpl-v10.html 
+ *  
+ * ******************************************************************/
+
+package org.aspectj.weaver.tools;
+
+import org.aspectj.util.TypeSafeEnum;
+
+/**
+ * An enumeration of the different kinds of pointcut primitives
+ * supported by AspectJ.
+ */
+public class PointcutPrimitive extends TypeSafeEnum {
+
+       public static final PointcutPrimitive CALL = new PointcutPrimitive("call",1);
+       public static final PointcutPrimitive EXECUTION = new PointcutPrimitive("execution",2);
+       public static final PointcutPrimitive GET = new PointcutPrimitive("get",3);
+       public static final PointcutPrimitive SET = new PointcutPrimitive("set",4);
+       public static final PointcutPrimitive INITIALIZATION = new PointcutPrimitive("initialization",5);
+       public static final PointcutPrimitive PRE_INITIALIZATION = new PointcutPrimitive("preinitialization",6);
+       public static final PointcutPrimitive STATIC_INITIALIZATION = new PointcutPrimitive("staticinitialization",7);
+       public static final PointcutPrimitive HANDLER = new PointcutPrimitive("handler",8);
+       public static final PointcutPrimitive ADVICE_EXECUTION = new PointcutPrimitive("adviceexecution",9);
+       public static final PointcutPrimitive WITHIN = new PointcutPrimitive("within",10);
+       public static final PointcutPrimitive WITHIN_CODE = new PointcutPrimitive("withincode",11);
+       public static final PointcutPrimitive CFLOW = new PointcutPrimitive("cflow",12);
+       public static final PointcutPrimitive CFLOW_BELOW = new PointcutPrimitive("cflowbelow",13);
+       public static final PointcutPrimitive IF = new PointcutPrimitive("if",14);
+       public static final PointcutPrimitive THIS = new PointcutPrimitive("this",15);
+       public static final PointcutPrimitive TARGET = new PointcutPrimitive("target",16);
+       public static final PointcutPrimitive ARGS = new PointcutPrimitive("args",17);
+       public static final PointcutPrimitive REFERENCE = new PointcutPrimitive("reference pointcut",18);
+
+       private PointcutPrimitive(String name, int key) {
+               super(name, key);
+       }
+
+}
diff --git a/weaver/src/org/aspectj/weaver/tools/PointcutPrimitives.java b/weaver/src/org/aspectj/weaver/tools/PointcutPrimitives.java
deleted file mode 100644 (file)
index d6c13e1..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* *******************************************************************
- * Copyright (c) 2004 IBM Corporation.
- * All rights reserved. 
- * This program and the accompanying materials are made available 
- * under the terms of the Common Public License v1.0 
- * which accompanies this distribution and is available at 
- * http://www.eclipse.org/legal/cpl-v10.html 
- *  
- * ******************************************************************/
-
-package org.aspectj.weaver.tools;
-
-import org.aspectj.util.TypeSafeEnum;
-
-/**
- * An enumeration of the different kinds of pointcut primitives
- * supported by AspectJ.
- */
-public class PointcutPrimitives extends TypeSafeEnum {
-
-       public static final PointcutPrimitives CALL = new PointcutPrimitives("call",1);
-       public static final PointcutPrimitives EXECUTION = new PointcutPrimitives("execution",2);
-       public static final PointcutPrimitives GET = new PointcutPrimitives("get",3);
-       public static final PointcutPrimitives SET = new PointcutPrimitives("set",4);
-       public static final PointcutPrimitives INITIALIZATION = new PointcutPrimitives("initialization",5);
-       public static final PointcutPrimitives PRE_INITIALIZATION = new PointcutPrimitives("preinitialization",6);
-       public static final PointcutPrimitives STATIC_INITIALIZATION = new PointcutPrimitives("staticinitialization",7);
-       public static final PointcutPrimitives HANDLER = new PointcutPrimitives("handler",8);
-       public static final PointcutPrimitives ADVICE_EXECUTION = new PointcutPrimitives("adviceexecution",9);
-       public static final PointcutPrimitives WITHIN = new PointcutPrimitives("within",10);
-       public static final PointcutPrimitives WITHIN_CODE = new PointcutPrimitives("withincode",11);
-       public static final PointcutPrimitives CFLOW = new PointcutPrimitives("cflow",12);
-       public static final PointcutPrimitives CFLOW_BELOW = new PointcutPrimitives("cflowbelow",13);
-       public static final PointcutPrimitives IF = new PointcutPrimitives("if",14);
-       public static final PointcutPrimitives THIS = new PointcutPrimitives("this",15);
-       public static final PointcutPrimitives TARGET = new PointcutPrimitives("target",16);
-       public static final PointcutPrimitives ARGS = new PointcutPrimitives("args",17);
-
-       private PointcutPrimitives(String name, int key) {
-               super(name, key);
-       }
-
-}
diff --git a/weaver/src/org/aspectj/weaver/tools/UnsupportedPointcutPrimitiveException.java b/weaver/src/org/aspectj/weaver/tools/UnsupportedPointcutPrimitiveException.java
new file mode 100644 (file)
index 0000000..49f6555
--- /dev/null
@@ -0,0 +1,43 @@
+/* *******************************************************************
+ * 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.tools;
+
+/**
+ * @author colyer
+ *
+ */
+public class UnsupportedPointcutPrimitiveException extends RuntimeException {
+
+       private static final long serialVersionUID = 3258689888517043251L;
+
+       private PointcutPrimitive unsupportedPrimitive; 
+       private String pointcutExpression;
+       
+       public UnsupportedPointcutPrimitiveException(String pcExpression, PointcutPrimitive primitive) {
+               super("Pointcut expression " + pcExpression + " contains unsupported pointcut primitive '" + 
+                                 primitive.getName() + "'");
+               this.pointcutExpression = pcExpression;
+               this.unsupportedPrimitive = primitive;
+       }
+
+       /**
+        * @return Returns the unsupportedPrimitive.
+        */
+       public PointcutPrimitive getUnsupportedPrimitive() {
+               return unsupportedPrimitive;
+       }
+       
+       public String getInvalidPointcutExpression() {
+               return pointcutExpression;
+       }
+       
+}
index af35626c6a6515f6c0ec9e451213b930ac954d13..8095fddf44927b6f85f2680aaafde67359522034 100644 (file)
Binary files a/weaver/testdata/dummyAspect.jar and b/weaver/testdata/dummyAspect.jar differ
index 7ee6e98889ebadde0da78cd2dc015b2d03726d70..ed55e51bc5afeefc1ab482b55a16f128cb619e24 100644 (file)
Binary files a/weaver/testdata/ltw-acaspects.jar and b/weaver/testdata/ltw-acaspects.jar differ
index f09ee3db18ba44477f94a256ddd026c00d67eb0c..2e1e86fb1fdc6c7af66288016516cfd7e6c6ed02 100644 (file)
Binary files a/weaver/testdata/ltw-aspects.jar and b/weaver/testdata/ltw-aspects.jar differ
index 1dfcc034bfe5a60f2dfe4c3ba8ddcf47ee8690eb..014510d57abc4f6f031cbc3a13ef0fef5bc618e2 100644 (file)
Binary files a/weaver/testdata/ltw-classes.jar and b/weaver/testdata/ltw-classes.jar differ
index 186e49409e7ccb4a3f519f1df6d5341b68384913..853e7147b11f826352d2e4061706773eb990f82c 100644 (file)
Binary files a/weaver/testdata/ltw-deaspects.jar and b/weaver/testdata/ltw-deaspects.jar differ
index 791213a885a25dbd611cd4ce8e82d6532500b9e7..7ca214cf3bc8256d45db5e06611690fab1bd02c9 100644 (file)
Binary files a/weaver/testdata/ltw-dwaspects.jar and b/weaver/testdata/ltw-dwaspects.jar differ
index eedfaf50599cfb240da62bba94a494389eab025e..6144a3f6f89b6c7701a8cfdc3bdba5e117bd580b 100644 (file)
Binary files a/weaver/testdata/ltw-itdaspects.jar and b/weaver/testdata/ltw-itdaspects.jar differ
index 53f31b7e6aa48b91c8d2624d5d58803bfb0e114a..2c37baeb7f2b726267ef13febed033b685f8b252 100644 (file)
Binary files a/weaver/testdata/ltw-peraspects.jar and b/weaver/testdata/ltw-peraspects.jar differ
index c60f5c745c2833c45d9c114d7327c964f3eccd20..d4f117eeac1edee8c24da76a9d0288e81efda129 100644 (file)
Binary files a/weaver/testdata/ltw-woven.jar and b/weaver/testdata/ltw-woven.jar differ
index 23a58710dec2d2192c533be6267fc6070cdb07fb..8735641c59b60d6fc48d3231d3cfd83181346eb6 100644 (file)
Binary files a/weaver/testdata/megatrace.jar and b/weaver/testdata/megatrace.jar differ
index 4c025a67f45995cc281d4f0cacd71ba0d39936b8..11deb555cd7c6c2f050e11ffea447b6f498e2e0f 100644 (file)
Binary files a/weaver/testdata/megatrace0easy.jar and b/weaver/testdata/megatrace0easy.jar differ
index 15f34d5d3f6a0d75877d10bcacbb9b5242dd2a15..84f4a7b1ee50384ba0a048b52c1a3ce3b74d0bd3 100644 (file)
Binary files a/weaver/testdata/megatrace0hard.jar and b/weaver/testdata/megatrace0hard.jar differ
index 3d5b1fa08fcf79aed19d53098df82a01fa443e0f..4f8d26a4a442df172d37717a4daf42bd09855d71 100644 (file)
Binary files a/weaver/testdata/megatraceNoweave.jar and b/weaver/testdata/megatraceNoweave.jar differ
index 8ce561163cebba7d9bde4f4cc90170aab633b70e..1a50581b17b510c9a8a36da1b477fd07eec2dca7 100644 (file)
Binary files a/weaver/testdata/tracing.jar and b/weaver/testdata/tracing.jar differ
index 3ca01ffc04b9a17a7b87b6c30f7cd525f19b9d18..2b80740c7ca684775f59e2c81111397e8b5e63de 100644 (file)
@@ -17,10 +17,13 @@ import junit.framework.TestCase;
 
 import org.aspectj.weaver.BcweaverTests;
 import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.TypeX;
 import org.aspectj.weaver.World;
 import org.aspectj.weaver.bcel.BcelShadow;
 import org.aspectj.weaver.bcel.BcelWorld;
 
+import sun.reflect.generics.tree.TypeVariableSignature;
+
 /**
  * @author hugunin
  *
@@ -229,6 +232,154 @@ public class ParserTestCase extends TestCase {
            assertEquals("@args(Foo, Goo, ANY, .., Moo)",p.toString());
        }
        
+       public void testParseSimpleTypeVariable() {
+               PatternParser parser = new PatternParser("T");
+               TypeVariable tv = parser.parseTypeVariable();
+               TypeVariable expected = new TypeVariable("T");
+               assertEquals("Expected simple type variable T",expected,tv);
+       }
+       
+       public void testParseExtendingTypeVariable() {
+               PatternParser parser = new PatternParser("T extends Number");
+               TypeVariable tv = parser.parseTypeVariable();
+               TypeVariable expected = new TypeVariable("T",new PatternParser("Number").parseTypePattern());
+               assertEquals("Expected type variable T extends Number",expected,tv);
+       }
+       
+       public void testParseExtendingTypeVariableWithPattern() {
+               PatternParser parser = new PatternParser("T extends Number+");
+               TypeVariable tv = parser.parseTypeVariable();
+               TypeVariable expected = new TypeVariable("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");
+               TypeVariable tv = parser.parseTypeVariable();
+               TypeVariable expected = new TypeVariable("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");
+               TypeVariable tv = parser.parseTypeVariable();
+               TypeVariable expected = new TypeVariable("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();
+               TypeVariable[] patterns = list.getTypeVariablePatterns();
+               TypeVariable expected = new TypeVariable("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();
+               TypeVariable[] patterns = list.getTypeVariablePatterns();
+               TypeVariable expected0 = new TypeVariable("T");
+               assertEquals("Expected simple type variable T",expected0,patterns[0]);
+               TypeVariable expected1 = new TypeVariable("S",new PatternParser("Number").parseTypePattern());
+               assertEquals("Expected type variable S extends Number",expected1,patterns[1]);
+               TypeVariable expected2 = new TypeVariable("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+");
+               TypeVariable tv = parser.parseTypeVariable();
+               TypeVariable expected = new TypeVariable("T",new ExactTypePattern(TypeX.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() {
+               PatternParser parser = new PatternParser("declare parents : <T> Foo<T> implements IveGoneMad");
+               DeclareParents decp = (DeclareParents) parser.parseDeclare();
+               TypeVariablePatternList tvp = decp.getTypeParameters();
+               assertEquals("one type parameter",1,tvp.getTypeVariablePatterns().length);
+               assertEquals("expecting T","T",tvp.getTypeVariablePatterns()[0].getName());
+       }
+       
+       public void testParameterizedTypePatternsAny() {
+               PatternParser parser = new PatternParser("*<T,S extends Number>");
+               WildTypePattern wtp = (WildTypePattern) parser.parseTypePattern(false,true);
+               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,true),tvs.getTypePatterns()[1]);
+       }
+       
+       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>");
+               TypeVariablePatternList tl = parser.maybeParseSimpleTypeVariableList();
+               TypeVariable[] patterns = tl.getTypeVariablePatterns();
+               assertEquals("3 patterns",3,patterns.length);
+               assertEquals("T",new TypeVariable("T"),patterns[0]);
+               assertEquals("S",new TypeVariable("S"),patterns[1]);
+               assertEquals("V",new TypeVariable("V"),patterns[2]);
+       }
+       
+       public void testSimpleTypeVariableListError() {
+               PatternParser parser = new PatternParser("<T extends Number>");
+               try {
+                       TypeVariablePatternList tl = parser.maybeParseSimpleTypeVariableList();
+               } catch (ParserException ex) {
+                       assertEquals("Expecting >",">",ex.getMessage());
+               }       
+       }
+       
        public TestScope makeSimpleScope() {
                TestScope s = new TestScope(new String[] {"int", "java.lang.String"}, new String[] {"a", "b"}, world);
                s.setImportedPrefixes(new String[]{"p."});
index 039bf89d5a7eedd2207c34aa4c7bc0db437cb808..857c82171717f14099b03a15a09d47403acc6270 100644 (file)
@@ -31,6 +31,10 @@ public class PointcutTestCase extends TestCase {
        public void testMatchJP() {
                Pointcut p = new Pointcut() {
 
+                       public Object accept(PatternNodeVisitor visitor, Object data) {
+                               return visitor.visit(this,data);
+                       }
+                       
                        public Set couldMatchKinds() {
                                return null;
                        }
@@ -38,6 +42,10 @@ public class PointcutTestCase extends TestCase {
                        public FuzzyBoolean fastMatch(FastMatchInfo info) {
                                return null;
                        }
+                       
+                       public FuzzyBoolean fastMatch(Class targetClass) {
+                               return null;
+                       }
 
                        protected FuzzyBoolean matchInternal(Shadow shadow) {
                                return null;
index b3a2a73bf869aa2e773dd460fdbf5ee2b3e8cf2f..12218df8b8237c3236715b759105e4173a739688 100644 (file)
@@ -50,7 +50,7 @@ public class VisitorTestCase extends TestCase {
         for (Iterator iterator = pointcuts.iterator(); iterator.hasNext();) {
             String pointcut = (String) iterator.next();
             try  {
-                PointcutVisitor.DumpPointcutVisitor.check(pointcut);
+                PatternNodeVisitor.DumpPointcutVisitor.check(pointcut);
             } catch (Throwable t) {
                 t.printStackTrace();
                 fail("Failed on '"+pointcut+"': " +t.toString());
@@ -66,7 +66,7 @@ public class VisitorTestCase extends TestCase {
             String tp = (String) iterator.next();
             try  {
                 TypePattern p = new PatternParser(tp).parseTypePattern();
-                PointcutVisitor.DumpPointcutVisitor.check(p, true);
+                PatternNodeVisitor.DumpPointcutVisitor.check(p, true);
             } catch (Throwable t) {
                 fail("Failed on '"+tp+"': " +t.toString());
             }
index 411716b95db69061cd8214f05d879fef4264f81d..6e3e3d35eaa5a7b075566c4237b7f144e08ba70d 100644 (file)
@@ -468,6 +468,20 @@ public class PointcutExpressionTest extends TestCase {
                PointcutExpression ex = p.parsePointcutExpression("staticinitialization(*..A+)");
                assertEquals("staticinitialization(*..A+)",ex.getPointcutExpression());
        }
+       
+       public void testCouldMatchJoinPointsInType() {
+               PointcutExpression ex = p.parsePointcutExpression("execution(* org.aspectj.weaver.tools.PointcutExpressionTest.B.*(..))");
+               assertFalse("Could never match String",ex.couldMatchJoinPointsInType(String.class));
+               assertTrue("Will always match B",ex.couldMatchJoinPointsInType(B.class));
+               assertFalse("Does not match A",ex.couldMatchJoinPointsInType(A.class));
+       }
+       
+       public void testMayNeedDynamicTest() {
+               PointcutExpression ex = p.parsePointcutExpression("execution(* org.aspectj.weaver.tools.PointcutExpressionTest.B.*(..))");
+               assertFalse("No dynamic test needed",ex.mayNeedDynamicTest());
+               ex = p.parsePointcutExpression("execution(* org.aspectj.weaver.tools.PointcutExpressionTest.B.*(..)) && args(X)");
+               assertTrue("Dynamic test needed",ex.mayNeedDynamicTest());
+       }
 
        protected void setUp() throws Exception {
                super.setUp();