forked from qt-creator/qt-creator
CppLocatorFilter: Introduce cpp matchers
Change-Id: I7a9d3713a941c46ea8412a26743cdfcfa5791892 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -85,6 +85,7 @@
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/fsengine/fileiconprovider.h>
|
||||
#include <utils/futuresynchronizer.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/macroexpander.h>
|
||||
#include <utils/mimeutils.h>
|
||||
@@ -198,6 +199,7 @@ public:
|
||||
ClangdSettingsPage *m_clangdSettingsPage = nullptr;
|
||||
CppCodeStyleSettingsPage m_cppCodeStyleSettingsPage;
|
||||
CppProjectUpdaterFactory m_cppProjectUpdaterFactory;
|
||||
FutureSynchronizer m_futureSynchronizer;
|
||||
};
|
||||
|
||||
static CppEditorPlugin *m_instance = nullptr;
|
||||
@@ -631,6 +633,12 @@ bool CppEditorPlugin::usePragmaOnce()
|
||||
return m_instance->d->m_fileSettings.headerPragmaOnce;
|
||||
}
|
||||
|
||||
FutureSynchronizer *CppEditorPlugin::futureSynchronizer()
|
||||
{
|
||||
QTC_ASSERT(m_instance, return nullptr);
|
||||
return &m_instance->d->m_futureSynchronizer;
|
||||
}
|
||||
|
||||
const QStringList &CppEditorPlugin::headerSearchPaths()
|
||||
{
|
||||
return m_instance->d->m_fileSettings.headerSearchPaths;
|
||||
|
@@ -5,7 +5,10 @@
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
namespace Utils { class FilePath; }
|
||||
namespace Utils {
|
||||
class FilePath;
|
||||
class FutureSynchronizer;
|
||||
}
|
||||
|
||||
namespace CppEditor {
|
||||
class CppCodeModelSettings;
|
||||
@@ -37,6 +40,7 @@ public:
|
||||
static Utils::FilePath licenseTemplatePath();
|
||||
static QString licenseTemplate();
|
||||
static bool usePragmaOnce();
|
||||
static Utils::FutureSynchronizer *futureSynchronizer();
|
||||
|
||||
void openDeclarationDefinitionInNextSplit();
|
||||
void openTypeHierarchy();
|
||||
|
@@ -4,17 +4,165 @@
|
||||
#include "cpplocatorfilter.h"
|
||||
|
||||
#include "cppeditorconstants.h"
|
||||
#include "cppeditorplugin.h"
|
||||
#include "cppeditortr.h"
|
||||
#include "cpplocatordata.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/asynctask.h>
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
using namespace Core;
|
||||
using namespace Utils;
|
||||
|
||||
namespace CppEditor {
|
||||
|
||||
using EntryFromIndex = std::function<LocatorFilterEntry(const IndexItem::Ptr &)>;
|
||||
|
||||
void matchesFor(QPromise<LocatorMatcherTask::OutputData> &promise, const QString &entry,
|
||||
IndexItem::ItemType wantedType, const EntryFromIndex &converter)
|
||||
{
|
||||
QList<LocatorFilterEntry> entries[int(ILocatorFilter::MatchLevel::Count)];
|
||||
const Qt::CaseSensitivity caseSensitivityForPrefix = ILocatorFilter::caseSensitivity(entry);
|
||||
const QRegularExpression regexp = ILocatorFilter::createRegExp(entry);
|
||||
if (!regexp.isValid())
|
||||
return;
|
||||
|
||||
const bool hasColonColon = entry.contains("::");
|
||||
const QRegularExpression shortRegexp = hasColonColon
|
||||
? ILocatorFilter::createRegExp(entry.mid(entry.lastIndexOf("::") + 2)) : regexp;
|
||||
CppLocatorData *locatorData = CppModelManager::instance()->locatorData();
|
||||
locatorData->filterAllFiles([&](const IndexItem::Ptr &info) {
|
||||
if (promise.isCanceled())
|
||||
return IndexItem::Break;
|
||||
const IndexItem::ItemType type = info->type();
|
||||
if (type & wantedType) {
|
||||
const QString symbolName = info->symbolName();
|
||||
QString matchString = hasColonColon ? info->scopedSymbolName() : symbolName;
|
||||
int matchOffset = hasColonColon ? matchString.size() - symbolName.size() : 0;
|
||||
QRegularExpressionMatch match = regexp.match(matchString);
|
||||
bool matchInParameterList = false;
|
||||
if (!match.hasMatch() && (type == IndexItem::Function)) {
|
||||
matchString += info->symbolType();
|
||||
match = regexp.match(matchString);
|
||||
matchInParameterList = true;
|
||||
}
|
||||
|
||||
if (match.hasMatch()) {
|
||||
LocatorFilterEntry filterEntry = converter(info);
|
||||
|
||||
// Highlight the matched characters, therefore it may be necessary
|
||||
// to update the match if the displayName is different from matchString
|
||||
if (QStringView(matchString).mid(matchOffset) != filterEntry.displayName) {
|
||||
match = shortRegexp.match(filterEntry.displayName);
|
||||
matchOffset = 0;
|
||||
}
|
||||
filterEntry.highlightInfo = ILocatorFilter::highlightInfo(match);
|
||||
if (matchInParameterList && filterEntry.highlightInfo.startsDisplay.isEmpty()) {
|
||||
match = regexp.match(filterEntry.extraInfo);
|
||||
filterEntry.highlightInfo = ILocatorFilter::highlightInfo(
|
||||
match, LocatorFilterEntry::HighlightInfo::ExtraInfo);
|
||||
} else if (matchOffset > 0) {
|
||||
for (int &start : filterEntry.highlightInfo.startsDisplay)
|
||||
start -= matchOffset;
|
||||
}
|
||||
|
||||
if (matchInParameterList)
|
||||
entries[int(ILocatorFilter::MatchLevel::Normal)].append(filterEntry);
|
||||
else if (filterEntry.displayName.startsWith(entry, caseSensitivityForPrefix))
|
||||
entries[int(ILocatorFilter::MatchLevel::Best)].append(filterEntry);
|
||||
else if (filterEntry.displayName.contains(entry, caseSensitivityForPrefix))
|
||||
entries[int(ILocatorFilter::MatchLevel::Better)].append(filterEntry);
|
||||
else
|
||||
entries[int(ILocatorFilter::MatchLevel::Good)].append(filterEntry);
|
||||
}
|
||||
}
|
||||
|
||||
if (info->type() & IndexItem::Enum)
|
||||
return IndexItem::Continue;
|
||||
return IndexItem::Recurse;
|
||||
});
|
||||
|
||||
for (auto &entry : entries) {
|
||||
if (entry.size() < 1000)
|
||||
Utils::sort(entry, LocatorFilterEntry::compareLexigraphically);
|
||||
}
|
||||
|
||||
promise.addResult(std::accumulate(std::begin(entries), std::end(entries),
|
||||
QList<LocatorFilterEntry>()));
|
||||
}
|
||||
|
||||
LocatorMatcherTask locatorMatcher(IndexItem::ItemType type, const EntryFromIndex &converter)
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
TreeStorage<LocatorMatcherTask::Storage> storage;
|
||||
|
||||
const auto onSetup = [=](AsyncTask<LocatorMatcherTask::OutputData> &async) {
|
||||
async.setFutureSynchronizer(Internal::CppEditorPlugin::futureSynchronizer());
|
||||
async.setConcurrentCallData(matchesFor, storage->input, type, converter);
|
||||
};
|
||||
const auto onDone = [storage](const AsyncTask<LocatorMatcherTask::OutputData> &async) {
|
||||
if (async.isResultAvailable())
|
||||
storage->output = async.result();
|
||||
};
|
||||
return {Async<LocatorMatcherTask::OutputData>(onSetup, onDone, onDone), storage};
|
||||
}
|
||||
|
||||
LocatorMatcherTask cppLocatorMatcher()
|
||||
{
|
||||
const auto converter = [](const IndexItem::Ptr &info) {
|
||||
// TODO: Passing nullptr for filter -> accept won't work now. Replace with accept function.
|
||||
LocatorFilterEntry filterEntry(nullptr, info->scopedSymbolName());
|
||||
filterEntry.displayIcon = info->icon();
|
||||
filterEntry.linkForEditor = {info->filePath(), info->line(), info->column()};
|
||||
if (info->type() == IndexItem::Class || info->type() == IndexItem::Enum)
|
||||
filterEntry.extraInfo = info->shortNativeFilePath();
|
||||
else
|
||||
filterEntry.extraInfo = info->symbolType();
|
||||
return filterEntry;
|
||||
};
|
||||
return locatorMatcher(IndexItem::All, converter);
|
||||
}
|
||||
|
||||
LocatorMatcherTask cppClassMatcher()
|
||||
{
|
||||
const auto converter = [](const IndexItem::Ptr &info) {
|
||||
// TODO: Passing nullptr for filter -> accept won't work now. Replace with accept function.
|
||||
LocatorFilterEntry filterEntry(nullptr, info->symbolName());
|
||||
filterEntry.displayIcon = info->icon();
|
||||
filterEntry.linkForEditor = {info->filePath(), info->line(), info->column()};
|
||||
filterEntry.extraInfo = info->symbolScope().isEmpty()
|
||||
? info->shortNativeFilePath()
|
||||
: info->symbolScope();
|
||||
filterEntry.filePath = info->filePath();
|
||||
return filterEntry;
|
||||
};
|
||||
return locatorMatcher(IndexItem::Class, converter);
|
||||
}
|
||||
|
||||
LocatorMatcherTask cppFunctionMatcher()
|
||||
{
|
||||
const auto converter = [](const IndexItem::Ptr &info) {
|
||||
QString name = info->symbolName();
|
||||
QString extraInfo = info->symbolScope();
|
||||
info->unqualifiedNameAndScope(name, &name, &extraInfo);
|
||||
if (extraInfo.isEmpty())
|
||||
extraInfo = info->shortNativeFilePath();
|
||||
else
|
||||
extraInfo.append(" (" + info->filePath().fileName() + ')');
|
||||
// TODO: Passing nullptr for filter -> accept won't work now. Replace with accept function.
|
||||
LocatorFilterEntry filterEntry(nullptr, name + info->symbolType());
|
||||
filterEntry.displayIcon = info->icon();
|
||||
filterEntry.linkForEditor = {info->filePath(), info->line(), info->column()};
|
||||
filterEntry.extraInfo = extraInfo;
|
||||
|
||||
return filterEntry;
|
||||
};
|
||||
return locatorMatcher(IndexItem::Function, converter);
|
||||
}
|
||||
|
||||
CppLocatorFilter::CppLocatorFilter()
|
||||
{
|
||||
setId(Constants::LOCATOR_FILTER_ID);
|
||||
|
@@ -10,6 +10,10 @@
|
||||
|
||||
namespace CppEditor {
|
||||
|
||||
Core::LocatorMatcherTask CPPEDITOR_EXPORT cppLocatorMatcher();
|
||||
Core::LocatorMatcherTask CPPEDITOR_EXPORT cppClassMatcher();
|
||||
Core::LocatorMatcherTask CPPEDITOR_EXPORT cppFunctionMatcher();
|
||||
|
||||
class CPPEDITOR_EXPORT CppLocatorFilter : public Core::ILocatorFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
Reference in New Issue
Block a user