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/algorithm.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/fsengine/fileiconprovider.h>
|
#include <utils/fsengine/fileiconprovider.h>
|
||||||
|
#include <utils/futuresynchronizer.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/macroexpander.h>
|
#include <utils/macroexpander.h>
|
||||||
#include <utils/mimeutils.h>
|
#include <utils/mimeutils.h>
|
||||||
@@ -198,6 +199,7 @@ public:
|
|||||||
ClangdSettingsPage *m_clangdSettingsPage = nullptr;
|
ClangdSettingsPage *m_clangdSettingsPage = nullptr;
|
||||||
CppCodeStyleSettingsPage m_cppCodeStyleSettingsPage;
|
CppCodeStyleSettingsPage m_cppCodeStyleSettingsPage;
|
||||||
CppProjectUpdaterFactory m_cppProjectUpdaterFactory;
|
CppProjectUpdaterFactory m_cppProjectUpdaterFactory;
|
||||||
|
FutureSynchronizer m_futureSynchronizer;
|
||||||
};
|
};
|
||||||
|
|
||||||
static CppEditorPlugin *m_instance = nullptr;
|
static CppEditorPlugin *m_instance = nullptr;
|
||||||
@@ -631,6 +633,12 @@ bool CppEditorPlugin::usePragmaOnce()
|
|||||||
return m_instance->d->m_fileSettings.headerPragmaOnce;
|
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()
|
const QStringList &CppEditorPlugin::headerSearchPaths()
|
||||||
{
|
{
|
||||||
return m_instance->d->m_fileSettings.headerSearchPaths;
|
return m_instance->d->m_fileSettings.headerSearchPaths;
|
||||||
|
@@ -5,7 +5,10 @@
|
|||||||
|
|
||||||
#include <extensionsystem/iplugin.h>
|
#include <extensionsystem/iplugin.h>
|
||||||
|
|
||||||
namespace Utils { class FilePath; }
|
namespace Utils {
|
||||||
|
class FilePath;
|
||||||
|
class FutureSynchronizer;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CppEditor {
|
namespace CppEditor {
|
||||||
class CppCodeModelSettings;
|
class CppCodeModelSettings;
|
||||||
@@ -37,6 +40,7 @@ public:
|
|||||||
static Utils::FilePath licenseTemplatePath();
|
static Utils::FilePath licenseTemplatePath();
|
||||||
static QString licenseTemplate();
|
static QString licenseTemplate();
|
||||||
static bool usePragmaOnce();
|
static bool usePragmaOnce();
|
||||||
|
static Utils::FutureSynchronizer *futureSynchronizer();
|
||||||
|
|
||||||
void openDeclarationDefinitionInNextSplit();
|
void openDeclarationDefinitionInNextSplit();
|
||||||
void openTypeHierarchy();
|
void openTypeHierarchy();
|
||||||
|
@@ -4,17 +4,165 @@
|
|||||||
#include "cpplocatorfilter.h"
|
#include "cpplocatorfilter.h"
|
||||||
|
|
||||||
#include "cppeditorconstants.h"
|
#include "cppeditorconstants.h"
|
||||||
|
#include "cppeditorplugin.h"
|
||||||
#include "cppeditortr.h"
|
#include "cppeditortr.h"
|
||||||
#include "cpplocatordata.h"
|
#include "cpplocatordata.h"
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/asynctask.h>
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace CppEditor {
|
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()
|
CppLocatorFilter::CppLocatorFilter()
|
||||||
{
|
{
|
||||||
setId(Constants::LOCATOR_FILTER_ID);
|
setId(Constants::LOCATOR_FILTER_ID);
|
||||||
|
@@ -10,6 +10,10 @@
|
|||||||
|
|
||||||
namespace CppEditor {
|
namespace CppEditor {
|
||||||
|
|
||||||
|
Core::LocatorMatcherTask CPPEDITOR_EXPORT cppLocatorMatcher();
|
||||||
|
Core::LocatorMatcherTask CPPEDITOR_EXPORT cppClassMatcher();
|
||||||
|
Core::LocatorMatcherTask CPPEDITOR_EXPORT cppFunctionMatcher();
|
||||||
|
|
||||||
class CPPEDITOR_EXPORT CppLocatorFilter : public Core::ILocatorFilter
|
class CPPEDITOR_EXPORT CppLocatorFilter : public Core::ILocatorFilter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Reference in New Issue
Block a user