Skip to content

Commit 2896783

Browse files
authored
Merge pull request #2467 from KathleenDollard/ph-parseresult-commandvalueresult
Improved access to `CommandValueResult`
2 parents 5166501 + 5bb4acb commit 2896783

File tree

8 files changed

+74
-44
lines changed

8 files changed

+74
-44
lines changed

src/System.CommandLine.Tests/ParserTests.cs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ public void Option_short_forms_can_be_bundled()
139139

140140
var result = CliParser.Parse(command, "the-command -xyz");
141141

142-
result.CommandResult
143-
.Children
144-
.Select(o => ((OptionResult)o).Option.Name)
142+
result.CommandValueResult
143+
.ValueResults
144+
.Select(o => o.ValueSymbol.Name)
145145
.Should()
146146
.BeEquivalentTo("-x", "-y", "-z");
147147
}
@@ -1710,11 +1710,11 @@ public void CommandResult_contains_argument_ValueResults()
17101710

17111711
var parseResult = CliParser.Parse(rootCommand, "subcommand Kirk Spock");
17121712

1713-
var commandResult = parseResult.CommandResult;
1714-
commandResult.ValueResults.Should().HaveCount(2);
1715-
var result1 = commandResult.ValueResults[0];
1713+
var commandValueResult = parseResult.CommandValueResult;
1714+
commandValueResult.ValueResults.Should().HaveCount(2);
1715+
var result1 = commandValueResult.ValueResults.First();
17161716
result1.GetValue<string>().Should().Be("Kirk");
1717-
var result2 = commandResult.ValueResults[1];
1717+
var result2 = commandValueResult.ValueResults.Skip(1).First();
17181718
result2.GetValue<string>().Should().Be("Spock");
17191719
}
17201720

@@ -1735,11 +1735,11 @@ public void CommandResult_contains_option_ValueResults()
17351735

17361736
var parseResult = CliParser.Parse(rootCommand, "subcommand arg1 --opt1 Kirk --opt2 Spock");
17371737

1738-
var commandResult = parseResult.CommandResult;
1739-
commandResult.ValueResults.Should().HaveCount(2);
1740-
var result1 = commandResult.ValueResults[0];
1738+
var commandValueResult = parseResult.CommandValueResult;
1739+
commandValueResult.ValueResults.Should().HaveCount(2);
1740+
var result1 = commandValueResult.ValueResults[0];
17411741
result1.GetValue<string>().Should().Be("Kirk");
1742-
var result2 = commandResult.ValueResults[1];
1742+
var result2 = commandValueResult.ValueResults[1];
17431743
result2.GetValue<string>().Should().Be("Spock");
17441744
}
17451745

@@ -1763,9 +1763,9 @@ public void Location_in_ValueResult_correct_for_arguments()
17631763

17641764
var parseResult = CliParser.Parse(rootCommand, "subcommand Kirk Spock");
17651765

1766-
var commandResult = parseResult.CommandResult;
1767-
var result1 = commandResult.ValueResults[0];
1768-
var result2 = commandResult.ValueResults[1];
1766+
var commandValueResult = parseResult.CommandValueResult;
1767+
var result1 = commandValueResult.ValueResults[0];
1768+
var result2 = commandValueResult.ValueResults[1];
17691769
result1.Locations.Single().Should().Be(expectedLocation1);
17701770
result2.Locations.Single().Should().Be(expectedLocation2);
17711771
}
@@ -1790,9 +1790,9 @@ public void Location_in_ValueResult_correct_for_options()
17901790

17911791
var parseResult = CliParser.Parse(rootCommand, "subcommand arg1 --opt1 Kirk --opt2 Spock");
17921792

