You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (JIRA)" <ji...@apache.org> on 2017/02/01 23:17:53 UTC

[jira] [Closed] (GROOVY-7301) Closure method gets successfully called on the both delegate and the owner

     [ https://issues.apache.org/jira/browse/GROOVY-7301?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Paul King closed GROOVY-7301.
-----------------------------

> Closure method gets successfully called on the both delegate and the owner
> --------------------------------------------------------------------------
>
>                 Key: GROOVY-7301
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7301
>             Project: Groovy
>          Issue Type: Bug
>          Components: Compiler
>    Affects Versions: 2.3.7
>            Reporter: Andrew Audibert
>            Assignee: Jochen Theodorou
>              Labels: usertask
>
> If a MissingMethodException occurs during the execution of a delegate's closure, the ClosureMetaClass will incorrectly try to execute the method on the owner.
> {{test.groovy}}
> {code}
> def count = 0
> def delegate = {}
> delegate.f = {
>     println "Successfully called f on the delegate"
>     count += 1
>     throw new MissingMethodException("f", String.class, [])
> }
> class Owner{}
> Owner.metaClass.invokeMethod = {name, args ->
>     println "Successfully called f on the owner"
>     count +=1
> }
> def a = {}
> a.delegate = delegate
> a.@owner = new Owner()
> a.setResolveStrategy(Closure.DELEGATE_FIRST)
> a.f()
> println count
> {code}
> Expected: Prints "Successfully called f on the delegate" and then throws a MissingMethodException.
> Actual:
> {code}
> aaudibert-mbp% groovy test.groovy
> Successfully called f on the delegate
> Successfully called f on the owner
> 2
> {code}
> The issue seems to be in ClosureMetaClass.invokeOnDelegationObjects where it does this:
> {code}
> try {
>     return go.invokeMethod(methodName, args);
> } catch (MissingMethodException mme) {
>     first = mme;
> } catch (GroovyRuntimeException gre) {
>     Throwable th = unwrap(gre);
>     if ((th instanceof MissingMethodException)
>             && (methodName.equals(((MissingMethodException) th).getMethod()))) {
>         first = (MissingMethodException) th;
>     } else {
>         throw gre;
>     }
> }
> {code}
> Invoking the method and checking for MissingMethodException isn't enough to determine whether the method exists for the {{go}} object, because it may exist, but have the effect of throwing MME. The handling for GroovyRuntimeException is better, but still inadequate for determining whether the method exists on the {{go}} object, as shown by the repro.
> Would {{go.getMetaClass().pickMethod(methodName, ARG_TYPES)}} be the right way to do this?



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)