You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Henry Tung (Jira)" <ji...@apache.org> on 2020/02/08 00:28:00 UTC
[jira] [Created] (GROOVY-9387) Using this.method() in closures
inside BuilderSupport subclasses doesn't dispatch properly
Henry Tung created GROOVY-9387:
----------------------------------
Summary: 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
Example failing script:
{code:groovy}
#!/usr/bin/env groovy
class TestClass extends BuilderSupport {
String value = "abc"
void thing() {
def b = { -> this.test(); 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.test(); 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)