[jira] [Commented] (GROOVY-10856) MethodSelectionException when calling respondsTo()

2022-12-01 Thread Rachel Greenham (Jira)


[ 
https://issues.apache.org/jira/browse/GROOVY-10856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=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)


[jira] [Created] (GROOVY-10856) MethodSelectionException when calling respondsTo()

2022-11-24 Thread Rachel Greenham (Jira)
Rachel Greenham created GROOVY-10856:


 Summary: 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
 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.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)


[jira] [Updated] (GROOVY-10304) XmlSlurper failing to handle namespaces

2021-10-13 Thread Rachel Greenham (Jira)


 [ 
https://issues.apache.org/jira/browse/GROOVY-10304?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Rachel Greenham updated GROOVY-10304:
-
Description: 
I would love to be told how I'm doing this wrong. :D 

My ultimate goal here is to use XmlSlurper on a StreamingSAXBuilder to prepare 
a document in a standard way, then modify it, without having to render it to an 
intermediate file or a large string in memory. I think I've narrowed the main 
problem down to XmlSlurper, although there are other issues with 
StreamingSAXBuilder. But it seems so basic, such a non-unusual thing to do that 
I feel sure it's just me doing it wrong...

Try the following in groovyConsole:

 
{code:groovy}
import groovy.xml.*
def src = '''
 hello

'''
def xml = new XmlSlurper()
def gpr = xml.parseText(src)
def serialized = XmlUtil.serialize(gpr)
println serialized
assert serialized == src
{code}
 

The assertion fails:
{noformat}
groovy> import groovy.xml.* 
groovy> def src = ''' 
groovy>   hello 
groovy>  
groovy> ''' 
groovy> def xml = new XmlSlurper() 
groovy> def gpr = xml.parseText(src) 
groovy> def serialized = XmlUtil.serialize(gpr) 
groovy> println serialized 
groovy> assert serialized == src 
 

  hello


Exception thrown

Assertion failed: 

assert serialized == src
   |  |  |
   |  |  '\n  hello\n\n'
   |  false
   '\n  hello\n\n'

at ConsoleScript49.run(ConsoleScript49:11)
at jdk.internal.reflect.GeneratedMethodAccessor78.invoke(Unknown Source)
at 
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

{noformat}
What's with all the "tag0"?

I have a forked XmlSlurper and slurpersupport.Node that I'm currently using to 
work around the above problem. But it doesn't solve the one below. And I'm sure 
it's the wrong approach anyway.

It gets worse if actually trying to slurp a StreamingSAXBuilder directly:

 
{code:groovy}
import groovy.xml.*
def expected = '''
 hello

'''
def doc = new StreamingSAXBuilder().bind {
 mkp.declareNamespace('': 'uri:urn')
 outer {
 inner 'hello'
 }
}
def xml = new XmlSlurper()
doc(xml)
def gpr = xml.document
def serialized = XmlUtil.serialize(gpr)
println serialized
assert serialized == expected
{code}
 

gives the output:
{noformat}
groovy> import groovy.xml.* 
groovy> def expected = ''' 
groovy>   hello 
groovy>  
groovy> ''' 
groovy> def doc = new StreamingSAXBuilder().bind { 
groovy> mkp.declareNamespace('': 'uri:urn') 
groovy> outer { 
groovy> inner 'hello' 
groovy> } 
groovy> } 
groovy> def xml = new XmlSlurper() 
groovy> doc(xml) 
groovy> def gpr = xml.document 
groovy> def serialized = XmlUtil.serialize(gpr) 
groovy> println serialized 
groovy> assert serialized == expected 
 
[Fatal Error] :2:70: The prefix "xmlns" cannot be bound to any namespace 
explicitly; neither can the namespace for "xmlns" be bound to any prefix 
explicitly.
Exception thrown

groovy.lang.GroovyRuntimeException: org.xml.sax.SAXParseException; lineNumber: 
2; columnNumber: 70; The prefix "xmlns" cannot be bound to any namespace 
explicitly; neither can the namespace for "xmlns" be bound to any prefix 
explicitly.
at ConsoleScript0.run(ConsoleScript0:16)
at jdk.internal.reflect.GeneratedMethodAccessor78.invoke(Unknown Source)
at 
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
{noformat}
It's not super-clear from the above but the error is thrown inside 
XmlUtil::serialize. The top of the stack trace from running it in my forked 
version (useful maybe for the XmlUtil line numbers, as XmlUtil has *not* been 
forked here:


{noformat}
groovy.lang.GroovyRuntimeException: org.xml.sax.SAXParseException; lineNumber: 
2; columnNumber: 70; The prefix "xmlns" cannot be bound to any namespace 
explicitly; neither can the namespace for "xmlns" be bound to any prefix 
explicitly.
at groovy.xml.XmlUtil.serialize(XmlUtil.java:475)
at groovy.xml.XmlUtil.serialize(XmlUtil.java:461)
at groovy.xml.XmlUtil.serialize(XmlUtil.java:191)
at groovy.xml.XmlUtil.serialize(XmlUtil.java:160)
at 
org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:318)
at 
uk.co.merus.groovy.xml.XmlSlurperTest.testSlurpingFromSAXBuilderWithNamespace(XmlSlurperTest.groovy:306)

{noformat}


Possibly-relevant old bug: GROOVY-5879, however while in my forked version of 
StreamingSAXBuilder I tried porting in the fix applied in that bug to 
StreamingMarkupBuilder, it didn't help in this case.

  was:
I would love to be told how I'm doing this wrong. :D 

My ultimate goal here is to use XmlSlurper on a StreamingSAXBuilder to prepare 
a document in a standard way, then modify it, without having to render it to an 
intermediate file or a large string in memory. I think I've narrowed the main 
problem down to 

[jira] [Created] (GROOVY-10304) XmlSlurper failing to handle namespaces

2021-10-13 Thread Rachel Greenham (Jira)
Rachel Greenham created GROOVY-10304:


 Summary: XmlSlurper failing to handle namespaces
 Key: GROOVY-10304
 URL: https://issues.apache.org/jira/browse/GROOVY-10304
 Project: Groovy
  Issue Type: Bug
  Components: XML Processing
Affects Versions: 3.0.9
 Environment: MacOS, although it doesn't look like something that would 
vary by platform.
Reporter: Rachel Greenham
 Attachments: slurpFromSaxBuilder.groovy, slurpFromString.groovy

I would love to be told how I'm doing this wrong. :D 

My ultimate goal here is to use XmlSlurper on a StreamingSAXBuilder to prepare 
a document in a standard way, then modify it, without having to render it to an 
intermediate file or a large string in memory. I think I've narrowed the main 
problem down to XmlSlurper, although there are other issues with 
StreamingSAXBuilder. But it seems so basic, such a non-unusual thing to do that 
I feel sure it's just me doing it wrong...

Try the following in groovyConsole:

 
{code:groovy}
import groovy.xml.*
def src = '''
 hello

'''
def xml = new XmlSlurper()
def gpr = xml.parseText(src)
def serialized = XmlUtil.serialize(gpr)
println serialized
assert serialized == src
{code}
 

The assertion fails:
{noformat}
groovy> import groovy.xml.* 
groovy> def src = ''' 
groovy>   hello 
groovy>  
groovy> ''' 
groovy> def xml = new XmlSlurper() 
groovy> def gpr = xml.parseText(src) 
groovy> def serialized = XmlUtil.serialize(gpr) 
groovy> println serialized 
groovy> assert serialized == src 
 

  hello


Exception thrown

Assertion failed: 

assert serialized == src
   |  |  |
   |  |  '\n  hello\n\n'
   |  false
   '\n  hello\n\n'

at ConsoleScript49.run(ConsoleScript49:11)
at jdk.internal.reflect.GeneratedMethodAccessor78.invoke(Unknown Source)
at 
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

{noformat}
What's with all the "tag0"?

I have a forked XmlSlurper and slurpersupport.Node that I'm currently using to 
work around the above problem. But it doesn't solve the one below. And I'm sure 
it's the wrong approach anyway.

It gets worse if actually trying to slurp a StreamingSAXBuilder directly:

 
{code:groovy}
import groovy.xml.*
def expected = '''
 hello

'''
def doc = new StreamingSAXBuilder().bind {
 mkp.declareNamespace('': 'uri:urn')
 outer {
 inner 'hello'
 }
}
def xml = new XmlSlurper()
doc(xml)
def gpr = xml.document
def serialized = XmlUtil.serialize(gpr)
println serialized
assert serialized == expected
{code}
 

gives the output:
{noformat}
groovy> import groovy.xml.* 
groovy> def expected = ''' 
groovy>   hello 
groovy>  
groovy> ''' 
groovy> def doc = new StreamingSAXBuilder().bind { 
groovy> mkp.declareNamespace('': 'uri:urn') 
groovy> outer { 
groovy> inner 'hello' 
groovy> } 
groovy> } 
groovy> def xml = new XmlSlurper() 
groovy> doc(xml) 
groovy> def gpr = xml.document 
groovy> def serialized = XmlUtil.serialize(gpr) 
groovy> println serialized 
groovy> assert serialized == expected 
 
[Fatal Error] :2:70: The prefix "xmlns" cannot be bound to any namespace 
explicitly; neither can the namespace for "xmlns" be bound to any prefix 
explicitly.
Exception thrown

groovy.lang.GroovyRuntimeException: org.xml.sax.SAXParseException; lineNumber: 
2; columnNumber: 70; The prefix "xmlns" cannot be bound to any namespace 
explicitly; neither can the namespace for "xmlns" be bound to any prefix 
explicitly.
at ConsoleScript0.run(ConsoleScript0:16)
at jdk.internal.reflect.GeneratedMethodAccessor78.invoke(Unknown Source)
at 
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
{noformat}
Possibly-relevant old bug: GROOVY-5879, however while in my forked version of 
StreamingSAXBuilder I tried porting in the fix applied in that bug to 
StreamingMarkupBuilder, it didn't help in this case.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)


[jira] [Commented] (GROOVY-10099) A single null argument to a varargs parameter is received as null

2021-06-10 Thread Rachel Greenham (Jira)


[ 
https://issues.apache.org/jira/browse/GROOVY-10099?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17360668#comment-17360668
 ] 

Rachel Greenham commented on GROOVY-10099:
--

Thoughts that keep me awake at night:

Am I making a category error here? In dynamic compiling mode is it actually a 
big faux-pas in principle to be using type data known at compile time to affect 
the code being compiled? Looking through the docs last night I was noticing how 
- outside of @CompileStatic or @TypeChecked, the use of types seemed to be just 
for
 * Self-documentation
 * Invoking *from* a type-checked setting
 * Allowing IDEs to offer autocomplete suggestions

Nothing about making the slightest difference to the code that runs.

I had just thought, well, the information's *available* while compiling, and 
lost at runtime, we should be using it to decide what to do, but is that kind 
of opportunism and pragmatism breaking some actual rule and principle of 
dynamic programming in force here? And that's why one answer to the actual 
problem might be: use @CompileStatic.

Someone would've said something, right? :) 

> A single null argument to a varargs parameter is received as null
> -
>
> Key: GROOVY-10099
> URL: https://issues.apache.org/jira/browse/GROOVY-10099
> Project: Groovy
>  Issue Type: Bug
> Environment: Observed on Groovy 3.0.8 on macOS Big Sur (Intel), but I 
> don't think that's relevant; it'll be everywhere.
>Reporter: Rachel Greenham
>Priority: Major
> Fix For: 4.x
>
> Attachments: VarArgsTest.groovy, VarArgsTest.jsh
>
>  Time Spent: 1h 10m
>  Remaining Estimate: 0h
>
> (NB: I would set the priority to P2 default to be triaged, but I seem not to 
> have that option, so I left it at the default I was presented with.)
> When calling a method with a varargs parameter with a single value, that 
> value is wrapped into an array of length 1. This is the behaviour in Java, 
> and is the expected behaviour, and _most_ of the time is the behaviour in 
> Groovy too.
> But when that single value is null, Groovy will instead just pass the null 
> into the method. Java will not do this: You'll get an array with a single 
> null in it. Because Groovy's behaviour is unexpected, especially when 
> interfacing with Java code, NullPointerExceptions can often ensue.
> Adding to the inconsistencies, if the Groovy code calling the method is in a 
> {{@CompileStatic}} context, it behaves just like Java, and the method 
> (whether or not _it_ is statically compiled or a dynamic Groovy method) 
> receives an array with a null in it.
> So the behaviour in Groovy is inconsistent, both with itself in a 
> {{@CompileStatic}} situation, and with Java, and is requiring workarounds in 
> Java code to handle this normally-impossible eventuality. (Even if no varargs 
> parameter is given you get an empty array, as in fact you do in Groovy too.)
> This may be an "early instalment weirdness": There's an ancient ticket, from 
> not long after varargs were introduced into Java, which appears to have 
> argued - successfully at the time - that the normal behaviour is a bug: 
> https://issues.apache.org/jira/browse/GROOVY-1026 
> Further adding to the confusion may be that Groovy usually elides the 
> difference between an {{Object[]}} parameter and an {{Object...}} parameter: 
> They both behave the same.
> The offending code appears to be in 
> org.codehaus.groovy.reflection.ParameterTypes.java in method fitToVars, lines 
> 200-215 in master at the time of writing, which even includes a comment that 
> "if the last argument is null, then we don't have to do anything", with which 
> I respectfully disagree. :) That behaviour should be to return an array with 
> a single null in it (Handily, MetaClassHelper.ARRAY_WITH_NULL saves having to 
> make a new one.)
> In principle it's an easy fix (although I've left tagging to others as this 
> is my first issue here), but there'd be an obvious nervousness about changing 
> behaviour like this when there might be a lot of old code out there depending 
> on it behaving the way it does now. OTOH the way it behaves now is breaking 
> the expectations of those of us coming to Groovy from a lifetime of Java...
> Attachments:
> VarArgsTest.groovy - a script saved from, and runnable in, groovyConsole, 
> demonstrating the behaviour. The behaviour is the same regardless of whether 
> the console is launched with the -indy option. (The issue was initially 
> observed in indy.) The dynamic portion of the test, when run, ends in a 
> NullPointerException as Arrays.asList is not expecting a null varargs 
> parameter. Output seen (-indy or  not):
>  
> {code:java}
> name: the static name 1
> params is null? false
> params length is 1
> [blah]
> name: the static name 2

