diff --git a/NuGet.config b/NuGet.config
index d34e6bd81a..d060e04ff3 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -15,8 +15,8 @@
-
-
+
+
diff --git a/eng/Versions.props b/eng/Versions.props
index 3e9c94afa7..ce4e543109 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -45,8 +45,7 @@
6.0.0
5.0.1
- 2.0.0-beta1.20468.1
- 2.0.0-beta1.20074.1
+ 2.0.0-beta4.25072.1
5.0.0
4.5.1
4.5.5
diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/CommandService.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/CommandService.cs
index 4f37f455e0..abf259de40 100644
--- a/src/Microsoft.Diagnostics.DebugServices.Implementation/CommandService.cs
+++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/CommandService.cs
@@ -5,11 +5,10 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.CommandLine;
-using System.CommandLine.Builder;
using System.CommandLine.Help;
using System.CommandLine.Invocation;
-using System.CommandLine.IO;
using System.CommandLine.Parsing;
+using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -67,7 +66,7 @@ public IReadOnlyList ExecuteAndCapture(string commandLine, IServiceProvi
/// other errors
public void Execute(string commandLine, IServiceProvider services)
{
- string[] commandLineArray = CommandLineStringSplitter.Instance.Split(commandLine).ToArray();
+ string[] commandLineArray = CommandLineParser.SplitCommandLine(commandLine).ToArray();
if (commandLineArray.Length <= 0)
{
throw new ArgumentException("Empty command line", nameof(commandLine));
@@ -89,7 +88,7 @@ public void Execute(string commandLine, IServiceProvider services)
public void Execute(string commandName, string commandArguments, IServiceProvider services)
{
commandName = commandName.Trim();
- string[] commandLineArray = CommandLineStringSplitter.Instance.Split(commandName + " " + (commandArguments ?? "")).ToArray();
+ string[] commandLineArray = CommandLineParser.SplitCommandLine(commandName + " " + (commandArguments ?? "")).ToArray();
if (commandLineArray.Length <= 0)
{
throw new ArgumentException("Empty command name or arguments", nameof(commandArguments));
@@ -194,7 +193,7 @@ public string GetDetailedHelp(string commandName, IServiceProvider services, int
{
if (group.TryGetCommand(commandName, out Command command))
{
- if (command.Handler is CommandHandler handler)
+ if (command.Action is CommandHandler handler)
{
try
{
@@ -275,8 +274,7 @@ public void AddCommands(Type type, Func factory)
///
private sealed class CommandGroup
{
- private Parser _parser;
- private readonly CommandLineBuilder _rootBuilder;
+ private Command _rootCommand;
private readonly Dictionary _commandHandlers = new();
///
@@ -285,7 +283,7 @@ private sealed class CommandGroup
/// command prompted used in help message
public CommandGroup(string commandPrompt = null)
{
- _rootBuilder = new CommandLineBuilder(new Command(commandPrompt));
+ _rootCommand = new Command(commandPrompt);
}
///
@@ -297,8 +295,15 @@ public CommandGroup(string commandPrompt = null)
/// parsing error
internal bool Execute(IReadOnlyList commandLine, IServiceProvider services)
{
+ IConsoleService consoleService = services.GetService();
+ CommandLineConfiguration configuration = new(_rootCommand)
+ {
+ Output = new ConsoleServiceWrapper(consoleService.Write),
+ Error = new ConsoleServiceWrapper(consoleService.WriteError)
+ };
+
// Parse the command line and invoke the command
- ParseResult parseResult = Parser.Parse(commandLine);
+ ParseResult parseResult = configuration.Parse(commandLine);
if (parseResult.Errors.Count > 0)
{
@@ -314,10 +319,9 @@ internal bool Execute(IReadOnlyList commandLine, IServiceProvider servic
{
if (parseResult.CommandResult.Command is Command command)
{
- if (command.Handler is CommandHandler handler)
+ if (command.Action is CommandHandler handler)
{
- InvocationContext context = new(parseResult, new LocalConsole(services.GetService()));
- handler.Invoke(context, services);
+ handler.Invoke(parseResult, services);
return true;
}
}
@@ -325,20 +329,17 @@ internal bool Execute(IReadOnlyList commandLine, IServiceProvider servic
return false;
}
- ///
- /// Build/return parser
- ///
- internal Parser Parser => _parser ??= _rootBuilder.Build();
-
///
/// Returns all the command handler instances
///
internal IEnumerable CommandHandlers => _commandHandlers.Values;
+ internal Command Parser => _rootCommand;
+
///
/// Returns true if command or command alias is found
///
- internal bool Contains(string commandName) => _rootBuilder.Command.Children.Contains(commandName);
+ internal bool Contains(string commandName) => TryGetCommand(commandName, out _);
///
/// Returns the command handler for the command or command alias
@@ -351,7 +352,7 @@ internal bool TryGetCommandHandler(string commandName, out CommandHandler handle
handler = null;
if (TryGetCommand(commandName, out Command command))
{
- handler = command.Handler as CommandHandler;
+ handler = command.Action as CommandHandler;
}
return handler != null;
}
@@ -364,7 +365,7 @@ internal bool TryGetCommandHandler(string commandName, out CommandHandler handle
/// true if found
internal bool TryGetCommand(string commandName, out Command command)
{
- command = _rootBuilder.Command.Children.GetByAlias(commandName) as Command;
+ command = _rootCommand.Subcommands.FirstOrDefault(cmd => cmd.Name == commandName || cmd.Aliases.Contains(commandName));
return command != null;
}
@@ -382,7 +383,7 @@ internal void CreateCommand(Type type, CommandAttribute commandAttribute, Func p.CanWrite))
@@ -390,16 +391,16 @@ internal void CreateCommand(Type type, CommandAttribute commandAttribute, Func).MakeGenericType(property.PropertyType)
+ .GetConstructor([typeof(string)])
+ .Invoke([argumentAttribute.Name ?? property.Name.ToLowerInvariant()]);
+
+ argument.Description = argumentAttribute.Help;
+ argument.Arity = arity;
+
+ command.Arguments.Add(argument);
arguments.Add((property, argument));
}
else
@@ -407,37 +408,34 @@ internal void CreateCommand(Type type, CommandAttribute commandAttribute, Func).MakeGenericType(property.PropertyType)
+ .GetConstructor([typeof(string), typeof(string[])])
+ .Invoke([optionAttribute.Name ?? BuildOptionAlias(property.Name), optionAttribute.Aliases]);
- foreach (string alias in optionAttribute.Aliases)
- {
- option.AddAlias(alias);
- }
+ option.Description = optionAttribute.Help;
+
+ command.Options.Add(option);
+ options.Add((property, option));
}
}
}
CommandHandler handler = new(commandAttribute, arguments, options, type, factory);
_commandHandlers.Add(command.Name, handler);
- command.Handler = handler;
- _rootBuilder.AddCommand(command);
+ command.Action = handler;
+ _rootCommand.Subcommands.Add(command);
// Build or re-build parser instance after this command is added
- FlushParser();
}
- internal string GetDetailedHelp(ICommand command, IServiceProvider services, int windowWidth)
+ internal string GetDetailedHelp(Command command, IServiceProvider services, int windowWidth)
{
- CaptureConsole console = new();
+ StringWriter console = new();
// Get the command help
- HelpBuilder helpBuilder = new(console, maxWidth: windowWidth);
- helpBuilder.Write(command);
+ HelpBuilder helpBuilder = new(maxWidth: windowWidth);
+ HelpContext helpContext = new(helpBuilder, command, console);
+ helpBuilder.Write(helpContext);
// Get the detailed help if any
if (TryGetCommandHandler(command.Name, out CommandHandler handler))
@@ -445,15 +443,13 @@ internal string GetDetailedHelp(ICommand command, IServiceProvider services, int
string helpText = handler.GetDetailedHelp(Parser, services);
if (helpText is not null)
{
- console.Out.Write(helpText);
+ console.Write(helpText);
}
}
return console.ToString();
}
- private void FlushParser() => _parser = null;
-
private static string BuildOptionAlias(string parameterName)
{
if (string.IsNullOrWhiteSpace(parameterName))
@@ -467,7 +463,7 @@ private static string BuildOptionAlias(string parameterName)
///
/// The normal command handler.
///
- private sealed class CommandHandler : ICommandHandler
+ private sealed class CommandHandler : SynchronousCommandLineAction
{
private readonly CommandAttribute _commandAttribute;
private readonly IEnumerable<(PropertyInfo Property, Argument Argument)> _arguments;
@@ -535,11 +531,6 @@ public CommandHandler(
}
}
- Task ICommandHandler.InvokeAsync(InvocationContext context)
- {
- return Task.FromException(new NotImplementedException());
- }
-
///
/// Returns the command name
///
@@ -568,14 +559,16 @@ Task ICommandHandler.InvokeAsync(InvocationContext context)
///
/// Returns true is the command is supported by the command filter. Calls the FilterInvokeAttribute marked method.
///
- internal bool IsCommandSupported(Parser parser, IServiceProvider services) => _methodInfoFilter == null || (bool)Invoke(_methodInfoFilter, context: null, parser, services);
+ internal bool IsCommandSupported(Command parser, IServiceProvider services) => _methodInfoFilter == null || (bool)Invoke(_methodInfoFilter, context: null, parser, services);
///
/// Execute the command synchronously.
///
/// invocation context
/// service provider
- internal void Invoke(InvocationContext context, IServiceProvider services) => Invoke(_methodInfo, context, context.Parser, services);
+ internal void Invoke(ParseResult context, IServiceProvider services) => Invoke(_methodInfo, context, (Command)context.RootCommandResult.Command, services);
+
+ public override int Invoke(ParseResult parseResult) => throw new NotImplementedException();
///
/// Return the various ways the command can be invoked. For building the help text.
@@ -604,7 +597,7 @@ internal string HelpInvocation
/// parser instance
/// service provider
/// true help called, false no help function
- internal string GetDetailedHelp(Parser parser, IServiceProvider services)
+ internal string GetDetailedHelp(Command parser, IServiceProvider services)
{
if (_methodInfoHelp == null)
{
@@ -618,7 +611,7 @@ internal string GetDetailedHelp(Parser parser, IServiceProvider services)
return (string)Invoke(_methodInfoHelp, context: null, parser, services);
}
- private object Invoke(MethodInfo methodInfo, InvocationContext context, Parser parser, IServiceProvider services)
+ private object Invoke(MethodInfo methodInfo, ParseResult context, Command parser, IServiceProvider services)
{
object instance = null;
if (!methodInfo.IsStatic)
@@ -629,7 +622,7 @@ private object Invoke(MethodInfo methodInfo, InvocationContext context, Parser p
return Utilities.Invoke(methodInfo, instance, services);
}
- private void SetProperties(InvocationContext context, Parser parser, object instance)
+ private void SetProperties(ParseResult contextParseResult, Command parser, object instance)
{
ParseResult defaultParseResult = null;
@@ -637,7 +630,9 @@ private void SetProperties(InvocationContext context, Parser parser, object inst
string defaultOptions = _commandAttribute.DefaultOptions;
if (defaultOptions != null)
{
- defaultParseResult = parser.Parse(Name + " " + defaultOptions);
+ List commandLine = new() { Name };
+ commandLine.AddRange(CommandLineParser.SplitCommandLine(defaultOptions));
+ defaultParseResult = parser.Parse(commandLine);
}
// Now initialize the option and service properties from the default and command line options
@@ -647,18 +642,18 @@ private void SetProperties(InvocationContext context, Parser parser, object inst
if (defaultParseResult != null)
{
- OptionResult defaultOptionResult = defaultParseResult.FindResultFor(option.Option);
+ OptionResult defaultOptionResult = defaultParseResult.GetResult(option.Option);
if (defaultOptionResult != null)
{
- value = defaultOptionResult.GetValueOrDefault();
+ value = defaultOptionResult.GetValueOrDefault