Skip to content

Commit 7ed0823

Browse files
authored
Fix 1351 and 1365 (#1361)
* R: consolidate MultipleArgumentsPerToken tests into a new file * fix #1083 * make TokenizeResult internal * add DebuggerDisplay for ArgumentArity * XML docs * fix #1365 * make option argument greedy * update source build patched versions
1 parent cd7a0ce commit 7ed0823

23 files changed

+441
-175
lines changed

eng/source-build-patches/0002-Use-package-version-properties-for-reference-version.patch

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ index 3048701..16a0eb7 100644
2323
<SystemNetHttpVersion>4.3.1</SystemNetHttpVersion>
2424
- </PropertyGroup> -->
2525
+ <MicrosoftExtensionsHostingPackageVersion Condition="'$(MicrosoftExtensionsHostingPackageVersion)' == ''">2.2.0</MicrosoftExtensionsHostingPackageVersion>
26-
+ <MicrosoftCSharpPackageVersion Condition="'$(MicrosoftCSharpPackageVersion)' == ''">4.4.1</MicrosoftCSharpPackageVersion>
27-
+ <SystemMemoryPackageVersion Condition="'$(SystemMemoryPackageVersion)' == ''">4.5.3</SystemMemoryPackageVersion>
26+
+ <MicrosoftCSharpPackageVersion Condition="'$(MicrosoftCSharpPackageVersion)' == ''">4.7.0</MicrosoftCSharpPackageVersion>
27+
+ <SystemMemoryPackageVersion Condition="'$(SystemMemoryPackageVersion)' == ''">4.5.4</SystemMemoryPackageVersion>
2828
+ </PropertyGroup>
2929
</Project>
3030
diff --git a/src/System.CommandLine/System.CommandLine.csproj b/src/System.CommandLine/System.CommandLine.csproj
@@ -35,7 +35,7 @@ index 1ae8dd3..aaa2c4a 100644
3535
</ItemGroup>
3636

3737
<ItemGroup>
38-
- <PackageReference Include="Microsoft.CSharp" Version="4.4.1" />
38+
- <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
3939
- <PackageReference Include="system.memory" Version="4.5.4" />
4040
+ <PackageReference Include="Microsoft.CSharp" Version="$(MicrosoftCSharpPackageVersion)" />
4141
+ <PackageReference Include="system.memory" Version="$(SystemMemoryPackageVersion)" />

src/System.CommandLine.Tests/Binding/ModelBinderTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,40 @@ public class ComplexType
794794
public decimal OptDecimal { get; set; }
795795
}
796796

797+
[Fact] // issue: https://github.com/dotnet/command-line-api/issues/1365
798+
public void Binder_does_not_match_by_substring()
799+
{
800+
var rootCommand = new RootCommand
801+
{
802+
new Option<string>(
803+
new[] { "-b", "--bundle" },
804+
"the path to the app bundle to be installed"),
805+
new Option<string>(
806+
new[] { "-1", "--bundle_id", "--bundle-id" },
807+
"specify bundle id for list and upload")
808+
};
809+
810+
DeployOptions boundOptions = null;
811+
812+
rootCommand.Handler = CommandHandler.Create<DeployOptions>(options =>
813+
{
814+
boundOptions = options;
815+
return 0;
816+
});
817+
818+
rootCommand.Invoke("-1 value");
819+
820+
boundOptions.Bundle.Should().Be(null);
821+
boundOptions.BundleId.Should().Be("value");
822+
}
823+
824+
class DeployOptions
825+
{
826+
public string Bundle { get; set; }
827+
public string BundleId { get; set; }
828+
}
829+
830+
797831
#if NETCOREAPP2_1_OR_GREATER
798832
[Theory]
799833
[InlineData("--class-with-span-ctor a51ca309-84fa-452f-96be-51e47702ffb4 --int-value 1234")]

src/System.CommandLine.Tests/Invocation/CommandHandlerTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ void Execute(string n, int a)
6767
}
6868

6969
var command = new Command("command");
70-
command.AddOption(new Option<string>("--name"));
71-
command.AddOption(new Option<string>("--age"));
70+
command.AddOption(new Option<string>(new[] { "-n", "--name" }));
71+
command.AddOption(new Option<string>(new[] { "-a", "--age" }));
7272
command.Handler = CommandHandler.Create<string, int>(Execute);
7373

7474
await command.InvokeAsync("command --age 425 --name Gandalf", _console);

src/System.CommandLine.Tests/OptionTests.MultipleArgumentsPerToken.cs

Lines changed: 92 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// Copyright (c) .NET Foundation and contributors. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using System.CommandLine.Parsing;
5+
using System.CommandLine.Tests.Utility;
46
using FluentAssertions;
57
using System.Linq;
68
using Xunit;
9+
using Xunit.Abstractions;
710

