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

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


The following commit(s) were added to refs/heads/GROOVY_5_0_X by this push:
     new 0363194358 GROOVY-10904, GROOVY-11781: MissingMethodException for 
class receiver
0363194358 is described below

commit 03631943585db75412e4268acafbab64323151bc
Author: Eric Milles <[email protected]>
AuthorDate: Sat Oct 11 12:26:40 2025 -0500

    GROOVY-10904, GROOVY-11781: MissingMethodException for class receiver
---
 src/main/java/groovy/lang/MetaClassImpl.java       |  30 ++---
 src/test/groovy/groovy/lang/MetaClassTest.java     | 144 ++++++++++++---------
 .../transform/stc/MethodReferenceTest.groovy       |  56 ++++----
 3 files changed, 126 insertions(+), 104 deletions(-)

diff --git a/src/main/java/groovy/lang/MetaClassImpl.java 
b/src/main/java/groovy/lang/MetaClassImpl.java
index aa1781625e..e1a13d9084 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -889,9 +889,9 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         }
 
         Class<?> instanceKlazz = instance.getClass();
-        if (theClass != instanceKlazz && 
theClass.isAssignableFrom(instanceKlazz))
+        if (theClass != instanceKlazz && 
theClass.isAssignableFrom(instanceKlazz)) {
             instanceKlazz = theClass;
-
+        }
         Class<?>[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
 
         MetaMethod method = findMixinMethod(methodName, argClasses);
@@ -914,7 +914,7 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
             return method.invoke(instance, invokeMethodArgs);
         }
 
-        // last resort look in the category
+        // last resort: look in the category
         if (method == null && 
GroovyCategorySupport.hasCategoryInCurrentThread()) {
             method = getCategoryMethodMissing(instanceKlazz);
             if (method != null) {
@@ -922,29 +922,27 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
             }
         }
 
+        if (theClass != Class.class && instance instanceof Class) { // 
GROOVY-11781
+            return invokeStaticMissingMethod((Class<?>) instance, methodName, 
arguments);
+        }
         if (methodMissing != null) {
             try {
                 return methodMissing.invoke(instance, new Object[]{methodName, 
arguments});
             } catch (InvokerInvocationException iie) {
                 if (methodMissing instanceof ClosureMetaMethod && 
iie.getCause() instanceof MissingMethodException) {
                     MissingMethodException mme = (MissingMethodException) 
iie.getCause();
-                    throw new MissingMethodExecutionFailed(mme.getMethod(), 
mme.getClass(),
-                            mme.getArguments(), mme.isStatic(), mme);
+                    throw new MissingMethodExecutionFailed(mme.getMethod(), 
mme.getClass(), mme.getArguments(), mme.isStatic(), mme);
                 }
                 throw iie;
             } catch (MissingMethodException mme) {
                 if (methodMissing instanceof ClosureMetaMethod) {
-                    throw new MissingMethodExecutionFailed(mme.getMethod(), 
mme.getClass(),
-                            mme.getArguments(), mme.isStatic(), mme);
-                } else {
-                    throw mme;
+                    throw new MissingMethodExecutionFailed(mme.getMethod(), 
mme.getClass(), mme.getArguments(), mme.isStatic(), mme);
                 }
+                throw mme;
             }
-        } else if (original != null) {
-            throw original;
-        } else {
-            throw new MissingMethodExceptionNoStack(methodName, theClass, 
arguments, false);
         }
