I created this:
https://issues.apache.org/jira/browse/GROOVY-9817

On Tue, Nov 17, 2020 at 2:11 PM Remko Popma <remko.po...@gmail.com> wrote:

> Eric and Paul,
> Thank you both for your responses!
>
> Paul,
> Thank you for your quick turnaround on supporting array annotations!
>
> I will create a Jira ticket when I get to my PC.
>
> Remko
>
> On Nov 17, 2020, at 12:24, Paul King <pa...@asert.com.au> wrote:
>
> 
> The following runs fine after adding in array support:
>
> import java.lang.annotation.*
> import org.codehaus.groovy.runtime.InvokerHelper
>
> class ClosureTest {
>     static class Demo {
>         @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.getDeclaredField("digest").getAnnotation(Option)
>         Class comp = annotation.completionCandidates()
>         assert comp != null
>         assert Closure.isAssignableFrom(comp)
>         assert ["A", "B", "C"] == InvokerHelper.invokeConstructorOf(comp,
> [null, null] as Object[])()
>
>         Class[] conv = annotation.converter()
>         assert conv != null
>         assert conv.length == 1
>         assert Closure.isAssignableFrom(conv[0])
>         assert 'SHA-1' == InvokerHelper.invokeConstructorOf(conv[0],
> [null, null] as Object[])('SHA-1').algorithm
>     }
> }
>
> interface ITypeConverter<K> {
>     K convert(String value) throws Exception
> }
>
> class NoCompletionCandidates {}
>
> @Retention(RetentionPolicy.RUNTIME)
> @Target([ElementType.FIELD])
> @interface Option {
>     Class<? extends ITypeConverter<?>>[] converter() default []
>     Class<? extends Iterable<String>> completionCandidates() default
> NoCompletionCandidates
>     String names()
> }
>
> Probably worth adding. Did you want to create a Jira?
>
> Cheers, Paul.
>
>
> On Tue, Nov 17, 2020 at 12:32 PM Paul King <pa...@asert.com.au> wrote:
>
>> The Closure to Class conversion doesn't currently support arrays. If you
>> change  converter() to take just a single convert, your example works
>> for me.
>>
>> Supporting arrays might be an interesting enhancement. I'll take a look
>> at what would be involved.
>>
>> Cheers, Paul.
>>
>>
>> On Tue, Nov 17, 2020 at 11:02 AM Remko Popma <remko.po...@gmail.com>
>> wrote:
>>
>>> 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
>>>>>
>>>>>

Reply via email to