Skip to content

[1653] remove the legacy double dash behavior and ParseResult.UnparsedTokens #1806

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ System.CommandLine
public static CommandLineBuilder AddMiddleware(this CommandLineBuilder builder, System.Action<System.CommandLine.Invocation.InvocationContext> onInvoke, System.CommandLine.Invocation.MiddlewareOrder order = Default)
public static CommandLineBuilder CancelOnProcessTermination(this CommandLineBuilder builder, System.Nullable<System.TimeSpan> timeout = null)
public static CommandLineBuilder EnableDirectives(this CommandLineBuilder builder, System.Boolean value = True)
public static CommandLineBuilder EnableLegacyDoubleDashBehavior(this CommandLineBuilder builder, System.Boolean value = True)
public static CommandLineBuilder EnablePosixBundling(this CommandLineBuilder builder, System.Boolean value = True)
public static CommandLineBuilder RegisterWithDotnetSuggest(this CommandLineBuilder builder)
public static CommandLineBuilder UseDefaults(this CommandLineBuilder builder)
Expand All @@ -98,9 +97,8 @@ System.CommandLine
public static CommandLineBuilder UseVersionOption(this CommandLineBuilder builder)
public static CommandLineBuilder UseVersionOption(this CommandLineBuilder builder, System.String[] aliases)
public class CommandLineConfiguration
.ctor(Command command, System.Boolean enablePosixBundling = True, System.Boolean enableDirectives = True, System.Boolean enableLegacyDoubleDashBehavior = False, System.Boolean enableTokenReplacement = True, LocalizationResources resources = null, System.Collections.Generic.IReadOnlyList<System.CommandLine.Invocation.InvocationMiddleware> middlewarePipeline = null, System.Func<System.CommandLine.Binding.BindingContext,System.CommandLine.Help.HelpBuilder> helpBuilderFactory = null, System.CommandLine.Parsing.TryReplaceToken tokenReplacer = null)
.ctor(Command command, System.Boolean enablePosixBundling = True, System.Boolean enableDirectives = True, System.Boolean enableTokenReplacement = True, LocalizationResources resources = null, System.Collections.Generic.IReadOnlyList<System.CommandLine.Invocation.InvocationMiddleware> middlewarePipeline = null, System.Func<System.CommandLine.Binding.BindingContext,System.CommandLine.Help.HelpBuilder> helpBuilderFactory = null, System.CommandLine.Parsing.TryReplaceToken tokenReplacer = null)
public System.Boolean EnableDirectives { get; }
public System.Boolean EnableLegacyDoubleDashBehavior { get; }
public System.Boolean EnablePosixBundling { get; }
public System.Boolean EnableTokenReplacement { get; }
public LocalizationResources LocalizationResources { get; }
Expand Down Expand Up @@ -236,7 +234,6 @@ System.CommandLine
public System.CommandLine.Parsing.CommandResult RootCommandResult { get; }
public System.Collections.Generic.IReadOnlyList<System.CommandLine.Parsing.Token> Tokens { get; }
public System.Collections.Generic.IReadOnlyList<System.String> UnmatchedTokens { get; }
public System.Collections.Generic.IReadOnlyList<System.String> UnparsedTokens { get; }
public System.CommandLine.Parsing.ArgumentResult FindResultFor(Argument argument)
public System.CommandLine.Parsing.CommandResult FindResultFor(Command command)
public System.CommandLine.Parsing.OptionResult FindResultFor(Option option)
Expand Down Expand Up @@ -487,8 +484,7 @@ System.CommandLine.Parsing
Command=1
Option=2
DoubleDash=3
Unparsed=4
Directive=5
Directive=4
public delegate TryReplaceToken : System.MulticastDelegate, System.ICloneable, System.Runtime.Serialization.ISerializable
.ctor(System.Object object, System.IntPtr method)
public System.IAsyncResult BeginInvoke(System.String tokenToReplace, ref System.Collections.Generic.IReadOnlyList<System.String> replacementTokens, ref System.String& errorMessage, System.AsyncCallback callback, System.Object object)
Expand Down
16 changes: 7 additions & 9 deletions src/System.CommandLine.Hosting.Tests/HostingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ void Execute(IHost host)
}

