diff --git a/kdevplatform/language/interfaces/abbreviations.h b/kdevplatform/language/interfaces/abbreviations.h --- a/kdevplatform/language/interfaces/abbreviations.h +++ b/kdevplatform/language/interfaces/abbreviations.h @@ -61,8 +61,7 @@ /** * @brief Matches a path against a list of search fragments. */ -KDEVPLATFORMLANGUAGE_EXPORT PathFilterMatchQuality matchPathFilter(const Path& toFilter, const QStringList& text, - const QString& joinedText); +KDEVPLATFORMLANGUAGE_EXPORT PathFilterMatchQuality matchPathFilter(const Path& toFilter, const QStringList& text); } #endif diff --git a/kdevplatform/language/interfaces/abbreviations.cpp b/kdevplatform/language/interfaces/abbreviations.cpp --- a/kdevplatform/language/interfaces/abbreviations.cpp +++ b/kdevplatform/language/interfaces/abbreviations.cpp @@ -154,8 +154,7 @@ return matchedFragments == typedFragments.size(); } -PathFilterMatchQuality matchPathFilter(const Path &toFilter, const QStringList &text, - const QString &joinedText) +PathFilterMatchQuality matchPathFilter(const Path &toFilter, const QStringList &text) { const QVector& segments = toFilter.segments(); @@ -189,7 +188,15 @@ const QString& segment = segments.at(pathIndex); const QString& typedSegment = text.at(searchIndex); lastMatchIndex = segment.indexOf(typedSegment, 0, Qt::CaseInsensitive); - if (lastMatchIndex == -1 && !matchesAbbreviation(segment.midRef(0), typedSegment)) { + bool isMatch = lastMatchIndex != -1; + // do fuzzy path matching on the last segment + if (!isMatch && searchIndex == text.size() - 1 && pathIndex == segments.size() - 1) { + isMatch = matchesPath(segment, typedSegment); + } else if (!isMatch) { + isMatch = matchesAbbreviation(segment.midRef(0), typedSegment); + } + + if (!isMatch) { // no match, try with next path segment ++pathIndex; continue; @@ -200,9 +207,7 @@ } if (searchIndex != text.size()) { - if ( ! matchesPath(segments.last(), joinedText) ) { - return PathFilterMatchQuality::NoMatch; - } + return PathFilterMatchQuality::NoMatch; } // prefer matches whose last element starts with the filter diff --git a/kdevplatform/language/interfaces/quickopenfilter.h b/kdevplatform/language/interfaces/quickopenfilter.h --- a/kdevplatform/language/interfaces/quickopenfilter.h +++ b/kdevplatform/language/interfaces/quickopenfilter.h @@ -180,8 +180,6 @@ return; } - const QString joinedText = text.join(QString()); - QVector filterBase = m_filtered; if ( m_oldFilterText.isEmpty()) { @@ -204,8 +202,7 @@ // all other matches are sorted by where they match, we prefer matches at the end QVector otherMatches; foreach( const Item& data, filterBase ) { - const auto matchQuality = matchPathFilter(static_cast(this)->itemPath(data), - text, joinedText); + const auto matchQuality = matchPathFilter(static_cast(this)->itemPath(data), text); switch (matchQuality) { case PathFilterMatchQuality::NoMatch: break; diff --git a/plugins/quickopen/tests/test_quickopen.cpp b/plugins/quickopen/tests/test_quickopen.cpp --- a/plugins/quickopen/tests/test_quickopen.cpp +++ b/plugins/quickopen/tests/test_quickopen.cpp @@ -204,6 +204,35 @@ { QTest::newRow("duplicate") << StringList({ QStringLiteral("/muh/kuh/asdf/foo") }) << QStringLiteral("kuh/kuh") << StringList(); } + { + const StringList fuzzyItems = { + QStringLiteral("/foo/bar.h"), + QStringLiteral("/foo/fooXbar.h"), + QStringLiteral("/foo/fXoXoXbXaXr.h"), + QStringLiteral("/bar/FOOxBAR.h") + }; + + QTest::newRow("fuzzy1") << fuzzyItems << QStringLiteral("br") << fuzzyItems; + QTest::newRow("fuzzy2") << fuzzyItems << QStringLiteral("foo/br") << StringList({ + QStringLiteral("/foo/bar.h"), + QStringLiteral("/foo/fooXbar.h"), + QStringLiteral("/foo/fXoXoXbXaXr.h") + }); + QTest::newRow("fuzzy3") << fuzzyItems << QStringLiteral("b/br") << StringList({ + QStringLiteral("/bar/FOOxBAR.h") + }); + QTest::newRow("fuzzy4") << fuzzyItems << QStringLiteral("br/br") << StringList(); + QTest::newRow("fuzzy5") << fuzzyItems << QStringLiteral("foo/bar") << StringList({ + QStringLiteral("/foo/bar.h"), + QStringLiteral("/foo/fooXbar.h"), + QStringLiteral("/foo/fXoXoXbXaXr.h") + }); + QTest::newRow("fuzzy6") << fuzzyItems << QStringLiteral("foobar") << StringList({ + QStringLiteral("/foo/fooXbar.h"), + QStringLiteral("/foo/fXoXoXbXaXr.h"), + QStringLiteral("/bar/FOOxBAR.h") + }); + } } void TestQuickOpen::testProjectFileFilter()