]> source.dussan.org Git - aspectj.git/commitdiff
Annotation matching.
authoraclement <aclement>
Wed, 8 Dec 2004 09:47:36 +0000 (09:47 +0000)
committeraclement <aclement>
Wed, 8 Dec 2004 09:47:36 +0000 (09:47 +0000)
18 files changed:
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java
weaver/src/org/aspectj/weaver/AnnotatedElement.java
weaver/src/org/aspectj/weaver/Member.java
weaver/src/org/aspectj/weaver/ResolvedMember.java
weaver/src/org/aspectj/weaver/ResolvedTypeX.java
weaver/src/org/aspectj/weaver/TypeX.java
weaver/src/org/aspectj/weaver/WeaverMessages.java
weaver/src/org/aspectj/weaver/bcel/BcelField.java
weaver/src/org/aspectj/weaver/bcel/BcelMethod.java
weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/ExactAnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/KindedAnnotationPointcut.java
weaver/src/org/aspectj/weaver/patterns/SignaturePattern.java
weaver/src/org/aspectj/weaver/weaver-messages.properties
weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternMatchingTestCase.java [new file with mode: 0644]
weaver/testsrc/org/aspectj/weaver/patterns/AnnotationPatternTestCase.java
weaver/testsrc/org/aspectj/weaver/patterns/PatternsTests.java

index 2ee7fefa17052099500378a4e143f7e395109f2a..f5bafb5c4aa2d7201cdb4555dbb54eeb66c57475 100644 (file)
@@ -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;
index eae2c1a5c35d7bd8ff9bd68288db9fc5c4a4e2bf..e2a6c7de48a20f540126aa8eedf7a26b344717ae 100644 (file)
@@ -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);
 }
index b1186624b95e26665648ea7224402df6af5a951a..d6b63e275d5dd7debe072a5c408cd97f3a9997db 100644 (file)
@@ -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];
 
index c7313bac6bc69f145452a0a13d030e886b27e738..3228699de8017d3b758e58a6fcd96243f4ecd65d 100644 (file)
@@ -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;
index 5c5323664bae83645f07e335bc52c76d133ce365..3bbd621b94ded086637c9cff6e47a2d7685344c8 100644 (file)
@@ -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;
         }
index 3d424618d19096939da308d46c90833ba9a7fb8b..a10561c48093f60ef82132f800922b8277432460 100644 (file)
@@ -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
index dac3f3fb4aea5320736982e2aa31ac298371c3e0..9bcd3e63c252c1d17ba95e94b69c85fc98e5b73f 100644 (file)
@@ -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);
index 972571b77717190881fa3fac5f5ce03a8ce5bebc..e5f49438ed1b53f274c779464248629f01688c65 100644 (file)
@@ -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;
+       }
 }
index cf15b093eaaebef7ce5dd03bfa55ff7cd5a407e6..be054952d069713a5539ef6d59fb8b174d316042 100644 (file)
@@ -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;
+       }
 }
index 07f1cc76e1fa32e17e02b71c6bb1037f25afa923..44da5969dedbafb2e6762845f99104852cc12007 100644 (file)
@@ -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;
+       }
 } 
     
     
index 2949bb5e792cb3a0d60ffb1c8f0ebd59554e0081..d00dec37e14cd32558d2d2801756079377c48064 100644 (file)
@@ -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;
        }
index 7916fc98dba622eb1a56c92c58ca91e6c1012b9a..fc2b6b8051c68b7e09a832bf3224897e825eda4c 100644 (file)
@@ -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;
                }
        }
index 08960c22842d8415e946a77471feb1dccf00294a..6dc0c556d8d9365541aab92e2b3a423c6bb685af 100644 (file)
@@ -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) {
index 1bdd488201386aa03775587e7f257facd4383cae..d1cb4fee89956759ed9cd36bf795eda80f2432a8 100644 (file)
@@ -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) {
index fa19b4a8015b064efdf7d6b0f566c58fad58d515..cd86ab148080018378b70276f4f2eaedeb7ef5d5 100644 (file)
@@ -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 (file)
index 0000000..8d6462b
--- /dev/null
@@ -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());
+
+       }
+
+}
index e11415c803601dd3bb988338c89e473a6872a246..489d2455000f78b0f3b3b7f253c3d8f7e2e8fe01 100644 (file)
@@ -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;
                        }
index 5ed4c21c023087119e995eadbd0f5910520e1ef1..71f35d6df81ef44941aa11f465a8f0e5063690cc 100644 (file)
@@ -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;
     }