You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2025/05/24 01:11:04 UTC
(groovy) branch GROOVY-11676 created (now 2f0a6feb8e)
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a change to branch GROOVY-11676
in repository https://gitbox.apache.org/repos/asf/groovy.git
at 2f0a6feb8e GROOVY-11676: object expression type in `MethodClosure` error message
This branch includes the following new commits:
new 9adbfdc53c separate class and method within `MissingMethodException` message
new 2f0a6feb8e GROOVY-11676: object expression type in `MethodClosure` error message
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(groovy) 01/02: separate class and method within `MissingMethodException` message
Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-11676
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 9adbfdc53c1909d53fe268e16f51be5470ed3be9
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri May 23 19:39:05 2025 -0500
separate class and method within `MissingMethodException` message
---
.../java/groovy/lang/MissingMethodException.java | 19 +++---
.../test/typing/StaticCompilationIntroTest.groovy | 27 ++++----
.../{Groovy3645Bug.groovy => Groovy3645.groovy} | 24 +++----
.../{Groovy4857Bug.groovy => Groovy4857.groovy} | 35 +++++-----
.../{Groovy6072Bug.groovy => Groovy6072.groovy} | 16 ++---
src/test/groovy/bugs/Groovy8678.groovy | 76 +++++++++++-----------
src/test/groovy/bugs/Groovy9779.groovy | 9 ++-
src/test/groovy/bugs/MethodClosureTest.groovy | 2 +-
src/test/groovy/groovy/ThisAndSuperTest.groovy | 6 +-
.../groovy/groovy/util/BuilderSupportTest.groovy | 62 +++++++++++-------
.../transform/NewifyTransformBlackBoxTest.groovy | 44 ++++---------
11 files changed, 156 insertions(+), 164 deletions(-)
diff --git a/src/main/java/groovy/lang/MissingMethodException.java b/src/main/java/groovy/lang/MissingMethodException.java
index 0400eff438..0efc4d1a46 100644
--- a/src/main/java/groovy/lang/MissingMethodException.java
+++ b/src/main/java/groovy/lang/MissingMethodException.java
@@ -54,16 +54,19 @@ public class MissingMethodException extends GroovyRuntimeException {
@Override
public String getMessage() {
- return "No signature of method: "
- + (isStatic ? "static " : "")
+ Class<?> type = getType();
+ Object[] args = getArguments();
+ return "No signature of "
+ + (isStatic() ? "static " : "")
+ + "method: "
+ + getMethod()
+ + " for class: "
+ (type != null ? type.getName() : "<unknown>")
- + "."
- + method
- + "() is applicable for argument types: ("
- + FormatHelper.toTypeString(arguments, 80)
+ + " is applicable for argument types: ("
+ + FormatHelper.toTypeString(args, 80)
+ ") values: "
- + FormatHelper.toArrayString(arguments, 80, true)
- + (type != null ? MethodRankHelper.getMethodSuggestionString(method, type, arguments) : "");
+ + FormatHelper.toArrayString(args, 80, true)
+ + (type != null ? MethodRankHelper.getMethodSuggestionString(getMethod(), type, args) : "");
}
/**
diff --git a/src/spec/test/typing/StaticCompilationIntroTest.groovy b/src/spec/test/typing/StaticCompilationIntroTest.groovy
index 1fad826411..0f6ba9062b 100644
--- a/src/spec/test/typing/StaticCompilationIntroTest.groovy
+++ b/src/spec/test/typing/StaticCompilationIntroTest.groovy
@@ -18,9 +18,12 @@
*/
package typing
-import groovy.test.GroovyTestCase
+import org.junit.jupiter.api.Test
-class StaticCompilationIntroTest extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
+
+final class StaticCompilationIntroTest {
private static String TYPESAFE_PROGRAM = '''
// tag::intro_typesafe[]
@@ -66,7 +69,7 @@ class StaticCompilationIntroTest extends GroovyTestCase {
private static final String RUN = '''
test()
-'''
+ '''
private static final String RUNTIME_MAGIC = '''
// tag::intro_typesafe_magic[]
@@ -74,23 +77,19 @@ class StaticCompilationIntroTest extends GroovyTestCase {
// end::intro_typesafe_magic[]
'''
+ @Test
void testTypeSafeProgram() {
- def shell = new GroovyShell()
- shell.evaluate(TYPESAFE_PROGRAM+RUN)
+ assertScript(TYPESAFE_PROGRAM+RUN)
}
+ @Test
void testTypeSafeProgramBroken() {
- def shell = new GroovyShell()
- try {
- shell.evaluate(TYPESAFE_PROGRAM+RUNTIME_MAGIC+RUN)
- assert false
- } catch (MissingMethodException e) {
- assert e.message.contains('No signature of method: Computer.compute() is applicable for argument types: (Date)')
- }
+ def e = shouldFail(MissingMethodException, TYPESAFE_PROGRAM+RUNTIME_MAGIC+RUN)
+ assert e.message.contains('No signature of method: compute for class: Computer is applicable for argument types: (Date)')
}
+ @Test
void testTypeSafeProgramFixedWithCompileStatic() {
- def shell = new GroovyShell()
- shell.evaluate(TYPESAFE_COMPILESTATIC_PROGRAM+RUNTIME_MAGIC+RUN)
+ assertScript(TYPESAFE_COMPILESTATIC_PROGRAM+RUNTIME_MAGIC+RUN)
}
}
diff --git a/src/test/groovy/bugs/Groovy3645Bug.groovy b/src/test/groovy/bugs/Groovy3645.groovy
similarity index 68%
rename from src/test/groovy/bugs/Groovy3645Bug.groovy
rename to src/test/groovy/bugs/Groovy3645.groovy
index 18122d92ca..e64919f022 100644
--- a/src/test/groovy/bugs/Groovy3645Bug.groovy
+++ b/src/test/groovy/bugs/Groovy3645.groovy
@@ -18,20 +18,20 @@
*/
package bugs
-import groovy.test.GroovyTestCase
+import org.junit.jupiter.api.Test
-class Groovy3645Bug extends GroovyTestCase {
+import static groovy.test.GroovyAssert.shouldFail
+
+final class Groovy3645 {
+ @Test
void testMethodCallOnSuperInAStaticMethod() {
- try{
- assertScript """
- class Foo3645 {
- static main(args) {
- super.bar()
- }
+ def err = shouldFail MissingMethodException, '''
+ class Foo3645 {
+ static main(args) {
+ super.bar()
}
- """
- } catch(MissingMethodException ex) {
- assertTrue ex.message.contains("No signature of method: static java.lang.Object.bar()")
- }
+ }
+ '''
+ assert err.message.contains('No signature of static method: bar for class: java.lang.Object')
}
}
diff --git a/src/test/groovy/bugs/Groovy4857Bug.groovy b/src/test/groovy/bugs/Groovy4857.groovy
similarity index 60%
rename from src/test/groovy/bugs/Groovy4857Bug.groovy
rename to src/test/groovy/bugs/Groovy4857.groovy
index 4ce7126b47..f20d377a01 100644
--- a/src/test/groovy/bugs/Groovy4857Bug.groovy
+++ b/src/test/groovy/bugs/Groovy4857.groovy
@@ -18,36 +18,35 @@
*/
package bugs
-import groovy.test.GroovyTestCase
+import org.junit.jupiter.api.Test
-class Groovy4857Bug extends GroovyTestCase {
+import static groovy.test.GroovyAssert.shouldFail
+
+final class Groovy4857 {
+
+ @Test
void testMissingMethodNotUnsupportedOperation() {
- try {
- new GroovyShell().evaluate """
- interface A { def getValue() }
+ def err = shouldFail MissingMethodException, '''
+ interface A { def getValue() }
- class B { }
+ class B { }
- def test = [ getValue: { 'getValue() called' } ] as A
+ def test = [ getValue: { 'getValue() called' } ] as A
- def b = new B()
+ def b = new B()
- b.call(test)
- """
- fail('The compilation should have failed with No signature of method: B.call()')
- } catch (e) {
- assert e.message.contains('No signature of method: B.call()')
- assert e.class.name == 'groovy.lang.MissingMethodException'
- }
+ b.call(test)
+ '''
+ assert err.message.contains('No signature of method: call for class: B')
}
+ @Test
void testTrygveAmundsensExample() {
- def val = new GroovyShell().evaluate """
+ def val = new GroovyShell().evaluate '''
[run: {}] as Runnable
- """
+ '''
assert val.toString()
assert val instanceof Runnable
}
}
-
diff --git a/src/test/groovy/bugs/Groovy6072Bug.groovy b/src/test/groovy/bugs/Groovy6072.groovy
similarity index 81%
rename from src/test/groovy/bugs/Groovy6072Bug.groovy
rename to src/test/groovy/bugs/Groovy6072.groovy
index ae23c34516..058f02c883 100644
--- a/src/test/groovy/bugs/Groovy6072Bug.groovy
+++ b/src/test/groovy/bugs/Groovy6072.groovy
@@ -18,16 +18,19 @@
*/
package bugs
-import groovy.test.GroovyTestCase
+import org.junit.jupiter.api.Test
-class Groovy6072Bug extends GroovyTestCase {
+import static groovy.test.GroovyAssert.shouldFail
+
+final class Groovy6072 {
+ @Test
void testShouldNotChangeBinExpToClassExp() {
- assertScript '''import groovy.transform.ASTTest
+ def err = shouldFail MissingMethodException, '''
+ import groovy.transform.ASTTest
import org.codehaus.groovy.ast.expr.BinaryExpression
class OhNo {}
- try {
@ASTTest(phase=CANONICALIZATION, value={
def right = node.rightExpression
assert right instanceof BinaryExpression
@@ -39,10 +42,7 @@ class Groovy6072Bug extends GroovyTestCase {
assert right instanceof BinaryExpression
})
def expr2 = OhNo | []
- } catch (MissingMethodException ex) {
- assert ex.message.contains('or()')
- // alright, what we wanted to test has gone
- }
'''
+ assert err.message.contains('No signature of static method: or for class: OhNo')
}
}
diff --git a/src/test/groovy/bugs/Groovy8678.groovy b/src/test/groovy/bugs/Groovy8678.groovy
index 87564a6d53..6a763527b9 100644
--- a/src/test/groovy/bugs/Groovy8678.groovy
+++ b/src/test/groovy/bugs/Groovy8678.groovy
@@ -18,7 +18,7 @@
*/
package bugs
-import org.junit.Test
+import org.junit.jupiter.api.Test
import static groovy.test.GroovyAssert.assertScript
import static groovy.test.GroovyAssert.shouldFail
@@ -79,87 +79,86 @@ final class Groovy8678 {
@Test
void testMissingPropertyOrMethod() {
def x = new WithMethods()
- def throwable = shouldFail () -> x.'42'
- assert throwable.class == MissingPropertyException.class
+
+ def throwable = shouldFail(MissingPropertyException) { x.'42' }
assert throwable.message.startsWith('No such property: 42 for class: bugs.Groovy8678$WithMethods')
- throwable = shouldFail () -> x.'42d'
- assert throwable.class == MissingPropertyException.class
+
+ throwable = shouldFail(MissingPropertyException) { x.'42d' }
assert throwable.message.startsWith('No such property: 42d for class: bugs.Groovy8678$WithMethods')
- throwable = shouldFail () -> x.'84'()
- assert throwable.class == MissingMethodException.class
- assert throwable.message.startsWith('No signature of method: bugs.Groovy8678$WithMethods.84() is applicable for argument types: () values: []')
- throwable = shouldFail () -> x.'84f'()
- assert throwable.class == MissingMethodException.class
- assert throwable.message.startsWith('No signature of method: bugs.Groovy8678$WithMethods.84f() is applicable for argument types: () values: []')
+
+ throwable = shouldFail(MissingMethodException) { x.'84'() }
+ assert throwable.message.startsWith('No signature of method: 84 for class: bugs.Groovy8678$WithMethods is applicable for argument types: () values: []')
+
+ throwable = shouldFail(MissingMethodException) { x.'84f'() }
+ assert throwable.message.startsWith('No signature of method: 84f for class: bugs.Groovy8678$WithMethods is applicable for argument types: () values: []')
}
@Test
- @SuppressWarnings("all")
void testCompilationFailure() {
shouldNotCompile('\'42\'', '\'FortyTwo\'', '42',
// after GROOVY-8678
- cls -> cls == MissingMethodException.class,
- msg -> msg.startsWith('No signature of method: WithMethods.call() is applicable for argument types: (BigDecimal) values: [0.42]'))
+ MissingMethodException,
+ msg -> msg.startsWith('No signature of method: call for class: WithMethods is applicable for argument types: (BigDecimal) values: [0.42]'))
// before GROOVY-8678
- // cls -> cls == MultipleCompilationErrorsException.class,
+ // MultipleCompilationErrorsException,
// msg -> msg.contains('Unexpected input: \'x.42\''))
shouldNotCompile('\'42\'', '\'FortyTwo\'', '42()',
// after GROOVY-8678
- cls -> cls == MissingMethodException.class,
- msg -> msg.startsWith('No signature of method: java.math.BigDecimal.call() is applicable for argument types: () values: []'))
+ MissingMethodException,
+ msg -> msg.startsWith('No signature of method: call for class: java.math.BigDecimal is applicable for argument types: () values: []'))
// before GROOVY-8678
- // cls -> cls == MultipleCompilationErrorsException.class,
+ // MultipleCompilationErrorsException,
// msg -> msg.contains('Unexpected input: \'x.42\''))
shouldNotCompile('\'42d\'', '\'FortyTwo\'', '42d',
// after GROOVY-8678
- cls -> cls == MissingMethodException.class,
- msg -> msg.startsWith('No signature of method: WithMethods.call() is applicable for argument types: (Double) values: [0.42]'))
+ MissingMethodException,
+ msg -> msg.startsWith('No signature of method: call for class: WithMethods is applicable for argument types: (Double) values: [0.42]'))
// before GROOVY-8678
- // cls -> cls == MultipleCompilationErrorsException.class,
+ // MultipleCompilationErrorsException,
// msg -> msg.contains('Unexpected input: \'x.42d\''))
shouldNotCompile('\'42d\'', '\'FortyTwo\'', '42d()',
// after GROOVY-8678
- cls -> cls == MissingMethodException.class,
- msg -> msg.startsWith('No signature of method: java.lang.Double.call() is applicable for argument types: () values: []'))
+ MissingMethodException,
+ msg -> msg.startsWith('No signature of method: call for class: java.lang.Double is applicable for argument types: () values: []'))
// before GROOVY-8678
- // cls -> cls == MultipleCompilationErrorsException.class,
+ // MultipleCompilationErrorsException,
// msg -> msg.contains('Unexpected input: \'x.42d\''))
shouldNotCompile('get84', '\'EightyFour\'', '84',
// after GROOVY-8678
- cls -> cls == MissingMethodException.class,
- msg -> msg.startsWith('No signature of method: WithMethods.call() is applicable for argument types: (BigDecimal) values: [0.84]'))
+ MissingMethodException,
+ msg -> msg.startsWith('No signature of method: call for class: WithMethods is applicable for argument types: (BigDecimal) values: [0.84]'))
// before GROOVY-8678
- // cls -> cls == MultipleCompilationErrorsException.class,
+ // MultipleCompilationErrorsException,
// msg -> msg.contains('Unexpected input: \'x.84\''))
shouldNotCompile('get84', '\'EightyFour\'', '84()',
// after GROOVY-8678
- cls -> cls == MissingMethodException.class,
- msg -> msg.startsWith('No signature of method: java.math.BigDecimal.call() is applicable for argument types: () values: []'))
+ MissingMethodException,
+ msg -> msg.startsWith('No signature of method: call for class: java.math.BigDecimal is applicable for argument types: () values: []'))
// before GROOVY-8678
- // cls -> cls == MultipleCompilationErrorsException.class,
+ // MultipleCompilationErrorsException,
// msg -> msg.contains('Unexpected input: \'x.84\''))
shouldNotCompile('get84f', '\'EightyFourEff\'', '84f',
// after GROOVY-8678
- cls -> cls == MissingMethodException.class,
- msg -> msg.startsWith('No signature of method: WithMethods.call() is applicable for argument types: (Float) values: [0.84]'))
+ MissingMethodException,
+ msg -> msg.startsWith('No signature of method: call for class: WithMethods is applicable for argument types: (Float) values: [0.84]'))
// before GROOVY-8678
- // cls -> cls == MultipleCompilationErrorsException.class,
+ // MultipleCompilationErrorsException,
// msg -> msg.contains('Unexpected input: \'x.84f\''))
shouldNotCompile('get84f', '\'EightyFourEff\'', '84f()',
// after GROOVY-8678
- cls -> cls == MissingMethodException.class,
- msg -> msg.startsWith('No signature of method: java.lang.Float.call() is applicable for argument types: () values: []'))
+ MissingMethodException,
+ msg -> msg.startsWith('No signature of method: call for class: java.lang.Float is applicable for argument types: () values: []'))
// before GROOVY-8678
- // cls -> cls == MultipleCompilationErrorsException.class,
+ // MultipleCompilationErrorsException,
// msg -> msg.contains('Unexpected input: \'x.84f\''))
}
private static void shouldNotCompile(String methodName,
String returnValue,
String expression,
- Closure<Class<? extends Exception>> exceptionAssertion,
+ Class<? extends Exception> exceptionType,
Closure<String> messageAssertion) {
- def throwable = shouldFail """
+ def throwable = shouldFail exceptionType, """
class WithMethods {
def ${methodName}() {
${returnValue}
@@ -168,7 +167,6 @@ final class Groovy8678 {
def x = new WithMethods()
x.${expression}
""".stripIndent()
- assert exceptionAssertion(throwable.class)
assert messageAssertion(throwable.message)
}
diff --git a/src/test/groovy/bugs/Groovy9779.groovy b/src/test/groovy/bugs/Groovy9779.groovy
index 64e2506e79..5edc308f24 100644
--- a/src/test/groovy/bugs/Groovy9779.groovy
+++ b/src/test/groovy/bugs/Groovy9779.groovy
@@ -18,14 +18,13 @@
*/
package bugs
-import groovy.transform.CompileStatic
-import org.junit.Test
+import org.junit.jupiter.api.Test
import static groovy.test.GroovyAssert.assertScript
import static groovy.test.GroovyAssert.shouldFail
-@CompileStatic
final class Groovy9779 {
+
@Test
void testCallOperatorOnDynamicProperties1() {
assertScript '''
@@ -73,7 +72,7 @@ final class Groovy9779 {
}
C.x()
'''
- assert err.message.contains('No signature of method: B.call() is applicable')
+ assert err.message.contains('No signature of method: call for class: B is applicable')
}
@Test // don't chain call properties together
@@ -90,7 +89,7 @@ final class Groovy9779 {
}
assert new C() + 1 == 42
'''
- assert err.message.contains('No signature of method: C.plus() is applicable')
+ assert err.message.contains('No signature of method: plus for class: C is applicable')
}
@Test
diff --git a/src/test/groovy/bugs/MethodClosureTest.groovy b/src/test/groovy/bugs/MethodClosureTest.groovy
index a61ed18f41..471df3ac35 100644
--- a/src/test/groovy/bugs/MethodClosureTest.groovy
+++ b/src/test/groovy/bugs/MethodClosureTest.groovy
@@ -19,7 +19,7 @@
package bugs
import org.codehaus.groovy.runtime.MethodClosure
-import org.junit.Test
+import org.junit.jupiter.api.Test
import static groovy.test.GroovyAssert.assertScript
import static groovy.test.GroovyAssert.shouldFail
diff --git a/src/test/groovy/groovy/ThisAndSuperTest.groovy b/src/test/groovy/groovy/ThisAndSuperTest.groovy
index b6efb04651..a0d5bdb570 100644
--- a/src/test/groovy/groovy/ThisAndSuperTest.groovy
+++ b/src/test/groovy/groovy/ThisAndSuperTest.groovy
@@ -19,7 +19,7 @@
package groovy
import groovy.test.NotYetImplemented
-import org.junit.Test
+import org.junit.jupiter.api.Test
import static groovy.test.GroovyAssert.assertScript
import static groovy.test.GroovyAssert.shouldFail
@@ -235,7 +235,7 @@ final class ThisAndSuperTest {
}
new C().test()
'''
- assert err =~ /No signature of method: java\.lang\.Object\.whatever\(\) is applicable for argument types: \(\) values: \[\]/
+ assert err =~ /No signature of method: whatever for class: java\.lang\.Object is applicable for argument types: \(\) values: \[\]/
}
// GROOVY-9615
@@ -254,7 +254,7 @@ final class ThisAndSuperTest {
}
new Outer.Inner(new Outer()).test()
'''
- assert err =~ /No signature of method: java\.lang\.Object\.whatever\(\) is applicable for argument types: \(\) values: \[\]/
+ assert err =~ /No signature of method: whatever for class: java\.lang\.Object is applicable for argument types: \(\) values: \[\]/
}
// GROOVY-6001
diff --git a/src/test/groovy/groovy/util/BuilderSupportTest.groovy b/src/test/groovy/groovy/util/BuilderSupportTest.groovy
index 8011e2ddd4..a11070e8dc 100644
--- a/src/test/groovy/groovy/util/BuilderSupportTest.groovy
+++ b/src/test/groovy/groovy/util/BuilderSupportTest.groovy
@@ -18,24 +18,29 @@
*/
package groovy.util
-import groovy.test.GroovyTestCase
+import org.junit.jupiter.api.Test
+
+import static groovy.test.GroovyAssert.shouldFail
/**
* Testing BuilderSupport and reveal how calling methods on it result in implementation callbacks.
* Using the SpoofBuilder (see below) to call it in various ways and analyze the "spoofed" logs.
* This is especially useful when designing subclasses of BuilderSupport.
*/
-class BuilderSupportTest extends GroovyTestCase{
+final class BuilderSupportTest {
+
+ @Test
void testSimpleNode() {
def b = new SpoofBuilder()
assert b.log == []
def node = b.foo()
assert b.log == [ 'create_with_name','foo',
- 'node_completed',null, node,
+ 'node_completed',null, node,
'post_node_completion',null, node
]
}
+ @Test
void testSimpleNodeWithValue() {
def b = new SpoofBuilder()
def node = b.foo('value')
@@ -45,17 +50,19 @@ class BuilderSupportTest extends GroovyTestCase{
]
}
+ @Test
void testSimpleNodeWithOneAttribute() {
def b = new SpoofBuilder()
def node = b.foo(name:'value')
assert b.log == [
- 'create_with_name_and_map','foo',
- 'name','value',
+ 'create_with_name_and_map','foo',
+ 'name','value',
'node_completed',null,'x',
'post_node_completion',null, 'x'
]
}
+ @Test
void testSimpleNodeWithClosure() {
def b = new SpoofBuilder()
b.foo(){
@@ -72,66 +79,75 @@ class BuilderSupportTest extends GroovyTestCase{
]
}
+ @Test
void testSimpleNodeWithOneAttributeAndValue() {
def b = new SpoofBuilder()
def node = b.foo(bar:'baz', 'value')
assert b.log == [
- 'create_with_name_map_and_value', 'foo', 'bar', 'baz','value',
+ 'create_with_name_map_and_value', 'foo', 'bar', 'baz','value',
'node_completed',null,node,
'post_node_completion',null, node
]
}
+ @Test
void testSimpleNodeWithValueAndOneAttribute() {
def b = new SpoofBuilder()
def node = b.foo('value', bar:'baz')
assert b.log == [
- 'create_with_name_map_and_value', 'foo', 'bar', 'baz','value',
+ 'create_with_name_map_and_value', 'foo', 'bar', 'baz','value',
'node_completed',null,node,
'post_node_completion',null, node
]
}
+ @Test
void testSimpleNodeWithOneAttributeAndValueAndClosure() {
def b = new SpoofBuilder()
def node = b.foo(bar:'baz', 'value') { 1 }
assert b.log == [
- 'create_with_name_map_and_value', 'foo', 'bar', 'baz','value',
+ 'create_with_name_map_and_value', 'foo', 'bar', 'baz','value',
'node_completed',null,node,
'post_node_completion',null, node
]
}
+ @Test
void testSimpleNodeWithValueAndOneAttributeAndClosure() {
def b = new SpoofBuilder()
def node = b.foo('value', bar:'baz') { 1 }
assert b.log == [
- 'create_with_name_map_and_value', 'foo', 'bar', 'baz','value',
+ 'create_with_name_map_and_value', 'foo', 'bar', 'baz','value',
'node_completed',null,node,
'post_node_completion',null, node
]
}
+ @Test
void testSimpleNodeTwoValues() {
def b = new SpoofBuilder()
shouldFail(MissingMethodException, {def node = b.foo('arg1', 'arg2')})
}
+ @Test
void testSimpleNodeTwoValuesClosure() {
def b = new SpoofBuilder()
shouldFail(MissingMethodException, {def node = b.foo('arg1', 'arg2') { 1 } })
}
+ @Test
void testSimpleNodeThreeValues() {
def b = new SpoofBuilder()
shouldFail(MissingMethodException, {def node = b.foo('arg1', 'arg2', 'arg3') })
}
+ @Test
void testSimpleNodeFourValues() {
def b = new SpoofBuilder()
shouldFail(MissingMethodException, {def node = b.foo('arg1', 'arg2', 'arg3', 'arg4') })
}
+ @Test
void testNestedMethodCallsResolution() {
def b = new SpoofBuilder()
b.outest {
@@ -139,7 +155,7 @@ class BuilderSupportTest extends GroovyTestCase{
nestedBuilderCall(b)
}
}
- assert b.log.contains('inner')
+ assert b.log.contains('inner')
}
void nestedBuilderCall(builder) {
@@ -147,49 +163,50 @@ class BuilderSupportTest extends GroovyTestCase{
}
// GROOVY-3341
+ @Test
void testSimpleNodeWithClosureThatThrowsAMissingMethodException() {
def builder = new SpoofBuilder()
- String errorMessage = shouldFail(MissingMethodException, {
+ String errorMessage = shouldFail(MissingMethodException) {
builder.a {
b {
error('xy'.foo())
}
}
- })
- assert errorMessage.contains('No signature of method: java.lang.String.foo()')
+ }
+ assert errorMessage.contains('No signature of method: foo for class: java.lang.String')
}
}
/**
- The SpoofBuilder is a sample instance of the abstract BuilderSupport class
- that does nothing but logging how it was called, returning 'x' for each node.
-**/
-class SpoofBuilder extends BuilderSupport{
+ * The SpoofBuilder is a sample instance of the abstract BuilderSupport class
+ * that does nothing but logging how it was called, returning 'x' for each node.
+ */
+class SpoofBuilder extends BuilderSupport {
def log = []
- protected void setParent(Object parent, Object child){
+ protected void setParent(Object parent, Object child) {
log << "set_parent"
log << parent
log << child
}
- protected Object createNode(Object name){
+ protected Object createNode(Object name) {
log << 'create_with_name'
log << name
return 'x'
}
- protected Object createNode(Object name, Object value){
+ protected Object createNode(Object name, Object value) {
log << 'create_with_name_and_value'
log << name
log << value
return 'x'
}
- protected Object createNode(Object name, Map attributes){
+ protected Object createNode(Object name, Map attributes) {
log << 'create_with_name_and_map'
log << name
attributes.each{entry -> log << entry.key; log << entry.value}
return 'x'
}
- protected Object createNode(Object name, Map attributes, Object value){
+ protected Object createNode(Object name, Map attributes, Object value) {
log << 'create_with_name_map_and_value'
log << name
attributes.each{entry -> log << entry.key; log << entry.value}
@@ -201,7 +218,6 @@ class SpoofBuilder extends BuilderSupport{
log << parent
log << node
}
-
protected Object postNodeCompletion(Object parent, Object node) {
log << 'post_node_completion'
log << parent
diff --git a/src/test/groovy/org/codehaus/groovy/transform/NewifyTransformBlackBoxTest.groovy b/src/test/groovy/org/codehaus/groovy/transform/NewifyTransformBlackBoxTest.groovy
index f75213be09..0b8ad37883 100644
--- a/src/test/groovy/org/codehaus/groovy/transform/NewifyTransformBlackBoxTest.groovy
+++ b/src/test/groovy/org/codehaus/groovy/transform/NewifyTransformBlackBoxTest.groovy
@@ -18,18 +18,15 @@
*/
package org.codehaus.groovy.transform
-import gls.CompilableTestSupport
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
+import org.junit.jupiter.api.Test
-import java.util.Map.Entry
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
/**
* Tests for the {@code @Newify} AST transform.
*/
-@RunWith(JUnit4)
-class NewifyTransformBlackBoxTest extends CompilableTestSupport {
+final class NewifyTransformBlackBoxTest {
@Test
void testNewifyWithoutNamePattern() {
@@ -57,11 +54,10 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
assertScript(script0)
- final result = shouldNotCompile(script1)
- assert result.contains("Cannot find matching method NewifyFoo#AB(java.lang.String)")
+ final result = shouldFail(script1)
+ assert result =~ "Cannot find matching method NewifyFoo#AB\\(java.lang.String\\)"
}
-
@Test
void testRegularClassNewifyWithNamePattern() {
final String script = """
@@ -93,7 +89,6 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
assert result.toString() == 'abc_123_13'
}
-
@Test
void testInnerScriptClassNewifyWithNamePattern() {
final String script = """
@@ -124,7 +119,6 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
assert resultList[1] == ['A(2018-04-08)', 'AB(I am, class AB)', 'ABC(A, B, C)']
}
-
@Test
void testInnerClassesNewifyWithNamePattern() {
final String script = """
@@ -158,7 +152,6 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
assert resultList[1] == ['Foo$A(2018-04-08)', 'Foo$AB(I am, class AB)', 'Foo$ABC(A, B, C)']
}
-
@Test
void testInnerStaticClassesNewifyWithNamePattern() {
final String script = """
@@ -191,7 +184,6 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
assert resultList[1] == ['Foo$A(2018-04-08)', 'Foo$AB(I am, class AB)', 'Foo$ABC(A, B, C)']
}
-
@Test
void testAmbiguousInnerStaticClassesNewifyWithNamePatternFails() {
final String script = """
@@ -216,11 +208,10 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
println "script=|$script|"
- final String result = shouldNotCompile(script)
+ final String result = shouldFail(script)
assert result ==~ '(?s).*Inner class name lookup is ambiguous between the following classes: Foo, Foo\\$Foo, Foo\\$Foo\\$Foo\\..*'
}
-
@Test
void testImportedClassesNewifyWithNamePattern() {
final String script = """
@@ -252,7 +243,6 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
assert resultList[1] == ['A(2018-04-08)', '*lol*', 'AB(I am, class AB)', 'ABC(A, B, C)']
}
-
@Test
void testAlwaysExistingClassesNewifyWithNamePattern() {
final String script = """
@@ -284,7 +274,6 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
assert resultList[1] == ['A(2018-04-08)', '*lol*', 'AB(I am, class AB)', 'ABC(A, B, C)', 'java.lang.Object']
}
-
@Test
void testNewifyWithNamePatternMixed() {
final String script = """
@@ -329,7 +318,6 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
]
}
-
@Test
void testAliasImportedClassesNewifyWithNamePattern() {
final String script = """
@@ -354,7 +342,6 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
assert resultList[1] == ['Discrete Reality']
}
-
@Test
void testAliasShadowededImportedClassesNewifyWithNamePatternFails() {
final String script = """
@@ -375,11 +362,10 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
println "script=|$script|"
- final String result = shouldNotCompile(script)
+ final String result = shouldFail(script)
assert result ==~ /(?s).*\[Static type checking] - Cannot find matching method TestScript[A-Za-z0-9]*#StringBuilder\(java\.lang\.String\).*/
}
-
@Test
void testInvalidNamePatternNewifyWithNamePatternFails() {
final String script = """
@@ -400,11 +386,10 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
println "script=|$script|"
- final String result = shouldNotCompile(script)
+ final String result = shouldFail(script)
assert result ==~ /(?s).*Invalid class name pattern: Illegal character range near index 3.*/
}
-
@Test
void testStaticallyAndDynamicallyCompiledMixedClassesNewifyWithNamePattern() {
final List<Boolean> compileStaticFlags = [true]
@@ -433,7 +418,6 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
assertMixedClassesNewifyWithNamePatternFails("@Newify(pattern=/XXX/)", [false], standardCompileDynamiccErrorMsg)
}
-
@Test
void testExtractName() {
['', 'A', 'Bc', 'DEF'].each { String s ->
@@ -446,9 +430,8 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
}
}
-
String getStandardCompileDynamiccErrorMsg() {
- "No signature of method: Foo.A() is applicable for argument types: (String) values: [2018-04-08]"
+ "No signature of method: A for class: Foo is applicable for argument types: (String) values: [2018-04-08]"
}
String getStandardCompileStaticErrorMsg() {
@@ -513,14 +496,12 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
return resultList
}
-
void assertExtractName(final String s, final String expected) {
final String result = NewifyASTTransformation.extractName(s)
println "|$s| -> |$result|"
assert result == expected
}
-
String classCode(final List<String> lines) { code(lines, 1) }
String scriptCode(final List<String> lines) { code(lines, 0) }
@@ -534,7 +515,7 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
final Map<String, Object> annotationParameters,
final String classPart, final String scriptPart = '') {
assert !hasAnnotation || (annotationParameters != null); assert classPart
- final String annotationParametersTerm = annotationParameters ? "(${annotationParameters.collect { final Entry<String, Object> e -> "$e.key=$e.value" }.join(', ')})" : ''
+ final String annotationParametersTerm = annotationParameters ? "(${annotationParameters.collect { final Map.Entry<String, Object> e -> "$e.key=$e.value" }.join(', ')})" : ''
final String script = """
import groovy.transform.Canonical
import groovy.transform.CompileStatic
@@ -560,13 +541,11 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
'NewifyFoo'
}
-
static def evalScript(final String script) throws Exception {
GroovyShell shell = new GroovyShell();
shell.evaluate(script);
}
-
static Throwable compileShouldThrow(final String script, final String testClassName) {
try {
final GroovyClassLoader gcl = new GroovyClassLoader()
@@ -577,5 +556,4 @@ class NewifyTransformBlackBoxTest extends CompilableTestSupport {
}
throw new Exception("Script was expected to throw here!")
}
-
}
(groovy) 02/02: GROOVY-11676: object expression type in `MethodClosure` error message
Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY-11676
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 2f0a6feb8ecee496f47a010d1832d5b0421a4a5f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri May 23 19:41:44 2025 -0500
GROOVY-11676: object expression type in `MethodClosure` error message
---
src/main/java/groovy/lang/MetaClassImpl.java | 8 +++++++-
src/test/groovy/bugs/MethodClosureTest.groovy | 8 +++++---
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/main/java/groovy/lang/MetaClassImpl.java b/src/main/java/groovy/lang/MetaClassImpl.java
index 445c018675..d2c6905148 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -1062,7 +1062,13 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
} catch (MissingMethodException ignore) {}
}
- return invokeMissingMethod(closure, method, arguments);
+ try {
+ return invokeMissingMethod(closure, method, arguments);
+ } catch (MissingMethodException mme) { // GROOVY-11676: owner class
+ mme = new MissingMethodException(method, ownerClass, arguments);
+ mme.addSuppressed(e);
+ throw mme;
+ }
}
}
}
diff --git a/src/test/groovy/bugs/MethodClosureTest.groovy b/src/test/groovy/bugs/MethodClosureTest.groovy
index 471df3ac35..1fe74659df 100644
--- a/src/test/groovy/bugs/MethodClosureTest.groovy
+++ b/src/test/groovy/bugs/MethodClosureTest.groovy
@@ -81,7 +81,7 @@ final class MethodClosureTest {
'''
}
- // GROOVY-9140
+ // GROOVY-9140, GROOVY-11676
@Test
void testMethodClosureWithoutThis() {
String base = '''
@@ -96,13 +96,15 @@ final class MethodClosureTest {
assert result == 11
'''
- shouldFail MissingMethodException, base + '''
+ def err = shouldFail MissingMethodException, base + '''
closure()
'''
+ assert err =~ /No signature of method: m for class: C is applicable for argument types: \(\) values: \[\]/
- shouldFail MissingMethodException, base + '''
+ /**/err = shouldFail MissingMethodException, base + '''
closure("")
'''
+ assert err =~ /No signature of method: m for class: C is applicable for argument types: \(String\) values: \[\]/
}
@Test