groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Leonard Brünings <groovy-...@bruenings-it.net>
Subject Re: Get reference to enclosing closure
Date Mon, 20 Nov 2017 20:58:07 GMT
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.milles@thomsonreuters.com:
>
> I think "this" or "getThisObject()" should really be "delegate" or 
> "getDelegate()".
>
> *From:*Leonard Brünings [mailto:groovy-dev@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
>


Mime
View raw message