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