forked from qt-creator/qt-creator
LanguageClient: add cache for document symbols
Change-Id: Ia4c4061258c74d839edbd472c2087be74ac30113 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
81
src/plugins/languageclient/documentsymbolcache.cpp
Normal file
81
src/plugins/languageclient/documentsymbolcache.cpp
Normal file
@@ -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
|
||||
58
src/plugins/languageclient/documentsymbolcache.h
Normal file
58
src/plugins/languageclient/documentsymbolcache.h
Normal file
@@ -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
|
||||
@@ -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 \
|
||||
|
||||
@@ -16,6 +16,8 @@ QtcPlugin {
|
||||
files: [
|
||||
"client.cpp",
|
||||
"client.h",
|
||||
"documentsymbolcache.cpp",
|
||||
"documentsymbolcache.h",
|
||||
"dynamiccapabilities.cpp",
|
||||
"dynamiccapabilities.h",
|
||||
"languageclient.qrc",
|
||||
|
||||
@@ -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,21 +209,18 @@ 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()));
|
||||
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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user