diff --git a/src/System.CommandLine.Tests/OptionTests.cs b/src/System.CommandLine.Tests/OptionTests.cs index 804af82386..f898c25024 100644 --- a/src/System.CommandLine.Tests/OptionTests.cs +++ b/src/System.CommandLine.Tests/OptionTests.cs @@ -512,5 +512,24 @@ public void Custom_parser_can_be_used_to_implement_int_binding_based_on_token_co result.GetValue(option).Should().Be(3); } + + [Fact] // https://github.com/dotnet/command-line-api/issues/2257 + public void Default_value_is_used_when_option_with_ZeroOrOne_arity_is_parsed_without_an_argument() + { + var option = new Option("-o") + { + Arity = ArgumentArity.ZeroOrOne, + DefaultValueFactory = _ => 42 + }; + + var rootCommand = new RootCommand + { + option + }; + + var parseResult = rootCommand.Parse("-o"); + + parseResult.GetValue(option).Should().Be(42); + } } } diff --git a/src/System.CommandLine/Parsing/ArgumentResult.cs b/src/System.CommandLine/Parsing/ArgumentResult.cs index ca969ab0ae..f076baa32f 100644 --- a/src/System.CommandLine/Parsing/ArgumentResult.cs +++ b/src/System.CommandLine/Parsing/ArgumentResult.cs @@ -153,7 +153,7 @@ private ArgumentConversionResult ValidateAndConvert(bool useValidators) } } - if (Parent!.UseDefaultValueFor(this)) + if (Argument.HasDefaultValue && Parent!.UseDefaultValueFor(this)) { var defaultValue = Argument.GetDefaultValue(this); diff --git a/src/System.CommandLine/Parsing/OptionResult.cs b/src/System.CommandLine/Parsing/OptionResult.cs index 478a3a9d23..c673a90458 100644 --- a/src/System.CommandLine/Parsing/OptionResult.cs +++ b/src/System.CommandLine/Parsing/OptionResult.cs @@ -64,6 +64,16 @@ internal bool IsArgumentLimitReached internal ArgumentConversionResult ArgumentConversionResult => _argumentConversionResult ??= GetResult(Option.Argument)!.GetArgumentConversionResult(); - internal override bool UseDefaultValueFor(ArgumentResult argument) => Implicit; + internal override bool UseDefaultValueFor(ArgumentResult argumentResult) + { + if (Implicit) + { + return true; + } + + return Tokens.Count is 0 && + Option.Arity is { MinimumNumberOfValues: 0, MaximumNumberOfValues: > 0 } && + !argumentResult.Argument.IsBoolean(); + } } }