1793-
var commandResult = parseResult.CommandResult;
1794-
var result1 = commandResult.ValueResults[0];
1795-
var result2 = commandResult.ValueResults[1];
1793+
var commandValueResult = parseResult.CommandValueResult;
1794+
var result1 = commandValueResult.ValueResults[0];
1795+
var result2 = commandValueResult.ValueResults[1];
17961796
result1.Locations.Single().Should().Be(expectedLocation1);
17971797
result2.Locations.Single().Should().Be(expectedLocation2);
17981798
}
@@ -1817,8 +1817,8 @@ public void Location_offsets_in_ValueResult_correct_for_arguments()
18171817

18181818
var parseResult = CliParser.Parse(rootCommand, "subcommand Kirk Spock");
18191819

1820-
var commandResult = parseResult.CommandResult;
1821-
var result1 = commandResult.ValueResults.Single();
1820+
var commandValueResult = parseResult.CommandValueResult;
1821+
var result1 = commandValueResult.ValueResults.Single();
18221822
result1.Locations.First().Should().Be(expectedLocation1);
18231823
result1.Locations.Skip(1).Single().Should().Be(expectedLocation2);
18241824
}
@@ -1841,8 +1841,8 @@ public void Location_offsets_in_ValueResult_correct_for_options()
18411841

18421842
var parseResult = CliParser.Parse(rootCommand, "subcommand arg1 --opt1 Kirk --opt1 Spock");
18431843

1844-
var commandResult = parseResult.CommandResult;
1845-
var result1 = commandResult.ValueResults.Single();
1844+
var commandValueResult = parseResult.CommandValueResult;
1845+
var result1 = commandValueResult.ValueResults.Single();
18461846
result1.Locations.First().Should().Be(expectedLocation1);
18471847
result1.Locations.Skip(1).Single().Should().Be(expectedLocation2);
18481848
}
@@ -1867,9 +1867,9 @@ public void Location_offset_correct_when_colon_or_equal_used()
18671867

18681868
var parseResult = CliParser.Parse(rootCommand, "subcommand arg1 --opt1:Kirk --opt11=Spock");
18691869

1870-
var commandResult = parseResult.CommandResult;
1871-
var result1 = commandResult.ValueResults[0];
1872-
var result2 = commandResult.ValueResults[1];
1870+
var commandValueResult = parseResult.CommandValueResult;
1871+
var result1 = commandValueResult.ValueResults[0];
1872+
var result2 = commandValueResult.ValueResults[1];
18731873
result1.Locations.Single().Should().Be(expectedLocation1);
18741874
result2.Locations.Single().Should().Be(expectedLocation2);
18751875
}

src/System.CommandLine/ParseResult.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public sealed class ParseResult
1717
private readonly IReadOnlyDictionary<CliSymbol, ValueResult> valueResultDictionary = new Dictionary<CliSymbol, ValueResult>();
1818
private SymbolLookupByName? symbolLookupByName = null;
1919

