]> source.dussan.org Git - aspectj.git/commitdiff
more @this @target fixes and tests
authoracolyer <acolyer>
Thu, 9 Dec 2004 16:27:56 +0000 (16:27 +0000)
committeracolyer <acolyer>
Thu, 9 Dec 2004 16:27:56 +0000 (16:27 +0000)
20 files changed:
org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/lookup/EclipseSourceType.java
tests/java5/annotations/thisOrtarget/BindingLimitation.aj [new file with mode: 0644]
tests/java5/annotations/thisOrtarget/NotRuntimeRetention.aj [new file with mode: 0644]
tests/java5/annotations/thisOrtarget/ThisOrTargetTests.aj
tests/src/org/aspectj/systemtest/ajc150/AnnotationRuntimeTests.java [new file with mode: 0644]
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/ast/HasAnnotation.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/ast/ITestVisitor.java
weaver/src/org/aspectj/weaver/ast/Test.java
weaver/src/org/aspectj/weaver/bcel/BcelObjectType.java
weaver/src/org/aspectj/weaver/bcel/BcelRenderer.java
weaver/src/org/aspectj/weaver/patterns/AnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/BindingAnnotationTypePattern.java
weaver/src/org/aspectj/weaver/patterns/PatternParser.java
weaver/src/org/aspectj/weaver/patterns/Pointcut.java
weaver/src/org/aspectj/weaver/patterns/PointcutImpl.java [new file with mode: 0644]
weaver/src/org/aspectj/weaver/patterns/ThisOrTargetAnnotationPointcut.java
weaver/src/org/aspectj/weaver/weaver-messages.properties

index 7a5207324c1d0f6021c9323770518be4e4d809be..7fbcd12cb52614d149f1e1471c89c6c999ca87ae 100644 (file)
@@ -221,6 +221,14 @@ public class EclipseSourceType extends ResolvedTypeX.ConcreteName {
                return (binding.getAccessFlags() & ACC_ANNOTATION)!=0;
        }
        
+       public boolean isAnnotationWithRuntimeRetention() {
+           if (!isAnnotation()) {
+               return false;
+           } else {
+                       throw new RuntimeException("How to implement this?  Needs to ask eclipse!");            
+           }
+       }
+       
        public boolean hasAnnotation(TypeX ofType) {
                throw new RuntimeException("How to implement this?  Needs to ask eclipse!");
        }
diff --git a/tests/java5/annotations/thisOrtarget/BindingLimitation.aj b/tests/java5/annotations/thisOrtarget/BindingLimitation.aj
new file mode 100644 (file)
index 0000000..1ed24c9
--- /dev/null
@@ -0,0 +1,10 @@
+public aspect BindingLimitation {
+       
+  pointcut doSomethingExecution() : execution(* doSomething());
+  pointcut doSomethingCall() : call(* doSomething());
+  
+  after(MyAnnotation ann) returning : @target(ann) && doSomethingCall() {
+       // should be compile time error (limitation)
+  }
+       
+}
\ No newline at end of file
diff --git a/tests/java5/annotations/thisOrtarget/NotRuntimeRetention.aj b/tests/java5/annotations/thisOrtarget/NotRuntimeRetention.aj
new file mode 100644 (file)
index 0000000..ea38a52
--- /dev/null
@@ -0,0 +1,18 @@
+public aspect NotRuntimeRetention {
+    
+    pointcut doSomethingExecution() : execution(* doSomething());
+    pointcut doSomethingCall() : call(* doSomething());
+    
+    // CE L7
+    before() : doSomethingExecution() && @this(@MyClassRetentionAnnotation) {
+       // should be compile-time error!
+        System.out.println("How did I get here?");
+    }
+    
+    // CE L13
+    after() returning : doSomethingCall() && @target(@MyClassRetentionAnnotation) {
+       // should be compile-time error!
+        System.out.println("How did I get here?");
+    }
+    
+}
\ No newline at end of file
index c642da9aae43dbffc58440363cd35b0849647ef2..cc5ab5cd07beb4f991d77d1b0e21ab69a5bda6b7 100644 (file)
@@ -12,10 +12,6 @@ public aspect ThisOrTargetTests {
        System.out.println("@this(@MyAnnotation): " + thisJoinPointStaticPart);\r
   }\r
   \r
