[
https://issues.apache.org/jira/browse/GROOVY-6837?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17474715#comment-17474715
]
Eric Milles commented on GROOVY-6837:
-------------------------------------
This is what I have so far. It is efficient, but the type parameters are not
true to the runtime behavior. The simplest solution would be to have all the
array plus methods return {{Object[]}}. Another option is to have the right
operand be of type {{Object[]}} and just describe the array store exception or
provide inline coercion.
I looked for an example in Java and the closest I found was Arrays#fill, which
is described this way (possibly for the same reasons): {{void fill(Object[] a,
Object v)}}
{code:java}
/**
* Create an array as a union of two arrays.
* <pre class="groovyTestCase">
* Integer[] a = [1, 2, 3]
* Integer[] b = [4, 5, 6]
* def result = a + b
* assert result.class == Integer[]
* assert result == new Integer[]{1, 2, 3, 4, 5, 6}
*
* Number[] c = [-1, 0.0, null]
* result = c + a
* assert result.class == Number[]
* assert result == new Number[]{-1, 0.0, null, 1, 2, 3}
* // improper type arguments; Number doesn't extend Integer
* groovy.test.GroovyAssert.shouldFail(ArrayStoreException) { a + c }
* </pre>
*
* @param left the left Array
* @param right the right Array
* @return A new array containing right appended to left.
* @since 1.8.7
*/
public static <T> T[] plus(final T[] left, final T[] right) {
T[] result = Arrays.copyOf(left, left.length + right.length);
System.arraycopy(right, 0, result, left.length, right.length);
return result;
}
/**
* Create an array containing elements from an original array plus an
additional appended element.
* <pre class="groovyTestCase">
* Integer[] a = [1, 2, 3]
* def result = a + 4
* assert result.class == Integer[]
* assert result == new Integer[]{1, 2, 3, 4}
*
* // improper type arguments; Double doesn't extend Integer
* groovy.test.GroovyAssert.shouldFail(ArrayStoreException) { a + 5d }
* </pre>
*
* @param left the array
* @param right the value to append
* @return A new array containing left with right appended to it.
* @since 1.8.7
*/
public static <T> T[] plus(final T[] left, final T right) {
T[] result = Arrays.copyOf(left, left.length + 1);
result[left.length] = right;
return result;
}
/**
* Create an array containing elements from an original array plus those
from a Collection.
* <pre class="groovyTestCase">
* Integer[] a = [1, 2, 3]
* def result = a + [4, 5]
* assert result.class == Integer[]
* assert result == new Integer[]{1, 2, 3, 4, 5}
* </pre>
*
* @param left the array
* @param right a Collection to be appended
* @return A new array containing left with right appended to it.
* @since 1.8.7
*/
public static <T> T[] plus(final T[] left, final Collection<? extends T>
right) {
T[] result = Arrays.copyOf(left, left.length + right.size());
int i = left.length;
for (T t : right) {
result[i] = t;
i += 1;
}
return result;
}
/**
* Create an array containing elements from an original array plus those
from an Iterable.
* <pre class="groovyTestCase">
* class AbcIterable implements Iterable<String> {
* Iterator<String> iterator() { "abc".iterator() }
* }
* String[] array = ['x', 'y', 'z']
* def result = array + new AbcIterable()
* assert result.class == String[]
* assert result == new String[]{'x', 'y', 'z', 'a', 'b', 'c'}
* </pre>
*
* @param left the array
* @param right an Iterable to be appended
* @return A new array containing elements from left with those from right
appended.
* @since 1.8.7
*/
public static <T> T[] plus(final T[] left, final Iterable<? extends T>
right) {
return plus(left, toList(right));
}
{code}
> String[] + String[] gives Object[]
> ----------------------------------
>
> Key: GROOVY-6837
> URL: https://issues.apache.org/jira/browse/GROOVY-6837
> Project: Groovy
> Issue Type: Bug
> Components: groovy-runtime
> Affects Versions: 2.3.1
> Reporter: Dmitry Ovchinnikov
> Assignee: Eric Milles
> Priority: Major
> Attachments: image-2022-01-12-10-43-14-275.png
>
> Time Spent: 20m
> Remaining Estimate: 0h
>
> {code:java}
> def a1 = ["a", "b"] as String[], a2 = ["c", "d"] as String[];
> def concatenated = a1 + a2;
> java.nio.file.Paths.get("parent", concatenated)
> {code}
> ==>
> {noformat}
> groovy.lang.MissingMethodException: No signature of method: static
> java.nio.file.Paths.get() is applicable for argument types:
> (java.lang.String, [Ljava.lang.Object;) values: [parent, [a, b, c, d]]
> Possible solutions: get(java.lang.String, [Ljava.lang.String;),
> get(java.net.URI), grep(), getAt(java.lang.String), wait(), any()
> at
> groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1373)
> at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1359)
> at
> org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:50)
> at
> org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
> at
> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
> at
> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
> at ideaGroovyConsole.run(ideaGroovyConsole.groovy:4)
> at
> groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:258)
> at groovy.lang.GroovyShell.run(GroovyShell.java:502)
> at groovy.lang.GroovyShell.run(GroovyShell.java:481)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:606)
> at
> org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSite.invoke(PogoMetaMethodSite.java:166)
> at
> org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:68)
> at
> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
> at console.run(console.txt:25)
> {noformat}
--
This message was sent by Atlassian Jira
(v8.20.1#820001)