[
https://issues.apache.org/jira/browse/GROOVY-10856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17642108#comment-17642108
]
Rachel Greenham commented on GROOVY-10856:
------------------------------------------
{quote}Update: Sorry, I misunderstood. {{respondsTo}} is not supposed to throw
and you are saying it is throwing {{{}MethodSelectionException{}}}, correct?
{quote}
Correct
{quote}In your example, if you call {{respondsTo('myMethod', [name: ''])}} does
it give an empty list due to the missing "number" element?
{quote}
No, which feels right to me. It's answering correctly that there's a method
that will take Map, which isn't dependent on the Map having the right contents.
The documentation does say "responds to a method with the given name and
arguments {*}types{*}" (my emphasis) the types, not the values. It feels right
to me that that should fail when the method's actually called, as it is.
I think whether it should do as you describe is a separate question (I'd vote
no fwiw, partly as I want the respondsTo to be quick and happy to let an
inadequately-filled map fail at invoke-time). But it's off-topic here.
This is really just about what specifically happens when it's given a null. If
you give otherwise-wrong parameters, eg: just one of the 42 or 'Arthur' from
the above examples, it - correctly - returns an empty list. and if, eg: you do
respondsTo(42,null) it correctly still returns the canonical method, but null,
alone, specifically, kills it, and seems like it shouldn't.
It should either: catch MethodSelectionException and return an empty list, or
return the map method, as when you just try to call it with null, it's
@NamedVariant's map method that throws an IllegalArgumentException, so
presumably *something's* decided that's the one to call... Either answer could
be argued for (though to me the first would be preferable: if it can't decide,
then neither); it should return *something* though, and not throwing exceptions
it promises not to throw. :)
I'm actually wondering if in my use-case (wrt my preferred solution here) I
shouldn't be using metaClass.getMetaMethod(name, args) instead. It throws the
same exception of course, but doesn't make any promises not to so it's not a
bug that it does. I'm wondering it so much that I wonder why I didn't do that
the first time, and what I've forgotten and should have commented about the
matter... 😅
> MethodSelectionException when calling respondsTo()
> --------------------------------------------------
>
> Key: GROOVY-10856
> URL: https://issues.apache.org/jira/browse/GROOVY-10856
> Project: Groovy
> Issue Type: Bug
> Components: Documentation
> Affects Versions: 4.0.6
> Environment: Seen in Groovy 4.0.6 on Linux x64 with java 17.0.5 and
> MacOS aarch64 in Java 19.0.1. I don't think any of that is significant. 😀
> Reporter: Rachel Greenham
> Priority: Minor
> Attachments: responds-to-issue.groovy
>
>
> if you have a method which takes certain parameters, and annotate it
> {{@NamedVariant}}, and then try a {{respondsTo}} with a null, or an empty
> array, you get this exception, listing both the methods that are there,
> rather than the expected groovy-falsehood (empty list) for no matching
> methods.
> This is related to
> # GROOVY-8248
> # GROOVY-8660
> but is different in scope because this is about the behaviour, specifically,
> of MetaObjectProtocol::respondsTo, which states clearly in the documentation
> that:
> {quote}This method is "safe" in that it will always return a value and never
> throw an exception
> {quote}
> ... which turns out not to be true, and should be. The behaviour may not be
> wrong for the calls described in the other two bugs, but
> {{MetaObjectProtocol::respondsTo}}, specifically, should be catching this,
> and returning, as promised, a groovy falsehood. (probably an empty list,
> which is correct as neither of the methods match.)
> Attached, a small script demonstrating this, which shows the problem clearly
> if simply run in groovy console.
> {code:groovy}
> import groovy.transform.*
> @NamedVariant
> def myMethod(int number, String name) {
> println "number: ${number}; name: ${name}"
> }
> println myMethod(42, 'Arthur')
> println myMethod(name: 'Arthur', number: 42)
> def result1 = respondsTo('myMethod', 42, 'Arthur')
> println "positive match: ${result1}"
> def result2 = respondsTo('myMethod', [number: 42, name: 'Arthur'])
> println "positive match: ${result2}"
> def result3 = respondsTo('myMethod', null)
> // expected an empty list, a groovy-falsehood
> {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)