diff options
8 files changed, 592 insertions, 176 deletions
diff --git a/testing/newsrc/org/aspectj/testing/AutowiredXMLBasedAjcTestCase.java b/testing/newsrc/org/aspectj/testing/AutowiredXMLBasedAjcTestCase.java index f77e289d7..02adcd515 100644 --- a/testing/newsrc/org/aspectj/testing/AutowiredXMLBasedAjcTestCase.java +++ b/testing/newsrc/org/aspectj/testing/AutowiredXMLBasedAjcTestCase.java @@ -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); + } + + } diff --git a/tests/java5/ataspectj/ataspectj/BindingTest.java b/tests/java5/ataspectj/ataspectj/BindingTest.java index e88bead39..c4114f020 100644 --- a/tests/java5/ataspectj/ataspectj/BindingTest.java +++ b/tests/java5/ataspectj/ataspectj/BindingTest.java @@ -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(); + } + } + } diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjAnnotationGenTests.java b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjAnnotationGenTests.java index 0a2edb2ca..9004bf9bf 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjAnnotationGenTests.java +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjAnnotationGenTests.java @@ -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() { diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java index f1255b6aa..0ff079345 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjSyntaxTests.java @@ -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"); -// } }
\ No newline at end of file diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml new file mode 100644 index 000000000..c975b0d5e --- /dev/null +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml @@ -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>
\ No newline at end of file diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml index 1717bf9e0..d56357c80 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/misuse.xml @@ -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 diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml new file mode 100644 index 000000000..417d0be48 --- /dev/null +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/syntax.xml @@ -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>
\ No newline at end of file diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java index 17f766f28..0442d8c68 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java @@ -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( |