From 173e33e47041032435299166b3c5c4fd86cc8f09 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 24 Feb 2023 19:57:24 +0100 Subject: [PATCH 1/5] make Symbol.Name a mandatory, non-nullable and readonly property --- ...ommandLine_api_is_not_changed.approved.txt | 12 ++--- .../SuggestionDispatcher.cs | 9 ++-- src/System.CommandLine/Argument.cs | 30 +----------- src/System.CommandLine/Argument{T}.cs | 25 ++-------- .../Binding/ArgumentConversionResult.cs | 12 ++--- src/System.CommandLine/Command.cs | 3 +- src/System.CommandLine/Help/HelpOption.cs | 6 ++- src/System.CommandLine/Help/VersionOption.cs | 7 ++- src/System.CommandLine/IdentifierSymbol.cs | 46 +------------------ src/System.CommandLine/Option.cs | 13 ++---- src/System.CommandLine/Option{T}.cs | 21 +++++---- .../Parsing/CommandResult.cs | 2 +- .../Parsing/StringExtensions.cs | 25 ---------- .../Parsing/SymbolResultExtensions.cs | 2 +- src/System.CommandLine/RootCommand.cs | 32 ++++++------- src/System.CommandLine/Symbol.cs | 31 +++++++++---- 16 files changed, 86 insertions(+), 190 deletions(-) diff --git a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt b/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt index 81680080eb..a53584fac4 100644 --- a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt +++ b/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt @@ -10,13 +10,11 @@ System.CommandLine public System.Object GetDefaultValue() public System.String ToString() public class Argument : Argument, IValueDescriptor, System.CommandLine.Binding.IValueDescriptor - .ctor() .ctor(System.String name, System.String description = null) .ctor(System.String name, Func defaultValueFactory, System.String description = null) .ctor(System.String name, T defaultValue, System.String description = null) - .ctor(Func defaultValueFactory) + .ctor(System.String name, Func defaultValueFactory) .ctor(System.String name, Func parse, System.Boolean isDefault = False, System.String description = null) - .ctor(Func parse, System.Boolean isDefault = False) public System.Boolean HasDefaultValue { get; } public System.Type ValueType { get; } public System.Void AcceptLegalFileNamesOnly() @@ -153,11 +151,11 @@ System.CommandLine public System.Collections.Generic.IEnumerable GetCompletions(System.CommandLine.Completions.CompletionContext context) public class Option : Option, IValueDescriptor, System.CommandLine.Binding.IValueDescriptor .ctor(System.String name, System.String description = null) - .ctor(System.String[] aliases, System.String description = null) + .ctor(System.String name, System.String[] aliases, System.String description = null) .ctor(System.String name, Func parseArgument, System.Boolean isDefault = False, System.String description = null) - .ctor(System.String[] aliases, Func parseArgument, System.Boolean isDefault = False, System.String description = null) + .ctor(System.String name, System.String[] aliases, Func parseArgument, System.Boolean isDefault = False, System.String description = null) .ctor(System.String name, Func defaultValueFactory, System.String description = null) - .ctor(System.String[] aliases, Func defaultValueFactory, System.String description = null) + .ctor(System.String name, System.String[] aliases, Func defaultValueFactory, System.String description = null) public System.Void AcceptLegalFileNamesOnly() public System.Void AcceptLegalFilePathsOnly() public System.Void AcceptOnlyFromAmong(System.String[] values) @@ -194,7 +192,7 @@ System.CommandLine public abstract class Symbol public System.String Description { get; set; } public System.Boolean IsHidden { get; set; } - public System.String Name { get; set; } + public System.String Name { get; } public System.Collections.Generic.IEnumerable Parents { get; } public System.Collections.Generic.IEnumerable GetCompletions(System.CommandLine.Completions.CompletionContext context) public System.String ToString() diff --git a/src/System.CommandLine.Suggest/SuggestionDispatcher.cs b/src/System.CommandLine.Suggest/SuggestionDispatcher.cs index e8fd907f5c..c45319a869 100644 --- a/src/System.CommandLine.Suggest/SuggestionDispatcher.cs +++ b/src/System.CommandLine.Suggest/SuggestionDispatcher.cs @@ -22,10 +22,7 @@ public SuggestionDispatcher(ISuggestionRegistration suggestionRegistration, ISug _suggestionStore = suggestionStore ?? new SuggestionStore(); - var shellTypeArgument = new Argument - { - Name = nameof(ShellType) - }; + var shellTypeArgument = new Argument(nameof(ShellType)); CompleteScriptCommand = new Command("script", "Print complete script for specific shell") { @@ -93,7 +90,7 @@ public SuggestionDispatcher(ISuggestionRegistration suggestionRegistration, ISug private static Option GetExecutableOption() { - var option = new Option(new[] { "-e", "--executable" }, "The executable to call for suggestions"); + var option = new Option("--executable", new[] { "-e", "--executable" }, "The executable to call for suggestions"); option.AcceptLegalFilePathsOnly(); return option; @@ -101,7 +98,7 @@ private static Option GetExecutableOption() private Command ListCommand { get; } - private Option PositionOption { get; } = new(new[] { "-p", "--position" }, + private Option PositionOption { get; } = new("--position", new[] { "-p", "--position" }, description: "The current character position on the command line", defaultValueFactory: () => short.MaxValue); diff --git a/src/System.CommandLine/Argument.cs b/src/System.CommandLine/Argument.cs index ae5276b1b3..29dfec7eba 100644 --- a/src/System.CommandLine/Argument.cs +++ b/src/System.CommandLine/Argument.cs @@ -19,22 +19,13 @@ public abstract class Argument : Symbol, IValueDescriptor private List>>? _completionSources = null; private List>? _validators = null; - /// - /// Initializes a new instance of the Argument class. - /// - protected Argument() - { - } - /// /// Initializes a new instance of the Argument class. /// /// The name of the argument. /// The description of the argument, shown in help. - protected Argument(string? name = null, string? description = null) + protected Argument(string name, string? description = null) : base(name, description, allowWhiteSpacesInName: true) { - Name = name!; - Description = description; } /// @@ -82,25 +73,6 @@ internal TryConvertArgument? ConvertArguments /// public abstract Type ValueType { get; } - private protected override string DefaultName - { - get - { - if (FirstParent is not null && FirstParent.Next is null) - { - switch (FirstParent.Symbol) - { - case Option option: - return option.Name; - case Command _: - return ValueType.Name.ToLowerInvariant(); - } - } - - return ""; - } - } - /// /// Provides a list of argument validators. Validators can be used /// to provide custom errors based on user input. diff --git a/src/System.CommandLine/Argument{T}.cs b/src/System.CommandLine/Argument{T}.cs index 12f14ff65c..da43b13ce6 100644 --- a/src/System.CommandLine/Argument{T}.cs +++ b/src/System.CommandLine/Argument{T}.cs @@ -13,17 +13,8 @@ public class Argument : Argument, IValueDescriptor private Func? _defaultValueFactory; private readonly bool _hasCustomParser; - /// - /// Initializes a new instance of the Argument class. - /// - public Argument() - { - } - /// - public Argument( - string? name, - string? description = null) : base(name, description) + public Argument(string name, string? description = null) : base(name, description) { } @@ -59,9 +50,10 @@ public Argument( /// /// Initializes a new instance of the Argument class. /// + /// The name of the argument. /// The delegate to invoke to return the default value. /// Thrown when is null. - public Argument(Func defaultValueFactory) : this() + public Argument(string name, Func defaultValueFactory) : this(name) { SetDefaultValueFactory(defaultValueFactory); } @@ -75,7 +67,7 @@ public Argument(Func defaultValueFactory) : this() /// The description of the argument, shown in help. /// Thrown when is null. public Argument( - string? name, + string name, Func parse, bool isDefault = false, string? description = null) : this(name, description) @@ -110,15 +102,6 @@ public Argument( _hasCustomParser = true; } - /// - /// Initializes a new instance of the Argument class. - /// - /// A custom argument parser. - /// to use the result as default value. - public Argument(Func parse, bool isDefault = false) : this(null!, parse, isDefault) - { - } - internal override bool HasCustomParser => _hasCustomParser; /// diff --git a/src/System.CommandLine/Binding/ArgumentConversionResult.cs b/src/System.CommandLine/Binding/ArgumentConversionResult.cs index 555125cf99..a8390776d7 100644 --- a/src/System.CommandLine/Binding/ArgumentConversionResult.cs +++ b/src/System.CommandLine/Binding/ArgumentConversionResult.cs @@ -47,32 +47,32 @@ private static string FormatErrorMessage( { if (argumentResult.Parent is CommandResult commandResult) { - string alias = commandResult.Command.GetLongestAlias(removePrefix: false); + string name = commandResult.Command.Name; CompletionItem[] completionItems = argumentResult.Argument.GetCompletions(CompletionContext.Empty).ToArray(); if (completionItems.Length > 0) { return LocalizationResources.ArgumentConversionCannotParseForCommand( - value, alias, expectedType, completionItems.Select(ci => ci.Label)); + value, name, expectedType, completionItems.Select(ci => ci.Label)); } else { - return LocalizationResources.ArgumentConversionCannotParseForCommand(value, alias, expectedType); + return LocalizationResources.ArgumentConversionCannotParseForCommand(value, name, expectedType); } } else if (argumentResult.Parent is OptionResult optionResult) { - string alias = optionResult.Option.GetLongestAlias(removePrefix: false); + string name = optionResult.Option.Name; CompletionItem[] completionItems = optionResult.Option.GetCompletions(CompletionContext.Empty).ToArray(); if (completionItems.Length > 0) { return LocalizationResources.ArgumentConversionCannotParseForOption( - value, alias, expectedType, completionItems.Select(ci => ci.Label)); + value, name, expectedType, completionItems.Select(ci => ci.Label)); } else { - return LocalizationResources.ArgumentConversionCannotParseForOption(value, alias, expectedType); + return LocalizationResources.ArgumentConversionCannotParseForOption(value, name, expectedType); } } diff --git a/src/System.CommandLine/Command.cs b/src/System.CommandLine/Command.cs index 170bef6a70..89ad03c658 100644 --- a/src/System.CommandLine/Command.cs +++ b/src/System.CommandLine/Command.cs @@ -32,6 +32,7 @@ public class Command : IdentifierSymbol, IEnumerable /// The description of the command, shown in help. public Command(string name, string? description = null) : base(name, description) { + AddAlias(name); } /// @@ -106,8 +107,6 @@ public void Add(Symbol symbol) } } - private protected override string DefaultName => throw new NotImplementedException(); - /// /// Gets or sets a value that indicates whether unmatched tokens should be treated as errors. For example, /// if set to and an extra command or argument is provided, validation will fail. diff --git a/src/System.CommandLine/Help/HelpOption.cs b/src/System.CommandLine/Help/HelpOption.cs index c5dca1a6c6..01f7750b18 100644 --- a/src/System.CommandLine/Help/HelpOption.cs +++ b/src/System.CommandLine/Help/HelpOption.cs @@ -9,7 +9,11 @@ namespace System.CommandLine.Help internal class HelpOption : Option { internal HelpOption(string[] aliases) - : base(aliases, LocalizationResources.HelpOptionDescription(), new Argument { Arity = ArgumentArity.Zero }) + : base( + "--help", + aliases, + LocalizationResources.HelpOptionDescription(), + new Argument("--help") { Arity = ArgumentArity.Zero }) { AppliesToSelfAndChildren = true; } diff --git a/src/System.CommandLine/Help/VersionOption.cs b/src/System.CommandLine/Help/VersionOption.cs index 3621a1ae04..fd382437ed 100644 --- a/src/System.CommandLine/Help/VersionOption.cs +++ b/src/System.CommandLine/Help/VersionOption.cs @@ -11,13 +11,16 @@ namespace System.CommandLine.Help internal class VersionOption : Option { internal VersionOption() - : base("--version", LocalizationResources.VersionOptionDescription(), new Argument { Arity = ArgumentArity.Zero }) + : base( + "--version", + LocalizationResources.VersionOptionDescription(), + new Argument("--help") { Arity = ArgumentArity.Zero }) { AddValidators(); } internal VersionOption(string[] aliases) - : base(aliases, LocalizationResources.VersionOptionDescription()) + : base("--version", aliases, LocalizationResources.VersionOptionDescription()) { AddValidators(); } diff --git a/src/System.CommandLine/IdentifierSymbol.cs b/src/System.CommandLine/IdentifierSymbol.cs index d52b09d2d9..c55cfa9ff2 100644 --- a/src/System.CommandLine/IdentifierSymbol.cs +++ b/src/System.CommandLine/IdentifierSymbol.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; -using System.CommandLine.Parsing; using System.Diagnostics; namespace System.CommandLine @@ -14,24 +13,13 @@ public abstract class IdentifierSymbol : Symbol { private readonly HashSet _aliases = new(StringComparer.Ordinal); - /// - /// Initializes a new instance of the class. - /// - /// The description of the symbol, which is displayed in command line help. - protected IdentifierSymbol(string? description = null) - { - Description = description; - } - /// /// Initializes a new instance of the class. /// /// The name of the symbol. /// The description of the symbol, which is displayed in command line help. - protected IdentifierSymbol(string name, string? description = null) + private protected IdentifierSymbol(string name, string? description = null) : base(name, description, allowWhiteSpacesInName: false) { - Name = name ?? throw new ArgumentNullException(nameof(name)); - Description = description; } /// @@ -39,25 +27,6 @@ protected IdentifierSymbol(string name, string? description = null) /// public IReadOnlyCollection Aliases => _aliases; - /// - public override string Name - { - set - { - if (_name is null || !string.Equals(_name, value, StringComparison.Ordinal)) - { - AddAlias(value); - - if (_name != null) - { - RemoveAlias(_name); - } - - _name = value; - } - } - } - /// /// Adds an alias. /// @@ -81,19 +50,6 @@ public void AddAlias(string alias) /// if the alias has already been defined; otherwise . public bool HasAlias(string alias) => _aliases.Contains(alias); - internal string GetLongestAlias(bool removePrefix) - { - string max = ""; - foreach (string alias in _aliases) - { - if (alias.Length > max.Length) - { - max = alias; - } - } - return removePrefix ? max.RemovePrefix() : max; - } - [DebuggerStepThrough] private void ThrowIfAliasIsInvalid(string alias) { diff --git a/src/System.CommandLine/Option.cs b/src/System.CommandLine/Option.cs index 87292dee05..b034b6c2c7 100644 --- a/src/System.CommandLine/Option.cs +++ b/src/System.CommandLine/Option.cs @@ -17,17 +17,12 @@ public abstract class Option : IdentifierSymbol, IValueDescriptor { private List>? _validators; - private protected Option(string name, string? description) : base(description) + private protected Option(string name, string? description) : base(name, description) { - if (name is null) - { - throw new ArgumentNullException(nameof(name)); - } - - AddAlias(name); + AddAlias(name ?? throw new ArgumentNullException(nameof(name))); } - private protected Option(string[] aliases, string? description) : base(description) + private protected Option(string name, string[] aliases, string? description) : base(name, description) { if (aliases is null) { @@ -124,8 +119,6 @@ internal virtual bool IsGreedy object? IValueDescriptor.GetDefaultValue() => Argument.GetDefaultValue(); - private protected override string DefaultName => GetLongestAlias(true); - /// public override IEnumerable GetCompletions(CompletionContext context) { diff --git a/src/System.CommandLine/Option{T}.cs b/src/System.CommandLine/Option{T}.cs index fcd623484c..f49a186f28 100644 --- a/src/System.CommandLine/Option{T}.cs +++ b/src/System.CommandLine/Option{T}.cs @@ -16,14 +16,16 @@ public class Option : Option, IValueDescriptor public Option( string name, string? description = null) - : this(name, description, new Argument()) - { } + : this(name, description, new Argument(name)) + { + } /// public Option( + string name, string[] aliases, string? description = null) - : this(aliases, description, new Argument()) + : this(name, aliases, description, new Argument(name)) { } /// @@ -33,16 +35,17 @@ public Option( bool isDefault = false, string? description = null) : this(name, description, - new Argument(parseArgument ?? throw new ArgumentNullException(nameof(parseArgument)), isDefault)) + new Argument(name, parseArgument ?? throw new ArgumentNullException(nameof(parseArgument)), isDefault)) { } /// public Option( + string name, string[] aliases, Func parseArgument, bool isDefault = false, string? description = null) - : this(aliases, description, new Argument(parseArgument ?? throw new ArgumentNullException(nameof(parseArgument)), isDefault)) + : this(name, aliases, description, new Argument(name, parseArgument ?? throw new ArgumentNullException(nameof(parseArgument)), isDefault)) { } /// @@ -51,15 +54,16 @@ public Option( Func defaultValueFactory, string? description = null) : this(name, description, - new Argument(defaultValueFactory)) + new Argument(name, defaultValueFactory)) { } /// public Option( + string name, string[] aliases, Func defaultValueFactory, string? description = null) - : this(aliases, description, new Argument(defaultValueFactory)) + : this(name, aliases, description, new Argument(name, defaultValueFactory)) { } @@ -74,10 +78,11 @@ private protected Option( } private protected Option( + string name, string[] aliases, string? description, Argument argument) - : base(aliases, description) + : base(name, aliases, description) { argument.AddParent(this); _argument = argument; diff --git a/src/System.CommandLine/Parsing/CommandResult.cs b/src/System.CommandLine/Parsing/CommandResult.cs index be6895f9b2..b727a63194 100644 --- a/src/System.CommandLine/Parsing/CommandResult.cs +++ b/src/System.CommandLine/Parsing/CommandResult.cs @@ -96,7 +96,7 @@ private void ValidateOptions(bool completeValidation) { if (option.IsRequired) { - AddError(LocalizationResources.RequiredOptionWasNotProvided(option.GetLongestAlias(removePrefix: false))); + AddError(LocalizationResources.RequiredOptionWasNotProvided(option.Name)); continue; } else if (option.Argument.HasDefaultValue) diff --git a/src/System.CommandLine/Parsing/StringExtensions.cs b/src/System.CommandLine/Parsing/StringExtensions.cs index 877674bfff..9412dcc317 100644 --- a/src/System.CommandLine/Parsing/StringExtensions.cs +++ b/src/System.CommandLine/Parsing/StringExtensions.cs @@ -24,31 +24,6 @@ internal static int IndexOfCaseInsensitive( value, CompareOptions.OrdinalIgnoreCase); - internal static string RemovePrefix(this string alias) - { - int prefixLength = GetPrefixLength(alias); - return prefixLength > 0 - ? alias.Substring(prefixLength) - : alias; - } - - private static int GetPrefixLength(this string alias) - { - if (alias[0] == '-') - { - return alias.Length > 1 && alias[1] == '-' - ? 2 - : 1; - } - - if (alias[0] == '/') - { - return 1; - } - - return 0; - } - internal static (string? Prefix, string Alias) SplitPrefix(this string rawAlias) { if (rawAlias[0] == '/') diff --git a/src/System.CommandLine/Parsing/SymbolResultExtensions.cs b/src/System.CommandLine/Parsing/SymbolResultExtensions.cs index 86a573f269..dc5ccea62d 100644 --- a/src/System.CommandLine/Parsing/SymbolResultExtensions.cs +++ b/src/System.CommandLine/Parsing/SymbolResultExtensions.cs @@ -30,7 +30,7 @@ internal static Token Token(this SymbolResult symbolResult) static Token CreateImplicitToken(Option option) { - return new Token(option.GetLongestAlias(removePrefix: false), TokenType.Option, option, Parsing.Token.ImplicitPosition); + return new Token(option.Name, TokenType.Option, option, Parsing.Token.ImplicitPosition); } } } diff --git a/src/System.CommandLine/RootCommand.cs b/src/System.CommandLine/RootCommand.cs index 59443d33b5..ea72431538 100644 --- a/src/System.CommandLine/RootCommand.cs +++ b/src/System.CommandLine/RootCommand.cs @@ -21,22 +21,6 @@ public class RootCommand : Command private static string? _executableName; private static string? _executableVersion; - private static string GetExecutableVersion() - { - var assembly = GetAssembly(); - - var assemblyVersionAttribute = assembly.GetCustomAttribute(); - - if (assemblyVersionAttribute is null) - { - return assembly.GetName().Version?.ToString() ?? ""; - } - else - { - return assemblyVersionAttribute.InformationalVersion; - } - } - /// The description of the command, shown in help. public RootCommand(string description = "") : base(ExecutableName, description) { @@ -58,6 +42,22 @@ public static string ExecutableName internal static string ExecutableVersion => _executableVersion ??= GetExecutableVersion(); + private static string GetExecutableVersion() + { + var assembly = GetAssembly(); + + var assemblyVersionAttribute = assembly.GetCustomAttribute(); + + if (assemblyVersionAttribute is null) + { + return assembly.GetName().Version?.ToString() ?? ""; + } + else + { + return assemblyVersionAttribute.InformationalVersion; + } + } + private protected override void RemoveAlias(string alias) { if (!string.Equals(alias, ExecutableName, StringComparison.Ordinal)) diff --git a/src/System.CommandLine/Symbol.cs b/src/System.CommandLine/Symbol.cs index 6a93eb4527..4637682365 100644 --- a/src/System.CommandLine/Symbol.cs +++ b/src/System.CommandLine/Symbol.cs @@ -11,11 +11,28 @@ namespace System.CommandLine /// public abstract class Symbol { - private protected string? _name; private ParentNode? _firstParent; - private protected Symbol() + private protected Symbol(string name, string? description, bool allowWhiteSpacesInName) { + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentException("A name cannot be null, empty, or consist entirely of whitespace."); + } + + if (!allowWhiteSpacesInName) + { + for (var i = 0; i < name.Length; i++) + { + if (char.IsWhiteSpace(name[i])) + { + throw new ArgumentException($"Name cannot contain whitespace: \"{name}\"", nameof(name)); + } + } + } + + Name = name; + Description = description; } /// @@ -24,15 +41,9 @@ private protected Symbol() public string? Description { get; set; } /// - /// Gets or sets the name of the symbol. + /// Gets the name of the symbol. /// - public virtual string Name - { - get => _name ??= DefaultName; - set => _name = value; - } - - private protected abstract string DefaultName { get; } + public string Name { get; } /// /// Represents the first parent node. From cdaf99cfbd18910e4b22d1f30c7c6a0e70d53cdf Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 24 Feb 2023 21:55:03 +0100 Subject: [PATCH 2/5] fix tests --- src/Common/OptionBuilder.cs | 8 +- .../LocalizationTests.cs | 2 +- .../CommandLine/Perf_Parser_Simple.cs | 4 +- .../GeneratedCommandHandlerTests.cs | 12 +- .../ModelBinderTests.cs | 24 +- .../ModelBindingCommandHandlerTests.cs | 4 +- .../ParameterBindingTests.cs | 4 +- src/System.CommandLine.Tests/ArgumentTests.cs | 56 ++-- .../Binding/TypeConversionTests.cs | 10 +- src/System.CommandLine.Tests/CommandTests.cs | 35 +-- .../CompletionContextTests.cs | 6 +- .../CompletionTests.cs | 28 +- .../DirectiveTests.cs | 2 +- .../GlobalOptionTests.cs | 2 +- ...s.Help_layout_has_not_changed.approved.txt | 2 +- .../Help/HelpBuilderTests.Approval.cs | 15 +- .../Help/HelpBuilderTests.Customization.cs | 4 +- .../Help/HelpBuilderTests.cs | 244 +++++------------- .../IdentifierSymbolTests.cs | 24 -- .../Invocation/TypoCorrectionTests.cs | 4 +- .../OptionTests.MultipleArgumentsPerToken.cs | 12 +- src/System.CommandLine.Tests/OptionTests.cs | 70 ++--- .../ParseDiagramTests.cs | 20 +- .../ParseDirectiveTests.cs | 2 +- .../ParseResultTests.cs | 8 +- .../ParserTests.DoubleDash.cs | 14 +- .../ParserTests.MultipleArguments.cs | 50 ++-- .../ParserTests.MultiplePositions.cs | 10 +- .../ParserTests.RootCommandAndArg0.cs | 2 +- src/System.CommandLine.Tests/ParserTests.cs | 108 ++++---- .../ParsingValidationTests.cs | 45 ++-- .../ResponseFileTests.cs | 10 +- .../RootCommandTests.cs | 4 +- .../SuggestDirectiveTests.cs | 2 +- src/System.CommandLine.Tests/SymbolTests.cs | 23 -- .../TestApps/NativeAOT/Program.cs | 4 +- .../TestApps/Trimming/Program.cs | 2 +- .../TokenReplacementTests.cs | 15 +- src/System.CommandLine.Tests/UseHelpTests.cs | 2 +- 39 files changed, 333 insertions(+), 560 deletions(-) delete mode 100644 src/System.CommandLine.Tests/IdentifierSymbolTests.cs delete mode 100644 src/System.CommandLine.Tests/SymbolTests.cs diff --git a/src/Common/OptionBuilder.cs b/src/Common/OptionBuilder.cs index 25d33bb959..d880f2900b 100644 --- a/src/Common/OptionBuilder.cs +++ b/src/Common/OptionBuilder.cs @@ -11,7 +11,7 @@ internal static class OptionBuilder static OptionBuilder() { - _ctor = typeof(Option).GetConstructor(new[] { typeof(string), typeof(string) }); + _ctor = typeof(Option).GetConstructor(new[] { typeof(string), typeof(string[]), typeof(string) }); } public static Option CreateOption(string name, Type valueType, string description = null) @@ -21,10 +21,10 @@ public static Option CreateOption(string name, Type valueType, string descriptio #if NET6_0_OR_GREATER var ctor = (ConstructorInfo)optionType.GetMemberWithSameMetadataDefinitionAs(_ctor); #else - var ctor = optionType.GetConstructor(new[] { typeof(string), typeof(string) }); + var ctor = optionType.GetConstructor(new[] { typeof(string), typeof(string[]), typeof(string) }); #endif - var option = (Option)ctor.Invoke(new object[] { name, description }); + var option = (Option)ctor.Invoke(new object[] { name.Replace("--", ""), new[] { name }, description }); return option; } @@ -48,7 +48,7 @@ public static Option CreateOption(string name, Type valueType, string descriptio private class Bridge : Option { public Bridge(string name, Func defaultValueFactory, string description) - : base(name, + : base(name.Replace("--", ""), new[] { name }, () => (T)defaultValueFactory(), // this type exists only for an easy Func => Func transformation description) { diff --git a/src/System.CommandLine.ApiCompatibility.Tests/LocalizationTests.cs b/src/System.CommandLine.ApiCompatibility.Tests/LocalizationTests.cs index 97abc2e674..3d730759b1 100644 --- a/src/System.CommandLine.ApiCompatibility.Tests/LocalizationTests.cs +++ b/src/System.CommandLine.ApiCompatibility.Tests/LocalizationTests.cs @@ -21,7 +21,7 @@ public void ErrorMessages_AreLocalized(string cultureName, string expectedMessag Command command = new(CommandName) { - new Argument() + new Argument("arg") }; ParseResult parseResult = command.Parse(CommandName); diff --git a/src/System.CommandLine.Benchmarks/CommandLine/Perf_Parser_Simple.cs b/src/System.CommandLine.Benchmarks/CommandLine/Perf_Parser_Simple.cs index 38a51da411..3bcdf4db33 100644 --- a/src/System.CommandLine.Benchmarks/CommandLine/Perf_Parser_Simple.cs +++ b/src/System.CommandLine.Benchmarks/CommandLine/Perf_Parser_Simple.cs @@ -24,8 +24,8 @@ public class Perf_Parser_Simple private static RootCommand BuildCommand() { - Option boolOption = new(new[] { "--bool", "-b" }, "Bool option"); - Option stringOption = new(new[] { "--string", "-s" }, "String option"); + Option boolOption = new("--bool", new[] { "--bool", "-b" }, "Bool option"); + Option stringOption = new("--string", new[] { "--string", "-s" }, "String option"); RootCommand command = new() { diff --git a/src/System.CommandLine.Generator.Tests/GeneratedCommandHandlerTests.cs b/src/System.CommandLine.Generator.Tests/GeneratedCommandHandlerTests.cs index 1ba6b23c9e..a538e6a665 100644 --- a/src/System.CommandLine.Generator.Tests/GeneratedCommandHandlerTests.cs +++ b/src/System.CommandLine.Generator.Tests/GeneratedCommandHandlerTests.cs @@ -29,7 +29,7 @@ void Execute(string fullnameOrNickname, IConsole console, int age) boundAge = age; } - var nameArgument = new Argument(); + var nameArgument = new Argument("nameArg"); var ageOption = new Option("--age"); var command = new Command("command") @@ -55,7 +55,7 @@ public async Task Can_generate_handler_for_void_returning_delegate() int boundAge = default; IConsole? boundConsole = null; - var nameArgument = new Argument(); + var nameArgument = new Argument("nameArg"); var ageOption = new Option("--age"); var command = new Command("command") @@ -180,7 +180,7 @@ async Task ExecuteAsync(string fullnameOrNickname, IConsole console, int age) boundAge = age; } - var nameArgument = new Argument(); + var nameArgument = new Argument("arg"); var ageOption = new Option("--age"); var command = new Command("command") @@ -272,7 +272,7 @@ void Execute(string fullnameOrNickname, IConsole console, int age) boundAge = age; } - var nameArgument = new Argument(); + var nameArgument = new Argument("nameArg"); var ageOption = new Option("--age"); var command = new Command("command") @@ -297,7 +297,7 @@ public async Task Can_generate_handler_for_lambda() int boundAge = default; IConsole? boundConsole = null; - var nameArgument = new Argument(); + var nameArgument = new Argument("nameArg"); var ageOption = new Option("--age"); var command = new Command("command") @@ -327,7 +327,7 @@ public async Task Can_generate_handler_for_lambda_wth_return_type_specified() int boundAge = default; IConsole? boundConsole = null; - var nameArgument = new Argument(); + var nameArgument = new Argument("nameArg"); var ageOption = new Option("--age"); var command = new Command("command") diff --git a/src/System.CommandLine.NamingConventionBinder.Tests/ModelBinderTests.cs b/src/System.CommandLine.NamingConventionBinder.Tests/ModelBinderTests.cs index 02014170d4..aa16296d9d 100644 --- a/src/System.CommandLine.NamingConventionBinder.Tests/ModelBinderTests.cs +++ b/src/System.CommandLine.NamingConventionBinder.Tests/ModelBinderTests.cs @@ -306,10 +306,7 @@ public void Values_from_parent_command_arguments_are_bound_by_name_by_default() { var parentCommand = new Command("parent-command") { - new Argument - { - Name = nameof(ClassWithMultiLetterSetters.IntOption) - }, + new Argument(nameof(ClassWithMultiLetterSetters.IntOption)), new Command("child-command") }; @@ -329,10 +326,7 @@ public void Default_values_from_parent_command_arguments_are_bound_by_name_by_de { var parentCommand = new Command("parent-command") { - new Argument(() => 123) - { - Name = nameof(ClassWithMultiLetterSetters.IntOption) - }, + new Argument(nameof(ClassWithMultiLetterSetters.IntOption), () => 123), new Command("child-command") }; @@ -415,7 +409,7 @@ public void PropertyInfo_can_be_bound_to_option() public void PropertyInfo_can_be_bound_to_argument() { var command = new Command("the-command"); - var argument = new Argument { Arity = ArgumentArity.ExactlyOne }; + var argument = new Argument("arg") { Arity = ArgumentArity.ExactlyOne }; command.Arguments.Add(argument); var type = typeof(ClassWithMultiLetterSetters); @@ -455,7 +449,7 @@ public void PropertyExpression_can_be_bound_to_option() public void PropertyExpression_can_be_bound_to_argument() { var command = new Command("the-command"); - var argument = new Argument { Arity = ArgumentArity.ExactlyOne }; + var argument = new Argument("arg") { Arity = ArgumentArity.ExactlyOne }; command.Arguments.Add(argument); var binder = new ModelBinder(); @@ -488,7 +482,7 @@ public void Option_argument_is_bound_to_longest_constructor() public void Command_argument_is_bound_to_longest_constructor() { var rootCommand = new RootCommand(); - rootCommand.Arguments.Add(new Argument { Name = nameof(ClassWithMultipleCtor.IntProperty) }); + rootCommand.Arguments.Add(new Argument(nameof(ClassWithMultipleCtor.IntProperty))); var bindingContext = new InvocationContext(rootCommand.Parse("42")).BindingContext; var binder = new ModelBinder(); @@ -633,7 +627,7 @@ public void Custom_ModelBinders_specified_via_BindingContext_can_be_used_for_com var rootCommand = new RootCommand { - new Argument() + new Argument("arg") }; rootCommand.Handler = CommandHandler.Create>(x => boundInstance = x); @@ -746,10 +740,10 @@ public void Binder_does_not_match_by_substring() { var rootCommand = new RootCommand { - new Option( + new Option("--bundle", new[] { "-b", "--bundle" }, "the path to the app bundle to be installed"), - new Option( + new Option("--bundle-id", new[] { "-1", "--bundle_id", "--bundle-id" }, "specify bundle id for list and upload") }; @@ -787,7 +781,7 @@ public void InvocationContext_GetValue_with_generic_option_returns_value() [Fact] public void InvocationContext_GetValue_with_generic_argument_returns_value() { - Argument option = new(); + Argument option = new("arg"); Command command = new("the-command") { option diff --git a/src/System.CommandLine.NamingConventionBinder.Tests/ModelBindingCommandHandlerTests.cs b/src/System.CommandLine.NamingConventionBinder.Tests/ModelBindingCommandHandlerTests.cs index 14d8748525..128596b7a9 100644 --- a/src/System.CommandLine.NamingConventionBinder.Tests/ModelBindingCommandHandlerTests.cs +++ b/src/System.CommandLine.NamingConventionBinder.Tests/ModelBindingCommandHandlerTests.cs @@ -136,9 +136,7 @@ public async Task When_binding_fails_due_to_parameter_naming_mismatch_then_handl { string[] received = { "this should get overwritten" }; - var o = new Option( - new[] { "-i" }, - "Path to an image or directory of supported images"); + var o = new Option("-i", "Path to an image or directory of supported images"); var command = new Command("command") { o }; command.Handler = CommandHandler.Create((nameDoesNotMatch, c) => received = nameDoesNotMatch); diff --git a/src/System.CommandLine.NamingConventionBinder.Tests/ParameterBindingTests.cs b/src/System.CommandLine.NamingConventionBinder.Tests/ParameterBindingTests.cs index 614e0eebe8..100ba378f7 100644 --- a/src/System.CommandLine.NamingConventionBinder.Tests/ParameterBindingTests.cs +++ b/src/System.CommandLine.NamingConventionBinder.Tests/ParameterBindingTests.cs @@ -124,8 +124,8 @@ void Execute(string name, int age) var command = new Command("command") { - new Option(new[] { "-n", "--NAME" }), - new Option(new[] { "-a", "--age" }) + new Option("--NAME", new[] { "-n", "--NAME" }), + new Option("--age", new[] { "-a", "--age" }) }; command.Handler = CommandHandler.Create(Execute); diff --git a/src/System.CommandLine.Tests/ArgumentTests.cs b/src/System.CommandLine.Tests/ArgumentTests.cs index 391d9adfbf..538faaeff0 100644 --- a/src/System.CommandLine.Tests/ArgumentTests.cs +++ b/src/System.CommandLine.Tests/ArgumentTests.cs @@ -9,16 +9,15 @@ using System.Linq; using System.Threading.Tasks; using Xunit; -using System.CommandLine.Completions; namespace System.CommandLine.Tests { - public class ArgumentTests : SymbolTests + public class ArgumentTests { [Fact] public void By_default_there_is_no_default_value() { - var argument = new Argument(); + var argument = new Argument("arg"); argument.HasDefaultValue.Should().BeFalse(); } @@ -26,7 +25,7 @@ public void By_default_there_is_no_default_value() [Fact] public void When_default_value_is_set_to_null_then_HasDefaultValue_is_true() { - var argument = new Argument(); + var argument = new Argument("arg"); argument.SetDefaultValue(null); @@ -36,7 +35,7 @@ public void When_default_value_is_set_to_null_then_HasDefaultValue_is_true() [Fact] public void When_default_value_factory_is_set_then_HasDefaultValue_is_true() { - var argument = new Argument(); + var argument = new Argument("args"); argument.SetDefaultValueFactory(() => null); @@ -62,7 +61,7 @@ public class CustomParsing [Fact] public void HasDefaultValue_can_be_set_to_true() { - var argument = new Argument(result => null, true); + var argument = new Argument("arg", result => null, true); argument.HasDefaultValue .Should() @@ -72,7 +71,7 @@ public void HasDefaultValue_can_be_set_to_true() [Fact] public void HasDefaultValue_can_be_set_to_false() { - var argument = new Argument(result => null, false); + var argument = new Argument("arg", result => null, false); argument.HasDefaultValue .Should() @@ -82,7 +81,7 @@ public void HasDefaultValue_can_be_set_to_false() [Fact] public void GetDefaultValue_returns_specified_value() { - var argument = new Argument(result => "the-default", isDefault: true); + var argument = new Argument("arg", result => "the-default", isDefault: true); argument.GetDefaultValue() .Should() @@ -92,7 +91,7 @@ public void GetDefaultValue_returns_specified_value() [Fact] public void GetDefaultValue_returns_null_when_parse_delegate_returns_true_without_setting_a_value() { - var argument = new Argument(result => null, isDefault: true); + var argument = new Argument("arg", result => null, isDefault: true); argument.GetDefaultValue() .Should() @@ -102,7 +101,7 @@ public void GetDefaultValue_returns_null_when_parse_delegate_returns_true_withou [Fact] public void GetDefaultValue_returns_null_when_parse_delegate_returns_true_and_sets_value_to_null() { - var argument = new Argument(result => null, isDefault: true); + var argument = new Argument("arg", result => null, isDefault: true); argument.GetDefaultValue() .Should() @@ -112,7 +111,7 @@ public void GetDefaultValue_returns_null_when_parse_delegate_returns_true_and_se [Fact] public void GetDefaultValue_can_return_null() { - var argument = new Argument(result => null, isDefault: true); + var argument = new Argument("arg", result => null, isDefault: true); argument.GetDefaultValue() .Should() @@ -122,7 +121,7 @@ public void GetDefaultValue_can_return_null() [Fact] public void Validation_failure_message_can_be_specified_when_parsing_tokens() { - var argument = new Argument(result => + var argument = new Argument("arg", result => { result.AddError("oops!"); return null; @@ -141,7 +140,7 @@ public void Validation_failure_message_can_be_specified_when_parsing_tokens() [Fact] public void Validation_failure_message_can_be_specified_when_evaluating_default_argument_value() { - var argument = new Argument(result => + var argument = new Argument("arg", result => { result.AddError("oops!"); return null; @@ -181,7 +180,7 @@ public void Validation_failure_message_can_be_specified_when_evaluating_default_ [Fact] public void custom_parsing_of_scalar_value_from_an_argument_with_one_token() { - var argument = new Argument(result => int.Parse(result.Tokens.Single().Value)); + var argument = new Argument("arg", result => int.Parse(result.Tokens.Single().Value)); new RootCommand { argument }.Parse("123") .GetValue(argument) @@ -192,7 +191,7 @@ public void custom_parsing_of_scalar_value_from_an_argument_with_one_token() [Fact] public void custom_parsing_of_sequence_value_from_an_argument_with_one_token() { - var argument = new Argument>(result => result.Tokens.Single().Value.Split(',').Select(int.Parse)); + var argument = new Argument>("args", result => result.Tokens.Single().Value.Split(',').Select(int.Parse)); new RootCommand { argument }.Parse("1,2,3") .GetValue(argument) @@ -203,7 +202,7 @@ public void custom_parsing_of_sequence_value_from_an_argument_with_one_token() [Fact] public void custom_parsing_of_sequence_value_from_an_argument_with_multiple_tokens() { - var argument = new Argument>(result => + var argument = new Argument>("arg", result => { return result.Tokens.Select(t => int.Parse(t.Value)).ToArray(); }); @@ -217,7 +216,7 @@ public void custom_parsing_of_sequence_value_from_an_argument_with_multiple_toke [Fact] public void custom_parsing_of_scalar_value_from_an_argument_with_multiple_tokens() { - var argument = new Argument(result => result.Tokens.Select(t => int.Parse(t.Value)).Sum()) + var argument = new Argument("arg", result => result.Tokens.Select(t => int.Parse(t.Value)).Sum()) { Arity = ArgumentArity.ZeroOrMore }; @@ -328,7 +327,7 @@ public void Command_ArgumentResult_Parent_is_set_correctly_when_token_is_implici var command = new Command("the-command") { - new Argument( + new Argument("arg", parse: argResult => { argumentResult = argResult; @@ -373,7 +372,7 @@ public async Task Custom_argument_parser_is_only_called_once() [Fact] public void Default_value_and_custom_argument_parser_can_be_used_together() { - var argument = new Argument(_ => 789, true); + var argument = new Argument("arg", _ => 789, true); argument.SetDefaultValue(123); var result = new RootCommand { argument }.Parse(""); @@ -424,7 +423,7 @@ public void When_custom_conversion_fails_then_an_option_does_not_accept_further_ { var command = new Command("the-command") { - new Argument(), + new Argument("arg"), new Option("-x", argResult => { argResult.AddError("nope"); @@ -440,7 +439,7 @@ public void When_custom_conversion_fails_then_an_option_does_not_accept_further_ [Fact] public void When_argument_cannot_be_parsed_as_the_specified_type_then_getting_value_throws() { - var option = new Option(new[] { "-o", "--one" }, argumentResult => + var option = new Option("--one", new[] { "-o", "--one" }, argumentResult => { if (int.TryParse(argumentResult.Tokens.Select(t => t.Value).Single(), out var value)) { @@ -688,12 +687,12 @@ public void OnlyTake_throws_when_called_twice() [Fact] public void OnlyTake_can_pass_on_all_tokens_from_one_multiple_arity_argument_to_another() { - var argument1 = new Argument(result => + var argument1 = new Argument("arg", result => { result.OnlyTake(0); return null; }); - var argument2 = new Argument(); + var argument2 = new Argument("argument2"); var command = new RootCommand { argument1, @@ -710,12 +709,12 @@ public void OnlyTake_can_pass_on_all_tokens_from_one_multiple_arity_argument_to_ [Fact] // https://github.com/dotnet/command-line-api/issues/1759 public void OnlyTake_can_pass_on_all_tokens_from_a_single_arity_argument_to_another() { - var scalar = new Argument(parse: ctx => + var scalar = new Argument("scalar", parse: ctx => { ctx.OnlyTake(0); return null; }); - Argument multiple = new(); + Argument multiple = new("multiple"); var command = new RootCommand { @@ -779,7 +778,7 @@ public void OnlyTake_can_pass_on_all_tokens_from_a_single_arity_argument_to_anot [Fact] public void Argument_of_enum_can_limit_enum_members_as_valid_values() { - var argument = new Argument(); + var argument = new Argument("color"); argument.AcceptOnlyFromAmong(ConsoleColor.Red.ToString(), ConsoleColor.Green.ToString()); Command command = new("set-color") @@ -794,10 +793,5 @@ public void Argument_of_enum_can_limit_enum_members_as_valid_values() .Should() .BeEquivalentTo(new[] { $"Argument 'Fuschia' not recognized. Must be one of:\n\t'Red'\n\t'Green'" }); } - - protected override Symbol CreateSymbol(string name) - { - return new Argument(name); - } } } \ No newline at end of file diff --git a/src/System.CommandLine.Tests/Binding/TypeConversionTests.cs b/src/System.CommandLine.Tests/Binding/TypeConversionTests.cs index c3ce14de47..b2b23a1ccf 100644 --- a/src/System.CommandLine.Tests/Binding/TypeConversionTests.cs +++ b/src/System.CommandLine.Tests/Binding/TypeConversionTests.cs @@ -99,7 +99,7 @@ public void Argument_of_array_of_FileInfo_can_be_called_without_custom_conversio [Fact] public void Argument_defaults_arity_to_One_for_non_IEnumerable_types() { - var argument = new Argument(); + var argument = new Argument("arg"); argument.Arity.Should().BeEquivalentTo(ArgumentArity.ExactlyOne); } @@ -107,7 +107,7 @@ public void Argument_defaults_arity_to_One_for_non_IEnumerable_types() [Fact] public void Argument_defaults_arity_to_ExactlyOne_for_string() { - var argument = new Argument(); + var argument = new Argument("arg"); argument.Arity.Should().BeEquivalentTo(ArgumentArity.ExactlyOne); } @@ -117,7 +117,7 @@ public void Command_Argument_defaults_arity_to_ZeroOrOne_for_nullable_types() { var command = new Command("the-command") { - new Argument() + new Argument("arg") }; command.Arguments.Single().Arity.Should().BeEquivalentTo(ArgumentArity.ZeroOrOne); @@ -947,7 +947,7 @@ public void When_getting_an_array_of_values_and_specifying_a_conversion_type_tha [Fact] public void String_defaults_to_null_when_not_specified() { - var argument = new Argument(); + var argument = new Argument("arg"); var command = new Command("mycommand") { argument @@ -980,7 +980,7 @@ public void String_defaults_to_null_when_not_specified() [InlineData(typeof(IList))] public void Sequence_type_defaults_to_empty_when_not_specified(Type sequenceType) { - var argument = Activator.CreateInstance(typeof(Argument<>).MakeGenericType(sequenceType)); + var argument = Activator.CreateInstance(typeof(Argument<>).MakeGenericType(sequenceType), new object[] { "argName", "description" }); AssertParsedValueIsEmpty((dynamic)argument); } diff --git a/src/System.CommandLine.Tests/CommandTests.cs b/src/System.CommandLine.Tests/CommandTests.cs index 0766e5d5a6..66a25e95fd 100644 --- a/src/System.CommandLine.Tests/CommandTests.cs +++ b/src/System.CommandLine.Tests/CommandTests.cs @@ -8,7 +8,7 @@ namespace System.CommandLine.Tests { - public class CommandTests : SymbolTests + public class CommandTests { private readonly Command _outerCommand; @@ -82,7 +82,7 @@ public void Inner_command_option_is_identified_correctly() .Option .Name .Should() - .Be("option"); + .Be("--option"); } [Fact] @@ -104,12 +104,12 @@ public void Commands_at_multiple_levels_can_have_their_own_arguments() { var outer = new Command("outer") { - new Argument() + new Argument("outerArg") }; outer.Subcommands.Add( new Command("inner") { - new Argument() + new Argument("innerArgs") }); var result = outer.Parse("outer arg1 inner arg2 arg3"); @@ -144,17 +144,17 @@ public void Aliases_is_aware_of_added_alias() [InlineData("aa ")] [InlineData(" aa")] [InlineData("aa aa")] - public void When_a_command_is_created_with_an_alias_that_contains_whitespace_then_an_informative_error_is_returned( - string alias) + public void When_a_command_is_created_with_a_name_that_contains_whitespace_then_an_informative_error_is_returned( + string name) { - Action create = () => new Command(alias); + Action create = () => new Command(name); create.Should() .Throw() .Which .Message .Should() - .Contain($"Alias cannot contain whitespace: \"{alias}\""); + .Contain($"Name cannot contain whitespace: \"{name}\""); } [Theory] @@ -254,27 +254,12 @@ public void It_retains_argument_name_when_it_is_provided() { var command = new Command("-alias") { - new Argument - { - Name = "arg" - } + new Argument("arg") }; command.Arguments.Single().Name.Should().Be("arg"); } - [Fact] - public void When_Name_is_set_to_its_current_value_then_it_is_not_removed_from_aliases() - { - var command = new Command("name"); - - command.Name = "name"; - - command.HasAlias("name").Should().BeTrue(); - command.Aliases.Should().Contain("name"); - command.Aliases.Should().Contain("name"); - } - [Fact] public void AddGlobalOption_updates_Options_property() { @@ -307,7 +292,5 @@ public void When_Options_is_referenced_before_a_global_option_is_added_then_addi .Should() .Contain(option); } - - protected override Symbol CreateSymbol(string name) => new Command(name); } } diff --git a/src/System.CommandLine.Tests/CompletionContextTests.cs b/src/System.CommandLine.Tests/CompletionContextTests.cs index f2c36fb931..df2a8911a3 100644 --- a/src/System.CommandLine.Tests/CompletionContextTests.cs +++ b/src/System.CommandLine.Tests/CompletionContextTests.cs @@ -114,7 +114,7 @@ public void When_position_is_greater_than_input_length_in_a_string_command_line_ var command = new Command("the-command") { - new Argument(), + new Argument("arg"), option1, new Option("--option2") }; @@ -186,7 +186,7 @@ public void When_position_is_unspecified_in_array_command_line_and_final_token_m { option1, new Option("--option2"), - new Argument() + new Argument("arg") }; string textToMatch = command.Parse(new[] { "the-command", "--option1", "a" }) @@ -210,7 +210,7 @@ public void When_position_is_specified_in_string_command_line_then_it_returns_ar var command = new Command("the-command") { - new Argument() + new Argument("args") }; var position = commandLine.IndexOf("$", StringComparison.Ordinal); diff --git a/src/System.CommandLine.Tests/CompletionTests.cs b/src/System.CommandLine.Tests/CompletionTests.cs index dd32982ab1..08953a5f3d 100644 --- a/src/System.CommandLine.Tests/CompletionTests.cs +++ b/src/System.CommandLine.Tests/CompletionTests.cs @@ -124,7 +124,7 @@ public void Command_GetCompletions_returns_available_subcommands_and_option_alia { new Command("subcommand", "subcommand"), new Option("--option", "option"), - new Argument + new Argument("args") { Arity = ArgumentArity.OneOrMore, CompletionSources = { "command-argument" } @@ -348,7 +348,7 @@ public void When_a_subcommand_has_been_specified_then_its_sibling_options_with_a { new Command("child"), new Option("--parent-option"), - new Argument() + new Argument("arg") }; var commandLine = "--parent-option 123 child"; @@ -366,7 +366,7 @@ public void When_a_subcommand_has_been_specified_then_its_child_options_will_be_ { var command = new RootCommand("parent") { - new Argument(), + new Argument("arg"), new Command("child") { new Option("--child-option") @@ -486,7 +486,7 @@ public void Subcommand_names_are_available_as_suggestions() { new Command("one", "Command one"), new Command("two", "Command two"), - new Argument() + new Argument("arg") }; var commandLine = "test"; @@ -505,7 +505,7 @@ public void Both_subcommands_and_options_are_available_as_suggestions() { new Command("one"), new Option("--one"), - new Argument() + new Argument("arg") }; var commandLine = "test"; @@ -627,10 +627,10 @@ public void Command_argument_completions_can_be_provided_using_a_delegate() { new Command("one") { - new Argument - { - CompletionSources = { _ => new[] { "vegetable", "mineral", "animal" } } - } + new Argument("arg") + { + CompletionSources = { _ => new[] { "vegetable", "mineral", "animal" } } + } } }; @@ -796,7 +796,7 @@ public void Arguments_of_type_enum_provide_enum_values_as_suggestions() { var command = new Command("the-command") { - new Argument() + new Argument("fileMode") }; var completions = command.Parse("the-command create") @@ -870,7 +870,7 @@ public void It_can_provide_completions_within_quotes(string commandLine, int pos "\"nuget:Microsoft.DotNet.Interactive\"" }; - var argument = new Argument(); + var argument = new Argument("arg"); argument.CompletionSources.Add(expectedSuggestions); var r = new Command("#r") @@ -891,7 +891,7 @@ public void It_can_provide_completions_within_quotes(string commandLine, int pos [Fact] public void Default_completions_can_be_cleared_and_replaced() { - var argument = new Argument(); + var argument = new Argument("day"); argument.CompletionSources.Clear(); argument.CompletionSources.Add(new[] { "mon", "tues", "wed", "thur", "fri", "sat", "sun" }); var command = new Command("the-command") @@ -912,7 +912,7 @@ public void Default_completions_can_be_appended_to() { var command = new Command("the-command") { - new Argument + new Argument("day") { CompletionSources = { "mon", "tues", "wed", "thur", "fri", "sat", "sun" } } @@ -987,7 +987,7 @@ public void When_option_completions_are_available_then_they_are_suggested_when_a private static Argument CreateArgumentWithAcceptOnlyFromAmong(params string[] values) { - Argument argument = new(); + Argument argument = new("arg"); argument.AcceptOnlyFromAmong(values); return argument; } diff --git a/src/System.CommandLine.Tests/DirectiveTests.cs b/src/System.CommandLine.Tests/DirectiveTests.cs index 3b9ad10a0e..76d5437ed1 100644 --- a/src/System.CommandLine.Tests/DirectiveTests.cs +++ b/src/System.CommandLine.Tests/DirectiveTests.cs @@ -143,7 +143,7 @@ public void Directives_can_be_disabled() { RootCommand rootCommand = new () { - new Argument>() + new Argument>("args") }; var configuration = new CommandLineConfiguration( diff --git a/src/System.CommandLine.Tests/GlobalOptionTests.cs b/src/System.CommandLine.Tests/GlobalOptionTests.cs index 7de39fdd0a..ac614245d8 100644 --- a/src/System.CommandLine.Tests/GlobalOptionTests.cs +++ b/src/System.CommandLine.Tests/GlobalOptionTests.cs @@ -49,7 +49,7 @@ public void When_a_required_global_option_is_omitted_it_results_in_an_error() public void When_a_required_global_option_has_multiple_aliases_the_error_message_uses_longest() { var rootCommand = new RootCommand(); - var requiredOption = new Option(new[] { "-i", "--i-must-be-set" }) + var requiredOption = new Option("--i-must-be-set", new[] { "-i", "--i-must-be-set" }) { IsRequired = true, AppliesToSelfAndChildren = true diff --git a/src/System.CommandLine.Tests/Help/Approvals/HelpBuilderTests.Help_layout_has_not_changed.approved.txt b/src/System.CommandLine.Tests/Help/Approvals/HelpBuilderTests.Help_layout_has_not_changed.approved.txt index c4a29b9d32..26797f3950 100644 --- a/src/System.CommandLine.Tests/Help/Approvals/HelpBuilderTests.Help_layout_has_not_changed.approved.txt +++ b/src/System.CommandLine.Tests/Help/Approvals/HelpBuilderTests.Help_layout_has_not_changed.approved.txt @@ -2,7 +2,7 @@ Test description Usage: - the-root-command [ [ []]] [options] + testhost [ [ []]] [options] Arguments: diff --git a/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs b/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs index 77949afe8c..90ad3a33ba 100644 --- a/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs +++ b/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs @@ -32,39 +32,38 @@ public void Help_layout_has_not_changed() { Description = "the-root-arg-enum-default-description" }, - new Option(aliases: new string[] {"--the-root-option-no-arg", "-trna"}) { + new Option("the-root-option-no-arg", aliases: new string[] {"--the-root-option-no-arg", "-trna"}) { Description = "the-root-option-no-arg-description", IsRequired = true }, - new Option( + new Option("the-root-option-no-description-default-arg", aliases: new string[] {"--the-root-option-no-description-default-arg", "-trondda"}, parseArgument: _ => "the-root-option--no-description-default-arg-value", isDefault: true ), - new Option(aliases: new string[] {"--the-root-option-no-default-arg", "-tronda"}) { + new Option("the-root-option-no-default-arg", aliases: new string[] {"--the-root-option-no-default-arg", "-tronda"}) { Description = "the-root-option-no-default-description", ArgumentHelpName = "the-root-option-arg-no-default-arg", IsRequired = true }, - new Option(aliases: new string[] {"--the-root-option-default-arg", "-troda"}, () => "the-root-option-arg-value") + new Option("the-root-option-default-arg", aliases: new string[] {"--the-root-option-default-arg", "-troda"}, () => "the-root-option-arg-value") { Description = "the-root-option-default-arg-description", ArgumentHelpName = "the-root-option-arg", }, - new Option(aliases: new string[] {"--the-root-option-enum-arg", "-troea"}, () => FileAccess.Read) + new Option("the-root-option-enum-arg", aliases: new string[] {"--the-root-option-enum-arg", "-troea"}, () => FileAccess.Read) { Description = "the-root-option-description", }, - new Option(aliases: new string[] {"--the-root-option-required-enum-arg", "-trorea"}, () => FileAccess.Read) + new Option("the-root-option-required-enum-arg", aliases: new string[] {"--the-root-option-required-enum-arg", "-trorea"}, () => FileAccess.Read) { Description = "the-root-option-description", IsRequired = true }, - new Option(aliases: new string[] {"--the-root-option-multi-line-description", "-tromld"}) { + new Option("the-root-option-multi-line-description", aliases: new string[] {"--the-root-option-multi-line-description", "-tromld"}) { Description = "the-root-option\r\nmulti-line\ndescription" } }; - command.Name = "the-root-command"; StringWriter writer = new(); GetHelpBuilder(LargeMaxWidth).Write(command, writer); diff --git a/src/System.CommandLine.Tests/Help/HelpBuilderTests.Customization.cs b/src/System.CommandLine.Tests/Help/HelpBuilderTests.Customization.cs index 04d6e53bcd..d314419955 100644 --- a/src/System.CommandLine.Tests/Help/HelpBuilderTests.Customization.cs +++ b/src/System.CommandLine.Tests/Help/HelpBuilderTests.Customization.cs @@ -33,7 +33,7 @@ public Customization() [Fact] public void Option_can_customize_default_value() { - var option = new Option("--the-option", defaultValueFactory: () => "not 42"); + var option = new Option("the-option", new[] { "--the-option" }, defaultValueFactory: () => "not 42"); var command = new Command("the-command", "command help") { option @@ -237,7 +237,7 @@ public void Customize_throws_when_symbol_is_null() public void Option_can_fallback_to_default_when_customizing(bool conditionA, bool conditionB, string expected) { var command = new Command("test"); - var option = new Option("--option", "description"); + var option = new Option("option", new[] { "--option" }, "description"); command.Options.Add(option); diff --git a/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs b/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs index 4ee61aa4fe..57e48841d2 100644 --- a/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs +++ b/src/System.CommandLine.Tests/Help/HelpBuilderTests.cs @@ -75,12 +75,9 @@ public void Synopsis_section_properly_wraps_description() } [Fact] - public void Command_name_in_synopsis_can_be_specified() + public void Command_name_can_be_specified() { - var command = new RootCommand - { - Name = "custom-name" - }; + var command = new Command("custom-name"); var helpBuilder = GetHelpBuilder(SmallMaxWidth); helpBuilder.Write(command, _console); @@ -104,15 +101,14 @@ public void Usage_section_shows_arguments_if_there_are_arguments_for_command_whe int maxArity, string expectedArgsUsage) { - var argument = new Argument + var argument = new Argument("the-args") { - Name = "the-args", Arity = new ArgumentArity(minArity, maxArity) }; var command = new Command("the-command", "command help") { argument, - new Option(new[] + new Option("--verbosity", new[] { "-v", "--verbosity" @@ -144,16 +140,14 @@ public void Usage_section_shows_arguments_if_there_are_arguments_for_command_whe int maxArityForArg2, string expectedArgsUsage) { - var arg1 = new Argument + var arg1 = new Argument("arg1") { - Name = "arg1", Arity = new ArgumentArity( minArityForArg1, maxArityForArg1) }; - var arg2 = new Argument + var arg2 = new Argument("arg2") { - Name = "arg2", Arity = new ArgumentArity( minArityForArg2, maxArityForArg2) @@ -162,7 +156,7 @@ public void Usage_section_shows_arguments_if_there_are_arguments_for_command_whe { arg1, arg2, - new Option(new[] { "-v", "--verbosity" }, "Sets the verbosity") + new Option("--verbosity", new[] { "-v", "--verbosity" }, "Sets the verbosity") }; var rootCommand = new RootCommand(); @@ -204,18 +198,12 @@ public void Usage_section_for_subcommand_shows_arguments_for_subcommand_and_pare var inner = new Command("inner", "command help") { new Option("-v", "Sets the verbosity"), - new Argument - { - Name = "inner-args" - } + new Argument("inner-args") }; _ = new Command("outer", "command help") { inner, - new Argument - { - Name = "outer-args" - } + new Argument("outer-args") }; _helpBuilder.Write(inner, _console); @@ -274,16 +262,10 @@ public void Usage_section_keeps_added_newlines() { var outer = new Command("outer-command", "command help") { - new Argument - { - Name = $"outer args {NewLine}\r\nwith new\nlines" - }, + new Argument($"outer args {NewLine}\r\nwith new\nlines"), new Command("inner-command", "command help") { - new Argument - { - Name = "inner-args" - } + new Argument("inner-args") } }; @@ -306,16 +288,10 @@ public void Usage_section_properly_wraps_description() var outerCommand = new Command("outer-command", "command help") { - new Argument - { - Name = "outer args long enough to wrap to a new line" - }, + new Argument("outer args long enough to wrap to a new line"), new Command("inner-command", "command help") { - new Argument - { - Name = "inner-args" - } + new Argument("inner-args") } }; //NB: Using Command with a fixed name, rather than RootCommand here @@ -342,14 +318,12 @@ public void Usage_section_does_not_contain_hidden_argument() var commandName = "the-command"; var visibleArgName = "visible"; var command = new Command(commandName, "Does things"); - var hiddenArg = new Argument + var hiddenArg = new Argument("hidden") { - Name = "hidden", IsHidden = true }; - var visibleArg = new Argument + var visibleArg = new Argument(visibleArgName) { - Name = visibleArgName, IsHidden = false }; command.Arguments.Add(hiddenArg); @@ -395,11 +369,7 @@ public void Arguments_section_is_included_if_there_are_commands_with_arguments_c { var command = new Command("the-command", "command help") { - new Argument - { - Name = "arg command name", - Description = "test" - } + new Argument("arg command name", "test") }; _helpBuilder.Write(command, _console); @@ -412,7 +382,7 @@ public void Arguments_section_is_not_included_if_there_are_options_with_no_argum { var command = new RootCommand { - new Option(new[] { "-v", "--verbosity" }, "Sets the verbosity.") + new Option("--verbosity", new[] { "-v", "--verbosity" }, "Sets the verbosity.") }; _helpBuilder.Write(command, _console); @@ -441,7 +411,7 @@ public void Arguments_section_includes_configured_argument_aliases() { var command = new Command("the-command", "command help") { - new Option(new[] { "-v", "--verbosity" }) + new Option("--verbosity", new[] { "-v", "--verbosity" }) { ArgumentHelpName = "LEVEL", Description = "Sets the verbosity." @@ -468,7 +438,7 @@ public void Arguments_section_uses_name_over_suggestions_if_specified() { var command = new Command("the-command") { - new Option(new[] { "-v", "--verbosity" }) + new Option("--verbosity", new[] { "-v", "--verbosity" }) { ArgumentHelpName = "LEVEL" } @@ -485,11 +455,7 @@ public void Arguments_section_uses_description_if_provided() { var command = new Command("the-command", "Help text from description") { - new Argument - { - Name = "the-arg", - Description = "Help text from HelpDetail" - } + new Argument("the-arg", "Help text from HelpDetail") }; var expected = @@ -509,15 +475,13 @@ public void Arguments_section_does_not_contain_hidden_argument() var hiddenDesc = "the hidden desc"; var visibleArgName = "the-visible"; var visibleDesc = "the visible desc"; - var hiddenArg = new Argument + var hiddenArg = new Argument(hiddenArgName) { - Name = hiddenArgName, Description = hiddenDesc, IsHidden = true }; - var visibleArg = new Argument + var visibleArg = new Argument(visibleArgName) { - Name = visibleArgName, Description = visibleDesc, IsHidden = false }; @@ -539,9 +503,8 @@ public void Arguments_section_does_not_contain_hidden_argument() [Fact] public void Arguments_section_does_not_repeat_arguments_that_appear_on_parent_command() { - var reused = new Argument + var reused = new Argument("reused") { - Name = "reused", Description = "This argument is valid on both outer and inner commands" }; var inner = new Command("inner", "The inner command") @@ -567,18 +530,11 @@ public void Arguments_section_aligns_arguments_on_new_lines() { var inner = new Command("inner", "HelpDetail text for the inner command") { - new Argument - { - Name = "the-inner-command-arg", - Description = "The argument for the inner command", - } + new Argument("the-inner-command-arg", "The argument for the inner command") }; _ = new Command("outer", "HelpDetail text for the outer command") { - new Argument - { - Name = "outer-command-arg", Description = "The argument for the outer command" - }, + new Argument("outer-command-arg", "The argument for the outer command"), inner }; @@ -597,11 +553,7 @@ public void Arguments_section_keeps_added_newlines() { var command = new Command("outer", "Help text for the outer command") { - new Argument - { - Name = "outer-command-arg", - Description = $"The argument\r\nfor the\ninner command" - } + new Argument("outer-command-arg", $"The argument\r\nfor the\ninner command") }; _helpBuilder.Write(command, _console); @@ -620,11 +572,7 @@ public void Arguments_section_keeps_added_newlines_when_width_is_very_small() { var command = new Command("outer", "Help text for the outer command") { - new Argument - { - Name = "outer-command-arg", - Description = $"The argument\r\nfor the\ninner command", - } + new Argument("outer-command-arg", $"The argument\r\nfor the\ninner command") }; var helpBuilder = GetHelpBuilder(25); @@ -652,11 +600,7 @@ public void Arguments_section_properly_wraps_description() var command = new Command("outer", "Help text for the outer command") { - new Argument - { - Name = "outer-command-arg", - Description = longCmdText - } + new Argument("outer-command-arg", longCmdText) }; HelpBuilder helpBuilder = GetHelpBuilder(SmallMaxWidth); @@ -679,11 +623,7 @@ public void Arguments_section_properly_wraps() var command = new RootCommand { - new Argument - { - Name = name, - Description = description - } + new Argument(name, description) }; HelpBuilder helpBuilder = GetHelpBuilder(SmallMaxWidth); @@ -707,8 +647,8 @@ public void Command_argument_usage_indicates_enums_values(bool nullable) var description = "This is the argument description"; Argument argument = nullable - ? new Argument() - : new Argument(); + ? new Argument("arg") + : new Argument("arg"); argument.Description = description; var command = new Command("outer", "Help text for the outer command") @@ -799,11 +739,7 @@ public void Option_argument_first_column_indicates_enums_values(bool nullable) [Fact] public void Help_describes_default_value_for_argument() { - var argument = new Argument - { - Name = "the-arg", - Description = "Help text from HelpDetail", - }; + var argument = new Argument("the-arg", "Help text from HelpDetail"); argument.SetDefaultValue("the-arg-value"); var command = new Command("the-command", @@ -861,15 +797,9 @@ public void Help_does_not_show_default_value_for_option_when_default_value_is_em [Fact] public void Command_arguments_default_value_provided() { - var argument = new Argument - { - Name = "the-arg", - }; + var argument = new Argument("the-arg"); + var otherArgument = new Argument("the-other-arg"); - var otherArgument = new Argument - { - Name = "the-other-arg", - }; argument.SetDefaultValue("the-arg-value"); otherArgument.SetDefaultValue("the-other-arg-value"); var command = new Command("the-command", @@ -913,9 +843,8 @@ public void Command_arguments_with_default_values_that_are_enumerable_display_pi [Fact] public void Command_shared_arguments_with_one_or_more_arity_are_displayed_as_being_required() { - var arg = new Argument + var arg = new Argument("shared-args") { - Name = "shared-args", Arity = ArgumentArity.OneOrMore }; @@ -1017,9 +946,9 @@ public void Options_section_aligns_options_on_new_lines() "the-command", "Help text for the command") { - new Option(new[] { "-a", "--aaa" }, + new Option("--aaa", new[] { "-a", "--aaa" }, "An option with 8 characters"), - new Option(new[] { "-b", "--bbbbbbbbbb" }, + new Option("--bbbbbbbbbb", new[] { "-b", "--bbbbbbbbbb" }, "An option with 15 characters") }; @@ -1041,7 +970,7 @@ public void Retains_single_dash_on_multi_char_option() { var command = new Command("command", "Help Test") { - new Option( + new Option("--alt-option", new[] { "-multi", "--alt-option" }, "HelpDetail for option") }; @@ -1058,7 +987,7 @@ public void Options_section_retains_multiple_dashes_on_single_char_option() { var command = new Command("command", "Help Test") { - new Option( + new Option("--alt-option", new[] { "--m", "--alt-option" }, "HelpDetail for option") }; @@ -1076,7 +1005,7 @@ public void Options_section_keeps_added_newlines() "test-command", "Help text for the command") { - new Option( + new Option("--aaa", new[] { "-a", "--aaa" }, $"Help{NewLine}for \r\n the\noption") }; @@ -1102,7 +1031,7 @@ public void Options_section_properly_wraps_description() var command = new Command("test-command", "Help text for the command") { new Option("-x", "Option with a short description"), - new Option(new[] { "-a", "--aaa" }, longOptionText), + new Option("--aaa", new[] { "-a", "--aaa" }, longOptionText), new Option("-y", "Option with a short description"), }; @@ -1127,7 +1056,7 @@ public void Options_section_properly_wraps_description_when_long_default_value_i var command = new Command("test-command", "Help text for the command") { new Option("-x", "Option with a short description"), - new Option(new[] { "-a", "--aaa" }, description: longOptionText, defaultValueFactory: () => "the quick brown fox jumps over the lazy dog"), + new Option("aaa", new[] { "-a", "--aaa" }, description: longOptionText, defaultValueFactory: () => "the quick brown fox jumps over the lazy dog"), new Option("-y", "Option with a short description"), }; @@ -1189,7 +1118,7 @@ public void Required_options_are_indicated_when_argument_is_named() { var command = new RootCommand { - new Option(new[] {"-r", "--required" }) + new Option("--required", new[] {"-r", "--required" }) { IsRequired = true, ArgumentHelpName = "ARG" @@ -1224,7 +1153,7 @@ public void Options_aliases_differing_only_by_prefix_are_deduplicated_favoring_d { var command = new RootCommand { - new Option(new[] { "-x", "/x" }) + new Option("-x", new[] { "-x", "/x" }) }; _helpBuilder.Write(command, _console); @@ -1239,7 +1168,7 @@ public void Options_aliases_differing_only_by_prefix_are_deduplicated_favoring_d { var command = new RootCommand { - new Option(new[] { "--long", "/long" }) + new Option("--long", new[] { "--long", "/long" }) }; _helpBuilder.Write(command, _console); @@ -1254,10 +1183,10 @@ public void Options_help_preserves_the_order_options_are_added_the_the_parent_co { var command = new RootCommand { - new Option(new[] { "--first", "-f" }), - new Option(new[] { "--second", "-s" }), - new Option(new[] { "--third" }), - new Option(new[] { "--last", "-l" }) + new Option("--first", new[] { "--first", "-f" }), + new Option("--second", new[] { "--second", "-s" }), + new Option("--third", new[] { "--third" }), + new Option("--last", new[] { "--last", "-l" }) }; _helpBuilder.Write(command, _console); @@ -1278,7 +1207,7 @@ public void Option_aliases_are_shown_before_long_names_regardless_of_alphabetica { var command = new RootCommand { - new Option(new[] { "-z", "-a", "--zzz", "--aaa" }) + new Option("--zzz", new[] { "-z", "-a", "--zzz", "--aaa" }) }; _helpBuilder.Write(command, _console); @@ -1291,7 +1220,7 @@ public void Help_describes_default_value_for_option_with_argument_having_default { var command = new Command("the-command", "command help") { - new Option(new[] { "-arg"}, defaultValueFactory: () => "the-arg-value") + new Option("-arg", new[] { "-arg"}, defaultValueFactory: () => "the-arg-value") { ArgumentHelpName = "the-arg" } @@ -1312,7 +1241,8 @@ public void Option_arguments_with_default_values_that_are_enumerable_display_pip var command = new Command("the-command", "command help") { new Option>( - "--filter-size", + "filter-size", + new [] { "--filter-size" }, defaultValueFactory: () => new List { 0, 2, 4 }) { } }; @@ -1331,7 +1261,8 @@ public void Option_arguments_with_default_values_that_are_array_display_pipe_del var command = new Command("the-command", "command help") { new Option( - "--prefixes", + "prefixes", + new[] { "--prefixes" }, defaultValueFactory: () => new[]{ "^(TODO|BUG)", "^HACK" }) { } }; @@ -1381,16 +1312,10 @@ public void Subcommands_keep_added_newlines() { var command = new Command("outer", "outer command help") { - new Argument - { - Name = "outer-args" - }, + new Argument("outer-args"), new Command("inner", $"inner{NewLine}command help \r\n with \nnewlines") { - new Argument - { - Name = "inner-args" - } + new Argument("inner-args") } }; @@ -1418,17 +1343,11 @@ public void Subcommands_properly_wraps_description() var command = new Command("outer-command", "outer command help") { - new Argument - { - Name = "outer-args" - }, + new Argument("outer-args"), new Command("inner-command", longSubcommandDescription) { - new Argument - { - Name = "inner-args" - }, - new Option(new[] + new Argument("inner-args"), + new Option("verbosity", new[] { "-v", "--verbosity" @@ -1449,8 +1368,8 @@ public void Subcommands_properly_wraps_description() [Fact] public void Subcommands_section_properly_wraps() { - var name = "subcommand-name-that-is-long-enough-to-wrap-to-a-new-line"; - var description = "Subcommand description that is really long. So long that it caused the line to wrap."; + const string name = "subcommand-name-that-is-long-enough-to-wrap-to-a-new-line"; + const string description = "Subcommand description that is really long. So long that it caused the line to wrap."; var command = new RootCommand { @@ -1509,14 +1428,12 @@ public void Subcommand_help_does_not_contain_hidden_argument() { var command = new Command("the-command", "Does things."); var subCommand = new Command("the-subcommand"); - var hidden = new Argument() + var hidden = new Argument("the-hidden") { - Name = "the-hidden", IsHidden = true }; - var visible = new Argument() + var visible = new Argument("the-visible") { - Name = "the-visible", IsHidden = false }; subCommand.Arguments.Add(hidden); @@ -1537,13 +1454,9 @@ public void Subcommand_help_does_not_contain_hidden_argument() [Fact] public void Help_describes_default_value_for_subcommand_with_arguments_and_only_defaultable_is_shown() { - var argument = new Argument + var argument = new Argument("the-arg"); + var otherArgumentHidden = new Argument("the-other-hidden-arg") { - Name = "the-arg", - }; - var otherArgumentHidden = new Argument - { - Name = "the-other-hidden-arg", IsHidden = true }; argument.SetDefaultValue("the-arg-value"); @@ -1551,18 +1464,12 @@ public void Help_describes_default_value_for_subcommand_with_arguments_and_only_ var command = new Command("outer", "outer command help") { - new Argument - { - Name = "outer-args" - }, + new Argument("outer-args"), new Command("inner", $"inner command help") { argument, otherArgumentHidden, - new Argument - { - Name = "inner-other-arg-no-default" - } + new Argument("inner-other-arg-no-default") } }; @@ -1578,23 +1485,14 @@ public void Help_describes_default_value_for_subcommand_with_arguments_and_only_ [Fact] public void Help_describes_default_values_for_subcommand_with_multiple_defaultable_arguments() { - var argument = new Argument - { - Name = "the-arg", - }; - var otherArgument = new Argument - { - Name = "the-other-arg" - }; + var argument = new Argument("the-arg"); + var otherArgument = new Argument("the-other-arg"); argument.SetDefaultValue("the-arg-value"); otherArgument.SetDefaultValue("the-other-arg-value"); var command = new Command("outer", "outer command help") { - new Argument - { - Name = "outer-args" - }, + new Argument("outer-args"), new Command("inner", "inner command help") { argument, otherArgument diff --git a/src/System.CommandLine.Tests/IdentifierSymbolTests.cs b/src/System.CommandLine.Tests/IdentifierSymbolTests.cs deleted file mode 100644 index 4c9705cd55..0000000000 --- a/src/System.CommandLine.Tests/IdentifierSymbolTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - - -using FluentAssertions; -using Xunit; - -namespace System.CommandLine.Tests -{ - public abstract class IdentifierSymbolTests : SymbolTests - { - [Fact] - public void When_Name_is_changed_then_old_name_is_not_among_aliases() - { - var symbol = (IdentifierSymbol) CreateSymbol("original"); - - symbol.Name = "changed"; - - symbol.HasAlias("original").Should().BeFalse(); - symbol.Aliases.Should().NotContain("original"); - symbol.Aliases.Should().NotContain("original"); - } - } -} \ No newline at end of file diff --git a/src/System.CommandLine.Tests/Invocation/TypoCorrectionTests.cs b/src/System.CommandLine.Tests/Invocation/TypoCorrectionTests.cs index 93c55270d5..db8fd85d17 100644 --- a/src/System.CommandLine.Tests/Invocation/TypoCorrectionTests.cs +++ b/src/System.CommandLine.Tests/Invocation/TypoCorrectionTests.cs @@ -167,8 +167,8 @@ public async Task Suggestions_favor_matches_with_prefix() { var rootCommand = new RootCommand { - new Option(new[] { "/call", "-call", "--call" }), - new Option(new[] { "/email", "-email", "--email" }) + new Option("--call", new[] { "/call", "-call", "--call" }), + new Option("--email", new[] { "/email", "-email", "--email" }) }; var config = new CommandLineBuilder(rootCommand) diff --git a/src/System.CommandLine.Tests/OptionTests.MultipleArgumentsPerToken.cs b/src/System.CommandLine.Tests/OptionTests.MultipleArgumentsPerToken.cs index 84c388a735..005f60e29d 100644 --- a/src/System.CommandLine.Tests/OptionTests.MultipleArgumentsPerToken.cs +++ b/src/System.CommandLine.Tests/OptionTests.MultipleArgumentsPerToken.cs @@ -10,7 +10,7 @@ namespace System.CommandLine.Tests { - public partial class OptionTests : SymbolTests + public partial class OptionTests { public class MultipleArgumentsPerToken { @@ -26,11 +26,11 @@ public Allowed(ITestOutputHelper output) [Fact] public void When_option_is_not_respecified_but_limit_is_not_reached_then_the_following_token_is_used_as_value() { - var animalsOption = new Option(new[] { "-a", "--animals" }) + var animalsOption = new Option("--animals", new[] { "-a", "--animals" }) { AllowMultipleArgumentsPerToken = true, }; - var vegetablesOption = new Option(new[] { "-v", "--vegetables" }); + var vegetablesOption = new Option("--vegetables", new[] { "-v", "--vegetables" }); var command = new RootCommand { @@ -63,11 +63,11 @@ public void When_option_is_not_respecified_but_limit_is_not_reached_then_the_fol [Fact] public void When_option_is_not_respecified_and_limit_is_reached_then_the_following_token_is_unmatched() { - var animalsOption = new Option(new[] { "-a", "--animals" }) + var animalsOption = new Option("--animals", new[] { "-a", "--animals" }) { AllowMultipleArgumentsPerToken = true }; - var vegetablesOption = new Option(new[] { "-v", "--vegetables" }); + var vegetablesOption = new Option("--vegetables", new[] { "-v", "--vegetables" }); var command = new RootCommand { @@ -109,7 +109,7 @@ public void When_max_arity_is_1_then_subsequent_option_args_overwrite_previous_o var command = new Command("the-command") { option, - new Argument() + new Argument("arg") }; var result = command.Parse(commandLine); diff --git a/src/System.CommandLine.Tests/OptionTests.cs b/src/System.CommandLine.Tests/OptionTests.cs index 0c71239bd8..1bc9bbff2f 100644 --- a/src/System.CommandLine.Tests/OptionTests.cs +++ b/src/System.CommandLine.Tests/OptionTests.cs @@ -2,37 +2,27 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using FluentAssertions; -using System.CommandLine.Completions; -using System.CommandLine.Parsing; using System.Linq; using Xunit; namespace System.CommandLine.Tests { - public partial class OptionTests : SymbolTests + public partial class OptionTests { [Fact] - public void When_an_option_has_only_one_alias_then_that_alias_is_its_name() + public void Aliases_do_not_affect_length() { - var option = new Option(new[] { "myname" }); + var option = new Option("short", new[] { "looooooong", "m" }); - option.Name.Should().Be("myname"); + option.Name.Should().Be("short"); } [Fact] - public void When_an_option_has_several_aliases_then_the_longest_alias_is_its_name() + public void Option_names_can_contain_prefixes() { - var option = new Option(new[] { "myname", "m" }); + var option = new Option("--myname", new[] { "myname", "m" }); - option.Name.Should().Be("myname"); - } - - [Fact] - public void Option_names_do_not_contain_prefix_characters() - { - var option = new Option(new[] { "--myname", "m" }); - - option.Name.Should().Be("myname"); + option.Name.Should().Be("--myname"); } [Fact] @@ -70,7 +60,7 @@ public void A_prefixed_alias_can_be_added_to_an_option() [Fact] public void Option_aliases_are_case_sensitive() { - var option = new Option(new[] { "-o" }); + var option = new Option("-o", new[] { "-o" }); option.HasAlias("O").Should().BeFalse(); } @@ -78,7 +68,7 @@ public void Option_aliases_are_case_sensitive() [Fact] public void HasAlias_accepts_prefixed_short_value() { - var option = new Option(new[] { "-o", "--option" }); + var option = new Option("--option", new[] { "-o", "--option" }); option.HasAlias("-o").Should().BeTrue(); } @@ -86,7 +76,7 @@ public void HasAlias_accepts_prefixed_short_value() [Fact] public void HasAlias_accepts_prefixed_long_value() { - var option = new Option(new[] { "-o", "--option" }); + var option = new Option("--option", new[] { "-o", "--option" }); option.HasAlias("--option").Should().BeTrue(); } @@ -94,7 +84,7 @@ public void HasAlias_accepts_prefixed_long_value() [Fact] public void It_is_not_necessary_to_specify_a_prefix_when_adding_an_option() { - var option = new Option(new[] { "o" }); + var option = new Option("option", new[] { "o" }); option.HasAlias("o").Should().BeTrue(); } @@ -102,7 +92,7 @@ public void It_is_not_necessary_to_specify_a_prefix_when_adding_an_option() [Fact] public void An_option_must_have_at_least_one_alias() { - Action create = () => new Option(Array.Empty()); + Action create = () => new Option("name", Array.Empty()); create.Should() .Throw() @@ -115,7 +105,7 @@ public void An_option_must_have_at_least_one_alias() [Fact] public void An_option_cannot_have_an_empty_alias() { - Action create = () => new Option(new[] { "" }); + Action create = () => new Option("name", new[] { "" }); create.Should() .Throw() @@ -128,7 +118,7 @@ public void An_option_cannot_have_an_empty_alias() [Fact] public void An_option_cannot_have_an_alias_consisting_entirely_of_whitespace() { - Action create = () => new Option(new[] { " \t" }); + Action create = () => new Option("name", new[] { " \t" }); create.Should() .Throw() @@ -141,7 +131,7 @@ public void An_option_cannot_have_an_alias_consisting_entirely_of_whitespace() [Fact] public void Raw_aliases_are_exposed_by_an_option() { - var option = new Option(new[] { "-h", "--help", "/?" }); + var option = new Option("--help", new[] { "-h", "--help", "/?" }); option.Aliases .Should() @@ -152,17 +142,17 @@ public void Raw_aliases_are_exposed_by_an_option() [InlineData("-x ")] [InlineData(" -x")] [InlineData("--aa aa")] - public void When_an_option_is_created_with_an_alias_that_contains_whitespace_then_an_informative_error_is_returned( - string alias) + public void When_an_option_is_created_with_a_name_that_contains_whitespace_then_an_informative_error_is_returned( + string name) { - Action create = () => new Option(alias); + Action create = () => new Option(name); create.Should() .Throw() .Which .Message .Should() - .Contain($"Alias cannot contain whitespace: \"{alias}\""); + .Contain($"Name cannot contain whitespace: \"{name}\""); } [Theory] @@ -210,7 +200,7 @@ public void When_options_use_different_prefixes_they_still_work(string prefix) [Fact] public void When_option_not_explicitly_provides_help_will_use_default_help() { - var option = new Option(new[] { "-o", "--option" }, "desc"); + var option = new Option("option", new[] { "-o", "--option" }, "desc"); option.Name.Should().Be("option"); option.Description.Should().Be("desc"); @@ -218,11 +208,11 @@ public void When_option_not_explicitly_provides_help_will_use_default_help() } [Fact] - public void Argument_takes_option_alias_as_its_name_when_it_is_not_provided() + public void Option_name_is_used_as_explicit_alias() { var command = new Option("--alias"); - command.Name.Should().Be("alias"); + command.Name.Should().Be("--alias"); } [Fact] @@ -315,25 +305,13 @@ public void Option_of_string_defaults_to_null_when_not_specified() .BeNull(); } - [Fact] - public void When_Name_is_set_to_its_current_value_then_it_is_not_removed_from_aliases() - { - var option = new Option("--name"); - - option.Name = "name"; - - option.HasAlias("name").Should().BeTrue(); - option.HasAlias("--name").Should().BeTrue(); - option.Aliases.Should().Contain("--name"); - option.Aliases.Should().Contain("name"); - } [Theory] [InlineData("-option value")] [InlineData("-option:value")] public void When_aliases_overlap_the_longer_alias_is_chosen(string parseInput) { - var option = new Option(new[] { "-o", "-option" }); + var option = new Option("-option", new[] { "-o", "-option" }); var parseResult = new RootCommand { option }.Parse(parseInput); @@ -368,7 +346,5 @@ public void Option_of_enum_can_limit_enum_members_as_valid_values() .Should() .BeEquivalentTo(new[] { $"Argument 'Fuschia' not recognized. Must be one of:\n\t'Red'\n\t'Green'" }); } - - protected override Symbol CreateSymbol(string name) => new Option(name); } } diff --git a/src/System.CommandLine.Tests/ParseDiagramTests.cs b/src/System.CommandLine.Tests/ParseDiagramTests.cs index 3b5ee6ad97..7ca91e3774 100644 --- a/src/System.CommandLine.Tests/ParseDiagramTests.cs +++ b/src/System.CommandLine.Tests/ParseDiagramTests.cs @@ -19,7 +19,7 @@ public void Parse_result_diagram_helps_explain_parse_operation() { new Option("-x"), new Option("-y"), - new Argument() + new Argument("args") }; var result = command.Parse("the-command -x one -y two three"); @@ -67,9 +67,9 @@ public void Parse_diagram_identifies_options_where_default_values_have_been_appl { var rootCommand = new RootCommand { - new Option(new[] { "-h", "--height" }, () => 10), - new Option(new[] { "-w", "--width" }, () => 15), - new Option(new[] { "-c", "--color" }, () => ConsoleColor.Cyan) + new Option("--height", new[] { "-h", "--height" }, () => 10), + new Option("--width", new[] { "-w", "--width" }, () => 15), + new Option("--color", new[] { "-c", "--color" }, () => ConsoleColor.Cyan) }; var result = rootCommand.Parse("-w 9000"); @@ -85,9 +85,9 @@ public void Parse_diagram_indicates_which_tokens_were_applied_to_which_command_a { var command = new Command("the-command") { - new Argument { Name = "first" }, - new Argument { Name = "second" }, - new Argument { Name = "third" } + new Argument("first"), + new Argument("second"), + new Argument("third") }; var result = command.Parse("one two three four five"); @@ -102,9 +102,9 @@ public void Parse_diagram_indicates_which_tokens_were_applied_to_which_command_a { var command = new Command("the-command") { - new Argument { Name = "first" }, - new Argument { Name = "second" }, - new Argument { Name = "third" } + new Argument("first"), + new Argument("second"), + new Argument("third") }; var result = command.Parse("one two three four five"); diff --git a/src/System.CommandLine.Tests/ParseDirectiveTests.cs b/src/System.CommandLine.Tests/ParseDirectiveTests.cs index 5e467784b0..01dbf6dd2d 100644 --- a/src/System.CommandLine.Tests/ParseDirectiveTests.cs +++ b/src/System.CommandLine.Tests/ParseDirectiveTests.cs @@ -25,7 +25,7 @@ public async Task Parse_directive_writes_parse_diagram() var rootCommand = new RootCommand(); var subcommand = new Command("subcommand"); rootCommand.Subcommands.Add(subcommand); - var option = new Option(new[] { "-c", "--count" }); + var option = new Option("--count", new[] { "-c", "--count" }); subcommand.Options.Add(option); var config = new CommandLineBuilder(rootCommand) diff --git a/src/System.CommandLine.Tests/ParseResultTests.cs b/src/System.CommandLine.Tests/ParseResultTests.cs index bd74cf03ad..dc7aa4ae53 100644 --- a/src/System.CommandLine.Tests/ParseResultTests.cs +++ b/src/System.CommandLine.Tests/ParseResultTests.cs @@ -27,7 +27,7 @@ public void An_option_with_a_default_value_and_no_explicitly_provided_argument_h [Fact] public void FindResult_can_be_used_to_check_the_presence_of_an_option() { - var option = new Option(new[] { "-h", "--help" }); + var option = new Option("--help", new[] { "-h", "--help" }); var command = new Command("the-command") { @@ -42,7 +42,7 @@ public void FindResult_can_be_used_to_check_the_presence_of_an_option() [Fact] public void FindResultFor_can_be_used_to_check_the_presence_of_an_implicit_option() { - var option = new Option(new[] { "-c", "--count" }, () => 5); + var option = new Option("--count", new[] { "-c", "--count" }, () => 5); var command = new Command("the-command") { option @@ -60,14 +60,14 @@ public void Command_will_not_accept_a_command_if_a_sibling_command_has_already_b { new Command("inner-one") { - new Argument + new Argument("inner-one-arg") { Arity = ArgumentArity.Zero } }, new Command("inner-two") { - new Argument + new Argument("inner-two-arg") { Arity = ArgumentArity.Zero } diff --git a/src/System.CommandLine.Tests/ParserTests.DoubleDash.cs b/src/System.CommandLine.Tests/ParserTests.DoubleDash.cs index 4c70908eff..d479ce382e 100644 --- a/src/System.CommandLine.Tests/ParserTests.DoubleDash.cs +++ b/src/System.CommandLine.Tests/ParserTests.DoubleDash.cs @@ -15,8 +15,8 @@ public class DefaultDoubleDashBehavior [Fact] // https://github.com/dotnet/command-line-api/issues/1238 public void Subsequent_tokens_are_parsed_as_arguments_even_if_they_match_option_identifiers() { - var option = new Option(new[] { "-o", "--one" }); - var argument = new Argument(); + var option = new Option("--one", new[] { "-o", "--one" }); + var argument = new Argument("args"); var rootCommand = new RootCommand { option, @@ -40,8 +40,8 @@ public void Subsequent_tokens_are_parsed_as_arguments_even_if_they_match_option_ [Fact] public void Unmatched_tokens_is_empty() { - var option = new Option(new[] { "-o", "--one" }); - var argument = new Argument(); + var option = new Option("--one", new[] { "-o", "--one" }); + var argument = new Argument("args"); var rootCommand = new RootCommand { option, @@ -57,8 +57,8 @@ public void Unmatched_tokens_is_empty() [Fact] // https://github.com/dotnet/command-line-api/issues/1631 public void No_errors_are_generated() { - var option = new Option(new[] { "-o", "--one" }); - var argument = new Argument(); + var option = new Option("--one", new[] { "-o", "--one" }); + var argument = new Argument("args"); var rootCommand = new RootCommand { option, @@ -74,7 +74,7 @@ public void No_errors_are_generated() [Fact] public void A_second_double_dash_is_parsed_as_an_argument() { - var argument = new Argument(); + var argument = new Argument("args"); var rootCommand = new RootCommand { argument diff --git a/src/System.CommandLine.Tests/ParserTests.MultipleArguments.cs b/src/System.CommandLine.Tests/ParserTests.MultipleArguments.cs index 347d93e113..6f31c834b1 100644 --- a/src/System.CommandLine.Tests/ParserTests.MultipleArguments.cs +++ b/src/System.CommandLine.Tests/ParserTests.MultipleArguments.cs @@ -18,16 +18,14 @@ public class MultipleArguments [Fact] public void Multiple_arguments_can_differ_by_arity() { - var multipleArityArg = new Argument> + var multipleArityArg = new Argument>("several") { Arity = new ArgumentArity(3, 3), - Name = "several" }; - var singleArityArg = new Argument> + var singleArityArg = new Argument>("one") { Arity = ArgumentArity.ZeroOrMore, - Name = "one" }; var command = new Command("the-command") @@ -49,14 +47,8 @@ public void Multiple_arguments_can_differ_by_arity() [Fact] public void Multiple_arguments_can_differ_by_type() { - var stringArg = new Argument - { - Name = "the-string" - }; - var intArg = new Argument - { - Name = "the-int" - }; + var stringArg = new Argument("the-string"); + var intArg = new Argument("the-int"); var command = new Command("the-command") { @@ -85,9 +77,9 @@ public void Multiple_arguments_can_differ_by_type() [InlineData("one two three four five --verbose true")] public void When_multiple_arguments_are_present_then_their_order_relative_to_sibling_options_is_not_significant(string commandLine) { - var first = new Argument { Name = "first" }; - var second = new Argument { Name = "second" }; - var third = new Argument { Name = "third" }; + var first = new Argument ("first"); + var second = new Argument ("second"); + var third = new Argument ("third"); var verbose = new Option("--verbose"); var command = new Command("the-command") @@ -153,8 +145,8 @@ public void When_multiple_arguments_are_defined_but_not_provided_then_option_par var command = new Command("the-command") { option, - new Argument(), - new Argument() + new Argument("arg1"), + new Argument("arg2") }; var result = command.Parse("-e foo"); @@ -167,8 +159,8 @@ public void When_multiple_arguments_are_defined_but_not_provided_then_option_par [Fact] public void Tokens_that_cannot_be_converted_by_multiple_arity_argument_flow_to_next_multiple_arity_argument() { - var ints = new Argument(); - var strings = new Argument(); + var ints = new Argument("ints"); + var strings = new Argument("strings"); var root = new RootCommand { @@ -194,8 +186,8 @@ public void Tokens_that_cannot_be_converted_by_multiple_arity_argument_flow_to_n [Fact] public void Tokens_that_cannot_be_converted_by_multiple_arity_argument_flow_to_next_single_arity_argument() { - var ints = new Argument(); - var strings = new Argument(); + var ints = new Argument("ints"); + var strings = new Argument("strings"); var root = new RootCommand { @@ -227,11 +219,11 @@ public void Tokens_that_cannot_be_converted_by_multiple_arity_argument_flow_to_n [Fact] public void Unsatisfied_subsequent_argument_with_min_arity_0_parses_as_default_value() { - var arg1 = new Argument + var arg1 = new Argument("arg1") { Arity = ArgumentArity.ExactlyOne }; - var arg2 = new Argument + var arg2 = new Argument("arg2") { Arity = ArgumentArity.ZeroOrOne, }; @@ -269,11 +261,11 @@ public void Unsatisfied_subsequent_argument_with_min_arity_1_parses_as_default_v [Fact] // https://github.com/dotnet/command-line-api/issues/1395 public void When_subsequent_argument_with_ZeroOrOne_arity_is_not_provided_then_parse_is_correct() { - var argument1 = new Argument(); + var argument1 = new Argument("argument1"); var rootCommand = new RootCommand { argument1, - new Argument + new Argument("argument2") { Arity = ArgumentArity.ZeroOrOne }, @@ -296,10 +288,10 @@ public void When_there_are_not_enough_tokens_for_all_arguments_then_the_correct_ { var command = new Command("command") { - new Argument(), - new Argument(), - new Argument(), - new Argument() + new Argument("arg1"), + new Argument("arg2"), + new Argument("arg3"), + new Argument("arg4") }; var result = Parser.Parse(command, providedArgs); diff --git a/src/System.CommandLine.Tests/ParserTests.MultiplePositions.cs b/src/System.CommandLine.Tests/ParserTests.MultiplePositions.cs index a915c08b4c..85739ef226 100644 --- a/src/System.CommandLine.Tests/ParserTests.MultiplePositions.cs +++ b/src/System.CommandLine.Tests/ParserTests.MultiplePositions.cs @@ -17,10 +17,7 @@ public class MultiplePositions [InlineData("outer inner xyz")] public void An_argument_can_be_specified_in_more_than_one_position(string commandLine) { - var argument = new Argument - { - Name = "the-argument" - }; + var argument = new Argument("the-argument"); var command = new Command("outer") { @@ -48,10 +45,7 @@ public void An_argument_can_be_specified_in_more_than_one_position(string comman [InlineData("outer inner xyz")] public void When_an_argument_is_shared_between_an_outer_and_inner_command_then_specifying_in_one_does_not_result_in_error_on_other(string commandLine) { - var argument = new Argument - { - Name = "the-argument" - }; + var argument = new Argument("the-argument"); var command = new Command("outer") { diff --git a/src/System.CommandLine.Tests/ParserTests.RootCommandAndArg0.cs b/src/System.CommandLine.Tests/ParserTests.RootCommandAndArg0.cs index b46fc1d62f..1198aa68a1 100644 --- a/src/System.CommandLine.Tests/ParserTests.RootCommandAndArg0.cs +++ b/src/System.CommandLine.Tests/ParserTests.RootCommandAndArg0.cs @@ -92,7 +92,7 @@ public void When_parsing_an_unsplit_string_then_a_renamed_RootCommand_can_be_omi new Option("-x") } }; - rootCommand.Name = "outer"; + rootCommand.AddAlias("outer"); var result1 = rootCommand.Parse("inner -x hello"); var result2 = rootCommand.Parse("outer inner -x hello"); diff --git a/src/System.CommandLine.Tests/ParserTests.cs b/src/System.CommandLine.Tests/ParserTests.cs index 16644eeef1..303aca55d5 100644 --- a/src/System.CommandLine.Tests/ParserTests.cs +++ b/src/System.CommandLine.Tests/ParserTests.cs @@ -38,9 +38,9 @@ public void An_option_can_be_checked_by_object_instance() [Fact] public void Two_options_are_parsed_correctly() { - var optionOne = new Option(new[] { "-o", "--one" }); + var optionOne = new Option("--one", new[] { "-o", "--one" }); - var optionTwo = new Option(new[] { "-t", "--two" }); + var optionTwo = new Option("--two", new[] { "-t", "--two" }); var result = new RootCommand { optionOne, optionTwo }.Parse("-o -t"); @@ -113,9 +113,9 @@ public void Long_form_options_can_be_specified_using_colon_delimiter() public void Option_short_forms_can_be_bundled() { var command = new Command("the-command"); - command.Options.Add(new Option("-x")); - command.Options.Add(new Option("-y")); - command.Options.Add(new Option("-z")); + command.Options.Add(new Option("x", new [] { "-x" })); + command.Options.Add(new Option("y", new [] { "-y" })); + command.Options.Add(new Option("z", new [] { "-z" })); var result = command.Parse("the-command -xyz"); @@ -168,7 +168,7 @@ public void Option_long_forms_do_not_get_unbundled() .Children .Select(o => ((OptionResult)o).Option.Name) .Should() - .BeEquivalentTo("xyz"); + .BeEquivalentTo("--xyz"); } [Fact] @@ -178,7 +178,7 @@ public void Options_do_not_get_unbundled_unless_all_resulting_options_would_be_v outer.Options.Add(new Option("-a")); var inner = new Command("inner") { - new Argument() + new Argument("args") }; inner.Options.Add(new Option("-b")); inner.Options.Add(new Option("-c")); @@ -316,8 +316,8 @@ public void Invalid_char_in_bundle_causes_rest_to_be_interpreted_as_value() [Fact] public void Parser_root_Options_can_be_specified_multiple_times_and_their_arguments_are_collated() { - var animalsOption = new Option(new[] { "-a", "--animals" }); - var vegetablesOption = new Option(new[] { "-v", "--vegetables" }); + var animalsOption = new Option("--animals", new[] { "-a", "--animals" }); + var vegetablesOption = new Option("--vegetables", new[] { "-v", "--vegetables" }); var parser = new RootCommand { animalsOption, @@ -342,9 +342,9 @@ public void Parser_root_Options_can_be_specified_multiple_times_and_their_argume [Fact] public void Options_can_be_specified_multiple_times_and_their_arguments_are_collated() { - var animalsOption = new Option(new[] { "-a", "--animals" }); + var animalsOption = new Option("--animals", new[] { "-a", "--animals" }); animalsOption.AcceptOnlyFromAmong("dog", "cat", "sheep"); - var vegetablesOption = new Option(new[] { "-v", "--vegetables" }); + var vegetablesOption = new Option("--vegetables", new[] { "-v", "--vegetables" }); Command command = new Command("the-command") { animalsOption, @@ -369,16 +369,16 @@ public void Options_can_be_specified_multiple_times_and_their_arguments_are_coll [Fact] public void When_an_option_is_not_respecified_but_limit_is_reached_then_the_following_token_is_considered_an_argument_to_the_parent_command() { - var animalsOption = new Option(new[] { "-a", "--animals" }); + var animalsOption = new Option("--animals", new[] { "-a", "--animals" }); - var vegetablesOption = new Option(new[] { "-v", "--vegetables" }); + var vegetablesOption = new Option("--vegetables", new[] { "-v", "--vegetables" }); Command command = new Command("the-command") { animalsOption, vegetablesOption, - new Argument() + new Argument("someArg") }; var result = command.Parse("the-command -a cat some-arg -v carrot"); @@ -417,13 +417,13 @@ public void Command_with_multiple_options_is_parsed_correctly() .Children .Should() .ContainSingle(o => - ((OptionResult)o).Option.Name == "inner1" && + ((OptionResult)o).Option.Name == "--inner1" && o.Tokens.Single().Value == "argument1"); result.CommandResult .Children .Should() .ContainSingle(o => - ((OptionResult)o).Option.Name == "inner2" && + ((OptionResult)o).Option.Name == "--inner2" && o.Tokens.Single().Value == "argument2"); } @@ -432,7 +432,7 @@ public void Relative_order_of_arguments_and_options_within_a_command_does_not_ma { var command = new Command("move") { - new Argument(), + new Argument("arg"), new Option("-X") }; @@ -475,7 +475,7 @@ public void Original_order_of_tokens_is_preserved_in_ParseResult_Tokens(string c var command = new Command("the-command") { - new Argument(), + new Argument("args"), new Option("--one"), new Option("--many") }; @@ -525,10 +525,10 @@ public void When_nested_commands_all_accept_arguments_then_the_nearest_captures_ var command = new Command( "outer") { - new Argument(), + new Argument("outerArg"), new Command("inner") { - new Argument() + new Argument("innerArg") } }; @@ -552,17 +552,17 @@ public void Nested_commands_with_colliding_names_cannot_both_be_applied() { var command = new Command("outer") { - new Argument(), + new Argument("arg1"), new Command("non-unique") { - new Argument() + new Argument("notUsed") }, new Command("inner") { - new Argument(), + new Argument("arg2"), new Command("non-unique") { - new Argument() + new Argument("arg3") } } }; @@ -579,7 +579,7 @@ public void When_child_option_will_not_accept_arg_then_parent_can() var command = new Command("the-command") { option, - new Argument() + new Argument("arg") }; var result = command.Parse("the-command -x the-argument"); @@ -611,10 +611,9 @@ public void Required_arguments_on_parent_commands_do_not_create_parse_errors_whe var parent = new RootCommand { - new Argument(), + new Argument("arg"), child }; - parent.Name = "parent"; var result = parent.Parse("child"); @@ -628,13 +627,12 @@ public void Required_arguments_on_grandparent_commands_do_not_create_parse_error var grandparent = new RootCommand { - new Argument(), + new Argument("arg"), new Command("parent") { grandchild } }; - grandparent.Name = "grandparent"; var result = grandparent.Parse("parent grandchild"); @@ -666,7 +664,7 @@ public void When_options_with_the_same_name_are_defined_on_parent_and_child_comm result.CommandResult .Children .Should() - .ContainSingle(o => ((OptionResult)o).Option.Name == "x"); + .ContainSingle(o => ((OptionResult)o).Option.Name == "-x"); } [Fact] @@ -691,7 +689,7 @@ public void When_options_with_the_same_name_are_defined_on_parent_and_child_comm .Which .Children .Should() - .ContainSingle(o => o is OptionResult && ((OptionResult)o).Option.Name == "x"); + .ContainSingle(o => o is OptionResult && ((OptionResult)o).Option.Name == "-x"); } [Fact] @@ -699,10 +697,10 @@ public void Arguments_only_apply_to_the_nearest_command() { var outer = new Command("outer") { - new Argument(), + new Argument("outerArg"), new Command("inner") { - new Argument() + new Argument("innerArg") } }; @@ -753,7 +751,7 @@ public void Subsequent_occurrences_of_tokens_matching_command_names_are_parsed_a { new Command("complete") { - new Argument(), + new Argument("arg"), new Option("--position") } }; @@ -777,7 +775,7 @@ public void Absolute_unix_style_paths_are_lexed_correctly() Command command = new ("rm") { - new Argument() + new Argument("args") }; var result = command.Parse(commandText); @@ -797,7 +795,7 @@ public void Absolute_Windows_style_paths_are_lexed_correctly() Command command = new("rm") { - new Argument() + new Argument("args") }; ParseResult result = command.Parse(commandText); @@ -829,7 +827,7 @@ public void Commands_can_have_default_argument_values() public void When_an_option_with_a_default_value_is_not_matched_then_the_option_can_still_be_accessed_as_though_it_had_been_applied() { var command = new Command("command"); - var option = new Option(new[] { "-o", "--option" }, () => "the-default"); + var option = new Option("--option", new[] { "-o", "--option" }, () => "the-default"); command.Options.Add(option); ParseResult result = command.Parse("command"); @@ -841,7 +839,7 @@ public void When_an_option_with_a_default_value_is_not_matched_then_the_option_c [Fact] public void When_an_option_with_a_default_value_is_not_matched_then_the_option_result_is_implicit() { - var option = new Option(new[]{ "-o", "--option" }, () => "the-default"); + var option = new Option("--option", new[]{ "-o", "--option" }, () => "the-default"); var command = new Command("command") { @@ -898,10 +896,7 @@ public void When_an_argument_with_a_default_value_is_not_matched_then_there_are_ [Fact] public void Command_default_argument_value_does_not_override_parsed_value() { - var argument = new Argument(() => new DirectoryInfo(Directory.GetCurrentDirectory())) - { - Name = "the-arg" - }; + var argument = new Argument("the-arg", () => new DirectoryInfo(Directory.GetCurrentDirectory())); var command = new Command("inner") { @@ -923,7 +918,7 @@ public void Unmatched_tokens_that_look_like_options_are_not_split_into_smaller_t { new Command("inner") { - new Argument + new Argument("arg") { Arity = ArgumentArity.OneOrMore } @@ -944,7 +939,7 @@ public void The_default_behavior_of_unmatched_tokens_resulting_in_errors_can_be_ { var command = new Command("the-command") { - new Argument() + new Argument("arg") }; command.TreatUnmatchedTokensAsErrors = false; @@ -962,7 +957,7 @@ public void Option_and_Command_can_have_the_same_alias() { var innerCommand = new Command("inner") { - new Argument() + new Argument("innerArgs") }; var option = new Option("--inner"); @@ -971,7 +966,7 @@ public void Option_and_Command_can_have_the_same_alias() { innerCommand, option, - new Argument() + new Argument("outerArgs") }; outerCommand.Parse("outer inner") @@ -1006,8 +1001,8 @@ public void Option_and_Command_can_have_the_same_alias() [Fact] public void Options_can_have_the_same_alias_differentiated_only_by_prefix() { - var option1 = new Option(new[] { "-a" }); - var option2 = new Option(new[] { "--a" }); + var option1 = new Option("-a", new[] { "-a" }); + var option2 = new Option("--a", new[] { "--a" }); var parser = new RootCommand { @@ -1136,7 +1131,7 @@ public void Option_arguments_can_match_subcommands() [Fact] public void Arguments_can_match_subcommands() { - var argument = new Argument(); + var argument = new Argument("arg"); var subcommand = new Command("subcommand") { argument @@ -1329,7 +1324,7 @@ public void Parse_can_not_be_called_with_null_args() [Fact] public void Command_argument_arity_can_be_a_fixed_value_greater_than_1() { - var argument = new Argument + var argument = new Argument("args") { Arity = new ArgumentArity(3, 3) }; @@ -1351,7 +1346,7 @@ public void Command_argument_arity_can_be_a_fixed_value_greater_than_1() [Fact] public void Command_argument_arity_can_be_a_range_with_a_lower_bound_greater_than_1() { - var argument = new Argument + var argument = new Argument("args") { Arity = new ArgumentArity(3, 5) }; @@ -1385,7 +1380,7 @@ public void When_command_arguments_are_fewer_than_minimum_arity_then_an_error_is { var command = new Command("the-command") { - new Argument + new Argument("args") { Arity = new ArgumentArity(2, 3) } @@ -1404,7 +1399,7 @@ public void When_command_arguments_are_greater_than_maximum_arity_then_an_error_ { var command = new Command("the-command") { - new Argument + new Argument("args") { Arity = new ArgumentArity(2, 3) } @@ -1505,10 +1500,9 @@ public void When_option_arguments_are_greater_than_maximum_arity_then_an_error_i [Fact] public void Tokens_are_not_split_if_the_part_before_the_delimiter_is_not_an_option() { - var rootCommand = new RootCommand - { - Name = "jdbc" - }; + var rootCommand = new RootCommand(); + rootCommand.AddAlias("jdbc"); + rootCommand.Add(new Option("url")); var result = rootCommand.Parse("jdbc url \"jdbc:sqlserver://10.0.0.2;databaseName=main\""); diff --git a/src/System.CommandLine.Tests/ParsingValidationTests.cs b/src/System.CommandLine.Tests/ParsingValidationTests.cs index 8ab17f547c..4fabc00eef 100644 --- a/src/System.CommandLine.Tests/ParsingValidationTests.cs +++ b/src/System.CommandLine.Tests/ParsingValidationTests.cs @@ -76,7 +76,7 @@ public void When_FromAmong_is_used_then_the_OptionResult_ErrorMessage_is_set() [Fact] // https://github.com/dotnet/command-line-api/issues/1475 public void When_FromAmong_is_used_then_the_ArgumentResult_ErrorMessage_is_set() { - var argument = new Argument(); + var argument = new Argument("arg"); argument.AcceptOnlyFromAmong("a", "b"); var command = new Command("test") { argument }; @@ -180,7 +180,7 @@ public void When_FromAmong_is_used_for_multiple_arguments_and_invalid_input_is_p [Fact] public void When_FromAmong_is_used_and_multiple_invalid_inputs_are_provided_the_errors_mention_all_invalid_arguments() { - Option option = new(new[] { "--columns" }); + Option option = new("--columns"); option.AcceptOnlyFromAmong("author", "language", "tags", "type"); option.Arity = new ArgumentArity(1, 4); option.AllowMultipleArgumentsPerToken = true; @@ -248,7 +248,7 @@ public void When_a_required_option_has_multiple_aliases_the_error_message_uses_l { var command = new Command("command") { - new Option(new[] {"-x", "--xray" }) + new Option("--xray", new[] {"-x", "--xray" }) { IsRequired = true } @@ -301,7 +301,6 @@ public void Required_options_on_parent_commands_do_not_create_parse_errors_when_ new Option("-x") { IsRequired = true }, child }; - parent.Name = "parent"; var result = parent.Parse("child"); @@ -529,7 +528,7 @@ public async Task A_custom_validator_added_to_a_global_option_is_checked(string public void Custom_validator_error_messages_are_not_repeated() { var errorMessage = "that's not right..."; - var argument = new Argument(); + var argument = new Argument("arg"); argument.Validators.Add(r => r.AddError(errorMessage)); var cmd = new Command("get") @@ -549,7 +548,7 @@ public void Custom_validator_error_messages_are_not_repeated() [Fact] public void The_parsed_value_of_an_argument_is_available_within_a_validator() { - var argument = new Argument(); + var argument = new Argument("arg"); var errorMessage = "The value of option '-x' must be between 1 and 100."; argument.Validators.Add(result => { @@ -599,7 +598,7 @@ public class PathValidity [Fact] public void LegalFilePathsOnly_rejects_command_arguments_containing_invalid_path_characters() { - Argument argument = new(); + Argument argument = new("arg"); argument.AcceptLegalFilePathsOnly(); var command = new Command("the-command") { @@ -636,14 +635,14 @@ public void LegalFilePathsOnly_rejects_option_arguments_containing_invalid_path_ .Should() .HaveCount(1) .And - .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "x" && + .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "-x" && e.Message == $"Character not allowed in a path: '{invalidCharacter}'."); } [Fact] public void LegalFilePathsOnly_accepts_command_arguments_containing_valid_path_characters() { - Argument argument = new (); + Argument argument = new ("arg"); argument.AcceptLegalFilePathsOnly(); var command = new Command("the-command") { @@ -683,7 +682,7 @@ public class FileNameValidity [Fact] public void LegalFileNamesOnly_rejects_command_arguments_containing_invalid_file_name_characters() { - Argument argument = new(); + Argument argument = new("arg"); argument.AcceptLegalFileNamesOnly(); var command = new Command("the-command") @@ -722,14 +721,14 @@ public void LegalFileNamesOnly_rejects_option_arguments_containing_invalid_file_ .Should() .HaveCount(1) .And - .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "x" && + .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "-x" && e.Message == $"Character not allowed in a file name: '{invalidCharacter}'."); } [Fact] public void LegalFileNamesOnly_accepts_command_arguments_containing_valid_file_name_characters() { - Argument argument = new (); + Argument argument = new ("arg"); argument.AcceptLegalFileNamesOnly(); var command = new Command("the-command") @@ -801,7 +800,7 @@ public void An_option_argument_can_be_invalid_based_on_file_existence() .Should() .HaveCount(1) .And - .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "to" && + .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "--to" && e.Message == $"File does not exist: '{path}'."); } @@ -839,7 +838,7 @@ public void An_option_argument_can_be_invalid_based_on_directory_existence() .Should() .HaveCount(1) .And - .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "to" && + .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "--to" && e.Message == $"Directory does not exist: '{path}'."); } @@ -848,7 +847,7 @@ public void A_command_argument_can_be_invalid_based_on_file_or_directory_existen { var command = new Command("move") { - new Argument().AcceptExistingOnly() + new Argument("arg").AcceptExistingOnly() }; var path = NonexistentPath(); @@ -877,7 +876,7 @@ public void An_option_argument_can_be_invalid_based_on_file_or_directory_existen .Should() .HaveCount(1) .And - .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "to" && + .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "--to" && e.Message == $"File or directory does not exist: '{path}'."); } @@ -915,7 +914,7 @@ public void An_option_argument_with_multiple_files_can_be_invalid_based_on_file_ .Should() .HaveCount(1) .And - .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "to" && + .Contain(e => ((OptionResult)e.SymbolResult).Option.Name == "--to" && e.Message == $"File does not exist: '{path}'."); } @@ -953,7 +952,7 @@ public void An_option_argument_with_multiple_directories_can_be_invalid_based_on .Should() .HaveCount(1) .And - .ContainSingle(e => ((OptionResult)e.SymbolResult).Option.Name == "to" && + .ContainSingle(e => ((OptionResult)e.SymbolResult).Option.Name == "--to" && e.Message == $"Directory does not exist: '{path}'."); } @@ -993,7 +992,7 @@ public void An_option_argument_with_multiple_FileSystemInfos_can_be_invalid_base result.Errors .Should() - .ContainSingle(e => ((OptionResult)e.SymbolResult).Option.Name == "to" && + .ContainSingle(e => ((OptionResult)e.SymbolResult).Option.Name == "--to" && e.Message == $"File or directory does not exist: '{path}'."); } @@ -1031,7 +1030,7 @@ public void An_option_argument_with_multiple_FileSystemInfos_can_be_invalid_base .Should() .HaveCount(1) .And - .ContainSingle(e => ((OptionResult)e.SymbolResult).Option.Name == "to" && + .ContainSingle(e => ((OptionResult)e.SymbolResult).Option.Name == "--to" && e.Message == $"File or directory does not exist: '{path}'."); } @@ -1040,7 +1039,7 @@ public void Command_argument_does_not_return_errors_when_file_exists() { var command = new Command("move") { - new Argument().AcceptExistingOnly() + new Argument("arg").AcceptExistingOnly() }; var path = ExistingFile(); @@ -1068,7 +1067,7 @@ public void Command_argument_does_not_return_errors_when_Directory_exists() { var command = new Command("move") { - new Argument().AcceptExistingOnly() + new Argument("arg").AcceptExistingOnly() }; var path = ExistingDirectory(); @@ -1252,7 +1251,7 @@ public void Multiple_validators_on_the_same_option_do_not_report_duplicate_error [Fact] // https://github.com/dotnet/command-line-api/issues/1573 public void Multiple_validators_on_the_same_argument_do_not_report_duplicate_errors() { - var argument = new Argument(); + var argument = new Argument("arg"); argument.Validators.Add(result => result.AddError("Wrong")); argument.Validators.Add(_ => { }); diff --git a/src/System.CommandLine.Tests/ResponseFileTests.cs b/src/System.CommandLine.Tests/ResponseFileTests.cs index 47f079df57..cf27110a2c 100644 --- a/src/System.CommandLine.Tests/ResponseFileTests.cs +++ b/src/System.CommandLine.Tests/ResponseFileTests.cs @@ -83,7 +83,7 @@ public void When_response_file_is_specified_it_loads_command_arguments_from_resp var result = new RootCommand { - new Argument() + new Argument("args") } .Parse($"@{responseFile}"); @@ -106,7 +106,7 @@ public void Response_file_can_provide_subcommand_arguments() { new Command("subcommand") { - new Argument() + new Argument("args") } } .Parse($"subcommand @{responseFile}"); @@ -127,7 +127,7 @@ public void Response_file_can_provide_subcommand() { new Command("subcommand") { - new Argument() + new Argument("args") } } .Parse($"@{responseFile} one two three"); @@ -151,7 +151,7 @@ public void When_response_file_is_specified_it_loads_subcommand_arguments_from_r { new Command("subcommand") { - new Argument() + new Argument("args") } } .Parse($"subcommand @{responseFile}"); @@ -301,7 +301,7 @@ public void When_response_file_processing_is_disabled_then_it_returns_response_f { var command = new RootCommand { - new Argument>() + new Argument>("args") }; var configuration = new CommandLineConfiguration( command, diff --git a/src/System.CommandLine.Tests/RootCommandTests.cs b/src/System.CommandLine.Tests/RootCommandTests.cs index 0692b4b220..ee36d57e3e 100644 --- a/src/System.CommandLine.Tests/RootCommandTests.cs +++ b/src/System.CommandLine.Tests/RootCommandTests.cs @@ -17,10 +17,10 @@ public void Root_command_name_defaults_to_executable_name() } [Fact] - public void When_Name_is_set_then_executable_name_is_still_an_alias() + public void When_alias_is_added_then_executable_name_is_still_an_alias() { var rootCommand = new RootCommand(); - rootCommand.Name = "custom"; + rootCommand.AddAlias("custom"); rootCommand.Aliases.Should().BeEquivalentTo("custom", RootCommand.ExecutableName); rootCommand.Aliases.Should().BeEquivalentTo("custom", RootCommand.ExecutableName); diff --git a/src/System.CommandLine.Tests/SuggestDirectiveTests.cs b/src/System.CommandLine.Tests/SuggestDirectiveTests.cs index ad8d7d830f..68778798e5 100644 --- a/src/System.CommandLine.Tests/SuggestDirectiveTests.cs +++ b/src/System.CommandLine.Tests/SuggestDirectiveTests.cs @@ -228,7 +228,7 @@ public async Task It_writes_suggestions_for_partial_option_and_subcommand_aliase new Command("child"), new Option("--option1"), new Option("--option2"), - new Argument() + new Argument("arg") }) .UseSuggestDirective() .Build(); diff --git a/src/System.CommandLine.Tests/SymbolTests.cs b/src/System.CommandLine.Tests/SymbolTests.cs deleted file mode 100644 index 728dab5982..0000000000 --- a/src/System.CommandLine.Tests/SymbolTests.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using FluentAssertions; -using Xunit; - -namespace System.CommandLine.Tests -{ - public abstract class SymbolTests - { - [Fact] - public void When_Name_is_explicitly_set_then_adding_aliases_does_not_change_it() - { - var symbol = CreateSymbol("original"); - - symbol.Name = "changed"; - - symbol.Name.Should().Be("changed"); - } - - protected abstract Symbol CreateSymbol(string name); - } -} \ No newline at end of file diff --git a/src/System.CommandLine.Tests/TestApps/NativeAOT/Program.cs b/src/System.CommandLine.Tests/TestApps/NativeAOT/Program.cs index c7de987072..7e10fbdaa5 100644 --- a/src/System.CommandLine.Tests/TestApps/NativeAOT/Program.cs +++ b/src/System.CommandLine.Tests/TestApps/NativeAOT/Program.cs @@ -7,8 +7,8 @@ public class Program { private static int Main(string[] args) { - Option boolOption = new Option(new[] { "--bool", "-b" }, "Bool option"); - Option stringOption = new Option(new[] { "--string", "-s" }, "String option"); + Option boolOption = new Option("bool", new[] { "--bool", "-b" }, "Bool option"); + Option stringOption = new Option("string", new[] { "--string", "-s" }, "String option"); RootCommand command = new RootCommand { diff --git a/src/System.CommandLine.Tests/TestApps/Trimming/Program.cs b/src/System.CommandLine.Tests/TestApps/Trimming/Program.cs index 9fb532bf2b..f01ec4a7d4 100644 --- a/src/System.CommandLine.Tests/TestApps/Trimming/Program.cs +++ b/src/System.CommandLine.Tests/TestApps/Trimming/Program.cs @@ -1,7 +1,7 @@ using System.CommandLine; using System.CommandLine.Invocation; -var fileArgument = new Argument(); +var fileArgument = new Argument("file"); fileArgument.AcceptLegalFileNamesOnly(); var command = new RootCommand diff --git a/src/System.CommandLine.Tests/TokenReplacementTests.cs b/src/System.CommandLine.Tests/TokenReplacementTests.cs index 07dda8d03f..0f7412bfaf 100644 --- a/src/System.CommandLine.Tests/TokenReplacementTests.cs +++ b/src/System.CommandLine.Tests/TokenReplacementTests.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Generic; -using System.CommandLine.Parsing; using FluentAssertions; using Xunit; @@ -13,7 +12,7 @@ public class TokenReplacementTests [Fact] public void Token_replacer_receives_the_token_from_the_command_line_with_the_leading_at_symbol_removed() { - var argument = new Argument(); + var argument = new Argument("arg"); var command = new RootCommand { argument }; @@ -37,7 +36,7 @@ public void Token_replacer_receives_the_token_from_the_command_line_with_the_lea [Fact] public void Token_replacer_can_expand_argument_values() { - var argument = new Argument(); + var argument = new Argument("arg"); var command = new RootCommand { argument }; @@ -106,7 +105,7 @@ public void Custom_token_replacer_can_expand_subcommands_and_options_and_argumen [Fact] public void Expanded_tokens_containing_whitespace_are_parsed_as_single_tokens() { - var argument = new Argument(); + var argument = new Argument("arg"); var command = new RootCommand { argument }; @@ -127,7 +126,7 @@ public void Expanded_tokens_containing_whitespace_are_parsed_as_single_tokens() [Fact] public void Token_replacer_can_set_a_custom_error_message() { - var argument = new Argument(); + var argument = new Argument("arg"); var command = new RootCommand { argument }; @@ -150,7 +149,7 @@ public void Token_replacer_can_set_a_custom_error_message() [Fact] public void When_token_replacer_returns_false_without_setting_an_error_message_then_the_command_line_is_unchanged_and_no_parse_error_is_produced() { - var argument = new Argument(); + var argument = new Argument("arg"); var command = new RootCommand { argument }; @@ -173,7 +172,7 @@ public void When_token_replacer_returns_false_without_setting_an_error_message_t [Fact] public void Token_replacer_will_delete_token_when_delegate_returns_true_and_sets_tokens_to_null() { - var argument = new Argument(); + var argument = new Argument("args"); var command = new RootCommand { argument }; @@ -196,7 +195,7 @@ public void Token_replacer_will_delete_token_when_delegate_returns_true_and_sets [Fact] public void Token_replacer_will_delete_token_when_delegate_returns_true_and_sets_tokens_to_empty_array() { - var argument = new Argument(); + var argument = new Argument("args"); var command = new RootCommand { argument }; diff --git a/src/System.CommandLine.Tests/UseHelpTests.cs b/src/System.CommandLine.Tests/UseHelpTests.cs index f9aa48c8a2..e0201fd55b 100644 --- a/src/System.CommandLine.Tests/UseHelpTests.cs +++ b/src/System.CommandLine.Tests/UseHelpTests.cs @@ -381,7 +381,7 @@ public void Help_default_sections_can_be_wrapped() { Command command = new("test") { - new Option("--option", "option description") + new Option("option", new [] { "--option" }, "option description") }; var config = new CommandLineBuilder(command) From 0ceb0c1741a9feab54aa23010fde55d8b7abecb1 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Fri, 24 Feb 2023 22:22:20 +0100 Subject: [PATCH 3/5] remove HelpName and ArgumentHelpName, unify how help works for Argument and Option: * both always have Name specified, so first column can't contain enum values for Arguments with no name anymore * move enum values to second column, but only for symbols with no description --- ...ommandLine_api_is_not_changed.approved.txt | 2 - ...s.Help_layout_has_not_changed.approved.txt | 37 +++++--- .../Help/HelpBuilderTests.Approval.cs | 94 +++++++++---------- .../Help/HelpBuilderTests.cs | 83 +++++++++++----- src/System.CommandLine.Tests/OptionTests.cs | 7 +- src/System.CommandLine/Argument.cs | 7 +- src/System.CommandLine/ArgumentArity.cs | 2 +- .../Binding/ArgumentConverter.cs | 4 +- .../Help/HelpBuilder.Default.cs | 61 ++++-------- src/System.CommandLine/Option.cs | 12 --- 10 files changed, 153 insertions(+), 156 deletions(-) diff --git a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt b/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt index a53584fac4..c85b94069f 100644 --- a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt +++ b/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt @@ -3,7 +3,6 @@ System.CommandLine public ArgumentArity Arity { get; set; } public System.Collections.Generic.List>> CompletionSources { get; } public System.Boolean HasDefaultValue { get; } - public System.String HelpName { get; set; } public System.Collections.Generic.List> Validators { get; } public System.Type ValueType { get; } public System.Collections.Generic.IEnumerable GetCompletions(System.CommandLine.Completions.CompletionContext context) @@ -142,7 +141,6 @@ System.CommandLine public abstract class Option : IdentifierSymbol, System.CommandLine.Binding.IValueDescriptor public System.Boolean AllowMultipleArgumentsPerToken { get; set; } public System.Boolean AppliesToSelfAndChildren { get; set; } - public System.String ArgumentHelpName { get; set; } public ArgumentArity Arity { get; set; } public System.Collections.Generic.List>> CompletionSources { get; } public System.Boolean IsRequired { get; set; } diff --git a/src/System.CommandLine.Tests/Help/Approvals/HelpBuilderTests.Help_layout_has_not_changed.approved.txt b/src/System.CommandLine.Tests/Help/Approvals/HelpBuilderTests.Help_layout_has_not_changed.approved.txt index 26797f3950..a531c7b9dd 100644 --- a/src/System.CommandLine.Tests/Help/Approvals/HelpBuilderTests.Help_layout_has_not_changed.approved.txt +++ b/src/System.CommandLine.Tests/Help/Approvals/HelpBuilderTests.Help_layout_has_not_changed.approved.txt @@ -2,25 +2,32 @@ Test description Usage: - testhost [ [ []]] [options] + testhost [ [ []]] [options] Arguments: - - [default: the-root-arg-no-description-default-value] - the-root-arg-no-default-description - the-root-arg-description [default: the-root-arg-one-value] - the-root-arg-enum-default-description [default: Read] + + description1 + [default: default2] + Read|ReadWrite|Write [default: Read] + description4 [default: default4] Options: - -trna, --the-root-option-no-arg (REQUIRED) the-root-option-no-arg-description - -trondda, --the-root-option-no-description-default-arg [default: the-root-option--no-description-default-arg-value] - -tronda, --the-root-option-no-default-arg (REQUIRED) the-root-option-no-default-description - -troda, --the-root-option-default-arg the-root-option-default-arg-description [default: the-root-option-arg-value] - -troea, --the-root-option-enum-arg the-root-option-description [default: Read] - -trorea, --the-root-option-required-enum-arg (REQUIRED) the-root-option-description [default: Read] - -tromld, --the-root-option-multi-line-description the-root-option - multi-line - description + -a, --alias-a + -b, --alias-b description6 + -c, --alias-c [default: default7] + -d, --alias-d Read|ReadWrite|Write [default: Read] + -e, --alias-e description9 [default: default9] + -f, --alias-f option-and- + multi-line + description + -r, --alias-r (REQUIRED) + -s, --alias-s (REQUIRED) description6 + -t, --alias-t (REQUIRED) [default: default7] + -u, --alias-u (REQUIRED) Read|ReadWrite|Write [default: Read] + -v, --alias-v (REQUIRED) description9 [default: default9] + -w, --alias-w (REQUIRED) option-and- + multi-line + description diff --git a/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs b/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs index 90ad3a33ba..bc67424555 100644 --- a/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs +++ b/src/System.CommandLine.Tests/Help/HelpBuilderTests.Approval.cs @@ -5,6 +5,8 @@ using System.IO; using ApprovalTests; using ApprovalTests.Reporters; +using System.Collections.Generic; +using System.Linq; namespace System.CommandLine.Tests.Help { @@ -16,58 +18,56 @@ public void Help_layout_has_not_changed() { var command = new RootCommand(description: "Test description") { - new Argument("the-root-arg-no-description-no-default"), - new Argument("the-root-arg-no-description-default", - argResult => "the-root-arg-no-description-default-value", - isDefault: true), - new Argument("the-root-arg-no-default") - { - Description = "the-root-arg-no-default-description", - }, - new Argument("the-root-arg", () => "the-root-arg-one-value") - { - Description = "the-root-arg-description" - }, - new Argument("the-root-arg-enum-default", () => FileAccess.Read) - { - Description = "the-root-arg-enum-default-description" - }, - new Option("the-root-option-no-arg", aliases: new string[] {"--the-root-option-no-arg", "-trna"}) { - Description = "the-root-option-no-arg-description", - IsRequired = true - }, - new Option("the-root-option-no-description-default-arg", - aliases: new string[] {"--the-root-option-no-description-default-arg", "-trondda"}, - parseArgument: _ => "the-root-option--no-description-default-arg-value", - isDefault: true - ), - new Option("the-root-option-no-default-arg", aliases: new string[] {"--the-root-option-no-default-arg", "-tronda"}) { - Description = "the-root-option-no-default-description", - ArgumentHelpName = "the-root-option-arg-no-default-arg", - IsRequired = true - }, - new Option("the-root-option-default-arg", aliases: new string[] {"--the-root-option-default-arg", "-troda"}, () => "the-root-option-arg-value") - { - Description = "the-root-option-default-arg-description", - ArgumentHelpName = "the-root-option-arg", - }, - new Option("the-root-option-enum-arg", aliases: new string[] {"--the-root-option-enum-arg", "-troea"}, () => FileAccess.Read) - { - Description = "the-root-option-description", - }, - new Option("the-root-option-required-enum-arg", aliases: new string[] {"--the-root-option-required-enum-arg", "-trorea"}, () => FileAccess.Read) - { - Description = "the-root-option-description", - IsRequired = true - }, - new Option("the-root-option-multi-line-description", aliases: new string[] {"--the-root-option-multi-line-description", "-tromld"}) { - Description = "the-root-option\r\nmulti-line\ndescription" - } + new Argument("arg-just-name"), + new Argument("arg-name-and-description", "description1"), + new Argument("arg-name-and-default-value-string", argResult => "default2", isDefault: true), + new Argument("arg-name-and-default-value-enum", () => FileAccess.Read), + new Argument("arg-name-and-description-and-default-value", () => "default4", "description4"), }; + foreach (Option notRequired in CreateOptions(firstAlias: 'a')) + { + command.Options.Add(notRequired); + } + + foreach (Option required in CreateOptions(firstAlias: 'r')) + { + required.IsRequired = true; + + command.Options.Add(required); + } + StringWriter writer = new(); GetHelpBuilder(LargeMaxWidth).Write(command, writer); Approvals.Verify(writer.ToString()); + + static IEnumerable