Skip to content

Commit 204a997

Browse files
ValueResult unifies OptionResult and ArgumentResult.
OptionResult and ArgumentResult access internal data and ValueResult is a public face for the data and location.
1 parent 84d40f3 commit 204a997

26 files changed

+1526
-1012
lines changed

src/System.CommandLine.Subsystems.Tests/AlternateSubsystems.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ protected override CliExit TearDown(CliExit cliExit)
6868
}
6969

7070
internal class StringDirectiveSubsystem(IAnnotationProvider? annotationProvider = null)
71-
: DirectiveSubsystem("other",SubsystemKind.Other, annotationProvider)
71+
: DirectiveSubsystem("other",SubsystemKind.Diagram, annotationProvider)
7272
{ }
7373

7474
internal class BooleanDirectiveSubsystem(IAnnotationProvider? annotationProvider = null)
75-
: DirectiveSubsystem("diagram", SubsystemKind.Other, annotationProvider)
75+
: DirectiveSubsystem("diagram", SubsystemKind.Diagram, annotationProvider)
7676
{ }
7777

7878
}

src/System.CommandLine.Subsystems.Tests/PipelineTests.cs

Lines changed: 160 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -5,194 +5,192 @@
55
using System.CommandLine.Parsing;
66
using Xunit;
77

