dotnet / command-line-api

Command line parsing, invocation, and rendering of terminal output.
https://github.com/dotnet/command-line-api/wiki
MIT License
3.37k stars 378 forks source link

Completions for multiple arity options #1727

Open JanKrivanek opened 2 years ago

JanKrivanek commented 2 years ago

I'm failing to get proper behavior for some cases of tab copletion of multiple arity option. I've simplified my case to following simple repro:

var myCommand = new Command("cmdx");
var option = new Option<string>("--testOption")
{
    IsRequired = true,
    Arity = new ArgumentArity(1, 3)
};
option.FromAmong("val1", "val2", "val3");
myCommand.AddOption(option);

var parseResult = myCommand.Parse($"cmdx --testOption val2 --testO");
var completions = parseResult.GetCompletions().Select(l => l.Label);
Assert.Equal(new[] { "--testOption" }, completions);

Observed behavior: This fails already during Parse call:

ArgumentConverter.CreateEnumerable(Type type, Type itemType, Int32 capacity)
ArgumentConverter.ConvertTokens(Argument argument, Type type, IReadOnlyList`1 tokens, LocalizationResources localizationResources, ArgumentResult argumentResult)
ArgumentConverter.TryConvertArgument(ArgumentResult argumentResult, Object& value)
ArgumentResult.Convert(Argument argument)
ArgumentResult.GetArgumentConversionResult()
ParseResultVisitor.ValidateAndConvertArgumentResult(ArgumentResult argumentResult)
ParseResultVisitor.ValidateAndConvertOptionResult(OptionResult optionResult)
ParseResultVisitor.Stop()
ParseResultVisitor.Visit(SyntaxNode node)
Parser.Parse(IReadOnlyList`1 arguments, String rawInput)
ParserExtensions.Parse(Parser parser, String commandLine)
CommandExtensions.Parse(Command command, String commandLine)

with System.ArgumentException : Type System.String cannot be created without a custom binder.

Looks like TryConvertArgument attempts for multiple arity options to interpret string argument as enumeration (https://github.com/dotnet/command-line-api/blob/main/src/System.CommandLine/Binding/ArgumentConverter.cs#L229)

Expected behavior: The above test case works as is.

Let me know if there is any further setup needed to make completions work as expected for multi-arity options.

Drizin commented 2 years ago

I was having the same error when I increased the Arity of Argument<string>, but all I had to do was changing it to Argument<string[]>

JanKrivanek commented 2 years ago

@Drizin Good point! Changing Option<string> to Option<string[]> in the above sample resolved the exception. Though it still doesn't produce the expected completion (empty result is returned).