codeconsole opened a new pull request, #3194:
URL: https://github.com/apache/groovy/pull/3194

   The closures returned by `trampoline()`, `memoize*()`, `curry()`, `>>`/`<<` 
and `asWritable()` do not report or forward the delegation settings of the 
closure they wrap:
   
   ```groovy
   class D { def m() { 'delegate' } }
   class O {
       def m() { 'owner' }
       def run() {
           def c = { x -> m() }
           assert c.curry(1).thisObject.is(this)   // null
           def t = c.trampoline()
           t.resolveStrategy = Closure.DELEGATE_FIRST
           t.delegate = new D()
           assert t(1) == 'delegate'               // 'owner'
       }
   }
   new O().run()
   ```
   
   Seen in 4.0.33, 5.0.8 and 6.0.0 too.
   
   - `TrampolineClosure` passed the wrapped closure's delegate as its 
`thisObject`, so its `delegate` reported the owner. It now takes the wrapped 
closure's `thisObject` and forwards `getDelegate`, `setDelegate`, 
`getResolveStrategy` and `setResolveStrategy` to the wrapped closure, as 
`ComposedClosure` does. Its `clone()` copies the wrapped closure, so 
`with`/`tap`, which clone and then set the delegate, leave the original 
trampoline unchanged. Its parameter count and types now come from the wrapped 
closure's getters; before, a trampolined writable or composed closure reported 
a single `Object[]` parameter.
   - `Memoize.MemoizeFunction` gets the same forwarding, `thisObject` and 
`clone()`. The copy shares the cache.
   - `CurriedClosure`, `ComposedClosure` and `Closure.WritableClosure` forward 
`getThisObject` to the closure they call. `getOwner()` of these three still 
returns the wrapped closure, which they call through.
   
   One commit per wrapper.
   
   Merging: with #3186 (GROOVY-12665, wrapper rehydrate/dehydrate) this merges 
cleanly. With #3190 (GROOVY-12669, memoize rehydrate/dehydrate) one hunk in 
`MemoizeFunction` conflicts: keep #3190's `cacheFactory` field and constructor 
parameter, make `closure` non-final (needed by `clone()` here), and call 
`super(closure.getOwner(), closure.getThisObject())`.
   
   ## Tests
   
   These fail without the change:
   - `ClosureCurryTest.testThisObject`
   - `ClosureComposeTest.testThisObject`
   - `ClosureTest.testWritableClosureThisObject` (includes a `@CompileStatic` 
case)
   - `TrampolineTest`: `testDelegateAndThisObject`, 
`testSetDelegateAndResolveStrategy`, `testWith`, 
`testParametersOfWrappedClosure`
   - `AbstractMemoizeTestCase`: `testDelegateAndThisObject`, 
`testSetDelegateAndResolveStrategy`, `testWith`, run by `MemoizeTest`, 
`MemoizeAtMostTest`, `MemoizeAtLeastTest` and `MemoizeBetweenTest`
   
   `groovy.lang.*Closure*`, `groovy.*Closure*`, 
`org.codehaus.groovy.runtime.*Closure*`, 
`org.codehaus.groovy.runtime.trampoline.*`, 
`org.codehaus.groovy.runtime.memoize.*`, `MemoizedASTTransformationTest`, 
`gls.closures.*`, `groovy.transform.stc.*` and 
`org.codehaus.groovy.classgen.asm.sc.*` pass. The Checkstyle and CodeNarc gates 
pass.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to