diff --git a/.vscode/launch.json b/.vscode/launch.json
index a6f8c927bd..3f190d2e4b 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -4,6 +4,23 @@
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
+ {
+ "name": "format @validate.rsp",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ // If you have changed target frameworks, make sure to update the program path.
+ "program": "${workspaceFolder}/artifacts/bin/dotnet-format/Debug/netcoreapp2.1/dotnet-format.dll",
+ "args": [
+ "@validate.rsp",
+ "--check"
+ ],
+ "cwd": "${workspaceFolder}",
+ // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
+ "console": "internalConsole",
+ "stopAtEntry": false,
+ "justMyCode": false
+ },
{
"name": "format -f --check",
"type": "coreclr",
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 44934e3d62..16d948f681 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -35,8 +35,8 @@
-
-
+
+
\ No newline at end of file
diff --git a/src/FormatCommand.cs b/src/FormatCommand.cs
index 8fe40ab00e..cf01eab100 100644
--- a/src/FormatCommand.cs
+++ b/src/FormatCommand.cs
@@ -3,6 +3,7 @@
using System;
using System.CommandLine;
using System.CommandLine.Parsing;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
@@ -17,8 +18,8 @@ internal static class FormatCommand
bool noRestore,
bool folder,
bool fixWhitespace,
- string? fixStyle,
- string? fixAnalyzers,
+ string fixStyle,
+ string fixAnalyzers,
string[] diagnostics,
string? verbosity,
bool check,
@@ -37,51 +38,35 @@ internal static RootCommand CreateCommandLineOptions()
// Sync changes to option and argument names with the FormatCommant.Handler above.
var rootCommand = new RootCommand
{
- new Argument("workspace")
+ new Argument("workspace", () => null, Resources.A_path_to_a_solution_file_a_project_file_or_a_folder_containing_a_solution_or_project_file_If_a_path_is_not_specified_then_the_current_directory_is_used).LegalFilePathsOnly(),
+ new Option(new[] { "--no-restore" }, Resources.Doesnt_execute_an_implicit_restore_before_formatting),
+ new Option(new[] { "--folder", "-f" }, Resources.Whether_to_treat_the_workspace_argument_as_a_simple_folder_of_files),
+ new Option(new[] { "--fix-whitespace", "-w" }, Resources.Run_whitespace_formatting_Run_by_default_when_not_applying_fixes),
+ new Option(new[] { "--fix-style", "-s" }, Resources.Run_code_style_analyzers_and_apply_fixes, argumentType: typeof(string), arity: ArgumentArity.ZeroOrOne)
{
- Arity = ArgumentArity.ZeroOrOne,
- Description = Resources.A_path_to_a_solution_file_a_project_file_or_a_folder_containing_a_solution_or_project_file_If_a_path_is_not_specified_then_the_current_directory_is_used
- }.LegalFilePathsOnly(),
- new Option(new[] { "--no-restore" }, Resources.Doesnt_execute_an_implicit_restore_before_formatting),
- new Option(new[] { "--folder", "-f" }, Resources.Whether_to_treat_the_workspace_argument_as_a_simple_folder_of_files),
- new Option(new[] { "--fix-whitespace", "-w" }, Resources.Run_whitespace_formatting_Run_by_default_when_not_applying_fixes),
- new Option(new[] { "--fix-style", "-s" }, Resources.Run_code_style_analyzers_and_apply_fixes)
- {
- Argument = new Argument("severity") { Arity = ArgumentArity.ZeroOrOne }.FromAmong(SeverityLevels)
- },
- new Option(new[] { "--fix-analyzers", "-a" }, Resources.Run_3rd_party_analyzers_and_apply_fixes)
+ ArgumentHelpName = "severity"
+ }.FromAmong(SeverityLevels),
+ new Option(new[] { "--fix-analyzers", "-a" }, Resources.Run_3rd_party_analyzers_and_apply_fixes, argumentType: typeof(string), arity: ArgumentArity.ZeroOrOne)
{
- Argument = new Argument("severity") { Arity = ArgumentArity.ZeroOrOne }.FromAmong(SeverityLevels)
- },
- new Option(new[] { "--diagnostics" }, Resources.A_space_separated_list_of_diagnostic_ids_to_use_as_a_filter_when_fixing_code_style_or_3rd_party_issues)
+ ArgumentHelpName = "severity"
+ }.FromAmong(SeverityLevels),
+ new Option(new[] { "--diagnostics" }, () => Array.Empty(), Resources.A_space_separated_list_of_diagnostic_ids_to_use_as_a_filter_when_fixing_code_style_or_3rd_party_issues),
+ new Option(new[] { "--include" }, () => Array.Empty(), Resources.A_list_of_relative_file_or_folder_paths_to_include_in_formatting_All_files_are_formatted_if_empty),
+ new Option(new[] { "--exclude" }, () => Array.Empty(), Resources.A_list_of_relative_file_or_folder_paths_to_exclude_from_formatting),
+ new Option(new[] { "--check" }, Resources.Formats_files_without_saving_changes_to_disk_Terminates_with_a_non_zero_exit_code_if_any_files_were_formatted),
+ new Option(new[] { "--report" }, Resources.Accepts_a_file_path_which_if_provided_will_produce_a_format_report_json_file_in_the_given_directory, argumentType: typeof(string), arity: ArgumentArity.ZeroOrOne)
{
- Argument = new Argument(() => Array.Empty())
- },
- new Option(new[] { "--include" }, Resources.A_list_of_relative_file_or_folder_paths_to_include_in_formatting_All_files_are_formatted_if_empty)
- {
- Argument = new Argument(() => Array.Empty())
- },
- new Option(new[] { "--exclude" }, Resources.A_list_of_relative_file_or_folder_paths_to_exclude_from_formatting)
- {
- Argument = new Argument(() => Array.Empty())
- },
- new Option(new[] { "--check" }, Resources.Formats_files_without_saving_changes_to_disk_Terminates_with_a_non_zero_exit_code_if_any_files_were_formatted),
- new Option(new[] { "--report" }, Resources.Accepts_a_file_path_which_if_provided_will_produce_a_format_report_json_file_in_the_given_directory)
- {
- Argument = new Argument(() => null) { Name = "report-path" }.LegalFilePathsOnly()
- },
- new Option(new[] { "--verbosity", "-v" }, Resources.Set_the_verbosity_level_Allowed_values_are_quiet_minimal_normal_detailed_and_diagnostic)
- {
- Argument = new Argument() { Arity = ArgumentArity.ExactlyOne }.FromAmong(VerbosityLevels)
- },
- new Option(new[] { "--include-generated" }, Resources.Include_generated_code_files_in_formatting_operations)
+ ArgumentHelpName = "report-path"
+ }.LegalFilePathsOnly(),
+ new Option(new[] { "--verbosity", "-v" }, Resources.Set_the_verbosity_level_Allowed_values_are_quiet_minimal_normal_detailed_and_diagnostic).FromAmong(VerbosityLevels),
+ new Option(new[] { "--include-generated" }, Resources.Include_generated_code_files_in_formatting_operations)
{
IsHidden = true
},
- new Option(new[] { "--binarylog" }, Resources.Log_all_project_or_solution_load_information_to_a_binary_log_file)
+ new Option(new[] { "--binarylog" }, Resources.Log_all_project_or_solution_load_information_to_a_binary_log_file, argumentType: typeof(string), arity: ArgumentArity.ZeroOrOne)
{
- Argument = new Argument(() => null) { Name = "binary-log-path", Arity = ArgumentArity.ZeroOrOne }.LegalFilePathsOnly()
- },
+ ArgumentHelpName = "binary-log-path"
+ }.LegalFilePathsOnly(),
};
rootCommand.Description = "dotnet-format";
@@ -95,8 +80,8 @@ internal static RootCommand CreateCommandLineOptions()
internal static string? EnsureFolderNotSpecifiedWhenFixingAnalyzers(CommandResult symbolResult)
{
- var folder = symbolResult.ValueForOption("--folder");
- var fixAnalyzers = symbolResult.OptionResult("--fix-analyzers");
+ var folder = symbolResult.GetValueForOption("--folder");
+ var fixAnalyzers = symbolResult.GetOptionResult("--fix-analyzers");
return folder && fixAnalyzers != null
? Resources.Cannot_specify_the_folder_option_when_running_analyzers
: null;
@@ -104,8 +89,8 @@ internal static RootCommand CreateCommandLineOptions()
internal static string? EnsureFolderNotSpecifiedWhenFixingStyle(CommandResult symbolResult)
{
- var folder = symbolResult.ValueForOption("--folder");
- var fixStyle = symbolResult.OptionResult("--fix-style");
+ var folder = symbolResult.GetValueForOption("--folder");
+ var fixStyle = symbolResult.GetOptionResult("--fix-style");
return folder && fixStyle != null
? Resources.Cannot_specify_the_folder_option_when_fixing_style
: null;
@@ -113,8 +98,8 @@ internal static RootCommand CreateCommandLineOptions()
internal static string? EnsureFolderNotSpecifiedWithNoRestore(CommandResult symbolResult)
{
- var folder = symbolResult.ValueForOption("--folder");
- var noRestore = symbolResult.OptionResult("--no-restore");
+ var folder = symbolResult.GetValueForOption("--folder");
+ var noRestore = symbolResult.GetOptionResult("--no-restore");
return folder && noRestore != null
? Resources.Cannot_specify_the_folder_option_with_no_restore
: null;
@@ -122,13 +107,30 @@ internal static RootCommand CreateCommandLineOptions()
internal static string? EnsureFolderNotSpecifiedWhenLoggingBinlog(CommandResult symbolResult)
{
- var folder = symbolResult.ValueForOption("--folder");
- var binarylog = symbolResult.OptionResult("--binarylog");
+ var folder = symbolResult.GetValueForOption("--folder");
+ var binarylog = symbolResult.GetOptionResult("--binarylog");
return folder && binarylog is not null && !binarylog.IsImplicit
? Resources.Cannot_specify_the_folder_option_when_writing_a_binary_log
: null;
}
+ internal static OptionResult? GetOptionResult(this CommandResult result, string alias)
+ {
+ return result.Children.GetByAlias(alias) as OptionResult;
+ }
+
+ [return: MaybeNull]
+ internal static T GetValueForOption(this CommandResult result, string alias)
+ {
+ if (result.GetOptionResult(alias) is OptionResult option &&
+ option.GetValueOrDefault() is { } t)
+ {
+ return t;
+ };
+
+ return default;
+ }
+
internal static bool WasOptionUsed(this ParseResult result, params string[] aliases)
{
return result.Tokens
diff --git a/src/Program.cs b/src/Program.cs
index 87f266a07c..f7c3764f49 100644
--- a/src/Program.cs
+++ b/src/Program.cs
@@ -48,8 +48,8 @@ private static async Task Main(string[] args)
bool noRestore,
bool folder,
bool fixWhitespace,
- string? fixStyle,
- string? fixAnalyzers,
+ string fixStyle,
+ string fixAnalyzers,
string[] diagnostics,
string? verbosity,
bool check,
@@ -173,8 +173,8 @@ private static async Task Main(string[] args)
noRestore,
logLevel,
fixType,
- codeStyleSeverity: GetSeverity(fixStyle ?? FixSeverity.Error),
- analyzerSeverity: GetSeverity(fixAnalyzers ?? FixSeverity.Error),
+ codeStyleSeverity: GetSeverity(fixStyle),
+ analyzerSeverity: GetSeverity(fixAnalyzers),
diagnostics: diagnostics.ToImmutableHashSet(),
saveFormattedFiles: !check,
changesAreErrors: check,
@@ -312,6 +312,7 @@ internal static DiagnosticSeverity GetSeverity(string? severity)
{
return severity?.ToLowerInvariant() switch
{
+ "" => DiagnosticSeverity.Error,
FixSeverity.Error => DiagnosticSeverity.Error,
FixSeverity.Warn => DiagnosticSeverity.Warning,
FixSeverity.Info => DiagnosticSeverity.Info,
diff --git a/tests/Analyzers/ThirdPartyAnalyzerFormatterTests.cs b/tests/Analyzers/ThirdPartyAnalyzerFormatterTests.cs
index fd993d4ea8..7565061e61 100644
--- a/tests/Analyzers/ThirdPartyAnalyzerFormatterTests.cs
+++ b/tests/Analyzers/ThirdPartyAnalyzerFormatterTests.cs
@@ -45,6 +45,8 @@ public async Task InitializeAsync()
MSBuildRegistrar.RegisterInstance();
var analyzerWorkspace = await MSBuildWorkspaceLoader.LockedLoadAsync(workspacePath, WorkspaceType.Project, binaryLogPath: null, logWorkspaceWarnings: true, logger, CancellationToken.None);
+ TestOutputHelper.WriteLine(logger.GetLog());
+
// From this project we can get valid AnalyzerReferences to add to our test project.
_analyzerReferencesProject = analyzerWorkspace.CurrentSolution.Projects.Single();
}
diff --git a/tests/ProgramTests.cs b/tests/ProgramTests.cs
index b930bc6edc..18a59606e6 100644
--- a/tests/ProgramTests.cs
+++ b/tests/ProgramTests.cs
@@ -59,17 +59,17 @@ public void CommandLine_OptionsAreParsedCorrectly()
Assert.Equal(0, result.Errors.Count);
Assert.Equal(0, result.UnmatchedTokens.Count);
Assert.Equal(0, result.UnparsedTokens.Count);
- Assert.True(result.ValueForOption("folder"));
- Assert.Collection(result.ValueForOption>("include"),
+ Assert.True(result.ValueForOption("--folder"));
+ Assert.Collection(result.ValueForOption>("--include"),
i0 => Assert.Equal("include1", i0),
i1 => Assert.Equal("include2", i1));
- Assert.Collection(result.ValueForOption>("exclude"),
+ Assert.Collection(result.ValueForOption>("--exclude"),
i0 => Assert.Equal("exclude1", i0),
i1 => Assert.Equal("exclude2", i1));
- Assert.True(result.ValueForOption("check"));
- Assert.Equal("report", result.ValueForOption("report"));
- Assert.Equal("detailed", result.ValueForOption("verbosity"));
- Assert.True(result.ValueForOption("include-generated"));
+ Assert.True(result.ValueForOption("--check"));
+ Assert.Equal("report", result.ValueForOption("--report"));
+ Assert.Equal("detailed", result.ValueForOption("--verbosity"));
+ Assert.True(result.ValueForOption("--include-generated"));
}
[Fact]
@@ -83,7 +83,7 @@ public void CommandLine_ProjectArgument_Simple()
// Assert
Assert.Equal(0, result.Errors.Count);
- Assert.Equal("workspaceValue", result.CommandResult.GetArgumentValueOrDefault("workspace"));
+ Assert.Equal("workspaceValue", result.ValueForArgument("workspace"));
}
[Fact]
@@ -97,8 +97,8 @@ public void CommandLine_ProjectArgument_WithOption_AfterArgument()
// Assert
Assert.Equal(0, result.Errors.Count);
- Assert.Equal("workspaceValue", result.CommandResult.GetArgumentValueOrDefault("workspace"));
- Assert.Equal("detailed", result.ValueForOption("verbosity"));
+ Assert.Equal("workspaceValue", result.ValueForArgument("workspace"));
+ Assert.Equal("detailed", result.ValueForOption("--verbosity"));
}
[Fact]
@@ -112,8 +112,8 @@ public void CommandLine_ProjectArgument_WithOption_BeforeArgument()
// Assert
Assert.Equal(0, result.Errors.Count);
- Assert.Equal("workspaceValue", result.CommandResult.GetArgumentValueOrDefault("workspace"));
- Assert.Equal("detailed", result.ValueForOption("verbosity"));
+ Assert.Equal("workspaceValue", result.ValueForArgument("workspace"));
+ Assert.Equal("detailed", result.ValueForOption("--verbosity"));
}
[Fact]
@@ -296,5 +296,44 @@ public void CommandLine_BinaryLog_FailsIfFolderIsSpecified()
// Assert
Assert.Equal(1, result.Errors.Count);
}
+
+ [Fact]
+ public void CommandLine_Diagnostics_FailsIfDiagnosticNoSpecified()
+ {
+ // Arrange
+ var sut = FormatCommand.CreateCommandLineOptions();
+
+ // Act
+ var result = sut.Parse(new[] { "--diagnostics" });
+
+ // Assert
+ Assert.Equal(1, result.Errors.Count);
+ }
+
+ [Fact]
+ public void CommandLine_Diagnostics_DoesNotFailIfDiagnosticIsSpecified()
+ {
+ // Arrange
+ var sut = FormatCommand.CreateCommandLineOptions();
+
+ // Act
+ var result = sut.Parse(new[] { "--diagnostics", "RS0016" });
+
+ // Assert
+ Assert.Equal(0, result.Errors.Count);
+ }
+
+ [Fact]
+ public void CommandLine_Diagnostics_DoesNotFailIfMultipleDiagnosticAreSpecified()
+ {
+ // Arrange
+ var sut = FormatCommand.CreateCommandLineOptions();
+
+ // Act
+ var result = sut.Parse(new[] { "--diagnostics", "RS0016", "RS0017", "RS0018" });
+
+ // Assert
+ Assert.Equal(0, result.Errors.Count);
+ }
}
}