From 8e3a00f0b557b67421802b5e1cd72a938b197fb3 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 10 Jan 2021 15:30:10 -0800 Subject: [PATCH 1/6] Update option/argument .Value to reflect .DefaultValue --- src/CommandLineUtils/CommandArgument.cs | 16 ++- src/CommandLineUtils/CommandArgument{T}.cs | 36 ++++++- src/CommandLineUtils/CommandOption.cs | 16 ++- src/CommandLineUtils/CommandOption{T}.cs | 37 ++++++- src/CommandLineUtils/PublicAPI.Unshipped.txt | 2 + .../CommandArgumentTests.cs | 101 ++++++++++++++++++ .../CommandOptionTests.cs | 92 ++++++++++++++++ .../DefaultHelpTextGeneratorTests.cs | 6 +- .../CommandLineUtils.Tests/ValidationTests.cs | 2 +- 9 files changed, 291 insertions(+), 17 deletions(-) create mode 100644 test/CommandLineUtils.Tests/CommandArgumentTests.cs diff --git a/src/CommandLineUtils/CommandArgument.cs b/src/CommandLineUtils/CommandArgument.cs index 24264d82..9e725533 100644 --- a/src/CommandLineUtils/CommandArgument.cs +++ b/src/CommandLineUtils/CommandArgument.cs @@ -36,7 +36,17 @@ public class CommandArgument /// /// All values specified, if any. /// - public IReadOnlyList Values => _values; + public IReadOnlyList Values + { + get + { + if (_values.Count == 0 && DefaultValue != null) + { + return new List { DefaultValue }; + } + return _values; + } + } /// /// Allow multiple values. @@ -54,9 +64,9 @@ public class CommandArgument public string? DefaultValue { get; set; } /// - /// True if this argument has been assigned values. + /// True when is not empty or when a is given. /// - public bool HasValue => Values.Any(); + public bool HasValue => _values.Count != 0 || DefaultValue != null; /// /// A collection of validators that execute before invoking . diff --git a/src/CommandLineUtils/CommandArgument{T}.cs b/src/CommandLineUtils/CommandArgument{T}.cs index bc99a216..567297d3 100644 --- a/src/CommandLineUtils/CommandArgument{T}.cs +++ b/src/CommandLineUtils/CommandArgument{T}.cs @@ -20,6 +20,8 @@ public class CommandArgument : CommandArgument, IInternalCommandParamOfT { private readonly List _parsedValues = new List(); private readonly IValueParser _valueParser; + private bool _hasBeenParsed; + private bool _hasDefaultValue; private T _defaultValue; /// @@ -29,19 +31,35 @@ public class CommandArgument : CommandArgument, IInternalCommandParamOfT public CommandArgument(IValueParser valueParser) { _valueParser = valueParser ?? throw new ArgumentNullException(nameof(valueParser)); + DefaultValue = default; UnderlyingType = typeof(T); - SetBaseDefaultValue(default); } /// /// The parsed value. /// - public T ParsedValue => _parsedValues.FirstOrDefault(); + public T ParsedValue => ParsedValues.FirstOrDefault(); /// /// All parsed values; /// - public IReadOnlyList ParsedValues => _parsedValues; + public IReadOnlyList ParsedValues + { + get + { + if (!_hasBeenParsed) + { + ((IInternalCommandParamOfT)this).Parse(CultureInfo.CurrentCulture); + } + + if (_parsedValues.Count == 0 && _hasDefaultValue) + { + return new[] { DefaultValue }; + } + + return _parsedValues; + } + } /// /// The default value of the argument. @@ -51,6 +69,7 @@ public CommandArgument(IValueParser valueParser) get => _defaultValue; set { + _hasDefaultValue = value != null; _defaultValue = value; SetBaseDefaultValue(value); } @@ -58,8 +77,9 @@ public CommandArgument(IValueParser valueParser) void IInternalCommandParamOfT.Parse(CultureInfo culture) { + _hasBeenParsed = true; _parsedValues.Clear(); - foreach (var t in Values) + foreach (var t in base._values) { _parsedValues.Add(_valueParser.Parse(Name, t, culture)); } @@ -79,5 +99,13 @@ void SetBaseDefaultValue(T value) } } } + + /// + public override void Reset() + { + _hasBeenParsed = false; + _parsedValues.Clear(); + base.Reset(); + } } } diff --git a/src/CommandLineUtils/CommandOption.cs b/src/CommandLineUtils/CommandOption.cs index df1010df..3a7cfb47 100644 --- a/src/CommandLineUtils/CommandOption.cs +++ b/src/CommandLineUtils/CommandOption.cs @@ -100,7 +100,17 @@ internal CommandOption(CommandOptionType type) /// /// Any values found during parsing, if any. /// - public IReadOnlyList Values => _values; + public IReadOnlyList Values + { + get + { + if (_values.Count == 0 && DefaultValue != null) + { + return new List { DefaultValue }; + } + return _values; + } + } /// /// The default value of the option. @@ -171,12 +181,12 @@ public bool TryParse(string? value) } /// - /// True when is not empty. + /// True when is not empty or when a is given. /// /// public bool HasValue() { - return Values.Any(); + return _values.Any() || DefaultValue != null; } /// diff --git a/src/CommandLineUtils/CommandOption{T}.cs b/src/CommandLineUtils/CommandOption{T}.cs index f3dcbe7a..e7c47c51 100644 --- a/src/CommandLineUtils/CommandOption{T}.cs +++ b/src/CommandLineUtils/CommandOption{T}.cs @@ -21,6 +21,8 @@ public class CommandOption : CommandOption, IInternalCommandParamOfT private readonly List _parsedValues = new List(); private readonly IValueParser _valueParser; private T _defaultValue; + private bool _hasDefaultValue; + private bool _hasBeenParsed; /// /// Initializes a new instance of @@ -32,6 +34,7 @@ public CommandOption(IValueParser valueParser, string template, CommandOption : base(template, optionType) { _valueParser = valueParser ?? throw new ArgumentNullException(nameof(valueParser)); + DefaultValue = default; UnderlyingType = typeof(T); SetBaseDefaultValue(default); } @@ -39,12 +42,28 @@ public CommandOption(IValueParser valueParser, string template, CommandOption /// /// The parsed value. /// - public T ParsedValue => _parsedValues.FirstOrDefault(); + public T ParsedValue => ParsedValues.FirstOrDefault(); /// /// All parsed values; /// - public IReadOnlyList ParsedValues => _parsedValues; + public IReadOnlyList ParsedValues + { + get + { + if (!_hasBeenParsed) + { + ((IInternalCommandParamOfT)this).Parse(CultureInfo.CurrentCulture); + } + + if (_values.Count == 0 && _hasDefaultValue) + { + return new[] { DefaultValue }; + } + + return _parsedValues; + } + } /// /// The default value of the option. @@ -54,6 +73,7 @@ public CommandOption(IValueParser valueParser, string template, CommandOption get => _defaultValue; set { + _hasDefaultValue = value != null; _defaultValue = value; SetBaseDefaultValue(value); } @@ -61,14 +81,15 @@ public CommandOption(IValueParser valueParser, string template, CommandOption void IInternalCommandParamOfT.Parse(CultureInfo culture) { + _hasBeenParsed = true; _parsedValues.Clear(); - foreach (var t in Values) + foreach (var t in base._values) { _parsedValues.Add(_valueParser.Parse(LongName ?? ShortName ?? SymbolName, t, culture)); } } - void SetBaseDefaultValue(T value) + private void SetBaseDefaultValue(T value) { if (!ReflectionHelper.IsSpecialValueTupleType(typeof(T), out _)) { @@ -82,5 +103,13 @@ void SetBaseDefaultValue(T value) } } } + + /// + public override void Reset() + { + _hasBeenParsed = false; + _parsedValues.Clear(); + base.Reset(); + } } } diff --git a/src/CommandLineUtils/PublicAPI.Unshipped.txt b/src/CommandLineUtils/PublicAPI.Unshipped.txt index 5018755e..7e1caaec 100644 --- a/src/CommandLineUtils/PublicAPI.Unshipped.txt +++ b/src/CommandLineUtils/PublicAPI.Unshipped.txt @@ -3,5 +3,7 @@ McMaster.Extensions.CommandLineUtils.CommandArgument.HasValue.get -> bool McMaster.Extensions.CommandLineUtils.CommandArgument.TryParse(string? value) -> bool virtual McMaster.Extensions.CommandLineUtils.CommandArgument.Reset() -> void virtual McMaster.Extensions.CommandLineUtils.CommandOption.Reset() -> void +override McMaster.Extensions.CommandLineUtils.CommandArgument.Reset() -> void +override McMaster.Extensions.CommandLineUtils.CommandOption.Reset() -> void McMaster.Extensions.CommandLineUtils.CommandLineApplication.AddArgument(McMaster.Extensions.CommandLineUtils.CommandArgument! argument) -> void McMaster.Extensions.CommandLineUtils.CommandLineApplication.AddOption(McMaster.Extensions.CommandLineUtils.CommandOption! option) -> void diff --git a/test/CommandLineUtils.Tests/CommandArgumentTests.cs b/test/CommandLineUtils.Tests/CommandArgumentTests.cs new file mode 100644 index 00000000..d0b98a76 --- /dev/null +++ b/test/CommandLineUtils.Tests/CommandArgumentTests.cs @@ -0,0 +1,101 @@ +// Copyright (c) Nate McMaster. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using McMaster.Extensions.CommandLineUtils.Abstractions; +using Xunit; + +namespace McMaster.Extensions.CommandLineUtils.Tests +{ + public class CommandArgumentTests + { + + [Fact] + public void AlwaysHasDefaultValueForValueTypes() + { + var app = new CommandLineApplication(); + var argument = app.Argument("abc", "xyz"); + Assert.Equal(default, argument.DefaultValue); + Assert.True(argument.HasValue()); + } + + [Fact] + public void DoesNotHaveDefaultForReferenceTypes() + { + var app = new CommandLineApplication(); + var argument = app.Argument("abc", "xyz"); + Assert.Null(argument.DefaultValue); + Assert.False(argument.HasValue()); + } + + [Fact] + public void DefaultValueReturnedIfUnset() + { + var option = new CommandArgument + { + DefaultValue = "ABC" + }; + + Assert.Equal("ABC", option.Value); + Assert.Equal(new List { "ABC" }, option.Values); + } + + [Fact] + public void DefaultValueOfTReturnedIfUnset() + { + var option = new CommandArgument(StockValueParsers.Int32) + { + DefaultValue = 42 + }; + + Assert.Equal("42", option.Value); + Assert.Equal(new List { "42" }, option.Values); + Assert.Equal(42, option.ParsedValue); + Assert.Equal(new List { 42 }, option.ParsedValues); + } + + [Fact] + public void DefaultOverriddenBySettingValue() + { + var option = new CommandArgument + { + DefaultValue = "ABC" + }; + + option.TryParse("xyz"); + + Assert.Equal("xyz", option.Value); + } + + [Fact] + public void DefaultOfTOverriddenBySettingValue() + { + var option = new CommandArgument(StockValueParsers.Int32) + { + DefaultValue = 42 + }; + + option.TryParse("999"); + + Assert.Equal("999", option.Value); + Assert.Equal(new List { "999" }, option.Values); + Assert.Equal(999, option.ParsedValue); + Assert.Equal(new List { 999 }, option.ParsedValues); + } + + [Fact] + public void DefaultOverriddenAndResetReturnsDefault() + { + var option = new CommandArgument + { + DefaultValue = "ABC" + }; + + option.TryParse("xyz"); + + option.Reset(); + + Assert.Equal("ABC", option.Value); + } + } +} diff --git a/test/CommandLineUtils.Tests/CommandOptionTests.cs b/test/CommandLineUtils.Tests/CommandOptionTests.cs index afa16678..4da28443 100644 --- a/test/CommandLineUtils.Tests/CommandOptionTests.cs +++ b/test/CommandLineUtils.Tests/CommandOptionTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Nate McMaster. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections.Generic; +using McMaster.Extensions.CommandLineUtils.Abstractions; using Xunit; namespace McMaster.Extensions.CommandLineUtils.Tests @@ -46,5 +48,95 @@ public void ItParsesSingleOrNoValueTemplate(string template, string shortName, s Assert.Equal(longName, opt.LongName); Assert.Equal(valueName, opt.ValueName); } + + [Fact] + public void DefaultValueReturnedIfUnset() + { + var option = new CommandOption("--value ", CommandOptionType.SingleValue) + { + DefaultValue = "ABC" + }; + + Assert.True(option.HasValue()); + Assert.Equal("ABC", option.Value()); + Assert.Equal(new List { "ABC" }, option.Values); + } + + [Fact] + public void DefaultValueOfTReturnedIfUnset() + { + var option = new CommandOption(StockValueParsers.Int32, "--value ", CommandOptionType.SingleValue) + { + DefaultValue = 42 + }; + + Assert.True(option.HasValue()); + Assert.Equal("42", option.Value()); + Assert.Equal(new List { "42" }, option.Values); + Assert.Equal(42, option.ParsedValue); + Assert.Equal(new List { 42 }, option.ParsedValues); + } + + [Fact] + public void AlwaysHasDefaultValueForValueTypes() + { + var app = new CommandLineApplication(); + var option = app.Option("--value ", "abc", CommandOptionType.SingleValue); + Assert.Equal(default, option.DefaultValue); + Assert.True(option.HasValue()); + } + + [Fact] + public void DoesNotHaveDefaultForReferenceTypes() + { + var app = new CommandLineApplication(); + var option = app.Option("--value ", "abc", CommandOptionType.SingleValue); + Assert.Null(option.DefaultValue); + Assert.False(option.HasValue()); + } + + [Fact] + public void DefaultOverriddenBySettingValue() + { + var option = new CommandOption("--value ", CommandOptionType.SingleValue) + { + DefaultValue = "ABC" + }; + + option.TryParse("xyz"); + + Assert.Equal("xyz", option.Value()); + } + + [Fact] + public void DefaultOfTOverriddenBySettingValue() + { + var option = new CommandOption(StockValueParsers.Int32, "--value ", CommandOptionType.SingleValue) + { + DefaultValue = 42 + }; + + option.TryParse("999"); + + Assert.Equal("999", option.Value()); + Assert.Equal(new List { "999" }, option.Values); + Assert.Equal(999, option.ParsedValue); + Assert.Equal(new List { 999 }, option.ParsedValues); + } + + [Fact] + public void DefaultOverriddenAndResetReturnsDefault() + { + var option = new CommandOption("--value ", CommandOptionType.SingleValue) + { + DefaultValue = "ABC" + }; + + option.TryParse("xyz"); + + option.Reset(); + + Assert.Equal("ABC", option.Value()); + } } } diff --git a/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs b/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs index 802de6e7..04b0b476 100644 --- a/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs +++ b/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs @@ -121,9 +121,11 @@ public void ShowHelp() app.Argument("RestrictedStringArgument", "restricted string arg desc.", a => a.IsRequired().Accepts().Values("Foo", "Bar")); app.Argument("DefaultValStringArgument", "string arg with default value desc.", a => a.DefaultValue = "Foo"); app.Argument("SomeEnumArgument", "enum arg desc."); - app.Argument("RestrictedEnumArgument", "restricted enum arg desc.", a => a.Accepts().Values("None", "Normal")); + var a = app.Argument("RestrictedEnumArgument", "restricted enum arg desc.", a => a.Accepts().Values("None", "Normal")); + a.DefaultValue = SomeEnum.Normal; app.Argument<(bool, SomeEnum)>("SomeNullableEnumArgument", "nullable enum arg desc."); var helpText = GetHelpText(app); + _output.WriteLine(helpText); Assert.Equal(@"Usage: [options] @@ -138,7 +140,7 @@ SomeEnumArgument enum arg desc. Default value is: None. RestrictedEnumArgument restricted enum arg desc. Allowed values are: None, Normal. - Default value is: None. + Default value is: Normal. SomeNullableEnumArgument nullable enum arg desc. Allowed values are: None, Normal, Extreme. diff --git a/test/CommandLineUtils.Tests/ValidationTests.cs b/test/CommandLineUtils.Tests/ValidationTests.cs index 0fd79fd4..1b4e3ce2 100644 --- a/test/CommandLineUtils.Tests/ValidationTests.cs +++ b/test/CommandLineUtils.Tests/ValidationTests.cs @@ -37,7 +37,7 @@ public void ValidationHandlerOfSubcommandIsInvoked() var sub = app.Command("sub", c => { }); var called = false; sub.OnValidationError(_ => called = true); - CommandArgument arg = sub.Argument("t", "test").IsRequired(); + var arg = sub.Argument("t", "test").IsRequired(); Assert.NotEqual(0, app.Execute("sub")); Assert.True(called, "Validation on subcommand should be called"); } From abafa73236f1bf8c0dab7c5b68757acc6a65ebb8 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 10 Jan 2021 15:37:01 -0800 Subject: [PATCH 2/6] fixup! Update option/argument .Value to reflect .DefaultValue --- test/CommandLineUtils.Tests/CommandArgumentTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CommandLineUtils.Tests/CommandArgumentTests.cs b/test/CommandLineUtils.Tests/CommandArgumentTests.cs index d0b98a76..59a09eee 100644 --- a/test/CommandLineUtils.Tests/CommandArgumentTests.cs +++ b/test/CommandLineUtils.Tests/CommandArgumentTests.cs @@ -16,7 +16,7 @@ public void AlwaysHasDefaultValueForValueTypes() var app = new CommandLineApplication(); var argument = app.Argument("abc", "xyz"); Assert.Equal(default, argument.DefaultValue); - Assert.True(argument.HasValue()); + Assert.True(argument.HasValue); } [Fact] @@ -25,7 +25,7 @@ public void DoesNotHaveDefaultForReferenceTypes() var app = new CommandLineApplication(); var argument = app.Argument("abc", "xyz"); Assert.Null(argument.DefaultValue); - Assert.False(argument.HasValue()); + Assert.False(argument.HasValue); } [Fact] From f10f447f7b16d9958876128a352c262d7a42bb5b Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 10 Jan 2021 16:33:11 -0800 Subject: [PATCH 3/6] fixup! fixup! Update option/argument .Value to reflect .DefaultValue --- Directory.Build.props | 2 +- src/CommandLineUtils/CommandArgument.cs | 4 +- src/CommandLineUtils/CommandArgument{T}.cs | 6 +-- src/CommandLineUtils/CommandOption.cs | 9 ++-- src/CommandLineUtils/CommandOption{T}.cs | 10 ++-- src/CommandLineUtils/PublicAPI.Shipped.txt | 8 --- src/CommandLineUtils/PublicAPI.Unshipped.txt | 8 +++ .../CommandArgumentTests.cs | 50 ++++++++++--------- .../CommandOptionTests.cs | 36 ++++++------- .../DefaultHelpTextGeneratorTests.cs | 11 ++-- .../CommandLineUtils.Tests/ValidationTests.cs | 2 +- 11 files changed, 73 insertions(+), 73 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index b0d18da2..db23f03e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -30,7 +30,7 @@ true $(WarningsNotAsErrors);1591 - 8.0 + 9.0 annotations $(MSBuildThisFileDirectory)src\StrongName.snk true diff --git a/src/CommandLineUtils/CommandArgument.cs b/src/CommandLineUtils/CommandArgument.cs index 9e725533..5d6ffee8 100644 --- a/src/CommandLineUtils/CommandArgument.cs +++ b/src/CommandLineUtils/CommandArgument.cs @@ -54,7 +54,7 @@ public IReadOnlyList Values public bool MultipleValues { get; set; } /// - /// The first value from , if any. + /// The first value from , if any, or . /// public string? Value => Values.FirstOrDefault(); @@ -66,7 +66,7 @@ public IReadOnlyList Values /// /// True when is not empty or when a is given. /// - public bool HasValue => _values.Count != 0 || DefaultValue != null; + public bool HasValue => Values.Any(); /// /// A collection of validators that execute before invoking . diff --git a/src/CommandLineUtils/CommandArgument{T}.cs b/src/CommandLineUtils/CommandArgument{T}.cs index 567297d3..23e6d097 100644 --- a/src/CommandLineUtils/CommandArgument{T}.cs +++ b/src/CommandLineUtils/CommandArgument{T}.cs @@ -17,12 +17,13 @@ namespace McMaster.Extensions.CommandLineUtils /// /// public class CommandArgument : CommandArgument, IInternalCommandParamOfT + where T : notnull { private readonly List _parsedValues = new List(); private readonly IValueParser _valueParser; private bool _hasBeenParsed; private bool _hasDefaultValue; - private T _defaultValue; + private T? _defaultValue; /// /// Initializes a new instance of @@ -31,7 +32,6 @@ public class CommandArgument : CommandArgument, IInternalCommandParamOfT public CommandArgument(IValueParser valueParser) { _valueParser = valueParser ?? throw new ArgumentNullException(nameof(valueParser)); - DefaultValue = default; UnderlyingType = typeof(T); } @@ -64,7 +64,7 @@ public IReadOnlyList ParsedValues /// /// The default value of the argument. /// - public new T DefaultValue + public new T? DefaultValue { get => _defaultValue; set diff --git a/src/CommandLineUtils/CommandOption.cs b/src/CommandLineUtils/CommandOption.cs index 3a7cfb47..a318a9e3 100644 --- a/src/CommandLineUtils/CommandOption.cs +++ b/src/CommandLineUtils/CommandOption.cs @@ -186,17 +186,14 @@ public bool TryParse(string? value) /// public bool HasValue() { - return _values.Any() || DefaultValue != null; + return Values.Any(); } /// - /// Returns the first element of , if any. + /// Returns the first element of , if any, or . /// /// - public string? Value() - { - return HasValue() ? Values[0] : null; - } + public string? Value() => Values.FirstOrDefault(); /// /// Generates the template string in the format "-{Symbol}|-{Short}|--{Long} <{Value}>" for display in help text. diff --git a/src/CommandLineUtils/CommandOption{T}.cs b/src/CommandLineUtils/CommandOption{T}.cs index e7c47c51..a855f8c6 100644 --- a/src/CommandLineUtils/CommandOption{T}.cs +++ b/src/CommandLineUtils/CommandOption{T}.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Reflection; using McMaster.Extensions.CommandLineUtils.Abstractions; namespace McMaster.Extensions.CommandLineUtils @@ -17,10 +16,11 @@ namespace McMaster.Extensions.CommandLineUtils /// /// The type of the option value(s) public class CommandOption : CommandOption, IInternalCommandParamOfT + where T : notnull { private readonly List _parsedValues = new List(); private readonly IValueParser _valueParser; - private T _defaultValue; + private T? _defaultValue; private bool _hasDefaultValue; private bool _hasBeenParsed; @@ -34,9 +34,7 @@ public CommandOption(IValueParser valueParser, string template, CommandOption : base(template, optionType) { _valueParser = valueParser ?? throw new ArgumentNullException(nameof(valueParser)); - DefaultValue = default; UnderlyingType = typeof(T); - SetBaseDefaultValue(default); } /// @@ -56,7 +54,7 @@ public IReadOnlyList ParsedValues ((IInternalCommandParamOfT)this).Parse(CultureInfo.CurrentCulture); } - if (_values.Count == 0 && _hasDefaultValue) + if (_parsedValues.Count == 0 && _hasDefaultValue) { return new[] { DefaultValue }; } @@ -68,7 +66,7 @@ public IReadOnlyList ParsedValues /// /// The default value of the option. /// - public new T DefaultValue + public new T? DefaultValue { get => _defaultValue; set diff --git a/src/CommandLineUtils/PublicAPI.Shipped.txt b/src/CommandLineUtils/PublicAPI.Shipped.txt index 49e347eb..1476d1c4 100644 --- a/src/CommandLineUtils/PublicAPI.Shipped.txt +++ b/src/CommandLineUtils/PublicAPI.Shipped.txt @@ -53,8 +53,6 @@ McMaster.Extensions.CommandLineUtils.ArgumentAttribute.ShowInHelpText.set -> voi McMaster.Extensions.CommandLineUtils.ArgumentEscaper McMaster.Extensions.CommandLineUtils.CommandArgument McMaster.Extensions.CommandLineUtils.CommandArgument.CommandArgument() -> void -McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.get -> string? -McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandArgument.Description.get -> string? McMaster.Extensions.CommandLineUtils.CommandArgument.Description.set -> void McMaster.Extensions.CommandLineUtils.CommandArgument.MultipleValues.get -> bool @@ -68,8 +66,6 @@ McMaster.Extensions.CommandLineUtils.CommandArgument.Value.get -> string? McMaster.Extensions.CommandLineUtils.CommandArgument.Values.get -> System.Collections.Generic.IReadOnlyList! McMaster.Extensions.CommandLineUtils.CommandArgument McMaster.Extensions.CommandLineUtils.CommandArgument.CommandArgument(McMaster.Extensions.CommandLineUtils.Abstractions.IValueParser! valueParser) -> void -McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.get -> T -McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandArgument.ParsedValue.get -> T McMaster.Extensions.CommandLineUtils.CommandArgument.ParsedValues.get -> System.Collections.Generic.IReadOnlyList! McMaster.Extensions.CommandLineUtils.CommandAttribute @@ -198,8 +194,6 @@ McMaster.Extensions.CommandLineUtils.CommandLineApplication.ModelFactory McMaster.Extensions.CommandLineUtils.CommandLineApplicationExtensions McMaster.Extensions.CommandLineUtils.CommandOption McMaster.Extensions.CommandLineUtils.CommandOption.CommandOption(string! template, McMaster.Extensions.CommandLineUtils.CommandOptionType optionType) -> void -McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.get -> string? -McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandOption.Description.get -> string? McMaster.Extensions.CommandLineUtils.CommandOption.Description.set -> void McMaster.Extensions.CommandLineUtils.CommandOption.HasValue() -> bool @@ -222,8 +216,6 @@ McMaster.Extensions.CommandLineUtils.CommandOption.ValueName.set -> void McMaster.Extensions.CommandLineUtils.CommandOption.Values.get -> System.Collections.Generic.IReadOnlyList! McMaster.Extensions.CommandLineUtils.CommandOption McMaster.Extensions.CommandLineUtils.CommandOption.CommandOption(McMaster.Extensions.CommandLineUtils.Abstractions.IValueParser! valueParser, string! template, McMaster.Extensions.CommandLineUtils.CommandOptionType optionType) -> void -McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.get -> T -McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandOption.ParsedValue.get -> T McMaster.Extensions.CommandLineUtils.CommandOption.ParsedValues.get -> System.Collections.Generic.IReadOnlyList! McMaster.Extensions.CommandLineUtils.CommandOptionType diff --git a/src/CommandLineUtils/PublicAPI.Unshipped.txt b/src/CommandLineUtils/PublicAPI.Unshipped.txt index 7e1caaec..451b9220 100644 --- a/src/CommandLineUtils/PublicAPI.Unshipped.txt +++ b/src/CommandLineUtils/PublicAPI.Unshipped.txt @@ -1,6 +1,14 @@ #nullable enable +McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.get -> string? +McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.set -> void +McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.get -> string? +McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.set -> void +McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.get -> T? +McMaster.Extensions.CommandLineUtils.CommandArgument.DefaultValue.set -> void McMaster.Extensions.CommandLineUtils.CommandArgument.HasValue.get -> bool McMaster.Extensions.CommandLineUtils.CommandArgument.TryParse(string? value) -> bool +McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.get -> T? +McMaster.Extensions.CommandLineUtils.CommandOption.DefaultValue.set -> void virtual McMaster.Extensions.CommandLineUtils.CommandArgument.Reset() -> void virtual McMaster.Extensions.CommandLineUtils.CommandOption.Reset() -> void override McMaster.Extensions.CommandLineUtils.CommandArgument.Reset() -> void diff --git a/test/CommandLineUtils.Tests/CommandArgumentTests.cs b/test/CommandLineUtils.Tests/CommandArgumentTests.cs index 59a09eee..d643ac60 100644 --- a/test/CommandLineUtils.Tests/CommandArgumentTests.cs +++ b/test/CommandLineUtils.Tests/CommandArgumentTests.cs @@ -11,76 +11,78 @@ public class CommandArgumentTests { [Fact] - public void AlwaysHasDefaultValueForValueTypes() + public void DoesNotHaveDefaultForValueTypes() { var app = new CommandLineApplication(); - var argument = app.Argument("abc", "xyz"); - Assert.Equal(default, argument.DefaultValue); - Assert.True(argument.HasValue); + var arg = app.Argument("abc", "xyz"); + Assert.False(arg.HasValue); } [Fact] public void DoesNotHaveDefaultForReferenceTypes() { var app = new CommandLineApplication(); - var argument = app.Argument("abc", "xyz"); - Assert.Null(argument.DefaultValue); - Assert.False(argument.HasValue); + var arg = app.Argument("abc", "xyz"); + Assert.Null(arg.DefaultValue); + Assert.False(arg.HasValue); } [Fact] public void DefaultValueReturnedIfUnset() { - var option = new CommandArgument + var arg = new CommandArgument { DefaultValue = "ABC" }; - Assert.Equal("ABC", option.Value); - Assert.Equal(new List { "ABC" }, option.Values); + Assert.Equal("ABC", arg.Value); + Assert.True(arg.HasValue); + Assert.Equal(new List { "ABC" }, arg.Values); } [Fact] public void DefaultValueOfTReturnedIfUnset() { - var option = new CommandArgument(StockValueParsers.Int32) + var arg = new CommandArgument(StockValueParsers.Int32) { DefaultValue = 42 }; - Assert.Equal("42", option.Value); - Assert.Equal(new List { "42" }, option.Values); - Assert.Equal(42, option.ParsedValue); - Assert.Equal(new List { 42 }, option.ParsedValues); + Assert.Equal("42", arg.Value); + Assert.True(arg.HasValue); + Assert.Equal(new List { "42" }, arg.Values); + Assert.Equal(42, arg.ParsedValue); + Assert.Equal(new List { 42 }, arg.ParsedValues); } [Fact] public void DefaultOverriddenBySettingValue() { - var option = new CommandArgument + var arg = new CommandArgument { DefaultValue = "ABC" }; - option.TryParse("xyz"); + arg.TryParse("xyz"); - Assert.Equal("xyz", option.Value); + Assert.Equal("xyz", arg.Value); } [Fact] public void DefaultOfTOverriddenBySettingValue() { - var option = new CommandArgument(StockValueParsers.Int32) + var arg = new CommandArgument(StockValueParsers.Int32) { DefaultValue = 42 }; - option.TryParse("999"); + arg.TryParse("999"); - Assert.Equal("999", option.Value); - Assert.Equal(new List { "999" }, option.Values); - Assert.Equal(999, option.ParsedValue); - Assert.Equal(new List { 999 }, option.ParsedValues); + Assert.Equal("999", arg.Value); + Assert.True(arg.HasValue); + Assert.Equal(new List { "999" }, arg.Values); + Assert.Equal(999, arg.ParsedValue); + Assert.Equal(new List { 999 }, arg.ParsedValues); } [Fact] diff --git a/test/CommandLineUtils.Tests/CommandOptionTests.cs b/test/CommandLineUtils.Tests/CommandOptionTests.cs index 4da28443..25d8341a 100644 --- a/test/CommandLineUtils.Tests/CommandOptionTests.cs +++ b/test/CommandLineUtils.Tests/CommandOptionTests.cs @@ -49,6 +49,23 @@ public void ItParsesSingleOrNoValueTemplate(string template, string shortName, s Assert.Equal(valueName, opt.ValueName); } + [Fact] + public void DoesNotHaveDefaultForValueTypes() + { + var app = new CommandLineApplication(); + var option = app.Option("--value ", "abc", CommandOptionType.SingleValue); + Assert.False(option.HasValue()); + } + + [Fact] + public void DoesNotHaveDefaultForReferenceTypes() + { + var app = new CommandLineApplication(); + var option = app.Option("--value ", "abc", CommandOptionType.SingleValue); + Assert.Null(option.DefaultValue); + Assert.False(option.HasValue()); + } + [Fact] public void DefaultValueReturnedIfUnset() { @@ -77,24 +94,6 @@ public void DefaultValueOfTReturnedIfUnset() Assert.Equal(new List { 42 }, option.ParsedValues); } - [Fact] - public void AlwaysHasDefaultValueForValueTypes() - { - var app = new CommandLineApplication(); - var option = app.Option("--value ", "abc", CommandOptionType.SingleValue); - Assert.Equal(default, option.DefaultValue); - Assert.True(option.HasValue()); - } - - [Fact] - public void DoesNotHaveDefaultForReferenceTypes() - { - var app = new CommandLineApplication(); - var option = app.Option("--value ", "abc", CommandOptionType.SingleValue); - Assert.Null(option.DefaultValue); - Assert.False(option.HasValue()); - } - [Fact] public void DefaultOverriddenBySettingValue() { @@ -118,6 +117,7 @@ public void DefaultOfTOverriddenBySettingValue() option.TryParse("999"); + Assert.True(option.HasValue()); Assert.Equal("999", option.Value()); Assert.Equal(new List { "999" }, option.Values); Assert.Equal(999, option.ParsedValue); diff --git a/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs b/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs index 04b0b476..ab708084 100644 --- a/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs +++ b/test/CommandLineUtils.Tests/DefaultHelpTextGeneratorTests.cs @@ -113,14 +113,18 @@ public void ShowHelp() app.Option("--rStrOpt ", "restricted str option desc.", CommandOptionType.SingleValue, o => o.IsRequired().Accepts().Values("Foo", "Bar")); app.Option("--dStrOpt ", "str option with default value desc.", CommandOptionType.SingleValue, o => o.DefaultValue = "Foo"); app.Option("--intOpt ", "int option desc.", CommandOptionType.SingleValue); - app.Option("--enumOpt ", "enum option desc.", CommandOptionType.SingleValue); - app.Option("--enumOpt2 ", "restricted enum option desc.", CommandOptionType.SingleValue, o => o.Accepts().Values("None", "Normal")); + app.Option("--enumOpt ", "enum option desc.", CommandOptionType.SingleValue, o => o.DefaultValue = default); + app.Option("--enumOpt2 ", "restricted enum option desc.", CommandOptionType.SingleValue, o => + { + o.DefaultValue = default; + o.Accepts().Values("None", "Normal"); + }); app.Option<(bool, SomeEnum)>("--enumOpt3 ", "nullable enum option desc.", CommandOptionType.SingleOrNoValue); app.Option("--enumOpt4 ", "nullable enum option desc.", CommandOptionType.SingleOrNoValue); app.Argument("SomeStringArgument", "string arg desc."); app.Argument("RestrictedStringArgument", "restricted string arg desc.", a => a.IsRequired().Accepts().Values("Foo", "Bar")); app.Argument("DefaultValStringArgument", "string arg with default value desc.", a => a.DefaultValue = "Foo"); - app.Argument("SomeEnumArgument", "enum arg desc."); + app.Argument("SomeEnumArgument", "enum arg desc.", a => a.DefaultValue = default); var a = app.Argument("RestrictedEnumArgument", "restricted enum arg desc.", a => a.Accepts().Values("None", "Normal")); a.DefaultValue = SomeEnum.Normal; app.Argument<(bool, SomeEnum)>("SomeNullableEnumArgument", "nullable enum arg desc."); @@ -152,7 +156,6 @@ SomeNullableEnumArgument nullable enum arg desc. --dStrOpt str option with default value desc. Default value is: Foo. --intOpt int option desc. - Default value is: 0. --enumOpt enum option desc. Allowed values are: None, Normal, Extreme. Default value is: None. diff --git a/test/CommandLineUtils.Tests/ValidationTests.cs b/test/CommandLineUtils.Tests/ValidationTests.cs index 1b4e3ce2..b3953cb8 100644 --- a/test/CommandLineUtils.Tests/ValidationTests.cs +++ b/test/CommandLineUtils.Tests/ValidationTests.cs @@ -37,7 +37,7 @@ public void ValidationHandlerOfSubcommandIsInvoked() var sub = app.Command("sub", c => { }); var called = false; sub.OnValidationError(_ => called = true); - var arg = sub.Argument("t", "test").IsRequired(); + var arg = sub.Argument("t", "test").IsRequired(); Assert.NotEqual(0, app.Execute("sub")); Assert.True(called, "Validation on subcommand should be called"); } From ae97ba9d50dd58b47bdfdbabdf222048c6785949 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 10 Jan 2021 16:56:52 -0800 Subject: [PATCH 4/6] Update docs to show usage of DefaultValue --- README.md | 17 ++++++++--------- docs/docs/intro.md | 7 ++----- docs/samples/custom-attribute/Program.cs | 6 ++---- docs/samples/helloworld-async/Program.cs | 16 +++++++--------- docs/samples/helloworld/HelloWorld.csproj | 1 + docs/samples/helloworld/Program.cs | 13 +++++-------- src/CommandLineUtils/CommandArgument{T}.cs | 1 - src/CommandLineUtils/CommandOption{T}.cs | 1 - 8 files changed, 25 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 209be6c2..0eab91d8 100644 --- a/README.md +++ b/README.md @@ -81,19 +81,18 @@ using McMaster.Extensions.CommandLineUtils; var app = new CommandLineApplication(); app.HelpOption(); -var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); -var optionRepeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); + +var subject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); +subject.DefaultValue = "world"; + +var repeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +repeat.DefaultValue = 1; app.OnExecute(() => { - var subject = optionSubject.HasValue() - ? optionSubject.Value() - : "world"; - - var count = optionRepeat.HasValue() ? optionRepeat.ParsedValue : 1; - for (var i = 0; i < count; i++) + for (var i = 0; i < repeat.ParsedValue; i++) { - Console.WriteLine($"Hello {subject}!"); + Console.WriteLine($"Hello {subject.Value()}!"); } return 0; }); diff --git a/docs/docs/intro.md b/docs/docs/intro.md index a740237f..4d925da6 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -65,14 +65,11 @@ public class Program app.HelpOption(); var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); + optionSubject.DefaultValue = "world"; app.OnExecute(() => { - var subject = optionSubject.HasValue() - ? optionSubject.Value() - : "world"; - - Console.WriteLine($"Hello {subject}!"); + Console.WriteLine($"Hello {subject.Value()}!"); return 0; }); diff --git a/docs/samples/custom-attribute/Program.cs b/docs/samples/custom-attribute/Program.cs index 41c8e5b5..001b706a 100644 --- a/docs/samples/custom-attribute/Program.cs +++ b/docs/samples/custom-attribute/Program.cs @@ -44,12 +44,10 @@ public void Apply(ConventionContext context, MemberInfo member) if (member is FieldInfo field) { var opt = context.Application.Option("--working-dir", "The working directory", CommandOptionType.SingleOrNoValue); + opt.DefaultValue = context.Application.WorkingDirectory; context.Application.OnParsingComplete(_ => { - var cwd = opt.HasValue() - ? opt.Value() - : context.Application.WorkingDirectory; - field.SetValue(context.ModelAccessor.GetModel(), cwd); + field.SetValue(context.ModelAccessor.GetModel(), opt.Value()); }); } } diff --git a/docs/samples/helloworld-async/Program.cs b/docs/samples/helloworld-async/Program.cs index 1e382ff5..099cbd37 100644 --- a/docs/samples/helloworld-async/Program.cs +++ b/docs/samples/helloworld-async/Program.cs @@ -5,24 +5,22 @@ var app = new CommandLineApplication(); app.HelpOption(); -var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); -var optionRepeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +var subject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); +subject.DefaultValue = "world"; + +var repeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +repeat.DefaultValue = 1; app.OnExecuteAsync(async cancellationToken => { - var subject = optionSubject.HasValue() - ? optionSubject.Value() - : "world"; - - var count = optionRepeat.HasValue() ? optionRepeat.ParsedValue : 1; - for (var i = 0; i < count; i++) + for (var i = 0; i < repeat.ParsedValue; i++) { Console.Write($"Hello"); // Pause for dramatic effect await Task.Delay(2000, cancellationToken); - Console.WriteLine($" {subject}!"); + Console.WriteLine($" {subject.Value()}!"); } }); diff --git a/docs/samples/helloworld/HelloWorld.csproj b/docs/samples/helloworld/HelloWorld.csproj index 9fe71e36..135c4fc5 100644 --- a/docs/samples/helloworld/HelloWorld.csproj +++ b/docs/samples/helloworld/HelloWorld.csproj @@ -3,6 +3,7 @@ Exe net5.0 + enable diff --git a/docs/samples/helloworld/Program.cs b/docs/samples/helloworld/Program.cs index 96c6c267..1dee2a7f 100644 --- a/docs/samples/helloworld/Program.cs +++ b/docs/samples/helloworld/Program.cs @@ -5,18 +5,15 @@ app.HelpOption(); var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); -var optionRepeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +optionSubject.DefaultValue = "world"; +var optionRepeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +optionRepeat.DefaultValue = 1; app.OnExecute(() => { - var subject = optionSubject.HasValue() - ? optionSubject.Value() - : "world"; - - var count = optionRepeat.HasValue() ? optionRepeat.ParsedValue : 1; - for (var i = 0; i < count; i++) + for (var i = 0; i < optionRepeat.ParsedValue; i++) { - Console.WriteLine($"Hello {subject}!"); + Console.WriteLine($"Hello {optionSubject.Value()}!"); } return 0; }); diff --git a/src/CommandLineUtils/CommandArgument{T}.cs b/src/CommandLineUtils/CommandArgument{T}.cs index 23e6d097..e43e4f2f 100644 --- a/src/CommandLineUtils/CommandArgument{T}.cs +++ b/src/CommandLineUtils/CommandArgument{T}.cs @@ -17,7 +17,6 @@ namespace McMaster.Extensions.CommandLineUtils /// /// public class CommandArgument : CommandArgument, IInternalCommandParamOfT - where T : notnull { private readonly List _parsedValues = new List(); private readonly IValueParser _valueParser; diff --git a/src/CommandLineUtils/CommandOption{T}.cs b/src/CommandLineUtils/CommandOption{T}.cs index a855f8c6..755a3495 100644 --- a/src/CommandLineUtils/CommandOption{T}.cs +++ b/src/CommandLineUtils/CommandOption{T}.cs @@ -16,7 +16,6 @@ namespace McMaster.Extensions.CommandLineUtils /// /// The type of the option value(s) public class CommandOption : CommandOption, IInternalCommandParamOfT - where T : notnull { private readonly List _parsedValues = new List(); private readonly IValueParser _valueParser; From 51b71e1eebf96564ecf037d7739c0004d41f50c2 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 10 Jan 2021 16:58:56 -0800 Subject: [PATCH 5/6] fixup! Update docs to show usage of DefaultValue --- docs/docs/intro.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/intro.md b/docs/docs/intro.md index 4d925da6..65d034c8 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -64,8 +64,8 @@ public class Program var app = new CommandLineApplication(); app.HelpOption(); - var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); - optionSubject.DefaultValue = "world"; + var subject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); + subject.DefaultValue = "world"; app.OnExecute(() => { From 8cd2a2ae94f761db9ebd63fa402014278a8b1a10 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 10 Jan 2021 17:18:15 -0800 Subject: [PATCH 6/6] fixup! fixup! Update docs to show usage of DefaultValue --- README.md | 1 - docs/samples/helloworld/Program.cs | 13 ++++++------- test/CommandLineUtils.Tests/CommandArgumentTests.cs | 1 + test/CommandLineUtils.Tests/CommandOptionTests.cs | 1 + 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0eab91d8..dde6f551 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,6 @@ app.OnExecute(() => { Console.WriteLine($"Hello {subject.Value()}!"); } - return 0; }); return app.Execute(args); diff --git a/docs/samples/helloworld/Program.cs b/docs/samples/helloworld/Program.cs index 1dee2a7f..6a0e80d9 100644 --- a/docs/samples/helloworld/Program.cs +++ b/docs/samples/helloworld/Program.cs @@ -4,18 +4,17 @@ var app = new CommandLineApplication(); app.HelpOption(); -var optionSubject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); -optionSubject.DefaultValue = "world"; -var optionRepeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); -optionRepeat.DefaultValue = 1; +var subject = app.Option("-s|--subject ", "The subject", CommandOptionType.SingleValue); +subject.DefaultValue = "world"; +var repeat = app.Option("-n|--count ", "Repeat", CommandOptionType.SingleValue); +repeat.DefaultValue = 1; app.OnExecute(() => { - for (var i = 0; i < optionRepeat.ParsedValue; i++) + for (var i = 0; i < repeat.ParsedValue; i++) { - Console.WriteLine($"Hello {optionSubject.Value()}!"); + Console.WriteLine($"Hello {subject.Value()}!"); } - return 0; }); return app.Execute(args); diff --git a/test/CommandLineUtils.Tests/CommandArgumentTests.cs b/test/CommandLineUtils.Tests/CommandArgumentTests.cs index d643ac60..aca3ce49 100644 --- a/test/CommandLineUtils.Tests/CommandArgumentTests.cs +++ b/test/CommandLineUtils.Tests/CommandArgumentTests.cs @@ -16,6 +16,7 @@ public void DoesNotHaveDefaultForValueTypes() var app = new CommandLineApplication(); var arg = app.Argument("abc", "xyz"); Assert.False(arg.HasValue); + Assert.Null(arg.Value); } [Fact] diff --git a/test/CommandLineUtils.Tests/CommandOptionTests.cs b/test/CommandLineUtils.Tests/CommandOptionTests.cs index 25d8341a..7e05006c 100644 --- a/test/CommandLineUtils.Tests/CommandOptionTests.cs +++ b/test/CommandLineUtils.Tests/CommandOptionTests.cs @@ -55,6 +55,7 @@ public void DoesNotHaveDefaultForValueTypes() var app = new CommandLineApplication(); var option = app.Option("--value ", "abc", CommandOptionType.SingleValue); Assert.False(option.HasValue()); + Assert.Null(option.Value()); } [Fact]