And this:
https://github.com/apache/groovy/pull/1420


On Tue, Nov 17, 2020 at 5:45 PM Paul King <pa...@asert.com.au> wrote:

> 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