-
Notifications
You must be signed in to change notification settings - Fork 403
Open
Description
If the default or custom parser for an Option
adds an error, its Validators
are still run. This is a problem because an exception will be thrown when a validator tries to get the value. Here is an example:
using System.CommandLine;
Option<int> intOption = new("--int")
{
Validators =
{
result =>
{
int value = result.GetValueOrDefault<int>();
if (value < 1)
result.AddError("Value must be at least 1.");
}
}
};
RootCommand command = new()
{
intOption
};
command.SetAction(result => Console.WriteLine("Command ran successfully"));
command.Parse(["--int", "nonsense"]).Invoke();
Running the code on my system gives this hostile error message:
Unhandled exception. System.InvalidOperationException: Cannot parse argument 'nonsense' for option '--int' as expected type 'System.Int32'.
at System.CommandLine.Binding.ArgumentConverter.GetValueOrDefault[T](ArgumentConversionResult result)
at System.CommandLine.Parsing.OptionResult.GetValueOrDefault[T]()
at Program.<>c.<<Main>$>b__0_1(OptionResult result) in /home/choosechee/RiderProjects/CommandLineIssue/CommandLineIssue/Program.cs:line 9
at System.CommandLine.Parsing.CommandResult.ValidateOptions(Boolean completeValidation)
at System.CommandLine.Parsing.CommandResult.Validate(Boolean completeValidation)
at System.CommandLine.Parsing.ParseOperation.Validate()
at System.CommandLine.Parsing.ParseOperation.Parse()
at System.CommandLine.Parsing.CommandLineParser.Parse(Command command, IReadOnlyList`1 arguments, String rawInput, CommandLineConfiguration configuration)
at System.CommandLine.Parsing.CommandLineParser.Parse(Command command, IReadOnlyList`1 args, CommandLineConfiguration configuration)
at System.CommandLine.Command.Parse(IReadOnlyList`1 args, CommandLineConfiguration configuration)
at Program.<Main>$(String[] args) in /home/choosechee/RiderProjects/CommandLineIssue/CommandLineIssue/Program.cs:line 22
Process finished with exit code 134.
If I remove the validator, it gives the expected friendlier error message:
Cannot parse argument 'nonsense' for option '--int' as expected type 'System.Int32'.
Description:
Usage:
CommandLineIssue [options]
Options:
-?, -h, --help Show help and usage information
--version Show version information
--int
Process finished with exit code 0.
It happens with a CustomParser
as well:
using System.CommandLine;
Option<int> intOption = new("--int")
{
CustomParser = result =>
{
if (int.TryParse(result.Tokens.Single().Value, out int value))
return value;
result.AddError("Value must be an integer."); // cause of exception
return -1;
},
Validators =
{
result =>
{
int value = result.GetValueOrDefault<int>();
if (value < 1)
result.AddError("Value must be at least 1.");
}
}
};
RootCommand command = new()
{
intOption
};
command.SetAction(result => Console.WriteLine("Command ran successfully"));
command.Parse(["--int", "nonsense"]).Invoke();
Unhandled exception. System.InvalidOperationException: Value must be an integer.
at System.CommandLine.Binding.ArgumentConverter.GetValueOrDefault[T](ArgumentConversionResult result)
at System.CommandLine.Parsing.OptionResult.GetValueOrDefault[T]()
...yadda yadda yadda
Process finished with exit code 134.
I can put the validator code that gets the value in a try-catch block to fix this, but I think this is unintuitive to have to do this. I think Validators
should not be run when parsing fails, or at least run in a try-catch block to handle these exceptions.
Metadata
Metadata
Assignees
Labels
No labels