You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2020/02/12 05:01:15 UTC

[groovy] branch GROOVY_2_5_X updated: GROOVY-9387: MissingMethodException: try one more metaClass.invokeMethod

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push:
     new 75c0682  GROOVY-9387: MissingMethodException: try one more metaClass.invokeMethod
75c0682 is described below

commit 75c068207ba24648ea2d698c520601c6fcf0a45b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Feb 8 10:30:49 2020 -0600

    GROOVY-9387: MissingMethodException: try one more metaClass.invokeMethod
---
 .../groovy/runtime/callsite/PogoMetaClassSite.java |  15 ++-
 src/test/groovy/bugs/Groovy9387.groovy             | 102 +++++++++++++++++++++
 2 files changed, 113 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/runtime/callsite/PogoMetaClassSite.java b/src/main/java/org/codehaus/groovy/runtime/callsite/PogoMetaClassSite.java
index 4b16fcb..7a52680 100644
--- a/src/main/java/org/codehaus/groovy/runtime/callsite/PogoMetaClassSite.java
+++ b/src/main/java/org/codehaus/groovy/runtime/callsite/PogoMetaClassSite.java
@@ -49,7 +49,7 @@ public class PogoMetaClassSite extends MetaClassSite {
                 throw ScriptBytecodeAdapter.unwrap(gre);
             }
         } else {
-          return CallSiteArray.defaultCall(this, receiver, args);
+            return CallSiteArray.defaultCall(this, receiver, args);
         }
     }
 
@@ -66,8 +66,15 @@ public class PogoMetaClassSite extends MetaClassSite {
                     if (e instanceof MissingMethodExecutionFailed) {
                         throw (MissingMethodException)e.getCause();
                     } else if (receiver.getClass() == e.getType() && e.getMethod().equals(name)) {
-                        // in case there's nothing else, invoke the object's own invokeMethod()
-                        return ((GroovyObject)receiver).invokeMethod(name, args);
+                        // in case there's nothing else, invoke the receiver's own invokeMethod()
+                        try {
+                            return receiver.invokeMethod(name, args);
+                        } catch (MissingMethodException mme) {
+                            if (mme instanceof MissingMethodExecutionFailed)
+                                throw (MissingMethodException) mme.getCause();
+                            // GROOVY-9387: in rare cases, this form still works
+                            return metaClass.invokeMethod(receiver, name, args);
+                        }
                     } else {
                         throw e;
                     }
@@ -76,7 +83,7 @@ public class PogoMetaClassSite extends MetaClassSite {
                 throw ScriptBytecodeAdapter.unwrap(gre);
             }
         } else {
-          return CallSiteArray.defaultCallCurrent(this, receiver, args);
+            return CallSiteArray.defaultCallCurrent(this, receiver, args);
         }
     }
 }
diff --git a/src/test/groovy/bugs/Groovy9387.groovy b/src/test/groovy/bugs/Groovy9387.groovy
new file mode 100644
index 0000000..ea0df36
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9387.groovy
@@ -0,0 +1,102 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy9387 {
+
+    private static final String SUPPORT_ADAPTER = '''
+        class BuilderSupportAdapter extends BuilderSupport {
+            def createNode(a, b) {}
+            def createNode(a) {}
+            def createNode(a, Map b) {}
+            def createNode(a, Map b, c) {}
+            void setParent(a, b) {}
+        }
+    '''
+
+    @Test
+    void testThisPropertySet() {
+        assertScript SUPPORT_ADAPTER + '''
+            class C extends BuilderSupportAdapter {
+                String value = 'abc'
+                void test() {
+                    def b = { -> this.'value' = 'def' }
+                    b()
+                }
+            }
+
+            def c = new C()
+            def v = c.value
+            assert v == 'abc'
+
+            c.test()
+            v = c.value
+            assert v == 'def'
+        '''
+    }
+
+    @Test
+    void testThisSetProperty() {
+        assertScript SUPPORT_ADAPTER + '''
+            class C extends BuilderSupportAdapter {
+                String value = 'abc'
+                void test() {
+                    def b = { -> this.setProperty('value', 'def') }
+                    b()
+                }
+            }
+
+            def c = new C()
+            def v = c.value
+            assert v == 'abc'
+
+            c.test()
+            v = c.value
+            assert v == 'def'
+        '''
+    }
+
+    @Test
+    void testThatSetProperty() {
+        assertScript SUPPORT_ADAPTER + '''
+            class C extends BuilderSupportAdapter {
+                private C that = this
+                String value = 'abc'
+                void test() {
+                    def b = { -> that.setProperty('value', 'def') }
+                    b()
+                }
+            }
+
+            def c = new C()
+            def v = c.value
+            assert v == 'abc'
+
+            c.test()
+            v = c.value
+            assert v == 'def'
+        '''
+    }
+}
\ No newline at end of file