[jira] [Commented] (GROOVY-10099) A single null argument to a varargs parameter is received as null

2021-06-09 Thread Rachel Greenham (Jira)


[ 
https://issues.apache.org/jira/browse/GROOVY-10099?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17360099#comment-17360099
 ] 

Rachel Greenham commented on GROOVY-10099:
--

Seems to be an argument for ignoring issues because it's easier than fixing 
them, which seems to have been the fate of all those issues quoted: No debate, 
just... ignored and left to wither. It feels like this one only got attention 
(for which thank you, by the way) because it was followed up by an actual PR 
which had to be responded to. :) 

(Seriously, there's nothing wrong with being a voice for caution, but it feels 
like it invites a robust defence, so here goes: :) )

So the advice is: "If you need to call a varargs method, do so via a 
statically-compiled intermediate method, so it doesn't blow up in certain 
situations." It's a bit... rubbish, isn't it? If you're in @CompileStatic 
anyway for other reasons, like "this bit needs to run faster", fine, but having 
to do it, and lose the _benefits_ of a dynamic language, just to get 
predictable behaviour out of varargs calls, is extremely retrograde.

I'm trying to get Groovy integrated into our platform. We already have a way of 
invoking scripts that basically goes through a method on a context object that 
looks like this (names have been changed):
{code:java}
public Object perform(String scriptName, Object... args) {...}{code}
Which will now preferentially find and execute a groovy script, and fall back 
to  scripts. And it may be called trivially both from scripts in the 
legacy scripting language (obscure, older-than-groovy, barrier-to-hiring), and 
from Java code, like:
{code:java}
perform("/misc/sanitize-basket", session.getBasket());{code}
Which could be used verbatim in Groovy, though more idiomatically like:
{code:java}
perform '/misc/sanitize-basket', session.basket{code}
Only, when you do this - either - in the rare-but-valid case of that 
Session::getBasket method returning null, the target script blows up, because 
its generated code looks like:
{code:java}
public Object run(Object[] args) {
    Basket basket = (Basket)args[0];
    if (basket != null) { ...

{code}
But only when called from Groovy. Not from anywhere else, because normal 
varargs behaviour is, if basket is null you still get the array with a null 
basket, because the argument _type_... is Basket. It's known by the compiler so 
it wraps it up.

If I _wanted_ to call it with a null constant, or obtain it untyped, I'd 
_expect_ to have to cast it, in case it was null:

 
{code:java}
perform '/misc/sanitize-basket', (Basket)null
perform '/misc/sanitize-basket', session.attrs["basket-${name}"] as Basket
{code}
 

... but at the moment that wouldn't even work.

It's an acceptance issue. Imagine the conversation:
{quote}"So you changed perform so it catches nulls and makes an array which... 
hopefully doesn't break anything else..."

"The  scripts have to be given an args array the length of the number 
of declared parameters, but if they're not declaring any they don't even look 
at it. So that should be safe if it's not null. I don't think they ever let you 
actually declare an array as a parameter. It's one of the limitations."

"Hmm. But otherwise the workaround is, to call varargs methods via another 
intermediate method compiled statically?"

"Yeah. Or you can make it an array here, like: {{}}
{code:java}
[session.basket] as Basket[]{code}
"So now you're making an ArrayList and toArraying it. Every time."

"Uh, yeah. Or you can make the array directly, like we did in Java before 
varargs."

__

"
{code:java}
session.basket ?: Basket.ARRAY_WITH_NULL 

{code}
? :D"

"Did we look at JRuby yet?"{color:#172b4d} {color}
{quote}
:)

I can't stress enough that the PR is attempting to intervene only where the 
expression type is known, and known not to be dynamically typed or an array. 
Maybe there's bugs in that identification, so we fix those if they arise. But 
as for the principle of it: if the type is known, when is it ever right to be 
knowingly sending a non-array argument to an array parameter? Such that it 
could only escape an immediate ClassCastException if it's null, or if it's 
intercepted and turned into an identical array anyway at runtime.

And I don't care about the no-cast null constant case. I thought it made sense 
to make it consistent with @CompileStatic behaviour, but that's not a hill I 
want to die on. It can go on instead being treated as a dynamically-typed 
expression. This is only fixing what happens when we _have_ the type. The 
reporter of GROOVY-6146 appeared to think the same way: Marking in bold the 
important bit: that even when you cast it explicitly to String it ignores you 
and still treats it like it's an array. This PR would fix that bug too.

Does it break the mitigations people might have put in to get around this?
 * If they ensure the argument can never be null? Then no: It's just turning 

[jira] [Commented] (GROOVY-10099) A single null argument to a varargs parameter is received as null

2021-05-22 Thread Rachel Greenham (Jira)


[ 
https://issues.apache.org/jira/browse/GROOVY-10099?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17349833#comment-17349833
 ] 

Rachel Greenham commented on GROOVY-10099:
--

That fix won't work. It breaks too much. I'm sure you're as unsurprised as I 
am. I had fun though. :D

Fundamentally you can't fix it at runtime because you can't tell if a single 
null value is a null object reference or a null array reference. And there's 
much that depends on the implicit assumption that it's an array reference. For 
instance, if you change it, you can't set or initialise a POGO's array-typed 
field to null. Which doesn't break immediately, it breaks later, when something 
tries to use it.

If this can be fixed anywhere, it's in the compiler. Maybe the AstBuilder? It 
has more information. After all, it works as expected in {{@CompileStatic}}.

Even in {{@CompileDynamic}} mode, it presumably has (or could have) a better 
idea of what a given _expression type_ is; at least quite a lot of the time: if 
it's a call to a real method, or a typed object reference, or a cast or 
type-coercion in the expression itself. It would be able to tell if the 
expression's _type_ is an array type or not. And if it's not an array type, and 
the parameter it fits to is a varargs parameter, whatever value it evaluates to 
at runtime (including null) should be wrapped in an array of one, and it can 
write that array-wrapping operation into the compiled code. Like it does in 
{{@CompileStatic}}, like javac does... As with {{@TypeChecked}} mode, it would 
still be writing an invokeMethod call, but it would wrap that parameter in an 
array. Then all the runtime invoke code sees is that array and it just passes 
it through.

And if it _hasn't_ got a definitive idea of the expression type, because it's 
an untyped variable, or an expression that _must_ be resolved to a dynamic call 
(ie: something that {{@CompileStatic}} would balk at), it would just pass it in 
as it is, the same behaviour as now, so it breaks nothing. And if it doesn't 
behave how the coder expects, they'd be able to resolve it by disambiguating 
the type of that expression in their own code (eg: with a cast, a type 
coercion, or declaring a variable or method return type properly).

So it wouldn't solve it everywhere, 100%, as it couldn't solve it for dynamic 
expressions of unknowable type at compiletime. But solving it for known 
expression types would reduce the footprint of the problem a _lot_, I expect, 
and put the rest in the hands of the coder to eg: put a cast in if necessary.

This would have solved my original problem, as it was a situation where the 
expression type was known, or at least knowable. But it was just one line in a 
script that didn't otherwise need to be {{@CompileStatic}}.

I'm not averse to trying that approach, but I don't know where to start...

> A single null argument to a varargs parameter is received as null
> -
>
> Key: GROOVY-10099
> URL: https://issues.apache.org/jira/browse/GROOVY-10099
> Project: Groovy
>  Issue Type: Bug
> Environment: Observed on Groovy 3.0.8 on macOS Big Sur (Intel), but I 
> don't think that's relevant; it'll be everywhere.
>Reporter: Rachel Greenham
>Priority: Major
> Fix For: 4.x
>
> Attachments: VarArgsTest.groovy, VarArgsTest.jsh
>
>
> (NB: I would set the priority to P2 default to be triaged, but I seem not to 
> have that option, so I left it at the default I was presented with.)
> When calling a method with a varargs parameter with a single value, that 
> value is wrapped into an array of length 1. This is the behaviour in Java, 
> and is the expected behaviour, and _most_ of the time is the behaviour in 
> Groovy too.
> But when that single value is null, Groovy will instead just pass the null 
> into the method. Java will not do this: You'll get an array with a single 
> null in it. Because Groovy's behaviour is unexpected, especially when 
> interfacing with Java code, NullPointerExceptions can often ensue.
> Adding to the inconsistencies, if the Groovy code calling the method is in a 
> {{@CompileStatic}} context, it behaves just like Java, and the method 
> (whether or not _it_ is statically compiled or a dynamic Groovy method) 
> receives an array with a null in it.
> So the behaviour in Groovy is inconsistent, both with itself in a 
> {{@CompileStatic}} situation, and with Java, and is requiring workarounds in 
> Java code to handle this normally-impossible eventuality. (Even if no varargs 
> parameter is given you get an empty array, as in fact you do in Groovy too.)
> This may be an "early instalment weirdness": There's an ancient ticket, from 
> not long after varargs were introduced into Java, which appears to have 
> argued - successfully at the time - 

[jira] [Commented] (GROOVY-10099) A single null argument to a varargs parameter is received as null

2021-05-20 Thread Rachel Greenham (Jira)


[ 
https://issues.apache.org/jira/browse/GROOVY-10099?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17348592#comment-17348592
 ] 

Rachel Greenham commented on GROOVY-10099:
--

I'll go at it at the weekend.

I was wondering if part of the original confusion/debate was because in groovy 
Object[] and Object... are treated interchangeably, based simply on whether the 
last parameter's type is an array type, whereas that's not the case in Java. 
Therefore, in the immediate aftermath of Java getting varargs, GROOVY_1026 
maybe was an attempt at keeping things behaving as they did before, for 
Object[] methods.

I don't think we can tell if a Groovy method was declared with Object..., as 
its Method::isVarArgs just returns true either way, but Java does let one 
distinguish. If we need to reduce the footprint of the change it might be to 
restrict it to calling Java classes' (does not implement GroovyObject) methods 
where isVarArgs() returns true, cache that in CachedMethod because it's those 
java methods that tend to assume they'll never receive null. But I expect the 
first preference would be to have a simpler change that is consistent 
everywhere. If it doesn't tear the world down around our ears!

> A single null argument to a varargs parameter is received as null
> -
>
> Key: GROOVY-10099
> URL: https://issues.apache.org/jira/browse/GROOVY-10099
> Project: Groovy
>  Issue Type: Bug
> Environment: Observed on Groovy 3.0.8 on macOS Big Sur (Intel), but I 
> don't think that's relevant; it'll be everywhere.
>Reporter: Rachel Greenham
>Priority: Major
> Fix For: 4.x
>
> Attachments: VarArgsTest.groovy, VarArgsTest.jsh
>
>
> (NB: I would set the priority to P2 default to be triaged, but I seem not to 
> have that option, so I left it at the default I was presented with.)
> When calling a method with a varargs parameter with a single value, that 
> value is wrapped into an array of length 1. This is the behaviour in Java, 
> and is the expected behaviour, and _most_ of the time is the behaviour in 
> Groovy too.
> But when that single value is null, Groovy will instead just pass the null 
> into the method. Java will not do this: You'll get an array with a single 
> null in it. Because Groovy's behaviour is unexpected, especially when 
> interfacing with Java code, NullPointerExceptions can often ensue.
> Adding to the inconsistencies, if the Groovy code calling the method is in a 
> {{@CompileStatic}} context, it behaves just like Java, and the method 
> (whether or not _it_ is statically compiled or a dynamic Groovy method) 
> receives an array with a null in it.
> So the behaviour in Groovy is inconsistent, both with itself in a 
> {{@CompileStatic}} situation, and with Java, and is requiring workarounds in 
> Java code to handle this normally-impossible eventuality. (Even if no varargs 
> parameter is given you get an empty array, as in fact you do in Groovy too.)
> This may be an "early instalment weirdness": There's an ancient ticket, from 
> not long after varargs were introduced into Java, which appears to have 
> argued - successfully at the time - that the normal behaviour is a bug: 
> https://issues.apache.org/jira/browse/GROOVY-1026 
> Further adding to the confusion may be that Groovy usually elides the 
> difference between an {{Object[]}} parameter and an {{Object...}} parameter: 
> They both behave the same.
> The offending code appears to be in 
> org.codehaus.groovy.reflection.ParameterTypes.java in method fitToVars, lines 
> 200-215 in master at the time of writing, which even includes a comment that 
> "if the last argument is null, then we don't have to do anything", with which 
> I respectfully disagree. :) That behaviour should be to return an array with 
> a single null in it (Handily, MetaClassHelper.ARRAY_WITH_NULL saves having to 
> make a new one.)
> In principle it's an easy fix (although I've left tagging to others as this 
> is my first issue here), but there'd be an obvious nervousness about changing 
> behaviour like this when there might be a lot of old code out there depending 
> on it behaving the way it does now. OTOH the way it behaves now is breaking 
> the expectations of those of us coming to Groovy from a lifetime of Java...
> Attachments:
> VarArgsTest.groovy - a script saved from, and runnable in, groovyConsole, 
> demonstrating the behaviour. The behaviour is the same regardless of whether 
> the console is launched with the -indy option. (The issue was initially 
> observed in indy.) The dynamic portion of the test, when run, ends in a 
> NullPointerException as Arrays.asList is not expecting a null varargs 
> parameter. Output seen (-indy or  not):
>  
> {code:java}
> name: the static name 1
> params is null? false
> params 

