From 49c10713945b8ed631d4de7f912558827440bede Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Mon, 25 Mar 2019 10:15:11 +0000 Subject: [PATCH] [clangd] Send empty diagnostics when a file is closed Summary: The LSP clients cannot know clangd will not send diagnostic updates for closed files, so we send them an empty list of diagnostics to avoid showing stale diagnostics for closed files in the UI, e.g. in the "Problems" pane of VSCode. Fixes PR41217. Reviewers: hokein Reviewed By: hokein Subscribers: ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D59757 llvm-svn: 356880 --- clang-tools-extra/clangd/ClangdLSPServer.cpp | 30 ++++++++++++++++++++------ clang-tools-extra/clangd/ClangdLSPServer.h | 4 ++++ clang-tools-extra/test/clangd/diagnostics.test | 9 ++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index bddea90..a72e8c7 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -536,6 +536,17 @@ void ClangdLSPServer::onDocumentDidClose( PathRef File = Params.textDocument.uri.file(); DraftMgr.removeDraft(File); Server->removeDocument(File); + + { + std::lock_guard Lock(FixItsMutex); + FixItsMap.erase(File); + } + // clangd will not send updates for this file anymore, so we empty out the + // list of diagnostics shown on the client (e.g. in the "Problems" pane of + // VSCode). Note that this cannot race with actual diagnostics responses + // because removeDocument() guarantees no diagnostic callbacks will be + // executed after it returns. + publishDiagnostics(URIForFile::canonicalize(File, /*TUPath=*/File), {}); } void ClangdLSPServer::onDocumentOnTypeFormatting( @@ -836,6 +847,16 @@ void ClangdLSPServer::applyConfiguration( reparseOpenedFiles(); } +void ClangdLSPServer::publishDiagnostics( + const URIForFile &File, std::vector Diagnostics) { + // Publish diagnostics. + notify("textDocument/publishDiagnostics", + llvm::json::Object{ + {"uri", File}, + {"diagnostics", std::move(Diagnostics)}, + }); +} + // FIXME: This function needs to be properly tested. void ClangdLSPServer::onChangeConfiguration( const DidChangeConfigurationParams &Params) { @@ -978,17 +999,12 @@ void ClangdLSPServer::onDiagnosticsReady(PathRef File, // Cache FixIts { - // FIXME(ibiryukov): should be deleted when documents are removed std::lock_guard Lock(FixItsMutex); FixItsMap[File] = LocalFixIts; } - // Publish diagnostics. - notify("textDocument/publishDiagnostics", - llvm::json::Object{ - {"uri", URI}, - {"diagnostics", std::move(LSPDiagnostics)}, - }); + // Send a notification to the LSP client. + publishDiagnostics(URI, std::move(LSPDiagnostics)); } void ClangdLSPServer::onFileUpdated(PathRef File, const TUStatus &Status) { diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h index 90971bc..c785f47 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.h +++ b/clang-tools-extra/clangd/ClangdLSPServer.h @@ -113,6 +113,10 @@ private: void reparseOpenedFiles(); void applyConfiguration(const ConfigurationSettings &Settings); + /// Sends a "publishDiagnostics" notification to the LSP client. + void publishDiagnostics(const URIForFile &File, + std::vector Diagnostics); + /// Used to indicate that the 'shutdown' request was received from the /// Language Server client. bool ShutdownRequestReceived = false; diff --git a/clang-tools-extra/test/clangd/diagnostics.test b/clang-tools-extra/test/clangd/diagnostics.test index ae66269..3f35940 100644 --- a/clang-tools-extra/test/clangd/diagnostics.test +++ b/clang-tools-extra/test/clangd/diagnostics.test @@ -23,6 +23,15 @@ # CHECK-NEXT: "uri": "file://{{.*}}/foo.c" # CHECK-NEXT: } --- +{"jsonrpc":"2.0","id":2,"method":"sync","params":null} +--- +{"jsonrpc":"2.0","method":"textDocument/didClose","params":{"textDocument":{"uri":"test:///foo.c"}}} +# CHECK: "method": "textDocument/publishDiagnostics", +# CHECK-NEXT: "params": { +# CHECK-NEXT: "diagnostics": [], +# CHECK-NEXT: "uri": "file://{{.*}}/foo.c" +# CHECK-NEXT: } +--- {"jsonrpc":"2.0","id":5,"method":"shutdown"} --- {"jsonrpc":"2.0","method":"exit"} -- 2.7.4