From 8f5109b6eee4d61207474916404621fb6a675811 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 12 May 2020 09:20:01 +0200 Subject: LSP: Robustify open documents Use Client::openDocument if you just want to open a document and activate it if it is not already used in another client. Use LanguageClientManager::openDocumentWithClient if you want to make sure a document is opened _and_ activated for a specific client. Change-Id: I6b790f15e17335ce2dc8981a04d2cd571b22b66b Reviewed-by: Christian Stenger --- src/plugins/languageclient/client.cpp | 10 +++--- .../languageclient/languageclientmanager.cpp | 39 +++++++++------------- src/plugins/languageclient/languageclientmanager.h | 9 +++-- src/plugins/languageclient/languageclientutils.cpp | 2 +- 4 files changed, 29 insertions(+), 31 deletions(-) (limited to 'src/plugins/languageclient') diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 5fad0bac464..4fbebdbc873 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -329,8 +329,11 @@ void Client::openDocument(TextEditor::TextDocument *document) item.setVersion(document->document()->revision()); sendContent(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item))); - if (LanguageClientManager::clientForDocument(document) == this) + const Client *currentClient = LanguageClientManager::clientForDocument(document); + if (currentClient == this) // this is the active client for the document so directly activate it activateDocument(document); + else if (currentClient == nullptr) // there is no client for this document so assign it to this server + LanguageClientManager::openDocumentWithClient(document, this); } void Client::sendContent(const IContent &content) @@ -887,11 +890,8 @@ void Client::projectFileListChanged() { for (Core::IDocument *doc : Core::DocumentModel::openedDocuments()) { if (m_project->isKnownFile(doc->filePath())) { - if (auto textDocument = qobject_cast(doc)) { + if (auto textDocument = qobject_cast(doc)) openDocument(textDocument); - if (!LanguageClientManager::clientForDocument(textDocument)) - LanguageClientManager::reOpenDocumentWithClient(textDocument, this); - } } } } diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp index 7e42c5c070d..d0740056950 100644 --- a/src/plugins/languageclient/languageclientmanager.cpp +++ b/src/plugins/languageclient/languageclientmanager.cpp @@ -245,11 +245,8 @@ void LanguageClientManager::applySettings() } if (!documents.isEmpty()) { Client *client = startClient(setting); - for (TextEditor::TextDocument *document : documents) { - if (managerInstance->m_clientForDocument.value(document).isNull()) - managerInstance->m_clientForDocument[document] = client; + for (TextEditor::TextDocument *document : documents) client->openDocument(document); - } } break; } @@ -332,13 +329,21 @@ Client *LanguageClientManager::clientForUri(const DocumentUri &uri) return clientForFilePath(uri.toFilePath()); } -void LanguageClientManager::reOpenDocumentWithClient(TextEditor::TextDocument *document, Client *client) +void LanguageClientManager::openDocumentWithClient(TextEditor::TextDocument *document, Client *client) { - Utils::ExecuteOnDestruction outlineUpdater(&TextEditor::IOutlineWidgetFactory::updateOutline); - if (Client *currentClient = clientForDocument(document)) + Client *currentClient = clientForDocument(document); + if (client == currentClient) + return; + if (currentClient) currentClient->deactivateDocument(document); managerInstance->m_clientForDocument[document] = client; - client->activateDocument(document); + if (client) { + if (!client->documentOpen(document)) + client->openDocument(document); + else + client->activateDocument(document); + } + TextEditor::IOutlineWidgetFactory::updateOutline(); } void LanguageClientManager::logBaseMessage(const LspLogMessage::MessageSender sender, @@ -458,22 +463,12 @@ void LanguageClientManager::documentOpened(Core::IDocument *document) } else if (setting->m_startBehavior == BaseSettings::RequiresFile && clients.isEmpty()) { clients << startClient(setting); } - for (auto client : clients) { - if (!m_clientForDocument.contains(textDocument)) - m_clientForDocument[textDocument] = client; - openDocumentWithClient(textDocument, client); - } + for (auto client : clients) + client->openDocument(textDocument); } } } -void LanguageClientManager::openDocumentWithClient(TextEditor::TextDocument *document, - Client *client) -{ - if (client && client->state() != Client::Error) - client->openDocument(document); -} - void LanguageClientManager::documentClosed(Core::IDocument *document) { if (auto textDocument = qobject_cast(document)) { @@ -629,9 +624,7 @@ void LanguageClientManager::updateProject(ProjectExplorer::Project *project) newClient = startClient(setting, project); if (!newClient) break; - openDocumentWithClient(textDoc, newClient); - if (m_clientForDocument.value(textDoc) == nullptr) - m_clientForDocument[textDoc] = newClient; + newClient->openDocument(textDoc); } } } diff --git a/src/plugins/languageclient/languageclientmanager.h b/src/plugins/languageclient/languageclientmanager.h index 0af23e6b0e5..2a1c42e62de 100644 --- a/src/plugins/languageclient/languageclientmanager.h +++ b/src/plugins/languageclient/languageclientmanager.h @@ -83,7 +83,13 @@ public: static Client *clientForDocument(TextEditor::TextDocument *document); static Client *clientForFilePath(const Utils::FilePath &filePath); static Client *clientForUri(const LanguageServerProtocol::DocumentUri &uri); - static void reOpenDocumentWithClient(TextEditor::TextDocument *document, Client *client); + + /// + /// \brief openDocumentWithClient + /// makes sure the document is opened and activated with the client and + /// deactivates the document for a potential previous active client + /// + static void openDocumentWithClient(TextEditor::TextDocument *document, Client *client); static void logBaseMessage(const LspLogMessage::MessageSender sender, const QString &clientName, @@ -98,7 +104,6 @@ private: void editorOpened(Core::IEditor *editor); void documentOpened(Core::IDocument *document); - void openDocumentWithClient(TextEditor::TextDocument *document, Client *client); void documentClosed(Core::IDocument *document); void documentContentsSaved(Core::IDocument *document); void documentWillSave(Core::IDocument *document); diff --git a/src/plugins/languageclient/languageclientutils.cpp b/src/plugins/languageclient/languageclientutils.cpp index 72bb0157576..d6f6c1676b8 100644 --- a/src/plugins/languageclient/languageclientutils.cpp +++ b/src/plugins/languageclient/languageclientutils.cpp @@ -231,7 +231,7 @@ void updateEditorToolBar(Core::IEditor *editor) auto reopen = [action, client = QPointer(client), document]() { if (!client) return; - LanguageClientManager::reOpenDocumentWithClient(document, client); + LanguageClientManager::openDocumentWithClient(document, client); action->setChecked(true); }; action->setCheckable(true); -- cgit v1.2.3