Bug 53981 - proceed used as method name in around advice
Summary: proceed used as method name in around advice
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.1.1   Edit
Hardware: PC Windows XP
: P2 normal (vote)
Target Milestone: 1.2.1   Edit
Assignee: Adrian Colyer CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-03-06 22:43 EST by Wes Isberg CLA
Modified: 2004-10-21 04:31 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Wes Isberg CLA 2004-03-06 22:43:04 EST
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() {}
}
Comment 1 Wes Isberg CLA 2004-03-06 22:44:16 EST
Sorry - last hypo should be

  static void proceed() {}
  ^^^^^^


Comment 2 Jim Hugunin CLA 2004-03-18 14:12:19 EST
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.
Comment 3 Jim Hugunin CLA 2004-03-18 14:12:57 EST
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.
Comment 4 Adrian Colyer CLA 2004-08-09 15:23:53 EDT
marked as target 1.2.1
Comment 5 Adrian Colyer CLA 2004-08-10 09:18:10 EDT
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.
Comment 6 Adrian Colyer CLA 2004-08-10 12:05:02 EDT
Fix now available in latest development jar from AspectJ download page.
Comment 7 Adrian Colyer CLA 2004-10-21 04:31:13 EDT
Fix released as part of AspectJ 1.2.1