[jira] [Commented] (GROOVY-10099) A single null argument to a varargs parameter is received as null

2021-05-20 Thread Rachel Greenham (Jira)


[ 
https://issues.apache.org/jira/browse/GROOVY-10099?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=17348314#comment-17348314
 ] 

Rachel Greenham commented on GROOVY-10099:
--

Noting that the current behaviour is deliberate and specifically tested for in 
VarargsMethodTest.groovy, so that too would need to be changed, so implying 
some kind of discussion on _whether_ to do so...

Should I just submit the patch, including the test change, and if so, as a PR 
on GitHub?

> A single null argument to a varargs parameter is received as null
> -
>
> Key: GROOVY-10099
> URL: https://issues.apache.org/jira/browse/GROOVY-10099
> Project: Groovy
>  Issue Type: Bug
> Environment: Observed on Groovy 3.0.8 on macOS Big Sur (Intel), but I 
> don't think that's relevant; it'll be everywhere.
>Reporter: Rachel Greenham
>Priority: Major
> Fix For: 4.x
>
> Attachments: VarArgsTest.groovy, VarArgsTest.jsh
>
>
> (NB: I would set the priority to P2 default to be triaged, but I seem not to 
> have that option, so I left it at the default I was presented with.)
> When calling a method with a varargs parameter with a single value, that 
> value is wrapped into an array of length 1. This is the behaviour in Java, 
> and is the expected behaviour, and _most_ of the time is the behaviour in 
> Groovy too.
> But when that single value is null, Groovy will instead just pass the null 
> into the method. Java will not do this: You'll get an array with a single 
> null in it. Because Groovy's behaviour is unexpected, especially when 
> interfacing with Java code, NullPointerExceptions can often ensue.
> Adding to the inconsistencies, if the Groovy code calling the method is in a 
> {{@CompileStatic}} context, it behaves just like Java, and the method 
> (whether or not _it_ is statically compiled or a dynamic Groovy method) 
> receives an array with a null in it.
> So the behaviour in Groovy is inconsistent, both with itself in a 
> {{@CompileStatic}} situation, and with Java, and is requiring workarounds in 
> Java code to handle this normally-impossible eventuality. (Even if no varargs 
> parameter is given you get an empty array, as in fact you do in Groovy too.)
> This may be an "early instalment weirdness": There's an ancient ticket, from 
> not long after varargs were introduced into Java, which appears to have 
> argued - successfully at the time - that the normal behaviour is a bug: 
> https://issues.apache.org/jira/browse/GROOVY-1026 
> Further adding to the confusion may be that Groovy usually elides the 
> difference between an {{Object[]}} parameter and an {{Object...}} parameter: 
> They both behave the same.
> The offending code appears to be in 
> org.codehaus.groovy.reflection.ParameterTypes.java in method fitToVars, lines 
> 200-215 in master at the time of writing, which even includes a comment that 
> "if the last argument is null, then we don't have to do anything", with which 
> I respectfully disagree. :) That behaviour should be to return an array with 
> a single null in it (Handily, MetaClassHelper.ARRAY_WITH_NULL saves having to 
> make a new one.)
> In principle it's an easy fix (although I've left tagging to others as this 
> is my first issue here), but there'd be an obvious nervousness about changing 
> behaviour like this when there might be a lot of old code out there depending 
> on it behaving the way it does now. OTOH the way it behaves now is breaking 
> the expectations of those of us coming to Groovy from a lifetime of Java...
> Attachments:
> VarArgsTest.groovy - a script saved from, and runnable in, groovyConsole, 
> demonstrating the behaviour. The behaviour is the same regardless of whether 
> the console is launched with the -indy option. (The issue was initially 
> observed in indy.) The dynamic portion of the test, when run, ends in a 
> NullPointerException as Arrays.asList is not expecting a null varargs 
> parameter. Output seen (-indy or  not):
>  
> {code:java}
> name: the static name 1
> params is null? false
> params length is 1
> [blah]
> name: the static name 2
> params is null? false
> params length is 2
> [blah, blue]
> name: the static name 3 with blah=null
> params is null? false
> params length is 1
> [null]
> Arrays.asList(blah)? [null]
> name: the dynamic name 1
> params is null? false
> params length is 1
> [blah]
> name: the dynamic name 2
> params is null? false
> params length is 2
> [blah, blue]
> name: the dynamic name 3 with blah=null
> params is null? true
> Exception thrown
> java.lang.NullPointerException
> ...{code}
> (etc. stack trace not shown for formatting reasons.)
> VarArgsTest.jsh - a jshell script demonstrating Java's behaviour, very 
> similar to the groovy test, but omitting the dynamic portion of the test for 
> obvious 

