The documentation on handling errors says:
convert and the other parameter transformations will wrap exceptions thrown inside them in a UsageError, so if you define a custom transformation, you don’t have to worry about an exception escaping to the user.
Since validate is not technically a transformation, the documentation does not lie, but the usage is unintuitive.
I foolishly assumed the require function is the same as the Kotlin stdlib, however it is an overload in the context of the OptionValidator.
I have some type that requires some more complex validator that is too big to fit nicely in the option declaration site, so it is extracted in a separate function:
val foo by option("--foo").validate { customValidationLogic(it) }
However, when validation fails here, since the custom logic does not throw BadParameterValue, it crashes the program assuming it's a programming error.
As a workaround for the time being, one must either do validation logic inside a convert lambda, or manually wrap exceptions, I defined my own util for this:
inline fun <AllT, EachT, ValueT> OptionWithValues<AllT, EachT, ValueT>.validateCatching(
crossinline validator: OptionValidator<AllT & Any>,
): OptionDelegate<AllT> = copy(
transformValue,
transformEach,
transformAll,
validator = {
if (it != null) runCatching { validator(it) }.getOrElse { cause ->
throw BadParameterValue(cause.message.orEmpty(), option)
}
},
)
I believe the .validate {} lambda should match the behavior of the other transformers, to make it easier to use validation logic from functions that might come from external libraries, for example.
The documentation on handling errors says:
Since
validateis not technically a transformation, the documentation does not lie, but the usage is unintuitive.I foolishly assumed the
requirefunction is the same as the Kotlin stdlib, however it is an overload in the context of theOptionValidator.I have some type that requires some more complex validator that is too big to fit nicely in the option declaration site, so it is extracted in a separate function:
However, when validation fails here, since the custom logic does not throw
BadParameterValue, it crashes the program assuming it's a programming error.As a workaround for the time being, one must either do validation logic inside a
convertlambda, or manually wrap exceptions, I defined my own util for this:I believe the
.validate {}lambda should match the behavior of the other transformers, to make it easier to use validation logic from functions that might come from external libraries, for example.