aboutsummaryrefslogtreecommitdiffstats
path: root/weaver
diff options
context:
space:
mode:
authoraclement <aclement>2004-12-08 09:47:36 +0000
committeraclement <aclement>2004-12-08 09:47:36 +0000
commit14769b5d6ddcc43da0af272187992abb7ea499a8 (patch)
tree6bc4b9083395a39db8c6a133b33e64ea73c762db /weaver
parent5bb7e432a8e1e94ebf6785a3b449b803df4a4942 (diff)
downloadaspectj-14769b5d6ddcc43da0af272187992abb7ea499a8.tar.gz
aspectj-14769b5d6ddcc43da0af272187992abb7ea499a8.zip
Annotation matching.
Diffstat (limited to 'weaver')
-rw-r--r--weaver/src/org/aspectj/weaver/AnnotatedElement.java2
-rw-r--r--weaver/src/org/aspectj/weaver/Member.java15
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedMember.java10
-rw-r--r--weaver/src/org/aspectj/weaver/ResolvedTypeX.java18
-rw-r--r--weaver/src/org/aspectj/weaver/TypeX.java5
-rw-r--r--weaver/src/org/aspectj/weaver/WeaverMessages.java1
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelField.java11
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelMethod.java11
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java28
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java19
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java19
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java14
-rw-r--r--weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java14
-rw-r--r--weaver/src/org/aspectj/weaver/weaver-messages.properties1
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java190
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternTestCase.java13
-rw-r--r--weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java1
17 files changed, 351 insertions, 21 deletions
diff --git a/weaver/src/org/aspectj/weaver/AnnotatedElement.java b/weaver/src/org/aspectj/weaver/AnnotatedElement.java
index eae2c1a5c..e2a6c7de4 100644
--- a/weaver/src/org/aspectj/weaver/AnnotatedElement.java
+++ b/weaver/src/org/aspectj/weaver/AnnotatedElement.java
@@ -13,7 +13,7 @@ package org.aspectj.weaver;
* Represents any element that may have annotations
*/
public interface AnnotatedElement {
- boolean hasAnnotation(TypeX ofType);
+ boolean hasAnnotation(ResolvedTypeX ofType);
// SomeType getAnnotation(TypeX ofType);
}
diff --git a/weaver/src/org/aspectj/weaver/Member.java b/weaver/src/org/aspectj/weaver/Member.java
index b1186624b..d6b63e275 100644
--- a/weaver/src/org/aspectj/weaver/Member.java
+++ b/weaver/src/org/aspectj/weaver/Member.java
@@ -464,14 +464,15 @@ public class Member implements Comparable, AnnotatedElement {
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;
+ /**
+ * If you want a sensible answer, resolve the member and call
+ * hasAnnotation() on the ResolvedMember.
+ */
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ throw new UnsupportedOperationException("You should resolve this member and call hasAnnotation() on the result...");
}
- // ---- fields 'n' stuff
+
+ // ---- fields 'n' stuff
public static final Member[] NONE = new Member[0];
diff --git a/weaver/src/org/aspectj/weaver/ResolvedMember.java b/weaver/src/org/aspectj/weaver/ResolvedMember.java
index c7313bac6..3228699de 100644
--- a/weaver/src/org/aspectj/weaver/ResolvedMember.java
+++ b/weaver/src/org/aspectj/weaver/ResolvedMember.java
@@ -24,7 +24,7 @@ import org.aspectj.bridge.ISourceLocation;
* This is the declared member, i.e. it will always correspond to an
* actual method/... declaration
*/
-public class ResolvedMember extends Member implements IHasPosition {
+public class ResolvedMember extends Member implements IHasPosition, AnnotatedElement {
public String[] parameterNames = null;
protected TypeX[] checkedExceptions = TypeX.NONE;
@@ -101,6 +101,14 @@ public class ResolvedMember extends Member implements IHasPosition {
public boolean isAjSynthetic() {
return true;
}
+
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ // The ctors don't allow annotations to be specified ... yet - but
+ // that doesn't mean it is an error to call this method.
+ // Normally the weaver will be working with subtypes of
+ // this type - BcelField/BcelMethod
+ return false;
+ }
public boolean isBridgeMethod() {
return (modifiers & Constants.ACC_BRIDGE)!=0;
diff --git a/weaver/src/org/aspectj/weaver/ResolvedTypeX.java b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java
index 5c5323664..3bbd621b9 100644
--- a/weaver/src/org/aspectj/weaver/ResolvedTypeX.java
+++ b/weaver/src/org/aspectj/weaver/ResolvedTypeX.java
@@ -28,7 +28,7 @@ import org.aspectj.bridge.MessageUtil;
import org.aspectj.weaver.patterns.Declare;
import org.aspectj.weaver.patterns.PerClause;
-public abstract class ResolvedTypeX extends TypeX {
+public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
protected World world;
@@ -559,6 +559,10 @@ public abstract class ResolvedTypeX extends TypeX {
public final boolean isClass() {
return delegate.isClass();
}
+
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ return delegate.hasAnnotation(ofType);
+ }
public boolean isAspect() {
return delegate.isAspect();
@@ -716,6 +720,8 @@ public abstract class ResolvedTypeX extends TypeX {
public abstract boolean isInterface();
public abstract boolean isEnum();
public abstract boolean isAnnotation();
+
+ public abstract boolean hasAnnotation(ResolvedTypeX ofType);
public abstract ResolvedMember[] getDeclaredFields();
@@ -790,6 +796,10 @@ public abstract class ResolvedTypeX extends TypeX {
return ResolvedMember.NONE;
}
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ return false;
+ }
+
public final ResolvedTypeX getSuperclass() {
return world.getCoreType(OBJECT);
}
@@ -849,6 +859,9 @@ public abstract class ResolvedTypeX extends TypeX {
public final boolean isPrimitive() {
return true;
}
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ return false;
+ }
public final boolean isAssignableFrom(TypeX other) {
if (! other.isPrimitive()) return false;
return assignTable[((Primitive)other).index][index];
@@ -923,6 +936,9 @@ public abstract class ResolvedTypeX extends TypeX {
public final String getName() {
return MISSING_NAME;
}
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ return false;
+ }
public final ResolvedMember[] getDeclaredFields() {
return ResolvedMember.NONE;
}
diff --git a/weaver/src/org/aspectj/weaver/TypeX.java b/weaver/src/org/aspectj/weaver/TypeX.java
index 3d424618d..a10561c48 100644
--- a/weaver/src/org/aspectj/weaver/TypeX.java
+++ b/weaver/src/org/aspectj/weaver/TypeX.java
@@ -552,9 +552,8 @@ public class TypeX implements AnnotatedElement {
return world.resolve(this);
}
- public boolean hasAnnotation(TypeX ofType) {
- //TODO implement TypeX.hasAnnotation
- return false;
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ throw new UnsupportedOperationException("You should resolve this member and call hasAnnotation() on the result...");
}
// ---- fields
diff --git a/weaver/src/org/aspectj/weaver/WeaverMessages.java b/weaver/src/org/aspectj/weaver/WeaverMessages.java
index dac3f3fb4..9bcd3e63c 100644
--- a/weaver/src/org/aspectj/weaver/WeaverMessages.java
+++ b/weaver/src/org/aspectj/weaver/WeaverMessages.java
@@ -109,6 +109,7 @@ public class WeaverMessages {
public static final String ITDC_ON_ANNOTATION_NOT_ALLOWED = "itdcOnAnnotationNotAllowed";
public static final String ITDM_ON_ANNOTATION_NOT_ALLOWED = "itdmOnAnnotationNotAllowed";
public static final String ITDF_ON_ANNOTATION_NOT_ALLOWED = "itdfOnAnnotationNotAllowed";
+ public static final String REFERENCE_TO_NON_ANNOTATION_TYPE = "referenceToNonAnnotationType";
public static String format(String key) {
return bundle.getString(key);
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelField.java b/weaver/src/org/aspectj/weaver/bcel/BcelField.java
index 972571b77..e5f49438e 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelField.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelField.java
@@ -19,9 +19,11 @@ import java.util.List;
import org.aspectj.apache.bcel.classfile.Attribute;
import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.classfile.Synthetic;
+import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.World;
@@ -73,4 +75,13 @@ final class BcelField extends ResolvedMember {
public boolean isSynthetic() {
return isSynthetic;
}
+
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ Annotation[] anns = field.getAnnotations();
+ for (int i = 0; i < anns.length; i++) {
+ Annotation annotation = anns[i];
+ if (annotation.getTypeName().equals(ofType.getName())) return true;
+ }
+ return false;
+ }
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java b/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
index cf15b093e..be054952d 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
@@ -21,9 +21,11 @@ import org.aspectj.apache.bcel.classfile.ExceptionTable;
import org.aspectj.apache.bcel.classfile.LocalVariable;
import org.aspectj.apache.bcel.classfile.LocalVariableTable;
import org.aspectj.apache.bcel.classfile.Method;
+import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.ShadowMunger;
import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.World;
@@ -135,4 +137,13 @@ final class BcelMethod extends ResolvedMember {
return super.getKind();
}
}
+
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ Annotation[] anns = method.getAnnotations();
+ for (int i = 0; i < anns.length; i++) {
+ Annotation annotation = anns[i];
+ if (annotation.getTypeName().equals(ofType.getName())) return true;
+ }
+ return false;
+ }
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
index 07f1cc76e..44da5969d 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
@@ -24,6 +24,7 @@ import java.util.List;
import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.apache.bcel.classfile.Method;
+import org.aspectj.apache.bcel.classfile.annotation.Annotation;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.BCException;
@@ -32,6 +33,7 @@ import org.aspectj.weaver.ResolvedPointcutDefinition;
import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.WeaverStateInfo;
+import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
import org.aspectj.weaver.patterns.PerClause;
// ??? exposed for testing
@@ -186,12 +188,12 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
}
} else if (a instanceof AjAttribute.WeaverVersionInfo) {
wvInfo = (AjAttribute.WeaverVersionInfo)a;
- if (wvInfo.getMajorVersion() > wvInfo.getCurrentWeaverMajorVersion()) {
+ if (wvInfo.getMajorVersion() > WeaverVersionInfo.getCurrentWeaverMajorVersion()) {
// The class file containing this attribute was created by a version of AspectJ that
// added some behavior that 'this' version of AspectJ doesn't understand. And the
// class file contains changes that mean 'this' version of AspectJ cannot continue.
throw new BCException("Unable to continue, this version of AspectJ supports classes built with weaver version "+
- wvInfo.toCurrentVersionString()+" but the class "+ javaClass.getClassName()+" is version "+wvInfo.toString());
+ WeaverVersionInfo.toCurrentVersionString()+" but the class "+ javaClass.getClassName()+" is version "+wvInfo.toString());
}
} else {
throw new BCException("bad attribute " + a);
@@ -317,6 +319,28 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
//System.err.println("javaClass: " + Arrays.asList(javaClass.getInterfaceNames()) + " super " + javaClass.getSuperclassName());
//if (lazyClassGen != null) lazyClassGen.print();
}
+
+// public Annotation[] getAnnotations() {
+// if (annotations == null) {
+// annotations = javaClass.getAnnotations();
+//// This would be how to resolve annotations ...
+//// annotationsTypeXs = new ResolvedTypeX[annotations.length];
+//// for (int i = 0; i < annotations.length; i++) {
+//// Annotation annotation = annotations[i];
+//// getResolvedTypeX().getWorld().resolve(TypeX.forName(annotation.getTypeName()));
+//// }
+// }
+// return annotations;
+// }
+
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
+ Annotation[] annotationsOnThisType = javaClass.getAnnotations();
+ for (int i = 0; i < annotationsOnThisType.length; i++) {
+ Annotation a = annotationsOnThisType[i];
+ if (a.getTypeName().equals(ofType.getName())) return true;
+ }
+ return false;
+ }
}
diff --git a/weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
index 2949bb5e7..d00dec37e 100644
--- a/weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
+++ b/weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
@@ -13,10 +13,14 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.World;
public class BindingAnnotationTypePattern extends ExactAnnotationTypePattern implements BindingPattern {
@@ -34,6 +38,21 @@ public class BindingAnnotationTypePattern extends ExactAnnotationTypePattern imp
this(binding.getType(),binding.getIndex());
}
+ public AnnotationTypePattern resolve(World world) {
+ if (resolved) return this;
+ resolved = true;
+ annotationType = annotationType.resolve(world);
+ if (!annotationType.isAnnotation(world)) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.REFERENCE_TO_NON_ANNOTATION_TYPE,annotationType.getName()),
+ getSourceLocation());
+ world.getMessageHandler().handleMessage(m);
+ resolved = false;
+ }
+ return this;
+ }
+
+
public int getFormalIndex() {
return formalIndex;
}
diff --git a/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java b/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
index 7916fc98d..fc2b6b805 100644
--- a/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
+++ b/weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
@@ -14,11 +14,14 @@ import java.io.DataOutputStream;
import java.io.IOException;
import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.MessageUtil;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.AnnotatedElement;
import org.aspectj.weaver.BCException;
import org.aspectj.weaver.ISourceContext;
+import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.WeaverMessages;
/**
* Matches an annotation of a given type
@@ -27,7 +30,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
protected TypeX annotationType;
protected String formalName;
- private boolean resolved = false;
+ protected boolean resolved = false;
private boolean bindingPattern = false;
/**
@@ -45,8 +48,12 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
// will be turned into BindingAnnotationTypePattern during resolution
}
+
public FuzzyBoolean matches(AnnotatedElement annotated) {
- return (annotated.hasAnnotation(annotationType) ?
+ if (!resolved) {
+ throw new IllegalStateException("Can't match on an unresolved annotation type pattern");
+ }
+ return (annotated.hasAnnotation((ResolvedTypeX)annotationType) ?
FuzzyBoolean.YES : FuzzyBoolean.NO);
}
@@ -74,6 +81,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
BindingAnnotationTypePattern binding = new BindingAnnotationTypePattern(formalBinding);
binding.copyLocationFrom(this);
bindings.register(binding, scope);
+ binding.resolve(scope.getWorld());
return binding;
} else {
@@ -82,6 +90,13 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern {
}
} else {
annotationType = annotationType.resolve(scope.getWorld());
+ if (!annotationType.isAnnotation(scope.getWorld())) {
+ IMessage m = MessageUtil.error(
+ WeaverMessages.format(WeaverMessages.REFERENCE_TO_NON_ANNOTATION_TYPE,annotationType.getName()),
+ getSourceLocation());
+ scope.getWorld().getMessageHandler().handleMessage(m);
+ resolved = false;
+ }
return this;
}
}
diff --git a/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java b/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java
index 08960c228..6dc0c556d 100644
--- a/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java
+++ b/weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java
@@ -19,6 +19,9 @@ import org.aspectj.bridge.Message;
import org.aspectj.util.FuzzyBoolean;
import org.aspectj.weaver.ISourceContext;
import org.aspectj.weaver.IntMap;
+import org.aspectj.weaver.Member;
+import org.aspectj.weaver.NameMangler;
+import org.aspectj.weaver.ResolvedMember;
import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.Shadow;
import org.aspectj.weaver.ShadowMunger;
@@ -79,7 +82,16 @@ public class KindedAnnotationPointcut extends NameBindingPointcut {
*/
public FuzzyBoolean match(Shadow shadow) {
if (!couldMatch(shadow)) return FuzzyBoolean.NO;
- return type.matches(shadow.getSignature());
+ Member member = shadow.getSignature();
+ ResolvedMember rMember = member.resolve(shadow.getIWorld());
+ if (rMember == null) {
+ if (member.getName().startsWith(NameMangler.PREFIX)) {
+ return FuzzyBoolean.NO;
+ }
+ shadow.getIWorld().getLint().unresolvableMember.signal(member.toString(), getSourceLocation());
+ return FuzzyBoolean.NO;
+ }
+ return type.matches(rMember);
}
private boolean couldMatch(Shadow shadow) {
diff --git a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
index 1bdd48820..d1cb4fee8 100644
--- a/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
+++ b/weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
@@ -118,7 +118,19 @@ public class SignaturePattern extends PatternNode {
public boolean matches(Member member, World world) {
return (matchesIgnoringAnnotations(member,world) &&
- annotationPattern.matches(member).alwaysTrue());
+ matchesAnnotations(member,world));
+ }
+
+ public boolean matchesAnnotations(Member member,World world) {
+ ResolvedMember rMember = member.resolve(world);
+ if (rMember == null) {
+ if (member.getName().startsWith(NameMangler.PREFIX)) {
+ return false;
+ }
+ world.getLint().unresolvableMember.signal(member.toString(), getSourceLocation());
+ return false;
+ }
+ return annotationPattern.matches(rMember).alwaysTrue();
}
public boolean matchesIgnoringAnnotations(Member member, World world) {
diff --git a/weaver/src/org/aspectj/weaver/weaver-messages.properties b/weaver/src/org/aspectj/weaver/weaver-messages.properties
index fa19b4a80..cd86ab148 100644
--- a/weaver/src/org/aspectj/weaver/weaver-messages.properties
+++ b/weaver/src/org/aspectj/weaver/weaver-messages.properties
@@ -120,4 +120,5 @@ itdcOnAnnotationNotAllowed=can''t make inter-type constructor declarations on an
itdmOnAnnotationNotAllowed=can''t make inter-type method declarations on annotation types
itdfOnAnnotationNotAllowed=can''t make inter-type field declarations on annotation types
+referenceToNonAnnotationType=Type referred to is not an annotation type: {0}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java
new file mode 100644
index 000000000..8d6462b75
--- /dev/null
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java
@@ -0,0 +1,190 @@
+/* *******************************************************************
+ * 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
+ *
+ * Contributors:
+ * Andy Clement initial implementation
+ * ******************************************************************/
+package org.aspectj.weaver.patterns;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import junit.framework.TestCase;
+
+import org.aspectj.bridge.AbortException;
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.IMessageHandler;
+import org.aspectj.bridge.MessageHandler;
+import org.aspectj.bridge.IMessage.Kind;
+import org.aspectj.weaver.BcweaverTests;
+import org.aspectj.weaver.ResolvedMember;
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.bcel.BcelWorld;
+
+/*
+ * Sample types that this program uses are:
+
+import p.SimpleAnnotation;
+
+@SimpleAnnotation(id=2)
+public class AnnotatedClass {
+
+ @SimpleAnnotation(id=3)
+ public void m1() { }
+
+ @SimpleAnnotation(id=4)
+ int i;
+}
+
+ * with SimpleAnnotation defined as:
+
+package p;
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SimpleAnnotation {
+ int id();
+ String fruit() default "bananas";
+}
+
+*NOTE NOTE NOTE NOTE NOTE NOTE NOTE*
+If you need to rebuild the test data code, run 'ant -f build-15.xml' in the
+testdata directory.
+
+ */
+public class AnnotationPatternMatchingTestCase extends TestCase {
+
+ private BcelWorld world;
+ private AnnotationTypePattern fooTP,simpleAnnotationTP;
+
+ private ResolvedTypeX loadType(String name) {
+ if (world == null) {
+ world = new BcelWorld(BcweaverTests.TESTDATA_PATH + "/testcode.jar");
+ }
+ return world.resolve(name);
+ }
+
+ private void initAnnotationTypePatterns() {
+ PatternParser p = new PatternParser("@Foo");
+ fooTP = p.parseAnnotationTypePattern();
+ fooTP = fooTP.resolveBindings(makeSimpleScope(),new Bindings(3),true);
+
+ p = new PatternParser("@p.SimpleAnnotation");
+ simpleAnnotationTP = p.parseAnnotationTypePattern();
+ simpleAnnotationTP = simpleAnnotationTP.resolveBindings(makeSimpleScope(),new Bindings(3),true);
+ }
+
+
+ public void testAnnotationPatternMatchingOnTypes() {
+
+ ResolvedTypeX rtx = loadType("AnnotatedClass");
+ initAnnotationTypePatterns();
+
+ // One should match
+ assertTrue("@Foo should not match on the AnnotatedClass",
+ fooTP.matches(rtx).alwaysFalse());
+ assertTrue("@SimpleAnnotation should match on the AnnotatedClass",
+ simpleAnnotationTP.matches(rtx).alwaysTrue());
+
+ }
+
+ static class MyMessageHandler implements IMessageHandler {
+ public List messages = new ArrayList();
+ public boolean handleMessage(IMessage message) throws AbortException {
+ messages.add(message);
+ return false;
+ }
+ public boolean isIgnoring(Kind kind) {return false;}
+ }
+
+ public void testReferenceToNonAnnotationType() {
+ ResolvedTypeX rtx = loadType("AnnotatedClass"); // inits the world
+ PatternParser p = new PatternParser("@java.lang.String");
+
+ MyMessageHandler mh = new MyMessageHandler();
+ world.setMessageHandler(mh);
+ AnnotationTypePattern atp = p.parseAnnotationTypePattern();
+ atp = atp.resolveBindings(makeSimpleScope(),new Bindings(3),true);
+
+ assertTrue("Expected 1 error message but got "+mh.messages.size(),mh.messages.size()==1);
+
+ String expected = "Type referred to is not an annotation type";
+ String msg = ((IMessage)mh.messages.get(0)).toString();
+ assertTrue("Expected: "+expected+" but got "+msg,msg.indexOf(expected)!=-1);
+ }
+
+ public void testReferenceViaFormalToNonAnnotationType() {
+ ResolvedTypeX rtx = loadType("AnnotatedClass"); // inits the world
+ PatternParser p = new PatternParser("a");
+
+ MyMessageHandler mh = new MyMessageHandler();
+ world.setMessageHandler(mh);
+ AnnotationTypePattern atp = p.parseAnnotationNameOrVarTypePattern();
+ atp = atp.resolveBindings(makeSimpleScope(),new Bindings(3),true);
+
+ assertTrue("Expected 1 error message but got "+mh.messages.size(),mh.messages.size()==1);
+
+ String expected = "Type referred to is not an annotation type";
+ String msg = ((IMessage)mh.messages.get(0)).toString();
+ assertTrue("Expected: "+expected+" but got "+msg,msg.indexOf(expected)!=-1);
+ }
+
+ public TestScope makeSimpleScope() {
+ return new TestScope(new String[] {"int", "java.lang.String"}, new String[] {"a", "b"}, world);
+ }
+
+ public void testUnresolvedAnnotationTypes() {
+ ResolvedTypeX rtx = loadType("AnnotatedClass");
+
+ PatternParser p = new PatternParser("@Foo");
+ AnnotationTypePattern fooTP = p.parseAnnotationTypePattern();
+ try {
+ fooTP.matches(rtx);
+ fail("Should have failed with illegal state exception, fooTP is not resolved");
+ } catch (IllegalStateException ise) {
+ // Correct!
+ }
+ }
+
+ public void testAnnotationPatternMatchingOnMethods() {
+
+ ResolvedTypeX rtx = loadType("AnnotatedClass");
+ ResolvedMember aMethod = rtx.getDeclaredMethods()[1];
+
+ assertTrue("Haven't got the right method, I'm looking for 'm1()': "+aMethod.getName(),
+ aMethod.getName().equals("m1"));
+
+ initAnnotationTypePatterns();
+
+ // One should match
+ assertTrue("@Foo should not match on the AnnotatedClass.m1() method",
+ fooTP.matches(aMethod).alwaysFalse());
+ assertTrue("@SimpleAnnotation should match on the AnnotatedClass.m1() method",
+ simpleAnnotationTP.matches(aMethod).alwaysTrue());
+
+ }
+
+ public void testAnnotationPatternMatchingOnFields() {
+
+ ResolvedTypeX rtx = loadType("AnnotatedClass");
+ ResolvedMember aField = rtx.getDeclaredFields()[0];
+
+ assertTrue("Haven't got the right field, I'm looking for 'i'"+aField.getName(),
+ aField.getName().equals("i"));
+
+ initAnnotationTypePatterns();
+
+ // One should match
+ assertTrue("@Foo should not match on the AnnotatedClass.i field",
+ fooTP.matches(aField).alwaysFalse());
+ assertTrue("@SimpleAnnotation should match on the AnnotatedClass.i field",
+ simpleAnnotationTP.matches(aField).alwaysTrue());
+
+ }
+
+}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternTestCase.java
index e11415c80..489d24550 100644
--- a/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternTestCase.java
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternTestCase.java
@@ -10,6 +10,8 @@
package org.aspectj.weaver.patterns;
import org.aspectj.weaver.AnnotatedElement;
+import org.aspectj.weaver.BcweaverTests;
+import org.aspectj.weaver.ResolvedTypeX;
import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.bcel.BcelWorld;
@@ -247,6 +249,7 @@ public class AnnotationPatternTestCase extends TestCase {
public void testExactAnnotationPatternMatching() {
PatternParser p = new PatternParser("@Foo");
AnnotationTypePattern ap = p.parseAnnotationTypePattern();
+ ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true);
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[]{"Foo"});
assertTrue("matches element with Foo",ap.matches(ae).alwaysTrue());
AnnotatedElementImpl ae2 = new AnnotatedElementImpl(new String[]{"Boo"});
@@ -266,6 +269,7 @@ public class AnnotationPatternTestCase extends TestCase {
public void testAndAnnotationPatternMatching() {
PatternParser p = new PatternParser("@Foo && @Boo");
AnnotationTypePattern ap = p.parseAnnotationTypePattern();
+ ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true);
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] {"Foo","Boo"});
assertTrue("matches foo and boo",ap.matches(ae).alwaysTrue());
ae = new AnnotatedElementImpl(new String[] {"Foo"});
@@ -279,6 +283,7 @@ public class AnnotationPatternTestCase extends TestCase {
public void testOrAnnotationPatternMatching() {
PatternParser p = new PatternParser("@Foo || @Boo");
AnnotationTypePattern ap = p.parseAnnotationTypePattern();
+ ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true);
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] {"Foo","Boo"});
assertTrue("matches foo and boo",ap.matches(ae).alwaysTrue());
ae = new AnnotatedElementImpl(new String[] {"Foo"});
@@ -292,6 +297,7 @@ public class AnnotationPatternTestCase extends TestCase {
public void testNotAnnotationPatternMatching() {
PatternParser p = new PatternParser("!@Foo");
AnnotationTypePattern ap = p.parseAnnotationTypePattern();
+ ap = ap.resolveBindings(makeSimpleScope(),new Bindings(3),true);
AnnotatedElementImpl ae = new AnnotatedElementImpl(new String[] {"Foo","Boo"});
assertTrue("does not match foo and boo",ap.matches(ae).alwaysFalse());
ae = new AnnotatedElementImpl(new String[] {"Boo"});
@@ -307,7 +313,10 @@ public class AnnotationPatternTestCase extends TestCase {
public TestScope makeSimpleScope() {
- return new TestScope(new String[] {"int", "java.lang.String","Foo"}, new String[] {"a", "b","foo"}, new BcelWorld());
+ BcelWorld bWorld = new BcelWorld(BcweaverTests.TESTDATA_PATH + "/testcode.jar"); // testcode contains Foo/Boo/Goo/etc
+ return new TestScope(new String[] {"int", "java.lang.String","Foo"},
+ new String[] {"a", "b","foo"},
+ bWorld);
}
// put test cases for AnnotationPatternList matching in separate test class...
@@ -320,7 +329,7 @@ public class AnnotationPatternTestCase extends TestCase {
this.annotationTypes = annotationTypes;
}
- public boolean hasAnnotation(TypeX ofType) {
+ public boolean hasAnnotation(ResolvedTypeX ofType) {
for (int i = 0; i < annotationTypes.length; i++) {
if (annotationTypes[i].equals(ofType.getName())) return true;
}
diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java b/weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java
index 5ed4c21c0..71f35d6df 100644
--- a/weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java
+++ b/weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java
@@ -38,6 +38,7 @@ public class PatternsTests extends TestCase {
suite.addTestSuite(KindedTestCase.class);
suite.addTestSuite(WithinCodeTestCase.class);
suite.addTestSuite(AnnotationPatternTestCase.class);
+ suite.addTestSuite(AnnotationPatternMatchingTestCase.class);
//$JUnit-END$
return suite;
}