groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From C├ędric Champeau <cedric.champ...@gmail.com>
Subject Re: Add closures to class via AST
Date Sat, 22 Aug 2015 08:06:44 GMT
Hi Anto,

(first of all, I don't think you will get more answers by sending multiple
mails in a single day, we all have our respective jobs).

I'm not sure if your closure code makes a lot of sense, however, `param` is
indeed null. What you generate is:

def helloTest(def param) {
    { param ->
        // why delegate.with?
        delegate.with {
            println delegate
            param()
        }

    }.call()
}


So you can already see that you have a conflict between the method
parameter name and the closure parameter. Regular code will not let you do
this, if you do AST xforms, you have to care about it yourself and make
sure you don't mix things up. So imagine that you rename the method param
name to `p` and call the method. -> NPE, because you call the closure with
no arguments, which will cause param to be `null`. That's what is
happening. On the other hand, if you create a closure that takes *no*
argument and refers to the parameter like this:

def helloTest(def param) {
    { ->
        delegate.with {
            println delegate
            param()
        }
    }.call()
}


Then it works as you expect. Last but not least, you may have to call the
VariableScopeVisitor yourself depending on the compiler phase your AST
transform works.

Best regards,

2015-08-22 1:05 GMT+02:00 Anto Aravinth <anto.aravinth.cse@gmail.com>:

> Any ideas will greatly helps!!
> On 21 Aug 2015 16:57, "Anto Aravinth" <anto.aravinth.cse@gmail.com> wrote:
>
>> Hi All,
>>
>> Any solutions?
>> On 21 Aug 2015 09:21, "Anto Aravinth" <anto.aravinth.cse@gmail.com>
>> wrote:
>>
>>> Hi all,
>>>
>>>
>>>
>>> I'm trying to add an closure to my classNode via AST transformation. My
>>> code looks something like this:
>>>
>>>
>>>
>>> List<ASTNode> closure = new AstBuilder().buildFromCode {
>>>
>>>                 { param ->
>>>
>>>                     delegate.with {
>>>
>>>                         param()
>>>
>>>                     }
>>>
>>>                 }
>>>
>>>             }
>>>
>>>
>>>
>>>             cNode.addMethod(new MethodNode('helloTest', ACC_PUBLIC,
>>> ClassHelper.DYNAMIC_TYPE,[new Parameter(ClassHelper.OBJECT_TYPE, "param")]
>>> as Parameter[], ClassNode.EMPTY_ARRAY, closure[0]));
>>>
>>>
>>>
>>> And running AST transformation, on the test class:
>>>
>>>
>>>
>>> @AddMethod
>>>
>>> class Test{
>>>
>>> }
>>>
>>>
>>>
>>> def a = new Test()
>>>
>>> a.helloTest({
>>>
>>>         println "Works great!";
>>>
>>> })
>>>
>>>
>>>
>>> Now no errors nothing. The code works fine, but since I have passed an
>>> println to the helloTest closure, I expect it to print on my console, which
>>> didn't happen. Looks like my closure itself didn't ran. Then I called the
>>> closure myself, something like this:
>>>
>>>
>>>
>>>             List<ASTNode> closure = new AstBuilder().buildFromCode {
>>>
>>>                 { param ->
>>>
>>>                     delegate.with {
>>>
>>>                         println delegate
>>>
>>>                         param()
>>>
>>>                     }
>>>
>>>                 }.call()
>>>
>>>             }
>>>
>>>
>>>
>>> Now this gives NPE, saying param is null. Looks now the parameter is not
>>> getting binded. Delegate is getting printed as expected.
>>>
>>>
>>>
>>> Also I'm not sure, the way I have added the closure to my class is right
>>> or not. Any help would be great!
>>>
>>

Mime
View raw message