splitted ajc150 xml test filetags/PRE_ANDY
@@ -135,5 +135,20 @@ public abstract class AutowiredXMLBasedAjcTestCase extends XMLBasedAjcTestCase { | |||
super.setUp(); | |||
} | |||
/** | |||
* This helper method runs the test with the given title in the | |||
* suite spec file. All tests steps in given ajc-test execute | |||
* in the same sandbox. | |||
*/ | |||
protected void runTest(String title) { | |||
AjcTest currentTest = (AjcTest) testMap.get(title); | |||
if (currentTest == null) { | |||
fail("No test '" + title + "' in suite."); | |||
} | |||
ajc.setShouldEmptySandbox(true); | |||
currentTest.runTest(this); | |||
} | |||
} |
@@ -17,10 +17,13 @@ import org.aspectj.lang.annotation.Pointcut; | |||
import org.aspectj.lang.annotation.Around; | |||
import org.aspectj.lang.JoinPoint; | |||
import org.aspectj.lang.ProceedingJoinPoint; | |||
import org.aspectj.lang.Aspects; | |||
import org.aspectj.lang.annotation.Around; | |||
import org.aspectj.lang.annotation.Aspect; | |||
import org.aspectj.lang.annotation.Pointcut; | |||
import java.security.PrivilegedAction; | |||
/** | |||
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | |||
*/ | |||
@@ -43,6 +46,10 @@ public class BindingTest extends TestCase { | |||
return i*3;//see x3 here | |||
} | |||
public int echo(int i) { | |||
return i; | |||
} | |||
public void testAroundArgs() { | |||
int res = substract(3, 2);// should be 2 without around advice | |||
assertEquals(1, res); | |||
@@ -54,6 +61,35 @@ public class BindingTest extends TestCase { | |||
callWithinStatic(); | |||
} | |||
public void testProceedInInner() { | |||
int res = echo(3);//advice will x2 using an inner | |||
assertEquals(6, res); | |||
} | |||
public void testNoProceed() { | |||
int res = echo(3);//advice will return 0 and not proceed | |||
assertEquals(0, res); | |||
} | |||
public void testDoubleProceed() { | |||
int res = echo(3);//advice will proceed twice and add the returned values | |||
assertEquals(6, res); | |||
} | |||
public void testDoubleProceedOneInner() { | |||
int res = echo(3);//advice will proceed twice with one in inner and add the returned values | |||
assertEquals(6, res); | |||
} | |||
public void testAccessAspectState() { | |||
//TestAspect_1 aspect = (TestAspect_1) Aspects.aspectOf(TestAspect_1.class); | |||
//aspect.m_count = 0; | |||
int res = echo(3); | |||
res += echo(3); | |||
assertEquals(6, res); | |||
//assertEquals(2, aspect.m_count); | |||
} | |||
private static void callWithinStatic() { | |||
int res = dup((3+1)); | |||
assertEquals(6, res); | |||
@@ -62,9 +98,12 @@ public class BindingTest extends TestCase { | |||
@Aspect | |||
public static class TestAspect_1 { | |||
private int m_count = 0; | |||
@Pointcut("call(int substract(int, int)) && within(ataspectj.BindingTest) && args(arg1, arg2)") | |||
void pc(int arg2, int arg1) {}// see rather fancy ordering here.. | |||
// see return int here. | |||
@Around("pc(argAdvice2, argAdvice1) && target(t)")//see here ordering remade consistent | |||
public int aaround(ProceedingJoinPoint jp, BindingTest t, int argAdvice1, int argAdvice2) throws Throwable { | |||
int res = ((Integer)jp.proceed()).intValue(); | |||
@@ -79,5 +118,69 @@ public class BindingTest extends TestCase { | |||
int res = ((Integer)jp.proceed(new Object[]{new Integer(argAdvice1-1)})).intValue(); | |||
return new Integer(res/3*2); | |||
} | |||
@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testProceedInInner()) && args(i)") | |||
public int aaround3(int i, final ProceedingJoinPoint jp) throws Throwable { | |||
final StringBuffer sb = new StringBuffer(); | |||
Runnable r = new Runnable() { | |||
public void run() { | |||
try { | |||
int res = ((Integer)jp.proceed()).intValue(); | |||
sb.append(res); | |||
} catch (Throwable t) { | |||
fail(t.toString()); | |||
} | |||
} | |||
}; | |||
Thread t = new Thread(r); | |||
t.start(); | |||
t.join(); | |||
assertEquals(i, Integer.parseInt(sb.toString())); | |||
return Integer.parseInt(sb.toString())*2; | |||
} | |||
@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testNoProceed()) && args(i)") | |||
public int aaround4(int i, final ProceedingJoinPoint jp) throws Throwable { | |||
// since no proceed() is call, this advice won't be inlined | |||
return 0; | |||
} | |||
@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testDoubleProceed()) && args(i)") | |||
public int aaround5(int i, final ProceedingJoinPoint jp) throws Throwable { | |||
int i1 = ((Integer)jp.proceed()).intValue(); | |||
int i2 = ((Integer)jp.proceed()).intValue(); | |||
return i1 + i2; | |||
} | |||
@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testDoubleProceedOneInner()) && args(i)") | |||
public int aaround6(int i, final ProceedingJoinPoint jp) throws Throwable { | |||
int i1 = ((Integer)jp.proceed()).intValue(); | |||
Object io2 = new PrivilegedAction() { | |||
public Object run() { | |||
try { | |||
return jp.proceed(); | |||
} catch (Throwable t) { | |||
fail(t.toString()); | |||
return null; | |||
} | |||
} | |||
}.run(); | |||
if (io2 == null) { | |||
// since inlining occured, proceed was never called | |||
fail("should not happen - advice was probably inlined while it must not be"); | |||
return i1 * 2; | |||
} else { | |||
int i2 = ((Integer)io2).intValue(); | |||
return i1 + i2; | |||
} | |||
} | |||
@Around("call(int echo(int)) && withincode(void ataspectj.BindingTest.testAccessAspectState()) && args(i)") | |||
public Object aaround7(int i, final ProceedingJoinPoint jp) throws Throwable { | |||
//m_count++;// what if inlined ? | |||
return jp.proceed(); | |||
} | |||
} | |||
} |
@@ -28,7 +28,7 @@ public class AtAjAnnotationGenTests extends XMLBasedAjcTestCase { | |||
} | |||
protected File getSpecFile() { | |||
return new File("../tests/src/org/aspectj/systemtest/ajc150/ataspectj/atajc150.xml"); | |||
return new File("../tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml"); | |||
} | |||
public void testSimpleAspect() { |
@@ -16,63 +16,21 @@ import java.io.File; | |||
import junit.framework.Test; | |||
import org.aspectj.testing.XMLBasedAjcTestCase; | |||
import org.aspectj.testing.AutowiredXMLBasedAjcTestCase; | |||
/** | |||
* A suite for @AspectJ aspects located in java5/ataspectj | |||
* | |||
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | |||
*/ | |||
public class AtAjSyntaxTests extends XMLBasedAjcTestCase { | |||
public class AtAjSyntaxTests extends AutowiredXMLBasedAjcTestCase { | |||
public static Test suite() { | |||
return XMLBasedAjcTestCase.loadSuite(AtAjSyntaxTests.class); | |||
return AutowiredXMLBasedAjcTestCase.loadSuite(AtAjSyntaxTests.class); | |||
} | |||
protected File getSpecFile() { | |||
return new File("../tests/src/org/aspectj/systemtest/ajc150/ataspectj/atajc150.xml"); | |||
return new File("../tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml"); | |||
} | |||
public void testSimpleBefore() { | |||
runTest("SimpleBefore"); | |||
} | |||
public void testSimpleAfter() { | |||
runTest("SimpleAfter"); | |||
} | |||
public void testSingletonAspectBinding() { | |||
runTest("singletonAspectBindings"); | |||
} | |||
public void testCflow() { | |||
runTest("CflowTest"); | |||
} | |||
public void testPointcutReference() { | |||
runTest("PointcutReferenceTest"); | |||
} | |||
public void testXXJoinPoint() { | |||
runTest("XXJoinPointTest"); | |||
} | |||
public void testPrecedence() { | |||
runTest("PrecedenceTest"); | |||
} | |||
// FIXME alex restore when AJC can compile it... #86452 | |||
// public void testAfterX() { | |||
// runTest("AfterXTest"); | |||
// } | |||
//FIXME AV uncomment when IfPointcutTest.TestAspect can be compiled ie if() pcd can be parsed. | |||
// right now the aspect is commented out. | |||
// public void testIfPointcut() { | |||
// runTest("IfPointcutTest"); | |||
// } | |||
// FIXME alex java.lang.VerifyError: (class: ataspectj/BindingTest, method: dup_aroundBody5$advice signature: (ILorg/aspectj/lang/JoinPoint;Lataspectj/BindingTest$TestAspect_1;ILorg/aspectj/lang/ProceedingJoinPoint;)Ljava/lang/Object;) Register 0 contains wrong type | |||
// public void testBindings() { | |||
// runTest("BindingTest"); | |||
// } | |||
} |
@@ -0,0 +1,140 @@ | |||
<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"[]> | |||
<suite> | |||
<!-- @AspectJ v1.5.0 Tests --> | |||
<!-- ================================================================= --> | |||
<!-- Adrian's tests for generation of @AspectJ annotations from ajc --> | |||
<!-- ================================================================= --> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for simple aspect"> | |||
<compile files="SimpleAspect.aj" options="-1.5"/> | |||
<run class="SimpleAspect"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for simple annotated aspect"> | |||
<compile files="SimpleAnnotatedAspect.aj" options="-1.5"/> | |||
<run class="SimpleAnnotatedAspect"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for simple aspect pre 1.5"> | |||
<compile files="Simple14Aspect.aj" options="-1.4"/> | |||
<compile files="Simple14AspectTest.java" options="-1.5"/> | |||
<run class="Simple14AspectTest"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for privileged aspect"> | |||
<compile files="PrivilegedAspect.aj" options="-1.5"/> | |||
<run class="PrivilegedAspect"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for perthis aspect"> | |||
<compile files="PerThisAspect.aj" options="-1.5"/> | |||
<run class="PerThisAspect"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pertarget aspect"> | |||
<compile files="PerTargetAspect.aj" options="-1.5"/> | |||
<run class="PerTargetAspect"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for percflow aspect"> | |||
<compile files="PerCflowAspect.aj" options="-1.5"/> | |||
<run class="PerCflowAspect"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for percflowbelow aspect"> | |||
<compile files="PerCflowbelowAspect.aj" options="-1.5"/> | |||
<run class="PerCflowbelowAspect"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pertypewithin aspect"> | |||
<compile files="PerTypeWithinAspect.aj" options="-1.5"/> | |||
<run class="PerTypeWithinAspect"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for inner aspect of aspect"> | |||
<compile files="InnerAspectAspect.aj" options="-1.5"/> | |||
<run class="InnerAspectAspect"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for inner aspect of class"> | |||
<compile files="InnerAspectClass.aj" options="-1.5"/> | |||
<run class="InnerAspectClass"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for advice declarations"> | |||
<compile files="BasicAdvice.aj" options="-1.5"/> | |||
<run class="BasicAdvice"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for simple pointcut"> | |||
<compile files="SimplePointcut.aj" options="-1.5"/> | |||
<run class="SimplePointcut"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pointcut modifiers"> | |||
<compile files="PointcutModifiers.aj" options="-1.5"/> | |||
<run class="PointcutModifiers"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pointcut params"> | |||
<compile files="PointcutsWithParams.aj" options="-1.5"/> | |||
<run class="PointcutsWithParams"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="annotation gen for pointcut refs"> | |||
<compile files="ReferencePointcuts.aj" options="-1.5"/> | |||
<run class="ReferencePointcuts"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="before ann with non-void return"> | |||
<compile files="BeforeWithBadReturn.java" options="-1.5"> | |||
<message kind="error" line="7" text="This advice must return void"/> | |||
<message kind="error" line="7" text="This method must return a result of type String"/> | |||
</compile> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="two anns on same element"> | |||
<compile files="TwoForThePriceOfOne.java" options="-1.5"> | |||
<message kind="error" line="7" text="The annotation @Pointcut is disallowed for this location"/> | |||
</compile> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="bad pcut in after advice"> | |||
<compile files="AfterReturningWithBadPCut.java" options="-1.5"> | |||
<message kind="error" line="6" text="Syntax error on token "excution(* *.*(..))""/> | |||
</compile> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="bad parameter binding in advice"> | |||
<compile files="BadParameterBinding.java" options="-1.5"> | |||
<message kind="warning" line="11" text="no match for this type name: bpb"/> | |||
<message kind="warning" line="15" text="no match for this type name: TheUnknownType"/> | |||
</compile> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="simple pointcut no params"> | |||
<compile files="APointcut.java" options="-1.5"/> | |||
<run class="APointcut"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="pointcut medley"> | |||
<compile files="PointcutAssortment.java" options="-1.5"> | |||
<message kind="error" line="9" text="Methods annotated with @Pointcut must return void"/> | |||
<message kind="error" line="9" text="This method must return a result of type String"/> | |||
<message kind="error" line="15" text="Pointcuts should have an empty method body"/> | |||
<message kind="error" line="28" text="Duplicate annotation @Pointcut"/> | |||
<message kind="error" line="29" text="Duplicate annotation @Pointcut"/> | |||
<message kind="error" line="11" text="can't find referenced pointcut foo"/> | |||
<message kind="warning" line="32" text="no match for this type name: foo [Xlint:invalidAbsoluteTypeName]"/> | |||
</compile> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj/annotationGen" title="advice in a class"> | |||
<compile files="AdviceInAClass.java" options="-1.5"> | |||
<message kind="error" line="6" text="Advice must be declared inside an aspect type"/> | |||
</compile> | |||
</ajc-test> | |||
</suite> |
@@ -4,20 +4,20 @@ | |||
<suite> | |||
<comment>this one is ok - too simple - could be removed..</comment> | |||
<ajc-test dir="java5/ataspectj" | |||
pr="" title="@Aspect class extending @Aspect class"> | |||
<compile files="ataspectj/misuse/Test005.java" options="-1.5 -Xdev:NoAtAspectJProcessing"> | |||
</compile> | |||
</ajc-test> | |||
<comment>just a warning - might be skept if further optimized in Aj5Attributes..</comment> | |||
<ajc-test dir="java5/ataspectj" | |||
pr="" title="class with @Before extending @Aspect class"> | |||
<compile files="ataspectj/misuse/Test006.java" options="-1.5 -Xdev:NoAtAspectJProcessing"> | |||
<message kind="warning" line="11" text="Found @AspectJ annotations in a non @Aspect type 'ataspectj.misuse.Test006B'"/> | |||
</compile> | |||
</ajc-test> | |||
<!-- <comment>this one is ok - too simple - could be removed..</comment>--> | |||
<!-- <ajc-test dir="java5/ataspectj"--> | |||
<!-- pr="" title="@Aspect class extending @Aspect class">--> | |||
<!-- <compile files="ataspectj/misuse/Test005.java" options="-1.5 -Xdev:NoAtAspectJProcessing">--> | |||
<!-- </compile>--> | |||
<!-- </ajc-test>--> | |||
<!----> | |||
<!-- <comment>just a warning - might be skept if further optimized in Aj5Attributes..</comment>--> | |||
<!-- <ajc-test dir="java5/ataspectj"--> | |||
<!-- pr="" title="class with @Before extending @Aspect class">--> | |||
<!-- <compile files="ataspectj/misuse/Test006.java" options="-1.5 -Xdev:NoAtAspectJProcessing">--> | |||
<!-- <message kind="warning" line="11" text="Found @AspectJ annotations in a non @Aspect type 'ataspectj.misuse.Test006B'"/>--> | |||
<!-- </compile>--> | |||
<!-- </ajc-test>--> | |||
<comment>a warning. We ignore the pointcut (TBD) - line is enclosing class (TBD Andy do better ?)</comment> | |||
<ajc-test dir="java5/ataspectj" | |||
@@ -35,46 +35,46 @@ | |||
<!-- </compile>--> | |||
<!-- </ajc-test>--> | |||
<comment>line is enclosing class - TBD</comment> | |||
<ajc-test dir="java5/ataspectj" | |||
pr="" title="@Pointcut with garbage string"> | |||
<compile files="ataspectj/misuse/Test014.java" options="-1.5 -Xdev:NoAtAspectJProcessing"> | |||
<message kind="error" line="7" text="Cannot parse @Pointcut 'call%dddd"/> | |||
</compile> | |||
</ajc-test> | |||
<comment>line is enclosing class - TBD</comment> | |||
<ajc-test dir="java5/ataspectj" | |||
pr="" title="@Pointcut with throws clause"> | |||
<compile files="ataspectj/misuse/Test016.java" options="-1.5 -Xdev:NoAtAspectJProcessing"> | |||
<message kind="warning" line="7" text="Found @Pointcut on a method throwing exception 'someCall()V'"/> | |||
</compile> | |||
</ajc-test> | |||
<comment>very dirty hack - can't get this location to work properly so added match all error..</comment> | |||
<ajc-test dir="java5/ataspectj" | |||
pr="" title="@AfterReturning with wrong number of args"> | |||
<compile files="ataspectj/misuse/Test019.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore"> | |||
<message kind="error" line="1" text="the parameter x is not bound"/> | |||
<message kind="error"/> | |||
</compile> | |||
</ajc-test> | |||
<comment>line number is enclosing type</comment> | |||
<ajc-test dir="java5/ataspectj" | |||
pr="" title="@Before on non-public method"> | |||
<compile files="ataspectj/misuse/Test020.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore"> | |||
<message kind="error" line="7" text="Found @AspectJ annotation on a non public advice 'someCall()V'"/> | |||
</compile> | |||
</ajc-test> | |||
<comment>line number is enclosing type</comment> | |||
<ajc-test dir="java5/ataspectj" | |||
pr="" title="@Before on method not returning void"> | |||
<compile files="ataspectj/misuse/Test021.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore"> | |||
<message kind="error" line="7" text="Found @AspectJ annotation on a non around advice not returning void 'someCall()I'"/> | |||
</compile> | |||
</ajc-test> | |||
<!-- <comment>line is enclosing class - TBD</comment>--> | |||
<!-- <ajc-test dir="java5/ataspectj"--> | |||
<!-- pr="" title="@Pointcut with garbage string">--> | |||
<!-- <compile files="ataspectj/misuse/Test014.java" options="-1.5 -Xdev:NoAtAspectJProcessing">--> | |||
<!-- <message kind="error" line="7" text="Cannot parse @Pointcut 'call%dddd"/>--> | |||
<!-- </compile>--> | |||
<!-- </ajc-test>--> | |||
<!----> | |||
<!-- <comment>line is enclosing class - TBD</comment>--> | |||
<!-- <ajc-test dir="java5/ataspectj"--> | |||
<!-- pr="" title="@Pointcut with throws clause">--> | |||
<!-- <compile files="ataspectj/misuse/Test016.java" options="-1.5 -Xdev:NoAtAspectJProcessing">--> | |||
<!-- <message kind="warning" line="7" text="Found @Pointcut on a method throwing exception 'someCall()V'"/>--> | |||
<!-- </compile>--> | |||
<!-- </ajc-test>--> | |||
<!----> | |||
<!-- <comment>very dirty hack - can't get this location to work properly so added match all error..</comment>--> | |||
<!-- <ajc-test dir="java5/ataspectj"--> | |||
<!-- pr="" title="@AfterReturning with wrong number of args">--> | |||
<!-- <compile files="ataspectj/misuse/Test019.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore">--> | |||
<!-- <message kind="error" line="1" text="the parameter x is not bound"/>--> | |||
<!-- <message kind="error"/>--> | |||
<!-- </compile>--> | |||
<!-- </ajc-test>--> | |||
<!----> | |||
<!-- <comment>line number is enclosing type</comment>--> | |||
<!-- <ajc-test dir="java5/ataspectj"--> | |||
<!-- pr="" title="@Before on non-public method">--> | |||
<!-- <compile files="ataspectj/misuse/Test020.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore">--> | |||
<!-- <message kind="error" line="7" text="Found @AspectJ annotation on a non public advice 'someCall()V'"/>--> | |||
<!-- </compile>--> | |||
<!-- </ajc-test>--> | |||
<!----> | |||
<!-- <comment>line number is enclosing type</comment>--> | |||
<!-- <ajc-test dir="java5/ataspectj"--> | |||
<!-- pr="" title="@Before on method not returning void">--> | |||
<!-- <compile files="ataspectj/misuse/Test021.java" options="-1.5 -Xdev:NoAtAspectJProcessing -Xlint:ignore">--> | |||
<!-- <message kind="error" line="7" text="Found @AspectJ annotation on a non around advice not returning void 'someCall()I'"/>--> | |||
<!-- </compile>--> | |||
<!-- </ajc-test>--> | |||
<!-- | |||
ALEX: todo |
@@ -0,0 +1,82 @@ | |||
<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"[]> | |||
<suite> | |||
<ajc-test dir="java5/ataspectj" title="SimpleBefore"> | |||
<compile files="SimpleBefore.java" options="-1.5 -showWeaveInfo -XnoInline"> | |||
<message kind="weave" text="(SimpleBefore.java:23) advised by before advice from 'SimpleBefore$X' (SimpleBefore.java:1)"/> | |||
</compile> | |||
<run class="SimpleBefore"/> | |||
<compile files="SimpleBefore.java" options="-1.5 -showWeaveInfo -XnoInline -Xdev:NoAtAspectJProcessing"> | |||
<message kind="weave" text="(SimpleBefore.java:23) advised by before advice from 'SimpleBefore$X' (SimpleBefore.java:1)"/> | |||
</compile> | |||
<run class="SimpleBefore"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj" title="SimpleAfter"> | |||
<compile files="SimpleAfter.java" options="-1.5 -showWeaveInfo -XnoInline"> | |||
<message kind="weave" text="(SimpleAfter.java:13) advised by after advice from 'SimpleAfter$X'"/> | |||
</compile> | |||
<run class="SimpleAfter"/> | |||
<compile files="SimpleAfter.java" options="-1.5 -showWeaveInfo -XnoInline -Xdev:NoAtAspectJProcessing"> | |||
<message kind="weave" text="(SimpleAfter.java:13) advised by after advice from 'SimpleAfter$X'"/> | |||
</compile> | |||
<run class="SimpleAfter"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj" title="singletonAspectBindings"> | |||
<compile files="ataspectj/SingletonAspectBindingsTest.java,ataspectj/TestHelper.java" options="-1.5 -XnoInline"/> | |||
<run class="ataspectj.SingletonAspectBindingsTest"/> | |||
<compile files="ataspectj/SingletonAspectBindingsTest.java,ataspectj/TestHelper.java" options="-1.5 -XnoInline -Xdev:NoAtAspectJProcessing"/> | |||
<run class="ataspectj.SingletonAspectBindingsTest"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj" title="CflowTest"> | |||
<compile files="ataspectj/CflowTest.java,ataspectj/TestHelper.java" options="-1.5"/> | |||
<run class="ataspectj.CflowTest"/> | |||
<compile files="ataspectj/CflowTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing"/> | |||
<run class="ataspectj.CflowTest"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj" title="PointcutReferenceTest"> | |||
<compile files="ataspectj/PointcutReferenceTest.java,ataspectj/TestHelper.java" options="-1.5"/> | |||
<run class="ataspectj.PointcutReferenceTest"/> | |||
<compile files="ataspectj/PointcutReferenceTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing"/> | |||
<run class="ataspectj.PointcutReferenceTest"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj" title="XXJoinPointTest"> | |||
<compile files="ataspectj/XXJoinPointTest.java,ataspectj/TestHelper.java" options="-1.5"/> | |||
<run class="ataspectj.XXJoinPointTest"/> | |||
<compile files="ataspectj/XXJoinPointTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing"/> | |||
<run class="ataspectj.XXJoinPointTest"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj" title="PrecedenceTest"> | |||
<compile files="ataspectj/PrecedenceTest.java,ataspectj/TestHelper.java" options="-1.5"/> | |||
<run class="ataspectj.PrecedenceTest"/> | |||
<compile files="ataspectj/PrecedenceTest.java,ataspectj/TestHelper.java" options="-1.5 -Xdev:NoAtAspectJProcessing"/> | |||
<run class="ataspectj.PrecedenceTest"/> | |||
</ajc-test> | |||
<!-- <comment>FIXME AV when JDT of M6 is in</comment>--> | |||
<!-- <ajc-test dir="java5/ataspectj" title="AfterXTest">--> | |||
<!-- <compile files="ataspectj/AfterXTest.java,ataspectj/TestHelper.java" options="-1.5"/>--> | |||
<!-- <run class="ataspectj.AfterXTest"/>--> | |||
<!-- </ajc-test>--> | |||
<!-- <comment>FIXME AV when we impl if support in pointcut parser and weaver</comment>--> | |||
<!-- <ajc-test dir="java5/ataspectj" title="IfPointcutTest">--> | |||
<!-- <compile files="ataspectj/IfPointcutTest.java,ataspectj/TestHelper.java" options="-1.5"/>--> | |||
<!-- <run class="ataspectj.IfPointcutTest"/>--> | |||
<!-- </ajc-test>--> | |||
<ajc-test dir="java5/ataspectj" title="BindingTest"> | |||
<compile files="ataspectj/BindingTest.java,ataspectj/TestHelper.java" options="-1.5"/> | |||
<run class="ataspectj.BindingTest"/> | |||
</ajc-test> | |||
<ajc-test dir="java5/ataspectj" title="BindingTest no inline"> | |||
<compile files="ataspectj/BindingTest.java,ataspectj/TestHelper.java" options="-1.5 -XnoInline"/> | |||
<run class="ataspectj.BindingTest"/> | |||
</ajc-test> | |||
</suite> |
@@ -1939,7 +1939,47 @@ public class BcelShadow extends Shadow { | |||
weaveAroundClosure(munger, hasDynamicTest); | |||
return; | |||
} | |||
// specific test for @AJ proceedInInners | |||
if (munger.getConcreteAspect().isAnnotationStyleAspect()) { | |||
//FIXME | |||
// if we can't find one proceed() | |||
// we suspect that the call is happening in an inner class | |||
// so we don't inline it. | |||
// Note: for code style, this is done at Aspect compilation time. | |||
// Limitation: if there is two calls and one is done in an inner class, inlining will happen | |||
// since we will see the non proceed in inner one as if it was the sole one. | |||
// The one made in the inner class will never be madeXXX. Should be documented. | |||
boolean canSeeProceedPassedToOther = false; | |||
InstructionHandle curr = adviceMethod.getBody().getStart(); | |||
InstructionHandle end = adviceMethod.getBody().getEnd(); | |||
ConstantPoolGen cpg = adviceMethod.getEnclosingClass().getConstantPoolGen(); | |||
while (curr != end) { | |||
InstructionHandle next = curr.getNext(); | |||
Instruction inst = curr.getInstruction(); | |||
/*if ((inst instanceof INVOKEINTERFACE) | |||
&& "proceed".equals(((INVOKEINTERFACE) inst).getMethodName(cpg))) { | |||
canSeeProceed = true; | |||
//continue since we may have a proceed in inner or pjp as arg | |||
} else*/ if ((inst instanceof InvokeInstruction) | |||
&& ((InvokeInstruction)inst).getSignature(cpg).indexOf("Lorg/aspectj/lang/ProceedingJoinPoint;") > 0) { | |||
// we may want to refine to exclude stuff returning jp ? | |||
// does code style skip inline if i write dump(thisJoinPoint) ? | |||
canSeeProceedPassedToOther = true;// we see one pjp passed around - dangerous | |||
break; | |||
} | |||
curr = next; | |||
} | |||
if (canSeeProceedPassedToOther) { | |||
// remember this decision to avoid re-analysis | |||
adviceMethod.setCanInline(false); | |||
weaveAroundClosure(munger, hasDynamicTest); | |||
return; | |||
} | |||
} | |||
// We can't inline around methods if they have around advice on them, this | |||
// is because the weaving will extract the body and hence the proceed call. | |||
//??? should consider optimizations to recognize simple cases that don't require body extraction | |||
@@ -1954,8 +1994,9 @@ public class BcelShadow extends Shadow { | |||
NameMangler.aroundCallbackMethodName( | |||
getSignature(), | |||
getEnclosingClass()), | |||
Modifier.PRIVATE, | |||
munger); | |||
Modifier.PRIVATE, | |||
munger | |||
); | |||
// now extract the advice into its own method | |||
@@ -2164,18 +2205,22 @@ public class BcelShadow extends Shadow { | |||
Instruction inst = curr.getInstruction(); | |||
if ((inst instanceof INVOKEINTERFACE) | |||
&& "proceed".equals(((INVOKEINTERFACE) inst).getMethodName(cpg))) { | |||
//TODO proceed(...varargs) will need some stuff there | |||
InstructionList insteadProceedIl = | |||
getRedoneProceedCallForAnnotationStyle( | |||
final boolean isProceedWithArgs; | |||
if (((INVOKEINTERFACE) inst).getArgumentTypes(cpg).length == 1) { | |||
// proceed with args as a boxed Object[] | |||
isProceedWithArgs = true; | |||
} else { | |||
isProceedWithArgs = false; | |||
} | |||
InstructionList insteadProceedIl = getRedoneProceedCallForAnnotationStyle( | |||
fact, | |||
extractedMethod, | |||
munger, | |||
localAdviceMethod, | |||
proceedVarList); | |||
//TODO optimize, a POP is added somewhere, what for non void ? | |||
localAdviceMethod.getBody().append( | |||
curr, insteadProceedIl); | |||
proceedVarList, | |||
isProceedWithArgs | |||
); | |||
localAdviceMethod.getBody().append(curr, insteadProceedIl); | |||
Utility.deleteInstruction(curr, localAdviceMethod); | |||
} | |||
curr = next; | |||
@@ -2242,6 +2287,7 @@ public class BcelShadow extends Shadow { | |||
* @param munger | |||
* @param localAdviceMethod | |||
* @param argVarList | |||
* @param isProceedWithArgs | |||
* @return | |||
*/ | |||
private InstructionList getRedoneProceedCallForAnnotationStyle( | |||
@@ -2249,57 +2295,129 @@ public class BcelShadow extends Shadow { | |||
LazyMethodGen callbackMethod, | |||
BcelAdvice munger, | |||
LazyMethodGen localAdviceMethod, | |||
List argVarList) | |||
List argVarList, | |||
boolean isProceedWithArgs) | |||
{ | |||
//if (true) return new InstructionList(); | |||
// Notes: | |||
// proceedingjp is on stack (since user was calling pjp.proceed(...) | |||
// the boxed args to proceed() are on stack as well (Object[]) unless | |||
// the call is to pjp.proceed(<noarg>) | |||
//TODO I think we just don't care about the proceed map | |||
// since that one must be the exact same of the advice sig. | |||
// perhaps with custom jp ? | |||
// new Object[]{new Integer(argAdvice1-1)};// arg of proceed | |||
// call to proceed(..) is NOT made | |||
// instead we do | |||
// itar callback args i | |||
// get from array i, convert it to the callback arg i | |||
// if ask for JP, push the one we got on the stack | |||
// invoke callback, create conversion back to Object/Integer | |||
// we have on stack all the arguments for the ADVICE call. | |||
// we have in frame somewhere all the arguments for the non-advice call. | |||
BcelVar[] adviceVars = munger.getExposedStateAsBcelVars(); | |||
IntMap proceedMap = makeProceedArgumentMap(adviceVars); | |||
// rest of method -- (hence all those conversions) | |||
// intValue() from original code | |||
// int res = .. from original code | |||
//System.out.println(proceedMap + " for " + this); | |||
//System.out.println(argVarList); | |||
ResolvedTypeX[] proceedParamTypes = | |||
world.resolve(munger.getSignature().getParameterTypes()); | |||
//System.out.println(proceedParamTypes); | |||
//Note: we just don't care about the proceed map etc | |||
InstructionList ret = new InstructionList(); | |||
ret.append(new POP());//the joinpoint instance is there | |||
for (int i=0, len=callbackMethod.getArgumentTypes().length; i < len; i++) { | |||
Type stateType = callbackMethod.getArgumentTypes()[i]; | |||
ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world); | |||
if (proceedMap.hasKey(i)) { | |||
ret.append(new ALOAD(i)); | |||
//throw new RuntimeException("unimplemented"); | |||
//proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX); | |||
} else { | |||
//FIXME Alex: odd code there | |||
//((BcelVar) argVarList.get(i)).appendLoad(ret, fact); | |||
//ret.append(new ALOAD(i)); | |||
// store the Object[] array on stack if proceed with args | |||
if (isProceedWithArgs) { | |||
Type objectArrayType = Type.getType("[Ljava/lang/Object;"); | |||
int localProceedArgArray = localAdviceMethod.allocateLocal(objectArrayType); | |||
ret.append(InstructionFactory.createStore(objectArrayType, localProceedArgArray)); | |||
Type proceedingJpType = Type.getType("Lorg/aspectj/lang/ProceedingJoinPoint;"); | |||
int localJp = localAdviceMethod.allocateLocal(proceedingJpType); | |||
ret.append(InstructionFactory.createStore(proceedingJpType, localJp)); | |||
// push on stack each element of the object array | |||
// that is assumed to be consistent with the callback argument (ie munger args) | |||
// TODO do we want to try catch ClassCast and AOOBE exception ? | |||
// special logic when withincode is static or not | |||
int startIndex = 0; | |||
if (thisVar != null) { | |||
startIndex = 1; | |||
//TODO this logic is actually depending on target as well - test me | |||
ret.append(new ALOAD(0));//thisVar | |||
} | |||
for (int i = startIndex, len=callbackMethod.getArgumentTypes().length; i < len; i++) { | |||
Type stateType = callbackMethod.getArgumentTypes()[i]; | |||
ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world); | |||
if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) { | |||
ret.append(new ALOAD(i)); | |||
ret.append(new ALOAD(localJp));// from localAdvice signature | |||
} else { | |||
ret.append(new ALOAD(i)); | |||
ret.append(InstructionFactory.createLoad(objectArrayType, localProceedArgArray)); | |||
ret.append(Utility.createConstant(fact, i-startIndex)); | |||
ret.append(InstructionFactory.createArrayLoad(Type.OBJECT)); | |||
ret.append(Utility.createConversion( | |||
fact, | |||
Type.OBJECT, | |||
stateType | |||
)); | |||
} | |||
} | |||
} else { | |||
Type proceedingJpType = Type.getType("Lorg/aspectj/lang/ProceedingJoinPoint;"); | |||
int localJp = localAdviceMethod.allocateLocal(proceedingJpType); | |||
ret.append(InstructionFactory.createStore(proceedingJpType, localJp)); | |||
for (int i = 0, len=callbackMethod.getArgumentTypes().length; i < len; i++) { | |||
Type stateType = callbackMethod.getArgumentTypes()[i]; | |||
ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world); | |||
if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) { | |||
ret.append(new ALOAD(localJp));// from localAdvice signature | |||
} else { | |||
ret.append(InstructionFactory.createLoad(stateType, i)); | |||
} | |||
} | |||
} | |||
// do the callback invoke | |||
ret.append(Utility.createInvoke(fact, callbackMethod)); | |||
ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(), | |||
BcelWorld.makeBcelType(munger.getSignature().getReturnType()))); | |||
ret.append(new ACONST_NULL());//will be POPed //FIXME Alex: if so clean up | |||
if (true) return ret; | |||
// box it again. Handles cases where around advice does return something else than Object | |||
if (!TypeX.OBJECT.equals(munger.getSignature().getReturnType())) { | |||
ret.append(Utility.createConversion( | |||
fact, | |||
callbackMethod.getReturnType(), | |||
Type.OBJECT | |||
)); | |||
} | |||
ret.append(Utility.createConversion( | |||
fact, | |||
callbackMethod.getReturnType(), | |||
BcelWorld.makeBcelType(munger.getSignature().getReturnType()) | |||
)); | |||
return ret; | |||
// | |||
// | |||
// | |||
// if (proceedMap.hasKey(i)) { | |||
// ret.append(new ALOAD(i)); | |||
// //throw new RuntimeException("unimplemented"); | |||
// //proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX); | |||
// } else { | |||
// //((BcelVar) argVarList.get(i)).appendLoad(ret, fact); | |||
// //ret.append(new ALOAD(i)); | |||
// if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) { | |||
// ret.append(new ALOAD(i)); | |||
// } else { | |||
// ret.append(new ALOAD(i)); | |||
// } | |||
// } | |||
// } | |||
// | |||
// ret.append(Utility.createInvoke(fact, callbackMethod)); | |||
// ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(), | |||
// BcelWorld.makeBcelType(munger.getSignature().getReturnType()))); | |||
// | |||
// //ret.append(new ACONST_NULL());//will be POPed | |||
// if (true) return ret; | |||
// | |||
// | |||
// | |||
// // we have on stack all the arguments for the ADVICE call. | |||
// // we have in frame somewhere all the arguments for the non-advice call. | |||
// | |||
@@ -2311,36 +2429,36 @@ public class BcelShadow extends Shadow { | |||
// | |||
// ResolvedTypeX[] proceedParamTypes = | |||
// world.resolve(munger.getSignature().getParameterTypes()); | |||
// remove this*JoinPoint* as arguments to proceed | |||
if (munger.getBaseParameterCount()+1 < proceedParamTypes.length) { | |||
int len = munger.getBaseParameterCount()+1; | |||
ResolvedTypeX[] newTypes = new ResolvedTypeX[len]; | |||
System.arraycopy(proceedParamTypes, 0, newTypes, 0, len); | |||
proceedParamTypes = newTypes; | |||
} | |||
//System.out.println("stateTypes: " + Arrays.asList(stateTypes)); | |||
BcelVar[] proceedVars = | |||
Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, localAdviceMethod); | |||
Type[] stateTypes = callbackMethod.getArgumentTypes(); | |||
// System.out.println("stateTypes: " + Arrays.asList(stateTypes)); | |||
for (int i=0, len=stateTypes.length; i < len; i++) { | |||
Type stateType = stateTypes[i]; | |||
ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world); | |||
if (proceedMap.hasKey(i)) { | |||
//throw new RuntimeException("unimplemented"); | |||
proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX); | |||
} else { | |||
((BcelVar) argVarList.get(i)).appendLoad(ret, fact); | |||
} | |||
} | |||
ret.append(Utility.createInvoke(fact, callbackMethod)); | |||
ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(), | |||
BcelWorld.makeBcelType(munger.getSignature().getReturnType()))); | |||
return ret; | |||
// // remove this*JoinPoint* as arguments to proceed | |||
// if (munger.getBaseParameterCount()+1 < proceedParamTypes.length) { | |||
// int len = munger.getBaseParameterCount()+1; | |||
// ResolvedTypeX[] newTypes = new ResolvedTypeX[len]; | |||
// System.arraycopy(proceedParamTypes, 0, newTypes, 0, len); | |||
// proceedParamTypes = newTypes; | |||
// } | |||
// | |||
// //System.out.println("stateTypes: " + Arrays.asList(stateTypes)); | |||
// BcelVar[] proceedVars = | |||
// Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, localAdviceMethod); | |||
// | |||
// Type[] stateTypes = callbackMethod.getArgumentTypes(); | |||
//// System.out.println("stateTypes: " + Arrays.asList(stateTypes)); | |||
// | |||
// for (int i=0, len=stateTypes.length; i < len; i++) { | |||
// Type stateType = stateTypes[i]; | |||
// ResolvedTypeX stateTypeX = BcelWorld.fromBcel(stateType).resolve(world); | |||
// if (proceedMap.hasKey(i)) { | |||
// //throw new RuntimeException("unimplemented"); | |||
// proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX); | |||
// } else { | |||
// ((BcelVar) argVarList.get(i)).appendLoad(ret, fact); | |||
// } | |||
// } | |||
// | |||
// ret.append(Utility.createInvoke(fact, callbackMethod)); | |||
// ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(), | |||
// BcelWorld.makeBcelType(munger.getSignature().getReturnType()))); | |||
// return ret; | |||
} | |||
public void weaveAroundClosure( |