diff options
80 files changed, 1818 insertions, 295 deletions
diff --git a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java index a310f0838..f3a8cf88f 100644 --- a/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java +++ b/weaver/src/org/aspectj/weaver/bcel/AtAjAttributes.java @@ -11,6 +11,12 @@ *******************************************************************************/ 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. diff --git a/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java b/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java index 046cf5a61..8757cae3f 100644 --- a/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java +++ b/weaver/src/org/aspectj/weaver/internal/tools/PointcutExpressionImpl.java @@ -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 index 000000000..11c4ea60c --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/AbstractPatternNodeVisitor.java @@ -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; + } +} diff --git a/weaver/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java index 077840632..4635051b2 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java @@ -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; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java b/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java index a688e66b9..e389d5a25 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/AndPointcut.java @@ -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; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java index cf547c235..bc150b1d3 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java @@ -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; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java b/weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java index 75dbb73a8..d9cbd07d6 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java +++ b/weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java @@ -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; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java index 586056a24..17a6da36f 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/AnnotationPointcut.java @@ -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); } diff --git a/weaver/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java index 831c6f8c4..c814ba0df 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java @@ -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); } diff --git a/weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java index f60f64446..de271b5f5 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java index eebacd084..5001fd06c 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ArgsPointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java b/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java index a11413539..1ae2c38fe 100644 --- a/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java +++ b/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java @@ -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); diff --git a/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java b/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java index 4c1c13d7b..13ed1b6f6 100644 --- a/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/CflowPointcut.java @@ -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); - } - + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java index 360b6456f..f704d7305 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ConcreteCflowPointcut.java @@ -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); } diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareAnnotation.java b/weaver/src/org/aspectj/weaver/patterns/DeclareAnnotation.java index 55db910a7..a3913f735 100644 --- a/weaver/src/org/aspectj/weaver/patterns/DeclareAnnotation.java +++ b/weaver/src/org/aspectj/weaver/patterns/DeclareAnnotation.java @@ -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); diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java b/weaver/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java index a3bebe50c..a053ae8e1 100644 --- a/weaver/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java +++ b/weaver/src/org/aspectj/weaver/patterns/DeclareErrorOrWarning.java @@ -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); diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java b/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java index 3607afe7d..ef228d43d 100644 --- a/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java +++ b/weaver/src/org/aspectj/weaver/patterns/DeclareParents.java @@ -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++) { diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclarePrecedence.java b/weaver/src/org/aspectj/weaver/patterns/DeclarePrecedence.java index 0bc548c8c..2dd5fb83d 100644 --- a/weaver/src/org/aspectj/weaver/patterns/DeclarePrecedence.java +++ b/weaver/src/org/aspectj/weaver/patterns/DeclarePrecedence.java @@ -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: "); diff --git a/weaver/src/org/aspectj/weaver/patterns/DeclareSoft.java b/weaver/src/org/aspectj/weaver/patterns/DeclareSoft.java index a7bb8fade..9ed15111f 100644 --- a/weaver/src/org/aspectj/weaver/patterns/DeclareSoft.java +++ b/weaver/src/org/aspectj/weaver/patterns/DeclareSoft.java @@ -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: "); diff --git a/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java index 8e980203e..a93cab6bb 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java index eb3cececa..5703251a8 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java @@ -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); } diff --git a/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java b/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java index 8cc32353c..9f8752ad1 100644 --- a/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/HandlerPointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java b/weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java index a05fe013f..90a302d1b 100644 --- a/weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java +++ b/weaver/src/org/aspectj/weaver/patterns/IdentityPointcutVisitor.java @@ -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; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java index 9aa1246f2..d6cf9fa84 100644 --- a/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/IfPointcut.java @@ -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); } diff --git a/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java index 8951931f6..f6c4ef835 100644 --- a/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/KindedPointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/ModifiersPattern.java b/weaver/src/org/aspectj/weaver/patterns/ModifiersPattern.java index a3f5eedce..f1543af1e 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ModifiersPattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/ModifiersPattern.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/NamePattern.java b/weaver/src/org/aspectj/weaver/patterns/NamePattern.java index a2879b1ea..45f4b154a 100644 --- a/weaver/src/org/aspectj/weaver/patterns/NamePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/NamePattern.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java index 37acaa16b..5e0293158 100644 --- a/weaver/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java @@ -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; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java index 47baa7acf..f042f0f82 100644 --- a/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/NotPointcut.java @@ -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; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java index e8dba6cb2..7affe0aa3 100644 --- a/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java @@ -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; + } + } diff --git a/weaver/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java index 6bdf616e4..562fafe00 100644 --- a/weaver/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java @@ -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), diff --git a/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java b/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java index 12abd441b..13317fe38 100644 --- a/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/OrPointcut.java @@ -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; + } } diff --git a/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java index 16fe35872..3355ea508 100644 --- a/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java @@ -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; + } + } diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternNode.java b/weaver/src/org/aspectj/weaver/patterns/PatternNode.java index 817064123..518446a04 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternNode.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternNode.java @@ -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/PointcutVisitor.java b/weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java index 1abf102ff..87a61a694 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PointcutVisitor.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternNodeVisitor.java @@ -8,6 +8,7 @@ * * Contributors: * Alexandre Vasseur initial implementation + * Adrian Colyer refactoring for traversal and grouping by kind *******************************************************************************/ package org.aspectj.weaver.patterns; @@ -18,122 +19,85 @@ import org.aspectj.weaver.Member; * * @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); +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(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(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(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(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(NotTypePattern node, Object data); - - Object visit(OrAnnotationTypePattern 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); - Object visit(OrTypePattern 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); - Object visit(PatternNode node, Object data); - - Object visit(ReferencePointcut 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(ThisOrTargetAnnotationPointcut node, Object data); - - Object visit(ThisOrTargetPointcut node, Object data); - Object visit(ThrowsPattern node, Object data); + Object visit(TypeVariable node, Object data); + Object visit(TypeVariablePatternList 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); + // 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 PointcutVisitor { + static class DumpPointcutVisitor implements PatternNodeVisitor { private StringBuffer sb = new StringBuffer(); public String get() { @@ -259,7 +223,7 @@ public interface PointcutVisitor { } public Object visit(CflowPointcut node, Object data) { - append(node.isBelow()?"cflowbelow(":"cflow("); + append(node.isCflowBelow()?"cflowbelow(":"cflow("); node.getEntry().accept(this, data); append(')'); return null; @@ -584,6 +548,16 @@ public interface PointcutVisitor { 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); @@ -610,13 +584,11 @@ public interface PointcutVisitor { 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))" + //"@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++) { diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java index d63484e0f..deb98242f 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java @@ -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; } diff --git a/weaver/src/org/aspectj/weaver/patterns/PerCflow.java b/weaver/src/org/aspectj/weaver/patterns/PerCflow.java index b61223ccf..c66d3e43a 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerCflow.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerCflow.java @@ -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; } diff --git a/weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java b/weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java index 63131f5ad..6b963df1a 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerFromSuper.java @@ -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"); } diff --git a/weaver/src/org/aspectj/weaver/patterns/PerObject.java b/weaver/src/org/aspectj/weaver/patterns/PerObject.java index a9294e853..b3494cd85 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerObject.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerObject.java @@ -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()); diff --git a/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java b/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java index 5b3b9f954..6554e4157 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerSingleton.java @@ -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; } diff --git a/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java b/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java index bd8873e27..b3c6cdd92 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java +++ b/weaver/src/org/aspectj/weaver/patterns/PerTypeWithin.java @@ -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); diff --git a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java index 886d1af9d..402c4ad47 100644 --- a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java @@ -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/ReferencePointcut.java b/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java index 1b18cced8..1dab1b0ba 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ReferencePointcut.java @@ -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 index 000000000..dcab3ba4f --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/ScopeWithTypeVariables.java @@ -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); + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java index 0cdd94dec..012d7c99a 100644 --- a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java index be281ffc4..da45228ea 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java index 2a2d6786b..958c9d8ba 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetPointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java b/weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java index 9977c3c5e..db3981040 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/ThrowsPattern.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/TypePattern.java b/weaver/src/org/aspectj/weaver/patterns/TypePattern.java index e541b3946..a99f05ed8 100644 --- a/weaver/src/org/aspectj/weaver/patterns/TypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/TypePattern.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java b/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java index 67327aa3d..33bdca150 100644 --- a/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java +++ b/weaver/src/org/aspectj/weaver/patterns/TypePatternList.java @@ -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 index 000000000..8c667f010 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/TypeVariable.java @@ -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><T> T genericMethod(T t) {...}</li> + * <li>static <T extends Foo> T staticGenericMethod(T t) {...}</li> + * <li>Foo<T extends Bar & IGoo> + * </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 index 000000000..1107d4e81 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/TypeVariablePatternList.java @@ -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. <T,S> + */ +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; + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java index c75924b1d..124e4508f 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/WildAnnotationTypePattern.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java index 2e5b98f5d..31df81d09 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java @@ -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); } diff --git a/weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java index a00734b1d..e66e9c676 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java index b1eae06cc..8ee9fdd64 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java index 142c97825..18c58a5d6 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/WithinPointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java index 04d0230b9..e3f64f9de 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/WithincodePointcut.java @@ -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); } } diff --git a/weaver/src/org/aspectj/weaver/tools/PointcutExpression.java b/weaver/src/org/aspectj/weaver/tools/PointcutExpression.java index 2da27a246..2f3a09e4a 100644 --- a/weaver/src/org/aspectj/weaver/tools/PointcutExpression.java +++ b/weaver/src/org/aspectj/weaver/tools/PointcutExpression.java @@ -23,6 +23,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 * @param thisClass the type making the method call diff --git a/weaver/src/org/aspectj/weaver/tools/PointcutPrimitive.java b/weaver/src/org/aspectj/weaver/tools/PointcutPrimitive.java new file mode 100644 index 000000000..cd357e743 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/tools/PointcutPrimitive.java @@ -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 index d6c13e186..000000000 --- a/weaver/src/org/aspectj/weaver/tools/PointcutPrimitives.java +++ /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 index 000000000..49f6555f6 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/tools/UnsupportedPointcutPrimitiveException.java @@ -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; + } + +} diff --git a/weaver/testdata/dummyAspect.jar b/weaver/testdata/dummyAspect.jar Binary files differindex af35626c6..8095fddf4 100644 --- a/weaver/testdata/dummyAspect.jar +++ b/weaver/testdata/dummyAspect.jar diff --git a/weaver/testdata/ltw-acaspects.jar b/weaver/testdata/ltw-acaspects.jar Binary files differindex 7ee6e9888..ed55e51bc 100644 --- a/weaver/testdata/ltw-acaspects.jar +++ b/weaver/testdata/ltw-acaspects.jar diff --git a/weaver/testdata/ltw-aspects.jar b/weaver/testdata/ltw-aspects.jar Binary files differindex f09ee3db1..2e1e86fb1 100644 --- a/weaver/testdata/ltw-aspects.jar +++ b/weaver/testdata/ltw-aspects.jar diff --git a/weaver/testdata/ltw-classes.jar b/weaver/testdata/ltw-classes.jar Binary files differindex 1dfcc034b..014510d57 100644 --- a/weaver/testdata/ltw-classes.jar +++ b/weaver/testdata/ltw-classes.jar diff --git a/weaver/testdata/ltw-deaspects.jar b/weaver/testdata/ltw-deaspects.jar Binary files differindex 186e49409..853e7147b 100644 --- a/weaver/testdata/ltw-deaspects.jar +++ b/weaver/testdata/ltw-deaspects.jar diff --git a/weaver/testdata/ltw-dwaspects.jar b/weaver/testdata/ltw-dwaspects.jar Binary files differindex 791213a88..7ca214cf3 100644 --- a/weaver/testdata/ltw-dwaspects.jar +++ b/weaver/testdata/ltw-dwaspects.jar diff --git a/weaver/testdata/ltw-itdaspects.jar b/weaver/testdata/ltw-itdaspects.jar Binary files differindex eedfaf505..6144a3f6f 100644 --- a/weaver/testdata/ltw-itdaspects.jar +++ b/weaver/testdata/ltw-itdaspects.jar diff --git a/weaver/testdata/ltw-peraspects.jar b/weaver/testdata/ltw-peraspects.jar Binary files differindex 53f31b7e6..2c37baeb7 100644 --- a/weaver/testdata/ltw-peraspects.jar +++ b/weaver/testdata/ltw-peraspects.jar diff --git a/weaver/testdata/ltw-woven.jar b/weaver/testdata/ltw-woven.jar Binary files differindex c60f5c745..d4f117eea 100644 --- a/weaver/testdata/ltw-woven.jar +++ b/weaver/testdata/ltw-woven.jar diff --git a/weaver/testdata/megatrace.jar b/weaver/testdata/megatrace.jar Binary files differindex 23a58710d..8735641c5 100644 --- a/weaver/testdata/megatrace.jar +++ b/weaver/testdata/megatrace.jar diff --git a/weaver/testdata/megatrace0easy.jar b/weaver/testdata/megatrace0easy.jar Binary files differindex 4c025a67f..11deb555c 100644 --- a/weaver/testdata/megatrace0easy.jar +++ b/weaver/testdata/megatrace0easy.jar diff --git a/weaver/testdata/megatrace0hard.jar b/weaver/testdata/megatrace0hard.jar Binary files differindex 15f34d5d3..84f4a7b1e 100644 --- a/weaver/testdata/megatrace0hard.jar +++ b/weaver/testdata/megatrace0hard.jar diff --git a/weaver/testdata/megatraceNoweave.jar b/weaver/testdata/megatraceNoweave.jar Binary files differindex 3d5b1fa08..4f8d26a4a 100644 --- a/weaver/testdata/megatraceNoweave.jar +++ b/weaver/testdata/megatraceNoweave.jar diff --git a/weaver/testdata/tracing.jar b/weaver/testdata/tracing.jar Binary files differindex 8ce561163..1a50581b1 100644 --- a/weaver/testdata/tracing.jar +++ b/weaver/testdata/tracing.jar diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java index 3ca01ffc0..2b80740c7 100644 --- a/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java +++ b/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java @@ -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."}); diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/PointcutTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/PointcutTestCase.java index 039bf89d5..857c82171 100644 --- a/weaver/testsrc/org/aspectj/weaver/patterns/PointcutTestCase.java +++ b/weaver/testsrc/org/aspectj/weaver/patterns/PointcutTestCase.java @@ -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; diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/VisitorTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/VisitorTestCase.java index b3a2a73bf..12218df8b 100644 --- a/weaver/testsrc/org/aspectj/weaver/patterns/VisitorTestCase.java +++ b/weaver/testsrc/org/aspectj/weaver/patterns/VisitorTestCase.java @@ -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()); } diff --git a/weaver/testsrc/org/aspectj/weaver/tools/PointcutExpressionTest.java b/weaver/testsrc/org/aspectj/weaver/tools/PointcutExpressionTest.java index 411716b95..6e3e3d35e 100644 --- a/weaver/testsrc/org/aspectj/weaver/tools/PointcutExpressionTest.java +++ b/weaver/testsrc/org/aspectj/weaver/tools/PointcutExpressionTest.java @@ -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(); |