-  before() : doSomethingExecution() && @this(@MyClassRetentionAnnotation) {\r
-       // should be compile-time error!\r
-  }\r
-  \r
   before() : doSomethingExecution() && @this(@MyInheritableAnnotation) {\r
        // should match:\r
        // c.doSomething()\r
@@ -24,17 +20,13 @@ public aspect ThisOrTargetTests {
        System.out.println("@this(@MyInheritableAnnotation): " + thisJoinPointStaticPart);\r
   }\r
   \r
-  after() returning : doSomthingCall() && @target(@MyAnnotation) {\r
+  after() returning : doSomethingCall() && @target(@MyAnnotation) {\r
        // should match:\r
        // b.doSomething(), reallyB.doSomething() [with test],\r
        // c.doSomething()\r
        System.out.println("@target(@MyAnnotation): " + thisJoinPointStaticPart);\r
   }\r
   \r
-  after() returning : doSomethingCall() && @target(@MyClassRetentionAnnotation) {\r
-       // should be compile-time error!\r
-  }\r
-  \r
   after() returning : doSomethingCall() && @target(@MyInheritableAnnotation) {\r
        // should match:\r
        // c.doSomething()\r
@@ -42,9 +34,5 @@ public aspect ThisOrTargetTests {
        // reallyD.doSomething()\r
        System.out.println("@target(@MyInheritableAnnotation): " + thisJoinPointStaticPart);\r
   }\r
-  \r
-  after(MyAnnotation ann) returning : @target(ann) {\r
-       // should be compile time error (limitation)\r
-  }\r
-       \r
+       \r
 }
\ No newline at end of file
diff --git a/tests/src/org/aspectj/systemtest/ajc150/AnnotationRuntimeTests.java b/tests/src/org/aspectj/systemtest/ajc150/AnnotationRuntimeTests.java
new file mode 100644 (file)
index 0000000..06b54d4
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.systemtest.ajc150;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.aspectj.tools.ajc.CompilationResult;
+
+/**
+* Tests for @this, @target, @args
+*/
+public class AnnotationRuntimeTests extends TestUtils {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+       baseDir = new File("../tests/java5/annotations/thisOrtarget");
+    }
+    
+    public void test001_NoBinding() {
+        CompilationResult cR = binaryWeave("TestingAnnotations.jar","BindingLimitation.aj",1,0);
+        List errors = cR.getErrorMessages();
+        assertTrue("Binding not supported",errors.get(0).toString().startsWith("error Binding not supported"));
+    }
+    
+    public void test002_MustHaveRuntimeRetention() {
+        CompilationResult cR = binaryWeave("TestingAnnotations.jar","NotRuntimeRetention.aj",2,0);
+        List errors = new ArrayList();
+        errors.add(new Message(7,"Annotation type MyClassRetentionAnnotation does not have runtime retention"));
+        errors.add(new Message(13,"Annotation type MyClassRetentionAnnotation does not have runtime retention"));
+        
+        MessageSpec messageSpec = new MessageSpec(new ArrayList(), errors);
+        assertMessages(cR, messageSpec);
+    }
+    
+    public void test003_InheritableOrNot() {
+        CompilationResult cR = binaryWeave("TestingAnnotations.jar","ThisOrTargetTests.aj",0,0);                       
+    }
+}
index 7b9a60174acfb2d297c0be81b32bd3b436266009..f324affae008ca2a31908415764496453052289b 100644 (file)
@@ -469,6 +469,12 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
        return false;
     }
     
