[ 
https://issues.apache.org/jira/browse/GROOVY-9662?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17202930#comment-17202930
 ] 

Eric Milles edited comment on GROOVY-9662 at 9/27/20, 10:19 PM:
----------------------------------------------------------------

ClosureMetaClass checks the closure for any method right after the call/doCall 
block.

{code:java}
    public Object invokeMethod(Class sender, Object object, String methodName, 
Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
        ...
        MetaMethod method = null;
        final Closure closure = (Closure) object;
        if (CLOSURE_DO_CALL_METHOD.equals(methodName) || 
CLOSURE_CALL_METHOD.equals(methodName)) {
            ...
        }
        boolean shouldDefer = closure.getResolveStrategy() == 
Closure.DELEGATE_ONLY && isInternalMethod(methodName);
        if (method == null && !shouldDefer) {
            method = CLOSURE_METACLASS.pickMethod(methodName, argClasses); // 
HERE!
        }

        if (method != null) return method.doMethodInvoke(object, arguments);
{code}

Here is a quick demonstration:
{code:groovy}
class D {
  void run() { println 'D.run()' }
}
class C {
  int times = 5
  void test() {
    new D().with {
      println "C.test.with $times"
      if (--times) run() // Closure.run() or D.run()?
    }
  }
}
new C().test()
{code}


was (Author: emilles):
ClosureMetaClass checks the closure for any method right after the call/doCall 
block.

{code:java}
    public Object invokeMethod(Class sender, Object object, String methodName, 
Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
        ...
        MetaMethod method = null;
        final Closure closure = (Closure) object;
        if (CLOSURE_DO_CALL_METHOD.equals(methodName) || 
CLOSURE_CALL_METHOD.equals(methodName)) {
            ...
        }
        boolean shouldDefer = closure.getResolveStrategy() == 
Closure.DELEGATE_ONLY && isInternalMethod(methodName);
        if (method == null && !shouldDefer) {
            method = CLOSURE_METACLASS.pickMethod(methodName, argClasses); // 
HERE!
        }

        if (method != null) return method.doMethodInvoke(object, arguments);
{code}

> Groovy 3.0.5: Closure delegate is not working properly
> ------------------------------------------------------
>
>                 Key: GROOVY-9662
>                 URL: https://issues.apache.org/jira/browse/GROOVY-9662
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 3.0.2, 3.0.3, 3.0.4, 3.0.5
>            Reporter: Puneet Behl
>            Assignee: Eric Milles
>            Priority: Major
>
> In Grails Views, we are using closures to generate JSON using 
> `StreamingJsonBuilder`. The HAL implementation for an entity now generates an 
> incorrect JSON after updating to Groovy 3.
>  
> Here is the problem code snipped from Grails Views: 
> {code:java}
> jsonDelegate.call(LINKS_ATTRIBUTE) {
>     call(SELF_ATTRIBUTE) {
>         call HREF_ATTRIBUTE, viewHelper.link(resource: object, method: 
> HttpMethod.GET, absolute: true)
>         call HREFLANG_ATTRIBUTE, locale.toString()
>         call TYPE_ATTRIBUTE, contentType
>     }
>     Set<Link> links = getLinks(object)
>     for (link in links) {
>         call(link.rel) {
>             call HREF_ATTRIBUTE, link.href
>             call HREFLANG_ATTRIBUTE, link.hreflang?.toString() ?: 
> locale.toString()
>             def linkType = link.contentType
>             if (linkType) {
>                 call TYPE_ATTRIBUTE, linkType
>             }
>         }
>     }
> }
> {code}
>  
> Although the `resolveStatergy` for the closures is `DELEGATE_FIRST` but I 
> believe that is not working correctly because it works if I change the above 
> to:
> {code:java}
> delegate.call (...
> {code}
>  
> To reproduce the issue please checkout 
> https://github.com/grails/grails-views/commits/bugs/groovy-9962
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to