[jira] [Updated] (GROOVY-10099) A single null argument to a varargs parameter is received as null

2021-05-20 Thread Rachel Greenham (Jira)


 [ 
https://issues.apache.org/jira/browse/GROOVY-10099?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Rachel Greenham updated GROOVY-10099:
-
Description: 
(NB: I would set the priority to P2 default to be triaged, but I seem not to 
have that option, so I left it at the default I was presented with.)

When calling a method with a varargs parameter with a single value, that value 
is wrapped into an array of length 1. This is the behaviour in Java, and is the 
expected behaviour, and _most_ of the time is the behaviour in Groovy too.

But when that single value is null, Groovy will instead just pass the null into 
the method. Java will not do this: You'll get an array with a single null in 
it. Because Groovy's behaviour is unexpected, especially when interfacing with 
Java code, NullPointerExceptions can often ensue.

Adding to the inconsistencies, if the Groovy code calling the method is in a 
{{@CompileStatic}} context, it behaves just like Java, and the method (whether 
or not _it_ is statically compiled or a dynamic Groovy method) receives an 
array with a null in it.

So the behaviour in Groovy is inconsistent, both with itself in a 
{{@CompileStatic}} situation, and with Java, and is requiring workarounds in 
Java code to handle this normally-impossible eventuality. (Even if no varargs 
parameter is given you get an empty array, as in fact you do in Groovy too.)

This may be an "early instalment weirdness": There's an ancient ticket, from 
not long after varargs were introduced into Java, which appears to have argued 
- successfully at the time - that the normal behaviour is a bug: 
https://issues.apache.org/jira/browse/GROOVY-1026 

Further adding to the confusion may be that Groovy usually elides the 
difference between an {{Object[]}} parameter and an {{Object...}} parameter: 
They both behave the same.

The offending code appears to be in 
org.codehaus.groovy.reflection.ParameterTypes.java in method fitToVars, lines 
200-215 in master at the time of writing, which even includes a comment that 
"if the last argument is null, then we don't have to do anything", with which I 
respectfully disagree. :) That behaviour should be to return an array with a 
single null in it (Handily, MetaClassHelper.ARRAY_WITH_NULL saves having to 
make a new one.)

