The documentation specifies annotation style pointcuts can use if(false) or if(true) and not require a boolean return value and body for the @Pointcut annotated method but it doesn't work without this change to validation that recognizes the situation. Fixes #115tags/V1_9_8
boolean noValueSupplied = true; | boolean noValueSupplied = true; | ||||
boolean containsIfPcd = false; | boolean containsIfPcd = false; | ||||
boolean isIfTrueOrFalse = false; | |||||
int[] pcLocation = new int[2]; | int[] pcLocation = new int[2]; | ||||
String pointcutExpression = getStringLiteralFor("value", ajAnnotations.pointcutAnnotation, pcLocation); | String pointcutExpression = getStringLiteralFor("value", ajAnnotations.pointcutAnnotation, pcLocation); | ||||
try { | try { | ||||
} else { | } else { | ||||
noValueSupplied = false; | noValueSupplied = false; | ||||
pc = new PatternParser(pointcutExpression, context).parsePointcut(); | pc = new PatternParser(pointcutExpression, context).parsePointcut(); | ||||
if (pc instanceof IfPointcut) { | |||||
if (((IfPointcut)pc).alwaysFalse() || ((IfPointcut)pc).alwaysTrue()) { | |||||
isIfTrueOrFalse = true; | |||||
} | |||||
} | |||||
} | } | ||||
pcDecl.pointcutDesignator = (pc == null) ? null : new PointcutDesignator(pc); | pcDecl.pointcutDesignator = (pc == null) ? null : new PointcutDesignator(pc); | ||||
pcDecl.setGenerateSyntheticPointcutMethod(); | pcDecl.setGenerateSyntheticPointcutMethod(); | ||||
methodDeclaration.returnType.sourceEnd, | methodDeclaration.returnType.sourceEnd, | ||||
"Methods annotated with @Pointcut must return void unless the pointcut contains an if() expression"); | "Methods annotated with @Pointcut must return void unless the pointcut contains an if() expression"); | ||||
} | } | ||||
if (!returnsBoolean && containsIfPcd) { | |||||
if (!returnsBoolean && containsIfPcd && !isIfTrueOrFalse) { | |||||
methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart, | methodDeclaration.scope.problemReporter().signalError(methodDeclaration.returnType.sourceStart, | ||||
methodDeclaration.returnType.sourceEnd, | methodDeclaration.returnType.sourceEnd, | ||||
"Methods annotated with @Pointcut must return boolean when the pointcut contains an if() expression"); | |||||
"Methods annotated with @Pointcut must return boolean when the pointcut contains an if() expression unless it is if(false) or if(true)"); | |||||
} | } | ||||
if (methodDeclaration.statements != null && methodDeclaration.statements.length > 0 && !containsIfPcd) { | if (methodDeclaration.statements != null && methodDeclaration.statements.length > 0 && !containsIfPcd) { |
import org.aspectj.lang.annotation.Aspect; | |||||
import org.aspectj.lang.annotation.Before; | |||||
import org.aspectj.lang.annotation.Pointcut; | |||||
public class A { | |||||
public static void main(String []argv) { | |||||
System.out.println("A.main"); | |||||
} | |||||
} | |||||
@Aspect | |||||
class Azpect { | |||||
@Pointcut("if(false)") | |||||
public void isFalse() { } | |||||
@Pointcut("if(true)") | |||||
public void isTrue() { } | |||||
@Before("isTrue() && execution(* A.main(..))") | |||||
public void beforeTrue() { | |||||
System.out.println("Azpect.beforeTrue"); | |||||
} | |||||
@Before("isFalse() && execution(* A.main(..))") | |||||
public void beforeFalse() { | |||||
System.out.println("Azpect.beforeFalse"); | |||||
} | |||||
} | |||||
import org.aspectj.lang.annotation.Aspect; | |||||
import org.aspectj.lang.annotation.Before; | |||||
import org.aspectj.lang.annotation.Pointcut; | |||||
public class B { | |||||
public static void main(String []argv) { | |||||
System.out.println("B.main"); | |||||
} | |||||
} | |||||
@Aspect | |||||
abstract class AbstractAzpect { | |||||
@Pointcut | |||||
public abstract void isTrue(); | |||||
@Before("isTrue() && execution(* B.main(..))") | |||||
public void beforeFalse() { | |||||
System.out.println("Azpect.beforeFalse"); | |||||
} | |||||
} | |||||
@Aspect | |||||
class Azpect extends AbstractAzpect { | |||||
@Override | |||||
@Pointcut("if(true)") | |||||
public void isTrue() { } | |||||
} | |||||
// TODO: replace 0 by Constants.PREVIEW_MINOR_VERSION after no longer using EA build, but final JDK version | // TODO: replace 0 by Constants.PREVIEW_MINOR_VERSION after no longer using EA build, but final JDK version | ||||
checkVersion("PersonAspect", Constants.MAJOR_17, 0 /*Constants.PREVIEW_MINOR_VERSION*/); | checkVersion("PersonAspect", Constants.MAJOR_17, 0 /*Constants.PREVIEW_MINOR_VERSION*/); | ||||
} | } | ||||
public void testAnnotationStyleSpecialIfClauses() { | |||||
runTest("annotation style A"); | |||||
} | |||||
public void testAnnotationStylePointcutInheritanceWithIfClauses() { | |||||
runTest("annotation style B"); | |||||
} | |||||
public static Test suite() { | public static Test suite() { | ||||
return XMLBasedAjcTestCase.loadSuite(Ajc198TestsJava.class); | return XMLBasedAjcTestCase.loadSuite(Ajc198TestsJava.class); |
<compile files="Buffers.java" options="--release 8"/> | <compile files="Buffers.java" options="--release 8"/> | ||||
</ajc-test> | </ajc-test> | ||||
<ajc-test dir="bugs198/github_115" title="annotation style A"> | |||||
<compile files="A.java" options="-1.5"> | |||||
<message kind="warning" line="28" text="advice defined in Azpect has not been applied [Xlint:adviceDidNotMatch]"/> | |||||
</compile> | |||||
<run class="A"> | |||||
<stdout> | |||||
<line text="Azpect.before"/> | |||||
<line text="A.main"/> | |||||
</stdout> | |||||
</run> | |||||
</ajc-test> | |||||
<ajc-test dir="bugs198/github_115" title="annotation style B"> | |||||
<compile files="B.java" options="-1.5"/> | |||||
<run class="B"> | |||||
<stdout> | |||||
<line text="Azpect.before"/> | |||||
<line text="B.main"/> | |||||
</stdout> | |||||
</run> | |||||
</ajc-test> | |||||
</suite> | </suite> |