diff options
author | David Schulz <david.schulz@qt.io> | 2019-04-04 14:36:28 +0200 |
---|---|---|
committer | David Schulz <david.schulz@qt.io> | 2019-04-25 10:54:23 +0000 |
commit | b79eabd4d2e65fd5b84c4bccc94e38d2a3b4cf85 (patch) | |
tree | 754c1f54583ba6295f0c36a94d982ccdfd01efb5 /src/plugins/languageclient | |
parent | dfeb0245838f0709e845ed264f343e4ac0bb2bfe (diff) | |
download | qt-creator-b79eabd4d2e65fd5b84c4bccc94e38d2a3b4cf85.tar.gz |
LanguageClient: add cache for document symbols
Change-Id: Ia4c4061258c74d839edbd472c2087be74ac30113
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/languageclient')
-rw-r--r-- | src/plugins/languageclient/client.cpp | 6 | ||||
-rw-r--r-- | src/plugins/languageclient/client.h | 3 | ||||
-rw-r--r-- | src/plugins/languageclient/documentsymbolcache.cpp | 81 | ||||
-rw-r--r-- | src/plugins/languageclient/documentsymbolcache.h | 58 | ||||
-rw-r--r-- | src/plugins/languageclient/languageclient.pro | 2 | ||||
-rw-r--r-- | src/plugins/languageclient/languageclient.qbs | 2 | ||||
-rw-r--r-- | src/plugins/languageclient/languageclientoutline.cpp | 42 |
7 files changed, 170 insertions, 24 deletions
diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 12c8f86531..dd544f37e9 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -94,6 +94,7 @@ Client::Client(BaseClientInterface *clientInterface) , m_completionProvider(this) , m_quickFixProvider(this) , m_clientInterface(clientInterface) + , m_documentSymbolCache(this) { m_contentHandler.insert(JsonRpcMessageHandler::jsonRpcMimeType(), &JsonRpcMessageHandler::parseContent); @@ -859,6 +860,11 @@ const BaseClientInterface *Client::clientInterface() const return m_clientInterface.data(); } +DocumentSymbolCache *Client::documentSymbolCache() +{ + return &m_documentSymbolCache; +} + void Client::log(const ShowMessageParams &message, Core::MessageManager::PrintToOutputPaneFlag flag) { diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index d29c4f6a88..f2f92cbfe6 100644 --- a/src/plugins/languageclient/client.h +++ b/src/plugins/languageclient/client.h @@ -25,6 +25,7 @@ #pragma once +#include "documentsymbolcache.h" #include "dynamiccapabilities.h" #include "languageclientcompletionassist.h" #include "languageclientquickfix.h" @@ -148,6 +149,7 @@ public: const LanguageServerProtocol::ServerCapabilities &capabilities() const; const DynamicCapabilities &dynamicCapabilities() const; const BaseClientInterface *clientInterface() const; + DocumentSymbolCache *documentSymbolCache(); signals: void initialized(LanguageServerProtocol::ServerCapabilities capabilities); @@ -197,6 +199,7 @@ private: int m_restartsLeft = 5; QScopedPointer<BaseClientInterface> m_clientInterface; QMap<LanguageServerProtocol::DocumentUri, QList<TextMark *>> m_diagnostics; + DocumentSymbolCache m_documentSymbolCache; }; } // namespace LanguageClient diff --git a/src/plugins/languageclient/documentsymbolcache.cpp b/src/plugins/languageclient/documentsymbolcache.cpp new file mode 100644 index 0000000000..b922486d56 --- /dev/null +++ b/src/plugins/languageclient/documentsymbolcache.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "documentsymbolcache.h" + +#include "client.h" + +#include <coreplugin/editormanager/editormanager.h> +#include <texteditor/textdocument.h> + +using namespace LanguageServerProtocol; + +namespace LanguageClient { + +DocumentSymbolCache::DocumentSymbolCache(Client *client) + : QObject(client) + , m_client(client) +{ + connect(Core::EditorManager::instance(), + &Core::EditorManager::documentOpened, + this, + [this](Core::IDocument *document) { + connect(document, &Core::IDocument::contentsChanged, this, [this, document]() { + m_cache.remove(DocumentUri::fromFileName(document->filePath())); + }); + }); +} + +void DocumentSymbolCache::requestSymbols(const DocumentUri &uri) +{ + auto entry = m_cache.find(uri); + if (entry != m_cache.end()) { + emit gotSymbols(uri, entry.value()); + return; + } + + const DocumentSymbolParams params((TextDocumentIdentifier(uri))); + DocumentSymbolsRequest request(params); + request.setResponseCallback([uri, self = QPointer<DocumentSymbolCache>(this)]( + const DocumentSymbolsRequest::Response &response) { + if (self) + self->handleResponse(uri, response); + }); + m_client->sendContent(request); +} + +void DocumentSymbolCache::handleResponse(const DocumentUri &uri, + const DocumentSymbolsRequest::Response &response) +{ + if (Utils::optional<DocumentSymbolsRequest::Response::Error> error = response.error()) { + if (m_client) + m_client->log(error.value()); + } + const DocumentSymbolsResult &symbols = response.result().value_or(DocumentSymbolsResult()); + m_cache[uri] = symbols; + emit gotSymbols(uri, symbols); +} + +} // namespace LanguageClient diff --git a/src/plugins/languageclient/documentsymbolcache.h b/src/plugins/languageclient/documentsymbolcache.h new file mode 100644 index 0000000000..2f0b2376bc --- /dev/null +++ b/src/plugins/languageclient/documentsymbolcache.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "utils/optional.h" + +#include <languageserverprotocol/languagefeatures.h> + +#include <QObject> + +namespace LanguageClient { + +class Client; + +class DocumentSymbolCache : public QObject +{ + Q_OBJECT +public: + DocumentSymbolCache(Client *client); + + void requestSymbols(const LanguageServerProtocol::DocumentUri &uri); + +signals: + void gotSymbols(const LanguageServerProtocol::DocumentUri &uri, + const LanguageServerProtocol::DocumentSymbolsResult &symbols); + +private: + void handleResponse(const LanguageServerProtocol::DocumentUri &uri, + const LanguageServerProtocol::DocumentSymbolsRequest::Response &response); + + QMap<LanguageServerProtocol::DocumentUri, LanguageServerProtocol::DocumentSymbolsResult> m_cache; + Client *m_client = nullptr; +}; + +} // namespace LanguageClient diff --git a/src/plugins/languageclient/languageclient.pro b/src/plugins/languageclient/languageclient.pro index dbae20e109..912873134b 100644 --- a/src/plugins/languageclient/languageclient.pro +++ b/src/plugins/languageclient/languageclient.pro @@ -4,6 +4,7 @@ DEFINES += LANGUAGECLIENT_LIBRARY HEADERS += \ client.h \ + documentsymbolcache.h \ dynamiccapabilities.h \ languageclient_global.h \ languageclientcompletionassist.h \ @@ -18,6 +19,7 @@ HEADERS += \ SOURCES += \ client.cpp \ + documentsymbolcache.cpp \ dynamiccapabilities.cpp \ languageclientcompletionassist.cpp \ languageclientinterface.cpp \ diff --git a/src/plugins/languageclient/languageclient.qbs b/src/plugins/languageclient/languageclient.qbs index 0c2752ef5e..b2520fba34 100644 --- a/src/plugins/languageclient/languageclient.qbs +++ b/src/plugins/languageclient/languageclient.qbs @@ -16,6 +16,8 @@ QtcPlugin { files: [ "client.cpp", "client.h", + "documentsymbolcache.cpp", + "documentsymbolcache.h", "dynamiccapabilities.cpp", "dynamiccapabilities.h", "languageclient.qrc", diff --git a/src/plugins/languageclient/languageclientoutline.cpp b/src/plugins/languageclient/languageclientoutline.cpp index 3c3a1aa1b1..e08587c1d3 100644 --- a/src/plugins/languageclient/languageclientoutline.cpp +++ b/src/plugins/languageclient/languageclientoutline.cpp @@ -155,7 +155,7 @@ public: void setCursorSynchronization(bool syncWithCursor) override; private: - void handleResponse(const LanguageServerProtocol::DocumentSymbolsRequest::Response &response); + void handleResponse(const DocumentUri &uri, const DocumentSymbolsResult &response); void updateTextCursor(const QModelIndex &proxyIndex); void updateSelectionInTree(const QTextCursor ¤tCursor); void onItemActivated(const QModelIndex &index); @@ -164,6 +164,7 @@ private: QPointer<TextEditor::BaseTextEditor> m_editor; LanguageClientOutlineModel m_model; Utils::TreeView m_view; + DocumentUri m_uri; bool m_sync = false; }; @@ -172,23 +173,19 @@ LanguageClientOutlineWidget::LanguageClientOutlineWidget(Client *client, : m_client(client) , m_editor(editor) , m_view(this) + , m_uri(DocumentUri::fromFileName(editor->textDocument()->filePath())) { - const DocumentSymbolParams params( - TextDocumentIdentifier( - DocumentUri::fromFileName(editor->textDocument()->filePath()))); - DocumentSymbolsRequest request(params); - request.setResponseCallback([self = QPointer<LanguageClientOutlineWidget>(this)] - (const DocumentSymbolsRequest::Response &response){ - if (self) - self->handleResponse(response); - }); + connect(client->documentSymbolCache(), + &DocumentSymbolCache::gotSymbols, + this, + &LanguageClientOutlineWidget::handleResponse); + client->documentSymbolCache()->requestSymbols(m_uri); auto *layout = new QVBoxLayout; layout->setMargin(0); layout->setSpacing(0); layout->addWidget(Core::ItemViewFind::createSearchableWrapper(&m_view)); setLayout(layout); - client->sendContent(request); m_view.setModel(&m_model); m_view.setHeaderHidden(true); connect(&m_view, &QAbstractItemView::activated, @@ -212,20 +209,17 @@ void LanguageClientOutlineWidget::setCursorSynchronization(bool syncWithCursor) updateSelectionInTree(m_editor->textCursor()); } -void LanguageClientOutlineWidget::handleResponse(const DocumentSymbolsRequest::Response &response) +void LanguageClientOutlineWidget::handleResponse(const DocumentUri &uri, + const DocumentSymbolsResult &result) { - if (Utils::optional<DocumentSymbolsRequest::Response::Error> error = response.error()) { - if (m_client) - m_client->log(error.value()); - } - if (Utils::optional<DocumentSymbolsResult> result = response.result()) { - if (Utils::holds_alternative<QList<SymbolInformation>>(result.value())) - m_model.setInfo(Utils::get<QList<SymbolInformation>>(result.value())); - else if (Utils::holds_alternative<QList<DocumentSymbol>>(result.value())) - m_model.setInfo(Utils::get<QList<DocumentSymbol>>(result.value())); - else - m_model.clear(); - } + if (uri != m_uri) + return; + if (Utils::holds_alternative<QList<SymbolInformation>>(result)) + m_model.setInfo(Utils::get<QList<SymbolInformation>>(result)); + else if (Utils::holds_alternative<QList<DocumentSymbol>>(result)) + m_model.setInfo(Utils::get<QList<DocumentSymbol>>(result)); + else + m_model.clear(); } void LanguageClientOutlineWidget::updateTextCursor(const QModelIndex &proxyIndex) |