In principle it's an easy fix (although I've left tagging to others as this is 
my first issue here), but there'd be an obvious nervousness about changing 
behaviour like this when there might be a lot of old code out there depending 
on it behaving the way it does now. OTOH the way it behaves now is breaking the 
expectations of those of us coming to Groovy from a lifetime of Java...

Attachments:

VarArgsTest.groovy - a script saved from, and runnable in, groovyConsole, 
demonstrating the behaviour. The behaviour is the same regardless of whether 
the console is launched with the -indy option. (The issue was initially 
observed in indy.) The dynamic portion of the test, when run, ends in a 
NullPointerException as Arrays.asList is not expecting a null varargs 
parameter. Output seen (-indy or  not):

 
{code:java}
name: the static name 1
params is null? false
params length is 1
[blah]
name: the static name 2
params is null? false
params length is 2
[blah, blue]
name: the static name 3 with blah=null
params is null? false
params length is 1
[null]
Arrays.asList(blah)? [null]

name: the dynamic name 1
params is null? false
params length is 1
[blah]
name: the dynamic name 2
params is null? false
params length is 2
[blah, blue]
name: the dynamic name 3 with blah=null
params is null? true
Exception thrown

java.lang.NullPointerException
...{code}
(etc. stack trace not shown for formatting reasons.)

