mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Throw when a required option is set but doesn't have a value
Closes #47
This commit is contained in:
@@ -933,7 +933,7 @@ namespace CliFx.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Property_annotated_as_a_required_option_must_always_be_bound_to_some_value()
|
public void Property_annotated_as_a_required_option_must_always_be_set()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var schema = ApplicationSchema.Resolve(new[] {typeof(RequiredOptionCommand)});
|
var schema = ApplicationSchema.Resolve(new[] {typeof(RequiredOptionCommand)});
|
||||||
@@ -946,6 +946,20 @@ namespace CliFx.Tests
|
|||||||
Assert.Throws<CliFxException>(() => schema.InitializeEntryPoint(input));
|
Assert.Throws<CliFxException>(() => schema.InitializeEntryPoint(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Property_annotated_as_a_required_option_must_always_be_bound_to_some_value()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var schema = ApplicationSchema.Resolve(new[] {typeof(RequiredOptionCommand)});
|
||||||
|
|
||||||
|
var input = new CommandLineInputBuilder()
|
||||||
|
.AddOption(nameof(RequiredOptionCommand.OptionB))
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
// Act & assert
|
||||||
|
Assert.Throws<CliFxException>(() => schema.InitializeEntryPoint(input));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Property_annotated_as_parameter_is_bound_directly_from_argument_value_according_to_the_order()
|
public void Property_annotated_as_parameter_is_bound_directly_from_argument_value_according_to_the_order()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -97,15 +97,15 @@ namespace CliFx.Domain
|
|||||||
var unsetRequiredOptions = Options.Where(o => o.IsRequired).ToList();
|
var unsetRequiredOptions = Options.Where(o => o.IsRequired).ToList();
|
||||||
|
|
||||||
// Environment variables
|
// Environment variables
|
||||||
foreach (var environmentVariable in environmentVariables)
|
foreach (var (name, value) in environmentVariables)
|
||||||
{
|
{
|
||||||
var option = Options.FirstOrDefault(o => o.MatchesEnvironmentVariableName(environmentVariable.Key));
|
var option = Options.FirstOrDefault(o => o.MatchesEnvironmentVariableName(name));
|
||||||
|
|
||||||
if (option != null)
|
if (option != null)
|
||||||
{
|
{
|
||||||
var values = option.IsScalar
|
var values = option.IsScalar
|
||||||
? new[] {environmentVariable.Value}
|
? new[] {value}
|
||||||
: environmentVariable.Value.Split(Path.PathSeparator);
|
: value.Split(Path.PathSeparator);
|
||||||
|
|
||||||
option.Inject(command, values);
|
option.Inject(command, values);
|
||||||
unsetRequiredOptions.Remove(option);
|
unsetRequiredOptions.Remove(option);
|
||||||
@@ -122,12 +122,14 @@ namespace CliFx.Domain
|
|||||||
|
|
||||||
if (inputs.Any())
|
if (inputs.Any())
|
||||||
{
|
{
|
||||||
option.Inject(command, inputs.SelectMany(i => i.Values).ToArray());
|
var inputValues = inputs.SelectMany(i => i.Values).ToArray();
|
||||||
|
option.Inject(command, inputValues);
|
||||||
|
|
||||||
foreach (var input in inputs)
|
foreach (var input in inputs)
|
||||||
remainingOptionInputs.Remove(input);
|
remainingOptionInputs.Remove(input);
|
||||||
|
|
||||||
unsetRequiredOptions.Remove(option);
|
if (inputValues.Any())
|
||||||
|
unsetRequiredOptions.Remove(option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
// ReSharper disable CheckNamespace
|
// ReSharper disable CheckNamespace
|
||||||
|
|
||||||
#if NET45 || NETSTANDARD2_0
|
// Polyfills to bridge the missing APIs in older versions of the framework/standard.
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace CliFx.Internal
|
#if NETSTANDARD2_0 || NET45
|
||||||
|
namespace System.Collections.Generic
|
||||||
{
|
{
|
||||||
internal static class Polyfills
|
internal static class Extensions
|
||||||
{
|
{
|
||||||
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> self, TKey key) =>
|
public static void Deconstruct<TKey, TValue>(this KeyValuePair<TKey, TValue> pair, out TKey key, out TValue value)
|
||||||
self.TryGetValue(key, out var value) ? value : default;
|
{
|
||||||
|
key = pair.Key;
|
||||||
|
value = pair.Value;
|
||||||
|
}
|
||||||
|
|
||||||
public static StringBuilder AppendJoin<T>(this StringBuilder self, string separator, IEnumerable<T> items) =>
|
public static TValue GetValueOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dic, TKey key) =>
|
||||||
self.Append(string.Join(separator, items));
|
dic.TryGetValue(key, out var result) ? result! : default!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user