diff options
author | acolyer <acolyer> | 2004-12-06 13:58:33 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2004-12-06 13:58:33 +0000 |
commit | a0d450944630dbc637ed841cf33eecbdebe2a3d2 (patch) | |
tree | 0c9659a2245bf07434857f603828914aadd80362 | |
parent | 9052d5d86cfcdeb9a64ed903beea53d077f0de08 (diff) | |
download | aspectj-a0d450944630dbc637ed841cf33eecbdebe2a3d2.tar.gz aspectj-a0d450944630dbc637ed841cf33eecbdebe2a3d2.zip |
work in progress.... annotation pointcuts, parsing, and patterns
54 files changed, 1826 insertions, 60 deletions
diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseShadow.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseShadow.java index eebb06dab..3ba294132 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseShadow.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseShadow.java @@ -100,7 +100,31 @@ public class EclipseShadow extends Shadow { public Var getThisEnclosingJoinPointStaticPartVar() { throw new RuntimeException("unimplemented"); } + + public Var getArgAnnotationVar(int i, TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + + public Var getKindedAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + + public Var getTargetAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + public Var getThisAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + + public Var getWithinAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + + public Var getWithinCodeAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + // --- factory methods public static EclipseShadow makeShadow(EclipseFactory world, ASTNode astNode, diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PointcutBinding.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PointcutBinding.java index ce8012806..51456722c 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PointcutBinding.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/PointcutBinding.java @@ -20,14 +20,14 @@ import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding; public class PointcutBinding extends Binding { /** - * @see org.eclipse.jdt.internal.compiler.lookup.Binding#bindingType() + * @see org.eclipse.jdt.internal.compiler.lookup.BindingPattern#bindingType() */ public int bindingType() { return 0; } /** - * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName() + * @see org.eclipse.jdt.internal.compiler.lookup.BindingPattern#readableName() */ public char[] readableName() { return null; diff --git a/org.aspectj.ajdt.core/testdata/OutjarTest/aspects.jar b/org.aspectj.ajdt.core/testdata/OutjarTest/aspects.jar Binary files differindex 07b10246a..807d8a372 100644 --- a/org.aspectj.ajdt.core/testdata/OutjarTest/aspects.jar +++ b/org.aspectj.ajdt.core/testdata/OutjarTest/aspects.jar diff --git a/org.aspectj.ajdt.core/testdata/OutjarTest/child.jar b/org.aspectj.ajdt.core/testdata/OutjarTest/child.jar Binary files differindex 1806f71fd..8f587d14f 100644 --- a/org.aspectj.ajdt.core/testdata/OutjarTest/child.jar +++ b/org.aspectj.ajdt.core/testdata/OutjarTest/child.jar diff --git a/org.aspectj.ajdt.core/testdata/OutjarTest/parent.jar b/org.aspectj.ajdt.core/testdata/OutjarTest/parent.jar Binary files differindex 665fe02d8..6b189266e 100644 --- a/org.aspectj.ajdt.core/testdata/OutjarTest/parent.jar +++ b/org.aspectj.ajdt.core/testdata/OutjarTest/parent.jar diff --git a/tests/harness/classpathTest/jars/required.jar b/tests/harness/classpathTest/jars/required.jar Binary files differindex 368789bd5..7267c1312 100644 --- a/tests/harness/classpathTest/jars/required.jar +++ b/tests/harness/classpathTest/jars/required.jar diff --git a/tests/harness/classpathTest/jars/requiredAspects.jar b/tests/harness/classpathTest/jars/requiredAspects.jar Binary files differindex 952176904..ce235c1b2 100644 --- a/tests/harness/classpathTest/jars/requiredAspects.jar +++ b/tests/harness/classpathTest/jars/requiredAspects.jar diff --git a/tests/incremental/initialTests/expClasses/expected/Main.class b/tests/incremental/initialTests/expClasses/expected/Main.class Binary files differindex fba840b69..fd25eb1dc 100644 --- a/tests/incremental/initialTests/expClasses/expected/Main.class +++ b/tests/incremental/initialTests/expClasses/expected/Main.class diff --git a/weaver/src/org/aspectj/weaver/AnnotatedElement.java b/weaver/src/org/aspectj/weaver/AnnotatedElement.java new file mode 100644 index 000000000..eae2c1a5c --- /dev/null +++ b/weaver/src/org/aspectj/weaver/AnnotatedElement.java @@ -0,0 +1,19 @@ +/* ******************************************************************* + * 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; + +/** + * Represents any element that may have annotations + */ +public interface AnnotatedElement { + boolean hasAnnotation(TypeX ofType); + + // SomeType getAnnotation(TypeX ofType); +} diff --git a/weaver/src/org/aspectj/weaver/Member.java b/weaver/src/org/aspectj/weaver/Member.java index 3f7e9205c..b1186624b 100644 --- a/weaver/src/org/aspectj/weaver/Member.java +++ b/weaver/src/org/aspectj/weaver/Member.java @@ -24,7 +24,7 @@ import java.util.List; import org.aspectj.util.TypeSafeEnum; -public class Member implements Comparable { +public class Member implements Comparable, AnnotatedElement { private final Kind kind; private final TypeX declaringType; @@ -464,6 +464,13 @@ public class Member implements Comparable { else return name; } + /* (non-Javadoc) + * @see org.aspectj.weaver.AnnotatedElement#hasAnnotation(org.aspectj.weaver.TypeX) + */ + public boolean hasAnnotation(TypeX ofType) { + // TODO complete this method + return false; + } // ---- fields 'n' stuff public static final Member[] NONE = new Member[0]; diff --git a/weaver/src/org/aspectj/weaver/Shadow.java b/weaver/src/org/aspectj/weaver/Shadow.java index de2348a4d..85cd0ad87 100644 --- a/weaver/src/org/aspectj/weaver/Shadow.java +++ b/weaver/src/org/aspectj/weaver/Shadow.java @@ -148,6 +148,14 @@ public abstract class Shadow { public abstract Var getThisJoinPointStaticPartVar(); public abstract Var getThisEnclosingJoinPointStaticPartVar(); + // annotation variables + public abstract Var getKindedAnnotationVar(TypeX forAnnotationType); + public abstract Var getWithinAnnotationVar(TypeX forAnnotationType); + public abstract Var getWithinCodeAnnotationVar(TypeX forAnnotationType); + public abstract Var getThisAnnotationVar(TypeX forAnnotationType); + public abstract Var getTargetAnnotationVar(TypeX forAnnotationType); + public abstract Var getArgAnnotationVar(int i, TypeX forAnnotationType); + public abstract Member getEnclosingCodeSignature(); diff --git a/weaver/src/org/aspectj/weaver/TypeX.java b/weaver/src/org/aspectj/weaver/TypeX.java index 05bf35641..3d424618d 100644 --- a/weaver/src/org/aspectj/weaver/TypeX.java +++ b/weaver/src/org/aspectj/weaver/TypeX.java @@ -18,7 +18,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.Iterator; -public class TypeX { +public class TypeX implements AnnotatedElement { /** * This is the bytecode string representation of this Type */ @@ -552,6 +552,11 @@ public class TypeX { return world.resolve(this); } + public boolean hasAnnotation(TypeX ofType) { + //TODO implement TypeX.hasAnnotation + return false; + } + // ---- fields public static final TypeX[] NONE = new TypeX[0]; diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java index c08fc485c..fe32b0aa6 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java @@ -15,8 +15,10 @@ package org.aspectj.weaver.bcel; import java.lang.reflect.Modifier; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import org.aspectj.apache.bcel.Constants; import org.aspectj.apache.bcel.classfile.Field; @@ -868,6 +870,12 @@ public class BcelShadow extends Shadow { private BcelVar thisVar = null; private BcelVar targetVar = null; private BcelVar[] argVars = null; + private Map/*<TypeX,BcelVar>*/ kindedAnnotationVars = null; + private Map/*<TypeX,BcelVar>*/ thisAnnotationVars = null; + private Map/*<TypeX,BcelVar>*/ targetAnnotationVars = null; + private Map/*<TypeX,BcelVar>*/[] argAnnotationVars = null; + private Map/*<TypeX,BcelVar>*/ withinAnnotationVars = null; + private Map/*<TypeX,BcelVar>*/ withincodeAnnotationVars = null; public Var getThisVar() { if (!hasThis()) { @@ -876,18 +884,48 @@ public class BcelShadow extends Shadow { initializeThisVar(); return thisVar; } + public Var getThisAnnotationVar(TypeX forAnnotationType) { + if (!hasThis()) { + throw new IllegalStateException("no this"); + } + initializeThisAnnotationVars(); + return (Var) thisAnnotationVars.get(forAnnotationType); + } public Var getTargetVar() { if (!hasTarget()) { throw new IllegalStateException("no target"); } initializeTargetVar(); return targetVar; + } + public Var getTargetAnnotationVar(TypeX forAnnotationType) { + if (!hasTarget()) { + throw new IllegalStateException("no target"); } - public Var getArgVar(int i) { + initializeTargetAnnotationVars(); + return (Var) targetAnnotationVars.get(forAnnotationType); + } + public Var getArgVar(int i) { initializeArgVars(); return argVars[i]; - } - + } + public Var getArgAnnotationVar(int i,TypeX forAnnotationType) { + initializeArgAnnotationVars(); + return (Var) argAnnotationVars[i].get(forAnnotationType); + } + public Var getKindedAnnotationVar(TypeX forAnnotationType) { + initializeKindedAnnotationVars(); + return (Var) kindedAnnotationVars.get(forAnnotationType); + } + public Var getWithinAnnotationVar(TypeX forAnnotationType) { + initializeWithinAnnotationVars(); + return (Var) withinAnnotationVars.get(forAnnotationType); + } + public Var getWithinCodeAnnotationVar(TypeX forAnnotationType) { + initializeWithinCodeAnnotationVars(); + return (Var) withincodeAnnotationVars.get(forAnnotationType); + } + // reflective thisJoinPoint support private BcelVar thisJoinPointVar = null; private boolean isThisJoinPointLazy; @@ -1227,6 +1265,50 @@ public class BcelShadow extends Shadow { // System.out.println("initialized: " + this + " thisVar = " + thisVar); } + public void initializeThisAnnotationVars() { + if (thisAnnotationVars != null) return; + thisAnnotationVars = new HashMap(); + // populate.. + } + public void initializeTargetAnnotationVars() { + if (targetAnnotationVars != null) return; + if (getKind().isTargetSameAsThis()) { + if (hasThis()) initializeThisAnnotationVars(); + targetAnnotationVars = thisAnnotationVars; + } else { + targetAnnotationVars = new HashMap(); + // populate. + } + } + public void initializeArgAnnotationVars() { + if (argAnnotationVars != null) return; + int numArgs = getArgCount(); + argAnnotationVars = new Map[numArgs]; + for (int i = 0; i < argAnnotationVars.length; i++) { + argAnnotationVars[i] = new HashMap(); + // populate + } + } + public void initializeKindedAnnotationVars() { + if (kindedAnnotationVars != null) return; + kindedAnnotationVars = new HashMap(); + // by determining what "kind" of shadow we are, we can find out the + // annotations on the appropriate element (method, field, constructor, type). + // Then create one BcelVar entry in the map for each annotation, keyed by + // annotation type (TypeX). + + } + public void initializeWithinAnnotationVars() { + if (withinAnnotationVars != null) return; + withinAnnotationVars = new HashMap(); + // populate + } + public void initializeWithinCodeAnnotationVars() { + if (withincodeAnnotationVars != null) return; + withincodeAnnotationVars = new HashMap(); + // populate + } + // ---- weave methods diff --git a/weaver/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java new file mode 100644 index 000000000..3d4eb11e9 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/AndAnnotationTypePattern.java @@ -0,0 +1,83 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.AnnotatedElement; +import org.aspectj.weaver.ISourceContext; + +/** + * @author colyer + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +public class AndAnnotationTypePattern extends AnnotationTypePattern { + + private AnnotationTypePattern left; + private AnnotationTypePattern right; + + public AndAnnotationTypePattern(AnnotationTypePattern left, AnnotationTypePattern right) { + this.left = left; + this.right = right; + setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); + } + + public FuzzyBoolean matches(AnnotatedElement annotated) { + return left.matches(annotated).and(right.matches(annotated)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings, boolean) + */ + public AnnotationTypePattern resolveBindings(IScope scope, + Bindings bindings, boolean allowBinding) { + left = left.resolveBindings(scope,bindings,allowBinding); + right =right.resolveBindings(scope,bindings,allowBinding); + return this; + } + + public static AnnotationTypePattern read(DataInputStream s, ISourceContext context) throws IOException { + AnnotationTypePattern p = new AndAnnotationTypePattern( + AnnotationTypePattern.read(s,context), + AnnotationTypePattern.read(s,context)); + p.readLocation(context,s); + return p; + } + + public void write(DataOutputStream s) throws IOException { + s.writeByte(AnnotationTypePattern.AND); + left.write(s); + right.write(s); + writeLocation(s); + } + + public boolean equals(Object obj) { + if (!(obj instanceof AndAnnotationTypePattern)) return false; + AndAnnotationTypePattern other = (AndAnnotationTypePattern) obj; + return (left.equals(other.left) && right.equals(other.right)); + } + + public int hashCode() { + int result = 17; + result = result*37 + left.hashCode(); + result = result*37 + right.hashCode(); + return result; + } + + public String toString() { + return "(" + left.toString() + " && " + right.toString() + ")"; + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java index c055692fe..bb94f602d 100644 --- a/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/AndTypePattern.java @@ -33,7 +33,7 @@ public class AndTypePattern extends TypePattern { private TypePattern left, right; public AndTypePattern(TypePattern left, TypePattern right) { - super(false); //??? we override all methods that care about includeSubtypes + super(false,false); //??? we override all methods that care about includeSubtypes this.left = left; this.right = right; setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); diff --git a/weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java b/weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java new file mode 100644 index 000000000..140e83f42 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/AnnotationPatternList.java @@ -0,0 +1,133 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; + +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.IntMap; + +/** + * @author colyer + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +public class AnnotationPatternList extends PatternNode { + + private AnnotationTypePattern[] typePatterns; + int ellipsisCount = 0; + + public static final AnnotationPatternList EMPTY = + new AnnotationPatternList(new AnnotationTypePattern[] {}); + + public static final AnnotationPatternList ANY = + new AnnotationPatternList(new AnnotationTypePattern[] {AnnotationTypePattern.ELLIPSIS}); + + public AnnotationPatternList() { + typePatterns = new AnnotationTypePattern[0]; + ellipsisCount = 0; + } + + public AnnotationPatternList(AnnotationTypePattern[] arguments) { + this.typePatterns = arguments; + for (int i=0; i<arguments.length; i++) { + if (arguments[i] == AnnotationTypePattern.ELLIPSIS) ellipsisCount++; + } + } + + public AnnotationPatternList(List l) { + this((AnnotationTypePattern[]) l.toArray(new AnnotationTypePattern[l.size()])); + } + + public int size() { return typePatterns.length; } + + public AnnotationTypePattern get(int index) { + return typePatterns[index]; + } + + public AnnotationPatternList resolveBindings(IScope scope, Bindings bindings, boolean allowBinding) { + for (int i=0; i<typePatterns.length; i++) { + AnnotationTypePattern p = typePatterns[i]; + if (p != null) { + typePatterns[i] = typePatterns[i].resolveBindings(scope, bindings, allowBinding); + } + } + return this; + } + + public AnnotationPatternList resolveReferences(IntMap bindings) { + int len = typePatterns.length; + AnnotationTypePattern[] ret = new AnnotationTypePattern[len]; + for (int i=0; i < len; i++) { + ret[i] = typePatterns[i].remapAdviceFormals(bindings); + } + return new AnnotationPatternList(ret); + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("("); + for (int i=0, len=typePatterns.length; i < len; i++) { + AnnotationTypePattern type = typePatterns[i]; + if (i > 0) buf.append(", "); + if (type == AnnotationTypePattern.ELLIPSIS) { + buf.append(".."); + } else { + buf.append(type.toString()); + } + } + buf.append(")"); + return buf.toString(); + } + + public boolean equals(Object other) { + if (!(other instanceof AnnotationPatternList)) return false; + AnnotationPatternList o = (AnnotationPatternList)other; + int len = o.typePatterns.length; + if (len != this.typePatterns.length) return false; + for (int i=0; i<len; i++) { + if (!this.typePatterns[i].equals(o.typePatterns[i])) return false; + } + return true; + } + + public int hashCode() { + int result = 41; + for (int i = 0, len = typePatterns.length; i < len; i++) { + result = 37*result + typePatterns[i].hashCode(); + } + return result; + } + + public static AnnotationPatternList read(DataInputStream s, ISourceContext context) throws IOException { + short len = s.readShort(); + AnnotationTypePattern[] arguments = new AnnotationTypePattern[len]; + for (int i=0; i<len; i++) { + arguments[i] = AnnotationTypePattern.read(s, context); + } + AnnotationPatternList ret = new AnnotationPatternList(arguments); + ret.readLocation(context, s); + return ret; + } + + + public void write(DataOutputStream s) throws IOException { + s.writeShort(typePatterns.length); + for (int i=0; i<typePatterns.length; i++) { + typePatterns[i].write(s); + } + writeLocation(s); + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java new file mode 100644 index 000000000..5b2560cbe --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java @@ -0,0 +1,99 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.AnnotatedElement; +import org.aspectj.weaver.BCException; +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.IntMap; + +public abstract class AnnotationTypePattern extends PatternNode { + + public static final AnnotationTypePattern ANY = new AnyAnnotationTypePattern(); + public static final AnnotationTypePattern ELLIPSIS = new EllipsisAnnotationTypePattern(); + + /** + * TODO: write, read, equals & hashcode both in annotation hierarachy and + * in altered TypePattern hierarchy + */ + protected AnnotationTypePattern() { + super(); + } + + public abstract FuzzyBoolean matches(AnnotatedElement annotated); + + public AnnotationTypePattern remapAdviceFormals(IntMap bindings) { + return this; + } + + /** + * This can modify in place, or return a new TypePattern if the type changes. + */ + public AnnotationTypePattern resolveBindings(IScope scope, Bindings bindings, + boolean allowBinding) + { + return this; + } + + + public static final byte EXACT = 1; + public static final byte BINDING = 2; + public static final byte NOT = 3; + public static final byte OR = 4; + public static final byte AND = 5; + public static final byte ELLIPSIS_KEY = 6; + public static final byte ANY_KEY = 7; + + public static AnnotationTypePattern read(DataInputStream s, ISourceContext context) throws IOException { + byte key = s.readByte(); + switch(key) { + case EXACT: return ExactAnnotationTypePattern.read(s, context); +// case BINDING: return BindingAnnotationTypePattern.read(s, context); + case NOT: return NotAnnotationTypePattern.read(s, context); + case OR: return OrAnnotationTypePattern.read(s, context); + case AND: return AndAnnotationTypePattern.read(s, context); + case ELLIPSIS_KEY: return ELLIPSIS; + case ANY_KEY: return ANY; + } + throw new BCException("unknown TypePattern kind: " + key); + } + +} + +class AnyAnnotationTypePattern extends AnnotationTypePattern { + + public FuzzyBoolean matches(AnnotatedElement annotated) { + return FuzzyBoolean.YES; + } + + public void write(DataOutputStream s) throws IOException { + s.writeByte(AnnotationTypePattern.ANY_KEY); + } + + public String toString() { return "@ANY"; } +} + +class EllipsisAnnotationTypePattern extends AnnotationTypePattern { + + public FuzzyBoolean matches(AnnotatedElement annotated) { + return FuzzyBoolean.NO; + } + + public void write(DataOutputStream s) throws IOException { + s.writeByte(AnnotationTypePattern.ELLIPSIS_KEY); + } + + public String toString() { return ".."; } +}
\ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java new file mode 100644 index 000000000..9d37412a3 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/ArgsAnnotationPointcut.java @@ -0,0 +1,94 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.IntMap; +import org.aspectj.weaver.ResolvedTypeX; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.ast.Test; + +/** + * @author colyer + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +public class ArgsAnnotationPointcut extends NameBindingPointcut { + + private AnnotationPatternList arguments; + /** + * + */ + public ArgsAnnotationPointcut(AnnotationPatternList arguments) { + super(); + this.arguments = arguments; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) + */ + public FuzzyBoolean fastMatch(FastMatchInfo info) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) + */ + public FuzzyBoolean match(Shadow shadow) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings) + */ + protected void resolveBindings(IScope scope, Bindings bindings) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindingsFromRTTI() + */ + protected void resolveBindingsFromRTTI() { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedTypeX, org.aspectj.weaver.IntMap) + */ + protected Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) + */ + public Test findResidue(Shadow shadow, ExposedState state) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + // TODO Auto-generated method stub + + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java b/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java index 5cfdc6a4a..c8c215a3d 100644 --- a/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java +++ b/weaver/src/org/aspectj/weaver/patterns/BasicTokenSource.java @@ -104,6 +104,7 @@ public class BasicTokenSource implements ITokenSource { case ',': case '!': case ':': + case '@': tokens.add(BasicToken.makeOperator(makeString(ch), i-1, i-1)); continue; case '&': diff --git a/weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java new file mode 100644 index 000000000..2949bb5e7 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java @@ -0,0 +1,80 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.weaver.BCException; +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.IntMap; +import org.aspectj.weaver.TypeX; + +public class BindingAnnotationTypePattern extends ExactAnnotationTypePattern implements BindingPattern { + + private int formalIndex; + + /** + * @param annotationType + */ + public BindingAnnotationTypePattern(TypeX annotationType, int index) { + super(annotationType); + this.formalIndex = index; + } + + public BindingAnnotationTypePattern(FormalBinding binding) { + this(binding.getType(),binding.getIndex()); + } + + public int getFormalIndex() { + return formalIndex; + } + + public boolean equals(Object obj) { + if (!(obj instanceof BindingAnnotationTypePattern)) return false; + BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern) obj; + return (super.equals(btp) && (btp.formalIndex == formalIndex)); + } + + public int hashCode() { + return super.hashCode()*37 + formalIndex; + } + + public AnnotationTypePattern remapAdviceFormals(IntMap bindings) { + if (!bindings.hasKey(formalIndex)) { + return new ExactAnnotationTypePattern(annotationType); + } else { + int newFormalIndex = bindings.get(formalIndex); + return new BindingAnnotationTypePattern(annotationType, newFormalIndex); + } + } + private static final byte VERSION = 1; // rev if serialised form changed + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.ExactAnnotationTypePattern#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + s.writeByte(AnnotationTypePattern.BINDING); + s.writeByte(VERSION); + annotationType.write(s); + s.writeShort((short)formalIndex); + writeLocation(s); + } + + public static AnnotationTypePattern read(DataInputStream s, ISourceContext context) throws IOException { + byte version = s.readByte(); + if (version > VERSION) { + throw new BCException("BindingAnnotationTypePattern was written by a more recent version of AspectJ"); + } + AnnotationTypePattern ret = new BindingAnnotationTypePattern(TypeX.read(s),s.readShort()); + ret.readLocation(context,s); + return ret; + } +} diff --git a/weaver/src/org/aspectj/weaver/patterns/BindingPattern.java b/weaver/src/org/aspectj/weaver/patterns/BindingPattern.java new file mode 100644 index 000000000..1b5bab357 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/BindingPattern.java @@ -0,0 +1,19 @@ +/* ******************************************************************* + * 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.patterns; + +import org.aspectj.weaver.IHasPosition; + +/** + * Marker interface for BindingTypePattern and BindingAnnotationTypePattern + */ +public interface BindingPattern extends IHasPosition { + int getFormalIndex(); +} diff --git a/weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java index 87a7b524d..937563c79 100644 --- a/weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/BindingTypePattern.java @@ -21,16 +21,16 @@ import org.aspectj.weaver.ISourceContext; import org.aspectj.weaver.IntMap; import org.aspectj.weaver.TypeX; -public class BindingTypePattern extends ExactTypePattern { +public class BindingTypePattern extends ExactTypePattern implements BindingPattern { private int formalIndex; - public BindingTypePattern(TypeX type, int index) { - super(type, false); + public BindingTypePattern(TypeX type, int index,boolean isVarArgs) { + super(type, false,isVarArgs); this.formalIndex = index; } - public BindingTypePattern(FormalBinding binding) { - this(binding.getType(), binding.getIndex()); + public BindingTypePattern(FormalBinding binding, boolean isVarArgs) { + this(binding.getType(), binding.getIndex(),isVarArgs); } public int getFormalIndex() { @@ -53,21 +53,22 @@ public class BindingTypePattern extends ExactTypePattern { out.writeByte(TypePattern.BINDING); type.write(out); out.writeShort((short)formalIndex); + out.writeBoolean(isVarArgs); writeLocation(out); } public static TypePattern read(DataInputStream s, ISourceContext context) throws IOException { - TypePattern ret = new BindingTypePattern(TypeX.read(s), s.readShort()); + TypePattern ret = new BindingTypePattern(TypeX.read(s), s.readShort(), s.readBoolean()); ret.readLocation(context, s); return ret; } public TypePattern remapAdviceFormals(IntMap bindings) { if (!bindings.hasKey(formalIndex)) { - return new ExactTypePattern(type, false); + return new ExactTypePattern(type, false, isVarArgs); } else { int newFormalIndex = bindings.get(formalIndex); - return new BindingTypePattern(type, newFormalIndex); + return new BindingTypePattern(type, newFormalIndex, isVarArgs); } } diff --git a/weaver/src/org/aspectj/weaver/patterns/Bindings.java b/weaver/src/org/aspectj/weaver/patterns/Bindings.java index 7fd02c179..cf9e660a5 100644 --- a/weaver/src/org/aspectj/weaver/patterns/Bindings.java +++ b/weaver/src/org/aspectj/weaver/patterns/Bindings.java @@ -19,19 +19,19 @@ import org.aspectj.weaver.BCException; public class Bindings { public static final Bindings NONE = new Bindings(0); - private BindingTypePattern[] bindings; + private BindingPattern[] bindings; - public Bindings(BindingTypePattern[] bindings) { + public Bindings(BindingPattern[] bindings) { this.bindings = bindings; } public Bindings(int count) { - this(new BindingTypePattern[count]); + this(new BindingPattern[count]); } - public void register(BindingTypePattern binding, IScope scope) { + public void register(BindingPattern binding, IScope scope) { int index = binding.getFormalIndex(); - BindingTypePattern existingBinding = bindings[index]; + BindingPattern existingBinding = bindings[index]; if (existingBinding != null) { scope.message(IMessage.ERROR, existingBinding, binding, "multiple bindings" + index + ", " + binding); @@ -53,8 +53,8 @@ public class Bindings { * signals an error if one has a binding and other doesn't */ public void checkEquals(Bindings other, IScope scope) { - BindingTypePattern[] b1 = this.bindings; - BindingTypePattern[] b2 = other.bindings; + BindingPattern[] b1 = this.bindings; + BindingPattern[] b2 = other.bindings; int len = b1.length; if (len != b2.length) { throw new BCException("INSANE"); @@ -102,7 +102,7 @@ public class Bindings { // int len = bindings.length; // boolean[] a = new boolean[len]; // System.arraycopy(bindings, 0, a, 0, len); - return new Bindings((BindingTypePattern[])bindings.clone()); + return new Bindings((BindingPattern[])bindings.clone()); } public void checkAllBound(IScope scope) { diff --git a/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java new file mode 100644 index 000000000..3db7d0030 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java @@ -0,0 +1,122 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.bridge.IMessage; +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.AnnotatedElement; +import org.aspectj.weaver.BCException; +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.TypeX; + +/** + * Matches an annotation of a given type + */ +public class ExactAnnotationTypePattern extends AnnotationTypePattern { + + protected TypeX annotationType; + protected String formalName; + + /** + * + */ + public ExactAnnotationTypePattern(TypeX annotationType) { + this.annotationType = annotationType; + } + + public ExactAnnotationTypePattern(String formalName) { + this.formalName = formalName; + // will be turned into BindingAnnotationTypePattern during resolution + } + + public FuzzyBoolean matches(AnnotatedElement annotated) { + return (annotated.hasAnnotation(annotationType) ? + FuzzyBoolean.YES : FuzzyBoolean.NO); + } + + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings, boolean) + */ + public AnnotationTypePattern resolveBindings(IScope scope, + Bindings bindings, boolean allowBinding) { + if (formalName != null) { + FormalBinding formalBinding = scope.lookupFormal(formalName); + if (formalBinding != null) { + if (bindings == null) { + scope.message(IMessage.ERROR, this, "negation doesn't allow binding"); + return this; + } + if (!allowBinding) { + scope.message(IMessage.ERROR, this, + "name binding only allowed in @pcds, args, this, and target"); + return this; + } + + BindingAnnotationTypePattern binding = new BindingAnnotationTypePattern(formalBinding); + binding.copyLocationFrom(this); + bindings.register(binding, scope); + + return binding; + } else { + scope.message(IMessage.ERROR,this,"unbound formal " + formalName); + return this; + } + } else { + return this; + } + } + + private static byte VERSION = 1; // rev if serialisation form changes + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + s.writeByte(AnnotationTypePattern.EXACT); + s.writeByte(VERSION); + annotationType.write(s); + writeLocation(s); + } + + public static AnnotationTypePattern read(DataInputStream s,ISourceContext context) throws IOException { + AnnotationTypePattern ret; + byte version = s.readByte(); + if (version > VERSION) { + throw new BCException("ExactAnnotationTypePattern was written by a newer version of AspectJ"); + } + ret = new ExactAnnotationTypePattern(TypeX.read(s)); + ret.readLocation(context,s); + return ret; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (!(obj instanceof ExactAnnotationTypePattern)) return false; + ExactAnnotationTypePattern other = (ExactAnnotationTypePattern) obj; + return (other.annotationType.equals(annotationType)); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + return annotationType.hashCode(); + } + + public String toString() { + return "@" + annotationType.toString(); + } +} diff --git a/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java index aa77747bf..36917a297 100644 --- a/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/ExactTypePattern.java @@ -63,8 +63,8 @@ public class ExactTypePattern extends TypePattern { } - public ExactTypePattern(TypeX type, boolean includeSubtypes) { - super(includeSubtypes); + public ExactTypePattern(TypeX type, boolean includeSubtypes,boolean isVarArgs) { + super(includeSubtypes,isVarArgs); this.type = type; } @@ -151,22 +151,32 @@ public class ExactTypePattern extends TypePattern { public boolean equals(Object other) { if (!(other instanceof ExactTypePattern)) return false; ExactTypePattern o = (ExactTypePattern)other; - return o.type.equals(this.type); + return (o.type.equals(this.type) && o.annotationPattern.equals(this.annotationPattern)); } public int hashCode() { - return type.hashCode(); + int result = 17; + result = 37*result + type.hashCode(); + result = 37*result + annotationPattern.hashCode(); + return result; } - + + private static final byte EXACT_VERSION = 1; // rev if changed public void write(DataOutputStream out) throws IOException { out.writeByte(TypePattern.EXACT); + out.writeByte(EXACT_VERSION); type.write(out); out.writeBoolean(includeSubtypes); + out.writeBoolean(isVarArgs); + annotationPattern.write(out); writeLocation(out); } public static TypePattern read(DataInputStream s, ISourceContext context) throws IOException { - TypePattern ret = new ExactTypePattern(TypeX.read(s), s.readBoolean()); + byte version = s.readByte(); + 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.readLocation(context, s); return ret; } diff --git a/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java new file mode 100644 index 000000000..08960c228 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java @@ -0,0 +1,186 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.bridge.ISourceLocation; +import org.aspectj.bridge.Message; +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.ISourceContext; +import org.aspectj.weaver.IntMap; +import org.aspectj.weaver.ResolvedTypeX; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.ShadowMunger; +import org.aspectj.weaver.TypeX; +import org.aspectj.weaver.ast.Literal; +import org.aspectj.weaver.ast.Test; +import org.aspectj.weaver.ast.Var; + +/** + * A KindedAnnotationPointcut matches iff the kind of a join point + * matches the kind of the pointcut (with no distinction between + * method and constructor for call and execution), AND if the + * member (field, method or constructor) has an annotation of the + * given type. + */ +public class KindedAnnotationPointcut extends NameBindingPointcut { + + private Shadow.Kind kind; + private AnnotationTypePattern type; + private ShadowMunger munger = null; // only set after concretization + + public KindedAnnotationPointcut(Shadow.Kind kind, AnnotationTypePattern type) { + super(); + this.kind = kind; + this.type = type; + this.pointcutKind = Pointcut.ATKINDED; + } + + public KindedAnnotationPointcut(Shadow.Kind kind, AnnotationTypePattern type, ShadowMunger munger) { + this(kind,type); + this.munger = munger; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) + */ + public FuzzyBoolean fastMatch(FastMatchInfo info) { + if (info.getKind() != null) { + if (info.getKind() != kind) { + // no distinction between method and constructors + if ((info.getKind() == Shadow.ConstructorExecution) && + kind == Shadow.MethodExecution) { + return FuzzyBoolean.MAYBE; + } + if ((info.getKind() == Shadow.ConstructorCall) && + kind == Shadow.MethodCall) { + return FuzzyBoolean.MAYBE; + } + } else { + return FuzzyBoolean.NO; + } + } + return FuzzyBoolean.MAYBE; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) + */ + public FuzzyBoolean match(Shadow shadow) { + if (!couldMatch(shadow)) return FuzzyBoolean.NO; + return type.matches(shadow.getSignature()); + } + + private boolean couldMatch(Shadow shadow) { + Shadow.Kind kindToMatch = shadow.getKind(); + if (kindToMatch == Shadow.ConstructorExecution) kindToMatch = Shadow.MethodExecution; + if (kindToMatch == Shadow.ConstructorCall) kindToMatch = Shadow.MethodCall; + return (kindToMatch == kind); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings) + */ + protected void resolveBindings(IScope scope, Bindings bindings) { + type = type.resolveBindings(scope,bindings,true); + // must be either a Var, or an annotation type pattern + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindingsFromRTTI() + */ + protected void resolveBindingsFromRTTI() { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedTypeX, org.aspectj.weaver.IntMap) + */ + protected Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { + AnnotationTypePattern newType = type.remapAdviceFormals(bindings); + Pointcut ret = new KindedAnnotationPointcut(kind, newType, bindings.getEnclosingAdvice()); + ret.copyLocationFrom(this); + return ret; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) + */ + public Test findResidue(Shadow shadow, ExposedState state) { + if (!couldMatch(shadow)) return Literal.FALSE; + + if (type instanceof BindingAnnotationTypePattern) { + BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)type; + TypeX annotationType = btp.annotationType; + Var var = shadow.getKindedAnnotationVar(annotationType); + if (var == null) return Literal.FALSE; + // Check if we have already bound something to this formal + if (state.get(btp.getFormalIndex())!=null) { + ISourceLocation pcdSloc = getSourceLocation(); + ISourceLocation shadowSloc = shadow.getSourceLocation(); + Message errorMessage = new Message( + "Cannot use @pointcut to match at this location and bind a formal to type '"+var.getType()+ + "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+ + ". The secondary source location points to the problematic binding.", + shadowSloc,true,new ISourceLocation[]{pcdSloc}); + shadow.getIWorld().getMessageHandler().handleMessage(errorMessage); + state.setErroneousVar(btp.getFormalIndex()); + } + state.set(btp.getFormalIndex(),var); + } + return Literal.TRUE; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + s.writeByte(Pointcut.ATKINDED); + kind.write(s); + type.write(s); + writeLocation(s); + } + + public static Pointcut read(DataInputStream s, ISourceContext context) throws IOException { + Shadow.Kind kind = Shadow.Kind.read(s); + AnnotationTypePattern type = AnnotationTypePattern.read(s, context); + KindedAnnotationPointcut ret = new KindedAnnotationPointcut(kind, type); + ret.readLocation(context, s); + return ret; + } + + public boolean equals(Object other) { + if (!(other instanceof KindedAnnotationPointcut)) return false; + KindedAnnotationPointcut o = (KindedAnnotationPointcut)other; + return o.kind == this.kind && o.type.equals(this.type); + } + + public int hashCode() { + int result = 17; + result = 37*result + kind.hashCode(); + result = 37*result + type.hashCode(); + return result; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(kind.getSimpleName()); + buf.append("("); + buf.append(type.toString()); + buf.append(")"); + return buf.toString(); + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java new file mode 100644 index 000000000..e55df2508 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/NotAnnotationTypePattern.java @@ -0,0 +1,74 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.AnnotatedElement; +import org.aspectj.weaver.ISourceContext; + +public class NotAnnotationTypePattern extends AnnotationTypePattern { + + private AnnotationTypePattern negatedPattern; + + public NotAnnotationTypePattern(AnnotationTypePattern pattern) { + this.negatedPattern = pattern; + setLocation(pattern.getSourceContext(), pattern.getStart(), pattern.getEnd()); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.AnnotationTypePattern#matches(org.aspectj.weaver.AnnotatedElement) + */ + public FuzzyBoolean matches(AnnotatedElement annotated) { + return negatedPattern.matches(annotated).not(); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings, boolean) + */ + public AnnotationTypePattern resolveBindings(IScope scope, + Bindings bindings, boolean allowBinding) { + negatedPattern = negatedPattern.resolveBindings(scope,bindings,allowBinding); + return this; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + s.writeByte(AnnotationTypePattern.NOT); + negatedPattern.write(s); + writeLocation(s); + } + + public static AnnotationTypePattern read(DataInputStream s, ISourceContext context) throws IOException { + AnnotationTypePattern ret = new NotAnnotationTypePattern(AnnotationTypePattern.read(s,context)); + ret.readLocation(context,s); + return ret; + } + + public boolean equals(Object obj) { + if (!(obj instanceof NotAnnotationTypePattern)) return false; + NotAnnotationTypePattern other = (NotAnnotationTypePattern) obj; + return other.negatedPattern.equals(negatedPattern); + } + + public int hashCode() { + int result = 17 + 37*negatedPattern.hashCode(); + return result; + } + + public String toString() { + return "!" + negatedPattern.toString(); + } +} diff --git a/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java index 68a719c73..17a402e91 100644 --- a/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/NotTypePattern.java @@ -34,7 +34,7 @@ public class NotTypePattern extends TypePattern { private TypePattern pattern; public NotTypePattern(TypePattern pattern) { - super(false); //??? we override all methods that care about includeSubtypes + super(false,false); //??? we override all methods that care about includeSubtypes this.pattern = pattern; setLocation(pattern.getSourceContext(), pattern.getStart(), pattern.getEnd()); } diff --git a/weaver/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java new file mode 100644 index 000000000..bd6414d39 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/OrAnnotationTypePattern.java @@ -0,0 +1,77 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.AnnotatedElement; +import org.aspectj.weaver.ISourceContext; + +public class OrAnnotationTypePattern extends AnnotationTypePattern { + + private AnnotationTypePattern left; + private AnnotationTypePattern right; + + public OrAnnotationTypePattern(AnnotationTypePattern left, AnnotationTypePattern right) { + this.left = left; + this.right = right; + setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); + } + + public FuzzyBoolean matches(AnnotatedElement annotated) { + return left.matches(annotated).or(right.matches(annotated)); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.AnnotationTypePattern#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings, boolean) + */ + public AnnotationTypePattern resolveBindings(IScope scope, + Bindings bindings, boolean allowBinding) { + left = left.resolveBindings(scope,bindings,allowBinding); + right =right.resolveBindings(scope,bindings,allowBinding); + return this; + } + + public static AnnotationTypePattern read(DataInputStream s, ISourceContext context) throws IOException { + AnnotationTypePattern p = new OrAnnotationTypePattern( + AnnotationTypePattern.read(s,context), + AnnotationTypePattern.read(s,context)); + p.readLocation(context,s); + return p; + } + + public void write(DataOutputStream s) throws IOException { + s.writeByte(AnnotationTypePattern.OR); + left.write(s); + right.write(s); + writeLocation(s); + } + + public boolean equals(Object obj) { + if (!(obj instanceof OrAnnotationTypePattern)) return false; + OrAnnotationTypePattern other = (OrAnnotationTypePattern) obj; + return (left.equals(other.left) && right.equals(other.right)); + } + + public int hashCode() { + int result = 17; + result = result*37 + left.hashCode(); + result = result*37 + right.hashCode(); + return result; + } + + public String toString() { + return "(" + left.toString() + " || " + right.toString() + ")"; + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java index da53ad6e5..6a423e03c 100644 --- a/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/OrTypePattern.java @@ -33,7 +33,7 @@ public class OrTypePattern extends TypePattern { private TypePattern left, right; public OrTypePattern(TypePattern left, TypePattern right) { - super(false); //??? we override all methods that care about includeSubtypes + super(false,false); //??? we override all methods that care about includeSubtypes this.left = left; this.right = right; setLocation(left.getSourceContext(), left.getStart(), right.getEnd()); diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java index 062f17b21..8a4324bf9 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java @@ -19,9 +19,13 @@ import java.util.List; import org.aspectj.weaver.ISourceContext; import org.aspectj.weaver.Member; import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.TypeX; //XXX doesn't handle errors for extra tokens very well (sometimes ignores) public class PatternParser { + + private static final String AT = "@"; + private ITokenSource tokenSource; private ISourceContext sourceContext; @@ -185,6 +189,13 @@ public class PatternParser { eat(")"); return p; } + if (maybeEat(AT)) { + int startPos = tokenSource.peek().getStart(); + Pointcut p = parseAnnotationPointcut(); + int endPos = tokenSource.peek(-1).getEnd(); + p.setLocation(sourceContext, startPos, endPos); + return p; + } int startPos = tokenSource.peek().getStart(); Pointcut p = parseSinglePointcut(); int endPos = tokenSource.peek(-1).getEnd(); @@ -227,7 +238,8 @@ public class PatternParser { new SignaturePattern(Member.ADVICE, ModifiersPattern.ANY, TypePattern.ANY, TypePattern.ANY, NamePattern.ANY, TypePatternList.ANY, - ThrowsPattern.ANY)); + ThrowsPattern.ANY, + AnnotationTypePattern.ANY)); } else if (kind.equals("handler")) { parseIdentifier(); eat("("); TypePattern typePat = parseTypePattern(); @@ -245,7 +257,7 @@ public class PatternParser { return new KindedPointcut(Shadow.StaticInitialization, new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY, TypePattern.ANY, typePat, NamePattern.ANY, TypePatternList.EMPTY, - ThrowsPattern.ANY)); + ThrowsPattern.ANY,AnnotationTypePattern.ANY)); } else if (kind.equals("preinitialization")) { parseIdentifier(); eat("("); SignaturePattern sig = parseConstructorSignaturePattern(); @@ -256,6 +268,61 @@ public class PatternParser { } } + public Pointcut parseAnnotationPointcut() { + int start = tokenSource.getIndex(); + IToken t = tokenSource.peek(); + String kind = parseIdentifier(); + tokenSource.setIndex(start); + if (kind.equals("execution") || kind.equals("call") || + kind.equals("get") || kind.equals("set") || + kind.equals("adviceexecution") || + kind.equals("initialization") || + kind.equals("preinitialization") || + kind.equals("staticinitialization")) { + return parseKindedAnnotationPointcut(); + } else if (kind.equals("args")) { + return parseArgsAnnotationPointcut(); + } else if (kind.equals("this") || kind.equals("target")) { + return parseThisOrTargetAnnotationPointcut(); + } else if (kind.equals("within")) { + return parseWithinAnnotationPointcut(); + } else if (kind.equals("withincode")) { + return parseWithinCodeAnnotationPointcut(); + } throw new ParserException("@pointcut name expected, but found " + kind, t); + } + + private Pointcut parseKindedAnnotationPointcut() { + String kind = parseIdentifier(); + Shadow.Kind shadowKind = null; + if (kind.equals("execution")) { + shadowKind = Shadow.MethodExecution; // also matches cons execution + } else if (kind.equals("call")) { + shadowKind = Shadow.MethodCall; // also matches cons call + } else if (kind.equals("get")) { + shadowKind = Shadow.FieldGet; + } else if (kind.equals("set")) { + shadowKind = Shadow.FieldSet; + } else if (kind.equals("adviceexecution")) { + shadowKind = Shadow.AdviceExecution; + } else if (kind.equals("initialization")) { + shadowKind = Shadow.Initialization; + } else if (kind.equals("preinitialization")) { + shadowKind = Shadow.PreInitialization; + } else if (kind.equals("staticinitialization")) { + shadowKind = Shadow.StaticInitialization; + } else { + throw new ParserException(("bad kind: " + kind), tokenSource.peek()); + } + eat("("); + if (maybeEat(")")) { + throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek()); + } + AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); + eat(")"); + return new KindedAnnotationPointcut(shadowKind,type); + } + + private SignaturePattern parseConstructorSignaturePattern() { SignaturePattern ret = parseMethodOrConstructorSignaturePattern(); if (ret.getKind() == Member.CONSTRUCTOR) return ret; @@ -306,6 +373,38 @@ public class PatternParser { return new ThisOrTargetPointcut(kind.equals("this"), type); } + private Pointcut parseThisOrTargetAnnotationPointcut() { + String kind = parseIdentifier(); + eat("("); + if (maybeEat(")")) { + throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek()); + } + AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); + eat(")"); + return new ThisOrTargetAnnotationPointcut(kind.equals("this"),type); + } + + private Pointcut parseWithinAnnotationPointcut() { + String kind = parseIdentifier(); + eat("("); + if (maybeEat(")")) { + throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek()); + } + AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); + eat(")"); + return new WithinAnnotationPointcut(type); + } + + private Pointcut parseWithinCodeAnnotationPointcut() { + String kind = parseIdentifier(); + eat("("); + if (maybeEat(")")) { + throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek()); + } + AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); + eat(")"); + return new WithinCodeAnnotationPointcut(type); + } /** * Method parseArgsPointcut. @@ -316,7 +415,12 @@ public class PatternParser { TypePatternList arguments = parseArgumentsPattern(); return new ArgsPointcut(arguments); } - + + private Pointcut parseArgsAnnotationPointcut() { + parseIdentifier(); + AnnotationPatternList arguments = parseArgumentsAnnotationPattern(); + return new ArgsAnnotationPointcut(arguments); + } private Pointcut parseReferencePointcut() { TypePattern onType = parseTypePattern(); @@ -378,23 +482,109 @@ public class PatternParser { } public TypePattern parseTypePattern() { - TypePattern p = parseAtomicTypePattern(); + AnnotationTypePattern ap = null; + TypePattern tp = null; + PatternNode p = parseAtomicPattern(); + if (isAnnotationPattern(p)) { + ap = completeAnnotationPattern((AnnotationTypePattern)p); + IToken tok = tokenSource.peek(); + PatternNode typepat = parseTypePattern(); + if (isAnnotationPattern(p)) { + throw new ParserException("Duplicate annotation pattern",tok); + } else { + tp = (TypePattern) typepat; + tp.setAnnotationTypePattern(ap); + } + } else { + tp = (TypePattern)p; + } if (maybeEat("&&")) { - p = new AndTypePattern(p, parseNotOrTypePattern()); + tp = new AndTypePattern(tp, parseNotOrTypePattern()); } if (maybeEat("||")) { - p = new OrTypePattern(p, parseTypePattern()); + tp = new OrTypePattern(tp, parseTypePattern()); } + return tp; + } + + private AnnotationTypePattern completeAnnotationPattern(AnnotationTypePattern p) { + if (maybeEat("&&")) { + return new AndAnnotationTypePattern(p,parseNotOrAnnotationPattern()); + } + if (maybeEat("||")) { + return new OrAnnotationTypePattern(p,parseAnnotationTypePattern(false)); + } + return p; + } + + private AnnotationTypePattern parseNotOrAnnotationPattern() { + AnnotationTypePattern p = parseAnnotationTypePattern(false); + if (maybeEat("&&")) { + p = new AndAnnotationTypePattern(p,parseAnnotationTypePattern(false)); + } + return p; + } + + private AnnotationTypePattern parseAnnotationTypePattern(boolean isOptional) { + IToken tok = tokenSource.peek(); + PatternNode p = parseAtomicPattern(); + if (!isAnnotationPattern(p)) { + if (isOptional) return null; + throw new ParserException("Expecting annotation pattern",tok); + } + AnnotationTypePattern ap = (AnnotationTypePattern) p; + if (maybeEat("&&")) { + ap = new AndAnnotationTypePattern(ap, parseNotOrAnnotationPattern()); + } + + if (maybeEat("||")) { + ap = new OrAnnotationTypePattern(ap, parseAnnotationTypePattern(false)); + } + return ap; + } + + private AnnotationTypePattern parseAnnotationNameOrVarTypePattern() { + AnnotationTypePattern p = null; + int startPos = tokenSource.peek().getStart(); + if (maybeEat(AT)) { + StringBuffer annotationName = new StringBuffer(); + annotationName.append(parseIdentifier()); + while (maybeEat(".")) { + annotationName.append(parseIdentifier()); + } + TypeX type = TypeX.forName(annotationName.toString()); + p = new ExactAnnotationTypePattern(type); + } else { + String formal = parseIdentifier(); + p = new ExactAnnotationTypePattern(formal); // will get replaced when bindings resolved + } + int endPos = tokenSource.peek(-1).getEnd(); + p.setLocation(sourceContext,startPos,endPos); return p; } private TypePattern parseNotOrTypePattern() { - TypePattern p = parseAtomicTypePattern(); + AnnotationTypePattern ap = null; + TypePattern tp = null; + PatternNode p = parseAtomicPattern(); + if (isAnnotationPattern(p)) { + ap = completeAnnotationPattern((AnnotationTypePattern)p); + IToken tok = tokenSource.peek(); + PatternNode typepat = parseTypePattern(); + if (isAnnotationPattern(p)) { + throw new ParserException("Duplicate annotation pattern",tok); + } else { + tp = (TypePattern) typepat; + tp.setAnnotationTypePattern(ap); + } + } else { + tp = (TypePattern) p; + } if (maybeEat("&&")) { - p = new AndTypePattern(p, parseTypePattern()); + tp = new AndTypePattern(tp, parseTypePattern()); } - return p; + return tp; } private TypePattern parseAtomicTypePattern() { @@ -416,6 +606,40 @@ public class PatternParser { return p; } + private PatternNode parseAtomicPattern() { + if (maybeEat("!")) { + PatternNode p = parseAtomicPattern(); + if (isAnnotationPattern(p)) { + return new NotAnnotationTypePattern((AnnotationTypePattern)p); + } else { + return new NotTypePattern((TypePattern)p); + } + } + if (maybeEat("(")) { + TypePattern p = parseTypePattern(); + eat(")"); + return p; + } + if (maybeEat(AT)) { + StringBuffer annotationName = new StringBuffer(); + annotationName.append(parseIdentifier()); + while (maybeEat(".")) { + annotationName.append(parseIdentifier()); + } + TypeX type = TypeX.forName(annotationName.toString()); + return new ExactAnnotationTypePattern(type); + } + int startPos = tokenSource.peek().getStart(); + TypePattern p = parseSingleTypePattern(); + int endPos = tokenSource.peek(-1).getEnd(); + p.setLocation(sourceContext, startPos, endPos); + return p; + } + + private boolean isAnnotationPattern(PatternNode p) { + return (p instanceof AnnotationTypePattern); + } + public TypePattern parseSingleTypePattern() { List names = parseDottedNamePattern(); // new ArrayList(); @@ -617,6 +841,28 @@ public class PatternParser { return new TypePatternList(patterns); } + public AnnotationPatternList parseArgumentsAnnotationPattern() { + List patterns = new ArrayList(); + eat("("); + if (maybeEat(")")) { + return new AnnotationPatternList(); + } + + do { + if (maybeEat(".")) { + eat("."); + patterns.add(AnnotationTypePattern.ELLIPSIS); + } else if (maybeEat("*")) { + patterns.add(AnnotationTypePattern.ANY); + } else { + patterns.add(parseAnnotationNameOrVarTypePattern()); + } + } while (maybeEat(",")); + eat(")"); + return new AnnotationPatternList(patterns); + } + + public ThrowsPattern parseOptionalThrowsPattern() { IToken t = tokenSource.peek(); if (t.isIdentifier() && t.getString().equals("throws")) { @@ -638,6 +884,7 @@ public class PatternParser { public SignaturePattern parseMethodOrConstructorSignaturePattern() { int startPos = tokenSource.peek().getStart(); + AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern(); ModifiersPattern modifiers = parseModifiersPattern(); TypePattern returnType = parseTypePattern(); @@ -679,7 +926,7 @@ public class PatternParser { TypePatternList parameterTypes = parseArgumentsPattern(); ThrowsPattern throwsPattern = parseOptionalThrowsPattern(); - SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes, throwsPattern); + SignaturePattern ret = new SignaturePattern(kind, modifiers, returnType, declaringType, name, parameterTypes, throwsPattern, annotationPattern); int endPos = tokenSource.peek(-1).getEnd(); ret.setLocation(sourceContext, startPos, endPos); return ret; @@ -703,6 +950,7 @@ public class PatternParser { public SignaturePattern parseFieldSignaturePattern() { int startPos = tokenSource.peek().getStart(); + AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern(); ModifiersPattern modifiers = parseModifiersPattern(); TypePattern returnType = parseTypePattern(); TypePattern declaringType = parseTypePattern(); @@ -717,7 +965,7 @@ public class PatternParser { } } SignaturePattern ret = new SignaturePattern(Member.FIELD, modifiers, returnType, - declaringType, name, TypePatternList.ANY, ThrowsPattern.ANY); + declaringType, name, TypePatternList.ANY, ThrowsPattern.ANY,annotationPattern); int endPos = tokenSource.peek(-1).getEnd(); ret.setLocation(sourceContext, startPos, endPos); @@ -822,6 +1070,18 @@ public class PatternParser { } } + public AnnotationTypePattern maybeParseAnnotationPattern() { + AnnotationTypePattern ret = null; + int start = tokenSource.getIndex(); + ret = parseAnnotationTypePattern(true); + if (ret == null) { + // failed to find one... + tokenSource.setIndex(start); + ret = AnnotationTypePattern.ANY; + } + return ret; + } + public boolean peek(String token) { IToken next = tokenSource.peek(); return next.getString() == token; diff --git a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java index 4f8ddba3f..2babd0c33 100644 --- a/weaver/src/org/aspectj/weaver/patterns/Pointcut.java +++ b/weaver/src/org/aspectj/weaver/patterns/Pointcut.java @@ -124,6 +124,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression public static final byte HANDLER = 13; public static final byte IF_TRUE = 14; public static final byte IF_FALSE = 15; + public static final byte ATKINDED = 16; public static final byte NONE = 20; @@ -241,7 +242,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression case HANDLER: ret = HandlerPointcut.read(s, context); break; case IF_TRUE: ret = IfPointcut.makeIfTruePointcut(RESOLVED); break; case IF_FALSE: ret = IfPointcut.makeIfFalsePointcut(RESOLVED); break; - + case ATKINDED: ret = KindedAnnotationPointcut.read(s, context); break; case NONE: ret = makeMatchesNothing(RESOLVED); break; default: throw new BCException("unknown kind: " + kind); diff --git a/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java new file mode 100644 index 000000000..c2b10b065 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java @@ -0,0 +1,97 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.IntMap; +import org.aspectj.weaver.ResolvedTypeX; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.ast.Test; + +/** + * @author colyer + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut { + + private boolean isThis; + private AnnotationTypePattern type; + + /** + * + */ + public ThisOrTargetAnnotationPointcut(boolean isThis, AnnotationTypePattern type) { + super(); + this.isThis = isThis; + this.type = type; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) + */ + public FuzzyBoolean fastMatch(FastMatchInfo info) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) + */ + public FuzzyBoolean match(Shadow shadow) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings) + */ + protected void resolveBindings(IScope scope, Bindings bindings) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindingsFromRTTI() + */ + protected void resolveBindingsFromRTTI() { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedTypeX, org.aspectj.weaver.IntMap) + */ + protected Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) + */ + public Test findResidue(Shadow shadow, ExposedState state) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + // TODO Auto-generated method stub + + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/TypePattern.java b/weaver/src/org/aspectj/weaver/patterns/TypePattern.java index 0e0496ad2..0596bb1e9 100644 --- a/weaver/src/org/aspectj/weaver/patterns/TypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/TypePattern.java @@ -51,9 +51,20 @@ public abstract class TypePattern extends PatternNode { protected boolean includeSubtypes; + protected boolean isVarArgs = false; + protected AnnotationTypePattern annotationPattern = AnnotationTypePattern.ANY; - protected TypePattern(boolean includeSubtypes) { + protected TypePattern(boolean includeSubtypes,boolean isVarArgs) { this.includeSubtypes = includeSubtypes; + this.isVarArgs = isVarArgs; + } + + protected TypePattern(boolean includeSubtypes) { + this(includeSubtypes,false); + } + + public void setAnnotationTypePattern(AnnotationTypePattern annPatt) { + this.annotationPattern = annPatt; } //XXX non-final for Not, && and || @@ -66,18 +77,19 @@ public abstract class TypePattern extends PatternNode { } public abstract FuzzyBoolean matchesInstanceof(ResolvedTypeX type); - public final FuzzyBoolean matches(ResolvedTypeX type, MatchKind kind) { + FuzzyBoolean typeMatch = null; //??? This is part of gracefully handling missing references if (type == ResolvedTypeX.MISSING) return FuzzyBoolean.NO; if (kind == STATIC) { - return FuzzyBoolean.fromBoolean(matchesStatically(type)); + typeMatch = FuzzyBoolean.fromBoolean(matchesStatically(type)); + return typeMatch.and(annotationPattern.matches(type)); } else if (kind == DYNAMIC) { //System.err.println("matching: " + this + " with " + type); - FuzzyBoolean ret = matchesInstanceof(type); + typeMatch = matchesInstanceof(type); //System.err.println(" got: " + ret); - return ret; + return typeMatch.and(annotationPattern.matches(type)); } else { throw new IllegalArgumentException("kind must be DYNAMIC or STATIC"); } @@ -142,6 +154,7 @@ public abstract class TypePattern extends PatternNode { } protected abstract boolean matchesExactly(ResolvedTypeX type); + protected boolean matchesSubtypes(ResolvedTypeX type) { //System.out.println("matching: " + this + " to " + type); if (matchesExactly(type)) { @@ -189,6 +202,7 @@ public abstract class TypePattern extends PatternNode { public TypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) { + annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding); return this; } @@ -267,7 +281,7 @@ class EllipsisTypePattern extends TypePattern { * @param includeSubtypes */ public EllipsisTypePattern() { - super(false); + super(false,false); } /** @@ -314,7 +328,7 @@ class AnyTypePattern extends TypePattern { * @param includeSubtypes */ public AnyTypePattern() { - super(false); + super(false,false); } /** @@ -376,7 +390,7 @@ class AnyTypePattern extends TypePattern { class NoTypePattern extends TypePattern { public NoTypePattern() { - super(false); + super(false,false); } /** diff --git a/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java index fa2e644f9..e9b1b4536 100644 --- a/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java +++ b/weaver/src/org/aspectj/weaver/patterns/WildTypePattern.java @@ -24,6 +24,7 @@ import org.aspectj.bridge.Message; import org.aspectj.bridge.MessageUtil; import org.aspectj.util.FileUtil; import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.BCException; import org.aspectj.weaver.ISourceContext; import org.aspectj.weaver.ResolvedTypeX; import org.aspectj.weaver.TypeX; @@ -38,7 +39,7 @@ public class WildTypePattern extends TypePattern { int dim; WildTypePattern(NamePattern[] namePatterns, boolean includeSubtypes, int dim) { - super(includeSubtypes); + super(includeSubtypes,false); this.namePatterns = namePatterns; this.dim = dim; ellipsisCount = 0; @@ -332,12 +333,14 @@ public class WildTypePattern extends TypePattern { public TypePattern resolveBindings(IScope scope, Bindings bindings, boolean allowBinding, boolean requireExactType) { - if (isStar()) { + if (isStar() && (annotationPattern == AnnotationTypePattern.ANY)) { if (dim == 0) { // pr72531 return TypePattern.ANY; //??? loses source location } } + annotationPattern = annotationPattern.resolveBindings(scope,bindings,allowBinding); + String simpleName = maybeGetSimpleName(); if (simpleName != null) { FormalBinding formalBinding = scope.lookupFormal(simpleName); @@ -352,7 +355,7 @@ public class WildTypePattern extends TypePattern { return this; } - BindingTypePattern binding = new BindingTypePattern(formalBinding); + BindingTypePattern binding = new BindingTypePattern(formalBinding,isVarArgs); binding.copyLocationFrom(this); bindings.register(binding, scope); @@ -396,7 +399,7 @@ public class WildTypePattern extends TypePattern { } } else { if (dim != 0) type = TypeX.makeArray(type, dim); - TypePattern ret = new ExactTypePattern(type, includeSubtypes); + TypePattern ret = new ExactTypePattern(type, includeSubtypes,isVarArgs); ret.copyLocationFrom(this); return ret; } @@ -450,7 +453,7 @@ public class WildTypePattern extends TypePattern { } else { TypeX type = TypeX.forName(clazz.getName()); if (dim != 0) type = TypeX.makeArray(type,dim); - TypePattern ret = new ExactTypePattern(type, includeSubtypes); + TypePattern ret = new ExactTypePattern(type, includeSubtypes,isVarArgs); ret.copyLocationFrom(this); return ret; } @@ -517,7 +520,7 @@ public class WildTypePattern extends TypePattern { for (int i=0; i < len; i++) { if (!o.namePatterns[i].equals(this.namePatterns[i])) return false; } - return true; + return (o.annotationPattern.equals(this.annotationPattern)); } public int hashCode() { @@ -525,6 +528,7 @@ public class WildTypePattern extends TypePattern { for (int i = 0, len = namePatterns.length; i < len; i++) { result = 37*result + namePatterns[i].hashCode(); } + result = 37*result + annotationPattern.hashCode(); return result; } @@ -537,11 +541,14 @@ public class WildTypePattern extends TypePattern { return matchesExactlyByName(type.getName()); } + + private static final byte VERSION = 1; // rev on change /** * @see org.aspectj.weaver.patterns.PatternNode#write(DataOutputStream) */ public void write(DataOutputStream s) throws IOException { s.writeByte(TypePattern.WILD); + s.writeByte(VERSION); s.writeShort(namePatterns.length); for (int i = 0; i < namePatterns.length; i++) { namePatterns[i].write(s); @@ -553,9 +560,14 @@ public class WildTypePattern extends TypePattern { FileUtil.writeStringArray(knownMatches, s); FileUtil.writeStringArray(importedPrefixes, s); writeLocation(s); + annotationPattern.write(s); } public static TypePattern read(DataInputStream s, ISourceContext context) throws IOException { + byte version = s.readByte(); + if (version > VERSION) { + throw new BCException("WildTypePattern was written by a more recent version of AspectJ, cannot read"); + } int len = s.readShort(); NamePattern[] namePatterns = new NamePattern[len]; for (int i=0; i < len; i++) { @@ -567,6 +579,7 @@ public class WildTypePattern extends TypePattern { ret.knownMatches = FileUtil.readStringArray(s); ret.importedPrefixes = FileUtil.readStringArray(s); ret.readLocation(context, s); + ret.setAnnotationTypePattern(AnnotationTypePattern.read(s,context)); return ret; } diff --git a/weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java new file mode 100644 index 000000000..c9194f2b5 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/WithinAnnotationPointcut.java @@ -0,0 +1,94 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.IntMap; +import org.aspectj.weaver.ResolvedTypeX; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.ast.Test; + +/** + * @author colyer + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +public class WithinAnnotationPointcut extends NameBindingPointcut { + + private AnnotationTypePattern type; + /** + * + */ + public WithinAnnotationPointcut(AnnotationTypePattern type) { + super(); + this.type = type; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) + */ + public FuzzyBoolean fastMatch(FastMatchInfo info) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) + */ + public FuzzyBoolean match(Shadow shadow) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings) + */ + protected void resolveBindings(IScope scope, Bindings bindings) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindingsFromRTTI() + */ + protected void resolveBindingsFromRTTI() { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedTypeX, org.aspectj.weaver.IntMap) + */ + protected Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) + */ + public Test findResidue(Shadow shadow, ExposedState state) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + // TODO Auto-generated method stub + + } + +} diff --git a/weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java new file mode 100644 index 000000000..ad36ea073 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/patterns/WithinCodeAnnotationPointcut.java @@ -0,0 +1,94 @@ +/* ******************************************************************* + * 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.patterns; + +import java.io.DataOutputStream; +import java.io.IOException; + +import org.aspectj.util.FuzzyBoolean; +import org.aspectj.weaver.IntMap; +import org.aspectj.weaver.ResolvedTypeX; +import org.aspectj.weaver.Shadow; +import org.aspectj.weaver.ast.Test; + +/** + * @author colyer + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +public class WithinCodeAnnotationPointcut extends NameBindingPointcut { + + private AnnotationTypePattern type; + /** + * + */ + public WithinCodeAnnotationPointcut(AnnotationTypePattern type) { + super(); + this.type = type; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo) + */ + public FuzzyBoolean fastMatch(FastMatchInfo info) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow) + */ + public FuzzyBoolean match(Shadow shadow) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings) + */ + protected void resolveBindings(IScope scope, Bindings bindings) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#resolveBindingsFromRTTI() + */ + protected void resolveBindingsFromRTTI() { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedTypeX, org.aspectj.weaver.IntMap) + */ + protected Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState) + */ + public Test findResidue(Shadow shadow, ExposedState state) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream) + */ + public void write(DataOutputStream s) throws IOException { + // TODO Auto-generated method stub + + } + +} diff --git a/weaver/testdata/dummyAspect.jar b/weaver/testdata/dummyAspect.jar Binary files differindex e2e964d62..5f2cec94b 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 9377b94df..f0f9bce40 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 de62d46cb..68d068023 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 9d06b066e..e86e95213 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 36364b7da..d22d18aa7 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 09274e5d9..1274055c6 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 d8de5ce69..71ee93ec0 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 ae6adc1b3..a3384f422 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 ce3821e03..79ef9d4e2 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 c814a67e6..2ae6de681 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 7b1682e85..34f42987e 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 06fa9b91c..b7fc01a1d 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 695b6ed55..0630eceb0 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 16fa51c90..e3ea96f96 100644 --- a/weaver/testdata/tracing.jar +++ b/weaver/testdata/tracing.jar diff --git a/weaver/testsrc/org/aspectj/weaver/TestShadow.java b/weaver/testsrc/org/aspectj/weaver/TestShadow.java index b4ed5ea61..9c1125438 100644 --- a/weaver/testsrc/org/aspectj/weaver/TestShadow.java +++ b/weaver/testsrc/org/aspectj/weaver/TestShadow.java @@ -70,4 +70,46 @@ public class TestShadow extends Shadow { throw new RuntimeException("unimplemented"); } + /* (non-Javadoc) + * @see org.aspectj.weaver.Shadow#getKindedAnnotationVar() + */ + public Var getKindedAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.Shadow#getWithinAnnotationVar() + */ + public Var getWithinAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.Shadow#getWithinCodeAnnotationVar() + */ + public Var getWithinCodeAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.Shadow#getThisAnnotationVar() + */ + public Var getThisAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.Shadow#getTargetAnnotationVar() + */ + public Var getTargetAnnotationVar(TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + + /* (non-Javadoc) + * @see org.aspectj.weaver.Shadow#getArgAnnotationVar(int) + */ + public Var getArgAnnotationVar(int i,TypeX annotationType) { + throw new RuntimeException("unimplemented"); + } + } diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java index e75479275..455663699 100644 --- a/weaver/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java +++ b/weaver/testsrc/org/aspectj/weaver/patterns/BindingTestCase.java @@ -31,8 +31,8 @@ public class BindingTestCase extends TestCase { public void testResolveBindings() { - BindingTypePattern at = new BindingTypePattern(world.resolve("java.lang.Object"), 0); - BindingTypePattern bt = new BindingTypePattern(world.resolve("java.lang.Object"), 1); + BindingTypePattern at = new BindingTypePattern(world.resolve("java.lang.Object"), 0, false); + BindingTypePattern bt = new BindingTypePattern(world.resolve("java.lang.Object"), 1, false); BindingTypePattern[] all = new BindingTypePattern[] {at, bt}; BindingTypePattern[] none = new BindingTypePattern[] {null, null}; diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/KindedAnnotationPointcutTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/KindedAnnotationPointcutTestCase.java new file mode 100644 index 000000000..954746d47 --- /dev/null +++ b/weaver/testsrc/org/aspectj/weaver/patterns/KindedAnnotationPointcutTestCase.java @@ -0,0 +1,27 @@ +/* ******************************************************************* + * 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.patterns; + +import junit.framework.TestCase; + +/** + * @author colyer + * + * TODO To change the template for this generated type comment go to + * Window - Preferences - Java - Code Style - Code Templates + */ +public class KindedAnnotationPointcutTestCase extends TestCase { + + public void testParsing() { + PatternParser p = new PatternParser("@call(@String)"); + Pointcut pc = p.parsePointcut(); + assertTrue(pc instanceof KindedAnnotationPointcut); + } +} |