VarArgsTest.jsh - a jshell script demonstrating Java's behaviour, very similar 
to the groovy test, but omitting the dynamic portion of the test for obvious 
reasons. (The statements in the Groovy script ending in semicolons are left 
that way precisely to mark that they're identical to the Java test.) Runnable 
with

 
{code:java}
jshell PRINTING VarArgsTest.jsh
{code}
Output seen:
{code:java}
name: the static name 1
params is null? false
params length is 1
[blah]
name: the static name 2
params is null? false
params length is 2
[blah, blue]
name: the static name 3 with blah=null
params is null? false
params length is 1
[null]
Arrays.asList(blah)? [null]
{code}

  was:
(NB: I would set the priority to P2 default to be triaged, but I seem not to 
have that option, so I left it at the default I was presented with.)

When calling a method with a varargs parameter with a single value, that value 
is wrapped into an array of length 1. This is the behaviour in Java, and is the 
expected behaviour, and _most_ of the time is the behaviour in Groovy too.

But when that single value is null, Groovy will instead just pass the null into 
the method. Java will not do this: You'll get an array with a single 

[jira] [Updated] (GROOVY-10099) A single null argument to a varargs parameter is received as null

2021-05-20 Thread Rachel Greenham (Jira)


 [ 
https://issues.apache.org/jira/browse/GROOVY-10099?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Rachel Greenham updated GROOVY-10099:
-
Description: 
(NB: I would set the priority to P2 default to be triaged, but I seem not to 
have that option, so I left it at the default I was presented with.)

When calling a method with a varargs parameter with a single value, that value 
is wrapped into an array of length 1. This is the behaviour in Java, and is the 
expected behaviour, and _most_ of the time is the behaviour in Groovy too.

But when that single value is null, Groovy will instead just pass the null into 
the method. Java will not do this: You'll get an array with a single null in 
it. Because Groovy's behaviour is unexpected, especially when interfacing with 
Java code, NullPointerExceptions can often ensue.

Adding to the inconsistencies, if the Groovy code calling the method is in a 
{{@CompileStatic}} context, it behaves just like Java, and the method (whether 
or not _it_ is statically compiled or a dynamic Groovy method) receives an 
array with a null in it.

So the behaviour in Groovy is inconsistent, both with itself in a 
{{@CompileStatic}} situation, and with Java, and is requiring workarounds in 
Java code to handle this normally-impossible eventuality. (Even if no varargs 
parameter is given you get an empty array, as in fact you do in Groovy too.)

This may be an "early instalment weirdness": There's an ancient ticket, from 
not long after varargs were introduced into Java, which appears to have argued 
- successfully at the time - that the normal behaviour is a bug: 
https://issues.apache.org/jira/browse/GROOVY-1026 

Further adding to the confusion may be that Groovy usually elides the 
difference between an {{Object[]}} parameter and an {{Object...}} parameter: 
They both behave the same.

The offending code appears to be in 
org.codehaus.groovy.reflection.ParameterTypes.java in method fitToVars, lines 
200-215 in master at the time of writing, which even includes a comment that 
"if the last argument is null, then we don't have to do anything", with which I 
respectfully disagree. :) That behaviour should be to return an array with a 
single null in it (Handily, MetaClassHelper.ARRAY_WITH_NULL saves having to 
make a new one.)

In principle it's an easy fix (although I've left tagging to others as this is 
my first issue here), but there'd be an obvious nervousness about changing 
behaviour like this when there might be a lot of old code out there depending 
on it behaving the way it does now. OTOH the way it behaves now is breaking the 
expectations of those of us coming to Groovy from a lifetime of Java...

