forked from qt-creator/qt-creator
ClangCodeModel: Reimplement matchers()
Change-Id: I2d541e24347aa47ec41f88cd7d18004dee7197cf Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
@@ -12,12 +12,15 @@
|
||||
#include <cppeditor/cpplocatorfilter.h>
|
||||
#include <cppeditor/cppmodelmanager.h>
|
||||
#include <cppeditor/indexitem.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <languageclient/currentdocumentsymbolsrequesttask.h>
|
||||
#include <languageclient/languageclientmanager.h>
|
||||
#include <languageclient/languageclientutils.h>
|
||||
#include <languageclient/locatorfilter.h>
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
#include <utils/link.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/asynctask.h>
|
||||
#include <utils/link.h>
|
||||
|
||||
#include <QHash>
|
||||
|
||||
@@ -25,6 +28,7 @@ using namespace Core;
|
||||
using namespace LanguageClient;
|
||||
using namespace LanguageServerProtocol;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace TextEditor;
|
||||
using namespace Utils;
|
||||
|
||||
namespace ClangCodeModel {
|
||||
@@ -212,6 +216,7 @@ LocatorMatcherTasks ClangFunctionsFilter::matchers()
|
||||
ClangModelManagerSupport::clientsForOpenProjects(), MaxResultCount);
|
||||
}
|
||||
|
||||
// TODO: Remove this class, it's used only internally by ClangdCurrentDocumentFilter
|
||||
class LspCurrentDocumentFilter : public DocumentLocatorFilter
|
||||
{
|
||||
public:
|
||||
@@ -341,6 +346,128 @@ ClangdCurrentDocumentFilter::ClangdCurrentDocumentFilter() : d(new Private)
|
||||
|
||||
ClangdCurrentDocumentFilter::~ClangdCurrentDocumentFilter() { delete d; }
|
||||
|
||||
static void filterCurrentResults(QPromise<void> &promise, const LocatorStorage &storage,
|
||||
const CurrentDocumentSymbolsData ¤tSymbolsData,
|
||||
const QString &contents)
|
||||
{
|
||||
Q_UNUSED(promise)
|
||||
struct Entry
|
||||
{
|
||||
LocatorFilterEntry entry;
|
||||
DocumentSymbol symbol;
|
||||
};
|
||||
QList<Entry> docEntries;
|
||||
|
||||
const auto docSymbolModifier = [&docEntries](LocatorFilterEntry &entry,
|
||||
const DocumentSymbol &info,
|
||||
const LocatorFilterEntry &parent) {
|
||||
entry.displayName = ClangdClient::displayNameFromDocumentSymbol(
|
||||
static_cast<SymbolKind>(info.kind()), info.name(),
|
||||
info.detail().value_or(QString()));
|
||||
entry.extraInfo = parent.extraInfo;
|
||||
if (!entry.extraInfo.isEmpty())
|
||||
entry.extraInfo.append("::");
|
||||
entry.extraInfo.append(parent.displayName);
|
||||
|
||||
// TODO: Can we extend clangd to send visibility information?
|
||||
docEntries.append({entry, info});
|
||||
return entry;
|
||||
};
|
||||
// TODO: Pass promise into currentSymbols
|
||||
const LocatorFilterEntries allMatches = LanguageClient::currentDocumentSymbols(storage.input(),
|
||||
currentSymbolsData, docSymbolModifier);
|
||||
if (docEntries.isEmpty()) {
|
||||
storage.reportOutput(allMatches);
|
||||
return; // SymbolInformation case
|
||||
}
|
||||
|
||||
QTC_CHECK(docEntries.size() == allMatches.size());
|
||||
QHash<QString, QList<Entry>> possibleDuplicates;
|
||||
for (const Entry &e : std::as_const(docEntries))
|
||||
possibleDuplicates[e.entry.displayName + e.entry.extraInfo] << e;
|
||||
const QTextDocument doc(contents);
|
||||
for (auto it = possibleDuplicates.cbegin(); it != possibleDuplicates.cend(); ++it) {
|
||||
const QList<Entry> &duplicates = it.value();
|
||||
if (duplicates.size() == 1)
|
||||
continue;
|
||||
QList<Entry> declarations;
|
||||
QList<Entry> definitions;
|
||||
for (const Entry &candidate : duplicates) {
|
||||
const DocumentSymbol symbol = candidate.symbol;
|
||||
const SymbolKind kind = static_cast<SymbolKind>(symbol.kind());
|
||||
if (kind != SymbolKind::Class && kind != SymbolKind::Function)
|
||||
break;
|
||||
const Range range = symbol.range();
|
||||
const Range selectionRange = symbol.selectionRange();
|
||||
if (kind == SymbolKind::Class) {
|
||||
if (range.end() == selectionRange.end())
|
||||
declarations << candidate;
|
||||
else
|
||||
definitions << candidate;
|
||||
continue;
|
||||
}
|
||||
const int startPos = selectionRange.end().toPositionInDocument(&doc);
|
||||
const int endPos = range.end().toPositionInDocument(&doc);
|
||||
const QString functionBody = contents.mid(startPos, endPos - startPos);
|
||||
|
||||
// Hacky, but I don't see anything better.
|
||||
if (functionBody.contains('{') && functionBody.contains('}'))
|
||||
definitions << candidate;
|
||||
else
|
||||
declarations << candidate;
|
||||
}
|
||||
if (definitions.size() == 1
|
||||
&& declarations.size() + definitions.size() == duplicates.size()) {
|
||||
for (const Entry &decl : std::as_const(declarations)) {
|
||||
Utils::erase(docEntries, [&decl](const Entry &e) {
|
||||
return e.symbol == decl.symbol;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
storage.reportOutput(Utils::transform(docEntries,
|
||||
[](const Entry &entry) { return entry.entry; }));
|
||||
}
|
||||
|
||||
LocatorMatcherTask currentDocumentMatcher()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
TreeStorage<LocatorStorage> storage;
|
||||
TreeStorage<CurrentDocumentSymbolsData> resultStorage;
|
||||
|
||||
const auto onQuerySetup = [=](CurrentDocumentSymbolsRequestTask &request) {
|
||||
Q_UNUSED(request)
|
||||
};
|
||||
const auto onQueryDone = [resultStorage](const CurrentDocumentSymbolsRequestTask &request) {
|
||||
*resultStorage = request.currentDocumentSymbolsData();
|
||||
};
|
||||
|
||||
const auto onFilterSetup = [=](AsyncTask<void> &async) {
|
||||
async.setFutureSynchronizer(ExtensionSystem::PluginManager::futureSynchronizer());
|
||||
async.setConcurrentCallData(filterCurrentResults, *storage, *resultStorage,
|
||||
TextDocument::currentTextDocument()->plainText());
|
||||
};
|
||||
|
||||
const Group root {
|
||||
Storage(resultStorage),
|
||||
CurrentDocumentSymbolsRequest(onQuerySetup, onQueryDone),
|
||||
Async<void>(onFilterSetup)
|
||||
};
|
||||
return {root, storage};
|
||||
}
|
||||
|
||||
LocatorMatcherTasks ClangdCurrentDocumentFilter::matchers()
|
||||
{
|
||||
const auto doc = TextDocument::currentTextDocument();
|
||||
QTC_ASSERT(doc, return {});
|
||||
if (const ClangdClient *client = ClangModelManagerSupport::clientForFile(doc->filePath());
|
||||
client && client->reachable()) {
|
||||
return {currentDocumentMatcher()};
|
||||
}
|
||||
return CppEditor::cppMatchers(MatcherType::CurrentDocumentSymbols);
|
||||
}
|
||||
|
||||
void ClangdCurrentDocumentFilter::prepareSearch(const QString &entry)
|
||||
{
|
||||
const auto doc = TextEditor::TextDocument::currentTextDocument();
|
||||
|
@@ -54,6 +54,7 @@ public:
|
||||
~ClangdCurrentDocumentFilter() override;
|
||||
|
||||
private:
|
||||
Core::LocatorMatcherTasks matchers() final;
|
||||
void prepareSearch(const QString &entry) override;
|
||||
QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
|
||||
const QString &entry) override;
|
||||
|
Reference in New Issue
Block a user