[Fact]
public static void UseHost_UnparsedTokens_can_propagate_to_Host_Configuration()
public static void UseHost_UnmatchedTokens_can_propagate_to_Host_Configuration()
{
const string testArgument = "test";
const string testKey = "unparsed-config";
string commandLineArgs = $"-- --{testKey} {testArgument}";
const string testKey = "unmatched-config";
string commandLineArgs = $"--{testKey} {testArgument}";

string testConfigValue = null;

Expand All @@ -110,11 +110,10 @@ void Execute(IHost host)
{
Handler = CommandHandler.Create<IHost>(Execute),
})
.EnableLegacyDoubleDashBehavior()
.UseHost(host =>
{
var invocation = (InvocationContext)host.Properties[typeof(InvocationContext)];
var args = invocation.ParseResult.UnparsedTokens.ToArray();
var args = invocation.ParseResult.UnmatchedTokens.ToArray();
host.ConfigureHostConfiguration(config =>
{
config.AddCommandLine(args);
Expand All @@ -129,11 +128,11 @@ void Execute(IHost host)
}

[Fact]
public static void UseHost_UnparsedTokens_are_available_in_HostBuilder_factory()
public static void UseHost_UnmatchedTokens_are_available_in_HostBuilder_factory()
{
const string testArgument = "test";
const string testKey = "unparsed-config";
string commandLineArgs = $"-- --{testKey} {testArgument}";
const string testKey = "unmatched-config";
string commandLineArgs = $"--{testKey} {testArgument}";

string testConfigValue = null;

Expand All @@ -148,7 +147,6 @@ void Execute(IHost host)
{
Handler = CommandHandler.Create<IHost>(Execute),
})
.EnableLegacyDoubleDashBehavior()
.UseHost(args =>
{
var host = new HostBuilder();
Expand Down
2 changes: 1 addition & 1 deletion src/System.CommandLine.Hosting/HostingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static CommandLineBuilder UseHost(this CommandLineBuilder builder,
Action<IHostBuilder> configureHost = null) =>
builder.AddMiddleware(async (invocation, next) =>
{
var argsRemaining = invocation.ParseResult.UnparsedTokens.ToArray();
var argsRemaining = invocation.ParseResult.UnmatchedTokens.ToArray();
var hostBuilder = hostBuilderFactory?.Invoke(argsRemaining)
?? new HostBuilder();
hostBuilder.Properties[typeof(InvocationContext)] = invocation;
Expand Down
5 changes: 2 additions & 3 deletions src/System.CommandLine.Suggest/SuggestionDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,8 @@ public SuggestionDispatcher(ISuggestionRegistration suggestionRegistration, ISug
RegisterCommand,
CompleteScriptCommand
};

root.TreatUnmatchedTokensAsErrors = false;
Parser = new CommandLineBuilder(root)
.EnableLegacyDoubleDashBehavior()
.UseVersionOption()
.UseHelp()
.UseParseDirective()
Expand Down Expand Up @@ -207,7 +206,7 @@ public static string FormatSuggestionArguments(
int position,
string targetExeName)
{
var tokens = parseResult.UnparsedTokens;
var tokens = parseResult.UnmatchedTokens;

var commandLine = tokens.FirstOrDefault() ?? "";

Expand Down
4 changes: 2 additions & 2 deletions src/System.CommandLine.Tests/ArgumentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ public void Custom_parser_can_pass_on_remaining_tokens(string commandLine)
}

[Fact]
public void When_tokens_are_passed_on_by_custom_parser_on_last_argument_then_they_become_unparsed_tokens()
public void When_tokens_are_passed_on_by_custom_parser_on_last_argument_then_they_become_unmatched_tokens()
{

var argument1 = new Argument<int[]>(
Expand All @@ -583,7 +583,7 @@ public void When_tokens_are_passed_on_by_custom_parser_on_last_argument_then_the

var parseResult = command.Parse("1 2 3 4 5 6 7 8");

parseResult.UnparsedTokens
parseResult.UnmatchedTokens
.Should()
.BeEquivalentTo(new[] { "4", "5", "6", "7", "8" },
options => options.WithStrictOrdering());
Expand Down
74 changes: 3 additions & 71 deletions src/System.CommandLine.Tests/ParserTests.DoubleDash.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public void Subsequent_tokens_are_parsed_as_arguments_even_if_they_match_option_
};

var result = new CommandLineBuilder(rootCommand)
.EnableLegacyDoubleDashBehavior(false)
.Build()
.Parse("-o \"some stuff\" -- -o --one -x -y -z -o:foo");

Expand All @@ -34,11 +33,11 @@ public void Subsequent_tokens_are_parsed_as_arguments_even_if_they_match_option_

result.GetValueForArgument(argument).Should().BeEquivalentSequenceTo("-o", "--one", "-x", "-y", "-z", "-o:foo");

result.UnparsedTokens.Should().BeEmpty();
result.UnmatchedTokens.Should().BeEmpty();
}

[Fact]
public void Unparsed_tokens_is_empty()
public void Unmatched_tokens_is_empty()
{
var option = new Option<string[]>(new[] { "-o", "--one" });
var argument = new Argument<string[]>();
Expand All @@ -49,11 +48,10 @@ public void Unparsed_tokens_is_empty()
};

var result = new CommandLineBuilder(rootCommand)
.EnableLegacyDoubleDashBehavior(false)
.Build()
.Parse("-o \"some stuff\" -- --one -x -y -z -o:foo");

result.UnparsedTokens.Should().BeEmpty();
result.UnmatchedTokens.Should().BeEmpty();
}

[Fact] // https://github.com/dotnet/command-line-api/issues/1631
Expand All @@ -68,7 +66,6 @@ public void No_errors_are_generated()
};

var result = new CommandLineBuilder(rootCommand)
.EnableLegacyDoubleDashBehavior(false)
.Build()
.Parse("-o \"some stuff\" -- -o --one -x -y -z -o:foo");

Expand All @@ -85,7 +82,6 @@ public void A_second_double_dash_is_parsed_as_an_argument()
};

var result = new CommandLineBuilder(rootCommand)
.EnableLegacyDoubleDashBehavior(false)
.Build()
.Parse("a b c -- -- d");

Expand All @@ -94,69 +90,5 @@ public void A_second_double_dash_is_parsed_as_an_argument()
strings.Should().BeEquivalentSequenceTo("a", "b", "c", "--", "d");
}
}

public class LegacyDoubleDashBehavior
{
[Fact]
public void The_portion_of_the_command_line_following_a_double_is_treated_as_unparsed_tokens()
{
var result = new CommandLineBuilder(new RootCommand { new Option<string>("-o") })
.EnableLegacyDoubleDashBehavior()
.Build()
.Parse("-o \"some stuff\" -- x y z");

result.UnparsedTokens
.Should()
.BeEquivalentSequenceTo("x", "y", "z");
}

[Fact]
public void Subsequent_tokens_matching_options_will_be_treated_as_unparsed_tokens()
{
var optionO = new Option<string>(new[] { "-o" });
var optionX = new Option<bool>(new[] { "-x" });
var optionY = new Option<bool>(new[] { "-y" });
var optionZ = new Option<bool>(new[] { "-z" });
var rootCommand = new RootCommand
{
optionO,
optionX,
optionY,
optionZ
};
var result = new CommandLineBuilder(rootCommand)
.EnableLegacyDoubleDashBehavior()
.Build()
.Parse("-o \"some stuff\" -- -x -y -z -o:foo");

result.HasOption(optionO).Should().BeTrue();
result.HasOption(optionX).Should().BeFalse();
result.HasOption(optionY).Should().BeFalse();
result.HasOption(optionZ).Should().BeFalse();

result.UnparsedTokens
.Should()
.BeEquivalentSequenceTo("-x",
"-y",
"-z",
"-o:foo");
}

[Fact]
public void Subsequent_tokens_matching_argument_will_be_treated_as_unparsed_tokens()
{
var argument = new Argument<int[]>();
var rootCommand = new RootCommand
{
argument
};
var result = new CommandLineBuilder(rootCommand)
.EnableLegacyDoubleDashBehavior()
.Build()
.Parse("1 2 3 -- 4 5 6 7");

result.GetValueForArgument(argument).Should().BeEquivalentSequenceTo(1, 2, 3);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ public void Tokens_that_cannot_be_converted_by_multiple_arity_argument_flow_to_n
.Should()
.Be("four");

result.UnparsedTokens
result.UnmatchedTokens
.Should()
.ContainSingle()
.Which
Expand Down
7 changes: 0 additions & 7 deletions src/System.CommandLine/Builder/CommandLineBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ public CommandLineBuilder(Command? rootCommand = null)
internal bool EnablePosixBundling { get; set; } = true;

internal bool EnableTokenReplacement { get; set; } = true;

/// <summary>
/// Determines the behavior when parsing a double dash (<c>--</c>) in a command line.
/// </summary>
/// <remarks>When set to <see langword="true"/>, all tokens following <c>--</c> will be placed into the <see cref="ParseResult.UnparsedTokens"/> collection. When set to <see langword="false"/>, all tokens following <c>--</c> will be treated as command arguments, even if they match an existing option.</remarks>
internal bool EnableLegacyDoubleDashBehavior { get; set; }

internal void CustomizeHelpLayout(Action<HelpContext> customize) =>
_customizeHelpBuilder = customize;
Expand Down Expand Up @@ -97,7 +91,6 @@ public Parser Build() =>
Command,
enablePosixBundling: EnablePosixBundling,
enableDirectives: EnableDirectives,
enableLegacyDoubleDashBehavior: EnableLegacyDoubleDashBehavior,
enableTokenReplacement: EnableTokenReplacement,
resources: LocalizationResources,
middlewarePipeline: _middlewareList is null
Expand Down
13 changes: 0 additions & 13 deletions src/System.CommandLine/Builder/CommandLineBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,19 +164,6 @@ public static CommandLineBuilder EnableDirectives(
return builder;
}

/// <summary>
/// Determines the behavior when parsing a double dash (<c>--</c>) in a command line.
/// </summary>
/// <param name="builder">A command line builder.</param>
/// <param name="value"><see langword="true" /> to place all tokens following <c>--</c> into the <see cref="ParseResult.UnparsedTokens"/> collection. <see langword="false" /> to treat all tokens following <c>--</c> as command arguments, even if they match an existing option.</param>
public static CommandLineBuilder EnableLegacyDoubleDashBehavior(
this CommandLineBuilder builder,
bool value = true)
{
builder.EnableLegacyDoubleDashBehavior = value;
return builder;
}

/// <summary>
/// Enables the parser to recognize and expand POSIX-style bundled options.
/// </summary>
Expand Down
9 changes: 0 additions & 9 deletions src/System.CommandLine/CommandLineConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public class CommandLineConfiguration
/// <param name="command">The root command for the parser.</param>
/// <param name="enablePosixBundling"><see langword="true"/> to enable POSIX bundling; otherwise, <see langword="false"/>.</param>
/// <param name="enableDirectives"><see langword="true"/> to enable directive parsing; otherwise, <see langword="false"/>.</param>
/// <param name="enableLegacyDoubleDashBehavior">Enables the legacy behavior of the <c>--</c> token, which is to ignore parsing of subsequent tokens and place them in the <see cref="ParseResult.UnparsedTokens"/> list.</param>
/// <param name="enableTokenReplacement"><see langword="true"/> to enable token replacement; otherwise, <see langword="false"/>.</param>
/// <param name="resources">Provide custom validation messages.</param>
/// <param name="middlewarePipeline">Provide a custom middleware pipeline.</param>
Expand All @@ -35,16 +34,13 @@ public CommandLineConfiguration(
Command command,
bool enablePosixBundling = true,
bool enableDirectives = true,
bool enableLegacyDoubleDashBehavior = false,
bool enableTokenReplacement = true,
LocalizationResources? resources = null,
IReadOnlyList<InvocationMiddleware>? middlewarePipeline = null,
Func<BindingContext, HelpBuilder>? helpBuilderFactory = null,
TryReplaceToken? tokenReplacer = null)
{
RootCommand = command ?? throw new ArgumentNullException(nameof(command));

EnableLegacyDoubleDashBehavior = enableLegacyDoubleDashBehavior;
EnableTokenReplacement = enableTokenReplacement;
EnablePosixBundling = enablePosixBundling;
EnableDirectives = enableDirectives;
Expand Down Expand Up @@ -72,11 +68,6 @@ internal static HelpBuilder DefaultHelpBuilderFactory(BindingContext context, in
/// </summary>
public bool EnableDirectives { get; }

/// <summary>
/// Enables the legacy behavior of the <c>--</c> token, which is to ignore parsing of subsequent tokens and place them in the <see cref="ParseResult.UnparsedTokens"/> list.
/// </summary>
public bool EnableLegacyDoubleDashBehavior { get; }

/// <summary>
/// Gets a value indicating whether POSIX bundling is enabled.
/// </summary>
Expand Down
9 changes: 0 additions & 9 deletions src/System.CommandLine/ParseResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public class ParseResult
{
private readonly List<ParseError> _errors;
private readonly RootCommandResult _rootCommandResult;
private readonly IReadOnlyList<Token> _unparsedTokens;
private readonly IReadOnlyList<Token> _unmatchedTokens;
private CompletionContext? _completionContext;

Expand All @@ -26,7 +25,6 @@ internal ParseResult(
CommandResult commandResult,
DirectiveCollection directives,
TokenizeResult tokenizeResult,
IReadOnlyList<Token>? unparsedTokens,
IReadOnlyList<Token>? unmatchedTokens,
List<ParseError>? errors,
string? commandLineText = null)
Expand All @@ -53,7 +51,6 @@ internal ParseResult(
Tokens = Array.Empty<Token>();
}

_unparsedTokens = unparsedTokens ?? Array.Empty<Token>();
_errors = errors ?? new List<ParseError>();
CommandLineText = commandLineText;

Expand Down Expand Up @@ -120,12 +117,6 @@ internal ParseResult(
/// </summary>
public IReadOnlyList<string> UnmatchedTokens => _unmatchedTokens.Select(t => t.Value).ToArray();

/// <summary>
/// Gets the list of tokens used on the command line that were ignored by the parser.
/// </summary>
/// <remarks>This list will contain all of the tokens following the first occurrence of a <c>--</c> token if <see cref="CommandLineConfiguration.EnableLegacyDoubleDashBehavior"/> is set to <see langword="true"/>.</remarks>
public IReadOnlyList<string> UnparsedTokens => _unparsedTokens.Select(t => t.Value).ToArray();

/// <summary>
/// Gets the completion context for the parse result.
/// </summary>
Expand Down
Loading