Attachments:

VarArgsTest.groovy - a script saved from, and runnable in, groovyConsole, 
demonstrating the behaviour. The behaviour is the same regardless of whether 
the console is launched with the -indy option. (The issue was initially 
observed in indy.) The dynamic portion of the test, when run, ends in a 
NullPointerException as Arrays.asList is not expecting a null varargs 
parameter. Output seen (-indy or  not):

 
{code:java}
name: the static name 1
params is null? false
params length is 1
[blah]
name: the static name 2
params is null? false
params length is 2[blah, blue]
name: the static name 3 with blah=null
params is null? false
params length is 1
[null]
Arrays.asList(blah)? [null]

name: the dynamic name 1
params is null? false
params length is 1
[blah]
name: the dynamic name 2
params is null? false
params length is 2[blah, blue]
name: the dynamic name 3 with blah=null
params is null? true
Exception thrown

java.lang.NullPointerException
...{code}
(etc. stack trace not shown for formatting reasons.)

VarArgsTest.jsh - a jshell script demonstrating Java's behaviour, very similar 
to the groovy test, but omitting the dynamic portion of the test for obvious 
reasons. (The statements in the Groovy script ending in semicolons are left 
that way precisely to mark that they're identical to the Java test.) Runnable 
with

 
{code:java}
jshell PRINTING VarArgsTest.jsh
{code}
Output seen:
{code:java}
name: the static name 1
params is null? false
params length is 1
[blah]
name: the static name 2
params is null? false
params length is 2
[blah, blue]
name: the static name 3 with blah=null
params is null? false
params length is 1
[null]
Arrays.asList(blah)? [null]
{code}

  was:
(NB: I would set the priority to P2 default to be triaged, but I seem not to 
have that option, so I left it at the default I was presented with.)

When calling a method with a varargs parameter with a single value, that value 
is wrapped into an array of length 1. This is the behaviour in Java, and is the 
expected behaviour, and _most_ of the time is the behaviour in Groovy too.

But when that single value is null, Groovy will instead just pass the null into 
the method. Java will not do this: You'll get an array with a single null 

[jira] [Created] (GROOVY-10099) A single null argument to a varargs parameter is received as null

2021-05-20 Thread Rachel Greenham (Jira)
Rachel Greenham created GROOVY-10099:


 Summary: A single null argument to a varargs parameter is received 
as null
 Key: GROOVY-10099
 URL: https://issues.apache.org/jira/browse/GROOVY-10099
 Project: Groovy
  Issue Type: Bug
 Environment: Observed on Groovy 3.0.8 on macOS Big Sur (Intel), but I 
don't think that's relevant; it'll be everywhere.
Reporter: Rachel Greenham
 Attachments: VarArgsTest.groovy, VarArgsTest.jsh

(NB: I would set the priority to P2 default to be triaged, but I seem not to 
have that option, so I left it at the default I was presented with.)

When calling a method with a varargs parameter with a single value, that value 
is wrapped into an array of length 1. This is the behaviour in Java, and is the 
expected behaviour, and _most_ of the time is the behaviour in Groovy too.

But when that single value is null, Groovy will instead just pass the null into 
the method. Java will not do this: You'll get an array with a single null in 
it. Because Groovy's behaviour is unexpected, especially when interfacing with 
Java code, NullPointerExceptions can often ensue.

Adding to the inconsistencies, if the Groovy code calling the method is in a 
{{@CompileStatic}} context, it behaves just like Java, and the method (whether 
or not _it_ is statically compiled or a dynamic Groovy method) receives an 
array with a null in it.

So the behaviour in Groovy is inconsistent, both with itself in a 
{{@CompileStatic}} situation, and with Java, and is requiring workarounds in 
Java code to handle this normally-impossible eventuality. (Even if no varargs 
parameter is given you get an empty array, as in fact you do in Groovy too.)

This may be an "early instalment weirdness": There's an ancient ticket, from 
not long after varargs were introduced into Java, which appears to have argued 
- successfully at the time - that the normal behaviour is a bug: 
https://issues.apache.org/jira/browse/GROOVY-1026 

Further adding to the confusion may be that Groovy usually elides the 
difference between an {{Object[]}} parameter and an {{Object...}} parameter: 
They both behave the same.

The offending code appears to be in 
org.codehaus.groovy.reflection.ParameterTypes.java in method fitToVars, lines 
200-215 in master at the time of writing, which even includes a comment that 
"if the last argument is null, then we don't have to do anything", with which I 
respectfully disagree. :) That behaviour should be to return an array with a 
single null in it (Handily, MetaClassHelper.ARRAY_WITH_NULL saves having to 
make a new one.)

