Skip to content

Commit d96b25f

Browse files
authored
Fix #1395 (#1603)
* InvocationContext is no longer IDisposable * fix #1395 * R: cleanup
1 parent a5684fa commit d96b25f

File tree

9 files changed

+39
-128
lines changed

9 files changed

+39
-128
lines changed

src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ System.CommandLine.Invocation
361361
public System.Threading.Tasks.Task<System.Int32> InvokeAsync(InvocationContext context)
362362
public interface IInvocationResult
363363
public System.Void Apply(InvocationContext context)
364-
public class InvocationContext, System.IDisposable
364+
public class InvocationContext
365365
.ctor(System.CommandLine.Parsing.ParseResult parseResult, System.CommandLine.IConsole console = null)
366366
public System.CommandLine.Binding.BindingContext BindingContext { get; }
367367
public System.CommandLine.IConsole Console { get; set; }
@@ -371,7 +371,6 @@ System.CommandLine.Invocation
371371
public System.CommandLine.LocalizationResources LocalizationResources { get; }
372372
public System.CommandLine.Parsing.Parser Parser { get; }
373373
public System.CommandLine.Parsing.ParseResult ParseResult { get; set; }
374-
public System.Void Dispose()
375374
public System.Threading.CancellationToken GetCancellationToken()
376375
public delegate InvocationMiddleware : System.MulticastDelegate, System.ICloneable, System.Runtime.Serialization.ISerializable
377376
.ctor(System.Object object, System.IntPtr method)

src/System.CommandLine.Tests/ParserTests.MultipleArguments.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using System.CommandLine.Tests.Utility;
6+
using System.Threading.Tasks;
67
using FluentAssertions;
78
using FluentAssertions.Execution;
89
using Xunit;
@@ -277,6 +278,26 @@ public void Unsatisfied_subsequent_argument_with_min_arity_1_parses_as_default_v
277278
result.FindResultFor(arg1).Should().BeNull();
278279
result.GetValueForArgument(arg2).Should().Be("the-default");
279280
}
281+
282+
[Fact] // https://github.com/dotnet/command-line-api/issues/1395
283+
public void When_subsequent_argument_with_ZeroOrOne_arity_is_not_provided_then_parse_is_correct()
284+
{
285+
var argument1 = new Argument<string>();
286+
var rootCommand = new RootCommand
287+
{
288+
argument1,
289+
new Argument<string>
290+
{
291+
Arity = ArgumentArity.ZeroOrOne
292+
},
293+
};
294+
295+
var result = rootCommand.Parse("one");
296+
297+
result.Errors.Should().BeEmpty();
298+
299+
result.GetValueForArgument(argument1).Should().Be("one");
300+
}
280301
}
281302
}
282303
}

src/System.CommandLine.Tests/ParserTests.cs

Lines changed: 2 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using Xunit;
1414
using System.ComponentModel;
1515
using System.Globalization;
16+
using System.Threading.Tasks;
1617
using Xunit.Abstractions;
1718

1819
namespace System.CommandLine.Tests
@@ -1591,32 +1592,7 @@ public void When_option_arguments_are_greater_than_maximum_arity_then_an_error_i
15911592
.Should()
15921593
.Contain(LocalizationResources.Instance.UnrecognizedCommandOrArgument("4"));
15931594
}
1594-
1595-
1596-
[Fact(Skip = "Can we support both type converters and trimming?")]
1597-
public void Argument_with_custom_type_converter_can_be_bound()
1598-
{
1599-
var option = new Option<ClassWithCustomTypeConverter>("--value");
1600-
1601-
var parseResult = option.Parse("--value a;b;c");
1602-
1603-
var instance = parseResult.GetValueForOption(option);
1604-
1605-
instance.Values.Should().BeEquivalentTo("a", "b", "c");
1606-
}
1607-
1608-
[Fact(Skip = "Can we support both type converters and trimming?")]
1609-
public void Argument_with_custom_collection_type_converter_can_be_bound()
1610-
{
1611-
var option = new Option<CollectionWithCustomTypeConverter>("--value") { Arity = ArgumentArity.ExactlyOne };
1612-
1613-
var parseResult = option.Parse("--value a;b;c");
1614-
1615-
CollectionWithCustomTypeConverter instance = parseResult.GetValueForOption(option);
1616-
1617-
instance.Should().BeEquivalentTo("a", "b", "c");
1618-
}
1619-
1595+
16201596
[Fact]
16211597
public void Tokens_are_not_split_if_the_part_before_the_delimiter_is_not_an_option()
16221598
{
@@ -1686,58 +1662,5 @@ public void Empty_strings_in_parsed_args_array_are_ignored()
16861662
result.CommandResult.Command.Should().BeSameAs(subcommand);
16871663
result.FindResultFor(option).Should().NotBeNull();
16881664
}
1689-
1690-
[TypeConverter(typeof(CustomTypeConverter))]
1691-
public class ClassWithCustomTypeConverter
1692-
{
1693-
public string[] Values { get; set; }
1694-
}
1695-
1696-
public class CustomTypeConverter : TypeConverter
1697-
{
1698-
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
1699-
{
1700-
return sourceType == typeof(string) ||
1701-
base.CanConvertFrom(context, sourceType);
1702-
}
1703-
1704-
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
1705-
{
1706-
if (value is string stringValue)
1707-
{
1708-
return new ClassWithCustomTypeConverter
1709-
{
1710-
Values = stringValue.Split(';')
1711-
};
1712-
}
1713-
return base.ConvertFrom(context, culture, value);
1714-
}
1715-
}
1716-
1717-
[TypeConverter(typeof(CustomCollectionTypeConverter))]
1718-
public class CollectionWithCustomTypeConverter : List<string>
1719-
{
1720-
public CollectionWithCustomTypeConverter(IEnumerable<string> values)
1721-
: base(values)
1722-
{ }
1723-
}
1724-
1725-
public class CustomCollectionTypeConverter : TypeConverter
1726-
{
1727-
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
1728-
{
1729-
return sourceType == typeof(string) ||
1730-
base.CanConvertFrom(context, sourceType);
1731-
}
1732-
1733-
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
1734-
{
1735-
if (value is string stringValue)
1736-
{
1737-
return new CollectionWithCustomTypeConverter(stringValue.Split(';'));
1738-
}
1739-
return base.ConvertFrom(context, culture, value);
1740-
}
1741-
}
17421665
}
17431666
}

