Hi Eric,
transforming every implicit method call this way would also break the
nested `with` blocks.
It would basically be a DELEGATE_ONLY strategy, which would prevent
helper methods defined
in the class to be used.
-Leo
Am 20.11.2017 um 21:29 schrieb eric.mil...@thomsonreuters.com:
I think "this" or "getThisObject()" should really be "delegate" or
"getDelegate()".
*From:*Leonard Brünings [mailto:groovy-...@bruenings-it.net]
*Sent:* Monday, November 20, 2017 2:27 PM
*To:* dev@groovy.apache.org
*Subject:* Get reference to enclosing closure
Hi,
I'm Leonard from the Spock framework team. Guillaume suggested that I
write to the dev-list with this problem.
Some context:
Spock has a method `with(Object, Closure)` in its Specification class
that sets the object as the delegate of the closure and transforms,
every call inside the closure to an implicit assertion.
given:
def person = new Person(name: "Peter", age: 28)
expect:
with(person) {
name == 'Peter'
age == 28
}
This worked fine for properties, however for single methods like
`contains` it didn't work.
The initial problem is described here
https://github.com/spockframework/spock/pull/606
<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_spockframework_spock_pull_606&d=DwMDaQ&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=Fa8Q9YcX7hY9VbwfwahFaxYu0kY_r2a9tvNUcGXmQSk&s=q_R3dw-m9pIZzvCwtx3GC4Mm0pBAF3QIJ5lFVjTIF7k&e=>
Here is the gist:
This snippet
d|ef list = [1, 2]|
|with(list) {|
| contains(1)|
|}|
transforms in AST (simplified) to
|def list = [1, 2]|
|with(list) {|
| SpockRuntime.verifyMethodCondition(this, "contains", [1])|
|}|
||
then when the AST is written to bytecode it gets transformed again
|def list = [1, 2]|
|with(list) {|
| SpockRuntime.verifyMethodCondition(this.getThisObject(), "contains",
[1])|
|}|
The problem is that the `contains` is now invoked on the containing
`Specification` instead of the `List`.
With the aforementioned PR it was changed to this
|def list = [1, 2]|
|with(list) {|
|
SpockRuntime.verifyMethodCondition(this.each(groovy.lang.Closure.IDENTITY),
"contains", [1])|
|}|
This "fix" now broke the nesting of `with` blocks as described here:
https://github.com/spockframework/spock/pull/782
<https://urldefense.proofpoint.com/v2/url?u=https-3A__github.com_spockframework_spock_pull_782&d=DwMDaQ&c=4ZIZThykDLcoWk-GVjSLmy8-1Cr1I4FWIvbLFebwKgY&r=tPJuIuL_GkTEazjQW7vvl7mNWVGXn3yJD5LGBHYYHww&m=Fa8Q9YcX7hY9VbwfwahFaxYu0kY_r2a9tvNUcGXmQSk&s=M5zC-i1pBw89T8iQDueDfncXWUr7YsR1IynIed9NqiI&e=>
Do you have any ideas on how to fix this elegantly?
- Cheers
Leonard