--- a/src/plugins/languageclient/client.cpp +++ a/src/plugins/languageclient/client.cpp @@ -335,7 +335,9 @@ void Client::openDocument(TextEditor::TextDocument *document) item.setLanguageId(TextDocumentItem::mimeTypeToLanguageId(document->mimeType())); item.setUri(DocumentUri::fromFilePath(filePath)); item.setText(document->plainText()); - item.setVersion(document->document()->revision()); + if (!m_documentVersions.contains(filePath)) + m_documentVersions[filePath] = 0; + item.setVersion(m_documentVersions[filePath]); sendContent(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item))); const Client *currentClient = LanguageClientManager::clientForDocument(document); @@ -494,8 +496,9 @@ void Client::requestDocumentHighlights(TextEditor::TextEditorWidget *widget) void Client::activateDocument(TextEditor::TextDocument *document) { - auto uri = DocumentUri::fromFilePath(document->filePath()); - m_diagnosticManager.showDiagnostics(uri); + const FilePath &filePath = document->filePath(); + auto uri = DocumentUri::fromFilePath(filePath); + m_diagnosticManager.showDiagnostics(uri, m_documentVersions.value(filePath)); SemanticHighligtingSupport::applyHighlight(document, m_highlights.value(uri), capabilities()); // only replace the assist provider if the language server support it updateCompletionProvider(document); @@ -930,6 +933,7 @@ bool Client::reset() m_runningAssistProcessors.clear(); qDeleteAll(m_documentHighlightsTimer); m_documentHighlightsTimer.clear(); + m_documentVersions.clear(); return true; } @@ -1047,10 +1051,11 @@ void Client::sendPostponedDocumentUpdates() const QList documents = m_documentsToUpdate.keys(); for (auto document : documents) { - const auto uri = DocumentUri::fromFilePath(document->filePath()); + const FilePath &filePath = document->filePath(); + const auto uri = DocumentUri::fromFilePath(filePath); m_highlights[uri].clear(); VersionedTextDocumentIdentifier docId(uri); - docId.setVersion(document->document()->revision()); + docId.setVersion(++m_documentVersions[filePath]); DidChangeTextDocumentParams params; params.setTextDocument(docId); params.setContentChanges(m_documentsToUpdate.take(document)); @@ -1136,7 +1141,7 @@ void Client::handleMethod(const QString &method, const MessageId &id, const ICon } else if (method == ApplyWorkspaceEditRequest::methodName) { auto params = dynamic_cast(content)->params().value_or(ApplyWorkspaceEditParams()); if (params.isValid(&error)) - applyWorkspaceEdit(params.edit()); + applyWorkspaceEdit(this, params.edit()); else logError(params); } else if (method == WorkSpaceFolderRequest::methodName) { @@ -1171,7 +1176,7 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams ¶ms) const QList &diagnostics = params.diagnostics(); m_diagnosticManager.setDiagnostics(uri, diagnostics, params.version()); if (LanguageClientManager::clientForUri(uri) == this) { - m_diagnosticManager.showDiagnostics(uri); + m_diagnosticManager.showDiagnostics(uri, m_documentVersions.value(uri.toFilePath())); requestCodeActions(uri, diagnostics); } } @@ -1194,7 +1199,7 @@ void Client::handleSemanticHighlight(const SemanticHighlightingParams ¶ms) uri.toFilePath()); if (!doc || LanguageClientManager::clientForDocument(doc) != this - || (!version.isNull() && doc->document()->revision() != version.value())) { + || (!version.isNull() && m_documentVersions.value(uri.toFilePath()) != version.value())) { return; } @@ -1224,6 +1229,11 @@ bool Client::documentUpdatePostponed(const Utils::FilePath &fileName) const }); } +int Client::documentVersion(const Utils::FilePath &filePath) const +{ + return m_documentVersions.value(filePath); +} + void Client::initializeCallback(const InitializeRequest::Response &initResponse) { QTC_ASSERT(m_state == InitializeRequested, return); diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index fca5a6a0..d4d3f6da 100644 --- a/src/plugins/languageclient/client.h +++ a/src/plugins/languageclient/client.h @@ -132,6 +132,7 @@ public: int charsAdded); void cursorPositionChanged(TextEditor::TextEditorWidget *widget); bool documentUpdatePostponed(const Utils::FilePath &fileName) const; + int documentVersion(const Utils::FilePath &filePath) const; // workspace control virtual void setCurrentProject(ProjectExplorer::Project *project); @@ -212,6 +213,7 @@ private: LanguageFilter m_languagFilter; QJsonObject m_initializationOptions; QMap m_openedDocument; + QMap m_documentVersions; QMap> m_documentsToUpdate; diff --git a/src/plugins/languageclient/diagnosticmanager.cpp b/src/plugins/languageclient/diagnosticmanager.cpp index bd5dcfdc..ed06bb8d 100644 --- a/src/plugins/languageclient/diagnosticmanager.cpp +++ a/src/plugins/languageclient/diagnosticmanager.cpp @@ -117,14 +117,13 @@ static QTextEdit::ExtraSelection toDiagnosticsSelections(const Diagnostic &diagn return QTextEdit::ExtraSelection{cursor, fontSettings.toTextCharFormat(style)}; } -void DiagnosticManager::showDiagnostics(const DocumentUri &uri) +void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version) { const FilePath &filePath = uri.toFilePath(); if (TextDocument *doc = TextDocument::textDocumentForFilePath(filePath)) { QList extraSelections; const VersionedDiagnostics &versionedDiagnostics = m_diagnostics.value(uri); - const int docRevision = doc->document()->revision(); - if (versionedDiagnostics.version.value_or(docRevision) == docRevision) { + if (versionedDiagnostics.version.value_or(version) == version) { const auto icon = QIcon::fromTheme("edit-copy", Utils::Icons::COPY.icon()); const QString tooltip = tr("Copy to Clipboard"); for (const Diagnostic &diagnostic : versionedDiagnostics.diagnostics) { diff --git a/src/plugins/languageclient/diagnosticmanager.h b/src/plugins/languageclient/diagnosticmanager.h index dcd292a1..ac38169d 100644 --- a/src/plugins/languageclient/diagnosticmanager.h +++ a/src/plugins/languageclient/diagnosticmanager.h @@ -47,7 +47,7 @@ public: const Utils::optional &version); void removeDiagnostics(const LanguageServerProtocol::DocumentUri &uri); - void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri); + void showDiagnostics(const LanguageServerProtocol::DocumentUri &uri, int version); void hideDiagnostics(TextEditor::TextDocument *doc); void clearDiagnostics(); diff --git a/src/plugins/languageclient/languageclientquickfix.cpp b/src/plugins/languageclient/languageclientquickfix.cpp index ca978c63..af4ceb1f 100644 --- a/src/plugins/languageclient/languageclientquickfix.cpp +++ a/src/plugins/languageclient/languageclientquickfix.cpp @@ -50,7 +50,7 @@ public: void perform() override { if (Utils::optional edit = m_action.edit()) { - applyWorkspaceEdit(*edit); + applyWorkspaceEdit(m_client, *edit); } else if (Utils::optional command = m_action.command()) { if (m_client) m_client->executeCommand(*command); diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp index 7f1f396d..4a9aa8fe 100644 --- a/src/plugins/languageclient/languageclientutils.cpp +++ a/src/plugins/languageclient/languageclientutils.cpp @@ -77,15 +77,16 @@ ChangeSet editsToChangeSet(const QList &edits, const QTextDocument *do return changeSet; } -bool applyTextDocumentEdit(const TextDocumentEdit &edit) +bool applyTextDocumentEdit(const Client *client, const TextDocumentEdit &edit) { const QList &edits = edit.edits(); if (edits.isEmpty()) return true; const DocumentUri &uri = edit.textDocument().uri(); - if (TextDocument* doc = TextDocument::textDocumentForFilePath(uri.toFilePath())) { + const FilePath &filePath = uri.toFilePath(); + if (TextDocument* doc = TextDocument::textDocumentForFilePath(filePath)) { LanguageClientValue version = edit.textDocument().version(); - if (!version.isNull() && version.value(0) < doc->document()->revision()) + if (!version.isNull() && version.value(0) < client->documentVersion(filePath)) return false; } return applyTextEdits(uri, edits); @@ -112,14 +113,14 @@ void applyTextEdit(TextDocumentManipulatorInterface &manipulator, const TextEdit manipulator.replace(start, end - start, edit.newText()); } -bool applyWorkspaceEdit(const WorkspaceEdit &edit) +bool applyWorkspaceEdit(const Client *client, const WorkspaceEdit &edit) { bool result = true; const QList &documentChanges = edit.documentChanges().value_or(QList()); if (!documentChanges.isEmpty()) { for (const TextDocumentEdit &documentChange : documentChanges) - result |= applyTextDocumentEdit(documentChange); + result |= applyTextDocumentEdit(client, documentChange); } else { const WorkspaceEdit::Changes &changes = edit.changes().value_or(WorkspaceEdit::Changes()); for (auto it = changes.cbegin(); it != changes.cend(); ++it) @@ -156,8 +157,8 @@ void updateCodeActionRefactoringMarker(Client *client, marker.tooltip = action.title(); if (action.edit().has_value()) { WorkspaceEdit edit = action.edit().value(); - marker.callback = [edit](const TextEditorWidget *) { - applyWorkspaceEdit(edit); + marker.callback = [client, edit](const TextEditorWidget *) { + applyWorkspaceEdit(client, edit); }; if (diagnostics.isEmpty()) { QList edits; diff --git a/src/plugins/languageclient/languageclientutils.h b/src/plugins/languageclient/languageclientutils.h index 99a52a2d..e4dfa908 100644 --- a/src/plugins/languageclient/languageclientutils.h +++ a/src/plugins/languageclient/languageclientutils.h @@ -46,9 +46,9 @@ class Client; Utils::ChangeSet editsToChangeSet(const QList &edits, const QTextDocument *doc); -bool LANGUAGECLIENT_EXPORT applyWorkspaceEdit(const LanguageServerProtocol::WorkspaceEdit &edit); +bool LANGUAGECLIENT_EXPORT applyWorkspaceEdit(const Client *client, const LanguageServerProtocol::WorkspaceEdit &edit); bool LANGUAGECLIENT_EXPORT -applyTextDocumentEdit(const LanguageServerProtocol::TextDocumentEdit &edit); +applyTextDocumentEdit(const Client *client, const LanguageServerProtocol::TextDocumentEdit &edit); bool LANGUAGECLIENT_EXPORT applyTextEdits(const LanguageServerProtocol::DocumentUri &uri, const QList &edits); void LANGUAGECLIENT_EXPORT applyTextEdit(TextEditor::TextDocumentManipulatorInterface &manipulator,