src/System.CommandLine.Tests/SymbolSetExtensions.cs

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/System.CommandLine.Tests/VersionOptionTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.CommandLine.Invocation;
66
using System.CommandLine.IO;
77
using System.CommandLine.Parsing;
8+
using System.Linq;
89
using System.Reflection;
910
using System.Threading.Tasks;
1011
using FluentAssertions;
@@ -162,9 +163,8 @@ public void Version_option_is_not_added_to_subcommands()
162163

163164
parser.Configuration
164165
.RootCommand
165-
.Children
166-
.GetByAlias("subcommand")
167-
.As<Command>()
166+
.Subcommands
167+
.Single(c => c.Name == "subcommand")
168168
.Options
169169
.Should()
170170
.BeEmpty();

src/System.CommandLine/Binding/ArgumentConverter.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -133,23 +133,21 @@ public static ArgumentConversionResult ConvertStrings(
133133

134134
internal static TryConvertArgument? GetConverter(Argument argument)
135135
{
136-
if (argument.ValueType == typeof(bool))
136+
switch (argument.Arity)
137137
{
138-
return TryConvertBoolArgument;
139-
}
138+
case { MaximumNumberOfValues: 1, MinimumNumberOfValues: 1 }:
140139

141-
if (_stringConverters.TryGetValue(argument.ValueType, out var converter))
142-
{
143-
switch (argument.Arity.MaximumNumberOfValues)
144-
{
145-
case 1:
140+
if (_stringConverters.TryGetValue(argument.ValueType, out var converter))
141+
{
146142
return ConvertSingleString;
147143

148144
bool ConvertSingleString(ArgumentResult result, out object? value)
149145
{
150146
return converter(result.Tokens[result.Tokens.Count - 1].Value, out value);
151147
}
152-
}
148+
}
149+
150+
break;
153151
}
154152

155153
if (argument.ValueType.CanBeBoundFromScalarValue())

src/System.CommandLine/Invocation/InvocationContext.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace System.CommandLine.Invocation
1212
/// <summary>
1313
/// Supports command invocation by providing access to parse results and other services.
1414
/// </summary>
15-
public sealed class InvocationContext : IDisposable
15+
public sealed class InvocationContext
1616
{
1717
private CancellationTokenSource? _cts;
1818
private Action<CancellationTokenSource>? _cancellationHandlingAddedEvent;
@@ -40,7 +40,6 @@ public BindingContext BindingContext
4040
if (_bindingContext is null)
4141
{
4242
_bindingContext = new BindingContext(this);
43-
4443
}
4544

4645
return _bindingContext;
@@ -123,11 +122,5 @@ public CancellationToken GetCancellationToken()
123122

124123
return _cts.Token;
125124
}
126-
127-
/// <inheritdoc />
128-
public void Dispose()
129-
{
130-
(Console as IDisposable)?.Dispose();
131-
}
132125
}
133126
}

src/System.CommandLine/Invocation/TypoCorrection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ private IEnumerable<string> GetPossibleTokens(Command targetSymbol, string token
4343
{
4444
IEnumerable<string> possibleMatches = targetSymbol
4545
.Children
46-
.Where(x => !x.IsHidden)
4746
.OfType<IdentifierSymbol>()
47+
.Where(x => !x.IsHidden)
4848
.Where(x => x.Aliases.Count > 0)
4949
.Select(symbol =>
5050
symbol.Aliases

src/System.CommandLine/Parsing/ParseResult.cs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,7 @@ IEnumerable<SymbolResult> AllSymbolResultsForCompletion()
350350
}
351351
else if (item is OptionResult option)
352352
{
353-
var willAcceptAnArgument =
354-
WillAcceptAnArgument(this, position, option);
355-
356-
if (willAcceptAnArgument)
353+
if (WillAcceptAnArgument(this, position, option))
357354
{
358355
yield return option;
359356
}
@@ -387,12 +384,9 @@ static bool WillAcceptAnArgument(
387384

388385
if (textCompletionContext.WordToComplete.Length > 0)
389386
{
390-
var tokenToComplete = parseResult.Tokens.LastOrDefault(t => t.Value == textCompletionContext.WordToComplete);
387+
var tokenToComplete = parseResult.Tokens.Last(t => t.Value == textCompletionContext.WordToComplete);
391388

392-
if (tokenToComplete is { })
393-
{
394-
return optionResult.Tokens.Contains(tokenToComplete);
395-
}
389+
return optionResult.Tokens.Contains(tokenToComplete);
396390
}
397391
}
398392

0 commit comments

Comments
 (0)