BaseFileFilter: Rate full matches higher than fuzzy matches

Searching for "qmap.h" should not have "qcore_mac_p.h" as
first search result and "qmap.h" somewhere later in the list.

This is only a partial solution for QTCREATORBUG-19531, as the
filter might be called multiple times (for "All Included Files"
and "Files in Any Project"). So the final result list may contain
the best results in the middle.

Task-number: QTCREATORBUG-19531
Change-Id: Ib5322824d3e0e8106c2f197169342f18923a894a
Reviewed-by: André Hartmann <aha_1980@gmx.de>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Andre Hartmann
2017-12-29 07:57:01 +01:00
committed by André Hartmann
parent 8e92c28573
commit adc8638de0
2 changed files with 42 additions and 10 deletions

View File

@@ -93,17 +93,31 @@ void BaseFileFilter::prepareSearch(const QString &entry)
d->m_data.forceNewSearchList = false;
}
static int matchLevelFor(const QRegularExpressionMatch &match, const QString &matchText)
{
const int consecutivePos = match.capturedStart(1);
if (consecutivePos == 0)
return 0;
if (consecutivePos > 0) {
const QChar prevChar = matchText.at(consecutivePos - 1);
if (prevChar == '_' || prevChar == '.')
return 1;
}
if (match.capturedStart() == 0)
return 2;
return 3;
}
QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFilterEntry> &future, const QString &origEntry)
{
QList<LocatorFilterEntry> betterEntries;
QList<LocatorFilterEntry> goodEntries;
QList<LocatorFilterEntry> entries[4];
const QString entry = QDir::fromNativeSeparators(origEntry);
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
const QRegularExpression regexp = createRegExp(fp.filePath);
if (!regexp.isValid()) {
d->m_current.clear(); // free memory
return betterEntries;
return entries[0];
}
const QChar pathSeparator('/');
const bool hasPathSeparator = fp.filePath.contains(pathSeparator);
@@ -141,7 +155,7 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
filterEntry.fileName = path;
filterEntry.extraInfo = FileUtils::shortNativePath(FileName(fi));
const bool betterMatch = match.capturedStart() == 0;
const int matchLevel = matchLevelFor(match, matchText);
if (hasPathSeparator) {
match = regexp.match(filterEntry.extraInfo);
filterEntry.highlightInfo =
@@ -150,16 +164,12 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
filterEntry.highlightInfo = highlightInfo(match);
}
if (betterMatch)
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
entries[matchLevel].append(filterEntry);
d->m_current.previousResultPaths.append(path);
d->m_current.previousResultNames.append(name);
}
}
betterEntries.append(goodEntries);
if (canceled) {
// we keep the old list of previous search results if this search was canceled
// so a later search without forceNewSearchList will use that previous list instead of an
@@ -169,7 +179,7 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
d->m_current.iterator.clear();
QTimer::singleShot(0, this, &BaseFileFilter::updatePreviousResultData);
}
return betterEntries;
return entries[0] + entries[1] + entries[2] + entries[3];
}
void BaseFileFilter::accept(LocatorFilterEntry selection,

View File

@@ -158,4 +158,26 @@ void Core::Internal::CorePlugin::test_basefilefilter_data()
<< ResultData("main.cpp", testFilesShort.at(1))
<< ResultData("main.cpp", testFilesShort.at(2))))
);
const QStringList priorityTestFiles({testDir.file("qmap.cpp"),
testDir.file("mid_qcore_mac_p.h"),
testDir.file("qcore_mac_p.h"),
testDir.file("foo_qmap.h"),
testDir.file("qmap.h"),
testDir.file("bar.h")});
QStringList priorityTestFilesShort;
for (const QString &file : priorityTestFiles)
priorityTestFilesShort << Utils::FileUtils::shortNativePath(Utils::FileName::fromString(file));
QTest::newRow("BaseFileFilter-InputPriorizeFullOverFuzzy")
<< priorityTestFiles
<< (QList<ReferenceData>()
<< ReferenceData(
"qmap.h",
(QList<ResultData>()
<< ResultData("qmap.h", priorityTestFilesShort.at(4))
<< ResultData("foo_qmap.h", priorityTestFilesShort.at(3))
<< ResultData("qcore_mac_p.h", priorityTestFilesShort.at(2))
<< ResultData("mid_qcore_mac_p.h", priorityTestFilesShort.at(1))))
);
}