From: aclement Date: Wed, 8 Dec 2004 09:47:36 +0000 (+0000) Subject: Annotation matching. X-Git-Tag: Root_AspectJ5_Development~188 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=14769b5d6ddcc43da0af272187992abb7ea499a8;p=aspectj.git Annotation matching. --- diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java index 2ee7fefa1..f5bafb5c4 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java @@ -220,6 +220,10 @@ public class EclipseSourceType extends ResolvedTypeX.ConcreteName { public boolean isAnnotation() { return (binding.getAccessFlags() & ACC_ANNOTATION)!=0; } + + public boolean hasAnnotation(ResolvedTypeX ofType) { + throw new RuntimeException("How to implement this? Needs to ask eclipse!"); + } public PerClause getPerClause() { //should probably be: ((AspectDeclaration)declaration).perClause; 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; }