diff --git a/src/FsAutoComplete/LspHelpers.fs b/src/FsAutoComplete/LspHelpers.fs index 52b7f2e56..ece9a9ff8 100644 --- a/src/FsAutoComplete/LspHelpers.fs +++ b/src/FsAutoComplete/LspHelpers.fs @@ -98,6 +98,11 @@ module Conversions = let urlForCompilerCode (number: int) = $"https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/compiler-messages/fs%04d{number}" + [] + let unicodeParagraphCharacter: string = "\u001d" + + let private handleUnicodeParagraph (message: string) = message.Replace(unicodeParagraphCharacter, Environment.NewLine) + let fcsErrorToDiagnostic (error: FSharpDiagnostic) = { Range = { Start = @@ -108,7 +113,7 @@ module Conversions = Character = error.EndColumn } } Severity = fcsSeverityToDiagnostic error.Severity Source = Some "F# Compiler" - Message = error.Message + Message = handleUnicodeParagraph error.Message Code = Some(string error.ErrorNumber) RelatedInformation = Some [||] Tags = None diff --git a/src/FsAutoComplete/LspHelpers.fsi b/src/FsAutoComplete/LspHelpers.fsi index 782fc48ed..2296192dc 100644 --- a/src/FsAutoComplete/LspHelpers.fsi +++ b/src/FsAutoComplete/LspHelpers.fsi @@ -36,6 +36,9 @@ module Conversions = val fcsRangeToLspLocation: range: FcsRange -> Location val findDeclToLspLocation: decl: FsAutoComplete.FindDeclarationResult -> Location + [] + val unicodeParagraphCharacter: string = "\u001d" + type TextDocumentIdentifier with member GetFilePath: unit -> string diff --git a/test/FsAutoComplete.Tests.Lsp/CoreTests.fs b/test/FsAutoComplete.Tests.Lsp/CoreTests.fs index fbc24265a..e3b691fe1 100644 --- a/test/FsAutoComplete.Tests.Lsp/CoreTests.fs +++ b/test/FsAutoComplete.Tests.Lsp/CoreTests.fs @@ -467,3 +467,40 @@ let closeTests state = let! diags = doc |> Document.waitForLatestDiagnostics (TimeSpan.FromSeconds 5.0) Expect.isNonEmpty diags "There should be no publishDiagnostics without any diags after close" }) ]) + +let diagnosticsTest state = + let server = + async { + let path = Path.Combine(__SOURCE_DIRECTORY__, "TestCases", "DiagnosticFormatting") + let! (server, events) = serverInitialize path defaultConfigDto state + let path = Path.Combine(path, "Program.fs") + do! waitForWorkspaceFinishedParsing events + return (server, events, path) + } + |> Async.Cache + + testList + "Diagnostics formatting Tests" + [ testCaseAsync + "replacing unicode paragraph by newline" + (async { + let! (server, events, path) = server + + let tdop: DidOpenTextDocumentParams = { TextDocument = loadDocument path } + do! server.TextDocumentDidOpen tdop + + let! compilerResults = waitForCompilerDiagnosticsForFile "Program.fs" events |> Async.StartChild + + match! compilerResults with + | Ok() -> failtest "should get an F# compiler checking error" + | Core.Result.Error errors -> + Expect.exists + errors + (fun error -> error.Code = Some "39" || error.Code = Some "41") + "should have an error FS0039(identifier not defined) or FS0041(a unique overload for method 'TryParse' could not be determined based on type information prior to this program point)" + + Expect.all + errors + (fun error -> not <| error.Message.Contains(unicodeParagraphCharacter)) + "message should not contains unicode paragraph characters" + }) ] diff --git a/test/FsAutoComplete.Tests.Lsp/Helpers.fs b/test/FsAutoComplete.Tests.Lsp/Helpers.fs index 23a459b20..108f1496b 100644 --- a/test/FsAutoComplete.Tests.Lsp/Helpers.fs +++ b/test/FsAutoComplete.Tests.Lsp/Helpers.fs @@ -51,11 +51,11 @@ module Expecto = let testCase = testCaseWithTimeout DEFAULT_TIMEOUT let ptestCase = ptestCaseWithTimeout DEFAULT_TIMEOUT - let ftestCase = ptestCaseWithTimeout DEFAULT_TIMEOUT + let ftestCase = ftestCaseWithTimeout DEFAULT_TIMEOUT let testCaseAsync = testCaseAsyncWithTimeout DEFAULT_TIMEOUT let ptestCaseAsync = ptestCaseAsyncWithTimeout DEFAULT_TIMEOUT - let ftestCaseAsync = ptestCaseAsyncWithTimeout DEFAULT_TIMEOUT + let ftestCaseAsync = ftestCaseAsyncWithTimeout DEFAULT_TIMEOUT let rec private copyDirectory sourceDir destDir = // Get the subdirectories for the specified directory. diff --git a/test/FsAutoComplete.Tests.Lsp/Program.fs b/test/FsAutoComplete.Tests.Lsp/Program.fs index 9e09c51e9..5774c9891 100644 --- a/test/FsAutoComplete.Tests.Lsp/Program.fs +++ b/test/FsAutoComplete.Tests.Lsp/Program.fs @@ -103,6 +103,7 @@ let lspTests = UnusedDeclarationsTests.tests createServer EmptyFileTests.tests createServer CallHierarchy.tests createServer + diagnosticsTest createServer ] ] /// Tests that do not require a LSP server diff --git a/test/FsAutoComplete.Tests.Lsp/TestCases/DiagnosticFormatting/DiagnosticFormatting.fsproj b/test/FsAutoComplete.Tests.Lsp/TestCases/DiagnosticFormatting/DiagnosticFormatting.fsproj new file mode 100644 index 000000000..14e942e52 --- /dev/null +++ b/test/FsAutoComplete.Tests.Lsp/TestCases/DiagnosticFormatting/DiagnosticFormatting.fsproj @@ -0,0 +1,13 @@ + + + + Exe + net6.0 + + + + + + + + diff --git a/test/FsAutoComplete.Tests.Lsp/TestCases/DiagnosticFormatting/Program.fs b/test/FsAutoComplete.Tests.Lsp/TestCases/DiagnosticFormatting/Program.fs new file mode 100644 index 000000000..5c56d738b --- /dev/null +++ b/test/FsAutoComplete.Tests.Lsp/TestCases/DiagnosticFormatting/Program.fs @@ -0,0 +1,9 @@ +// Learn more about F# at http://fsharp.org + +open System + +[] +let main argv = + let isOk, integer = System.Int32.TryParse nope + printfn "Hello World from F#!" + 0 // return an integer exit code