From e6d0ed31601f5a4f6ab02b5bbbc41a7cdabee216 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 1 Feb 2021 14:16:34 +0100 Subject: [PATCH] LanguageClient: support versioned diagnostics Change-Id: Id182431f371201c7266fe0683e78fe56a8a9735b Reviewed-by: Christian Stenger --- src/libs/languageserverprotocol/diagnostics.h | 4 +++ src/plugins/languageclient/client.cpp | 6 ++--- src/plugins/languageclient/client.h | 2 +- .../languageclient/diagnosticmanager.cpp | 27 +++++++++++++------ .../languageclient/diagnosticmanager.h | 11 +++++--- .../languageclienthoverhandler.cpp | 2 +- .../languageclient/languageclientquickfix.cpp | 2 +- 7 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/libs/languageserverprotocol/diagnostics.h b/src/libs/languageserverprotocol/diagnostics.h index 68ede706db5..c7b6d7fefb8 100644 --- a/src/libs/languageserverprotocol/diagnostics.h +++ b/src/libs/languageserverprotocol/diagnostics.h @@ -42,6 +42,10 @@ public: void setDiagnostics(const QList &diagnostics) { insertArray(diagnosticsKey, diagnostics); } + Utils::optional version() const { return optionalValue(versionKey); } + void setVersion(int version) { insert(versionKey, version); } + void clearVersion() { remove(versionKey); } + bool isValid(ErrorHierarchy *error) const override { return checkArray(error, diagnosticsKey); } }; diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index d0c3d32136d..aaa213e8f98 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -946,9 +946,9 @@ void Client::removeAssistProcessor(TextEditor::IAssistProcessor *processor) m_runningAssistProcessors.remove(processor); } -QList Client::diagnosticsAt(const DocumentUri &uri, const Range &range) const +QList Client::diagnosticsAt(const DocumentUri &uri, const QTextCursor &cursor) const { - return m_diagnosticManager.diagnosticsAt(uri, range); + return m_diagnosticManager.diagnosticsAt(uri, cursor); } bool Client::start() @@ -1219,7 +1219,7 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams ¶ms) const DocumentUri &uri = params.uri(); const QList &diagnostics = params.diagnostics(); - m_diagnosticManager.setDiagnostics(uri, diagnostics); + m_diagnosticManager.setDiagnostics(uri, diagnostics, params.version()); if (LanguageClientManager::clientForUri(uri) == this) { m_diagnosticManager.showDiagnostics(uri); requestCodeActions(uri, diagnostics); diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index ea804ce6ffe..b52eded2a72 100644 --- a/src/plugins/languageclient/client.h +++ b/src/plugins/languageclient/client.h @@ -152,7 +152,7 @@ public: QList diagnosticsAt( const LanguageServerProtocol::DocumentUri &uri, - const LanguageServerProtocol::Range &range) const; + const QTextCursor &cursor) const; bool start(); bool reset(); diff --git a/src/plugins/languageclient/diagnosticmanager.cpp b/src/plugins/languageclient/diagnosticmanager.cpp index 802ff4a58fd..4a00acca101 100644 --- a/src/plugins/languageclient/diagnosticmanager.cpp +++ b/src/plugins/languageclient/diagnosticmanager.cpp @@ -76,10 +76,11 @@ DiagnosticManager::~DiagnosticManager() } void DiagnosticManager::setDiagnostics(const LanguageServerProtocol::DocumentUri &uri, - const QList &diagnostics) + const QList &diagnostics, + const Utils::optional &version) { removeDiagnostics(uri); - m_diagnostics[uri] = diagnostics; + m_diagnostics[uri] = {version, diagnostics}; } void DiagnosticManager::hideDiagnostics(TextDocument *doc) @@ -115,10 +116,13 @@ void DiagnosticManager::showDiagnostics(const DocumentUri &uri) const FilePath &filePath = uri.toFilePath(); if (TextDocument *doc = TextDocument::textDocumentForFilePath(filePath)) { QList extraSelections; - - for (const Diagnostic &diagnostic : m_diagnostics.value(uri)) { - doc->addMark(new TextMark(filePath, diagnostic, m_clientId)); - extraSelections << toDiagnosticsSelections(diagnostic, doc->document()); + const VersionedDiagnostics &versionedDiagnostics = m_diagnostics.value(uri); + const int docRevision = doc->document()->revision(); + if (versionedDiagnostics.version.value_or(docRevision) == docRevision) { + for (const Diagnostic &diagnostic : versionedDiagnostics.diagnostics) { + doc->addMark(new TextMark(filePath, diagnostic, m_clientId)); + extraSelections << toDiagnosticsSelections(diagnostic, doc->document()); + } } for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(doc)) { @@ -134,9 +138,16 @@ void DiagnosticManager::clearDiagnostics() removeDiagnostics(uri); } -QList DiagnosticManager::diagnosticsAt(const DocumentUri &uri, const Range &range) const +QList DiagnosticManager::diagnosticsAt(const DocumentUri &uri, + const QTextCursor &cursor) const { - return Utils::filtered(m_diagnostics.value(uri), [range](const Diagnostic &diagnostic) { + const int documentRevision = cursor.document()->revision(); + auto it = m_diagnostics.find(uri); + if (it == m_diagnostics.end()) + return {}; + if (documentRevision != it->version.value_or(documentRevision)) + return {}; + return Utils::filtered(it->diagnostics, [range = Range(cursor)](const Diagnostic &diagnostic) { return diagnostic.range().overlaps(range); }); } diff --git a/src/plugins/languageclient/diagnosticmanager.h b/src/plugins/languageclient/diagnosticmanager.h index 9b83f0019d1..3483c976f21 100644 --- a/src/plugins/languageclient/diagnosticmanager.h +++ b/src/plugins/languageclient/diagnosticmanager.h @@ -42,7 +42,8 @@ public: ~DiagnosticManager(); void setDiagnostics(const LanguageServerProtocol::DocumentUri &uri, - const QList &diagnostics); + const QList &diagnostics, + const Utils::optional &version); void removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri); void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri); @@ -52,10 +53,14 @@ public: QList diagnosticsAt( const LanguageServerProtocol::DocumentUri &uri, - const LanguageServerProtocol::Range &range) const; + const QTextCursor &cursor) const; private: - QMap> m_diagnostics; + struct VersionedDiagnostics { + Utils::optional version; + QList diagnostics; + }; + QMap m_diagnostics; Utils::Id m_clientId; }; diff --git a/src/plugins/languageclient/languageclienthoverhandler.cpp b/src/plugins/languageclient/languageclienthoverhandler.cpp index e95760b8b27..cf0cf596980 100644 --- a/src/plugins/languageclient/languageclienthoverhandler.cpp +++ b/src/plugins/languageclient/languageclienthoverhandler.cpp @@ -66,7 +66,7 @@ void HoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget, auto uri = DocumentUri::fromFilePath(editorWidget->textDocument()->filePath()); QTextCursor tc = editorWidget->textCursor(); tc.setPosition(pos); - QList diagnostics = m_client->diagnosticsAt(uri, Range(Position(tc), Position(tc))); + const QList &diagnostics = m_client->diagnosticsAt(uri, tc); if (!diagnostics.isEmpty()) { const QStringList messages = Utils::transform(diagnostics, &Diagnostic::message); setToolTip(messages.join('\n')); diff --git a/src/plugins/languageclient/languageclientquickfix.cpp b/src/plugins/languageclient/languageclientquickfix.cpp index 4aea17b7d4f..ca978c63e94 100644 --- a/src/plugins/languageclient/languageclientquickfix.cpp +++ b/src/plugins/languageclient/languageclientquickfix.cpp @@ -115,7 +115,7 @@ IAssistProposal *LanguageClientQuickFixAssistProcessor::perform(const AssistInte auto uri = DocumentUri::fromFilePath(interface->filePath()); params.setTextDocument(TextDocumentIdentifier(uri)); CodeActionParams::CodeActionContext context; - context.setDiagnostics(m_client->diagnosticsAt(uri, range)); + context.setDiagnostics(m_client->diagnosticsAt(uri, cursor)); params.setContext(context); CodeActionRequest request(params);