This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push: new 290cd3f72f GROOVY-8045: support coercion for variadic parameter 290cd3f72f is described below commit 290cd3f72f381bb2752a14595b1245af81f67c26 Author: Eric Milles <eric.mil...@thomsonreuters.com> AuthorDate: Wed May 25 15:40:57 2022 -0500 GROOVY-8045: support coercion for variadic parameter --- .../codehaus/groovy/reflection/ParameterTypes.java | 123 ++++++++++----------- .../groovy/transform/stc/CoercionSTCTest.groovy | 11 ++ 2 files changed, 69 insertions(+), 65 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/reflection/ParameterTypes.java b/src/main/java/org/codehaus/groovy/reflection/ParameterTypes.java index 86056e578b..59a745b9a1 100644 --- a/src/main/java/org/codehaus/groovy/reflection/ParameterTypes.java +++ b/src/main/java/org/codehaus/groovy/reflection/ParameterTypes.java @@ -235,19 +235,17 @@ public class ParameterTypes { return result; } - public boolean isValidMethod(Class[] arguments) { - if (arguments == null) return true; - - final int size = arguments.length; + public boolean isValidMethod(Class[] argumentTypes) { + if (argumentTypes == null) return true; CachedClass[] pt = getParameterTypes(); - final int paramMinus1 = pt.length - 1; - - if (isVargsMethod && size >= paramMinus1) - return isValidVarargsMethod(arguments, size, pt, paramMinus1); - else if (pt.length == size) - return isValidExactMethod(arguments, pt); - else if (pt.length == 1 && size == 0 && !pt[0].isPrimitive) - return true; + final int nArguments = argumentTypes.length, nParameters = pt.length, nthParameter = nParameters - 1; + + if (isVargsMethod && nArguments >= nthParameter) + return isValidVargsMethod(argumentTypes, pt, nthParameter); + else if (nArguments == nParameters) + return isValidExactMethod(argumentTypes, pt); + else if (nArguments == 0 && nParameters == 1 && !pt[0].isPrimitive) + return true; // implicit null argument return false; } @@ -292,77 +290,72 @@ public class ParameterTypes { return true; } - private static boolean testComponentAssignable(Class toTestAgainst, Class toTest) { - Class component = toTest.getComponentType(); - if (component == null) return false; - return MetaClassHelper.isAssignableFrom(toTestAgainst, component); - } - - private static boolean isValidVarargsMethod(Class[] arguments, int size, CachedClass[] pt, int paramMinus1) { - // first check normal number of parameters - for (int i = 0; i < paramMinus1; i++) { - if (pt[i].isAssignableFrom(arguments[i])) continue; - return false; + private static boolean isValidVargsMethod(Class[] argumentTypes, CachedClass[] parameterTypes, int nthParameter) { + for (int i = 0; i < nthParameter; i += 1) { + if (!parameterTypes[i].isAssignableFrom(argumentTypes[i])) { + return false; + } } + CachedClass arrayType = parameterTypes[nthParameter]; + CachedClass componentType = ReflectionCache.getCachedClass(arrayType.getTheClass().getComponentType()); + // check direct match - CachedClass varg = pt[paramMinus1]; - Class clazz = varg.getTheClass().getComponentType(); - if (size == pt.length && - (varg.isAssignableFrom(arguments[paramMinus1]) || - testComponentAssignable(clazz, arguments[paramMinus1]))) { - return true; + if (argumentTypes.length == parameterTypes.length) { + Class argumentType = argumentTypes[nthParameter]; + if (arrayType.isAssignableFrom(argumentType) || (argumentType.isArray() + && componentType.isAssignableFrom(argumentType.getComponentType()))) { + return true; + } } - // check varged - for (int i = paramMinus1; i < size; i++) { - if (MetaClassHelper.isAssignableFrom(clazz, arguments[i])) continue; - return false; + // check vararg match + for (int i = nthParameter; i < argumentTypes.length; i += 1) { + if (!componentType.isAssignableFrom(argumentTypes[i])) { + return false; + } } + return true; } public boolean isValidMethod(Object[] arguments) { if (arguments == null) return true; - - final int size = arguments.length; - CachedClass[] paramTypes = getParameterTypes(); - final int paramMinus1 = paramTypes.length - 1; - - if (size >= paramMinus1 && paramTypes.length > 0 && - paramTypes[(paramMinus1)].isArray) { - // first check normal number of parameters - for (int i = 0; i < paramMinus1; i++) { - if (paramTypes[i].isAssignableFrom(getArgClass(arguments[i]))) continue; - return false; + final CachedClass[] parameterTypes = getParameterTypes(); + final int nArguments = arguments.length, nParameters = parameterTypes.length, nthParameter = nParameters - 1; + + if (nParameters > 0 && parameterTypes[nthParameter].isArray && nArguments >= nthParameter) { + for (int i = 0; i < nthParameter; i += 1) { + if (!parameterTypes[i].isAssignableFrom(getArgClass(arguments[i]))) { + return false; + } } - - + CachedClass arrayType = parameterTypes[nthParameter]; + CachedClass componentType = ReflectionCache.getCachedClass(arrayType.getTheClass().getComponentType()); // check direct match - CachedClass varg = paramTypes[paramMinus1]; - Class clazz = varg.getTheClass().getComponentType(); - if (size == paramTypes.length && - (varg.isAssignableFrom(getArgClass(arguments[paramMinus1])) || - testComponentAssignable(clazz, getArgClass(arguments[paramMinus1])))) { - return true; + if (nArguments == parameterTypes.length) { + Class argumentType = getArgClass(arguments[nthParameter]); + if (arrayType.isAssignableFrom(argumentType) || (argumentType.isArray() + && componentType.isAssignableFrom(argumentType.getComponentType()))) { + return true; + } } - - - // check varged - for (int i = paramMinus1; i < size; i++) { - if (MetaClassHelper.isAssignableFrom(clazz, getArgClass(arguments[i]))) continue; - return false; + // check vararg match + for (int i = nthParameter; i < nArguments; i += 1) { + if (!componentType.isAssignableFrom(getArgClass(arguments[i]))) { + return false; + } } return true; - } else if (paramTypes.length == size) { - // lets check the parameter types match - for (int i = 0; i < size; i++) { - if (paramTypes[i].isAssignableFrom(getArgClass(arguments[i]))) continue; - return false; + } else if (nArguments == nParameters) { + for (int i = 0; i < nArguments; i += 1) { + if (!parameterTypes[i].isAssignableFrom(getArgClass(arguments[i]))) { + return false; + } } return true; - } else if (paramTypes.length == 1 && size == 0 && !paramTypes[0].isPrimitive) { - return true; + } else if (nArguments == 0 && nParameters == 1 && !parameterTypes[0].isPrimitive) { + return true; // implicit null argument } return false; } diff --git a/src/test/groovy/transform/stc/CoercionSTCTest.groovy b/src/test/groovy/transform/stc/CoercionSTCTest.groovy index 2c100508b7..35f6a1be2c 100644 --- a/src/test/groovy/transform/stc/CoercionSTCTest.groovy +++ b/src/test/groovy/transform/stc/CoercionSTCTest.groovy @@ -158,4 +158,15 @@ class CoercionSTCTest extends StaticTypeCheckingTestCase { def s = (() -> ['']) as Supplier<Number> ''', 'Cannot return value of type java.util.List<java.lang.String> for lambda expecting java.lang.Number' } + + // GROOVY-8045 + void testCoerceToFunctionalInterface2() { + assertScript '''import java.util.function.* + def f(Supplier<Integer>... suppliers) { + suppliers*.get().sum() + } + Object result = f({->1},{->2}) + assert result == 3 + ''' + } }