20+
// TODO: Remove usage and remove
2021
private readonly CommandResult _rootCommandResult;
2122
// TODO: unmatched tokens, invocation, completion
2223
/*
@@ -28,10 +29,11 @@ public sealed class ParseResult
2829

2930
internal ParseResult(
3031
CliConfiguration configuration,
31-
// TODO: determine how rootCommandResult and commandResult differ
32+
// TODO: Remove RootCommandResult - it is the root of the CommandValueResult ancestors (fix that)
3233
CommandResult rootCommandResult,
34+
// TODO: Replace with CommandValueResult and remove CommandResult
3335
CommandResult commandResult,
34-
SymbolResultTree symbolResultTree,
36+
IReadOnlyDictionary<CliSymbol, ValueResult> valueResultDictionary,
3537
/*
3638
List<CliToken> tokens,
3739
*/
@@ -50,7 +52,8 @@ internal ParseResult(
5052
Configuration = configuration;
5153
_rootCommandResult = rootCommandResult;
5254
CommandResult = commandResult;
53-
valueResultDictionary = symbolResultTree.BuildValueResultDictionary();
55+
CommandValueResult = commandResult.CommandValueResult;
56+
this.valueResultDictionary = valueResultDictionary;
5457
// TODO: invocation
5558
/*
5659
_action = action;
@@ -98,8 +101,11 @@ internal ParseResult(
98101
/// <summary>
99102
/// A result indicating the command specified in the command line input.
100103
/// </summary>
104+
// TODO: Update SymbolLookupByName to use CommandValueResult, then remove
101105
internal CommandResult CommandResult { get; }
102106

107+
public CommandValueResult CommandValueResult { get; }
108+
103109
/// <summary>
104110
/// The configuration used to produce the parse result.
105111
/// </summary>
@@ -108,6 +114,7 @@ internal ParseResult(
108114
/// <summary>
109115
/// Gets the root command result.
110116
/// </summary>
117+
/// TODO: Update usage and then remove
111118
internal CommandResult RootCommandResult => _rootCommandResult;
112119

113120
/// <summary>
@@ -215,6 +222,7 @@ CommandLineText is null
215222
? result
216223
: null;
217224

225+
// TODO: Update tests and remove all use of things deriving from SymbolResult from this class
218226
/// <summary>
219227
/// Gets the result, if any, for the specified argument.
220228
/// </summary>

src/System.CommandLine/Parsing/ArgumentResult.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ public ValueResult ValueResult
3333
// TODO: Make sure errors are added
3434
var conversionValue = GetArgumentConversionResult().Value;
3535
var locations = Tokens.Select(token => token.Location).ToArray();
36-
//TODO: Remove this wrapper later
3736
_valueResult = new ValueResult(Argument, conversionValue, locations, ArgumentResult.GetValueResultOutcome(GetArgumentConversionResult()?.Result)); // null is temporary here
3837
}
3938
return _valueResult;

src/System.CommandLine/Parsing/CommandResult.cs

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,23 @@ internal CommandResult(
3838
/// </summary>
3939
public IEnumerable<SymbolResult> Children => SymbolResultTree.GetChildren(this);
4040

41-
public IReadOnlyList<ValueResult> ValueResults => Children.Select(GetValueResult).OfType<ValueResult>().ToList();
41+
private CommandValueResult? commandValueResult;
42+
public CommandValueResult CommandValueResult
43+
{
44+
get
45+
{
46+
if (commandValueResult is null)
47+
{
48+
var parent = Parent is CommandResult commandResult
49+
? commandResult.CommandValueResult
50+
: null;
51+
commandValueResult = new CommandValueResult(Command, parent);
52+
}
53+
// Reset unless we put tests in place to ensure it is not called in error handling before SymbolTree processing is complete
54+
commandValueResult.ValueResults = Children.Select(GetValueResult).OfType<ValueResult>().ToList();
55+
return commandValueResult;
56+
}
57+
}
4258

4359
private ValueResult? GetValueResult(SymbolResult symbolResult)
4460
=> symbolResult switch
@@ -51,24 +67,26 @@ internal CommandResult(
5167
/// <inheritdoc/>
5268
public override string ToString() => $"{nameof(CommandResult)}: {IdentifierToken.Value} {string.Join(" ", Tokens.Select(t => t.Value))}";
5369

70+
// TODO: DefaultValues
71+
/*
5472
internal override bool UseDefaultValueFor(ArgumentResult argumentResult)
5573
=> argumentResult.Argument.HasDefaultValue && argumentResult.Tokens.Count == 0;
74+
*/
5675

76+
// TODO: Validation
77+
/*
5778
/// <param name="completeValidation">Only the inner most command goes through complete validation.</param>
5879
internal void Validate(bool completeValidation)
5980
{
6081
if (completeValidation)
6182
{
62-
// TODO: invocation
63-
// if (Command.Action is null && Command.HasSubcommands)
6483
if (Command.HasSubcommands)
6584
{
6685
SymbolResultTree.InsertFirstError(
6786
new ParseError(LocalizationResources.RequiredCommandWasNotProvided(), this));
6887
}
6988
70-
// TODO: validators
71-
/*
89+
// TODO: validators
7290
if (Command.HasValidators)
7391
{
7492
int errorCountBefore = SymbolResultTree.ErrorCount;
@@ -82,7 +100,6 @@ internal void Validate(bool completeValidation)
82100
return;
83101
}
84102
}
85-
*/
86103
}
87104
88105
// TODO: Validation
@@ -104,8 +121,8 @@ private void ValidateOptions(bool completeValidation)
104121
{
105122
var option = options[i];
106123
107-
// TODO: VersionOption, recursive options
108-
// if (!completeValidation && !(option.Recursive || option.Argument.HasDefaultValue || option is VersionOption))
124+
// TODO: VersionOption, recursive options
125+
// if (!completeValidation && !(option.Recursive || option.Argument.HasDefaultValue || option is VersionOption))
109126
if (!completeValidation && !option.Argument.HasDefaultValue)
110127
{
111128
continue;
@@ -148,8 +165,7 @@ private void ValidateOptions(bool completeValidation)
148165
continue;
149166
}
150167
151-
// TODO: validators
152-
/*
168+
// TODO: validators
153169
if (optionResult.Option.HasValidators)
154170
{
155171
int errorsBefore = SymbolResultTree.ErrorCount;
@@ -164,12 +180,9 @@ private void ValidateOptions(bool completeValidation)
164180
continue;
165181
}
166182
}
167-
*/
168183
169184
// TODO: Ensure all argument conversions are run for entered values
170-
/*
171185
_ = argumentResult.GetArgumentConversionResult();
172-
*/
173186
}
174187
}
175188
@@ -210,5 +223,6 @@ private void ValidateArguments(bool completeValidation)
210223
_ = argumentResult.GetArgumentConversionResult();
211224
}
212225
}
226+
*/
213227
}
214228
}

