From ed1f03a804de5979b8ae8df63971142d23422f7a Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Tue, 28 Feb 2023 15:44:12 +0100 Subject: [PATCH] Qute generated value resolvers - fix varArgs methods with 1 argument - fixes #31449 --- .../deployment/varargs/VarargsMethodTest.java | 35 ++++++++++++++++++- .../generator/ValueResolverGenerator.java | 28 ++++++++++++--- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/varargs/VarargsMethodTest.java b/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/varargs/VarargsMethodTest.java index 0cf8f640c6601..957bae5ac1151 100644 --- a/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/varargs/VarargsMethodTest.java +++ b/extensions/qute/deployment/src/test/java/io/quarkus/qute/deployment/varargs/VarargsMethodTest.java @@ -2,7 +2,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.Arrays; + import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Singleton; import org.jboss.shrinkwrap.api.asset.StringAsset; import org.junit.jupiter.api.Test; @@ -22,7 +26,13 @@ public class VarargsMethodTest { .addAsResource(new StringAsset("{foo.getStr}:{foo.getStr('foo','bar','baz')}"), "templates/foo.txt") .addAsResource(new StringAsset("{fmt.format('a','b','c')}"), - "templates/bar.txt")); + "templates/bar.txt") + .addAsResource(new StringAsset("{foo.getInt}:{foo.getInt(1)}:{foo.getInt(1,2,3)}"), + "templates/baz.txt") + .addAsResource( + new StringAsset( + "{cdi:qux.getBoolean(1)}:{cdi:qux.getBoolean(1, true, false)}:{cdi:qux.getBoolean(2, false)}"), + "templates/qux.txt"));; @Inject Template foo; @@ -30,15 +40,24 @@ public class VarargsMethodTest { @Inject Template bar; + @Inject + Template baz; + + @Inject + Template qux; + @Test public void testVarargs() { assertEquals("ok:foo:bar baz", foo.data("foo", new Foo()).render()); assertEquals(" b a", bar.data("fmt", "%2$2s%1$2s").render()); + assertEquals("[]:[1]:[1, 2, 3]", baz.data("foo", new Foo()).render()); + assertEquals("1 []:1 [true, false]:2 [false]", qux.render()); } @TemplateData(properties = false) public static class Foo { + // This one is ignored String getStr(String foo) { return foo; } @@ -52,6 +71,10 @@ public String getStr(String foo, String... args) { return foo + String.format(":%s %s", args[0], args[1]); } + public String getInt(int... args) { + return Arrays.toString(args); + } + @TemplateExtension static String format(String fmt, Object... args) { return String.format(fmt, args); @@ -59,4 +82,14 @@ static String format(String fmt, Object... args) { } + @Named + @Singleton + public static class Qux { + + public String getBoolean(int first, Boolean... args) { + return first + " " + Arrays.toString(args); + } + + } + } diff --git a/independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ValueResolverGenerator.java b/independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ValueResolverGenerator.java index fe00046e02921..05e62a4f268fe 100644 --- a/independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ValueResolverGenerator.java +++ b/independent-projects/qute/generator/src/main/java/io/quarkus/qute/generator/ValueResolverGenerator.java @@ -690,21 +690,41 @@ private void matchMethod(MethodInfo method, ClassInfo clazz, MethodCreator resol exception.invokeVirtualMethod(Descriptors.COMPLETABLE_FUTURE_COMPLETE_EXCEPTIONALLY, whenRet, exception.getCaughtException()); + ResultHandle[] realParamsHandle = paramsHandle; + if (isVarArgs(method)) { + // For varargs the number of results may be higher than the number of method params + // First get the regular params + realParamsHandle = new ResultHandle[parameterTypes.size()]; + for (int i = 0; i < parameterTypes.size() - 1; i++) { + ResultHandle resultHandle = tryCatch.invokeVirtualMethod(Descriptors.EVALUATED_PARAMS_GET_RESULT, + whenEvaluatedParams, tryCatch.load(i)); + realParamsHandle[i] = resultHandle; + } + // Then we need to create an array for the last argument + Type varargsParam = parameterTypes.get(parameterTypes.size() - 1); + ResultHandle componentType = tryCatch + .loadClass(varargsParam.asArrayType().component().name().toString()); + ResultHandle varargsResults = tryCatch.invokeVirtualMethod(Descriptors.EVALUATED_PARAMS_GET_VARARGS_RESULTS, + evaluatedParams, tryCatch.load(parameterTypes.size()), componentType); + // E.g. String, String, String -> String, String[] + realParamsHandle[parameterTypes.size() - 1] = varargsResults; + } + if (Modifier.isStatic(method.flags())) { if (Modifier.isInterface(clazz.flags())) { tryCatch.assign(invokeRet, - tryCatch.invokeStaticInterfaceMethod(MethodDescriptor.of(method), paramsHandle)); + tryCatch.invokeStaticInterfaceMethod(MethodDescriptor.of(method), realParamsHandle)); } else { tryCatch.assign(invokeRet, - tryCatch.invokeStaticMethod(MethodDescriptor.of(method), paramsHandle)); + tryCatch.invokeStaticMethod(MethodDescriptor.of(method), realParamsHandle)); } } else { if (Modifier.isInterface(clazz.flags())) { tryCatch.assign(invokeRet, - tryCatch.invokeInterfaceMethod(MethodDescriptor.of(method), whenBase, paramsHandle)); + tryCatch.invokeInterfaceMethod(MethodDescriptor.of(method), whenBase, realParamsHandle)); } else { tryCatch.assign(invokeRet, - tryCatch.invokeVirtualMethod(MethodDescriptor.of(method), whenBase, paramsHandle)); + tryCatch.invokeVirtualMethod(MethodDescriptor.of(method), whenBase, realParamsHandle)); } }