}
</programlisting>
+ <para>
+ Any occurence of <literal>proceed(..)</literal> within the body of
+ around advice is treated as the special proceed form (even if the
+ aspect defines a method named <literal>proceed</literal>) unless a
+ target other than the aspect instance is specified as the recipient of
+ the call.
+ For example, in the following program the first
+ call to proceed will be treated as a method call to
+ the <literal>ICanProceed</literal> instance, whereas the second call to
+ proceed is treated as the special proceed form.
+ </para>
+
+<programlisting>
+ aspect A {
+ Object around(ICanProceed canProceed) : execution(* *(..)) <![CDATA[&&]]> this(canProceed) {
+ canProceed.proceed(); // a method call
+ return proceed(canProceed); // the special proceed form
+ }
+
+ private Object proceed(ICanProceed canProceed) {
+ // this method cannot be called from inside the body of around advice in
+ // the aspect
+ }
+ }
+</programlisting>
+
<para>
In all kinds of advice, the parameters of the advice behave exactly like
method parameters. In particular, assigning to any parameter affects
/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
+ * 2004 contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Common Public License v1.0
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
- * PARC initial implementation
+ * PARC initial implementation
+ * IBM ongoing maintenance
* ******************************************************************/
/**
* Used to represent any method call to a method named <code>proceed</code>. During
* <code>resolvedType</code> it will be determined if this is actually in the body
- * of an <code>around</code> advice and if not this will be treated like any other
+ * of an <code>around</code> advice and has no receiver (must be a bare proceed call,
+ * see pr 53981), and if not this will be treated like any other
* MessageSend.
*
* @author Jim Hugunin
private AdviceDeclaration findEnclosingAround(Scope scope) {
if (scope == null) return null;
-
+
if (scope instanceof MethodScope) {
MethodScope methodScope = (MethodScope)scope;
ReferenceContext context = methodScope.referenceContext;
if (context instanceof AdviceDeclaration) {
AdviceDeclaration adviceDecl = (AdviceDeclaration)context;
if (adviceDecl.kind == AdviceKind.Around) {
+ // pr 53981 only match "bare" calls to proceed
+ if((receiver != null) && (!receiver.isThis())) { return null; }
adviceDecl.proceedCalls.add(this);
return adviceDecl;
} else {
--- /dev/null
+import org.aspectj.testing.Tester;
+
+public class Proceeding1 {
+ public static void main(String[] args) {
+ Tester.checkAllEvents();
+ }
+ static aspect A {
+ interface IProceed {
+ void proceeds(Runnable next);
+ }
+ IProceed decorator = new IProceed() {
+ public void proceeds(Runnable next) {
+ Tester.event("IProceed.proceed()");
+ next.run();
+ }
+ };
+ void around() : execution(void main(String[])) {
+ Tester.expectEvent("IProceed.proceed()");
+ decorator.proceeds(new Runnable() {
+ public void run() {
+ proceed();
+ }
+ });
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+import org.aspectj.testing.Tester;
+
+public class Proceeding2 {
+ public static void main(String[] args) {
+ Tester.checkFailed("Proceed with a receiver should be treated as a method call, not the special form");
+ }
+ static aspect A {
+ void around() : execution(void main(String[])) {
+ Proceeding2.proceed(null); // BUG: treated as proceed(Object);
+ }
+ }
+ static void proceed(Object o) {}
+}
\ No newline at end of file
--- /dev/null
+import org.aspectj.testing.Tester;
+
+public class Proceeding3 {
+ public static void main(String[] args) {
+ }
+ static aspect A {
+ void around() : execution(void main(String[])) {
+ proceed(); // special form or Proceeding.proceed()?
+ }
+ }
+ void proceed() {
+ Tester.checkFailed("A bare call to proceed inside around advice should never refer to a method");
+ }
+}
\ No newline at end of file
// public void test022_BcelFailureWithVeryLargeClasses_Binary() {
// runTest("Weaver fails in BCEL for large classes (binary)");
// }
+
+ public void test023_proceedInAround1() {
+ runTest("proceed used as method name in around advice (1)");
+ }
+
+ public void test024_proceedInAround2() {
+ runTest("proceed used as method name in around advice (2)");
+ }
+
+ public void test025_proceedInAround3() {
+ runTest("proceed used as method name in around advice (3)");
+ }
}
<message kind="error" line="0" text="constant pool too big"></message>
</compile>
</ajc-test>
--->
\ No newline at end of file
+-->
+
+ <ajc-test dir="bugs/pr53981" pr="538981"
+ title="proceed used as method name in around advice (1)">
+ <compile files="Proceeding1.aj"/>
+ <run class="Proceeding1"/>
+ </ajc-test>
+
+ <ajc-test dir="bugs/pr53981" pr="538981"
+ title="proceed used as method name in around advice (2)">
+ <compile files="Proceeding2.aj"/>
+ <run class="Proceeding2"/>
+ </ajc-test>
+
+ <ajc-test dir="bugs/pr53981" pr="538981"
+ title="proceed used as method name in around advice (3)">
+ <compile files="Proceeding3.aj"/>
+ <run class="Proceeding3"/>
+ </ajc-test>
\ No newline at end of file