@@ -255,7 +255,9 @@ | |||
will be emitted by the compiler if the pointcut expression associated with an | |||
advice statement can be statically determined to not match any join points. The | |||
warning can be suppressed for an individual advice statement by using the | |||
<literal>@SuppressWarnings({"unmatched"})</literal> annotation. (See JLS 9.6.1.5). | |||
<literal>@SuppressAjWarnings({"unmatched"})</literal> annotation. This works in | |||
the same way as the Java 5 SuppressWarnings annotation (See JLS 9.6.1.5), but has class file | |||
retention. | |||
</para> | |||
</sect1> | |||
@@ -264,11 +266,6 @@ | |||
<sect1 id="annotations-pointcuts-and-advice"> | |||
<title>Join Point Matching based on Annotations</title> | |||
<para><emphasis>Note: compared to the previous version, this version restricts the | |||
use of annotations in type patterns (package annotations and outer type annotations | |||
cannot be specified inline), and requires parenthesis more often. These changes were | |||
made to make pointcut expressions easier to read and interpret.</emphasis></para> | |||
<para> | |||
This section discusses changes to type pattern and signature pattern matching in | |||
AspectJ 5 that support matching join points based on the presence or absence of | |||
@@ -733,7 +730,7 @@ | |||
AtTarget := '@target' '(' AnnotationOrIdentifier ')' | |||
AnnotationOrIdentifier := '@' FullyQualifiedName | Identifier | |||
AnnotationOrIdentifier := FullyQualifiedName | Identifier | |||
AtArgs := '@args' '(' AnnotationsOrIdentifiersPattern ')' | |||
@@ -759,7 +756,7 @@ | |||
<variablelist> | |||
<varlistentry> | |||
<term>@this(@Foo)</term> | |||
<term>@this(Foo)</term> | |||
<listitem> | |||
<para> | |||
Matches any join point where the object currently bound to 'this' | |||
@@ -769,7 +766,7 @@ | |||
</varlistentry> | |||
<varlistentry> | |||
<term>call(* *(..)) && @target(@Classified)</term> | |||
<term>call(* *(..)) && @target(Classified)</term> | |||
<listitem> | |||
<para> | |||
Matches a call to any object where the target of the call has | |||
@@ -810,7 +807,7 @@ | |||
* matches any join point with at least one argument, and where the | |||
* type of the first argument has the @Classified annotation | |||
*/ | |||
pointcut classifiedArgument() : @args(@Classified,..); | |||
pointcut classifiedArgument() : @args(Classified,..); | |||
/** | |||
* matches any join point with three arguments, where the third | |||
@@ -867,7 +864,7 @@ | |||
<variablelist> | |||
<varlistentry> | |||
<term>@within(@Foo)</term> | |||
<term>@within(Foo)</term> | |||
<listitem> | |||
<para> | |||
Matches any join point where the executing code is defined | |||
@@ -1158,7 +1155,7 @@ | |||
<programlisting><![CDATA[ | |||
declare error : call(* org.xyz.model.*.*(..)) && | |||
!@within(@Trusted *) | |||
!@within(Trusted) | |||
: "Untrusted code should not call the model classes directly"; | |||
]]></programlisting> | |||
@@ -1259,11 +1256,16 @@ | |||
<title>Declare Annotation</title> | |||
<para>AspectJ 5 supports a new kind of declare statement, <literal>declare annotation</literal>. | |||
The general form of a <literal>declare annotation</literal> statement is: | |||
This takes different forms according to the recipient of the annotation: | |||
<literal>declare @type</literal> for types, <literal>declare @method</literal> for methods, | |||
<literal>declare @constructor</literal> for constructors, and <literal>declare @field</literal> | |||
for fields. <literal>declare @package</literal> may be supported in a future release. | |||
</para> | |||
<para>The general form is:</para> | |||
<programlisting><![CDATA[ | |||
declare annotation : ElementPattern : Annotation ; | |||
declare @<kind> : ElementPattern : Annotation ; | |||
]]></programlisting> | |||
<para>Where annotation is a regular annotation expression as defined in the Java 5 language. If the annotation has | |||
@@ -1284,7 +1286,7 @@ | |||
<variablelist> | |||
<varlistentry> | |||
<term>declare annotation : org.xyz.model..* : @BusinessDomain ;</term> | |||
<term>declare @type : org.xyz.model..* : @BusinessDomain ;</term> | |||
<listitem> | |||
<para> | |||
All types defined in a package with the prefix <literal>org.xyz.model</literal> | |||
@@ -1294,7 +1296,7 @@ | |||
</varlistentry> | |||
<varlistentry> | |||
<term>declare annotation : public * BankAccount+.*(..) : @Secured(role="supervisor")</term> | |||
<term>declare @method : public * BankAccount+.*(..) : @Secured(role="supervisor")</term> | |||
<listitem> | |||
<para> | |||
All public methods in <literal>BankAccount</literal> and its subtypes have the | |||
@@ -1304,7 +1306,7 @@ | |||
</varlistentry> | |||
<varlistentry> | |||
<term>declare annotation : * DAO+.* : @Persisted;</term> | |||
<term>declare @field : * DAO+.* : @Persisted;</term> | |||
<listitem> | |||
<para> | |||
All fields defined in <literal>DAO</literal> or its subtypes have the |
@@ -138,7 +138,7 @@ | |||
AtWithin := '@within' '(' AnnotationOrIdentifier ')' | |||
AtWithinCode := '@withincode' '(' AnnotationOrIdentifier ')' | |||
AnnotationOrIdentifier := '@' FullyQualifiedName | Identifier | |||
AnnotationOrIdentifier := FullyQualifiedName | Identifier | |||
AtArgs := '@args' '(' AnnotationsOrIdentifiersPattern ')' | |||
@@ -1,6 +1,6 @@ | |||
public aspect AnnotationAspect03 { | |||
declare warning : execution(* *.*(..)) && @annotation(@SimpleAnnotation) | |||
declare warning : execution(* *.*(..)) && @annotation(SimpleAnnotation) | |||
: "@annotation matched here"; | |||
@@ -62,62 +62,62 @@ public aspect AtArgsAspect { | |||
// Non-inherited | |||
// test 5 | |||
before() : myMethod() && @args(@MyAnnotation,..) { | |||
before() : myMethod() && @args(MyAnnotation,..) { | |||
System.out.print("@args(@MyAnnotation,..): "); | |||
System.out.println(TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
before() : myMethod() && !@args(@MyAnnotation,..) { | |||
before() : myMethod() && !@args(MyAnnotation,..) { | |||
System.out.print("@args(@MyAnnotation,..): "); | |||
System.out.println(!TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
// test 6 | |||
before() : myMethod() && @args(@MyAnnotation,*,*,@MyAnnotation,*) { | |||
before() : myMethod() && @args(MyAnnotation,*,*,MyAnnotation,*) { | |||
System.out.print("@args(@MyAnnotation,*,*,@MyAnnotation,*): "); | |||
System.out.println(TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
before() : myMethod() && !@args(@MyAnnotation,*,*,@MyAnnotation,*) { | |||
before() : myMethod() && !@args(MyAnnotation,*,*,MyAnnotation,*) { | |||
System.out.print("@args(@MyAnnotation,*,*,@MyAnnotation,*): "); | |||
System.out.println(!TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
// test 7 | |||
before() : myMethod() && @args(@MyAnnotation,*,*,@MyAnnotation,@MyAnnotation) { | |||
before() : myMethod() && @args(MyAnnotation,*,*,MyAnnotation,MyAnnotation) { | |||
System.out.print("@args(@MyAnnotation,*,*,@MyAnnotation,@MyAnnotation): "); | |||
System.out.println(TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
before() : myMethod() && !@args(@MyAnnotation,*,*,@MyAnnotation,@MyAnnotation) { | |||
before() : myMethod() && !@args(MyAnnotation,*,*,MyAnnotation,MyAnnotation) { | |||
System.out.print("@args(@MyAnnotation,*,*,@MyAnnotation,@MyAnnotation): "); | |||
System.out.println(!TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
// Inherited | |||
// test 8 | |||
before() : myMethod() && @args(..,@MyInheritableAnnotation,*) { | |||
before() : myMethod() && @args(..,MyInheritableAnnotation,*) { | |||
System.out.print("@args(..,@MyInheritableAnnotation,*): "); | |||
System.out.println(TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
@org.aspectj.lang.annotation.SuppressAjWarnings before() : myMethod() && !@args(..,@MyInheritableAnnotation,*) { | |||
@org.aspectj.lang.annotation.SuppressAjWarnings before() : myMethod() && !@args(..,MyInheritableAnnotation,*) { | |||
System.out.print("@args(..,@MyInheritableAnnotation,*): "); | |||
System.out.println(!TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
// test 9 | |||
before() : myMethod() && @args(..,@MyInheritableAnnotation,@MyInheritableAnnotation) { | |||
before() : myMethod() && @args(..,MyInheritableAnnotation,MyInheritableAnnotation) { | |||
System.out.print("@args(..,@MyInheritableAnnotation,@MyInheritableAnnotation): "); | |||
System.out.println(TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
@org.aspectj.lang.annotation.SuppressAjWarnings before() : myMethod() && !@args(..,@MyInheritableAnnotation,@MyInheritableAnnotation) { | |||
@org.aspectj.lang.annotation.SuppressAjWarnings before() : myMethod() && !@args(..,MyInheritableAnnotation,MyInheritableAnnotation) { | |||
System.out.print("@args(..,@MyInheritableAnnotation,@MyInheritableAnnotation): "); | |||
System.out.println(!TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
// test 10 | |||
before() : myMethod() && @args(..,@MyInheritableAnnotation,@MyInheritableAnnotation,@MyInheritableAnnotation) { | |||
before() : myMethod() && @args(..,MyInheritableAnnotation,MyInheritableAnnotation,MyInheritableAnnotation) { | |||
System.out.print("@args(..,@MyInheritableAnnotation,@MyInheritableAnnotation,@MyInheritableAnnotation): "); | |||
System.out.println(TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} | |||
before() : myMethod() && !@args(..,@MyInheritableAnnotation,@MyInheritableAnnotation,@MyInheritableAnnotation) { | |||
before() : myMethod() && !@args(..,MyInheritableAnnotation,MyInheritableAnnotation,MyInheritableAnnotation) { | |||
System.out.print("@args(..,@MyInheritableAnnotation,@MyInheritableAnnotation,@MyInheritableAnnotation): "); | |||
System.out.println(!TestingArgsAnnotations.expected() ? "PASS" : "FAIL"); | |||
} |
@@ -1,5 +1,5 @@ | |||
public aspect DeclareEoW { | |||
declare warning : @args(@MyAnnotation) : "@args is not allowed in declares..."; | |||
declare warning : @args(MyAnnotation) : "@args is not allowed in declares..."; | |||
} |
@@ -1,6 +1,6 @@ | |||
public aspect AtTargetAspect { | |||
before(): call(* *(..)) && @target(@MyAnnotation) { | |||
before(): call(* *(..)) && @target(MyAnnotation) { | |||
System.err.println("advice running"); | |||
} | |||
@@ -20,7 +20,7 @@ aspect X { | |||
static boolean b = false; | |||
before(): call(* m(..)) && !within(X) && @args(@Colored) { | |||
before(): call(* m(..)) && !within(X) && @args(Colored) { | |||
b=true; | |||
} | |||
@@ -3,11 +3,11 @@ import d.e.f.Color; | |||
public aspect X { | |||
before(): call(* *(..)) && @annotation(@Color) { | |||
before(): call(* *(..)) && @annotation(Color) { | |||
System.err.println("Before call to "+thisJoinPoint); | |||
} | |||
before(): execution(* *(..)) && @annotation(@Color) { | |||
before(): execution(* *(..)) && @annotation(Color) { | |||
System.err.println("Before execution of "+thisJoinPoint); | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
public aspect DeclareEoW { | |||
declare warning : @this(@MyAnnotation) : "should give compilation error"; | |||
declare warning : @this(MyAnnotation) : "should give compilation error"; | |||
declare error : @target(@MyAnnotation) : "should give compilation error"; | |||
declare error : @target(MyAnnotation) : "should give compilation error"; | |||
} |
@@ -4,13 +4,13 @@ public aspect NotRuntimeRetention { | |||
pointcut doSomethingCall() : call(* doSomething()); | |||
// CE L7 | |||
before() : doSomethingExecution() && @this(@MyClassRetentionAnnotation) { | |||
before() : doSomethingExecution() && @this(MyClassRetentionAnnotation) { | |||
// should be compile-time error! | |||
System.out.println("How did I get here?"); | |||
} | |||
// CE L13 | |||
after() returning : doSomethingCall() && @target(@MyClassRetentionAnnotation) { | |||
after() returning : doSomethingCall() && @target(MyClassRetentionAnnotation) { | |||
// should be compile-time error! | |||
System.out.println("How did I get here?"); | |||
} |
@@ -16,14 +16,14 @@ public aspect ThisOrTargetTests { | |||
pointcut doSomethingExecution() : execution(* doSomething()); | |||
pointcut doSomethingCall() : call(* doSomething()); | |||
before() : doSomethingExecution() && @this(@MyAnnotation) { | |||
before() : doSomethingExecution() && @this(MyAnnotation) { | |||
// should match: | |||
// b.doSomething(), reallyB.doSomething() [with test], | |||
// c.doSomething() | |||
add(before1Matches,thisJoinPointStaticPart); | |||
} | |||
before() : doSomethingExecution() && @this(@MyInheritableAnnotation) { | |||
before() : doSomethingExecution() && @this(MyInheritableAnnotation) { | |||
// should match: | |||
// c.doSomething() | |||
// d.doSomething() | |||
@@ -31,14 +31,14 @@ public aspect ThisOrTargetTests { | |||
add(before2Matches,thisJoinPointStaticPart); | |||
} | |||
after() returning : doSomethingCall() && @target(@MyAnnotation) { | |||
after() returning : doSomethingCall() && @target(MyAnnotation) { | |||
// should match: | |||
// b.doSomething(), reallyB.doSomething() [with test], | |||
// c.doSomething() | |||
add(after1Matches,thisJoinPointStaticPart); | |||
} | |||
after() returning : doSomethingCall() && @target(@MyInheritableAnnotation) { | |||
after() returning : doSomethingCall() && @target(MyInheritableAnnotation) { | |||
// should match: | |||
// c.doSomething() | |||
// d.doSomething() |
@@ -1,14 +1,14 @@ | |||
public aspect WithinAndWithinCodeTests { | |||
// should be two matches, L32 and L39 | |||
declare warning : execution(* doSomething(..)) && @within(@MyAnnotation) | |||
declare warning : execution(* doSomething(..)) && @within(MyAnnotation) | |||
: "@within match on non-inherited annotation"; | |||
// one match on L39 | |||
declare warning : execution(* doSomething(..)) && @within(@MyInheritableAnnotation) | |||
declare warning : execution(* doSomething(..)) && @within(MyInheritableAnnotation) | |||
: "@within match on inheritable annotation"; | |||
// one match on L32 | |||
declare warning : call(* doSomething(..)) && @withincode(@MyClassRetentionAnnotation) | |||
declare warning : call(* doSomething(..)) && @withincode(MyClassRetentionAnnotation) | |||
: "@withincode match"; | |||
} |
@@ -129,7 +129,8 @@ public class AnnotationPatternList extends PatternNode { | |||
if (type == AnnotationTypePattern.ELLIPSIS) { | |||
buf.append(".."); | |||
} else { | |||
buf.append(type.toString()); | |||
String annPatt = type.toString(); | |||
buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt); | |||
} | |||
} | |||
buf.append(")"); |
@@ -244,7 +244,8 @@ public class AnnotationPointcut extends NameBindingPointcut { | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append("@annotation("); | |||
buf.append(annotationTypePattern.toString()); | |||
String annPatt = annotationTypePattern.toString(); | |||
buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt); | |||
buf.append(")"); | |||
return buf.toString(); | |||
} |
@@ -42,7 +42,7 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
this.resolved = (annotationType instanceof ResolvedTypeX); | |||
} | |||
public ExactAnnotationTypePattern(String formalName) { | |||
protected ExactAnnotationTypePattern(String formalName) { | |||
this.formalName = formalName; | |||
this.resolved = false; | |||
this.bindingPattern = true; | |||
@@ -104,8 +104,9 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
Bindings bindings, boolean allowBinding) { | |||
if (resolved) return this; | |||
resolved = true; | |||
if (formalName != null) { | |||
FormalBinding formalBinding = scope.lookupFormal(formalName); | |||
String simpleName = maybeGetSimpleName(); | |||
if (simpleName != null) { | |||
FormalBinding formalBinding = scope.lookupFormal(simpleName); | |||
if (formalBinding != null) { | |||
if (bindings == null) { | |||
scope.message(IMessage.ERROR, this, "negation doesn't allow binding"); | |||
@@ -116,6 +117,8 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
"name binding only allowed in @pcds, args, this, and target"); | |||
return this; | |||
} | |||
formalName = simpleName; | |||
bindingPattern = true; | |||
verifyIsAnnotationType(formalBinding.getType(),scope); | |||
BindingAnnotationTypePattern binding = new BindingAnnotationTypePattern(formalBinding); | |||
binding.copyLocationFrom(this); | |||
@@ -123,30 +126,32 @@ public class ExactAnnotationTypePattern extends AnnotationTypePattern { | |||
binding.resolveBinding(scope.getWorld()); | |||
return binding; | |||
} else { | |||
scope.message(IMessage.ERROR,this,"unbound formal " + formalName); | |||
return this; | |||
} | |||
} else { | |||
// Non binding case | |||
} | |||
} | |||
String cleanname = annotationType.getName(); | |||
annotationType = scope.getWorld().resolve(annotationType,true); | |||
// We may not have found it if it is in a package, lets look it up... | |||
if (annotationType == ResolvedTypeX.MISSING) { | |||
TypeX type = null; | |||
while ((type = scope.lookupType(cleanname,this)) == ResolvedTypeX.MISSING) { | |||
int lastDot = cleanname.lastIndexOf('.'); | |||
if (lastDot == -1) break; | |||
cleanname = cleanname.substring(0,lastDot)+"$"+cleanname.substring(lastDot+1); | |||
} | |||
annotationType = scope.getWorld().resolve(type,true); | |||
// Non binding case | |||
String cleanname = annotationType.getName(); | |||
annotationType = scope.getWorld().resolve(annotationType,true); | |||
// We may not have found it if it is in a package, lets look it up... | |||
if (annotationType == ResolvedTypeX.MISSING) { | |||
TypeX type = null; | |||
while ((type = scope.lookupType(cleanname,this)) == ResolvedTypeX.MISSING) { | |||
int lastDot = cleanname.lastIndexOf('.'); | |||
if (lastDot == -1) break; | |||
cleanname = cleanname.substring(0,lastDot)+"$"+cleanname.substring(lastDot+1); | |||
} | |||
verifyIsAnnotationType(annotationType,scope); | |||
return this; | |||
annotationType = scope.getWorld().resolve(type,true); | |||
} | |||
verifyIsAnnotationType(annotationType,scope); | |||
return this; | |||
} | |||
private String maybeGetSimpleName() { | |||
if (formalName != null) return formalName; | |||
String ret = annotationType.getName(); | |||
return (ret.indexOf('.') == -1) ? ret : null; | |||
} | |||
/** |
@@ -689,11 +689,9 @@ public class PatternParser { | |||
ExactAnnotationTypePattern p = null; | |||
int startPos = tokenSource.peek().getStart(); | |||
if (maybeEat("@")) { | |||
p = parseSimpleAnnotationName(); | |||
} else { | |||
String formal = parseIdentifier(); | |||
p = new ExactAnnotationTypePattern(formal); // will get replaced when bindings resolved | |||
throw new ParserException("@Foo form was deprecated in AspectJ 5 M2: annotation name or var ",tokenSource.peek(-1)); | |||
} | |||
p = parseSimpleAnnotationName(); | |||
int endPos = tokenSource.peek(-1).getEnd(); | |||
p.setLocation(sourceContext,startPos,endPos); | |||
return p; |
@@ -261,7 +261,8 @@ public class ThisOrTargetAnnotationPointcut extends NameBindingPointcut { | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append(isThis ? "@this(" : "@target("); | |||
buf.append(annotationTypePattern.toString()); | |||
String annPatt = annotationTypePattern.toString(); | |||
buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt); | |||
buf.append(")"); | |||
return buf.toString(); | |||
} |
@@ -199,7 +199,8 @@ public class WithinAnnotationPointcut extends NameBindingPointcut { | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append("@within("); | |||
buf.append(annotationTypePattern.toString()); | |||
String annPatt = annotationTypePattern.toString(); | |||
buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt); | |||
buf.append(")"); | |||
return buf.toString(); | |||
} |
@@ -206,7 +206,8 @@ public class WithinCodeAnnotationPointcut extends NameBindingPointcut { | |||
public String toString() { | |||
StringBuffer buf = new StringBuffer(); | |||
buf.append("@withincode("); | |||
buf.append(annotationTypePattern.toString()); | |||
String annPatt = annotationTypePattern.toString(); | |||
buf.append(annPatt.startsWith("@") ? annPatt.substring(1) : annPatt); | |||
buf.append(")"); | |||
return buf.toString(); | |||
} |
@@ -110,7 +110,7 @@ public class AnnotationPatternTestCase extends TestCase { | |||
} | |||
public void testParseNameOrVarAnnotationPattern() { | |||
PatternParser p = new PatternParser("@Foo"); | |||
PatternParser p = new PatternParser("Foo"); | |||
AnnotationTypePattern foo = p.parseAnnotationNameOrVarTypePattern(); | |||
assertTrue("ExactAnnotationTypePattern",foo instanceof ExactAnnotationTypePattern); | |||
assertEquals("Foo",TypeX.forName("Foo"),((ExactAnnotationTypePattern)foo).annotationType); | |||
@@ -127,7 +127,7 @@ public class AnnotationPatternTestCase extends TestCase { | |||
} | |||
public void testParseNameOrVarAnnotationPatternWithOr() { | |||
PatternParser p = new PatternParser("@Foo || @Boo"); | |||
PatternParser p = new PatternParser("Foo || Boo"); | |||
AnnotationTypePattern foo = p.parseAnnotationNameOrVarTypePattern(); | |||
// rest of pattern not consumed... | |||
assertTrue("ExactAnnotationTypePattern",foo instanceof ExactAnnotationTypePattern); | |||
@@ -138,12 +138,11 @@ public class AnnotationPatternTestCase extends TestCase { | |||
PatternParser p = new PatternParser("foo"); | |||
AnnotationTypePattern foo = p.parseAnnotationNameOrVarTypePattern(); | |||
assertTrue("ExactAnnotationTypePattern",foo instanceof ExactAnnotationTypePattern); | |||
assertNull("no type pattern yet",((ExactAnnotationTypePattern)foo).annotationType); | |||
assertEquals("foo",((ExactAnnotationTypePattern)foo).formalName); | |||
assertEquals("@foo",((ExactAnnotationTypePattern)foo).toString()); | |||
} | |||
public void testParseNameOrVarAnnotationPatternWithAnd() { | |||
PatternParser p = new PatternParser("@Foo @Boo"); | |||
PatternParser p = new PatternParser("Foo Boo"); | |||
AnnotationTypePattern foo = p.parseAnnotationNameOrVarTypePattern(); | |||
// rest of pattern not consumed... | |||
assertEquals("@Foo",foo.toString()); |
@@ -152,13 +152,13 @@ public class ParserTestCase extends TestCase { | |||
} | |||
public void testAtAnnotation() { | |||
PatternParser parser = new PatternParser("@annotation(@Foo)"); | |||
PatternParser parser = new PatternParser("@annotation(Foo)"); | |||
AnnotationPointcut p = (AnnotationPointcut) parser.parsePointcut(); | |||
assertEquals("@annotation(@Foo)",p.toString()); | |||
assertEquals("@annotation(Foo)",p.toString()); | |||
} | |||
public void testBadAtAnnotation() { | |||
PatternParser parser = new PatternParser("@annotation(!@Foo)"); | |||
PatternParser parser = new PatternParser("@annotation(!Foo)"); | |||
try { | |||
Pointcut p = parser.parsePointcut(); | |||
fail("Expected parser exception"); | |||
@@ -174,7 +174,7 @@ public class ParserTestCase extends TestCase { | |||
} | |||
public void testDoubleAtAnnotation() { | |||
PatternParser parser = new PatternParser("@annotation(@Foo @Goo)"); | |||
PatternParser parser = new PatternParser("@annotation(Foo Goo)"); | |||
try { | |||
Pointcut p = parser.parsePointcut(); | |||
fail("Expected parser exception"); | |||
@@ -187,18 +187,18 @@ public class ParserTestCase extends TestCase { | |||
PatternParser parser = new PatternParser("@within(foo)"); | |||
WithinAnnotationPointcut p = (WithinAnnotationPointcut) parser.parsePointcut(); | |||
assertEquals("@within(foo)",p.toString()); | |||
parser = new PatternParser("@within(@Foo))"); | |||
parser = new PatternParser("@within(Foo))"); | |||
p = (WithinAnnotationPointcut) parser.parsePointcut(); | |||
assertEquals("@within(@Foo)",p.toString()); | |||
assertEquals("@within(Foo)",p.toString()); | |||
} | |||
public void testAtWithinCode() { | |||
PatternParser parser = new PatternParser("@withincode(foo)"); | |||
WithinCodeAnnotationPointcut p = (WithinCodeAnnotationPointcut) parser.parsePointcut(); | |||
assertEquals("@withincode(foo)",p.toString()); | |||
parser = new PatternParser("@withincode(@Foo))"); | |||
parser = new PatternParser("@withincode(Foo))"); | |||
p = (WithinCodeAnnotationPointcut) parser.parsePointcut(); | |||
assertEquals("@withincode(@Foo)",p.toString()); | |||
assertEquals("@withincode(Foo)",p.toString()); | |||
} | |||
public void testAtThis() { | |||
@@ -206,10 +206,10 @@ public class ParserTestCase extends TestCase { | |||
ThisOrTargetAnnotationPointcut p = (ThisOrTargetAnnotationPointcut) parser.parsePointcut(); | |||
assertEquals("@this(foo)",p.toString()); | |||
assertTrue("isThis",p.isThis()); | |||
parser = new PatternParser("@this(@Foo))"); | |||
parser = new PatternParser("@this(Foo))"); | |||
p = (ThisOrTargetAnnotationPointcut) parser.parsePointcut(); | |||
assertTrue("isThis",p.isThis()); | |||
assertEquals("@this(@Foo)",p.toString()); | |||
assertEquals("@this(Foo)",p.toString()); | |||
} | |||
public void testAtTarget() { | |||
@@ -217,16 +217,16 @@ public class ParserTestCase extends TestCase { | |||
ThisOrTargetAnnotationPointcut p = (ThisOrTargetAnnotationPointcut) parser.parsePointcut(); | |||
assertEquals("@target(foo)",p.toString()); | |||
assertTrue("isTarget",!p.isThis()); | |||
parser = new PatternParser("@target(@Foo))"); | |||
parser = new PatternParser("@target(Foo))"); | |||
p = (ThisOrTargetAnnotationPointcut) parser.parsePointcut(); | |||
assertTrue("isTarget",!p.isThis()); | |||
assertEquals("@target(@Foo)",p.toString()); | |||
assertEquals("@target(Foo)",p.toString()); | |||
} | |||
public void testAtArgs() { | |||
PatternParser parser = new PatternParser("@args(@Foo,@Goo,*,..,@Moo)"); | |||
PatternParser parser = new PatternParser("@args(Foo,Goo,*,..,Moo)"); | |||
Pointcut p = parser.parsePointcut(); | |||
assertEquals("@args(@Foo, @Goo, @ANY, .., @Moo)",p.toString()); | |||
assertEquals("@args(Foo, Goo, ANY, .., Moo)",p.toString()); | |||
} | |||
public TestScope makeSimpleScope() { |
@@ -289,7 +289,7 @@ public class PointcutRewriterTest extends TestCase { | |||
} | |||
} | |||
// + @ | |||
p = getPointcut("@this(@Foo)"); | |||
p = getPointcut("@this(Foo)"); | |||
matches = p.couldMatchKinds(); | |||
for (Iterator iter = matches.iterator(); iter.hasNext();) { | |||
Shadow.Kind kind = (Shadow.Kind) iter.next(); | |||
@@ -315,7 +315,7 @@ public class PointcutRewriterTest extends TestCase { | |||
} | |||
} | |||
// + @ | |||
p = getPointcut("@target(@Foo)"); | |||
p = getPointcut("@target(Foo)"); | |||
matches = p.couldMatchKinds(); | |||
for (Iterator iter = matches.iterator(); iter.hasNext();) { | |||
Shadow.Kind kind = (Shadow.Kind) iter.next(); | |||
@@ -337,7 +337,7 @@ public class PointcutRewriterTest extends TestCase { | |||
} | |||
public void testKindSetOfAnnotation() { | |||
Pointcut p = getPointcut("@annotation(@Foo)"); | |||
Pointcut p = getPointcut("@annotation(Foo)"); | |||
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS)); | |||
} | |||
@@ -345,7 +345,7 @@ public class PointcutRewriterTest extends TestCase { | |||
Pointcut p = getPointcut("within(*)"); | |||
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS)); | |||
// + @ | |||
p = getPointcut("@within(@Foo)"); | |||
p = getPointcut("@within(Foo)"); | |||
assertTrue("All kinds",p.couldMatchKinds().containsAll(Shadow.ALL_SHADOW_KINDS)); | |||
} | |||
@@ -365,7 +365,7 @@ public class PointcutRewriterTest extends TestCase { | |||
assertTrue("Need cons-exe for inlined field inits",matches.contains(Shadow.ConstructorExecution)); | |||
assertTrue("Need init for inlined field inits",matches.contains(Shadow.Initialization)); | |||
// + @ | |||
p = getPointcut("@withincode(@Foo)"); | |||
p = getPointcut("@withincode(Foo)"); | |||
matches = p.couldMatchKinds(); | |||
for (Iterator iter = matches.iterator(); iter.hasNext();) { | |||
Shadow.Kind kind = (Shadow.Kind) iter.next(); | |||
@@ -409,9 +409,9 @@ public class PointcutRewriterTest extends TestCase { | |||
} | |||
public void testOrderingInAnd() { | |||
Pointcut bigLongPC = getPointcut("cflow(this(Foo)) && @args(@X) && args(X) && @this(@Foo) && @target(@Boo) && this(Moo) && target(Boo) && @annotation(@Moo) && @withincode(@Boo) && withincode(new(..)) && set(* *)&& @within(@Foo) && within(Foo)"); | |||
Pointcut bigLongPC = getPointcut("cflow(this(Foo)) && @args(X) && args(X) && @this(Foo) && @target(Boo) && this(Moo) && target(Boo) && @annotation(Moo) && @withincode(Boo) && withincode(new(..)) && set(* *)&& @within(Foo) && within(Foo)"); | |||
Pointcut rewritten = prw.rewrite(bigLongPC); | |||
assertEquals("((((((((((((within(Foo) && @within(@Foo)) && set(* *)) && withincode(new(..))) && @withincode(@Boo)) && @annotation(@Moo)) && target(Boo)) && this(Moo)) && @target(@Boo)) && @this(@Foo)) && args(X)) && @args(@X)) && cflow(this(Foo)))",rewritten.toString()); | |||
assertEquals("((((((((((((within(Foo) && @within(Foo)) && set(* *)) && withincode(new(..))) && @withincode(Boo)) && @annotation(Moo)) && target(Boo)) && this(Moo)) && @target(Boo)) && @this(Foo)) && args(X)) && @args(X)) && cflow(this(Foo)))",rewritten.toString()); | |||
} | |||
public void testOrderingInSimpleOr() { |