groovy
  1. groovy
  2. GROOVY-2565

Exception with inheritance and private method calls from a closure

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Duplicate
    • Affects Version/s: 1.5.2
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None
    • Number of attachments :
      0

      Description

      The test 'testClosureCallWithPrivateMethod' fails with Groovy 1.5.1 and 1.5.2 (I don't know about the other versions). It should not fail.

      class Parent {
          void publicMethod1() {
              privateMethod()
          }
      
          void publicMethod2() {
              [''].each { privateMethod()}
          }
      
          void publicMethod3() {
              [''].each { protectedMethod()} 
          }
      
          private void privateMethod() {}
      
          protected void protectedMethod() {}
      }
      
      class Child extends Parent {}
      
      class ClosureMethodCallTest extends GroovyTestCase {
          void testDirectCall() {
              // No exceptions means the test passes
              new Child().publicMethod1()
          }
          
          void testClosureCallWithPrivateMethod() {
              // No exceptions means the test passes
              new Child().publicMethod2()
          }
      
          void testClosureCallWithProtectedMethod() {
              // No exceptions means the test passes
              new Child().publicMethod3()
          }
      }
      

        Issue Links

          Activity

          Hide
          blackdrag blackdrag added a comment -

          I can confirm this is no issue in 1.6

          Show
          blackdrag blackdrag added a comment - I can confirm this is no issue in 1.6
          Hide
          Guillaume Laforge added a comment -

          Already working in 1.6, not yet in 1.5.x.

          Show
          Guillaume Laforge added a comment - Already working in 1.6, not yet in 1.5.x.
          Hide
          Roshan Dawrani added a comment -

          Hi,
          I looked into this issue and it is not working in 1.5.8 because its handling of missing method is different from 1.6.

          In 1.5.8, MetaClassImpl -> invokeMissingMethod() simply throws MissingMethodExceptionNoStack if no missingMethod exception has been explicitly provided by user.

          In 1.6, MetaClassImpl -> invokeMissingMethod() does a lot more before deciding to throw the MissingMethodExceptionNoStack. One of the things it does is that it looks for the called methods up the class hierarchy and this is what is making the difference.

          In the code below, the closure's owner is Child object but Child class itself does not define privateMethod. Since 1.6 invokeMissingMethod() also checks up the hierarchy, it is successful. And since 1.5 invokeMissingMethod() doesn't do it, it fails to lookup privateMethod.

          I will try working on a patch for 1.5.8 to introduce this check up the hierarchy in 1.5.8 as well. Please let me know if anyone sees any issues with that.

          new Child().publicMethod2()
          
          class Parent {
              void publicMethod2() {
                  def cl = { privateMethod()}
                  cl()
              }
              private void privateMethod() {println "success"}
          }
          
          class Child extends Parent {}
          

          rgds,
          Roshan

          Show
          Roshan Dawrani added a comment - Hi, I looked into this issue and it is not working in 1.5.8 because its handling of missing method is different from 1.6. In 1.5.8, MetaClassImpl -> invokeMissingMethod() simply throws MissingMethodExceptionNoStack if no missingMethod exception has been explicitly provided by user. In 1.6, MetaClassImpl -> invokeMissingMethod() does a lot more before deciding to throw the MissingMethodExceptionNoStack. One of the things it does is that it looks for the called methods up the class hierarchy and this is what is making the difference. In the code below, the closure's owner is Child object but Child class itself does not define privateMethod. Since 1.6 invokeMissingMethod() also checks up the hierarchy, it is successful. And since 1.5 invokeMissingMethod() doesn't do it, it fails to lookup privateMethod. I will try working on a patch for 1.5.8 to introduce this check up the hierarchy in 1.5.8 as well. Please let me know if anyone sees any issues with that. new Child().publicMethod2() class Parent { void publicMethod2() { def cl = { privateMethod()} cl() } private void privateMethod() {println "success" } } class Child extends Parent {} rgds, Roshan
          Hide
          blackdrag blackdrag added a comment -

          this issue is duplicating GROOVY-3073

          Show
          blackdrag blackdrag added a comment - this issue is duplicating GROOVY-3073

            People

            • Assignee:
              blackdrag blackdrag
              Reporter:
              Hans Dockter
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: