Skip to content

Commit 3132acb

Browse files
Separate parse from invocation configurations (#2606)
* restore System.CommandLine.v3.ncrunchsolution * split out configuration types for Parse vs Invoke * remove Output and Error from CommandLineConfiguration * remove CommandLineConfiguration.RootCommand * update API baseline * rename CommandLineConfiguration to ParserConfiguration * rename CommandLineInvocationConfiguration to InvocationConfiguration * rename CommandLineConfigurationException to ParserConfigurationException * update API baseline * fix a couple of warnings * Update src/System.CommandLine/ParseResult.cs Co-authored-by: Adam Sitnik <adam.sitnik@gmail.com> * PR comments, API baseline update * fix test app code * Consolidate ParseResult.InvokeAsync overloads, remove ThrowIfInvalid * Remove unused custom exception type * consolidate Invoke overloads into one method per PR feedback --------- Co-authored-by: Adam Sitnik <adam.sitnik@gmail.com>
1 parent 7bb08a6 commit 3132acb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+698
-1258
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<SolutionConfiguration>
2+
<Settings>
3+
<AllowParallelTestExecution>True</AllowParallelTestExecution>
4+
<CustomBuildProperties>
5+
<Value>TargetFrameworks = net8.0</Value>
6+
<Value>TargetFramework = net8.0</Value>
7+
</CustomBuildProperties>
8+
<EnableRDI>False</EnableRDI>
9+
<RdiConfigured>True</RdiConfigured>
10+
<SolutionConfigured>True</SolutionConfigured>
11+
</Settings>
12+
</SolutionConfiguration>

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

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,31 +49,13 @@
4949
public System.Void Add(Option option)
5050
public System.Void Add(Command command)
5151
public System.Collections.Generic.IEnumerable<System.CommandLine.Completions.CompletionItem> GetCompletions(System.CommandLine.Completions.CompletionContext context)
52-
public ParseResult Parse(System.Collections.Generic.IReadOnlyList<System.String> args, CommandLineConfiguration configuration = null)
53-
public ParseResult Parse(System.String commandLine, CommandLineConfiguration configuration = null)
52+
public ParseResult Parse(System.Collections.Generic.IReadOnlyList<System.String> args, ParserConfiguration configuration = null)
53+
public ParseResult Parse(System.String commandLine, ParserConfiguration configuration = null)
5454
public System.Void SetAction(System.Action<ParseResult> action)
5555
public System.Void SetAction(System.Func<ParseResult,System.Int32> action)
5656
public System.Void SetAction(System.Func<ParseResult,System.Threading.CancellationToken,System.Threading.Tasks.Task> action)
5757
public System.Void SetAction(System.Func<ParseResult,System.Threading.Tasks.Task> action)
5858
public System.Void SetAction(System.Func<ParseResult,System.Threading.CancellationToken,System.Threading.Tasks.Task<System.Int32>> action)
59-
public class CommandLineConfiguration
60-
.ctor(Command rootCommand)
61-
public System.Boolean EnableDefaultExceptionHandler { get; set; }
62-
public System.Boolean EnablePosixBundling { get; set; }
63-
public System.IO.TextWriter Error { get; set; }
64-
public System.IO.TextWriter Output { get; set; }
65-
public System.Nullable<System.TimeSpan> ProcessTerminationTimeout { get; set; }
66-
public System.CommandLine.Parsing.TryReplaceToken ResponseFileTokenReplacer { get; set; }
67-
public Command RootCommand { get; }
68-
public System.Int32 Invoke(System.String commandLine)
69-
public System.Int32 Invoke(System.String[] args)
70-
public System.Threading.Tasks.Task<System.Int32> InvokeAsync(System.String commandLine, System.Threading.CancellationToken cancellationToken = null)
71-
public System.Threading.Tasks.Task<System.Int32> InvokeAsync(System.String[] args, System.Threading.CancellationToken cancellationToken = null)
72-
public ParseResult Parse(System.Collections.Generic.IReadOnlyList<System.String> args)
73-
public ParseResult Parse(System.String commandLine)
74-
public System.Void ThrowIfInvalid()
75-
public class CommandLineConfigurationException : System.Exception, System.Runtime.Serialization.ISerializable
76-
.ctor(System.String message)
7759
public static class CompletionSourceExtensions
7860
public static System.Void Add(this System.Collections.Generic.List<System.Func<System.CommandLine.Completions.CompletionContext,System.Collections.Generic.IEnumerable<System.CommandLine.Completions.CompletionItem>>> completionSources, System.Func<System.CommandLine.Completions.CompletionContext,System.Collections.Generic.IEnumerable<System.String>> completionsDelegate)
7961
public static System.Void Add(this System.Collections.Generic.List<System.Func<System.CommandLine.Completions.CompletionContext,System.Collections.Generic.IEnumerable<System.CommandLine.Completions.CompletionItem>>> completionSources, System.String[] completions)
@@ -88,6 +70,12 @@
8870
public class EnvironmentVariablesDirective : Directive
8971
.ctor()
9072
public System.CommandLine.Invocation.CommandLineAction Action { get; set; }
73+
public class InvocationConfiguration
74+
.ctor()
75+
public System.Boolean EnableDefaultExceptionHandler { get; set; }
76+
public System.IO.TextWriter Error { get; set; }
77+
public System.IO.TextWriter Output { get; set; }
78+
public System.Nullable<System.TimeSpan> ProcessTerminationTimeout { get; set; }
9179
public abstract class Option : Symbol
9280
public System.CommandLine.Invocation.CommandLineAction Action { get; set; }
9381
public System.Collections.Generic.ICollection<System.String> Aliases { get; }
@@ -115,11 +103,16 @@
115103
public static Option<System.IO.DirectoryInfo> AcceptExistingOnly(this Option<System.IO.DirectoryInfo> option)
116104
public static Option<System.IO.FileSystemInfo> AcceptExistingOnly(this Option<System.IO.FileSystemInfo> option)
117105
public static Option<T> AcceptExistingOnly<T>(this Option<T> option)
106+
public class ParserConfiguration
107+
.ctor()
108+
public System.Boolean EnablePosixBundling { get; set; }
109+
public System.CommandLine.Parsing.TryReplaceToken ResponseFileTokenReplacer { get; set; }
118110
public class ParseResult
119111
public System.CommandLine.Invocation.CommandLineAction Action { get; }
120112
public System.CommandLine.Parsing.CommandResult CommandResult { get; }
121-
public CommandLineConfiguration Configuration { get; }
113+
public ParserConfiguration Configuration { get; }
122114
public System.Collections.Generic.IReadOnlyList<System.CommandLine.Parsing.ParseError> Errors { get; }
115+
public InvocationConfiguration InvocationConfiguration { get; }
123116
public System.CommandLine.Parsing.CommandResult RootCommandResult { get; }
124117
public System.Collections.Generic.IReadOnlyList<System.CommandLine.Parsing.Token> Tokens { get; }
125118
public System.Collections.Generic.IReadOnlyList<System.String> UnmatchedTokens { get; }
@@ -137,8 +130,8 @@
137130
public T GetValue<T>(Argument<T> argument)
138131
public T GetValue<T>(Option<T> option)
139132
public T GetValue<T>(System.String name)
140-
public System.Int32 Invoke()
141-
public System.Threading.Tasks.Task<System.Int32> InvokeAsync(System.Threading.CancellationToken cancellationToken = null)
133+
public System.Int32 Invoke(InvocationConfiguration configuration = null)
134+
public System.Threading.Tasks.Task<System.Int32> InvokeAsync(InvocationConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = null)
142135
public System.String ToString()
143136
public class RootCommand : Command, System.Collections.IEnumerable
144137
public static System.String ExecutableName { get; }
@@ -212,8 +205,8 @@ System.CommandLine.Parsing
212205
public System.Void OnlyTake(System.Int32 numberOfTokens)
213206
public System.String ToString()
214207
public static class CommandLineParser
215-
public static System.CommandLine.ParseResult Parse(System.CommandLine.Command command, System.Collections.Generic.IReadOnlyList<System.String> args, System.CommandLine.CommandLineConfiguration configuration = null)
216-
public static System.CommandLine.ParseResult Parse(System.CommandLine.Command command, System.String commandLine, System.CommandLine.CommandLineConfiguration configuration = null)
208+
public static System.CommandLine.ParseResult Parse(System.CommandLine.Command command, System.Collections.Generic.IReadOnlyList<System.String> args, System.CommandLine.ParserConfiguration configuration = null)
209+
public static System.CommandLine.ParseResult Parse(System.CommandLine.Command command, System.String commandLine, System.CommandLine.ParserConfiguration configuration = null)
217210
public static System.Collections.Generic.IEnumerable<System.String> SplitCommandLine(System.String commandLine)
218211
public class CommandResult : SymbolResult
219212
public System.Collections.Generic.IEnumerable<SymbolResult> Children { get; }

src/System.CommandLine.Suggest.Tests/EndToEndTestApp/Program.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ static async Task Main(string[] args)
3333
return Task.CompletedTask;
3434
});
3535

36-
CommandLineConfiguration commandLine = new (rootCommand);
37-
38-
await commandLine.InvokeAsync(args);
36+
await rootCommand.Parse(args).InvokeAsync();
3937
}
4038
}
4139
}

src/System.CommandLine.Suggest.Tests/SuggestionShellScriptHandlerTest.cs

Lines changed: 17 additions & 18 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.IO;
5+
using System.Threading;
56
using System.Threading.Tasks;
67
using FluentAssertions;
78
using Xunit;
@@ -10,32 +11,34 @@ namespace System.CommandLine.Suggest.Tests
1011
{
1112
public class SuggestionShellScriptHandlerTest
1213
{
13-
private readonly CommandLineConfiguration _configuration;
14+
private readonly RootCommand _rootCommand;
15+
private readonly InvocationConfiguration _configuration;
1416

1517
public SuggestionShellScriptHandlerTest()
1618
{
17-
_configuration = new SuggestionDispatcher(new TestSuggestionRegistration()).Configuration;
19+
_rootCommand = new SuggestionDispatcher(new TestSuggestionRegistration()).RootCommand;
20+
_configuration = new()
21+
{
22+
Output = new StringWriter(),
23+
Error = new StringWriter()
24+
};
1825
}
1926

2027
[Fact]
2128
public async Task When_shell_type_is_not_supported_it_throws()
2229
{
23-
_configuration.Error = new StringWriter();
24-
25-
await _configuration.InvokeAsync("script 123");
30+
await _rootCommand.Parse("script 123").InvokeAsync(_configuration, CancellationToken.None);
2631

2732
_configuration.Error
28-
.ToString()
29-
.Should()
30-
.Contain("Shell '123' is not supported.");
33+
.ToString()
34+
.Should()
35+
.Contain("Shell '123' is not supported.");
3136
}
3237

3338
[Fact]
3439
public async Task It_should_print_bash_shell_script()
3540
{
36-
_configuration.Output = new StringWriter();
37-
38-
await _configuration.InvokeAsync("script bash");
41+
await _rootCommand.Parse("script bash").InvokeAsync(_configuration, CancellationToken.None);
3942

4043
_configuration.Output.ToString().Should().Contain("_dotnet_bash_complete()");
4144
_configuration.Output.ToString().Should().NotContain("\r\n");
@@ -44,9 +47,7 @@ public async Task It_should_print_bash_shell_script()
4447
[Fact]
4548
public async Task It_should_print_powershell_shell_script()
4649
{
47-
_configuration.Output = new StringWriter();
48-
49-
await _configuration.InvokeAsync("script powershell");
50+
await _rootCommand.Parse("script powershell").InvokeAsync(_configuration, CancellationToken.None);
5051

5152
_configuration.Output.ToString().Should().Contain("Register-ArgumentCompleter");
5253
_configuration.Output.ToString().Should().Contain("\r\n");
@@ -55,12 +56,10 @@ public async Task It_should_print_powershell_shell_script()
5556
[Fact]
5657
public async Task It_should_print_zsh_shell_script()
5758
{
58-
_configuration.Output = new StringWriter();
59+
await _rootCommand.Parse("script zsh").InvokeAsync(_configuration, CancellationToken.None);
5960

60-
await _configuration.InvokeAsync("script zsh");
61-
6261
_configuration.Output.ToString().Should().Contain("_dotnet_zsh_complete()");
6362
_configuration.Output.ToString().Should().NotContain("\r\n");
6463
}
6564
}
66-
}
65+
}

src/System.CommandLine.Suggest/SuggestionDispatcher.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using System.Linq;
77
using System.Threading;
88
using System.Threading.Tasks;
9-
using System.CommandLine.Completions;
109

1110
namespace System.CommandLine.Suggest
1211
{
@@ -29,7 +28,7 @@ public SuggestionDispatcher(ISuggestionRegistration suggestionRegistration, ISug
2928
};
3029
CompleteScriptCommand.SetAction(context =>
3130
{
32-
SuggestionShellScriptHandler.Handle(context.Configuration.Output, context.GetValue(shellTypeArgument));
31+
SuggestionShellScriptHandler.Handle(context.InvocationConfiguration.Output, context.GetValue(shellTypeArgument));
3332
});
3433

3534
ListCommand = new Command("list")
@@ -38,7 +37,7 @@ public SuggestionDispatcher(ISuggestionRegistration suggestionRegistration, ISug
3837
};
3938
ListCommand.SetAction((ctx, cancellationToken) =>
4039
{
41-
ctx.Configuration.Output.WriteLine(ShellPrefixesToMatch(_suggestionRegistration));
40+
ctx.InvocationConfiguration.Output.WriteLine(ShellPrefixesToMatch(_suggestionRegistration));
4241
return Task.CompletedTask;
4342
});
4443

@@ -59,25 +58,27 @@ public SuggestionDispatcher(ISuggestionRegistration suggestionRegistration, ISug
5958

6059
RegisterCommand.SetAction((context, cancellationToken) =>
6160
{
62-
Register(context.GetValue(commandPathOption), context.Configuration.Output);
61+
Register(context.GetValue(commandPathOption), context.InvocationConfiguration.Output);
6362
return Task.CompletedTask;
6463
});
6564

66-
var root = new RootCommand
65+
RootCommand = new RootCommand
6766
{
6867
ListCommand,
6968
GetCommand,
7069
RegisterCommand,
7170
CompleteScriptCommand,
7271
};
73-
root.TreatUnmatchedTokensAsErrors = false;
74-
Configuration = new CommandLineConfiguration(root);
72+
RootCommand.TreatUnmatchedTokensAsErrors = false;
73+
Configuration = new InvocationConfiguration();
7574
}
7675

7776
private Command CompleteScriptCommand { get; }
7877

7978
private Command GetCommand { get; }
8079

80+
public RootCommand RootCommand { get; }
81+
8182
private Option<FileInfo> ExecutableOption { get; } = GetExecutableOption();
8283

8384
private static Option<FileInfo> GetExecutableOption()
@@ -98,11 +99,11 @@ private static Option<FileInfo> GetExecutableOption()
9899

99100
private Command RegisterCommand { get; }
100101

101-
public CommandLineConfiguration Configuration { get; }
102+
public InvocationConfiguration Configuration { get; }
102103

103104
public TimeSpan Timeout { get; set; } = TimeSpan.FromMilliseconds(5000);
104105

105-
public Task<int> InvokeAsync(string[] args) => Configuration.InvokeAsync(args);
106+
public Task<int> InvokeAsync(string[] args) => RootCommand.Parse(args).InvokeAsync(Configuration);
106107

107108
private void Register(
108109
string commandPath,
@@ -168,7 +169,7 @@ private Task<int> Get(ParseResult parseResult, CancellationToken cancellationTok
168169
Program.LogDebug($"dotnet-suggest returning: \"{completions.Replace("\r", "\\r").Replace("\n", "\\n")}\"");
169170
#endif
170171

171-
parseResult.Configuration.Output.Write(completions);
172+
parseResult.InvocationConfiguration.Output.Write(completions);
172173

173174
return Task.FromResult(0);
174175
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public class ClassWithMethodHavingParameter<T>
7171

7272
public ClassWithMethodHavingParameter(ParseResult parseResult)
7373
{
74-
_output = parseResult.Configuration.Output;
74+
_output = parseResult.InvocationConfiguration.Output;
7575
}
7676

7777
public int Handle(T value)

0 commit comments

Comments
 (0)