You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
JewelCli 0.8.9 requires that the type of an option has a (String) constructor, but many value types do not meet this requirement.
Exception in thread "main" java.lang.ClassCastException: cannot convert class java.lang.String to interface java.nio.file.Path
at com.lexicalscope.jewel.cli.ConvertTypeOfObject.convertValueTo(ConvertTypeOfObject.java:159)
at com.lexicalscope.jewel.cli.ConvertTypeOfObject.convert(ConvertTypeOfObject.java:98)
at com.lexicalscope.jewel.cli.ArgumentPresenterImpl.putValuesInMap(ArgumentPresenterImpl.java:79)
at com.lexicalscope.jewel.cli.ArgumentPresenterImpl.presentArguments(ArgumentPresenterImpl.java:40)
at com.lexicalscope.jewel.cli.AbstractCliImpl.parseArguments(AbstractCliImpl.java:42)
The workaround is to build an intermediate type that parses a String into the desired type, but since JewelCli also does not support Java 8 default methods (#38), this cannot be done transparently.
Other option libraries such as jopt-simple (see withValuesConvertedBy) allow a factory method to be registered in case a constructor is not available or is otherwise undesirable.
Here's two different ways to do this:
Add a parser attribute to @Option that accepts a Class<? extends Function<String, ?>>. The main downside of this approach is that, as far as I know, we cannot guarantee the function return type matches the annotated method's return type at compile time. :( It can also cause some duplication if there are multiple arguments of the same type, but on the other hand it has the flexibility of allowing different parsers (or validators) for each argument as well.
Add a method to either Cli or CliFactory to register a parser, e.g. <T> Cli<O> withParser(Class<T>, Function<String, T>). The downside of this is that it is not aligned with the rest of JewelCli's annotation-centric API.
I think the first approach is more desirable since it maintains API consistency and option parsing tends to happen very early in the application, lessening the pain of errors at runtime.
The text was updated successfully, but these errors were encountered:
JewelCli 0.8.9 requires that the type of an option has a (String) constructor, but many value types do not meet this requirement.
The workaround is to build an intermediate type that parses a String into the desired type, but since JewelCli also does not support Java 8 default methods (#38), this cannot be done transparently.
Other option libraries such as jopt-simple (see withValuesConvertedBy) allow a factory method to be registered in case a constructor is not available or is otherwise undesirable.
Here's two different ways to do this:
Add a parser attribute to
@Option
that accepts aClass<? extends Function<String, ?>>
. The main downside of this approach is that, as far as I know, we cannot guarantee the function return type matches the annotated method's return type at compile time. :( It can also cause some duplication if there are multiple arguments of the same type, but on the other hand it has the flexibility of allowing different parsers (or validators) for each argument as well.Add a method to either Cli or CliFactory to register a parser, e.g.
<T> Cli<O> withParser(Class<T>, Function<String, T>)
. The downside of this is that it is not aligned with the rest of JewelCli's annotation-centric API.I think the first approach is more desirable since it maintains API consistency and option parsing tends to happen very early in the application, lessening the pain of errors at runtime.
The text was updated successfully, but these errors were encountered: