Commit 632f2a77 authored by Andre Hartmann's avatar Andre Hartmann Committed by André Hartmann

Locator: Add camel hump locator filter for C++, QML, and files

* Use the CamelHumpMatcher in the C++, QML, and files filters
* Supports matching against UpperCamelCase, lowerCamelCase
  and snake_case strings
* Supports highlighting of matched characters

Task-number: QTCREATORBUG-3111
Started-by: default avatarDavid Kaspar <dkaspar@blackberry.com>
Change-Id: If6220191432ef965bde3c8dbe4a10d89e222ba6f
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
Reviewed-by: Eike Ziller's avatarEike Ziller <eike.ziller@qt.io>
parent 2fb54abd
......@@ -79,16 +79,19 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp(
else if (c == asterisk)
keyRegExp += ".*";
else
keyRegExp += QRegularExpression::escape(c);
keyRegExp += '(' + QRegularExpression::escape(c) + ')';
} else if (caseSensitivity == CaseSensitivity::CaseInsensitive ||
(caseSensitivity == CaseSensitivity::FirstLetterCaseSensitive && !first)) {
keyRegExp += "(?:";
keyRegExp += first ? uppercaseWordFirst : uppercaseWordContinuation;
keyRegExp += QRegularExpression::escape(c.toUpper());
keyRegExp += '|';
keyRegExp += first ? lowercaseWordFirst : lowercaseWordContinuation;
keyRegExp += QRegularExpression::escape(c.toLower());
keyRegExp += '(' + QRegularExpression::escape(c.toUpper());
if (first) {
keyRegExp += '|' + lowercaseWordFirst + QRegularExpression::escape(c.toLower()) + ')';
} else {
keyRegExp += ")|" + lowercaseWordContinuation;
keyRegExp += '(' + QRegularExpression::escape(c.toLower()) + ')';
}
keyRegExp += ')';
} else {
if (!first) {
......@@ -104,3 +107,34 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp(
}
return QRegularExpression(keyRegExp);
}
/*!
* \brief Returns a list of matched character positions and their matched lengths for the
* given regular expression \a match.
*
* The list is minimized by combining adjacent highlighting positions to a single position.
*/
CamelHumpMatcher::HighlightingPositions CamelHumpMatcher::highlightingPositions(
const QRegularExpressionMatch &match)
{
HighlightingPositions result;
for (int i = 1, size = match.capturedTexts().size(); i < size; ++i) {
// skip unused positions, they can appear because upper- and lowercase
// checks for one character are done using two capture groups
if (match.capturedStart(i) < 0)
continue;
// check for possible highlighting continuation to keep the list minimal
if (!result.starts.isEmpty()
&& (result.starts.last() + result.lengths.last() == match.capturedStart(i))) {
result.lengths.last() += match.capturedLength(i);
} else {
// no continuation, append as different chunk
result.starts.append(match.capturedStart(i));
result.lengths.append(match.capturedLength(i));
}
}
return result;
}
......@@ -29,8 +29,11 @@
#include "utils_global.h"
#include <QVector>
QT_BEGIN_NAMESPACE
class QRegularExpression;
class QRegularExpressionMatch;
class QString;
QT_END_NAMESPACE
......@@ -43,6 +46,13 @@ public:
FirstLetterCaseSensitive
};
class HighlightingPositions {
public:
QVector<int> starts;
QVector<int> lengths;
};
static QRegularExpression createCamelHumpRegExp(const QString &pattern,
CaseSensitivity caseSensitivity = CaseSensitivity::CaseInsensitive);
static HighlightingPositions highlightingPositions(const QRegularExpressionMatch &match);
};
......@@ -155,28 +155,37 @@ void HighlightingItemDelegate::drawText(QPainter *painter,
if (index.model()->hasChildren(index))
text += " (" + QString::number(index.model()->rowCount(index)) + ')';
int searchTermStart = index.model()->data(index, int(HighlightingItemRole::StartColumn)).toInt();
int searchTermLength = index.model()->data(index, int(HighlightingItemRole::Length)).toInt();
if (searchTermStart < 0 || searchTermStart >= text.length() || searchTermLength < 1) {
QVector<int> searchTermStarts =
index.model()->data(index, int(HighlightingItemRole::StartColumn)).value<QVector<int>>();
QVector<int> searchTermLengths =
index.model()->data(index, int(HighlightingItemRole::Length)).value<QVector<int>>();
if (searchTermStarts.isEmpty()) {
drawDisplay(painter, option, rect, text.replace('\t', m_tabString), {});
return;
}
// replace tabs with searchTerm bookkeeping
int searchTermEnd = searchTermStart + searchTermLength;
const int tabDiff = m_tabString.size() - 1;
for (int i = 0; i < text.length(); i++) {
if (text.at(i) == '\t') {
text.replace(i, 1, m_tabString);
if (i < searchTermStart) {
searchTermStart += tabDiff;
searchTermEnd += tabDiff;
} else if (i < searchTermEnd) {
searchTermEnd += tabDiff;
searchTermLength += tabDiff;
}
i += tabDiff;
if (text.at(i) != '\t')
continue;
text.replace(i, 1, m_tabString);
// adjust highlighting length if tab is highlighted
for (int j = 0; j < searchTermStarts.size(); ++j) {
if (i >= searchTermStarts.at(j) && i < searchTermStarts.at(j) + searchTermLengths.at(j))
searchTermLengths[j] += tabDiff;
}
// adjust all following highlighting starts
for (int j = 0; j < searchTermStarts.size(); ++j) {
if (searchTermStarts.at(j) > i)
searchTermStarts[j] += tabDiff;
}
i += tabDiff;
}
const QColor highlightForeground =
......@@ -187,7 +196,11 @@ void HighlightingItemDelegate::drawText(QPainter *painter,
highlightFormat.setForeground(highlightForeground);
highlightFormat.setBackground(highlightBackground);
drawDisplay(painter, option, rect, text, {{searchTermStart, searchTermLength, highlightFormat}});
QVector<QTextLayout::FormatRange> formats;
for (int i = 0, size = searchTermStarts.size(); i < size; ++i)
formats.append({searchTermStarts.at(i), searchTermLengths.at(i), highlightFormat});
drawDisplay(painter, option, rect, text, formats);
}
// copied from QItemDelegate for drawDisplay
......
......@@ -26,12 +26,12 @@
#include "basefilefilter.h"
#include <coreplugin/editormanager/editormanager.h>
#include <utils/camelhumpmatcher.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <QDir>
#include <QRegExp>
#include <QStringMatcher>
#include <QRegularExpression>
#include <QTimer>
using namespace Core;
......@@ -100,16 +100,15 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
QList<LocatorFilterEntry> goodEntries;
const QString entry = QDir::fromNativeSeparators(origEntry);
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
const Qt::CaseSensitivity cs = caseSensitivity(fp.filePath);
QStringMatcher matcher(fp.filePath, cs);
QRegExp regexp(fp.filePath, cs, QRegExp::Wildcard);
const QRegularExpression regexp = containsWildcard(entry)
? createWildcardRegExp(entry) : CamelHumpMatcher::createCamelHumpRegExp(entry);
if (!regexp.isValid()) {
d->m_current.clear(); // free memory
return betterEntries;
}
const QChar pathSeparator(QLatin1Char('/'));
const bool hasPathSeparator = fp.filePath.contains(pathSeparator);
const bool hasWildcard = containsWildcard(fp.filePath);
const bool containsPreviousEntry = !d->m_current.previousEntry.isEmpty()
&& fp.filePath.contains(d->m_current.previousEntry);
const bool pathSeparatorAdded = !d->m_current.previousEntry.contains(pathSeparator)
......@@ -136,27 +135,24 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
QString path = d->m_current.iterator->filePath();
QString name = d->m_current.iterator->fileName();
QString matchText = hasPathSeparator ? path : name;
int index = hasWildcard ? regexp.indexIn(matchText) : matcher.indexIn(matchText);
QRegularExpressionMatch match = regexp.match(matchText);
if (index >= 0) {
if (match.hasMatch()) {
QFileInfo fi(path);
LocatorFilterEntry filterEntry(this, fi.fileName(), QString(path + fp.postfix));
filterEntry.fileName = path;
filterEntry.extraInfo = FileUtils::shortNativePath(FileName(fi));
LocatorFilterEntry::HighlightInfo::DataType hDataType = LocatorFilterEntry::HighlightInfo::DisplayName;
int length = hasWildcard ? regexp.matchedLength() : fp.filePath.length();
const bool betterMatch = index == 0;
const bool betterMatch = match.capturedStart() == 0;
if (hasPathSeparator) {
const int indexCandidate = index + filterEntry.extraInfo.length() - path.length();
const int cutOff = indexCandidate < 0 ? -indexCandidate : 0;
index = qMax(indexCandidate, 0);
length = qMax(length - cutOff, 1);
match = regexp.match(filterEntry.extraInfo);
hDataType = LocatorFilterEntry::HighlightInfo::ExtraInfo;
}
if (index >= 0)
filterEntry.highlightInfo = LocatorFilterEntry::HighlightInfo(index, length, hDataType);
const CamelHumpMatcher::HighlightingPositions positions =
CamelHumpMatcher::highlightingPositions(match);
filterEntry.highlightInfo =
LocatorFilterEntry::HighlightInfo(positions.starts, positions.lengths, hDataType);
if (betterMatch)
betterEntries.append(filterEntry);
......
......@@ -34,6 +34,7 @@
#include <QDialogButtonBox>
#include <QLabel>
#include <QLineEdit>
#include <QRegularExpression>
using namespace Core;
......@@ -201,6 +202,25 @@ bool ILocatorFilter::containsWildcard(const QString &str)
return str.contains(QLatin1Char('*')) || str.contains(QLatin1Char('?'));
}
/*!
* \brief Returns a simple regular expression to search for \a text.
*
* \a text may contain the simple '?' and '*' wildcards known from the shell.
* '?' matches exactly one character, '*' matches a number of characters
* (including none).
*
* The regular expression contains capture groups to allow highlighting
* matched characters after a match.
*/
QRegularExpression ILocatorFilter::createWildcardRegExp(const QString &text)
{
QString pattern = '(' + text + ')';
pattern.replace('?', ").(");
pattern.replace('*', ").*(");
pattern.remove("()");
return QRegularExpression(pattern, QRegularExpression::CaseInsensitiveOption);
}
/*!
Specifies a title for configuration dialogs.
*/
......
......@@ -46,13 +46,19 @@ struct LocatorFilterEntry
};
HighlightInfo(int startIndex, int length, DataType type = DataType::DisplayName)
: startIndex(startIndex)
, length(length)
: starts{startIndex}
, lengths{length}
, dataType(type)
{}
int startIndex;
int length;
HighlightInfo(QVector<int> startIndex, QVector<int> length, DataType type = DataType::DisplayName)
: starts(startIndex)
, lengths(length)
, dataType(type)
{}
QVector<int> starts;
QVector<int> lengths;
DataType dataType;
};
......@@ -138,6 +144,7 @@ public:
static Qt::CaseSensitivity caseSensitivity(const QString &str);
static bool containsWildcard(const QString &str);
static QRegularExpression createWildcardRegExp(const QString &text);
static QString msgConfigureDialogTitle();
static QString msgPrefixLabel();
......
......@@ -217,7 +217,8 @@ QVariant LocatorModel::data(const QModelIndex &index, int role) const
: ExtraInfoColumn;
if (highlightColumn == index.column()) {
const bool startIndexRole = role == int(HighlightingItemRole::StartColumn);
return startIndexRole ? entry.highlightInfo.startIndex : entry.highlightInfo.length;
return startIndexRole ? QVariant::fromValue(entry.highlightInfo.starts)
: QVariant::fromValue(entry.highlightInfo.lengths);
}
break;
}
......
......@@ -27,12 +27,13 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <utils/camelhumpmatcher.h>
#include <utils/fileutils.h>
#include <QAbstractItemModel>
#include <QFileInfo>
#include <QMutexLocker>
#include <QRegExp>
#include <QRegularExpression>
using namespace Core;
using namespace Core::Internal;
......@@ -60,7 +61,9 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
QList<LocatorFilterEntry> goodEntries;
QList<LocatorFilterEntry> betterEntries;
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
QRegExp regexp(fp.filePath, caseSensitivity(fp.filePath), QRegExp::Wildcard);
const QRegularExpression regexp = containsWildcard(entry)
? createWildcardRegExp(entry) : CamelHumpMatcher::createCamelHumpRegExp(entry);
if (!regexp.isValid())
return goodEntries;
......@@ -71,13 +74,16 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
if (fileName.isEmpty())
continue;
QString displayName = editorEntry.displayName;
const int index = regexp.indexIn(displayName);
if (index >= 0) {
const QRegularExpressionMatch match = regexp.match(displayName);
if (match.hasMatch()) {
const CamelHumpMatcher::HighlightingPositions positions =
CamelHumpMatcher::highlightingPositions(match);
LocatorFilterEntry filterEntry(this, displayName, QString(fileName + fp.postfix));
filterEntry.extraInfo = FileUtils::shortNativePath(FileName::fromString(fileName));
filterEntry.fileName = fileName;
filterEntry.highlightInfo = {index, regexp.matchedLength()};
if (index == 0)
filterEntry.highlightInfo.starts = positions.starts;
filterEntry.highlightInfo.lengths = positions.lengths;
if (match.capturedStart() == 0)
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
......
......@@ -30,9 +30,9 @@
#include <coreplugin/idocument.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <utils/camelhumpmatcher.h>
#include <QRegExp>
#include <QStringMatcher>
#include <QRegularExpression>
using namespace CppTools::Internal;
using namespace CPlusPlus;
......@@ -66,12 +66,12 @@ QList<Core::LocatorFilterEntry> CppCurrentDocumentFilter::matchesFor(
{
QList<Core::LocatorFilterEntry> goodEntries;
QList<Core::LocatorFilterEntry> betterEntries;
const Qt::CaseSensitivity cs = caseSensitivity(entry);
QStringMatcher matcher(entry, cs);
QRegExp regexp(entry, cs, QRegExp::Wildcard);
const QRegularExpression regexp = containsWildcard(entry)
? createWildcardRegExp(entry) : CamelHumpMatcher::createCamelHumpRegExp(entry);
if (!regexp.isValid())
return goodEntries;
bool hasWildcard = containsWildcard(entry);
foreach (IndexItem::Ptr info, itemsOfCurrentDocument()) {
if (future.isCanceled())
......@@ -83,29 +83,30 @@ QList<Core::LocatorFilterEntry> CppCurrentDocumentFilter::matchesFor(
else if (info->type() == IndexItem::Function)
matchString += info->symbolType();
int index = hasWildcard ? regexp.indexIn(matchString) : matcher.indexIn(matchString);
if (index >= 0) {
const bool betterMatch = index == 0;
QRegularExpressionMatch match = regexp.match(matchString);
if (match.hasMatch()) {
const bool betterMatch = match.capturedStart() == 0;
QVariant id = qVariantFromValue(info);
QString name = matchString;
QString extraInfo = info->symbolScope();
if (info->type() == IndexItem::Function) {
if (info->unqualifiedNameAndScope(matchString, &name, &extraInfo)) {
name += info->symbolType();
index = hasWildcard ? regexp.indexIn(name) : matcher.indexIn(name);
match = regexp.match(name);
}
}
Core::LocatorFilterEntry filterEntry(this, name, id, info->icon());
filterEntry.extraInfo = extraInfo;
if (index < 0) {
index = hasWildcard ? regexp.indexIn(extraInfo) : matcher.indexIn(extraInfo);
if (!match.hasMatch()) {
match = regexp.match(extraInfo);
filterEntry.highlightInfo.dataType = Core::LocatorFilterEntry::HighlightInfo::ExtraInfo;
}
if (index >= 0) {
filterEntry.highlightInfo.startIndex = index;
filterEntry.highlightInfo.length = hasWildcard ? regexp.matchedLength() : entry.length();
}
const CamelHumpMatcher::HighlightingPositions positions =
CamelHumpMatcher::highlightingPositions(match);
filterEntry.highlightInfo.starts = positions.starts;
filterEntry.highlightInfo.lengths = positions.lengths;
if (betterMatch)
betterEntries.append(filterEntry);
else
......
......@@ -28,9 +28,9 @@
#include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
#include <utils/camelhumpmatcher.h>
#include <QRegExp>
#include <QStringMatcher>
#include <QRegularExpression>
#include <algorithm>
......@@ -72,34 +72,37 @@ QList<Core::LocatorFilterEntry> CppLocatorFilter::matchesFor(
{
QList<Core::LocatorFilterEntry> goodEntries;
QList<Core::LocatorFilterEntry> betterEntries;
const Qt::CaseSensitivity cs = caseSensitivity(entry);
QStringMatcher matcher(entry, cs);
QRegExp regexp(entry, cs, QRegExp::Wildcard);
if (!regexp.isValid())
return goodEntries;
bool hasWildcard = containsWildcard(entry);
QList<Core::LocatorFilterEntry> bestEntries;
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
bool hasColonColon = entry.contains(QLatin1String("::"));
const IndexItem::ItemType wanted = matchTypes();
const QRegularExpression regexp = containsWildcard(entry)
? createWildcardRegExp(entry) : CamelHumpMatcher::createCamelHumpRegExp(entry);
if (!regexp.isValid())
return goodEntries;
m_data->filterAllFiles([&](const IndexItem::Ptr &info) -> IndexItem::VisitorResult {
if (future.isCanceled())
return IndexItem::Break;
if (info->type() & wanted) {
const QString matchString = hasColonColon ? info->scopedSymbolName() : info->symbolName();
int index = hasWildcard ? regexp.indexIn(matchString) : matcher.indexIn(matchString);
if (index >= 0) {
const bool betterMatch = index == 0;
QString matchString = hasColonColon ? info->scopedSymbolName() : info->symbolName();
QRegularExpressionMatch match = regexp.match(matchString);
if (match.hasMatch()) {
Core::LocatorFilterEntry filterEntry = filterEntryFromIndexItem(info);
if (matchString != filterEntry.displayName) {
index = hasWildcard ? regexp.indexIn(filterEntry.displayName)
: matcher.indexIn(filterEntry.displayName);
}
if (index >= 0)
filterEntry.highlightInfo = {index, (hasWildcard ? regexp.matchedLength() : entry.length())};
if (betterMatch)
// Highlight the matched characters, therefore it may be necessary
// to update the match if the displayName is different from matchString
if (matchString != filterEntry.displayName)
match = regexp.match(filterEntry.displayName);
const CamelHumpMatcher::HighlightingPositions positions =
CamelHumpMatcher::highlightingPositions(match);
filterEntry.highlightInfo.starts = positions.starts;
filterEntry.highlightInfo.lengths = positions.lengths;
if (matchString.startsWith(entry, caseSensitivityForPrefix))
bestEntries.append(filterEntry);
else if (matchString.contains(entry, caseSensitivityForPrefix))
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
......@@ -116,9 +119,12 @@ QList<Core::LocatorFilterEntry> CppLocatorFilter::matchesFor(
Utils::sort(goodEntries, Core::LocatorFilterEntry::compareLexigraphically);
if (betterEntries.size() < 1000)
Utils::sort(betterEntries, Core::LocatorFilterEntry::compareLexigraphically);
if (bestEntries.size() < 1000)
Utils::sort(bestEntries, Core::LocatorFilterEntry::compareLexigraphically);
betterEntries += goodEntries;
return betterEntries;
bestEntries += betterEntries;
bestEntries += goodEntries;
return bestEntries;
}
void CppLocatorFilter::accept(Core::LocatorFilterEntry selection,
......
......@@ -190,6 +190,16 @@ void CppToolsPlugin::test_cpplocatorfilters_CppLocatorFilter_data()
<< ResultData(_("myFunction(bool, int)"), _("<anonymous namespace> (file1.cpp)"))
);
QTest::newRow("CppFunctionsFilter-Sorting")
<< testFile
<< cppFunctionsFilter
<< _("pos")
<< (QList<ResultData>()
<< ResultData(_("positiveNumber()"), testFileShort)
<< ResultData(_("getPosition()"), testFileShort)
<< ResultData(_("pointOfService()"), testFileShort)
);
QTest::newRow("CppFunctionsFilter-WithNamespacePrefix")
<< testFile
<< cppFunctionsFilter
......@@ -280,6 +290,9 @@ void CppToolsPlugin::test_cpplocatorfilters_CppCurrentDocumentFilter()
QList<ResultData> expectedResults = QList<ResultData>()
<< ResultData(_("int myVariable"), _(""))
<< ResultData(_("myFunction(bool, int)"), _(""))
<< ResultData(_("pointOfService()"), _(""))
<< ResultData(_("getPosition()"), _(""))
<< ResultData(_("positiveNumber()"), _(""))
<< ResultData(_("MyEnum"), _(""))
<< ResultData(_("int V1"), _("MyEnum"))
<< ResultData(_("int V2"), _("MyEnum"))
......
......@@ -28,9 +28,9 @@
#include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
#include <utils/camelhumpmatcher.h>
#include <QRegExp>
#include <QStringMatcher>
#include <QRegularExpression>
using namespace QmlJSTools::Internal;
......@@ -59,12 +59,13 @@ QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(
{
QList<Core::LocatorFilterEntry> goodEntries;
QList<Core::LocatorFilterEntry> betterEntries;
const Qt::CaseSensitivity cs = caseSensitivity(entry);
QStringMatcher matcher(entry, cs);
QRegExp regexp(entry, cs, QRegExp::Wildcard);
QList<Core::LocatorFilterEntry> bestEntries;
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
const QRegularExpression regexp = containsWildcard(entry)
? createWildcardRegExp(entry) : CamelHumpMatcher::createCamelHumpRegExp(entry);
if (!regexp.isValid())
return goodEntries;
bool hasWildcard = containsWildcard(entry);
QHashIterator<QString, QList<LocatorData::Entry> > it(m_data->entries());
while (it.hasNext()) {
......@@ -78,16 +79,19 @@ QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(
if (info.type != LocatorData::Function)
continue;
const int index = hasWildcard ? regexp.indexIn(info.symbolName)
: matcher.indexIn(info.symbolName);
if (index >= 0) {
const QRegularExpressionMatch match = regexp.match(info.symbolName);
if (match.hasMatch()) {
QVariant id = qVariantFromValue(info);
Core::LocatorFilterEntry filterEntry(this, info.displayName, id/*, info.icon*/);
const CamelHumpMatcher::HighlightingPositions positions =
CamelHumpMatcher::highlightingPositions(match);
filterEntry.extraInfo = info.extraInfo;
const int length = hasWildcard ? regexp.matchedLength() : entry.length();
filterEntry.highlightInfo = {index, length};
filterEntry.highlightInfo.starts = positions.starts;
filterEntry.highlightInfo.lengths = positions.lengths;
if (index == 0)
if (filterEntry.displayName.startsWith(entry, caseSensitivityForPrefix))
bestEntries.append(filterEntry);
else if (filterEntry.displayName.contains(entry, caseSensitivityForPrefix))
betterEntries.append(filterEntry);
else
goodEntries.append(filterEntry);
......@@ -99,9 +103,12 @@ QList<Core::LocatorFilterEntry> FunctionFilter::matchesFor(
Utils::sort(goodEntries, Core::LocatorFilterEntry::compareLexigraphically);
if (betterEntries.size() < 1000)
Utils::sort(betterEntries, Core::LocatorFilterEntry::compareLexigraphically);
if (bestEntries.size() < 1000)
Utils::sort(bestEntries, Core::LocatorFilterEntry::compareLexigraphically);
betterEntries += goodEntries;
return betterEntries;
bestEntries += betterEntries;
bestEntries += goodEntries;
return bestEntries;
}
void FunctionFilter::accept(Core::LocatorFilterEntry selection,
......
......@@ -35,6 +35,8 @@ class tst_CamelHumpMatcher : public QObject
private slots:
void camelHumpMatcher();
void camelHumpMatcher_data();
void highlighting();
void highlighting_data();
};
void tst_CamelHumpMatcher::camelHumpMatcher()
......@@ -75,5 +77,64 @@ void tst_CamelHumpMatcher::camelHumpMatcher_data()
QTest::newRow("middle-continued") << "cahu" << "LongCamelHump" << 4;