Bug 153464

Summary: negated annotation type pattern fails
Product: [Tools] AspectJ Reporter: Wes Isberg <wes>
Component: CompilerAssignee: aspectj inbox <aspectj-inbox>
Status: NEW --- QA Contact:
Severity: normal    
Priority: P3 CC: aclement
Version: 1.5.2   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Wes Isberg CLA 2006-08-10 12:31:03 EDT
!within(@Annot *) works to exclude annotated classes, but within(!@Annot *) does not, though permitted syntactically in the AspectJ 5 developers guide.

 http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-pointcuts-and-advice.html#type-patterns

(Taken from excellent user-list email "Combination of Class Annotation and Method Annotation matching" by Takao Nakaguchi.)

--------------------------------------------------

package ajsandbox;

public class AnnotTest {
    public static aspect TestAspect {
        // works - Derived.func() omitted
        //declare warning : execution(@Annot * *(..)) && !within(@Annot *): "hi!";
        
        // fails - Derived.func() not omitted
        declare warning : execution(@Annot * *(..)) && within(!@Annot *)
            : "unexpected warning";
    }

    @interface Annot {
    };

    class Base {
        void func() {
        }
    }

    @Annot
    class Derived extends Base {
        // ok! and ng!
        @Annot
        void func() {
        }
    }

    class NoAnnotClass {
        // ng!
        @Annot
        void func() {
        }
    }
}
Comment 1 Andrew Clement CLA 2006-09-25 10:55:05 EDT
interesting program.

The reason this pointcut 

execution(@Annot * *(..)) && within(!@Annot *)

matches against the first type is because of the use of an inner type.

class AnnotTest {
  @Annot
  class Derived extends Base {
    @Annot void func() { }
  }
}

the method-execution of func() does kind of occur 'within' a non-annotated type, the AnnotTest type.  If we annotate AnnotTest like this:

@Annot
class AnnotTest {
  @Annot
  class Derived extends Base {
    @Annot void func() { }
  }
}

then the pointcut no longer matches.

So we have to think about the difference between: "!within(@Annot *)" and "within(!Annot *)".  The first says "match join points that are not within an @Annot annotated type", the second says "match joinpoints that are within a non-@Annot annotated type".
Comment 2 Andrew Clement CLA 2006-09-25 10:57:36 EDT
testcase is committed but commented out