In principle it's an easy fix (although I've left tagging to others as this is 
my first issue here), but there'd be an obvious nervousness about changing 
behaviour like this when there might be a lot of old code out there depending 
on it behaving the way it does now. OTOH the way it behaves now is breaking the 
expectations of those of us coming to Groovy from a lifetime of Java...

Attachments:

VarArgsTest.groovy - a script saved from, and runnable in, groovyConsole, 
demonstrating the behaviour. The behaviour is the same regardless of whether 
the console is launched with the --indy option. (The issue was initially 
observed in indy.) The dynamic portion of the test, when run, ends in a 
NullPointerException as Arrays.asList is not expecting a null varargs 
parameter. Output seen (--indy or  not):

 
{code:java}
name: the static name 1
params is null? false
params length is 1
[blah]
name: the static name 2
params is null? false
params length is 2[blah, blue]
name: the static name 3 with blah=null
params is null? false
params length is 1
[null]
Arrays.asList(blah)? [null]

name: the dynamic name 1
params is null? false
params length is 1
[blah]
name: the dynamic name 2
params is null? false
params length is 2[blah, blue]
name: the dynamic name 3 with blah=null
params is null? true
Exception thrown

java.lang.NullPointerException
...{code}
(etc. stack trace not shown for formatting reasons.)

VarArgsTest.jsh - a jshell script demonstrating Java's behaviour, very similar 
to the groovy test, but omitting the dynamic portion of the test for obvious 
reasons. (The statements in the Groovy script ending in semicolons are left 
that way precisely to mark that they're identical to the Java test.) Runnable 
with

 
{code:java}
jshell PRINTING VarArgsTest.jsh
{code}
Output seen:
{code:java}
name: the static name 1
params is null? false
params length is 1
[blah]
name: the static name 2
params is null? false
params length is 2
[blah, blue]
name: the static name 3 with blah=null
params is null? false
params length is 1
[null]
Arrays.asList(blah)? [null]
{code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)