I’m probably overlooking something simple but I’m not seeing it yet. The below code demonstrates the issue when trying to pass a Groovy closure to the @Option(converter = ...)attribute:
class ClosureTest { static class Demo { @picocli.CommandLine.Option(names = "-x", completionCandidates = {["A", "B", "C"]}, converter = [{ str -> java.security.MessageDigest.getInstance(str) }]) java.security.MessageDigest digest } static void main(String[] args) { def annotation = Demo.class.getDeclaredField("digest").getAnnotation(picocli.CommandLine.Option) Class ok = annotation.completionCandidates() assert ok != null assert Closure.class.isAssignableFrom(ok) assert ["A", "B", "C"] == ((Closure) ok.getConstructor(Object, Object).newInstance(null, null)).call() Class[] bad = annotation.converter() assert bad != null assert bad.length == 1 // this assert fails: //Exception in thread "main" Assertion failed: // //assert bad.length == 1 // | | | // [] 0 false // // at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:434) // at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.assertFailed(ScriptBytecodeAdapter.java:670) // at closure.ClosureTest.main(ClosureTest.groovy:18) } } On Mon, Nov 16, 2020 at 21:16 Remko Popma <remko.po...@gmail.com> wrote: > PS > > The ITypeConverter interface definition is here: > https://picocli.info/apidocs/picocli/CommandLine.ITypeConverter.html > > > On Mon, Nov 16, 2020 at 21:08 Remko Popma <remko.po...@gmail.com> wrote: > >> Hi all, >> >> I have a question about passing closures to annotations in Groovy. >> To illustrate, consider the @Option annotation in the picocli library. >> Relevant attributes are `completionCandidates` and `converter`, defined >> in Java as follows: >> >> @Retention(RetentionPolicy.RUNTIME) >> @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) >> public @interface Option { >> Class<? extends ITypeConverter<?>>[] converter() default {}; >> Class<? extends Iterable<String>> completionCandidates() default >> NoCompletionCandidates.class; >> ... >> } >> >> I am working on a change to picocli >> <https://github.com/remkop/picocli/issues/1258> that would allow users >> to specify closures for these and other attributes. >> User code could look like this: >> >> @Option(names = '-s', completionCandidates = {["A", "B", "C"]}) >> @Field String s >> >> @Option(names = '-a', converter = [{ str -> >> MessageDigest.getInstance(str) }] ) >> @Field MessageDigest algorithm >> >> I think this would be a nice addition and would make picocli more >> "groovy". >> >> I have a prototype implementation, but it appears that only the first >> example ( completionCandidates = {["A", "B", "C"]} ) works as expected. >> When stepping through my prototype test in a debugger, it looks like the >> second example (the converter attribute) receives a zero-length array of >> classes when invoked from Groovy. I tried with Groovy 2.4.10 and 3.0.6. >> >> Is this a known limitation of Groovy? >> Is there a way to work around this? >> >> I can provide an example project to reproduce this if that is helpful. >> >> Kind regards, >> Remko >> >>