From 7e4220898ba214c4bf308beb2828953b3d03f38b Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 16 Dec 2023 01:43:12 +0100 Subject: [PATCH 1/5] slight rejig of CustomLogging module and adding logic from #176 back to the Microsoft.Extensions.Logging branch. --- CHANGELOG.md | 1 + src/FSharp.Analyzers.Cli/CustomLogging.fs | 66 +++++++++++++++-------- src/FSharp.Analyzers.Cli/Program.fs | 44 +++++++++------ 3 files changed, 71 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af5556b..cc71dfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed * [Add path to ASTCollecting](https://github.com/ionide/FSharp.Analyzers.SDK/pull/171) (thanks @nojaf!) * [Use Microsoft.Extensions.Logging instead of printf based logging infrastructure](https://github.com/ionide/FSharp.Analyzers.SDK/pull/175) (thanks @dawedawe!) +* [Console finer colorized pretty printing and link to analyzer URI](https://github.com/ionide/FSharp.Analyzers.SDK/pull/177) (thanks @smoothdeveloper!) ## [0.21.0] - 2023-11-22 diff --git a/src/FSharp.Analyzers.Cli/CustomLogging.fs b/src/FSharp.Analyzers.Cli/CustomLogging.fs index 60011d7..8493001 100644 --- a/src/FSharp.Analyzers.Cli/CustomLogging.fs +++ b/src/FSharp.Analyzers.Cli/CustomLogging.fs @@ -8,20 +8,59 @@ open Microsoft.Extensions.Logging.Console open Microsoft.Extensions.Logging.Abstractions open Microsoft.Extensions.Options +module AnsiColorHelpers = + let private initialConsoleColor = Console.ForegroundColor + // see https://learn.microsoft.com/en-us/dotnet/core/extensions/console-log-formatter#implement-custom-color-formatting + let private ansiForegroundEscapeCodeOfColorConsole color = + match color with + | ConsoleColor.Black -> "\x1B[30m" + | ConsoleColor.DarkRed -> "\x1B[31m" + | ConsoleColor.DarkGreen -> "\x1B[32m" + | ConsoleColor.DarkYellow -> "\x1B[33m" + | ConsoleColor.DarkBlue -> "\x1B[34m" + | ConsoleColor.DarkMagenta -> "\x1B[35m" + | ConsoleColor.DarkCyan -> "\x1B[36m" + | ConsoleColor.Gray -> "\x1B[37m" + | ConsoleColor.Red -> "\x1B[1m\x1B[31m" + | ConsoleColor.Green -> "\x1B[1m\x1B[32m" + | ConsoleColor.Yellow -> "\x1B[1m\x1B[33m" + | ConsoleColor.Blue -> "\x1B[1m\x1B[34m" + | ConsoleColor.Magenta -> "\x1B[1m\x1B[35m" + | ConsoleColor.Cyan -> "\x1B[1m\x1B[36m" + | ConsoleColor.White -> "\x1B[1m\x1B[37m" + | _ -> + #if DEBUG + failwith $"didn't implement ansi code for color: {color}" + #else + // do not break code analyzis to wrong runtime color or such thing for release + "\x1B[37m" // ConsoleColor.Gray + #endif + + let consoleColorOfLogLevel logLevel = + match logLevel with + | LogLevel.Error -> ConsoleColor.Red + | LogLevel.Warning ->ConsoleColor.DarkYellow + | LogLevel.Information -> ConsoleColor.Blue + | LogLevel.Trace -> ConsoleColor.Cyan + | _ -> ConsoleColor.Gray + + let formatMessageAsAnsiColorizedString (color: ConsoleColor) (message: string) = + $"{ansiForegroundEscapeCodeOfColorConsole color}{message}{ansiForegroundEscapeCodeOfColorConsole initialConsoleColor}" + type CustomOptions() = inherit ConsoleFormatterOptions() /// if true: no LogLevel as prefix, colored output according to LogLevel /// if false: LogLevel as prefix, no colored output member val UseAnalyzersMsgStyle = false with get, set + member x.UseColoredOutput = x.UseAnalyzersMsgStyle + member x.UseLogLevelAsPrefix = not x.UseAnalyzersMsgStyle type CustomFormatter(options: IOptionsMonitor) as this = inherit ConsoleFormatter("customName") let mutable optionsReloadToken: IDisposable = null let mutable formatterOptions = options.CurrentValue - let origColor = Console.ForegroundColor - do optionsReloadToken <- options.OnChange(fun x -> this.ReloadLoggerOptions(x)) member private _.ReloadLoggerOptions(opts: CustomOptions) = formatterOptions <- opts @@ -34,14 +73,9 @@ type CustomFormatter(options: IOptionsMonitor) as this = ) = let message = logEntry.Formatter.Invoke(logEntry.State, logEntry.Exception) - - if formatterOptions.UseAnalyzersMsgStyle then - this.SetColor(textWriter, logEntry.LogLevel) - textWriter.WriteLine(message) - this.ResetColor() - else + if formatterOptions.UseLogLevelAsPrefix then this.WritePrefix(textWriter, logEntry.LogLevel) - textWriter.WriteLine(message) + textWriter.WriteLine message member private _.WritePrefix(textWriter: TextWriter, logLevel: LogLevel) = match logLevel with @@ -53,20 +87,6 @@ type CustomFormatter(options: IOptionsMonitor) as this = | LogLevel.Critical -> textWriter.Write("critical: ") | _ -> () - // see https://learn.microsoft.com/en-us/dotnet/core/extensions/console-log-formatter - member private _.SetColor(textWriter: TextWriter, logLevel: LogLevel) = - let color = - match logLevel with - | LogLevel.Error -> "\x1B[1m\x1B[31m" // ConsoleColor.Red - | LogLevel.Warning -> "\x1B[33m" // ConsoleColor.DarkYellow - | LogLevel.Information -> "\x1B[1m\x1B[34m" // ConsoleColor.Blue - | LogLevel.Trace -> "\x1B[1m\x1B[36m" // ConsoleColor.Cyan - | _ -> "\x1B[37m" // ConsoleColor.Gray - - textWriter.Write(color) - - member private _.ResetColor() = Console.ForegroundColor <- origColor - interface IDisposable with member _.Dispose() = optionsReloadToken.Dispose() diff --git a/src/FSharp.Analyzers.Cli/Program.fs b/src/FSharp.Analyzers.Cli/Program.fs index 38e6705..35bc685 100644 --- a/src/FSharp.Analyzers.Cli/Program.fs +++ b/src/FSharp.Analyzers.Cli/Program.fs @@ -6,12 +6,13 @@ open System.Text.RegularExpressions open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Text open Argu -open FSharp.Analyzers.SDK open GlobExpressions open Microsoft.CodeAnalysis.Sarif open Microsoft.CodeAnalysis.Sarif.Writers open Microsoft.Extensions.Logging open Ionide.ProjInfo +open FSharp.Analyzers.SDK +open FSharp.Analyzers.Cli open FSharp.Analyzers.Cli.CustomLogging type Arguments = @@ -252,23 +253,32 @@ let printMessages (msgs: AnalyzerMessage list) = let msgLogger = factory.CreateLogger("") - msgs - |> Seq.iter (fun analyzerMessage -> - let m = analyzerMessage.Message + let useAnsiColorCodes = true + let colorFormat color message = + if useAnsiColorCodes then + CustomLogging.AnsiColorHelpers.formatMessageAsAnsiColorizedString color message + else + message - msgLogger.Log( - severityToLogLevel[m.Severity], - "{0}({1},{2}): {3} {4} - {5}", - m.Range.FileName, - m.Range.StartLine, - m.Range.StartColumn, - (m.Severity.ToString()), - m.Code, - m.Message - ) - ) - - () + for analyzerMessage in msgs do + let m = analyzerMessage.Message + let logLevel = severityToLogLevel[m.Severity] + let messageFormat, messageArgs = + let baseArgs : obj array = + [| + m.Range.FileName + m.Range.StartLine + m.Range.StartColumn + colorFormat (CustomLogging.AnsiColorHelpers.consoleColorOfLogLevel logLevel) (m.Severity.ToString()) + colorFormat (CustomLogging.AnsiColorHelpers.consoleColorOfLogLevel logLevel) m.Code + m.Message + |] + let baseFormat = "{0}({1},{2}): {3} {4} - {5}" + match analyzerMessage.HelpUri with + | None -> baseFormat, baseArgs + | Some uri -> baseFormat + " {6}", [|yield! baseArgs; colorFormat ConsoleColor.Cyan uri|] + + msgLogger.Log(logLevel, messageFormat, messageArgs) let writeReport (results: AnalyzerMessage list option) (codeRoot: string option) (report: string) = try From 5abbdb0782bec5c3a7a2f663d60b9a34188619f6 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 16 Dec 2023 01:57:33 +0100 Subject: [PATCH 2/5] PR link in changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc71dfb..0df9dd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). * [Add path to ASTCollecting](https://github.com/ionide/FSharp.Analyzers.SDK/pull/171) (thanks @nojaf!) * [Use Microsoft.Extensions.Logging instead of printf based logging infrastructure](https://github.com/ionide/FSharp.Analyzers.SDK/pull/175) (thanks @dawedawe!) * [Console finer colorized pretty printing and link to analyzer URI](https://github.com/ionide/FSharp.Analyzers.SDK/pull/177) (thanks @smoothdeveloper!) +* [Console finer colorized pretty printing and link to analyzer URI](https://github.com/ionide/FSharp.Analyzers.SDK/pull/180) (thanks @smoothdeveloper!) ## [0.21.0] - 2023-11-22 From 6c057a60be70263a5477a5d18eeebb7d68d76f2a Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Tue, 19 Dec 2023 04:13:36 +0100 Subject: [PATCH 3/5] address review --- src/FSharp.Analyzers.Cli/CustomLogging.fs | 1 - src/FSharp.Analyzers.Cli/Program.fs | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/FSharp.Analyzers.Cli/CustomLogging.fs b/src/FSharp.Analyzers.Cli/CustomLogging.fs index 8493001..465a1f0 100644 --- a/src/FSharp.Analyzers.Cli/CustomLogging.fs +++ b/src/FSharp.Analyzers.Cli/CustomLogging.fs @@ -53,7 +53,6 @@ type CustomOptions() = /// if true: no LogLevel as prefix, colored output according to LogLevel /// if false: LogLevel as prefix, no colored output member val UseAnalyzersMsgStyle = false with get, set - member x.UseColoredOutput = x.UseAnalyzersMsgStyle member x.UseLogLevelAsPrefix = not x.UseAnalyzersMsgStyle type CustomFormatter(options: IOptionsMonitor) as this = diff --git a/src/FSharp.Analyzers.Cli/Program.fs b/src/FSharp.Analyzers.Cli/Program.fs index 35bc685..0ab2080 100644 --- a/src/FSharp.Analyzers.Cli/Program.fs +++ b/src/FSharp.Analyzers.Cli/Program.fs @@ -253,12 +253,8 @@ let printMessages (msgs: AnalyzerMessage list) = let msgLogger = factory.CreateLogger("") - let useAnsiColorCodes = true let colorFormat color message = - if useAnsiColorCodes then CustomLogging.AnsiColorHelpers.formatMessageAsAnsiColorizedString color message - else - message for analyzerMessage in msgs do let m = analyzerMessage.Message From b1fce929e18404aa2c686bc07a062ae47fcf57a1 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Tue, 19 Dec 2023 04:16:08 +0100 Subject: [PATCH 4/5] fantomas run (note that there seems to be a change on a line I didn't touch in my PR AFAIR) --- src/FSharp.Analyzers.Cli/CustomLogging.fs | 48 ++++++++++++----------- src/FSharp.Analyzers.Cli/Program.fs | 7 +++- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/FSharp.Analyzers.Cli/CustomLogging.fs b/src/FSharp.Analyzers.Cli/CustomLogging.fs index 465a1f0..2be2d9e 100644 --- a/src/FSharp.Analyzers.Cli/CustomLogging.fs +++ b/src/FSharp.Analyzers.Cli/CustomLogging.fs @@ -13,39 +13,39 @@ module AnsiColorHelpers = // see https://learn.microsoft.com/en-us/dotnet/core/extensions/console-log-formatter#implement-custom-color-formatting let private ansiForegroundEscapeCodeOfColorConsole color = match color with - | ConsoleColor.Black -> "\x1B[30m" - | ConsoleColor.DarkRed -> "\x1B[31m" - | ConsoleColor.DarkGreen -> "\x1B[32m" - | ConsoleColor.DarkYellow -> "\x1B[33m" - | ConsoleColor.DarkBlue -> "\x1B[34m" + | ConsoleColor.Black -> "\x1B[30m" + | ConsoleColor.DarkRed -> "\x1B[31m" + | ConsoleColor.DarkGreen -> "\x1B[32m" + | ConsoleColor.DarkYellow -> "\x1B[33m" + | ConsoleColor.DarkBlue -> "\x1B[34m" | ConsoleColor.DarkMagenta -> "\x1B[35m" - | ConsoleColor.DarkCyan -> "\x1B[36m" - | ConsoleColor.Gray -> "\x1B[37m" - | ConsoleColor.Red -> "\x1B[1m\x1B[31m" - | ConsoleColor.Green -> "\x1B[1m\x1B[32m" - | ConsoleColor.Yellow -> "\x1B[1m\x1B[33m" - | ConsoleColor.Blue -> "\x1B[1m\x1B[34m" - | ConsoleColor.Magenta -> "\x1B[1m\x1B[35m" - | ConsoleColor.Cyan -> "\x1B[1m\x1B[36m" - | ConsoleColor.White -> "\x1B[1m\x1B[37m" - | _ -> - #if DEBUG + | ConsoleColor.DarkCyan -> "\x1B[36m" + | ConsoleColor.Gray -> "\x1B[37m" + | ConsoleColor.Red -> "\x1B[1m\x1B[31m" + | ConsoleColor.Green -> "\x1B[1m\x1B[32m" + | ConsoleColor.Yellow -> "\x1B[1m\x1B[33m" + | ConsoleColor.Blue -> "\x1B[1m\x1B[34m" + | ConsoleColor.Magenta -> "\x1B[1m\x1B[35m" + | ConsoleColor.Cyan -> "\x1B[1m\x1B[36m" + | ConsoleColor.White -> "\x1B[1m\x1B[37m" + | _ -> +#if DEBUG failwith $"didn't implement ansi code for color: {color}" - #else +#else // do not break code analyzis to wrong runtime color or such thing for release - "\x1B[37m" // ConsoleColor.Gray - #endif - + "\x1B[37m" // ConsoleColor.Gray +#endif + let consoleColorOfLogLevel logLevel = match logLevel with - | LogLevel.Error -> ConsoleColor.Red - | LogLevel.Warning ->ConsoleColor.DarkYellow + | LogLevel.Error -> ConsoleColor.Red + | LogLevel.Warning -> ConsoleColor.DarkYellow | LogLevel.Information -> ConsoleColor.Blue | LogLevel.Trace -> ConsoleColor.Cyan | _ -> ConsoleColor.Gray let formatMessageAsAnsiColorizedString (color: ConsoleColor) (message: string) = - $"{ansiForegroundEscapeCodeOfColorConsole color}{message}{ansiForegroundEscapeCodeOfColorConsole initialConsoleColor}" + $"{ansiForegroundEscapeCodeOfColorConsole color}{message}{ansiForegroundEscapeCodeOfColorConsole initialConsoleColor}" type CustomOptions() = inherit ConsoleFormatterOptions() @@ -72,8 +72,10 @@ type CustomFormatter(options: IOptionsMonitor) as this = ) = let message = logEntry.Formatter.Invoke(logEntry.State, logEntry.Exception) + if formatterOptions.UseLogLevelAsPrefix then this.WritePrefix(textWriter, logEntry.LogLevel) + textWriter.WriteLine message member private _.WritePrefix(textWriter: TextWriter, logLevel: LogLevel) = diff --git a/src/FSharp.Analyzers.Cli/Program.fs b/src/FSharp.Analyzers.Cli/Program.fs index 0ab2080..8cc78cd 100644 --- a/src/FSharp.Analyzers.Cli/Program.fs +++ b/src/FSharp.Analyzers.Cli/Program.fs @@ -259,8 +259,9 @@ let printMessages (msgs: AnalyzerMessage list) = for analyzerMessage in msgs do let m = analyzerMessage.Message let logLevel = severityToLogLevel[m.Severity] + let messageFormat, messageArgs = - let baseArgs : obj array = + let baseArgs: obj array = [| m.Range.FileName m.Range.StartLine @@ -269,10 +270,12 @@ let printMessages (msgs: AnalyzerMessage list) = colorFormat (CustomLogging.AnsiColorHelpers.consoleColorOfLogLevel logLevel) m.Code m.Message |] + let baseFormat = "{0}({1},{2}): {3} {4} - {5}" + match analyzerMessage.HelpUri with | None -> baseFormat, baseArgs - | Some uri -> baseFormat + " {6}", [|yield! baseArgs; colorFormat ConsoleColor.Cyan uri|] + | Some uri -> baseFormat + " {6}", [| yield! baseArgs; colorFormat ConsoleColor.Cyan uri |] msgLogger.Log(logLevel, messageFormat, messageArgs) From fdd36a12c75a9327b210b6d60ccc51e65dc1e9d4 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Tue, 19 Dec 2023 04:33:13 +0100 Subject: [PATCH 5/5] fix changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0df9dd8..9f10d3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed * [Add path to ASTCollecting](https://github.com/ionide/FSharp.Analyzers.SDK/pull/171) (thanks @nojaf!) * [Use Microsoft.Extensions.Logging instead of printf based logging infrastructure](https://github.com/ionide/FSharp.Analyzers.SDK/pull/175) (thanks @dawedawe!) -* [Console finer colorized pretty printing and link to analyzer URI](https://github.com/ionide/FSharp.Analyzers.SDK/pull/177) (thanks @smoothdeveloper!) * [Console finer colorized pretty printing and link to analyzer URI](https://github.com/ionide/FSharp.Analyzers.SDK/pull/180) (thanks @smoothdeveloper!) ## [0.21.0] - 2023-11-22