+    /**
+     * Note: Only overridden by Name subtype.
+     */
+    public boolean isAnnotationWithRuntimeRetention() {
+        return false;
+    }
     
     public boolean isSynthetic() {
        return signature.indexOf("$ajc") != -1;
@@ -579,6 +585,10 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
            public boolean isAnnotation() {
                return delegate.isAnnotation();
            }
+           
+           public boolean isAnnotationWithRuntimeRetention() {
+               return delegate.isAnnotationWithRuntimeRetention();
+           }
             
         public final boolean needsNoConversionFrom(TypeX o) {
             return isAssignableFrom(o);
@@ -724,6 +734,7 @@ public abstract class ResolvedTypeX extends TypeX implements AnnotatedElement {
            public abstract boolean isInterface();
            public abstract boolean isEnum();
            public abstract boolean isAnnotation();
+           public abstract boolean isAnnotationWithRuntimeRetention();
            
            public abstract boolean hasAnnotation(TypeX ofType);
            public abstract ResolvedTypeX[] getAnnotationTypes();
index 2cc7528f3616594dd939dcf2a04bd1287c2b7531..6a44d338c0da0c99e673d145a0a1ff1c2405f712 100644 (file)
@@ -427,6 +427,13 @@ public class TypeX implements AnnotatedElement {
     public final boolean isAnnotation(World world) {
        return world.resolve(this).isAnnotation();
     }
+    
+    /**
+     * Determine if this class represents an annotation type that has runtime retention 
+     */
+    public final boolean isAnnotationWithRuntimeRetention(World world) {
+        return world.resolve(this).isAnnotationWithRuntimeRetention();
+    }
 
 
     /**
@@ -572,7 +579,9 @@ public class TypeX implements AnnotatedElement {
     public static final TypeX   SERIALIZABLE = forSignature("Ljava/io/Serializable;");
     public static final TypeX   THROWABLE    = forSignature("Ljava/lang/Throwable;");
     public static final TypeX   RUNTIME_EXCEPTION    = forSignature("Ljava/lang/RuntimeException;");
-    public static final TypeX   ERROR    = forSignature("Ljava/lang/Error;");
+    public static final TypeX   ERROR    = forSignature("Ljava/lang/Error;");    
+    public static final TypeX   AT_INHERITED = forSignature("Ljava/lang/annotation/Inherited;");
+    public static final TypeX   AT_RETENTION = forSignature("Ljava/lang/annotation/Retention;");
     
     // ---- helpers
     
index 9bcd3e63c252c1d17ba95e94b69c85fc98e5b73f..4cb4da5b7ddb1d45f26ea089187de871ce736a1a 100644 (file)
@@ -110,6 +110,7 @@ public class WeaverMessages {
        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 final String BINDING_NON_RUNTIME_RETENTION_ANNOTATION = "bindingNonRuntimeRetentionAnnotation";
        
        public static String format(String key) {
                return bundle.getString(key);
diff --git a/weaver/src/org/aspectj/weaver/ast/HasAnnotation.java b/weaver/src/org/aspectj/weaver/ast/HasAnnotation.java
new file mode 100644 (file)
index 0000000..4bdeecb
--- /dev/null
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver.ast;
+
+import org.aspectj.weaver.ResolvedTypeX;
+import org.aspectj.weaver.TypeX;
+
+public class HasAnnotation extends Test {
+
+    private Var v;
+    private ResolvedTypeX annType;
+    
+    public HasAnnotation(Var v, ResolvedTypeX annType) {
+        super();
+        this.v = v;
+        this.annType = annType;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.aspectj.weaver.ast.Test#accept(org.aspectj.weaver.ast.ITestVisitor)
+     */
+    public void accept(ITestVisitor v) {
+        v.visit(this);
+    }
+
+       public String toString() {
+               return "(" + v + " has annotation @" + annType + ")";
+       }
+
+       public boolean equals(Object other) {
+               if (other instanceof HasAnnotation) {
+                   HasAnnotation o = (HasAnnotation) other;
+                       return o.v.equals(v) && o.annType.equals(annType);
+               } else {
+                       return false;
+               }
+       }
+
+    public Var getVar() {
+        return v;
+    }
+
+    public TypeX getAnnotationType() {
+        return annType;
+    } 
+    
+}
index 4147afbd8f2f7a79f3a8e300aa949658b88861a3..67035e6dc209d8d70884868fe31715ff4d908b2e 100644 (file)
@@ -23,5 +23,6 @@ public interface ITestVisitor {
        void visit(Literal literal);
        void visit(Call call);
        void visit(FieldGetCall fieldGetCall);
+       void visit(HasAnnotation hasAnnotation);
 
 }
index b714ccb82a3ec712188b7266e102566f160141a8..73d18dd8485d1298d25006f4f87fba592c884a1b 100644 (file)
@@ -81,6 +81,10 @@ public abstract class Test extends ASTNode {
         return e;
     }
     
+    public static Test makeHasAnnotation(Var v, ResolvedTypeX annTy) {
+        return new HasAnnotation(v,annTy);
+    }
+    
     public static Test makeCall(Member m, Expr[] args) {
        return new Call(m, args);
     }
index ce8a253b2c05ef6c9d91aa2f8a35b47552b60724..9ccd7ad6de81091fb345056d008ccfcc0bc9c16d 100644 (file)
@@ -25,6 +25,8 @@ 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.apache.bcel.classfile.annotation.ElementNameValuePair;
+import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
 import org.aspectj.bridge.ISourceLocation;
 import org.aspectj.weaver.AjAttribute;
 import org.aspectj.weaver.BCException;
@@ -293,6 +295,28 @@ public class BcelObjectType extends ResolvedTypeX.ConcreteName {
                return javaClass.isAnnotation();
        }
        
+       public boolean isAnnotationWithRuntimeRetention() {
+           if (!isAnnotation()) {
+               return false;
+           } else {
+               Annotation[] annotationsOnThisType = javaClass.getAnnotations();
+               for (int i = 0; i < annotationsOnThisType.length; i++) {
+                   Annotation a = annotationsOnThisType[i];
+                   if (a.getTypeName().equals(TypeX.AT_RETENTION.getName())) {
+                       List values = a.getValues();
+                       boolean isRuntime = false;
+                       for (Iterator it = values.iterator(); it.hasNext();) {
+                        ElementNameValuePair element = (ElementNameValuePair) it.next();
+                        ElementValue v = element.getValue();
+                        isRuntime = v.stringifyValue().equals("RUNTIME");
+                    }
+                       return isRuntime;
+                   }
+               }
+               }
+           return false;
+       }
+       
        public boolean isSynthetic() {
                return getResolvedTypeX().isSynthetic();
        }
index b2b50ca8359544f9f4e3067f88038f59803860c9..1c74a522909d853c3d32c7606603c8b7325daced 100644 (file)
@@ -17,16 +17,19 @@ import org.aspectj.apache.bcel.Constants;
 import org.aspectj.apache.bcel.generic.InstructionFactory;
 import org.aspectj.apache.bcel.generic.InstructionHandle;
 import org.aspectj.apache.bcel.generic.InstructionList;
+import org.aspectj.apache.bcel.generic.LDC_W;
 import org.aspectj.apache.bcel.generic.ReferenceType;
 import org.aspectj.apache.bcel.generic.Type;
 import org.aspectj.weaver.BCException;
 import org.aspectj.weaver.Member;
+import org.aspectj.weaver.TypeX;
 import org.aspectj.weaver.ast.And;
 import org.aspectj.weaver.ast.Call;
 import org.aspectj.weaver.ast.CallExpr;
 import org.aspectj.weaver.ast.Expr;
 import org.aspectj.weaver.ast.FieldGet;
 import org.aspectj.weaver.ast.FieldGetCall;
+import org.aspectj.weaver.ast.HasAnnotation;
 import org.aspectj.weaver.ast.IExprVisitor;
 import org.aspectj.weaver.ast.ITestVisitor;
 import org.aspectj.weaver.ast.Instanceof;
@@ -171,6 +174,27 @@ public class BcelRenderer implements ITestVisitor, IExprVisitor {
         i.getVar().accept(this);
     }
 
+    public void visit(HasAnnotation hasAnnotation) {
+        instructions.insert(createJumpBasedOnBooleanOnStack());
+        // now insert the instructions that leave a boolean on the stack
+        // in Java:
+        // foo.class.isAnnotationPresent(annotationClass);
+        // in bytecode:
+        // load var onto the stack  (done for us later)
+        // invokevirtual java/lang/Object.getClass:()Ljava/lang/Class
+        // ldc_w annotationClass
+        // invokevirtual java/lang/Class.isAnnotationPresent:(Ljava/lang/Class;)Z
+        Member getClass = Member.method(TypeX.OBJECT, 0, "getClass", "()Ljava/lang/Class;");
+        instructions.insert(Utility.createInvoke(fact, world, getClass));
+        // aload annotationClass
+        int annClassIndex = fact.getConstantPool().addClass(hasAnnotation.getAnnotationType().getSignature());
+        instructions.insert(new LDC_W(annClassIndex));
+        Member isAnnotationPresent = Member.method(TypeX.forName("Ljava/lang/Class"),0,
+                "isAnnotationPresent","(Ljava/lang/Class;)Z");
+        instructions.insert(Utility.createInvoke(fact,world,isAnnotationPresent));
+        hasAnnotation.getVar().accept(this);
+    }
+    
        private InstructionList createJumpBasedOnBooleanOnStack() {
                InstructionList il = new InstructionList();
         if (sk == fk) {
index ad8eab5c8e942313f321aeffc4a5b300f75b0580..60edc3f3736e6af5a0a48384afbaf756c5202a57 100644 (file)
@@ -61,7 +61,7 @@ public abstract class AnnotationTypePattern extends PatternNode {
                byte key = s.readByte();
                switch(key) {
                        case EXACT: return ExactAnnotationTypePattern.read(s, context);
-//                     case BINDING: return BindingAnnotationTypePattern.read(s, context);
+                       case BINDING: return BindingAnnotationTypePattern.read(s, context);
                        case NOT: return NotAnnotationTypePattern.read(s, context);
                        case OR: return OrAnnotationTypePattern.read(s, context);
                        case AND: return AndAnnotationTypePattern.read(s, context);
index 1a369fccf1a6df3cc0b7db27f5f951f609edc452..d6b63205274238ef85a6406e2f9c03a246b5bbea 100644 (file)
@@ -55,6 +55,17 @@ public class BindingAnnotationTypePattern extends ExactAnnotationTypePattern imp
                        world.getMessageHandler().handleMessage(m);
                        resolved = false;
                }
+               if (!annotationType.hasAnnotation(TypeX.AT_RETENTION)) {
+                   // default is class visibility
+                       IMessage m = MessageUtil.error(
+                                       WeaverMessages.format(WeaverMessages.BINDING_NON_RUNTIME_RETENTION_ANNOTATION,annotationType.getName()),
+                                       getSourceLocation());
+                       world.getMessageHandler().handleMessage(m);
+                       resolved = false;                   
+               } else {
+                   // TO DO... get the retention policy annotation, and check the value is 
+                   // RetentionPolicy.RUNTIME;
+               }
                return this;
        }
        
index 1eab94f92badc3404934d4af36463cc28e0921d2..9b994deb8bda01af9ea9244f58189204445434ec 100644 (file)
@@ -351,7 +351,7 @@ public class PatternParser {
                if (maybeEat(")")) {
                        throw new ParserException("expecting @AnnotationName or parameter, but found ')'", tokenSource.peek());
                }
-               AnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); 
+               ExactAnnotationTypePattern type = parseAnnotationNameOrVarTypePattern(); 
                eat(")");
                return new ThisOrTargetAnnotationPointcut(kind.equals("this"),type);            
        }
index e29b80c445402ff9c0f9779c77f8a6a40ccf2081..afd01ce86846f22fb91ba823e6f7fedebe16cac2 100644 (file)
@@ -127,6 +127,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
        public static final byte ANNOTATION = 16;
        public static final byte ATWITHIN = 17;
        public static final byte ATWITHINCODE = 18;
+       public static final byte ATTHIS_OR_TARGET = 19;
        
        public static final byte NONE = 20;
 
@@ -247,6 +248,7 @@ public abstract class Pointcut extends PatternNode implements PointcutExpression
                        case ANNOTATION: ret = AnnotationPointcut.read(s, context); break;
                        case ATWITHIN: ret = WithinAnnotationPointcut.read(s, context); break;
                        case ATWITHINCODE: ret = WithinCodeAnnotationPointcut.read(s, context); break;
+                       case ATTHIS_OR_TARGET: ret = ThisOrTargetAnnotationPointcut.read(s, context); break;
                        case NONE: ret = makeMatchesNothing(RESOLVED); break;
                        default:
                                throw new BCException("unknown kind: " + kind);
diff --git a/weaver/src/org/aspectj/weaver/patterns/PointcutImpl.java b/weaver/src/org/aspectj/weaver/patterns/PointcutImpl.java
new file mode 100644 (file)
index 0000000..839ae93
--- /dev/null
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * 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:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.aspectj.weaver.patterns;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.JoinPoint.StaticPart;
+import org.aspectj.lang.reflect.Pointcut;
+import org.aspectj.util.FuzzyBoolean;
+
+/**
+ * Implementation of the reflective pointcut interface in org.aspectj.lang.reflect
+ * (not to be confused with the Pointcut class in this package, which itself should 
+ * be considered part of the weaver implementation).
+ */
+public class PointcutImpl implements Pointcut {
+
+    private String pointcutExpression;
+    private org.aspectj.weaver.patterns.Pointcut pointcut;
+    
+    public PointcutImpl(String pointcutExpression) {
+        this.pointcutExpression = pointcutExpression;
+        try {
+           pointcut = new PatternParser(pointcutExpression).parsePointcut(); 
+        } catch (ParserException pEx) {
+            throw new IllegalArgumentException(pEx.getMessage());
+        }
+    }
+    
+    /* (non-Javadoc)
+     * @see org.aspectj.lang.reflect.Pointcut#matches(org.aspectj.lang.JoinPoint, org.aspectj.lang.JoinPoint.StaticPart)
+     */
+    public boolean matches(JoinPoint jp, StaticPart enclosingJoinPoint) {
+        return pointcut.match(jp,enclosingJoinPoint) == FuzzyBoolean.YES;
+    }
+
+    /* (non-Javadoc)
+     * @see org.aspectj.lang.reflect.Pointcut#getPointcutExpression()
+     */
+    public String getPointcutExpression() {
+        return pointcutExpression;
+    }
+
+}
index 7c1a302640e8c19d14fdab1668ec58a19f979873..4b8686c27147c44939b1f2833236f31ee701ba56 100644 (file)
@@ -9,14 +9,25 @@
  * ******************************************************************/
 package org.aspectj.weaver.patterns;
 
+import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
 
+import org.aspectj.bridge.IMessage;
+import org.aspectj.bridge.ISourceLocation;
+import org.aspectj.bridge.Message;
+import org.aspectj.bridge.MessageUtil;
 import org.aspectj.util.FuzzyBoolean;
+import org.aspectj.weaver.ISourceContext;
 import org.aspectj.weaver.IntMap;
 import org.aspectj.weaver.ResolvedTypeX;
 import org.aspectj.weaver.Shadow;
+import org.aspectj.weaver.ShadowMunger;
+import org.aspectj.weaver.TypeX;
+import org.aspectj.weaver.WeaverMessages;
+import org.aspectj.weaver.ast.Literal;
 import org.aspectj.weaver.ast.Test;
+import org.aspectj.weaver.ast.Var;
 
 /**
  * @author colyer
@@ -27,31 +38,45 @@ import org.aspectj.weaver.ast.Test;
 public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
 
        private boolean isThis;
-       private AnnotationTypePattern type;
+       private ExactAnnotationTypePattern annotationTypePattern;
+       private ShadowMunger munger;
        
        /**
         * 
         */
-       public ThisOrTargetAnnotationPointcut(boolean isThis, AnnotationTypePattern type) {
+       public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type) {
                super();
                this.isThis = isThis;
-               this.type = type;
+               this.annotationTypePattern = type;
        }
 
+       public ThisOrTargetAnnotationPointcut(boolean isThis, ExactAnnotationTypePattern type, ShadowMunger munger) {
+           this(isThis,type);
+           this.munger = munger;
+       }
+       
        /* (non-Javadoc)
         * @see org.aspectj.weaver.patterns.Pointcut#fastMatch(org.aspectj.weaver.patterns.FastMatchInfo)
         */
        public FuzzyBoolean fastMatch(FastMatchInfo info) {
-               // TODO Auto-generated method stub
-               return null;
+               return FuzzyBoolean.MAYBE;
        }
 
        /* (non-Javadoc)
         * @see org.aspectj.weaver.patterns.Pointcut#match(org.aspectj.weaver.Shadow)
         */
        public FuzzyBoolean match(Shadow shadow) {
-               // TODO Auto-generated method stub
-               return null;
+               if (!couldMatch(shadow)) return FuzzyBoolean.NO;
+               TypeX annotationType = annotationTypePattern.annotationType;
+               annotationType = annotationType.resolve(shadow.getIWorld());
+               if (annotationType.hasAnnotation(TypeX.AT_INHERITED)) {
+                   // we can attempt to match now
+                   ResolvedTypeX toMatchAgainst = 
+                       (isThis ? shadow.getThisType() : shadow.getTargetType() ).resolve(shadow.getIWorld());
+                   return FuzzyBoolean.fromBoolean(toMatchAgainst.hasAnnotation(annotationType));
+               } 
+           // else we can only do matching via a runtime test
+               return FuzzyBoolean.MAYBE;
        }
 
        public boolean isThis() { return isThis; }
@@ -60,8 +85,17 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
         * @see org.aspectj.weaver.patterns.Pointcut#resolveBindings(org.aspectj.weaver.patterns.IScope, org.aspectj.weaver.patterns.Bindings)
         */
        protected void resolveBindings(IScope scope, Bindings bindings) {
-               // TODO Auto-generated method stub
-
+               annotationTypePattern = (ExactAnnotationTypePattern) annotationTypePattern.resolveBindings(scope,bindings,true);
+               // must be either a Var, or an annotation type pattern
+               // if annotationType does not have runtime retention, this is an error
+               ResolvedTypeX rAnnotationType = (ResolvedTypeX) annotationTypePattern.annotationType;
+               if (!(rAnnotationType.isAnnotationWithRuntimeRetention())) {
+                   IMessage m = MessageUtil.error(
+                                       WeaverMessages.format(WeaverMessages.BINDING_NON_RUNTIME_RETENTION_ANNOTATION,rAnnotationType.getName()),
+                                       getSourceLocation());
+                       scope.getMessageHandler().handleMessage(m);
+               }
+               
        }
 
        /* (non-Javadoc)
@@ -76,33 +110,102 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut {
         * @see org.aspectj.weaver.patterns.Pointcut#concretize1(org.aspectj.weaver.ResolvedTypeX, org.aspectj.weaver.IntMap)
         */
        protected Pointcut concretize1(ResolvedTypeX inAspect, IntMap bindings) {
-               // TODO Auto-generated method stub
-               return null;
+               ExactAnnotationTypePattern newType = (ExactAnnotationTypePattern) annotationTypePattern.remapAdviceFormals(bindings);           
+               Pointcut ret = new ThisOrTargetAnnotationPointcut(isThis, newType, bindings.getEnclosingAdvice());
+        ret.copyLocationFrom(this);
+        return ret;
        }
 
        /* (non-Javadoc)
         * @see org.aspectj.weaver.patterns.Pointcut#findResidue(org.aspectj.weaver.Shadow, org.aspectj.weaver.patterns.ExposedState)
         */
        public Test findResidue(Shadow shadow, ExposedState state) {
-               // TODO Auto-generated method stub
-               return null;
+           if (!couldMatch(shadow)) return Literal.FALSE;
+           boolean alwaysMatches = match(shadow).alwaysTrue();
+           Var var = isThis ? shadow.getThisVar() : shadow.getTargetVar();
+           Var annVar = null;
+           TypeX annotationType = annotationTypePattern.annotationType;
+               if (annotationTypePattern instanceof BindingAnnotationTypePattern) {
+                       BindingAnnotationTypePattern btp = (BindingAnnotationTypePattern)annotationTypePattern;
+                       annotationType = btp.annotationType;
+                       annVar = isThis ? shadow.getThisAnnotationVar(annotationType) :
+                                          shadow.getTargetAnnotationVar(annotationType);
+                       if (annVar == null) return Literal.TRUE;  // should be exception when we implement properly
+                       // Check if we have already bound something to this formal
+                       if (state.get(btp.getFormalIndex())!=null) {
+                               ISourceLocation pcdSloc = getSourceLocation(); 
+                               ISourceLocation shadowSloc = shadow.getSourceLocation();
+                               Message errorMessage = new Message(
+                                       "Cannot use @pointcut to match at this location and bind a formal to type '"+annVar.getType()+
+                                       "' - the formal is already bound to type '"+state.get(btp.getFormalIndex()).getType()+"'"+
+                                       ".  The secondary source location points to the problematic binding.",
+                                       shadowSloc,true,new ISourceLocation[]{pcdSloc}); 
+                               shadow.getIWorld().getMessageHandler().handleMessage(errorMessage);
+                               state.setErroneousVar(btp.getFormalIndex());
+                       }
+                       state.set(btp.getFormalIndex(),annVar);
+               }
+
+               if (alwaysMatches && (annVar == null)) {
+                   return Literal.TRUE;
+               } else {
+                   if (annVar != null) { 
+                       // TODO - need to bind it, next line is a placeholder
+                       return Literal.FALSE;
+                   } else {
+                       ResolvedTypeX rType = annotationType.resolve(shadow.getIWorld());
+                       return Test.makeHasAnnotation(var,rType);
+                   }
+               }
        }
 
+       
+       private boolean couldMatch(Shadow shadow) {
+               return isThis ? shadow.hasThis() : shadow.hasTarget();
+       }
+       
        /* (non-Javadoc)
         * @see org.aspectj.weaver.patterns.PatternNode#write(java.io.DataOutputStream)
         */
        public void write(DataOutputStream s) throws IOException {
-               // TODO Auto-generated method stub
-
+           s.writeByte(Pointcut.ATTHIS_OR_TARGET);
+           s.writeBoolean(isThis);
+               annotationTypePattern.write(s);
+               writeLocation(s);
        }
-
+       
+       public static Pointcut read(DataInputStream s, ISourceContext context) throws IOException {
+           boolean isThis = s.readBoolean();
+               AnnotationTypePattern type = AnnotationTypePattern.read(s, context);
+               ThisOrTargetAnnotationPointcut ret = new ThisOrTargetAnnotationPointcut(isThis,(ExactAnnotationTypePattern)type);
+               ret.readLocation(context, s);
+               return ret;
+       }
+       
+       /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object obj) {
+        if (!(obj instanceof ThisOrTargetAnnotationPointcut)) return false;
+        ThisOrTargetAnnotationPointcut other = (ThisOrTargetAnnotationPointcut) obj;
+        return ( other.annotationTypePattern.equals(this.annotationTypePattern) &&
+                 (other.isThis == this.isThis) );
+    }
+    
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        return 17 + 37*annotationTypePattern.hashCode() + (isThis ? 49 : 13);
+    }
+    
        /* (non-Javadoc)
      * @see java.lang.Object#toString()
      */
     public String toString() {
                StringBuffer buf = new StringBuffer();
                buf.append(isThis ? "@this(" : "@target(");
-               buf.append(type.toString());
+               buf.append(annotationTypePattern.toString());
                buf.append(")");
                return buf.toString();   
        }
index cd86ab148080018378b70276f4f2eaedeb7ef5d5..440faa7726cf7aea0e8204fbaf51325fcacfc540 100644 (file)
@@ -121,4 +121,4 @@ itdmOnAnnotationNotAllowed=can''t make inter-type method declarations on annotat
 itdfOnAnnotationNotAllowed=can''t make inter-type field declarations on annotation types
 
 referenceToNonAnnotationType=Type referred to is not an annotation type: {0}
-
+bindingNonRuntimeRetentionAnnotation=Annotation type {0} does not have runtime retention