8-
namespace System.CommandLine.Subsystems.Tests
8+
namespace System.CommandLine.Subsystems.Tests;
9+
10+
public class PipelineTests
911
{
10-
public class PipelineTests
11-
{
12-
private static Pipeline GetTestPipeline(VersionSubsystem versionSubsystem)
13-
=> new()
14-
{
15-
Version = versionSubsystem
16-
};
17-
private static CliConfiguration GetNewTestConfiguration()
18-
=> new(new CliRootCommand { new CliOption<bool>("-x") }); // Add option expected by test data
19-
20-
private static ConsoleHack GetNewTestConsole()
21-
=> new ConsoleHack().RedirectToBuffer(true);
22-
23-
//private static (Pipeline pipeline, CliConfiguration configuration, ConsoleHack consoleHack) StandardObjects(VersionSubsystem versionSubsystem)
24-
//{
25-
// var configuration = new CliConfiguration(new CliRootCommand { new CliOption<bool>("-x") });
26-
// var pipeline = new Pipeline
27-
// {
28-
// Version = versionSubsystem
29-
// };
30-
// var consoleHack = new ConsoleHack().RedirectToBuffer(true);
31-
// return (pipeline, configuration, consoleHack);
32-
//}
33-
34-
[Theory]
35-
[ClassData(typeof(TestData.Version))]
36-
public void Subsystem_runs_in_pipeline_only_when_requested(string input, bool shouldRun)
12+
private static Pipeline GetTestPipeline(VersionSubsystem versionSubsystem)
13+
=> new()
3714
{
38-
var pipeline = GetTestPipeline(new VersionSubsystem());
39-
var console = GetNewTestConsole();
15+
Version = versionSubsystem
16+
};
17+
private static CliConfiguration GetNewTestConfiguration()
18+
=> new(new CliRootCommand { new CliOption<bool>("-x") }); // Add option expected by test data
19+
20+
private static ConsoleHack GetNewTestConsole()
21+
=> new ConsoleHack().RedirectToBuffer(true);
22+
23+
//private static (Pipeline pipeline, CliConfiguration configuration, ConsoleHack consoleHack) StandardObjects(VersionSubsystem versionSubsystem)
24+
//{
25+
// var configuration = new CliConfiguration(new CliRootCommand { new CliOption<bool>("-x") });
26+
// var pipeline = new Pipeline
27+
// {
28+
// Version = versionSubsystem
29+
// };
30+
// var consoleHack = new ConsoleHack().RedirectToBuffer(true);
31+
// return (pipeline, configuration, consoleHack);
32+
//}
33+
34+
[Theory]
35+
[ClassData(typeof(TestData.Version))]
36+
public void Subsystem_runs_in_pipeline_only_when_requested(string input, bool shouldRun)
37+
{
38+
var pipeline = GetTestPipeline(new VersionSubsystem());
39+
var console = GetNewTestConsole();
4040

41-
var exit = pipeline.Execute(GetNewTestConfiguration(), input, console);
41+
var exit = pipeline.Execute(GetNewTestConfiguration(), input, console);
4242

43-
exit.ExitCode.Should().Be(0);
44-
exit.Handled.Should().Be(shouldRun);
45-
if (shouldRun)
46-
{
47-
console.GetBuffer().Trim().Should().Be(TestData.AssemblyVersionString);
48-
}
43+
exit.ExitCode.Should().Be(0);
44+
exit.Handled.Should().Be(shouldRun);
45+
if (shouldRun)
46+
{
47+
console.GetBuffer().Trim().Should().Be(TestData.AssemblyVersionString);
4948
}
49+
}
5050

51-
[Theory]
52-
[ClassData(typeof(TestData.Version))]
53-
public void Subsystem_runs_with_explicit_parse_only_when_requested(string input, bool shouldRun)
54-
{
55-
var pipeline = GetTestPipeline(new VersionSubsystem());
56-
var console = GetNewTestConsole();
51+
[Theory]
52+
[ClassData(typeof(TestData.Version))]
53+
public void Subsystem_runs_with_explicit_parse_only_when_requested(string input, bool shouldRun)
54+
{
55+
var pipeline = GetTestPipeline(new VersionSubsystem());
56+
var console = GetNewTestConsole();
5757

58-
var result = pipeline.Parse(GetNewTestConfiguration(), input);
59-
var exit = pipeline.Execute(result, input, console);
58+
var result = pipeline.Parse(GetNewTestConfiguration(), input);
59+
var exit = pipeline.Execute(result, input, console);
6060

61-
exit.ExitCode.Should().Be(0);
62-
exit.Handled.Should().Be(shouldRun);
63-
if (shouldRun)
64-
{
65-
console.GetBuffer().Trim().Should().Be(TestData.AssemblyVersionString);
66-
}
61+
exit.ExitCode.Should().Be(0);
62+
exit.Handled.Should().Be(shouldRun);
63+
if (shouldRun)
64+
{
65+
console.GetBuffer().Trim().Should().Be(TestData.AssemblyVersionString);
6766
}
67+
}
6868

69-
[Theory]
70-
[ClassData(typeof(TestData.Version))]
71-
public void Subsystem_runs_initialize_and_teardown_when_requested(string input, bool shouldRun)
72-
{
73-
var versionSubsystem = new AlternateSubsystems.VersionWithInitializeAndTeardown();
74-
var pipeline = GetTestPipeline(versionSubsystem);
75-
var console = GetNewTestConsole();
69+
[Theory]
70+
[ClassData(typeof(TestData.Version))]
71+
public void Subsystem_runs_initialize_and_teardown_when_requested(string input, bool shouldRun)
72+
{
73+
var versionSubsystem = new AlternateSubsystems.VersionWithInitializeAndTeardown();
74+
var pipeline = GetTestPipeline(versionSubsystem);
75+
var console = GetNewTestConsole();
7676

77-
var exit = pipeline.Execute(GetNewTestConfiguration(), input, console);
77+
var exit = pipeline.Execute(GetNewTestConfiguration(), input, console);
7878

79-
exit.ExitCode.Should().Be(0);
80-
exit.Handled.Should().Be(shouldRun);
81-
versionSubsystem.InitializationWasRun.Should().BeTrue();
82-
versionSubsystem.ExecutionWasRun.Should().Be(shouldRun);
83-
versionSubsystem.TeardownWasRun.Should().BeTrue();
84-
}
79+
exit.ExitCode.Should().Be(0);
80+
exit.Handled.Should().Be(shouldRun);
81+
versionSubsystem.InitializationWasRun.Should().BeTrue();
82+
versionSubsystem.ExecutionWasRun.Should().Be(shouldRun);
83+
versionSubsystem.TeardownWasRun.Should().BeTrue();
84+
}
8585

8686

87-
[Theory]
88-
[ClassData(typeof(TestData.Version))]
89-
public void Subsystem_works_without_pipeline(string input, bool shouldRun)
87+
[Theory]
88+
[ClassData(typeof(TestData.Version))]
89+
public void Subsystem_works_without_pipeline(string input, bool shouldRun)
90+
{
91+
var versionSubsystem = new VersionSubsystem();
92+
// TODO: Ensure an efficient conversion as people may copy this code
93+
var args = CliParser.SplitCommandLine(input).ToList().AsReadOnly();
94+
var console = GetNewTestConsole();
95+
var configuration = GetNewTestConfiguration();
96+
97+
Subsystem.Initialize(versionSubsystem, configuration, args);
98+
// This approach might be taken if someone is using a subsystem just for initialization
99+
var parseResult = CliParser.Parse(configuration.RootCommand, args, configuration);
100+
bool value = parseResult.GetValue<bool>("--version");
101+
102+
parseResult.Errors.Should().BeEmpty();
103+
value.Should().Be(shouldRun);
104+
if (shouldRun)
90105
{
91-
var versionSubsystem = new VersionSubsystem();
92-
// TODO: Ensure an efficient conversion as people may copy this code
93-
var args = CliParser.SplitCommandLine(input).ToList().AsReadOnly();
94-
var console = GetNewTestConsole();
95-
var configuration = GetNewTestConfiguration();
96-
97-
Subsystem.Initialize(versionSubsystem, configuration, args);
98-
// This approach might be taken if someone is using a subsystem just for initialization
99-
var parseResult = CliParser.Parse(configuration.RootCommand, args, configuration);
100-
bool value = parseResult.GetValue<bool>("--version");
101-
102-
parseResult.Errors.Should().BeEmpty();
103-
value.Should().Be(shouldRun);
104-
if (shouldRun)
105-
{
106-
// TODO: Add an execute overload to avoid checking activated twice
107-
var exit = Subsystem.Execute(versionSubsystem, parseResult, input, console);
108-
exit.Should().NotBeNull();
109-
exit.ExitCode.Should().Be(0);
110-
exit.Handled.Should().BeTrue();
111-
console.GetBuffer().Trim().Should().Be(TestData.AssemblyVersionString);
112-
}
106+
// TODO: Add an execute overload to avoid checking activated twice
107+
var exit = Subsystem.Execute(versionSubsystem, parseResult, input, console);
108+
exit.Should().NotBeNull();
109+
exit.ExitCode.Should().Be(0);
110+
exit.Handled.Should().BeTrue();
111+
console.GetBuffer().Trim().Should().Be(TestData.AssemblyVersionString);
113112
}
113+
}
114114

115-
[Theory]
116-
[ClassData(typeof(TestData.Version))]
117-
public void Subsystem_works_without_pipeline_style2(string input, bool shouldRun)
118-
{
119-
var versionSubsystem = new VersionSubsystem();
120-
var args = CliParser.SplitCommandLine(input).ToList().AsReadOnly();
121-
var console = GetNewTestConsole();
122-
var configuration = GetNewTestConfiguration();
123-
var expectedVersion = shouldRun
124-
? TestData.AssemblyVersionString
125-
: "";
126-
127-
// Someone might use this approach if they wanted to do something with the ParseResult
128-
Subsystem.Initialize(versionSubsystem, configuration, args);
129-
var parseResult = CliParser.Parse(configuration.RootCommand, args, configuration);
130-
var exit = Subsystem.ExecuteIfNeeded(versionSubsystem, parseResult, input, console);
115+
[Theory]
116+
[ClassData(typeof(TestData.Version))]
117+
public void Subsystem_works_without_pipeline_style2(string input, bool shouldRun)
118+
{
119+
var versionSubsystem = new VersionSubsystem();
120+
var args = CliParser.SplitCommandLine(input).ToList().AsReadOnly();
121+
var console = GetNewTestConsole();
122+
var configuration = GetNewTestConfiguration();
123+
var expectedVersion = shouldRun
124+
? TestData.AssemblyVersionString
125+
: "";
126+
127+
// Someone might use this approach if they wanted to do something with the ParseResult
128+
Subsystem.Initialize(versionSubsystem, configuration, args);
129+
var parseResult = CliParser.Parse(configuration.RootCommand, args, configuration);
130+
var exit = Subsystem.ExecuteIfNeeded(versionSubsystem, parseResult, input, console);
131+
132+
exit.ExitCode.Should().Be(0);
133+
exit.Handled.Should().Be(shouldRun);
134+
console.GetBuffer().Trim().Should().Be(expectedVersion);
135+
}
131136

132-
exit.ExitCode.Should().Be(0);
133-
exit.Handled.Should().Be(shouldRun);
134-
console.GetBuffer().Trim().Should().Be(expectedVersion);
135-
}
136137

138+
[Theory]
139+
[InlineData("-xy", false)]
140+
[InlineData("--versionx", false)]
141+
public void Subsystem_runs_when_requested_even_when_there_are_errors(string input, bool shouldRun)
142+
{
143+
var versionSubsystem = new VersionSubsystem();
144+
var args = CliParser.SplitCommandLine(input).ToList().AsReadOnly();
145+
var configuration = GetNewTestConfiguration();
137146

138-
[Theory]
139-
[InlineData("-xy", false)]
140-
[InlineData("--versionx", false)]
141-
public void Subsystem_runs_when_requested_even_when_there_are_errors(string input, bool shouldRun)
142-
{
143-
var versionSubsystem = new VersionSubsystem();
144-
var args = CliParser.SplitCommandLine(input).ToList().AsReadOnly();
145-
var configuration = GetNewTestConfiguration();
147+
Subsystem.Initialize(versionSubsystem, configuration, args);
148+
// This approach might be taken if someone is using a subsystem just for initialization
149+
var parseResult = CliParser.Parse(configuration.RootCommand, args, configuration);
150+
bool value = parseResult.GetValue<bool>("--version");
146151

147-
Subsystem.Initialize(versionSubsystem, configuration, args);
148-
// This approach might be taken if someone is using a subsystem just for initialization
149-
var parseResult = CliParser.Parse(configuration.RootCommand, args, configuration);
150-
bool value = parseResult.GetValue<bool>("--version");
152+
parseResult.Errors.Should().NotBeEmpty();
153+
value.Should().Be(shouldRun);
154+
}
151155

152-
parseResult.Errors.Should().NotBeEmpty();
153-
value.Should().Be(shouldRun);
154-
}
156+
[Fact]
157+
public void Standard_pipeline_contains_expected_subsystems()
158+
{
159+
var pipeline = new StandardPipeline();
160+
pipeline.Version.Should().BeOfType<VersionSubsystem>();
161+
pipeline.Help.Should().BeOfType<HelpSubsystem>();
162+
pipeline.ErrorReporting.Should().BeOfType<ErrorReportingSubsystem>();
163+
pipeline.Completion.Should().BeOfType<CompletionSubsystem>();
164+
}
155165

156-
[Fact]
157-
public void Standard_pipeline_contains_expected_subsystems()
158-
{
159-
var pipeline = new StandardPipeline();
160-
pipeline.Version.Should().BeOfType<VersionSubsystem>();
161-
pipeline.Help.Should().BeOfType<HelpSubsystem>();
162-
pipeline.ErrorReporting.Should().BeOfType<ErrorReportingSubsystem>();
163-
pipeline.Completion.Should().BeOfType<CompletionSubsystem>();
164-
}
166+
[Fact]
167+
public void Normal_pipeline_contains_no_subsystems()
168+
{
169+
var pipeline = new Pipeline();
170+
pipeline.Version.Should().BeNull();
171+
pipeline.Help.Should().BeNull();
172+
pipeline.ErrorReporting.Should().BeNull();
173+
pipeline.Completion.Should().BeNull();
174+
}
165175

166-
[Fact]
167-
public void Normal_pipeline_contains_no_subsystems()
176+
[Fact]
177+
public void Subsystems_can_access_each_others_data()
178+
{
179+
// TODO: Explore a mechanism that doesn't require the reference to retrieve data, this shows that it is awkward
180+
var symbol = new CliOption<bool>("-x");
181+
var console = GetNewTestConsole();
182+
var pipeline = new StandardPipeline
168183
{
169-
var pipeline = new Pipeline();
170-
pipeline.Version.Should().BeNull();
171-
pipeline.Help.Should().BeNull();
172-
pipeline.ErrorReporting.Should().BeNull();
173-
pipeline.Completion.Should().BeNull();
174-
}
184+
Version = new AlternateSubsystems.VersionThatUsesHelpData(symbol)
185+
};
186+
if (pipeline.Help is null) throw new InvalidOperationException();
187+
var rootCommand = new CliRootCommand
188+
{
189+
symbol.With(pipeline.Help.Description, "Testing")
190+
};
175191

192+
pipeline.Execute(new CliConfiguration(rootCommand), "-v", console);
176193

177-
[Fact]
178-
public void Subsystems_can_access_each_others_data()
179-
{
180-
// TODO: Explore a mechanism that doesn't require the reference to retrieve data, this shows that it is awkward
181-
var symbol = new CliOption<bool>("-x");
182-
var console = GetNewTestConsole();
183-
var pipeline = new StandardPipeline
184-
{
185-
Version = new AlternateSubsystems.VersionThatUsesHelpData(symbol)
186-
};
187-
if (pipeline.Help is null) throw new InvalidOperationException();
188-
var rootCommand = new CliRootCommand
189-
{
190-
symbol.With(pipeline.Help.Description, "Testing")
191-
};
192-
193-
pipeline.Execute(new CliConfiguration(rootCommand), "-v", console);
194-
195-
console.GetBuffer().Trim().Should().Be($"Testing");
196-
}
194+
console.GetBuffer().Trim().Should().Be($"Testing");
197195
}
198196
}

0 commit comments

Comments
 (0)