From dbced62f51127d3f0586acada79de82a06c47118 Mon Sep 17 00:00:00 2001 From: moormaster Date: Fri, 28 Feb 2025 23:48:14 +0100 Subject: [PATCH] feat: enable jumping to "not formatted" files from VisualStudio error list - adds --msbuild-format parameter to format error message according to standard error/warning format of MSBuild. See https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-diagnostic-format-for-tasks?view=vs-2022 --- Src/CSharpier.Cli/CommandLineFormatter.cs | 15 ++++++++-- Src/CSharpier.Cli/CommandLineOptions.cs | 6 ++++ Src/CSharpier.Cli/ConsoleLogger.cs | 4 +-- Src/CSharpier.Cli/FileIssueLogger.cs | 22 +++++++++++++-- Src/CSharpier.Cli/Program.cs | 4 ++- .../build/CSharpier.MsBuild.targets | 4 +-- .../CommandLineFormatterTests.cs | 28 +++++++++++++++++-- 7 files changed, 69 insertions(+), 14 deletions(-) diff --git a/Src/CSharpier.Cli/CommandLineFormatter.cs b/Src/CSharpier.Cli/CommandLineFormatter.cs index bd14a4736..ecef51484 100644 --- a/Src/CSharpier.Cli/CommandLineFormatter.cs +++ b/Src/CSharpier.Cli/CommandLineFormatter.cs @@ -60,7 +60,8 @@ CancellationToken cancellationToken { var fileIssueLogger = new FileIssueLogger( commandLineOptions.OriginalDirectoryOrFilePaths[0], - logger + logger, + commandLineOptions.MsBuildFormat ); var printerOptions = optionsProvider.GetPrinterOptionsFor(filePath); @@ -231,7 +232,11 @@ await FormatPhysicalFile( } else if (warnForUnsupported) { - var fileIssueLogger = new FileIssueLogger(originalFilePath, logger); + var fileIssueLogger = new FileIssueLogger( + originalFilePath, + logger, + isMsBuildFormat: false + ); fileIssueLogger.WriteWarning("Is an unsupported file type."); } } @@ -307,7 +312,11 @@ CancellationToken cancellationToken cancellationToken ); - var fileIssueLogger = new FileIssueLogger(originalFilePath, logger); + var fileIssueLogger = new FileIssueLogger( + originalFilePath, + logger, + commandLineOptions.MsBuildFormat + ); logger.LogDebug( commandLineOptions.Check diff --git a/Src/CSharpier.Cli/CommandLineOptions.cs b/Src/CSharpier.Cli/CommandLineOptions.cs index 1ed067ca0..e3ccdab42 100644 --- a/Src/CSharpier.Cli/CommandLineOptions.cs +++ b/Src/CSharpier.Cli/CommandLineOptions.cs @@ -7,6 +7,7 @@ internal class CommandLineOptions { public string[] DirectoryOrFilePaths { get; init; } = []; public bool Check { get; init; } + public bool MsBuildFormat { get; init; } public bool Fast { get; init; } public bool SkipWrite { get; init; } public bool WriteStdout { get; init; } @@ -21,6 +22,7 @@ internal class CommandLineOptions internal delegate Task Handler( string[] directoryOrFile, bool check, + bool msBuildFormat, bool fast, bool skipWrite, bool writeStdout, @@ -52,6 +54,10 @@ public static RootCommand Create() () => LogLevel.Information.ToString(), "Specify the log level - Debug, Information (default), Warning, Error, None" ), + new Option( + ["--msbuild-format"], + "Formats messages in standard error/warning format for MSBuild." + ), new Option( ["--no-cache"], "Bypass the cache to determine if a file needs to be formatted." diff --git a/Src/CSharpier.Cli/ConsoleLogger.cs b/Src/CSharpier.Cli/ConsoleLogger.cs index aa314d505..864e1f6ce 100644 --- a/Src/CSharpier.Cli/ConsoleLogger.cs +++ b/Src/CSharpier.Cli/ConsoleLogger.cs @@ -2,7 +2,7 @@ namespace CSharpier.Cli; -internal class ConsoleLogger(IConsole console, LogLevel loggingLevel) : ILogger +internal class ConsoleLogger(IConsole console, LogLevel loggingLevel, bool isMsBuildFormat) : ILogger { private static readonly object ConsoleLock = new(); @@ -52,7 +52,7 @@ void WriteLine(string? value = null) { var message = formatter(state, exception!); - if (logLevel >= LogLevel.Warning) + if (!isMsBuildFormat && logLevel >= LogLevel.Warning) { console.ForegroundColor = GetColorLevel(logLevel); Write($"{logLevel} "); diff --git a/Src/CSharpier.Cli/FileIssueLogger.cs b/Src/CSharpier.Cli/FileIssueLogger.cs index a3fc96994..ffdedadbb 100644 --- a/Src/CSharpier.Cli/FileIssueLogger.cs +++ b/Src/CSharpier.Cli/FileIssueLogger.cs @@ -2,11 +2,29 @@ namespace CSharpier.Cli; -internal class FileIssueLogger(string filePath, ILogger logger) +internal class FileIssueLogger(string filePath, ILogger logger, bool isMsBuildFormat) { + static string FormatMsBuildError(LogState logState, Exception? exception) => + $"{logState.Path}: error: {logState.Message}"; + + record class LogState + { + public required string Path; + public required string Message; + } + public void WriteError(string value, Exception? exception = null) { - logger.LogError(exception, $"{this.GetPath()} - {value}"); + if (isMsBuildFormat) + { + var logState = new LogState() { Path = this.GetPath(), Message = value }; + + logger.Log(LogLevel.Error, 0, logState, exception, FormatMsBuildError); + } + else + { + logger.LogError(exception, $"{this.GetPath()} - {value}"); + } } public void WriteWarning(string value) diff --git a/Src/CSharpier.Cli/Program.cs b/Src/CSharpier.Cli/Program.cs index ca941719e..e3f7ea487 100644 --- a/Src/CSharpier.Cli/Program.cs +++ b/Src/CSharpier.Cli/Program.cs @@ -23,6 +23,7 @@ public static async Task Main(string[] args) public static async Task Run( string[]? directoryOrFile, bool check, + bool msBuildFormat, bool fast, bool skipWrite, bool writeStdout, @@ -42,7 +43,7 @@ CancellationToken cancellationToken var actualConfigPath = string.IsNullOrEmpty(configPath) ? null : configPath; var console = new SystemConsole(); - var logger = new ConsoleLogger(console, logLevel); + var logger = new ConsoleLogger(console, logLevel, msBuildFormat); if (pipeMultipleFiles) { @@ -89,6 +90,7 @@ CancellationToken cancellationToken OriginalDirectoryOrFilePaths = originalDirectoryOrFile!, StandardInFileContents = standardInFileContents, Check = check, + MsBuildFormat = msBuildFormat, NoCache = noCache, NoMSBuildCheck = noMSBuildCheck, Fast = fast, diff --git a/Src/CSharpier.MsBuild/build/CSharpier.MsBuild.targets b/Src/CSharpier.MsBuild/build/CSharpier.MsBuild.targets index 0fc959dbd..f01c58649 100644 --- a/Src/CSharpier.MsBuild/build/CSharpier.MsBuild.targets +++ b/Src/CSharpier.MsBuild/build/CSharpier.MsBuild.targets @@ -43,9 +43,7 @@ StdOutEncoding="utf-8" StdErrEncoding="utf-8" IgnoreExitCode="true" - IgnoreStandardErrorWarningFormat="true" - CustomErrorRegularExpression="^Error " - Command=""$(CSharpier_dotnet_Path)" exec "$(CSharpierDllPath)" $(CSharpierArgs) --no-msbuild-check --compilation-errors-as-warnings "$(MSBuildProjectDirectory)" > $(NullOutput) " + Command=""$(CSharpier_dotnet_Path)" exec "$(CSharpierDllPath)" $(CSharpierArgs) --msbuild-format --no-msbuild-check --compilation-errors-as-warnings "$(MSBuildProjectDirectory)" > $(NullOutput) " />