[ 
https://issues.apache.org/jira/browse/GROOVY-11313?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17819818#comment-17819818
 ] 

Jochen Theodorou commented on GROOVY-11313:
-------------------------------------------

in { owner -> owner} owner refers to a local variable named owner, shadowing 
the getOwner. local variables take precedence, because of lexical scope. If you 
see a Closure as class then you expect the same rules to apply:
{code:Java}
class X {
    def getFoo(){1}
    def m(){foo}
    def m2(foo){foo}
    def m3(){
        def foo = 42
        return foo
    }
}

assert new X().m() == 1
assert new X().m2("foo") == "foo"
assert new X().m3() == 42
{code}
Following these examples I see not why owner in a Closure should get resolved 
to getOwner if there is a local variable of the same name. 
{code:Java}
def owner = 1
def cl = {owner}
assert cl() == 1
def cl2 = {return {owner}}
assert cl2()() == 1
{code}
And frankly I even expect this:
{code:Java}
class X {
  def owner = 22
  def m() {return {owner}}
}
assert new X().m() == 22
{code}
But I am aware that this probably never worked. And changing it would break 
things now. Out of delegate, owner and thisObject there is really only delegate 
the one that can change and might not be available through other means. So from 
inside a Closure we would really only to take care of that. But in the end the 
MOP gets in the way for this last one. But the others are supposed to work.

> Closure owner seems to be overwritten
> -------------------------------------
>
>                 Key: GROOVY-11313
>                 URL: https://issues.apache.org/jira/browse/GROOVY-11313
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 4.0.18
>            Reporter: Tomás Crespo García
>            Priority: Major
>
> I had a Groovy script with nested closures that used {{owner}} as the name of 
> the outer closure's parameter (even though {{owner}} might conflict with the 
> closure [owner|https://groovy-lang.org/closures.html#_owner_of_a_closure]):
> {code:java}
> import groovy.sql.GroovyRowResult
>  
> runAll()
>  
> void runAll() {
>     List owners = [new GroovyRowResult([user_id: 1])]
>     List pets = [new GroovyRowResult([id: 1])]
>  
>     owners.each { owner ->
>         myMethod(1)
>         pets.each { pet ->
>             myMethod(2)
>             println(owner.user_id)
>         }
>     }
> }
>  
> void myMethod(int i) {
>     println("Running my method ${i}")
> } {code}
> The same script worked as I expected in Groovy 3.x, but, in Groovy 4.0.18, it 
> fails with the following error:
> {code:java}
> Exception in thread "main" groovy.lang.MissingPropertyException: No such 
> property: myMethod for class: groovy.sql.GroovyRowResult
> at groovy.sql.GroovyRowResult.getProperty(GroovyRowResult.java:55)
> at groovy.sql.GroovyRowResult.get(GroovyRowResult.java:157)
> at groovy.lang.MetaClassImpl.invokePropertyOrMissing(MetaClassImpl.java:1389)
> at groovy.lang.MetaClassImpl.doInvokeMethod(MetaClassImpl.java:1335)
> at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1088)
> at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1007)
> at 
> org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:645)
> at 
> org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:628)
> at 
> org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeOnDelegationObjects(ClosureMetaClass.java:391)
> at 
> org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:328)
> at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1007)
> at 
> org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:321)
> at Script1$_runAll_closure1$_closure2.doCall(Script1.groovy:16)
> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native 
> Method)
> at 
> java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
> at 
> java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.base/java.lang.reflect.Method.invoke(Method.java:568)
> at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:343)
> at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:328) {code}
> It seems that {{myMethod}} in the inner closure is trying to get resolved as 
> a property of {{{}GroovyRowResult{}}}, which is the type of the {{owner}} 
> parameter of the outer closure. The moment I rename {{owner}} to something 
> else or transform the inner {{each}} to a {{for}} loop, the script works. It 
> doesn't fail either if I don't try to access any property of {{owner}} inside 
> the inner closure (such as {{{}owner.user_id{}}}).
>  
> Is this expected? 
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to