Community
Participate
Working Groups
Using a method named proceed(..) in around advice confuses the compiler (in at least the 2-3 ways shown below). True of the current tree (untested in 1.1.1). Workaround for now is to rename the method. ---- first problem: NPE in compiler java.lang.NullPointerException at org.aspectj.ajdt.internal.compiler.ast.MakeDeclsPublicVisitor.endVisit(MakeDeclsPublicVisitor.java:44) public class Proceeding { public static void main(String[] args) { } static aspect A { interface IProceed { void proceed(Runnable next); } IProceed decorator; void around() : execution(void main(String[])) { decorator.proceed(new Runnable() { public void run() { proceed(); } }); } } } ---- second problem: incorrect error wrt number of arguments public class Proceeding { public static void main(String[] args) { } static aspect A { void around() : execution(void main(String[])) { Proceeding.proceed(null); // BUG: treated as proceed(Object); } } static void proceed(Object o) {} } ---- third hypothetical: we should document how ambiguity is resolved public class Proceeding { public static void main(String[] args) { } static aspect A { void around() : execution(void main(String[])) { proceed(); // special form or Proceeding.proceed()? } } void proceed() {} }
Sorry - last hypo should be static void proceed() {} ^^^^^^
To maintain a simple specification the rule should be that a bare proceed in an aspect is always the special form and can never refer to a method even if one is defined by the aspect. However, we should support calling proceed with a receiver as in examples 1 and 2 as this is clearly unambiguous. This can probably be fixed fairly easily by modifying the method Proceed.findEnclosingAround to check if Proceed.receiver exists and if so to claim the proceed is not inside an around and therefore should be treated as a normal method.
Raising to a P2 bug to increase visibility, but not marking 1.2 as I don't think this should delay a 1.2 release.
marked as target 1.2.1
Fixed following Jim's suggestion. Had to make one refinement which is to treat the proceed as the special form in the case when the receiver is null, OR the receiver is non-null and receiver.isThis() returns true. All three of the cases below now work correctly. I also added the following to the semantics appendix: ============= Any occurence of proceed(..) within the body of around advice is treated as the special proceed form (even if the aspect defines a method named proceed) 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 ICanProceed instance, whereas the second call to proceed is treated as the special proceed form. aspect A { Object around(ICanProceed canProceed) : execution(* *(..)) && 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 } } ============== The wording is slightly cumbersome, but it was very hard to phrase this accurately.
Fix now available in latest development jar from AspectJ download page.
Fix released as part of AspectJ 1.2.1