FileSystemFilter: Convert to FuzzyMatcher

Fixes: QTCREATORBUG-18960
Change-Id: I7125362e77d7f079eec0cdcc270438cc98ca9407
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Andre Hartmann
2019-07-14 08:10:50 +02:00
committed by André Hartmann
parent 857b299356
commit 40921421ae
5 changed files with 63 additions and 37 deletions

View File

@@ -122,6 +122,21 @@ QRegularExpression FuzzyMatcher::createRegExp(
return QRegularExpression('(' + plainRegExp + ")|" + keyRegExp);
}
/**
\overload
This overload eases the construction of a fuzzy regexp from a given
Qt::CaseSensitivity.
*/
QRegularExpression FuzzyMatcher::createRegExp(const QString &pattern,
Qt::CaseSensitivity caseSensitivity)
{
const CaseSensitivity sensitivity = (caseSensitivity == Qt::CaseSensitive)
? CaseSensitivity::CaseSensitive
: CaseSensitivity::CaseInsensitive;
return createRegExp(pattern, sensitivity);
}
/*!
* \brief Returns a list of matched character positions and their matched lengths for the
* given regular expression \a match.

View File

@@ -54,5 +54,7 @@ public:
static QRegularExpression createRegExp(const QString &pattern,
CaseSensitivity caseSensitivity = CaseSensitivity::CaseInsensitive);
static QRegularExpression createRegExp(const QString &pattern,
Qt::CaseSensitivity caseSensitivity);
static HighlightingPositions highlightingPositions(const QRegularExpressionMatch &match);
};

View File

@@ -35,30 +35,34 @@
#include <utils/fileutils.h>
#include <QDir>
#include <QRegularExpression>
using namespace Core;
using namespace Core::Internal;
namespace {
enum class MatchLevel {
Best = 0,
Better,
Good,
Normal,
Number
};
QList<LocatorFilterEntry> *categorize(const QString &entry, const QString &candidate,
Qt::CaseSensitivity caseSensitivity,
QList<LocatorFilterEntry> *betterEntries, QList<LocatorFilterEntry> *goodEntries,
int *index)
static MatchLevel matchLevelFor(const QRegularExpressionMatch &match, const QString &matchText)
{
const int position = candidate.indexOf(entry, 0, caseSensitivity);
if (index)
*index = position;
if (entry.isEmpty() || position == 0)
return betterEntries;
if (position >= 0)
return goodEntries;
return nullptr;
const int consecutivePos = match.capturedStart(1);
if (consecutivePos == 0)
return MatchLevel::Best;
if (consecutivePos > 0) {
const QChar prevChar = matchText.at(consecutivePos - 1);
if (prevChar == '_' || prevChar == '.')
return MatchLevel::Better;
}
if (match.capturedStart() == 0)
return MatchLevel::Good;
return MatchLevel::Normal;
}
} // anynoumous namespace
FileSystemFilter::FileSystemFilter()
{
setId("Files in file system");
@@ -76,8 +80,7 @@ void FileSystemFilter::prepareSearch(const QString &entry)
QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorFilterEntry> &future,
const QString &entry)
{
QList<LocatorFilterEntry> goodEntries;
QList<LocatorFilterEntry> betterEntries;
QList<LocatorFilterEntry> entries[int(MatchLevel::Number)];
const QFileInfo entryInfo(entry);
const QString entryFileName = entryInfo.fileName();
QString directory = entryInfo.path();
@@ -101,19 +104,24 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
+ dirInfo.entryList(dirFilter, QDir::Name|QDir::IgnoreCase|QDir::LocaleAware);
const QStringList files = dirInfo.entryList(fileFilter,
QDir::Name|QDir::IgnoreCase|QDir::LocaleAware);
const QRegularExpression regExp = createRegExp(entryFileName, caseSensitivity_);
if (!regExp.isValid())
return {};
for (const QString &dir : dirs) {
if (future.isCanceled())
break;
int index = -1;
if (QList<LocatorFilterEntry> *category = categorize(entryFileName, dir, caseSensitivity_,
&betterEntries, &goodEntries, &index)) {
const QRegularExpressionMatch match = regExp.match(dir);
if (match.hasMatch()) {
const MatchLevel level = matchLevelFor(match, dir);
const QString fullPath = dirInfo.filePath(dir);
LocatorFilterEntry filterEntry(this, dir, QVariant());
filterEntry.fileName = fullPath;
if (index >= 0)
filterEntry.highlightInfo = {index, entryFileName.length()};
filterEntry.highlightInfo = highlightInfo(match);
category->append(filterEntry);
entries[int(level)].append(filterEntry);
}
}
// file names can match with +linenumber or :linenumber
@@ -122,29 +130,29 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
for (const QString &file : files) {
if (future.isCanceled())
break;
int index = -1;
if (QList<LocatorFilterEntry> *category = categorize(fileName, file, caseSensitivity_,
&betterEntries, &goodEntries, &index)) {
const QRegularExpressionMatch match = regExp.match(file);
if (match.hasMatch()) {
const MatchLevel level = matchLevelFor(match, file);
const QString fullPath = dirInfo.filePath(file);
LocatorFilterEntry filterEntry(this, file, QString(fullPath + fp.postfix));
filterEntry.fileName = fullPath;
if (index >= 0)
filterEntry.highlightInfo = {index, fileName.length()};
filterEntry.highlightInfo = highlightInfo(match);
category->append(filterEntry);
entries[int(level)].append(filterEntry);
}
}
betterEntries.append(goodEntries);
// "create and open" functionality
const QString fullFilePath = dirInfo.filePath(fileName);
if (!QFileInfo::exists(fullFilePath) && dirInfo.exists()) {
const bool containsWildcard = entry.contains('?') || entry.contains('*');
if (!containsWildcard && !QFileInfo::exists(fullFilePath) && dirInfo.exists()) {
LocatorFilterEntry createAndOpen(this, tr("Create and Open \"%1\"").arg(entry), fullFilePath);
createAndOpen.extraInfo = Utils::FilePath::fromString(dirInfo.absolutePath()).shortNativePath();
betterEntries.append(createAndOpen);
entries[int(MatchLevel::Normal)].append(createAndOpen);
}
return betterEntries;
return std::accumulate(std::begin(entries), std::end(entries), QList<LocatorFilterEntry>());
}
void FileSystemFilter::accept(LocatorFilterEntry selection,

View File

@@ -207,9 +207,9 @@ Qt::CaseSensitivity ILocatorFilter::caseSensitivity(const QString &str)
return str == str.toLower() ? Qt::CaseInsensitive : Qt::CaseSensitive;
}
QRegularExpression ILocatorFilter::createRegExp(const QString &text)
QRegularExpression ILocatorFilter::createRegExp(const QString &text, Qt::CaseSensitivity caseSensitivity)
{
return FuzzyMatcher::createRegExp(text);
return FuzzyMatcher::createRegExp(text, caseSensitivity);
}
LocatorFilterEntry::HighlightInfo ILocatorFilter::highlightInfo(

View File

@@ -145,7 +145,8 @@ public:
bool isEnabled() const;
static Qt::CaseSensitivity caseSensitivity(const QString &str);
static QRegularExpression createRegExp(const QString &text);
static QRegularExpression createRegExp(const QString &text,
Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive);
LocatorFilterEntry::HighlightInfo highlightInfo(const QRegularExpressionMatch &match,
LocatorFilterEntry::HighlightInfo::DataType dataType = LocatorFilterEntry::HighlightInfo::DisplayName);