811
namespace System.CommandLine.Tests
912
{
@@ -13,6 +16,13 @@ public class MultipleArgumentsPerToken
1316
{
1417
public class Allowed
1518
{
19+
private readonly ITestOutputHelper _output;
20+
21+
public Allowed(ITestOutputHelper output)
22+
{
23+
_output = output;
24+
}
25+
1626
[Fact]
1727
public void When_option_is_not_respecified_but_limit_is_not_reached_then_the_following_token_is_used_as_value()
1828
{
@@ -86,6 +96,77 @@ public void When_option_is_not_respecified_and_limit_is_reached_then_the_followi
8696
.Should()
8797
.BeEquivalentTo("some-arg");
8898
}
99+
100+
[Theory]
101+
[InlineData("--option 1 --option 2")]
102+
[InlineData("xyz --option 1 --option 2")]
103+
[InlineData("--option 1 xyz --option 2")]
104+
[InlineData("--option 1 --option 2 xyz")]
105+
public void When_max_arity_is_1_then_subsequent_option_args_overwrite_previous_ones(string commandLine)
106+
{
107+
var option = new Option<string>("--option")
108+
{
109+
AllowMultipleArgumentsPerToken = true
110+
};
111+
var command = new Command("the-command")
112+
{
113+
option,
114+
new Argument<string>()
115+
};
116+
117+
var result = command.Parse(commandLine);
118+
119+
var value = result.ValueForOption(option);
120+
121+
value.Should().Be("2");
122+
}
123+
124+
[Fact]
125+
public void All_consumed_tokens_are_present_in_option_result()
126+
{
127+
var option = new Option<int>("-x")
128+
{
129+
AllowMultipleArgumentsPerToken = true
130+
};
131+
132+
var result = option.Parse("-x 1 -x 2 -x 3 -x 4");
133+
134+
_output.WriteLine(result.Diagram());
135+
136+
var optionResult = result.FindResultFor(option);
137+
138+
optionResult
139+
.Tokens
140+
.Select(t => t.Value)
141+
.Should().BeEquivalentSequenceTo("1", "2", "3", "4");
142+
}
143+
144+
[Fact]
145+
public void Multiple_option_arguments_that_match_single_arity_option_aliases_are_parsed_correctly()
146+
{
147+
var optionX = new Option<string>("-x")
148+
{
149+
AllowMultipleArgumentsPerToken = true
150+
};
151+
var optionY = new Option<string>("-y")
152+
{
153+
AllowMultipleArgumentsPerToken = true
154+
};
155+
156+
var command = new RootCommand
157+
{
158+
optionX,
159+
optionY
160+
};
161+
162+
var result = command.Parse("-x -x -x -y -y -x -y -y -y -x -x -y");
163+
164+
_output.WriteLine(result.Diagram());
165+
166+
result.Errors.Should().BeEmpty();
167+
result.ValueForOption(optionY).Should().Be("-x");
168+
result.ValueForOption(optionX).Should().Be("-y");
169+
}
89170
}
90171

91172
public class Disallowed
@@ -101,39 +182,32 @@ public void Single_option_arg_is_matched()
101182
var value = result.ValueForOption(option);
102183

103184
value.Should().BeEquivalentTo(new[] { "1" });
104-
result.UnmatchedTokens.Should().BeEquivalentTo(new[] { "2" });
105185
}
106186

107187
[Fact]
108-
public void When_max_arity_is_greater_than_1_then_multiple_option_args_are_matched()
188+
public void Subsequent_matched_arguments_result_in_errors()
109189
{
110190
var option = new Option<string[]>("--option") { AllowMultipleArgumentsPerToken = false };
111191
var command = new Command("the-command") { option };
112192

113-
var result = command.Parse("--option 1 --option 2");
114-
115-
var value = result.ValueForOption(option);
193+
var result = command.Parse("--option 1 2");
116194

117-
value.Should().BeEquivalentTo(new[] { "1", "2" });
195+
result.UnmatchedTokens.Should().BeEquivalentTo(new[] { "2" });
196+
result.Errors.Should().Contain(e => e.Message == Resources.Instance.UnrecognizedCommandOrArgument("2"));
118197
}
119198

120-
[Theory]
121-
[InlineData("--option 1 --option 2")]
122-
[InlineData("xyz --option 1 --option 2")]
123-
[InlineData("--option 1 xyz --option 2")]
124-
public void When_max_arity_is_1_then_subsequent_option_args_overwrite_its_value(string commandLine)
199+
[Fact]
200+
public void When_max_arity_is_greater_than_1_then_multiple_option_args_are_matched()
125201
{
126-
var option = new Option<string>("--option") { AllowMultipleArgumentsPerToken = false };
127-
var command = new Command("the-command") {
128-
option,
129-
new Argument<string>()
130-
};
202+
var option = new Option<string[]>("--option") { AllowMultipleArgumentsPerToken = false };
203+
var command = new Command("the-command") { option };
131204

132-
var result = command.Parse(commandLine);
205+
var result = command.Parse("--option 1 --option 2");
133206

134207
var value = result.ValueForOption(option);
135208

136-
value.Should().Be("2");
209+
value.Should().BeEquivalentTo(new[] { "1", "2" });
210+
result.Errors.Should().BeEmpty();
137211
}
138212
}
139213
}

src/System.CommandLine.Tests/OptionTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System.Collections.Generic;
5+
using System.CommandLine.Binding;
56
using System.CommandLine.Parsing;
67
using System.Linq;
78
using FluentAssertions;

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

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -232,30 +232,6 @@ public void tokens_that_cannot_be_converted_by_multiple_arity_argument_flow_to_n
232232
.Should()
233233
.Be("five");
234234
}
235-
236-
[Fact(Skip = "https://github.com/dotnet/command-line-api/issues/1143")]
237-
public void tokens_that_cannot_be_converted_by_multiple_arity_option_flow_to_next_single_arity_argument()
238-
{
239-
var option = new Option<int[]>("-i");
240-
var argument = new Argument<string>("arg");
241-
242-
var command = new RootCommand
243-
{
244-
option,
245-
argument
246-
};
247-
248-
var result = command.Parse("-i 1 2 3 four");
249-
250-
result.FindResultFor(option)
251-
.GetValueOrDefault()
252-
.Should()
253-
.BeEquivalentTo(new[] { 1, 2, 3 }, options => options.WithStrictOrdering());
254-
255-
result.FindResultFor(argument)
256-
.Should()
257-
.Be("four");
258-
}
259235
}
260236
}
261237
}

0 commit comments

Comments
 (0)