diff --git a/src/dotnet/CommonOptions.cs b/src/dotnet/CommonOptions.cs new file mode 100644 index 000000000..7cabd551c --- /dev/null +++ b/src/dotnet/CommonOptions.cs @@ -0,0 +1,26 @@ +using System.IO; +using Microsoft.DotNet.Cli.CommandLine; +using Microsoft.DotNet.Tools.Common; + +namespace Microsoft.DotNet.Cli +{ + internal static class CommonOptions + { + public static Option HelpOption() => + Create.Option("-h|--help", + "Show help information", + Accept.NoArguments, + materialize: o => o.Option.Command().HelpView()); + + public static Option VerbosityOption() => + Create.Option("-v|--verbosity", + "Set the verbosity level of the command. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]", + Accept.AnyOneOf("quiet", + "minimal", + "normal", + "detailed")); + + public static ArgumentsRule DefaultToCurrentDirectory(this ArgumentsRule rule) => + rule.With(defaultValue: () => PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory())); + } +} \ No newline at end of file diff --git a/src/dotnet/CompleteCommandParser.cs b/src/dotnet/CompleteCommandParser.cs new file mode 100644 index 000000000..b4add15ea --- /dev/null +++ b/src/dotnet/CompleteCommandParser.cs @@ -0,0 +1,21 @@ +// 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 System; +using System.Linq; +using Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class CompleteCommandParser + { + public static Command Complete() => + Create.Command("complete", "", + Accept.ExactlyOneArgument + .With(name: "path"), + Create.Option("--position", "", + Accept.ExactlyOneArgument + .With(name: "command"), + o => Int32.Parse(o.Arguments.Single()))); + } +} \ No newline at end of file diff --git a/src/dotnet/DotNetTopLevelCommandBase.cs b/src/dotnet/DotNetTopLevelCommandBase.cs index 640d8dccc..89aa1a6e6 100644 --- a/src/dotnet/DotNetTopLevelCommandBase.cs +++ b/src/dotnet/DotNetTopLevelCommandBase.cs @@ -3,12 +3,9 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.Tools; -using Microsoft.DotNet.Tools.Common; namespace Microsoft.DotNet.Cli { @@ -24,61 +21,44 @@ namespace Microsoft.DotNet.Cli { DebugHelper.HandleDebugSwitch(ref args); - CommandLineApplication command = new CommandLineApplication(throwOnUnexpectedArg: true) + var result = Parser.DotnetCommand[CommandName] + .Parse(args); + + Reporter.Verbose.WriteLine(result.Diagram()); + + var command = result[CommandName]; + + if (command.HasOption("help")) { - Name = $"dotnet {CommandName}", - FullName = FullCommandNameLocalized, - }; - - command.HelpOption("-h|--help"); - - command.Argument(ArgumentName, ArgumentDescriptionLocalized); - - foreach (var subCommandCreator in SubCommands) - { - var subCommand = subCommandCreator(); - command.AddCommand(subCommand); - - subCommand.OnExecute(() => { - try - { - if (!command.Arguments.Any()) - { - throw new GracefulException(CommonLocalizableStrings.RequiredArgumentNotPassed, ArgumentDescriptionLocalized); - } - - var projectOrDirectory = command.Arguments.First().Value; - if (string.IsNullOrEmpty(projectOrDirectory)) - { - projectOrDirectory = PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory()); - } - - return subCommand.Run(projectOrDirectory); - } - catch (GracefulException e) - { - Reporter.Error.WriteLine(e.Message.Red()); - subCommand.ShowHelp(); - return 1; - } - }); + result.ShowHelp(); + return 0; } + if (result.Errors.Any()) + { + Reporter.Error.WriteLine(result.Errors.First().Message.Red()); + return 1; + } + + var subCommand = SubCommands + .Select(c => c()) + .FirstOrDefault(c => c.Name == command.AppliedOptions.First().Name); + + var fileOrDirectory = command.AppliedOptions + .First() + .Arguments + .FirstOrDefault(); + try { - return command.Execute(args); + return subCommand.Run(fileOrDirectory); } catch (GracefulException e) { Reporter.Error.WriteLine(e.Message.Red()); - command.ShowHelp(); - return 1; - } - catch (CommandParsingException e) - { - Reporter.Error.WriteLine(e.Message.Red()); + subCommand.ShowHelp(); return 1; } } } -} +} \ No newline at end of file diff --git a/src/dotnet/ParseResultExtensions.cs b/src/dotnet/ParseResultExtensions.cs new file mode 100644 index 000000000..1eeac1662 --- /dev/null +++ b/src/dotnet/ParseResultExtensions.cs @@ -0,0 +1,14 @@ +// 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 System; +using Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + public static class ParseResultExtensions + { + public static void ShowHelp(this ParseResult parseResult) => + Console.WriteLine(parseResult.Command().HelpView()); + } +} \ No newline at end of file diff --git a/src/dotnet/Parser.cs b/src/dotnet/Parser.cs new file mode 100644 index 000000000..c57e9d87b --- /dev/null +++ b/src/dotnet/Parser.cs @@ -0,0 +1,37 @@ +// 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 System; +using System.Linq; +using Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + public static class Parser + { + public static Command DotnetCommand { get; } = + Create.Command("dotnet", + ".NET Command Line Tools", + Accept.NoArguments, + NewCommandParser.New(), + RestoreCommandParser.Restore(), + BuildCommandParser.Build(), + PublishCommandParser.Publish(), + RunCommandParser.Run(), + TestCommandParser.Test(), + PackCommandParser.Pack(), + MigrateCommandParser.Migrate(), + CleanCommandParser.Clean(), + SlnCommandParser.Sln(), + AddCommandParser.Add(), + RemoveCommandParser.Remove(), + ListCommandParser.List(), + NuGetCommandParser.NuGet(), + Create.Command("msbuild", ""), + Create.Command("vstest", ""), CompleteCommandParser.Complete(), + CommonOptions.HelpOption(), + Create.Option("--info", ""), + CommonOptions.VerbosityOption(), + Create.Option("-d", "")); + } +} \ No newline at end of file diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs index 38e570881..d463dea58 100644 --- a/src/dotnet/Program.cs +++ b/src/dotnet/Program.cs @@ -6,13 +6,11 @@ using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Configurer; using Microsoft.DotNet.PlatformAbstractions; using Microsoft.DotNet.Tools.Add; using Microsoft.DotNet.Tools.Build; using Microsoft.DotNet.Tools.Clean; -using Microsoft.DotNet.Tools.Complete; using Microsoft.DotNet.Tools.Help; using Microsoft.DotNet.Tools.List; using Microsoft.DotNet.Tools.Migrate; @@ -23,7 +21,6 @@ using Microsoft.DotNet.Tools.Pack; using Microsoft.DotNet.Tools.Publish; using Microsoft.DotNet.Tools.Remove; using Microsoft.DotNet.Tools.Restore; -using Microsoft.DotNet.Tools.RestoreProjectJson; using Microsoft.DotNet.Tools.Run; using Microsoft.DotNet.Tools.Sln; using Microsoft.DotNet.Tools.Test; diff --git a/src/dotnet/commands/dotnet-add/AddCommandParser.cs b/src/dotnet/commands/dotnet-add/AddCommandParser.cs new file mode 100644 index 000000000..6e4a1881f --- /dev/null +++ b/src/dotnet/commands/dotnet-add/AddCommandParser.cs @@ -0,0 +1,74 @@ +// 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 System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using Microsoft.DotNet.Cli.CommandLine; +using Newtonsoft.Json.Linq; + +namespace Microsoft.DotNet.Cli +{ + internal static class AddCommandParser + { + public static Command Add() => + Create.Command("add", + ".NET Add Command", + Accept.ExactlyOneArgument.DefaultToCurrentDirectory(), + Create.Command("package", + ".NET Add Package reference Command", + Accept.ExactlyOneArgument + .WithSuggestionsFrom(QueryNuGet), CommonOptions.HelpOption(), + Create.Option("-v|--version", + "Version for the package to be added.", + Accept.ExactlyOneArgument + .With(name: "VERSION")), + Create.Option("-f|--framework", + "Add reference only when targetting a specific framework", + Accept.ExactlyOneArgument + .With(name: "FRAMEWORK")), + Create.Option("-n|--no-restore ", + "Add reference without performing restore preview and compatibility check."), + Create.Option("-s|--source", + "Use specific NuGet package sources to use during the restore."), + Create.Option("--package-directory", + "Restore the packages to this Directory .", + Accept.ExactlyOneArgument + .With(name: "PACKAGE_DIRECTORY"))), + Create.Command("reference", + "Command to add project to project reference", + Accept.OneOrMoreArguments, CommonOptions.HelpOption(), + Create.Option("-f|--framework", + "Add reference only when targetting a specific framework", + Accept.AnyOneOf(Suggest.TargetFrameworksFromProjectFile) + .With(name: "FRAMEWORK"))), CommonOptions.HelpOption()); + + public static IEnumerable QueryNuGet(string match) + { + var httpClient = new HttpClient(); + + string result; + + try + { + var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(10)); + var response = httpClient.GetAsync($"https://api-v2v3search-0.nuget.org/query?q={match}&skip=0&take=100&prerelease=true", cancellation.Token) + .Result; + + result = response.Content.ReadAsStringAsync().Result; + } + catch (Exception) + { + yield break; + } + + var json = JObject.Parse(result); + + foreach (var id in json["data"]) + { + yield return id["id"].Value(); + } + } + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-build/BuildCommandParser.cs b/src/dotnet/commands/dotnet-build/BuildCommandParser.cs new file mode 100644 index 000000000..f93feb438 --- /dev/null +++ b/src/dotnet/commands/dotnet-build/BuildCommandParser.cs @@ -0,0 +1,39 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class BuildCommandParser + { + public static Command Build() => + Create.Command("build", + ".NET Builder", + CommonOptions.HelpOption(), + Create.Option("-o|--output", + "Output directory in which to place built artifacts.", + Accept.ExactlyOneArgument + .With(name: "OUTPUT_DIR")), + Create.Option("-f|--framework", + "Target framework to build for. The target framework has to be specified in the project file.", + Accept.AnyOneOf(Suggest.TargetFrameworksFromProjectFile)), + Create.Option("-r|--runtime", + "Target runtime to build for. The default is to build a portable application.", + Accept.AnyOneOf(Suggest.RunTimesFromProjectFile)), + Create.Option("-c|--configuration", + "Configuration to use for building the project. Default for most projects is \"Debug\".", + Accept.ExactlyOneArgument + .With(name: "CONFIGURATION") + .WithSuggestionsFrom("DEBUG", "RELEASE")), + Create.Option("--version-suffix", + "Defines the value for the $(VersionSuffix) property in the project", + Accept.ExactlyOneArgument + .With(name: "VERSION_SUFFIX")), + Create.Option("--no-incremental", + "Disables incremental build."), + Create.Option("--no-dependencies", + "Set this flag to ignore project-to-project references and only build the root project"), + CommonOptions.VerbosityOption()); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-clean/CleanCommandParser.cs b/src/dotnet/commands/dotnet-clean/CleanCommandParser.cs new file mode 100644 index 000000000..dfdc5d1ac --- /dev/null +++ b/src/dotnet/commands/dotnet-clean/CleanCommandParser.cs @@ -0,0 +1,27 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class CleanCommandParser + { + public static Command Clean() => + Create.Command("clean", + ".NET Clean Command", + CommonOptions.HelpOption(), + Create.Option("-o|--output", "Directory in which the build outputs have been placed.", + Accept.ExactlyOneArgument + .With(name: "OUTPUT_DIR")), + Create.Option("-f|--framework", "Clean a specific framework.", + Accept.ExactlyOneArgument + .With(name: "FRAMEWORK") + .WithSuggestionsFrom(_ => Suggest.TargetFrameworksFromProjectFile())), + Create.Option("-c|--configuration", + "Clean a specific configuration.", + Accept.ExactlyOneArgument + .With(name: "CONFIGURATION") + .WithSuggestionsFrom("DEBUG", "RELEASE"))); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-complete/CompleteCommand.cs b/src/dotnet/commands/dotnet-complete/CompleteCommand.cs index 0518df868..f8b08125e 100644 --- a/src/dotnet/commands/dotnet-complete/CompleteCommand.cs +++ b/src/dotnet/commands/dotnet-complete/CompleteCommand.cs @@ -8,7 +8,7 @@ using System.Text; using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli.Utils; -namespace Microsoft.DotNet.Tools.Complete +namespace Microsoft.DotNet.Cli { public class CompleteCommand { @@ -16,24 +16,22 @@ namespace Microsoft.DotNet.Tools.Complete { DebugHelper.HandleDebugSwitch(ref args); - var log = new StringBuilder(); - log.AppendLine($"args: {string.Join(" ", args.Select(a => $"\"{a}\""))}"); - // get the parser for the current subcommand - var completeCommandParser = ParserFor.DotnetCommand["complete"]; + var completeCommandParser = Parser.DotnetCommand["complete"]; // parse the arguments var result = completeCommandParser.Parse(args); - log.AppendLine("diagram (1): " + result.Diagram()); - var complete = result["complete"]; - var suggestions = Suggestions(complete, log); - - log.AppendLine($"suggestions: {Environment.NewLine}{string.Join(Environment.NewLine, suggestions)}"); + var suggestions = Suggestions(complete); +#if DEBUG + var log = new StringBuilder(); + log.AppendLine($"args: {string.Join(" ", args.Select(a => $"\"{a}\""))}"); + log.AppendLine("diagram: " + result.Diagram()); File.WriteAllText("parse.log", log.ToString()); +#endif foreach (var suggestion in suggestions) { @@ -43,7 +41,7 @@ namespace Microsoft.DotNet.Tools.Complete return 0; } - private static string[] Suggestions(AppliedOption complete, StringBuilder log) + private static string[] Suggestions(AppliedOption complete) { var input = complete.Arguments.SingleOrDefault() ?? ""; @@ -58,9 +56,7 @@ namespace Microsoft.DotNet.Tools.Complete } } - var result = ParserFor.DotnetCommand.Parse(input); - - log.AppendLine("diagram (2): " + result.Diagram()); + var result = Parser.DotnetCommand.Parse(input); return result.Suggestions() .ToArray(); diff --git a/src/dotnet/commands/dotnet-list/ListCommandParser.cs b/src/dotnet/commands/dotnet-list/ListCommandParser.cs new file mode 100644 index 000000000..ddfde2b6f --- /dev/null +++ b/src/dotnet/commands/dotnet-list/ListCommandParser.cs @@ -0,0 +1,26 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class ListCommandParser + { + public static Command List() => + Create.Command("list", + ".NET List Command", + Accept.ZeroOrOneArgument + .With(name: "PROJECT", + description: + "The project file to operate on. If a file is not specified, the command will search the current directory for one.") + .DefaultToCurrentDirectory(), + CommonOptions.HelpOption(), + Create.Command("reference", "Command to list project to project references", + Accept.ExactlyOneArgument + .With(name: "PROJECT", + description: + "The project file to operate on. If a file is not specified, the command will search the current directory for one."), + CommonOptions.HelpOption())); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-migrate/MigrateCommandParser.cs b/src/dotnet/commands/dotnet-migrate/MigrateCommandParser.cs new file mode 100644 index 000000000..2f30281af --- /dev/null +++ b/src/dotnet/commands/dotnet-migrate/MigrateCommandParser.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class MigrateCommandParser + { + public static Command Migrate() => + Create.Command("migrate", + ".NET Migrate Command", + CommonOptions.HelpOption(), + Create.Option("-t|--template-file", + "Base MSBuild template to use for migrated app. The default is the project included in dotnet new."), + Create.Option("-v|--sdk-package-version", + "The version of the SDK package that will be referenced in the migrated app. The default is the version of the SDK in dotnet new."), + Create.Option("-x|--xproj-file", + "The path to the xproj file to use. Required when there is more than one xproj in a project directory."), + Create.Option("-s|--skip-project-references", + "Skip migrating project references. By default, project references are migrated recursively."), + Create.Option("-r|--report-file", + "Output migration report to the given file in addition to the console."), + Create.Option("--format-report-file-json", + "Output migration report file as json rather than user messages."), + Create.Option("--skip-backup", + "Skip moving project.json, global.json, and *.xproj to a `backup` directory after successful migration.")); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-new/NewCommandParser.cs b/src/dotnet/commands/dotnet-new/NewCommandParser.cs new file mode 100644 index 000000000..36f49c8b9 --- /dev/null +++ b/src/dotnet/commands/dotnet-new/NewCommandParser.cs @@ -0,0 +1,39 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class NewCommandParser + { + public static Command New() => + Create.Command("new", + "Initialize .NET projects.", + Accept + .ExactlyOneArgument + .WithSuggestionsFrom( + "console", + "classlib", + "mstest", + "xunit", + "web", + "mvc", + "webapi", + "sln"), + Create.Option("-l|--list", + "List templates containing the specified name."), + Create.Option("-lang|--language", + "Specifies the language of the template to create", + Accept.WithSuggestionsFrom("C#", "F#") + .With(defaultValue: () => "C#")), + Create.Option("-n|--name", + "The name for the output being created. If no name is specified, the name of the current directory is used."), + Create.Option("-o|--output", + "Location to place the generated output."), + Create.Option("-h|--help", + "Displays help for this command."), + Create.Option("-all|--show-all", + "Shows all templates")); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-nuget/NuGetCommandParser.cs b/src/dotnet/commands/dotnet-nuget/NuGetCommandParser.cs new file mode 100644 index 000000000..2358c685e --- /dev/null +++ b/src/dotnet/commands/dotnet-nuget/NuGetCommandParser.cs @@ -0,0 +1,78 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class NuGetCommandParser + { + public static Command NuGet() => + Create.Command("nuget", + "NuGet Command Line 4.0.0.0", + CommonOptions.HelpOption(), + Create.Option("--version", + "Show version information"), + Create.Option("-v|--verbosity", + "The verbosity of logging to use. Allowed values: Debug, Verbose, Information, Minimal, Warning, Error.", + Accept.ExactlyOneArgument + .With(name: "verbosity")), + Create.Command("delete", + "Deletes a package from the server.", + Accept.ExactlyOneArgument + .With(name: "root", + description: "The Package Id and version."), + CommonOptions.HelpOption(), + Create.Option("--force-english-output", + "Forces the application to run using an invariant, English-based culture."), + Create.Option("-s|--source", + "Specifies the server URL", + Accept.ExactlyOneArgument + .With(name: "source")), + Create.Option("--non-interactive", + "Do not prompt for user input or confirmations."), + Create.Option("-k|--api-key", + "The API key for the server.", + Accept.ExactlyOneArgument + .With(name: "apiKey"))), + Create.Command("locals", + "Clears or lists local NuGet resources such as http requests cache, packages cache or machine-wide global packages folder.", + Accept.AnyOneOf(@"all", + @"http-cache", + @"global-packages", + @"temp") + .With(description: "Cache Location(s) Specifies the cache location(s) to list or clear."), + CommonOptions.HelpOption(), + Create.Option("--force-english-output", + "Forces the application to run using an invariant, English-based culture."), + Create.Option("-c|--clear", "Clear the selected local resources or cache location(s)."), + Create.Option("-l|--list", "List the selected local resources or cache location(s).")), + Create.Command("push", + "Pushes a package to the server and publishes it.", + CommonOptions.HelpOption(), + Create.Option("--force-english-output", + "Forces the application to run using an invariant, English-based culture."), + Create.Option("-s|--source", + "Specifies the server URL", + Accept.ExactlyOneArgument + .With(name: "source")), + Create.Option("-ss|--symbol-source", + "Specifies the symbol server URL. If not specified, nuget.smbsrc.net is used when pushing to nuget.org.", + Accept.ExactlyOneArgument + .With(name: "source")), + Create.Option("-t|--timeout", + "Specifies the timeout for pushing to a server in seconds. Defaults to 300 seconds (5 minutes).", + Accept.ExactlyOneArgument + .With(name: "timeout")), + Create.Option("-k|--api-key", "The API key for the server.", + Accept.ExactlyOneArgument + .With(name: "apiKey")), + Create.Option("-sk|--symbol-api-key", "The API key for the symbol server.", + Accept.ExactlyOneArgument + .With(name: "apiKey")), + Create.Option("-d|--disable-buffering", + "Disable buffering when pushing to an HTTP(S) server to decrease memory usage."), + Create.Option("-n|--no-symbols", + "If a symbols package exists, it will not be pushed to a symbols server."))); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-pack/PackCommandParser.cs b/src/dotnet/commands/dotnet-pack/PackCommandParser.cs new file mode 100644 index 000000000..1f36cd9a3 --- /dev/null +++ b/src/dotnet/commands/dotnet-pack/PackCommandParser.cs @@ -0,0 +1,38 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class PackCommandParser + { + public static Command Pack() => + Create.Command("pack", + ".NET Core NuGet Package Packer", + CommonOptions.HelpOption(), + Create.Option("-o|--output", + "Directory in which to place built packages.", + Accept.ExactlyOneArgument + .With(name: "OUTPUT_DIR")), + Create.Option("--no-build", + "Skip building the project prior to packing. By default, the project will be built."), + Create.Option("--include-symbols", + "Include packages with symbols in addition to regular packages in output directory."), + Create.Option("--include-source", + "Include PDBs and source files. Source files go into the src folder in the resulting nuget package"), + Create.Option("-c|--configuration", + "Configuration to use for building the project. Default for most projects is \"Debug\".", + Accept.ExactlyOneArgument + .With(name: "CONFIGURATION") + .WithSuggestionsFrom("DEBUG", + "RELEASE")), + Create.Option("--version-suffix", + "Defines the value for the $(VersionSuffix) property in the project.", + Accept.ExactlyOneArgument + .With(name: "VERSION_SUFFIX")), + Create.Option("-s|--serviceable", + "Set the serviceable flag in the package. For more information, please see https://aka.ms/nupkgservicing."), + CommonOptions.VerbosityOption()); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs b/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs new file mode 100644 index 000000000..a9ede850d --- /dev/null +++ b/src/dotnet/commands/dotnet-publish/PublishCommandParser.cs @@ -0,0 +1,36 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class PublishCommandParser + { + public static Command Publish() => + Create.Command("publish", + ".NET Publisher", + Accept.ExactlyOneArgument, + CommonOptions.HelpOption(), + Create.Option("-f|--framework", + "Target framework to publish for. The target framework has to be specified in the project file.", + Accept.AnyOneOf(Suggest.TargetFrameworksFromProjectFile) + .With(name: "FRAMEWORK")), + Create.Option("-r|--runtime", + "Publish the project for a given runtime. This is used when creating self-contained deployment. Default is to publish a framework-dependent app.", + Accept.AnyOneOf(Suggest.RunTimesFromProjectFile) + .With(name: "RUNTIME_IDENTIFIER")), + Create.Option("-o|--output", + "Output directory in which to place the published artifacts.", + Accept.ExactlyOneArgument + .With(name: "OUTPUT_DIR")), + Create.Option("-c|--configuration", "Configuration to use for building the project. Default for most projects is \"Debug\".", + Accept.ExactlyOneArgument + .With(name: "CONFIGURATION") + .WithSuggestionsFrom("DEBUG", "RELEASE")), + Create.Option("--version-suffix", "Defines the value for the $(VersionSuffix) property in the project.", + Accept.ExactlyOneArgument + .With(name: "VERSION_SUFFIX")), + CommonOptions.VerbosityOption()); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-remove/RemoveCommandParser.cs b/src/dotnet/commands/dotnet-remove/RemoveCommandParser.cs new file mode 100644 index 000000000..0e99c019b --- /dev/null +++ b/src/dotnet/commands/dotnet-remove/RemoveCommandParser.cs @@ -0,0 +1,29 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class RemoveCommandParser + { + public static Command Remove() => + Create.Command("remove", + ".NET Remove Command", + Accept.ZeroOrOneArgument + .With(name: "PROJECT") + .DefaultToCurrentDirectory(), + CommonOptions.HelpOption(), + Create.Command("package", + "Command to remove package reference.", + CommonOptions.HelpOption()), + Create.Command("reference", + "Command to remove project to project reference", + Accept.AnyOneOf(Suggest.ProjectReferencesFromProjectFile), + CommonOptions.HelpOption(), + Create.Option("-f|--framework", + "Remove reference only when targetting a specific framework", + Accept.ExactlyOneArgument + .With(name: "FRAMEWORK")))); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-restore/RestoreCommandParser.cs b/src/dotnet/commands/dotnet-restore/RestoreCommandParser.cs new file mode 100644 index 000000000..0cc2f82d3 --- /dev/null +++ b/src/dotnet/commands/dotnet-restore/RestoreCommandParser.cs @@ -0,0 +1,41 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class RestoreCommandParser + { + public static Command Restore() => + Create.Command("restore", + ".NET dependency restorer", + Accept.ZeroOrOneArgument, + CommonOptions.HelpOption(), + Create.Option("-s|--source", + "Specifies a NuGet package source to use during the restore.", + Accept.ExactlyOneArgument + .With(name: "SOURCE")), + Create.Option("-r|--runtime", + "Target runtime to restore packages for.", + Accept.AnyOneOf(Suggest.RunTimesFromProjectFile) + .With(name: "RUNTIME_IDENTIFIER")), + Create.Option("--packages", + "Directory to install packages in.", + Accept.ExactlyOneArgument + .With(name: "PACKAGES_DIRECTORY")), + Create.Option("--disable-parallel", + "Disables restoring multiple projects in parallel."), + Create.Option("--configfile", + "The NuGet configuration file to use.", + Accept.ExactlyOneArgument + .With(name: "FILE")), + Create.Option("--no-cache", + "Do not cache packages and http requests."), + Create.Option("--ignore-failed-sources", + "Treat package source failures as warnings."), + Create.Option("--no-dependencies", + "Set this flag to ignore project to project references and only restore the root project"), + CommonOptions.VerbosityOption()); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-run/RunCommandParser.cs b/src/dotnet/commands/dotnet-run/RunCommandParser.cs new file mode 100644 index 000000000..dba6ec68a --- /dev/null +++ b/src/dotnet/commands/dotnet-run/RunCommandParser.cs @@ -0,0 +1,25 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class RunCommandParser + { + public static Command Run() => + Create.Command("run", + ".NET Run Command", + CommonOptions.HelpOption(), + Create.Option("-c|--configuration", + @"Configuration to use for building the project. Default for most projects is ""Debug"".", + Accept.ExactlyOneArgument + .WithSuggestionsFrom("DEBUG", "RELEASE")), + Create.Option("-f|--framework", + "Build and run the app using the specified framework. The framework has to be specified in the project file.", + Accept.AnyOneOf(Suggest.TargetFrameworksFromProjectFile)), + Create.Option("-p|--project", + "The path to the project file to run (defaults to the current directory if there is only one project).", + Accept.ZeroOrOneArgument)); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-sln/SlnCommandParser.cs b/src/dotnet/commands/dotnet-sln/SlnCommandParser.cs new file mode 100644 index 000000000..9d9f073e4 --- /dev/null +++ b/src/dotnet/commands/dotnet-sln/SlnCommandParser.cs @@ -0,0 +1,27 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class SlnCommandParser + { + public static Command Sln() => + Create.Command("sln", + ".NET modify solution file command", + CommonOptions.HelpOption(), + Create.Command("add", + ".NET Add project(s) to a solution file Command", + Accept.ExactlyOneArgument + .With(name: "SLN_FILE"), + CommonOptions.HelpOption()), + Create.Command("list", + "List all projects in the solution.", + Accept.ExactlyOneArgument + .With(name: "SLN_FILE"), + CommonOptions.HelpOption()), + Create.Command("remove", + "Remove the specified project(s) from the solution. The project is not impacted.")); + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-test/TestCommandParser.cs b/src/dotnet/commands/dotnet-test/TestCommandParser.cs new file mode 100644 index 000000000..2340ee4b3 --- /dev/null +++ b/src/dotnet/commands/dotnet-test/TestCommandParser.cs @@ -0,0 +1,54 @@ +using System.Linq; +using Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class TestCommandParser + { + public static Command Test() => + Create.Command("test", + ".NET Test Driver", + Create.Option("-h|--help", + "Show help information"), + Create.Option("-s|--settings", + "Settings to use when running tests.", + Accept.ExactlyOneArgument + .With(name: "SETTINGS_FILE")), + Create.Option("-t|--list-tests", + "Lists discovered tests"), + Create.Option("--filter", + @"Run tests that match the given expression. + Examples: + Run tests with priority set to 1: --filter ""Priority = 1"" + Run a test with the specified full name: --filter ""FullyQualifiedName=Namespace.ClassName.MethodName"" + Run tests that contain the specified name: --filter ""FullyQualifiedName~Namespace.Class"" + More info on filtering support: https://aka.ms/vstest-filtering", + Accept.ExactlyOneArgument + .With(name: "EXPRESSION")), + Create.Option("-a|--test-adapter-path", + "Use custom adapters from the given path in the test run.\r\n Example: --test-adapter-path "), + Create.Option("-l|--logger", + "Specify a logger for test results.\r\n Example: --logger \"trx[;LogFileName=]\"", + Accept.ExactlyOneArgument + .With(name: "LoggerUri/FriendlyName")), + Create.Option("-c|--configuration", "Configuration to use for building the project. Default for most projects is \"Debug\".", + Accept.ExactlyOneArgument + .With(name: "CONFIGURATION") + .WithSuggestionsFrom("DEBUG", "RELEASE")), + Create.Option("-f|--framework", + "Looks for test binaries for a specific framework", + Accept.AnyOneOf(Suggest.TargetFrameworksFromProjectFile) + .With(name: "FRAMEWORK")), + Create.Option("-o|--output", + "Directory in which to find the binaries to be run", + Accept.ExactlyOneArgument + .With(name: "OUTPUT_DIR")), + Create.Option("-d|--diag", + "Enable verbose logs for test platform.\r\n Logs are written to the provided file.", + Accept.ExactlyOneArgument + .With(name: "PATH_TO_FILE")), + Create.Option("--no-build", + "Do not build project before testing."), + CommonOptions.VerbosityOption()); + } +} \ No newline at end of file diff --git a/src/dotnet/dotnet-complete/Suggest.cs b/src/dotnet/dotnet-complete/Suggest.cs new file mode 100644 index 000000000..e4b78e65c --- /dev/null +++ b/src/dotnet/dotnet-complete/Suggest.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.Build.Evaluation; +using Microsoft.DotNet.Tools; + +namespace Microsoft.DotNet.Cli +{ + internal static class Suggest + { + public static IEnumerable TargetFrameworksFromProjectFile() + { + var msbuildProj = MsbuildProject.FromFileOrDirectory( + new ProjectCollection(), + Directory.GetCurrentDirectory()); + + foreach (var tfm in msbuildProj.GetTargetFrameworks()) + { + yield return tfm.GetShortFolderName(); + } + } + + public static IEnumerable RunTimesFromProjectFile() + { + var msbuildProj = MsbuildProject.FromFileOrDirectory( + new ProjectCollection(), + Directory.GetCurrentDirectory()); + + return msbuildProj.GetRuntimeIdentifiers(); + } + + public static IEnumerable ProjectReferencesFromProjectFile() + { + var msbuildProj = MsbuildProject.FromFileOrDirectory( + new ProjectCollection(), + Directory.GetCurrentDirectory()); + + return msbuildProj.GetProjectToProjectReferences() + .Select(r => r.Include); + } + } +} \ No newline at end of file diff --git a/src/dotnet/dotnet-complete/commands/ParserExtensions.cs b/src/dotnet/dotnet-complete/commands/ParserExtensions.cs deleted file mode 100644 index 825a1067c..000000000 --- a/src/dotnet/dotnet-complete/commands/ParserExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using Microsoft.DotNet.Cli.CommandLine; - -namespace Microsoft.DotNet.Tools -{ - public static class ParserExtensions - { - public static void ShowHelp(this ParseResult parseResult) => - Console.WriteLine(parseResult.Command().HelpView()); - } -} \ No newline at end of file diff --git a/src/dotnet/dotnet-complete/commands/ParserFor.cs b/src/dotnet/dotnet-complete/commands/ParserFor.cs deleted file mode 100644 index cf64aa10f..000000000 --- a/src/dotnet/dotnet-complete/commands/ParserFor.cs +++ /dev/null @@ -1,517 +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 System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Threading; -using Microsoft.Build.Evaluation; -using Microsoft.DotNet.Cli.CommandLine; -using Microsoft.DotNet.Tools.Common; -using Newtonsoft.Json.Linq; -using static Microsoft.DotNet.Cli.CommandLine.Accept; -using static Microsoft.DotNet.Cli.CommandLine.Create; -using Command = Microsoft.DotNet.Cli.CommandLine.Command; - -namespace Microsoft.DotNet.Tools -{ - public static class ParserFor - { - private static readonly Command _dotnetCommand = Command("dotnet", - ".NET Command Line Tools", - NoArguments, - New(), - Restore(), - Build(), - Publish(), - Run(), - Test(), - Pack(), - Migrate(), - Clean(), - Sln(), - Add(), - Remove(), - List(), - NuGet(), - Command("msbuild", ""), - Command("vstest", ""), - Complete(), - HelpOption(), - Option("--info", ""), - VerbosityOption(), - Option("-d", "")); - - public static Command DotnetCommand { get; } = _dotnetCommand; - - private static Command Add() => - Command("add", - ".NET Add Command", - ExactlyOneArgument.DefaultToCurrentDirectory(), - Command("package", - ".NET Add Package reference Command", - ExactlyOneArgument - .WithSuggestionsFrom(QueryNuGet), - HelpOption(), - Option("-v|--version", - "Version for the package to be added.", - ExactlyOneArgument - .With(name: "VERSION")), - Option("-f|--framework", - "Add reference only when targetting a specific framework", - ExactlyOneArgument - .With(name: "FRAMEWORK")), - Option("-n|--no-restore ", - "Add reference without performing restore preview and compatibility check."), - Option("-s|--source", - "Use specific NuGet package sources to use during the restore."), - Option("--package-directory", - "Restore the packages to this Directory .", - ExactlyOneArgument - .With(name: "PACKAGE_DIRECTORY"))), - Command("reference", - "Command to add project to project reference", - OneOrMoreArguments, - HelpOption(), - Option("-f|--framework", - "Add reference only when targetting a specific framework", - AnyOneOf(TargetFrameworksFromProjectFile) - .With(name: "FRAMEWORK"))), - HelpOption()); - - private static Command Complete() => - Command("complete", "", - ExactlyOneArgument - .With(name: "path"), - Option("--position", "", - ExactlyOneArgument - .With(name: "command"), - o => int.Parse(o.Arguments.Single()))); - - private static Command Build() => - Command("build", - ".NET Builder", - HelpOption(), - Option("-o|--output", - "Output directory in which to place built artifacts.", - ExactlyOneArgument - .With(name: "OUTPUT_DIR")), - Option("-f|--framework", - "Target framework to build for. The target framework has to be specified in the project file.", - AnyOneOf(TargetFrameworksFromProjectFile)), - Option("-r|--runtime", - "Target runtime to build for. The default is to build a portable application.", - AnyOneOf(RunTimesFromProjectFile)), - Option("-c|--configuration", - "Configuration to use for building the project. Default for most projects is \"Debug\".", - ExactlyOneArgument - .With(name: "CONFIGURATION") - .WithSuggestionsFrom(_ => new[] { "DEBUG", "RELEASE" })), - Option("--version-suffix", "Defines the value for the $(VersionSuffix) property in the project", - ExactlyOneArgument - .With(name: "VERSION_SUFFIX")), - Option("--no-incremental", "Disables incremental build."), - Option("--no-dependencies", "Set this flag to ignore project-to-project references and only build the root project"), - VerbosityOption()); - - private static Command Clean() => - Command("clean", - ".NET Clean Command", - HelpOption(), - Option("-o|--output", "Directory in which the build outputs have been placed.", - ExactlyOneArgument - .With(name: "OUTPUT_DIR")), - Option("-f|--framework", "Clean a specific framework.", - ExactlyOneArgument - .With(name: "FRAMEWORK") - .WithSuggestionsFrom(_ => TargetFrameworksFromProjectFile())), - Option("-c|--configuration", - "Clean a specific configuration.", - ExactlyOneArgument - .With(name: "CONFIGURATION") - .WithSuggestionsFrom(_ => new[] { "DEBUG", "RELEASE" }))); - - private static Command List() => - Command("list", - ".NET List Command", - ZeroOrOneArgument - .With(name: "PROJECT", - description: - "The project file to operate on. If a file is not specified, the command will search the current directory for one.") - .DefaultToCurrentDirectory(), - HelpOption(), - Command("reference", "Command to list project to project references", - ExactlyOneArgument - .With(name: "PROJECT") - .With(description: "The project file to operate on. If a file is not specified, the command will search the current directory for one."), - HelpOption())); - - private static Command Migrate() => - Command("migrate", - ".NET Migrate Command", - HelpOption(), - Option("-t|--template-file", - "Base MSBuild template to use for migrated app. The default is the project included in dotnet new."), - Option("-v|--sdk-package-version", - "The version of the SDK package that will be referenced in the migrated app. The default is the version of the SDK in dotnet new."), - Option("-x|--xproj-file", - "The path to the xproj file to use. Required when there is more than one xproj in a project directory."), - Option("-s|--skip-project-references", - "Skip migrating project references. By default, project references are migrated recursively."), - Option("-r|--report-file", - "Output migration report to the given file in addition to the console."), - Option("--format-report-file-json", - "Output migration report file as json rather than user messages."), - Option("--skip-backup", - "Skip moving project.json, global.json, and *.xproj to a `backup` directory after successful migration.")); - - private static Command New() => - Command("new", - "Initialize .NET projects.", - WithSuggestionsFrom("console", - "classlib", - "mstest", - "xunit", - "web", - "mvc", - "webapi", - "sln"), - Option("-l|--list", - "List templates containing the specified name."), - Option("-lang|--language", - "Specifies the language of the template to create", - WithSuggestionsFrom("C#", "F#") - .With(defaultValue: () => "C#")), - Option("-n|--name", - "The name for the output being created. If no name is specified, the name of the current directory is used."), - Option("-o|--output", - "Location to place the generated output."), - Option("-h|--help", - "Displays help for this command."), - Option("-all|--show-all", - "Shows all templates")); - - private static Command NuGet() => - Command("nuget", - "NuGet Command Line 4.0.0.0", - HelpOption(), - Option("--version", - "Show version information"), - Option("-v|--verbosity", - "The verbosity of logging to use. Allowed values: Debug, Verbose, Information, Minimal, Warning, Error.", - ExactlyOneArgument - .With(name: "verbosity")), - Command("delete", - "Deletes a package from the server.", - ExactlyOneArgument - .With(name: "root", - description: "The Package Id and version."), - HelpOption(), - Option("--force-english-output", - "Forces the application to run using an invariant, English-based culture."), - Option("-s|--source", - "Specifies the server URL", - ExactlyOneArgument - .With(name: "source")), - Option("--non-interactive", - "Do not prompt for user input or confirmations."), - Option("-k|--api-key", - "The API key for the server.", - ExactlyOneArgument - .With(name: "apiKey"))), - Command("locals", - "Clears or lists local NuGet resources such as http requests cache, packages cache or machine-wide global packages folder.", - AnyOneOf(@"all", @"http-cache", @"global-packages", @"temp") - .With(description: "Cache Location(s) Specifies the cache location(s) to list or clear."), - HelpOption(), - Option("--force-english-output", - "Forces the application to run using an invariant, English-based culture."), - Option("-c|--clear", "Clear the selected local resources or cache location(s)."), - Option("-l|--list", "List the selected local resources or cache location(s).")), - Command("push", - "Pushes a package to the server and publishes it.", - HelpOption(), - Option("--force-english-output", - "Forces the application to run using an invariant, English-based culture."), - Option("-s|--source", - "Specifies the server URL", - ExactlyOneArgument - .With(name: "source")), - Option("-ss|--symbol-source", - "Specifies the symbol server URL. If not specified, nuget.smbsrc.net is used when pushing to nuget.org.", - ExactlyOneArgument - .With(name: "source")), - Option("-t|--timeout", - "Specifies the timeout for pushing to a server in seconds. Defaults to 300 seconds (5 minutes).", - ExactlyOneArgument - .With(name: "timeout")), - Option("-k|--api-key", "The API key for the server.", - ExactlyOneArgument - .With(name: "apiKey")), - Option("-sk|--symbol-api-key", "The API key for the symbol server.", - ExactlyOneArgument - .With(name: "apiKey")), - Option("-d|--disable-buffering", - "Disable buffering when pushing to an HTTP(S) server to decrease memory usage."), - Option("-n|--no-symbols", - "If a symbols package exists, it will not be pushed to a symbols server."))); - - private static Command Pack() => - Command("pack", - ".NET Core NuGet Package Packer", - HelpOption(), - Option("-o|--output", - "Directory in which to place built packages.", - ExactlyOneArgument - .With(name: "OUTPUT_DIR")), - Option("--no-build", - "Skip building the project prior to packing. By default, the project will be built."), - Option("--include-symbols", - "Include packages with symbols in addition to regular packages in output directory."), - Option("--include-source", - "Include PDBs and source files. Source files go into the src folder in the resulting nuget package"), - Option("-c|--configuration", - "Configuration to use for building the project. Default for most projects is \"Debug\".", - ExactlyOneArgument - .With(name: "CONFIGURATION") - .WithSuggestionsFrom(_ => new[] { "DEBUG", "RELEASE" })), - Option("--version-suffix", - "Defines the value for the $(VersionSuffix) property in the project.", - ExactlyOneArgument - .With(name: "VERSION_SUFFIX")), - Option("-s|--serviceable", - "Set the serviceable flag in the package. For more information, please see https://aka.ms/nupkgservicing."), - VerbosityOption()); - - private static Command Publish() => - Command("publish", - ".NET Publisher", - ExactlyOneArgument, - HelpOption(), - Option("-f|--framework", - "Target framework to publish for. The target framework has to be specified in the project file.", - AnyOneOf(TargetFrameworksFromProjectFile) - .With(name: "FRAMEWORK")), - Option("-r|--runtime", - "Publish the project for a given runtime. This is used when creating self-contained deployment. Default is to publish a framework-dependent app.", - AnyOneOf(RunTimesFromProjectFile) - .With(name: "RUNTIME_IDENTIFIER")), - Option("-o|--output", - "Output directory in which to place the published artifacts.", - ExactlyOneArgument - .With(name: "OUTPUT_DIR")), - Option("-c|--configuration", "Configuration to use for building the project. Default for most projects is \"Debug\".", - ExactlyOneArgument - .With(name: "CONFIGURATION") - .WithSuggestionsFrom(_ => new[] { "DEBUG", "RELEASE" })), - Option("--version-suffix", "Defines the value for the $(VersionSuffix) property in the project.", - ExactlyOneArgument - .With(name: "VERSION_SUFFIX")), - VerbosityOption()); - - private static Command Remove() => - Command("remove", - ".NET Remove Command", - ZeroOrOneArgument - .With(name: "PROJECT") - .DefaultToCurrentDirectory(), - HelpOption(), - Command("package", - "Command to remove package reference.", - HelpOption()), - Command("reference", - "Command to remove project to project reference", - AnyOneOf(ProjectReferencesFromProjectFile), - HelpOption(), - Option("-f|--framework", - "Remove reference only when targetting a specific framework", - ExactlyOneArgument - .With(name: "FRAMEWORK")))); - - private static Command Restore() => - Command("restore", - ".NET dependency restorer", - HelpOption(), - Option("-s|--source", - "Specifies a NuGet package source to use during the restore.", - ExactlyOneArgument - .With(name: "SOURCE")), - Option("-r|--runtime", - "Target runtime to restore packages for.", - AnyOneOf(RunTimesFromProjectFile) - .With(name: "RUNTIME_IDENTIFIER")), - Option("--packages", - "Directory to install packages in.", - ExactlyOneArgument - .With(name: "PACKAGES_DIRECTORY")), - Option("--disable-parallel", - "Disables restoring multiple projects in parallel."), - Option("--configfile", - "The NuGet configuration file to use.", - ExactlyOneArgument - .With(name: "FILE")), - Option("--no-cache", - "Do not cache packages and http requests."), - Option("--ignore-failed-sources", - "Treat package source failures as warnings."), - Option("--no-dependencies", - "Set this flag to ignore project to project references and only restore the root project"), - VerbosityOption()); - - private static Command Run() => - Command("run", - ".NET Run Command", - HelpOption(), - Option("-c|--configuration", - @"Configuration to use for building the project. Default for most projects is ""Debug"".", - ExactlyOneArgument - .WithSuggestionsFrom(_ => new[] { "DEBUG", "RELEASE" })), - Option("-f|--framework", - "Build and run the app using the specified framework. The framework has to be specified in the project file.", - AnyOneOf(TargetFrameworksFromProjectFile)), - Option("-p|--project", - "The path to the project file to run (defaults to the current directory if there is only one project).", - ZeroOrOneArgument)); - - private static Command Sln() => - Command("sln", - ".NET modify solution file command", - - HelpOption(), - Command("add", - ".NET Add project(s) to a solution file Command", - ExactlyOneArgument - .With(name: "SLN_FILE"), - HelpOption()), - Command("list", - "List all projects in the solution.", - ExactlyOneArgument - .With(name: "SLN_FILE"), - HelpOption()), - Command("remove", - "Remove the specified project(s) from the solution. The project is not impacted.")); - - private static Command Test() => - Command("test", - ".NET Test Driver", - Option("-h|--help", - "Show help information"), - Option("-s|--settings", - "Settings to use when running tests.", - ExactlyOneArgument - .With(name: "SETTINGS_FILE")), - Option("-t|--list-tests", - "Lists discovered tests"), - Option("--filter", - @"Run tests that match the given expression. - Examples: - Run tests with priority set to 1: --filter ""Priority = 1"" - Run a test with the specified full name: --filter ""FullyQualifiedName=Namespace.ClassName.MethodName"" - Run tests that contain the specified name: --filter ""FullyQualifiedName~Namespace.Class"" - More info on filtering support: https://aka.ms/vstest-filtering", - ExactlyOneArgument - .With(name: "EXPRESSION")), - Option("-a|--test-adapter-path", - "Use custom adapters from the given path in the test run.\r\n Example: --test-adapter-path "), - Option("-l|--logger", - "Specify a logger for test results.\r\n Example: --logger \"trx[;LogFileName=]\"", - ExactlyOneArgument - .With(name: "LoggerUri/FriendlyName")), - Option("-c|--configuration", "Configuration to use for building the project. Default for most projects is \"Debug\".", - ExactlyOneArgument - .With(name: "CONFIGURATION") - .WithSuggestionsFrom(_ => new[] { "DEBUG", "RELEASE" })), - Option("-f|--framework", - "Looks for test binaries for a specific framework", - AnyOneOf(() => TargetFrameworksFromProjectFile().ToArray()) - .With(name: "FRAMEWORK")), - Option("-o|--output", - "Directory in which to find the binaries to be run", - ExactlyOneArgument - .With(name: "OUTPUT_DIR")), - Option("-d|--diag", - "Enable verbose logs for test platform.\r\n Logs are written to the provided file.", - ExactlyOneArgument - .With(name: "PATH_TO_FILE")), - Option("--no-build", - "Do not build project before testing."), - VerbosityOption()); - - private static ArgumentsRule DefaultToCurrentDirectory(this ArgumentsRule rule) => - rule.With(defaultValue: () => PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory())); - - private static Option HelpOption() => - Option("-h|--help", - "Show help information", - NoArguments, - materialize: o => o.Option.Command().HelpView()); - - private static Option VerbosityOption() => - Option("-v|--verbosity", - "Set the verbosity level of the command. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]", - AnyOneOf("q[uiet]", - "m[inimal]", - "n[ormal]", - "d[etailed]")); - - private static IEnumerable QueryNuGet(string match) - { - var httpClient = new HttpClient(); - - string result = null; - - try - { - var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(10)); - var response = httpClient.GetAsync($"https://api-v2v3search-0.nuget.org/query?q={match}&skip=0&take=100&prerelease=true", cancellation.Token) - .Result; - - result = response.Content.ReadAsStringAsync().Result; - } - catch (Exception) - { - yield break; - } - - var json = JObject.Parse(result); - - foreach (var id in json["data"]) - { - yield return id["id"].Value(); - } - } - - private static IEnumerable TargetFrameworksFromProjectFile() - { - var msbuildProj = MsbuildProject.FromFileOrDirectory( - new ProjectCollection(), - Directory.GetCurrentDirectory()); - - foreach (var tfm in msbuildProj.GetTargetFrameworks()) - { - yield return tfm.GetShortFolderName(); - } - } - - private static IEnumerable RunTimesFromProjectFile() - { - var msbuildProj = MsbuildProject.FromFileOrDirectory( - new ProjectCollection(), - Directory.GetCurrentDirectory()); - - return msbuildProj.GetRuntimeIdentifiers(); - } - - private static IEnumerable ProjectReferencesFromProjectFile() - { - var msbuildProj = MsbuildProject.FromFileOrDirectory( - new ProjectCollection(), - Directory.GetCurrentDirectory()); - - return msbuildProj.GetProjectToProjectReferences() - .Select(r => r.Include); - } - } -} \ No newline at end of file diff --git a/src/dotnet/dotnet.csproj b/src/dotnet/dotnet.csproj index 4a6355cd3..3f0d29978 100644 --- a/src/dotnet/dotnet.csproj +++ b/src/dotnet/dotnet.csproj @@ -10,6 +10,7 @@ true true $(PackageTargetFallback);dotnet5.4 + Microsoft.DotNet.Cli @@ -39,10 +40,14 @@ - + + + + + diff --git a/test/dotnet.Tests/ParseTests.cs b/test/dotnet.Tests/ParserTests/AddReferenceParserTests.cs similarity index 65% rename from test/dotnet.Tests/ParseTests.cs rename to test/dotnet.Tests/ParserTests/AddReferenceParserTests.cs index b4b5d5c2b..51bb79f75 100644 --- a/test/dotnet.Tests/ParseTests.cs +++ b/test/dotnet.Tests/ParserTests/AddReferenceParserTests.cs @@ -1,14 +1,17 @@ +// 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 System; using System.IO; -using FluentAssertions; using System.Linq; +using FluentAssertions; using Microsoft.DotNet.Cli.CommandLine; -using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Common; using Xunit; using Xunit.Abstractions; +using Parser = Microsoft.DotNet.Cli.Parser; -namespace Microsoft.DotNet.Tests +namespace Microsoft.DotNet.Tests.ParserTests { public class AddReferenceParserTests { @@ -20,9 +23,9 @@ namespace Microsoft.DotNet.Tests } [Fact] - public void dotnet_add_reference_has_default_argument_set_to_current_directory() + public void AddReferenceHasDefaultArgumentSetToCurrentDirectory() { - var command = ParserFor.DotnetCommand; + var command = Parser.DotnetCommand; var result = command.Parse("dotnet add reference my.csproj"); @@ -36,11 +39,11 @@ namespace Microsoft.DotNet.Tests } [Fact] - public void dotnet_add_reference_without_argument_results_in_an_error() + public void AddReferenceWithoutArgumentResultsInAnError() { - var command = ParserFor.DotnetCommand["add"]; + var command = Parser.DotnetCommand; - var result = command.Parse("add reference"); + var result = command.Parse("dotnet add reference"); output.WriteLine(result.Diagram());