Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
2.5.9
-
None
-
None
-
Groovy Version: 2.5.9 JVM: 1.8.0_232 Vendor: Azul Systems, Inc. OS: Mac OS X
Description
Example failing script:
#!/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
Expected output:
abc def
Actual output:
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)
Explanation of what I think is going on:
This commit 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:
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
Attachments
Issue Links
- links to