forked from qt-creator/qt-creator
LanguageClient: Introduce workspace matchers
Change-Id: I958e83f140ce5d12a5fb6734b9fbfd8a5f95a787 Reviewed-by: David Schulz <david.schulz@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
@@ -33,6 +33,12 @@ LanguageClientPlugin *LanguageClientPlugin::instance()
|
|||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Utils::FutureSynchronizer *LanguageClientPlugin::futureSynchronizer()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(m_instance, return nullptr);
|
||||||
|
return &m_instance->m_futureSynchronizer;
|
||||||
|
}
|
||||||
|
|
||||||
void LanguageClientPlugin::initialize()
|
void LanguageClientPlugin::initialize()
|
||||||
{
|
{
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include <extensionsystem/iplugin.h>
|
#include <extensionsystem/iplugin.h>
|
||||||
|
|
||||||
|
#include <utils/futuresynchronizer.h>
|
||||||
|
|
||||||
namespace LanguageClient {
|
namespace LanguageClient {
|
||||||
|
|
||||||
class LanguageClientPlugin : public ExtensionSystem::IPlugin
|
class LanguageClientPlugin : public ExtensionSystem::IPlugin
|
||||||
@@ -19,6 +21,7 @@ public:
|
|||||||
~LanguageClientPlugin() override;
|
~LanguageClientPlugin() override;
|
||||||
|
|
||||||
static LanguageClientPlugin *instance();
|
static LanguageClientPlugin *instance();
|
||||||
|
static Utils::FutureSynchronizer *futureSynchronizer();
|
||||||
|
|
||||||
// IPlugin interface
|
// IPlugin interface
|
||||||
private:
|
private:
|
||||||
@@ -29,6 +32,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
LanguageClientOutlineWidgetFactory m_outlineFactory;
|
LanguageClientOutlineWidgetFactory m_outlineFactory;
|
||||||
CallHierarchyFactory m_callHierarchyFactory;
|
CallHierarchyFactory m_callHierarchyFactory;
|
||||||
|
Utils::FutureSynchronizer m_futureSynchronizer;
|
||||||
|
|
||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
private slots:
|
private slots:
|
||||||
|
@@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
#include "locatorfilter.h"
|
#include "locatorfilter.h"
|
||||||
|
|
||||||
|
#include "clientrequesttask.h"
|
||||||
#include "documentsymbolcache.h"
|
#include "documentsymbolcache.h"
|
||||||
#include "languageclient_global.h"
|
#include "languageclient_global.h"
|
||||||
#include "languageclientmanager.h"
|
#include "languageclientmanager.h"
|
||||||
|
#include "languageclientplugin.h"
|
||||||
#include "languageclienttr.h"
|
#include "languageclienttr.h"
|
||||||
|
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
@@ -14,6 +16,7 @@
|
|||||||
|
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
|
||||||
|
#include <utils/asynctask.h>
|
||||||
#include <utils/fuzzymatcher.h>
|
#include <utils/fuzzymatcher.h>
|
||||||
|
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
@@ -21,9 +24,92 @@
|
|||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace LanguageServerProtocol;
|
using namespace LanguageServerProtocol;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace LanguageClient {
|
namespace LanguageClient {
|
||||||
|
|
||||||
|
void filterResults(QPromise<LocatorMatcherTask::OutputData> &promise, Client *client,
|
||||||
|
const QList<SymbolInformation> &results, const QList<SymbolKind> &filter)
|
||||||
|
{
|
||||||
|
const auto doFilter = [&](const SymbolInformation &info) {
|
||||||
|
return filter.contains(SymbolKind(info.kind()));
|
||||||
|
};
|
||||||
|
const QList<SymbolInformation> filteredResults = filter.isEmpty() ? results
|
||||||
|
: Utils::filtered(results, doFilter);
|
||||||
|
const auto generateEntry = [client](const SymbolInformation &info) {
|
||||||
|
LocatorFilterEntry entry;
|
||||||
|
// TODO: Passing nullptr for filter -> accept won't work now. Replace with accept function.
|
||||||
|
entry.filter = nullptr;
|
||||||
|
entry.displayName = info.name();
|
||||||
|
if (std::optional<QString> container = info.containerName())
|
||||||
|
entry.extraInfo = container.value_or(QString());
|
||||||
|
entry.displayIcon = symbolIcon(info.kind());
|
||||||
|
entry.linkForEditor = info.location().toLink(client->hostPathMapper());
|
||||||
|
return entry;
|
||||||
|
};
|
||||||
|
promise.addResult(Utils::transform(filteredResults, generateEntry));
|
||||||
|
}
|
||||||
|
|
||||||
|
LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount,
|
||||||
|
const QList<SymbolKind> &filter)
|
||||||
|
{
|
||||||
|
using namespace Tasking;
|
||||||
|
|
||||||
|
TreeStorage<LocatorMatcherTask::Storage> storage;
|
||||||
|
TreeStorage<QList<SymbolInformation>> resultStorage;
|
||||||
|
|
||||||
|
const auto onQuerySetup = [=](WorkspaceSymbolRequestTask &request) {
|
||||||
|
request.setClient(client);
|
||||||
|
WorkspaceSymbolParams params;
|
||||||
|
params.setQuery(storage->input);
|
||||||
|
if (maxResultCount > 0)
|
||||||
|
params.setLimit(maxResultCount);
|
||||||
|
request.setParams(params);
|
||||||
|
};
|
||||||
|
const auto onQueryDone = [resultStorage](const WorkspaceSymbolRequestTask &request) {
|
||||||
|
const std::optional<LanguageClientArray<SymbolInformation>> result
|
||||||
|
= request.response().result();
|
||||||
|
if (result.has_value())
|
||||||
|
*resultStorage = result->toList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto onFilterSetup = [=](AsyncTask<LocatorMatcherTask::OutputData> &async) {
|
||||||
|
const QList<SymbolInformation> results = *resultStorage;
|
||||||
|
if (results.isEmpty())
|
||||||
|
return TaskAction::StopWithDone;
|
||||||
|
async.setFutureSynchronizer(LanguageClientPlugin::futureSynchronizer());
|
||||||
|
async.setConcurrentCallData(filterResults, client, results, filter);
|
||||||
|
return TaskAction::Continue;
|
||||||
|
};
|
||||||
|
const auto onFilterDone = [storage](const AsyncTask<LocatorMatcherTask::OutputData> &async) {
|
||||||
|
if (async.isResultAvailable())
|
||||||
|
storage->output = async.result();
|
||||||
|
};
|
||||||
|
|
||||||
|
const Group root {
|
||||||
|
Storage(resultStorage),
|
||||||
|
SymbolRequest(onQuerySetup, onQueryDone),
|
||||||
|
Async<LocatorMatcherTask::OutputData>(onFilterSetup, onFilterDone)
|
||||||
|
};
|
||||||
|
return {root, storage};
|
||||||
|
}
|
||||||
|
|
||||||
|
LocatorMatcherTask workspaceLocatorMatcher(Client *client, int maxResultCount)
|
||||||
|
{
|
||||||
|
return locatorMatcher(client, maxResultCount, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
LocatorMatcherTask workspaceClassMatcher(Client *client, int maxResultCount)
|
||||||
|
{
|
||||||
|
return locatorMatcher(client, maxResultCount, {SymbolKind::Class, SymbolKind::Struct});
|
||||||
|
}
|
||||||
|
|
||||||
|
LocatorMatcherTask workspaceFunctionMatcher(Client *client, int maxResultCount)
|
||||||
|
{
|
||||||
|
return locatorMatcher(client, maxResultCount,
|
||||||
|
{SymbolKind::Method, SymbolKind::Function, SymbolKind::Constructor});
|
||||||
|
}
|
||||||
|
|
||||||
DocumentLocatorFilter::DocumentLocatorFilter(LanguageClientManager *languageManager)
|
DocumentLocatorFilter::DocumentLocatorFilter(LanguageClientManager *languageManager)
|
||||||
{
|
{
|
||||||
setId(Constants::LANGUAGECLIENT_DOCUMENT_FILTER_ID);
|
setId(Constants::LANGUAGECLIENT_DOCUMENT_FILTER_ID);
|
||||||
@@ -129,7 +215,7 @@ QList<LocatorFilterEntry> DocumentLocatorFilter::entriesForDocSymbols(
|
|||||||
void DocumentLocatorFilter::prepareSearch(const QString &/*entry*/)
|
void DocumentLocatorFilter::prepareSearch(const QString &/*entry*/)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
m_currentFilePath = m_pathMapper ? m_currentUri.toFilePath(m_pathMapper) : Utils::FilePath();
|
m_currentFilePath = m_pathMapper ? m_currentUri.toFilePath(m_pathMapper) : FilePath();
|
||||||
if (m_symbolCache && !m_currentSymbols.has_value()) {
|
if (m_symbolCache && !m_currentSymbols.has_value()) {
|
||||||
locker.unlock();
|
locker.unlock();
|
||||||
m_symbolCache->requestSymbols(m_currentUri, Schedule::Now);
|
m_symbolCache->requestSymbols(m_currentUri, Schedule::Now);
|
||||||
@@ -154,7 +240,7 @@ QList<LocatorFilterEntry> DocumentLocatorFilter::matchesFor(
|
|||||||
return matchesForImpl(future, entry, docSymbolGenerator);
|
return matchesForImpl(future, entry, docSymbolGenerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::Link DocumentLocatorFilter::linkForDocSymbol(const DocumentSymbol &info) const
|
Link DocumentLocatorFilter::linkForDocSymbol(const DocumentSymbol &info) const
|
||||||
{
|
{
|
||||||
const Position &pos = info.range().start();
|
const Position &pos = info.range().start();
|
||||||
return {m_currentFilePath, pos.line() + 1, pos.character()};
|
return {m_currentFilePath, pos.line() + 1, pos.character()};
|
||||||
|
@@ -19,6 +19,14 @@ namespace Core { class IEditor; }
|
|||||||
|
|
||||||
namespace LanguageClient {
|
namespace LanguageClient {
|
||||||
|
|
||||||
|
// TODO: Could be public methods of Client instead
|
||||||
|
Core::LocatorMatcherTask LANGUAGECLIENT_EXPORT workspaceLocatorMatcher(Client *client,
|
||||||
|
int maxResultCount = 0);
|
||||||
|
Core::LocatorMatcherTask LANGUAGECLIENT_EXPORT workspaceClassMatcher(Client *client,
|
||||||
|
int maxResultCount = 0);
|
||||||
|
Core::LocatorMatcherTask LANGUAGECLIENT_EXPORT workspaceFunctionMatcher(Client *client,
|
||||||
|
int maxResultCount = 0);
|
||||||
|
|
||||||
class LanguageClientManager;
|
class LanguageClientManager;
|
||||||
|
|
||||||
class LANGUAGECLIENT_EXPORT DocumentLocatorFilter : public Core::ILocatorFilter
|
class LANGUAGECLIENT_EXPORT DocumentLocatorFilter : public Core::ILocatorFilter
|
||||||
|
Reference in New Issue
Block a user