groovy
  1. groovy
  2. GROOVY-5367

Closure property in Binding used as Closure delegate cannot be called

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 1.8.6
    • Fix Version/s: 3.0
    • Component/s: groovy-runtime
    • Labels:
      None
    • Testcase included:
      yes
    • Number of attachments :
      0

      Description

      In a script, this works:

      c =

      { println 'works' }

      c()

      whereas this one doesn't:

      def bind = new Binding(c:

      { println 'does not work' }

      )
      def t =

      { c() }

      t.delegate = bind
      t()

      They both define a 'c' property in the binding which happens to be a closure. In the first case, the closure get's called as Groovy apparently tries to get the binding property and invoke it if it's a closure; in the latter, the delegate of the closure is a binding with a property 'c' that is a closure, but c() still doesn't work.

      I debugged this and there is actually an if in MetaClassImpl that checks if the 'this' object is a Script, and if so, a property with the name is retrieved and a call() method is called. (MetaClassImpl#invokePropertyOrMissing:1089 in Groovy 1.8.6-all from maven central).

        Activity

        Hide
        Wujek added a comment -

        Here is a short conversation and a bug request from the mailing list:
        http://groovy.329449.n5.nabble.com/Binding-Closure-property-not-called-as-method-td5562137.html

        Show
        Wujek added a comment - Here is a short conversation and a bug request from the mailing list: http://groovy.329449.n5.nabble.com/Binding-Closure-property-not-called-as-method-td5562137.html
        Hide
        John Boone added a comment -

        There is a workaround for this issue. It's a bit of a hack but is valid in most cases. Simply bind the closures to the Binding.metaClass (see below):

        CODE:
        Binding.metaClass.c =

        {exclamation -> println "$a Yipee $exclamation " }

        def t =

        { c(' !!! :) ') }

        t.delegate = [a : 'It works'] as Binding
        t()

        OUTPUT:
        It works Yipee !!!

        Show
        John Boone added a comment - There is a workaround for this issue. It's a bit of a hack but is valid in most cases. Simply bind the closures to the Binding.metaClass (see below): CODE: Binding.metaClass.c = {exclamation -> println "$a Yipee $exclamation " } def t = { c(' !!! :) ') } t.delegate = [a : 'It works'] as Binding t() OUTPUT: It works Yipee !!!
        Hide
        blackdrag blackdrag added a comment -

        from debugging the code I can now see, that this kind of operation is only allowed of the delegate is a GroovyObject, and even then only for normal properties, getProperty or missingProperty won't be called.

        Show
        blackdrag blackdrag added a comment - from debugging the code I can now see, that this kind of operation is only allowed of the delegate is a GroovyObject, and even then only for normal properties, getProperty or missingProperty won't be called.

          People

          • Assignee:
            Unassigned
            Reporter:
            Wujek
          • Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: