diff --git a/src/Cli/dotnet/ParserOptionActions.cs b/src/Cli/dotnet/ParserOptionActions.cs index 0e7c134105f5..772ec3fdd8af 100644 --- a/src/Cli/dotnet/ParserOptionActions.cs +++ b/src/Cli/dotnet/ParserOptionActions.cs @@ -3,6 +3,7 @@ using System.CommandLine; using System.CommandLine.Invocation; +using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli.Commands.Workload; using Microsoft.DotNet.Cli.Extensions; using Microsoft.DotNet.Cli.Help; @@ -24,16 +25,18 @@ internal abstract class InvocableOptionAction(Option option) : SynchronousComman public Option Option { get; } = option; } -internal class HandleDiagnosticAction(Option option) : InvocableOptionAction(option) +internal class HandleDiagnosticAction(Option option) : InvocableOptionAction(option) { public override bool Terminating => false; + // S.CL will always invoke this option action because: + // 1. A boolean option has a default value of `false`. + // 2. The option has Terminating set to `false`. + // When a default value exists (non-null) and the option is not terminating, the option action is always invoked. public override int Invoke(ParseResult parseResult) { - // Required because of: https://github.com/dotnet/command-line-api/pull/2708 - // S.CL now always invokes non-terminating option actions for implicit (default-valued) options. - // Meaning, this action always runs independent of the option being provided or not. - if (parseResult.GetResult(Option) is not { } result || result.Implicit + // This check is necessary as per comment above. + if (!parseResult.HasOption(Option) || !parseResult.GetValue(option) // Only set verbose output on built-in commands. || !parseResult.IsDotnetBuiltInCommand()) { @@ -41,7 +44,7 @@ public override int Invoke(ParseResult parseResult) } // Determine whether the diagnostic option should be attached to the dotnet command or the subcommand. - if (DiagOptionPrecedesSubcommand(parseResult.Tokens.Select(t => t.Value), parseResult.RootSubCommandResult())) + if (OptionPrecedesSubcommand(parseResult.Tokens.Select(t => t.Value), parseResult.RootSubCommandResult())) { Environment.SetEnvironmentVariable(CommandLoggingContext.Variables.Verbose, bool.TrueString); CommandLoggingContext.SetVerbose(true); @@ -58,7 +61,7 @@ public override int Invoke(ParseResult parseResult) return 0; } - private static bool DiagOptionPrecedesSubcommand(IEnumerable tokens, string subCommand) + private bool OptionPrecedesSubcommand(IEnumerable tokens, string subCommand) { if (string.IsNullOrEmpty(subCommand)) { @@ -72,8 +75,7 @@ private static bool DiagOptionPrecedesSubcommand(IEnumerable tokens, str return false; } - if (Parser.RootCommand.DiagOption.Name == token - || Parser.RootCommand.DiagOption.Aliases.Contains(token)) + if (Option.Name == token || Option.Aliases.Contains(token)) { return true; } @@ -101,14 +103,15 @@ public override int Invoke(ParseResult parseResult) } } -internal class PrintVersionAction(Option option) : InvocableOptionAction(option) +internal class PrintVersionAction(Option option) : InvocableOptionAction(option) { public override bool Terminating => true; public override int Invoke(ParseResult parseResult) { - // Only print for top-level commands. - if (!parseResult.IsTopLevelDotnetCommand()) + if (!parseResult.HasOption(Option) || !parseResult.GetValue(option) + // Only print for top-level commands. + || !parseResult.IsTopLevelDotnetCommand()) { return 0; } @@ -119,14 +122,15 @@ public override int Invoke(ParseResult parseResult) } } -internal class PrintInfoAction(Option option) : InvocableOptionAction(option) +internal class PrintInfoAction(Option option) : InvocableOptionAction(option) { public override bool Terminating => true; public override int Invoke(ParseResult parseResult) { - // Only print for top-level commands. - if (!parseResult.IsTopLevelDotnetCommand()) + if (!parseResult.HasOption(Option) || !parseResult.GetValue(option) + // Only print for top-level commands. + || !parseResult.IsTopLevelDotnetCommand()) { return 0; } @@ -162,12 +166,17 @@ public override int Invoke(ParseResult parseResult) } } -internal class PrintCliSchemaAction(Option option) : InvocableOptionAction(option) +internal class PrintCliSchemaAction(Option option) : InvocableOptionAction(option) { public override bool Terminating => true; public override int Invoke(ParseResult parseResult) { + if (!parseResult.HasOption(Option) || !parseResult.GetValue(option)) + { + return 0; + } + CliSchema.PrintCliSchema(parseResult, parseResult.InvocationConfiguration.Output, Program.TelemetryInstance); return 0;