src/System.CommandLine/Parsing/CommandValueResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ internal CommandValueResult(CliCommand command, CommandValueResult? parent = nul
2727
/// <summary>
2828
/// The ValueResult instances for user entered data. This is a sparse list.
2929
/// </summary>
30-
public IEnumerable<ValueResult> ValueResults { get; } = new List<ValueResult>();
30+
public IReadOnlyList<ValueResult> ValueResults { get; internal set; } = [];
3131

3232
/// <summary>
3333
/// The CliCommand that the result is for.

src/System.CommandLine/Parsing/OptionResult.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ internal bool IsArgumentLimitReached
9393
internal ArgumentConversionResult ArgumentConversionResult
9494
=> _argumentConversionResult ??= GetResult(Option.Argument)!.GetArgumentConversionResult();
9595

96+
// TODO: Default values
97+
/*
9698
internal override bool UseDefaultValueFor(ArgumentResult argument) => Implicit;
99+
*/
97100
}
98101
}

src/System.CommandLine/Parsing/ParseOperation.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ internal ParseResult Parse()
8585
_configuration,
8686
_rootCommandResult,
8787
_innermostCommandResult,
88-
_rootCommandResult.SymbolResultTree,
88+
_rootCommandResult.SymbolResultTree.BuildValueResultDictionary(),
8989
/*
9090
_tokens,
9191
*/
@@ -389,6 +389,8 @@ private void AddCurrentTokenToUnmatched()
389389
_symbolResultTree.AddUnmatchedToken(CurrentToken, _innermostCommandResult, _rootCommandResult);
390390
}
391391

392+
// TODO: Validation
393+
/*
392394
private void Validate()
393395
{
394396
// Only the inner most command goes through complete validation,
@@ -403,5 +405,6 @@ private void Validate()
403405
currentResult = currentResult.Parent as CommandResult;
404406
}
405407
}
408+
*/
406409
}
407-
}
410+
}

src/System.CommandLine/Parsing/SymbolResult.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ public IEnumerable<ParseError> Errors
156156
}
157157
*/
158158

159+
// TODO: DefaultValues
160+
/*
159161
internal virtual bool UseDefaultValueFor(ArgumentResult argumentResult) => false;
162+
*/
160163
}
161164
}

0 commit comments

Comments
 (0)