Matthew Matthew - 1 month ago 11
Groovy Question

Nested closure resolution different between methods and properties?

When a closure's resolveStrategy is set to

DELEGATE_ONLY
or
DELEGATE_FIRST
, resolution is different in nested closures between methods and properties of the delegate. For example, in the following,
x
resolves to
f
's delegate (what I expect), but
keySet()
resolves to
g
's delegate.

​def g = {->
def f = {
{-> [x, keySet()]}()
}

f.resolveStrategy = Closure.DELEGATE_ONLY
f.delegate = [x: 1, f: 0]

f()
}

g.delegate = [x: 0, g: 0]
g()



Result:
[1, ['x', 'g']]


Whereas without the nested closure

def g = {->
def f = {
[x, keySet()]
}

f.resolveStrategy = Closure.DELEGATE_ONLY
f.delegate = [x: 1, f: 0]

f()
}

g.delegate = [x: 0, g: 0]
g()


Result:
[1, ['x', 'f']]


Is this behavior expected and documented somewhere? Is it a bug?

Answer

I believe it is a bug. If you change the map for a Expando it behaviors differently:

f = {
  g = {
    { -> keySet() }()
  }

  g.delegate = new Expando(a: 1000, b: 900, c: 800, keySet: { 'g keyset' })
  g.resolveStrategy = Closure.DELEGATE_ONLY
  g()

}

f.delegate = new Expando(a: 90, x: 9, y: 1, keySet: { 'f keyset' })

assert f() == 'g keyset'




f = {
  g = {
    { -> keySet() }()
  }

  g.delegate = [a: 1000, b: 900, c: 800]
  g.resolveStrategy = Closure.DELEGATE_ONLY
  g()

}

f.delegate = [a: 90, x: 9, y: 1]

assert f().toList() == ['a', 'b', 'c'] // fails :-(

Maybe filling a JIRA?