+
+        throw original != null ? original : new 
MissingMethodExceptionNoStack(methodName, theClass, arguments, false);
     }
 
     protected void onSuperPropertyFoundInHierarchy(MetaBeanProperty property) {
@@ -1018,9 +1016,9 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         var ownerMetaClass = registry.getMetaClass(ownerClass);
         try {
             return ownerMetaClass.invokeMethod(ownerClass, owner, method, 
arguments, false, false);
-        } catch (GroovyRuntimeException e) { // 
GroovyRuntimeException(cause:IllegalArgumentException) thrown for final fields
-                                             // 
InvokerInvocationException(cause:IllegalArgumentException) thrown for not this
-            if (!ownerIsClass || !(e instanceof MissingMethodException || 
e.getCause() instanceof IllegalArgumentException)) {
+        } catch (GroovyRuntimeException e) { // 
GroovyRuntimeException(cause:IllegalArgumentException) thrown for final field
+                                             // 
InvokerInvocationException(cause:MissingMethodException) thrown for not found
+            if (!ownerIsClass || !(e instanceof MissingMethodException || 
e.getCause() instanceof MissingMethodException || e.getCause() instanceof 
IllegalArgumentException)) {
                 throw e;
             }
             if (MethodClosure.NEW.equals(method)) {
diff --git a/src/test/groovy/groovy/lang/MetaClassTest.java 
b/src/test/groovy/groovy/lang/MetaClassTest.java
index fc9e37aa6c..3cf26ab0c8 100644
--- a/src/test/groovy/groovy/lang/MetaClassTest.java
+++ b/src/test/groovy/groovy/lang/MetaClassTest.java
@@ -18,59 +18,68 @@
  */
 package groovy.lang;
 
-import groovy.test.GroovyTestCase;
 import org.codehaus.groovy.runtime.InvokerHelper;
+import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
-public class MetaClassTest extends GroovyTestCase {
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-    public void testMetaClass() {
-        Class foo = String[].class;
+final class MetaClassTest {
+
+    @Test
+    void testMetaClass() {
+        Class<?> foo = String[].class;
         System.out.println(foo + " name: " + foo.getName());
 
         MetaClass metaClass = InvokerHelper.getMetaClass(this);
 
-        assertTrue("got metaclass", metaClass != null);
+        assertNotNull(metaClass, "got metaclass");
 
         metaClass.invokeMethod(this, "doSomething", new Object[0]);
     }
 
-    public void testArray() {
+    @Test
+    void testArray() {
         String[] value = new String[]{"hello"};
 
         MetaClass metaClass = InvokerHelper.getMetaClass(value);
 
-        assertTrue("got metaclass", metaClass != null);
+        assertNotNull(metaClass, "got metaclass");
 
         metaClass.invokeMethod(value, "toString", new Object[0]);
     }
 
-    public void testString() {
+    @Test
+    void testString() {
         String value = "hello";
 
         MetaClass metaClass = InvokerHelper.getMetaClass(value);
 
-        assertTrue("got metaclass", metaClass != null);
+        assertNotNull(metaClass, "got metaclass");
 
         Object answer = metaClass.invokeMethod(value, "toString", new 
Object[0]);
 
         assertEquals("hello", answer);
     }
 
-    public void testObject() {
+    @Test
+    void testObject() {
         Object value = new Object();
 
         MetaClass metaClass = InvokerHelper.getMetaClass(value);
 
-        assertTrue("got metaclass", metaClass != null);
+        assertNotNull(metaClass, "got metaclass");
 
         metaClass.invokeMethod(value, "toString", new Object[0]);
     }
 
-    public void testPublicField() {
+    @Test
+    void testPublicField() {
         DymmyClass dymmyClass = new DymmyClass();
 
         MetaClass metaClass = InvokerHelper.getMetaClass(dymmyClass);
@@ -85,13 +94,25 @@ public class MetaClassTest extends GroovyTestCase {
         assertEquals(dymmyClass.y, "newvalue");
     }
 
-    public void testSetPropertyWithInt() {
+    // GROOVY-11781
+    @Test
+    void testMethodMissing() {
+        MetaClass metaClass = InvokerHelper.getMetaClass(DymmyClass.class);
+
+        assertThrows(MissingMethodException.class, () -> {
+            metaClass.invokeMissingMethod(DymmyClass.class, "xxx", new 
Object[0]);
+        });
+    }
+
+    @Test
+    void testSetPropertyWithInt() {
         DymmyClass dymmyClass = new DymmyClass();
         MetaClass metaClass = InvokerHelper.getMetaClass(dymmyClass);
         metaClass.setProperty(dymmyClass, "anInt", Integer.valueOf(10));
     }
 
-    public void testSetPropertyWithDoubleArray() {
+    @Test
+    void testSetPropertyWithDoubleArray() {
         DymmyClass dymmyClass = new DymmyClass();
         MetaClass metaClass = InvokerHelper.getMetaClass(dymmyClass);
         Double[][] matrix2 =
@@ -107,7 +128,8 @@ public class MetaClassTest extends GroovyTestCase {
         metaClass.setProperty(dymmyClass, "matrix2", matrix2);
     }
 
-    public void testSetPropertyWithArray() {
+    @Test
+    void testSetPropertyWithArray() {
         DymmyClass dymmyClass = new DymmyClass();
         MetaClass metaClass = InvokerHelper.getMetaClass(dymmyClass);
 
@@ -126,12 +148,13 @@ public class MetaClassTest extends GroovyTestCase {
         assertEquals(integers, metaClass.getProperty(dymmyClass, "integers"));
     }
 
-    public void testSetPropertyWithList() {
+    @Test
+    void testSetPropertyWithList() {
         DymmyClass dymmyClass = new DymmyClass();
         MetaClass metaClass = InvokerHelper.getMetaClass(dymmyClass);
 
         // test list
-        ArrayList list = new ArrayList();
+        var list = new ArrayList<Integer>();
         list.add(Integer.valueOf(120));
         list.add(Integer.valueOf(150));
 
@@ -142,74 +165,75 @@ public class MetaClassTest extends GroovyTestCase {
         metaClass.setProperty(dymmyClass, "integers", list);
     }
 
-    public void testMetaMethodsOnlyAddedOnce() {
+    @Test
+    void testMetaMethodsOnlyAddedOnce() {
         MetaClass metaClass = InvokerHelper.getMetaClass("some String");
 
-        List methods = metaClass.getMetaMethods();
-        for (Iterator iter = methods.iterator(); iter.hasNext();) {
-            MetaMethod method = (MetaMethod) iter.next();
+        List<MetaMethod> methods = metaClass.getMetaMethods();
+        for (Iterator<MetaMethod> iter = methods.iterator(); iter.hasNext(); ) 
{
+            MetaMethod method = iter.next();
             int count = 0;
-            for (Iterator inner = methods.iterator(); inner.hasNext();) {
-                MetaMethod runner = (MetaMethod) inner.next();
+            for (Iterator<MetaMethod> inner = methods.iterator(); 
inner.hasNext(); ) {
+                MetaMethod runner = inner.next();
                 if (method.equals(runner)) {
                     System.out.println("runner = " + runner);
                     System.out.println("method = " + method);
                     count++;
                 }
             }
-            assertEquals("count of Method " + method.getName(), 1, count);
+            assertEquals(1, count, "count of Method " + method.getName());
         }
-
     }
 
+    
//--------------------------------------------------------------------------
 
     public void doSomething() {
         System.out.println("Called doSomething()");
     }
-}
-
 
-class DymmyClass {
-    public int x = 0;
-    public String y = "none";
+    static class DymmyClass {
+        public int x = 0;
+        public String y = "none";
+        private int anInt;
+        private int[] ints;
+        private Integer[] integers;
+        double[][] matrix2;
+        Double[][] matrix;
 
-    private int anInt;
-    private int[] ints;
-    private Integer[] integers;
-    double[][] matrix2;
-    Double[][] matrix;
+        public Integer[] getIntegers() {
+            return integers;
+        }
 
-    public Integer[] getIntegers() {
-        return integers;
-    }
+        public void setIntegers(Integer[] integers) {
+            this.integers = integers;
+        }
 
-    public void setIntegers(Integer[] integers) {
-        this.integers = integers;
-    }
+        public int[] getInts() {
+            return ints;
+        }
 
-    public int[] getInts() {
-        return ints;
-    }
+        public void setInts(int[] ints) {
+            this.ints = ints;
+        }
 
-    public void setInts(int[] ints) {
-        this.ints = ints;
-    }
+        public int getAnInt() {
+            return anInt;
+        }
 
-    public int getAnInt() {
-        return anInt;
-    }
+        public void setAnInt(int anInt) {
+            this.anInt = anInt;
+        }
 
-    public void setAnInt(int anInt) {
-        this.anInt = anInt;
-    }
+        public void setMatrix(Double[][] matrix) {
+            this.matrix = matrix;
+        }
 
-    public void setMatrix(Double[][] matrix) {
-        this.matrix = matrix;
-    }
+        public void setMatrix2(double[][] matrixReloaded) {
+            this.matrix2 = matrixReloaded;
+        }
 
-    public void setMatrix2(double[][] matrixReloaded) {
-        this.matrix2 = matrixReloaded;
+        public Object methodMissing(String name, Object args) {
+            throw new MissingMethodException(name, getClass(), 
InvokerHelper.asArray(args));
+        }
     }
-
 }
-
diff --git a/src/test/groovy/groovy/transform/stc/MethodReferenceTest.groovy 
b/src/test/groovy/groovy/transform/stc/MethodReferenceTest.groovy
index 18f54655a9..b109fa590f 100644
--- a/src/test/groovy/groovy/transform/stc/MethodReferenceTest.groovy
+++ b/src/test/groovy/groovy/transform/stc/MethodReferenceTest.groovy
@@ -19,6 +19,8 @@
 package groovy.transform.stc
 
 import org.junit.jupiter.api.Test
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.ValueSource
 
 import static groovy.test.GroovyAssert.assertScript
 import static groovy.test.GroovyAssert.shouldFail
@@ -1517,41 +1519,39 @@ final class MethodReferenceTest {
     }
 
     // GROOVY-10859
-    @Test
-    void testDynamicMethodSelection() {
-        for (tag in ['@TypeChecked', '@CompileStatic', '@CompileDynamic']) {
-            assertScript shell, """
-                $tag
-                void test() {
-                    def result = [[]].stream().flatMap(List::stream).toList()
-                    assert result.isEmpty()
-                }
+    @ParameterizedTest
+    @ValueSource(strings=['@CompileDynamic','@TypeChecked','@CompileStatic'])
+    void testDynamicMethodSelection(String tag) {
+        assertScript shell, """
+            $tag
+            void test() {
+                def result = [[]].stream().flatMap(List::stream).toList()
+                assert result.isEmpty()
+            }
 
-                test()
-            """
-        }
+            test()
+        """
     }
 
     // GROOVY-10904
-    @Test
-    void testPropertyMethodLocation() {
-        for (tag in ['@TypeChecked', '@CompileStatic', '@CompileDynamic']) {
-            assertScript shell, """
-                $tag
-                class Test {
-                    static class Profile {
-                        String foo, bar
-                    }
+    @ParameterizedTest
+    @ValueSource(strings=['@CompileDynamic','@TypeChecked','@CompileStatic'])
+    void testPropertyMethodLocation(String tag) {
+        assertScript shell, """
+            $tag
+            class Test {
+                static class Profile {
+                    String foo, bar
+                }
 
-                    Map<String, Profile> profiles = [new Profile()].stream()
-                        .collect(Collectors.toMap(Profile::getFoo, 
Function.identity()))
+                Map<String, Profile> profiles = [new Profile()].stream()
+                    .collect(Collectors.toMap(Profile::getFoo, 
Function.identity()))
 
-                    static main(args) {
-                        assert this.newInstance().getProfiles().size() == 1
-                    }
+                static main(args) {
+                    assert this.newInstance().getProfiles().size() == 1
                 }
-            """
-        }
+            }
+        """
     }
 
     // GROOVY-10742, GROOVY-10858

Reply via email to