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

Here is the gist:

This snippet

 
def 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

Do you have any ideas on how to fix this elegantly?

- Cheers
Leonard