You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Eric Milles (Jira)" <ji...@apache.org> on 2020/02/08 18:56:00 UTC
[jira] [Assigned] (GROOVY-9387) Using this.method() in closures
inside BuilderSupport subclasses doesn't dispatch properly
[ https://issues.apache.org/jira/browse/GROOVY-9387?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Eric Milles reassigned GROOVY-9387:
-----------------------------------
Assignee: Eric Milles
> Using this.method() in closures inside BuilderSupport subclasses doesn't dispatch properly
> ------------------------------------------------------------------------------------------
>
> Key: GROOVY-9387
> URL: https://issues.apache.org/jira/browse/GROOVY-9387
> Project: Groovy
> Issue Type: Bug
> Affects Versions: 2.5.9
> Environment: Groovy Version: 2.5.9 JVM: 1.8.0_232 Vendor: Azul Systems, Inc. OS: Mac OS X
> Reporter: Henry Tung
> Assignee: Eric Milles
> Priority: Major
>
> Example failing script:
> {code:groovy}
> #!/usr/bin/env groovy
> class TestClass extends BuilderSupport {
> String value = "abc"
> void thing() {
> def b = { -> this.setProperty("value", "def") }
> b()
> }
>
> Object createNode(Object a, Object b) {}
> Object createNode(Object a) {}
> Object createNode(Object a, Map b) {}
> Object createNode(Object a, Map b, Object c) {}
> void setParent(Object a, Object b) {}
> }
> def x = new TestClass()
> println x.value
> x.thing()
> println x.value
> {code}
> Expected output:
> {noformat}
> abc
> def
> {noformat}
> Actual output:
> {noformat}
> abc
> Caught: groovy.lang.MissingMethodException: No signature of method: TestClass.setProperty() is applicable for argument types: (String, String) values: [value, def]
> Possible solutions: setProperty(java.lang.String, java.lang.Object), getProperty(java.lang.String), hasProperty(java.lang.String), getProperties()
> groovy.lang.MissingMethodException: No signature of method: TestClass.setProperty() is applicable for argument types: (String, String) values: [value, def]
> Possible solutions: setProperty(java.lang.String, java.lang.Object), getProperty(java.lang.String), hasProperty(java.lang.String), getProperties()
> at TestClass$_thing_closure1.doCall(test.groovy:6)
> at TestClass.thing(test.groovy:7)
> at TestClass$thing.call(Unknown Source)
> at test.run(test.groovy:19)
> {noformat}
> Explanation of what I think is going on:
> [This commit|https://github.com/apache/groovy/commit/34ad466ba6a87a5eb26cf4a444f817299b744edb#diff-ba71c5ea5d5201ae4da0b6a7b7e46137L66] changed what used to be a dispatch to the owner's metaclass into a dispatch using sender == closure class. For some reason, the metaclass looks up {{(closure class, "setProperty")}} in its {{MetaMethodIndex}}, which naturally doesn't find anything.
> The second attempt using {{((GroovyObject)receiver).invokeMethod()}} doesn't work because {{BuilderSupport}} overrides {{invokeMethod}} and doesn't delegate back to dynamic lookup. Thus, code fails at runtime.
> Example workaround:
> {code:groovy}
> class TestClass extends BuilderSupport {
> String value = "abc"
> TestClass that = this
> void thing() {
> def b = { -> that.setProperty("value", "def") }
> b()
> }
>
> Object createNode(Object a, Object b) {}
> Object createNode(Object a) {}
> Object createNode(Object a, Map b) {}
> Object createNode(Object a, Map b, Object c) {}
> void setParent(Object a, Object b) {}
> }
> def x = new TestClass()
> println x.value
> x.thing()
> println x.value
> {code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)