Skip to content

Commit 997ec58

Browse files
authored
Fix 1292 (#1293)
1 parent 3264927 commit 997ec58

File tree

4 files changed

+82
-15
lines changed

4 files changed

+82
-15
lines changed

src/System.CommandLine.Tests/ArgumentTests.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Linq;
1010
using System.Threading.Tasks;
1111
using Xunit;
12+
using Xunit.Abstractions;
1213

1314
namespace System.CommandLine.Tests
1415
{
@@ -498,8 +499,11 @@ public void Parse_delegate_is_called_once_per_parse_operation()
498499
i.Should().Be(2);
499500
}
500501

501-
[Fact]
502-
public void Custom_parser_can_pass_on_remaining_tokens()
502+
[Theory]
503+
[InlineData("1 2 3 4 5 6 7 8")]
504+
[InlineData("-o 999 1 2 3 4 5 6 7 8")]
505+
[InlineData("1 2 3 -o 999 4 5 6 7 8")]
506+
public void Custom_parser_can_pass_on_remaining_tokens(string commandLine)
503507
{
504508
var argument1 = new Argument<int[]>(
505509
"one",
@@ -520,10 +524,11 @@ public void Custom_parser_can_pass_on_remaining_tokens()
520524
var command = new RootCommand
521525
{
522526
argument1,
523-
argument2
527+
argument2,
528+
new Option<int>("-o")
524529
};
525530

526-
var parseResult = command.Parse("1 2 3 4 5 6 7 8");
531+
var parseResult = command.Parse(commandLine);
527532

528533
parseResult.FindResultFor(argument1)
529534
.GetValueOrDefault()

src/System.CommandLine.Tests/ParsingValidationTests.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,47 @@ public void A_custom_validator_can_be_added_to_an_argument()
227227
.Be("Argument x cannot be set to 123");
228228
}
229229

230+
[Theory]
231+
[InlineData("-o=optionValue argValue")]
232+
[InlineData("argValue -o=optionValue")]
233+
public void All_custom_validators_are_called(string commandLine)
234+
{
235+
var commandValidatorWasCalled = false;
236+
var optionValidatorWasCalled = false;
237+
var argumentValidatorWasCalled = false;
238+
239+
var option = new Option<string>("-o");
240+
option.AddValidator(_ =>
241+
{
242+
optionValidatorWasCalled = true;
243+
return null;
244+
});
245+
246+
var argument = new Argument<string>("the-arg");
247+
argument.AddValidator(_ =>
248+
{
249+
argumentValidatorWasCalled = true;
250+
return null;
251+
});
252+
253+
var rootCommand = new RootCommand
254+
{
255+
option,
256+
argument
257+
};
258+
rootCommand.AddValidator(_ =>
259+
{
260+
commandValidatorWasCalled = true;
261+
return null;
262+
});
263+
264+
rootCommand.Invoke(commandLine);
265+
266+
commandValidatorWasCalled.Should().BeTrue();
267+
optionValidatorWasCalled.Should().BeTrue();
268+
argumentValidatorWasCalled.Should().BeTrue();
269+
}
270+
230271
[Theory]
231272
[InlineData("--file \"Foo\" subcommand")]
232273
[InlineData("subcommand --file \"Foo\"")]

src/System.CommandLine/Parsing/ParseResult.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public T ValueForArgument<T>(Argument<T> argument)
105105
return t;
106106
}
107107

108-
return (T)Binder.GetDefaultValue(argument.ArgumentType);
108+
return (T)Binder.GetDefaultValue(argument.ArgumentType)!;
109109
}
110110

111111
[return: MaybeNull]
@@ -117,7 +117,7 @@ public T ValueForArgument<T>(Argument argument)
117117
return t;
118118
}
119119

120-
return (T)Binder.GetDefaultValue(argument.ArgumentType);
120+
return (T)Binder.GetDefaultValue(argument.ArgumentType)!;
121121
}
122122

123123
[return: MaybeNull]
@@ -147,7 +147,7 @@ public T ValueForOption<T>(Option<T> option)
147147
return t;
148148
}
149149

150-
return (T)Binder.GetDefaultValue(option.Argument.ArgumentType);
150+
return (T)Binder.GetDefaultValue(option.Argument.ArgumentType)!;
151151
}
152152

153153
[return: MaybeNull]
@@ -159,7 +159,7 @@ public T ValueForOption<T>(Option option)
159159
return t;
160160
}
161161

162-
return (T)Binder.GetDefaultValue(option.Argument.ArgumentType);
162+
return (T)Binder.GetDefaultValue(option.Argument.ArgumentType)!;
163163
}
164164

165165
[return: MaybeNull]

src/System.CommandLine/Parsing/ParseResultVisitor.cs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -164,17 +164,25 @@ protected override void Stop(SyntaxNode node)
164164
ValidateAndConvertOptionResult(optionResult);
165165
}
166166

167-
var argumentResults = _rootCommandResult!
168-
.AllArgumentResults
169-
.ToList();
167+
var argumentResults = new List<ArgumentResult>();
168+
foreach (var result in _rootCommandResult.AllArgumentResults)
169+
{
170+
if (!(result.Parent is OptionResult))
171+
{
172+
argumentResults.Add(result);
173+
}
174+
}
170175

171176
if (argumentResults.Count > 0)
172177
{
173-
var arguments = _innermostCommandResult!.Command.Arguments;
178+
var arguments = _innermostCommandResult.Command.Arguments;
179+
180+
var commandArgumentResultCount = argumentResults.Count;
174181

175182
for (var i = 0; i < arguments.Count; i++)
176183
{
177-
if (argumentResults.Count == i)
184+
// If this is the current last result but there are more arguments, see if we can shift tokens to the next argument
185+
if (commandArgumentResultCount == i)
178186
{
179187
var nextArgument = arguments[i];
180188
var nextArgumentResult = new ArgumentResult(
@@ -201,7 +209,7 @@ protected override void Stop(SyntaxNode node)
201209

202210
if (previousArgumentResult.Parent is CommandResult commandResult)
203211
{
204-
commandResult.Children.Add(nextArgumentResult);
212+
commandResult.Children.Add(nextArgumentResult);
205213
}
206214

207215
_rootCommandResult.AddToSymbolMap(nextArgumentResult);
@@ -211,12 +219,25 @@ protected override void Stop(SyntaxNode node)
211219

212220
ValidateAndConvertArgumentResult(argumentResult);
213221

214-
if (argumentResult.PassedOnTokens is {} &&
222+
if (argumentResult.PassedOnTokens is { } &&
215223
i == arguments.Count - 1)
216224
{
217225
_unparsedTokens.AddRange(argumentResult.PassedOnTokens);
218226
}
219227
}
228+
229+
if (argumentResults.Count > arguments.Count)
230+
{
231+
for (var i = arguments.Count; i < argumentResults.Count; i++)
232+
{
233+
var result = argumentResults[i];
234+
235+
if (result.Parent is CommandResult cr)
236+
{
237+
ValidateAndConvertArgumentResult(result);
238+
}
239+
}
240+
}
220241
}
221242
}
222243

0 commit comments

Comments
 (0)