From bdc88651b8646cbb02ea9a7f2c7d4e042d781430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=8D=E1=B4=9C=C7=AB=C9=AA=E1=B4=9C=20=CA=9C=E1=B4=80?= =?UTF-8?q?=C9=B4=20=28=E9=9F=A9=E6=9A=AE=E7=A7=8B=29?= Date: Tue, 27 Aug 2024 18:05:23 +0800 Subject: [PATCH] Diagnostics: Clearer information style (#17488) --- src/Compiler/Driver/CompilerDiagnostics.fs | 61 +++++++++++++++++-- src/Compiler/Driver/CompilerDiagnostics.fsi | 3 +- src/Compiler/Facilities/DiagnosticsLogger.fs | 3 +- src/Compiler/Facilities/DiagnosticsLogger.fsi | 3 +- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Driver/CompilerDiagnostics.fs b/src/Compiler/Driver/CompilerDiagnostics.fs index b722fae4437..df5a27cabbe 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fs +++ b/src/Compiler/Driver/CompilerDiagnostics.fs @@ -2044,6 +2044,7 @@ type FormattedDiagnosticDetailedInfo = Location: FormattedDiagnosticLocation option Canonical: FormattedDiagnosticCanonicalInformation Message: string + Context: string option } [] @@ -2051,7 +2052,7 @@ type FormattedDiagnostic = | Short of FSharpDiagnosticSeverity * string | Long of FSharpDiagnosticSeverity * FormattedDiagnosticDetailedInfo -let FormatDiagnosticLocation (tcConfig: TcConfig) m : FormattedDiagnosticLocation = +let FormatDiagnosticLocation (tcConfig: TcConfig) (m: Range) : FormattedDiagnosticLocation = if equals m rangeStartup || equals m rangeCmdArgs then { Range = m @@ -2114,6 +2115,10 @@ let FormatDiagnosticLocation (tcConfig: TcConfig) m : FormattedDiagnosticLocatio sprintf "%s(%d,%d,%d,%d): " file m.StartLine m.StartColumn m.EndLine m.EndColumn, m, file else "", m, file + | DiagnosticStyle.Rich -> + let file = file.Replace('/', Path.DirectorySeparatorChar) + let m = withStart (mkPos m.StartLine (m.StartColumn + 1)) m + (sprintf "◦→ %s (%d,%d)" file m.StartLine m.StartColumn), m, file { Range = m @@ -2154,8 +2159,12 @@ let CollectFormattedDiagnostics (tcConfig: TcConfig, severity: FSharpDiagnosticS let text = match tcConfig.diagnosticStyle with // Show the subcategory for --vserrors so that we can fish it out in Visual Studio and use it to determine error stickiness. + | DiagnosticStyle.Emacs + | DiagnosticStyle.Gcc + | DiagnosticStyle.Default + | DiagnosticStyle.Test -> sprintf "%s FS%04d: " message errorNumber | DiagnosticStyle.VisualStudio -> sprintf "%s %s FS%04d: " subcategory message errorNumber - | _ -> sprintf "%s FS%04d: " message errorNumber + | DiagnosticStyle.Rich -> sprintf "\n◦→ %s FS%04d: " message errorNumber let canonical: FormattedDiagnosticCanonicalInformation = { @@ -2164,11 +2173,51 @@ let CollectFormattedDiagnostics (tcConfig: TcConfig, severity: FSharpDiagnosticS TextRepresentation = text } - let message = diagnostic.FormatCore(tcConfig.flatErrors, suggestNames) + let message = + match tcConfig.diagnosticStyle with + | DiagnosticStyle.Emacs + | DiagnosticStyle.Gcc + | DiagnosticStyle.Default + | DiagnosticStyle.Test + | DiagnosticStyle.VisualStudio -> diagnostic.FormatCore(tcConfig.flatErrors, suggestNames) + | DiagnosticStyle.Rich -> + diagnostic.FormatCore(tcConfig.flatErrors, suggestNames).Split([| '\n' |]) + |> Array.map (fun msg -> "\n◦ " + msg) + |> String.Concat + + let context = + match tcConfig.diagnosticStyle with + | DiagnosticStyle.Emacs + | DiagnosticStyle.Gcc + | DiagnosticStyle.Default + | DiagnosticStyle.Test + | DiagnosticStyle.VisualStudio -> None + | DiagnosticStyle.Rich -> + match diagnostic.Range with + | Some m -> + let content = + m.FileName + |> FileSystem.GetFullFilePathInDirectoryShim tcConfig.implicitIncludeDir + |> System.IO.File.ReadAllLines + + if m.StartLine = m.EndLine then + $"\n◦ {m.StartLine} |{content[m.StartLine - 1]}\n" + + $"""◦ {String.init (m.StartColumn + 3) (fun _ -> " ")}^{String.init (m.EndColumn - m.StartColumn) (fun _ -> "~")}""" + |> Some + else + content + |> fun lines -> Array.sub lines (m.StartLine - 1) (m.EndLine - m.StartLine - 1) + |> Array.fold + (fun (context, lineNumber) line -> (context + $"\n◦ {lineNumber} |{line}", lineNumber + 1)) + ("", (m.StartLine)) + |> fst + |> Some + | None -> None let entry: FormattedDiagnosticDetailedInfo = { Location = where + Context = context Canonical = canonical Message = message } @@ -2199,7 +2248,11 @@ type PhasedDiagnostic with | FormattedDiagnostic.Short(_, txt) -> buf.AppendString txt | FormattedDiagnostic.Long(_, details) -> match details.Location with - | Some l when not l.IsEmpty -> buf.AppendString l.TextRepresentation + | Some l when not l.IsEmpty -> + buf.AppendString l.TextRepresentation + // Because details.Context depends on the value of details.Location, if details.Location is not None, details.Context can be accessed directly. + if details.Context.IsSome then + buf.AppendString details.Context.Value | _ -> () buf.AppendString details.Canonical.TextRepresentation diff --git a/src/Compiler/Driver/CompilerDiagnostics.fsi b/src/Compiler/Driver/CompilerDiagnostics.fsi index 7398ebf1a0b..a7a088b1627 100644 --- a/src/Compiler/Driver/CompilerDiagnostics.fsi +++ b/src/Compiler/Driver/CompilerDiagnostics.fsi @@ -113,7 +113,8 @@ type FormattedDiagnosticCanonicalInformation = type FormattedDiagnosticDetailedInfo = { Location: FormattedDiagnosticLocation option Canonical: FormattedDiagnosticCanonicalInformation - Message: string } + Message: string + Context: string option } /// Used internally and in LegacyHostedCompilerForTesting [] diff --git a/src/Compiler/Facilities/DiagnosticsLogger.fs b/src/Compiler/Facilities/DiagnosticsLogger.fs index af19ae2f617..84e1cb55360 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fs +++ b/src/Compiler/Facilities/DiagnosticsLogger.fs @@ -18,13 +18,14 @@ open Internal.Utilities.Library.Extras open System.Threading.Tasks /// Represents the style being used to format errors -[] +[] type DiagnosticStyle = | Default | Emacs | Test | VisualStudio | Gcc + | Rich /// Thrown when we want to add some range information to a .NET exception exception WrappedError of exn * range with diff --git a/src/Compiler/Facilities/DiagnosticsLogger.fsi b/src/Compiler/Facilities/DiagnosticsLogger.fsi index 0f9b2432403..6cf3a5f2184 100644 --- a/src/Compiler/Facilities/DiagnosticsLogger.fsi +++ b/src/Compiler/Facilities/DiagnosticsLogger.fsi @@ -10,13 +10,14 @@ open System.Runtime.CompilerServices open System.Runtime.InteropServices /// Represents the style being used to format errors -[] +[] type DiagnosticStyle = | Default | Emacs | Test | VisualStudio | Gcc + | Rich /// Thrown when we want to add some range information to a .NET exception exception WrappedError of exn * range