FileSearch: Get rid of FileSearchResult

Use SearchResultItem instead.
This change should reduce the remaining freeze described in
a9eb732ce6 even more.

Change-Id: I102b82ed5677360ccd9e425dd0bdd941d87116f0
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Jarek Kobus
2023-05-05 14:05:10 +02:00
parent 1d4228dfda
commit 936086745a
18 changed files with 289 additions and 294 deletions

View File

@@ -7,6 +7,7 @@
#include "filepath.h" #include "filepath.h"
#include "mapreduce.h" #include "mapreduce.h"
#include "qtcassert.h" #include "qtcassert.h"
#include "searchresultitem.h"
#include "stringutils.h" #include "stringutils.h"
#include "utilstr.h" #include "utilstr.h"
#include "utiltypes.h" #include "utiltypes.h"
@@ -69,7 +70,7 @@ public:
FileSearch(const QString &searchTerm, FileSearch(const QString &searchTerm,
QTextDocument::FindFlags flags, QTextDocument::FindFlags flags,
const QMap<FilePath, QString> &fileToContentsMap); const QMap<FilePath, QString> &fileToContentsMap);
void operator()(QFutureInterface<FileSearchResultList> &futureInterface, void operator()(QFutureInterface<SearchResultItems> &futureInterface,
const FileIterator::Item &item) const; const FileIterator::Item &item) const;
private: private:
@@ -91,7 +92,7 @@ public:
QTextDocument::FindFlags flags, QTextDocument::FindFlags flags,
const QMap<FilePath, QString> &fileToContentsMap); const QMap<FilePath, QString> &fileToContentsMap);
FileSearchRegExp(const FileSearchRegExp &other); FileSearchRegExp(const FileSearchRegExp &other);
void operator()(QFutureInterface<FileSearchResultList> &futureInterface, void operator()(QFutureInterface<SearchResultItems> &futureInterface,
const FileIterator::Item &item) const; const FileIterator::Item &item) const;
private: private:
@@ -117,7 +118,7 @@ FileSearch::FileSearch(const QString &searchTerm,
termDataUpper = searchTermUpper.constData(); termDataUpper = searchTermUpper.constData();
} }
void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterface, void FileSearch::operator()(QFutureInterface<SearchResultItems> &futureInterface,
const FileIterator::Item &item) const const FileIterator::Item &item) const
{ {
if (futureInterface.isCanceled()) if (futureInterface.isCanceled())
@@ -125,7 +126,7 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
qCDebug(searchLog) << "Searching in" << item.filePath; qCDebug(searchLog) << "Searching in" << item.filePath;
futureInterface.setProgressRange(0, 1); futureInterface.setProgressRange(0, 1);
futureInterface.setProgressValue(0); futureInterface.setProgressValue(0);
FileSearchResultList results; SearchResultItems results;
QString tempString; QString tempString;
if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) { if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) {
qCDebug(searchLog) << "- failed to get content for" << item.filePath; qCDebug(searchLog) << "- failed to get content for" << item.filePath;
@@ -190,13 +191,13 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
} }
} }
if (equal) { if (equal) {
const QString resultItemText = clippedText(chunk, MAX_LINE_SIZE); SearchResultItem result;
results << FileSearchResult(item.filePath, result.setFilePath(item.filePath);
lineNr, result.setMainRange(lineNr, regionPtr - chunkPtr, termMaxIndex + 1);
resultItemText, result.setDisplayText(clippedText(chunk, MAX_LINE_SIZE));
regionPtr - chunkPtr, result.setUserData(QStringList());
termMaxIndex + 1, result.setUseTextEditorFont(true);
QStringList()); results << result;
regionPtr += termMaxIndex; // another +1 done by for-loop regionPtr += termMaxIndex; // another +1 done by for-loop
} }
} }
@@ -238,7 +239,7 @@ QRegularExpressionMatch FileSearchRegExp::doGuardedMatch(const QString &line, in
return expression.match(line, offset); return expression.match(line, offset);
} }
void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &futureInterface, void FileSearchRegExp::operator()(QFutureInterface<SearchResultItems> &futureInterface,
const FileIterator::Item &item) const const FileIterator::Item &item) const
{ {
if (!expression.isValid()) { if (!expression.isValid()) {
@@ -250,7 +251,7 @@ void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &future
qCDebug(searchLog) << "Searching in" << item.filePath; qCDebug(searchLog) << "Searching in" << item.filePath;
futureInterface.setProgressRange(0, 1); futureInterface.setProgressRange(0, 1);
futureInterface.setProgressValue(0); futureInterface.setProgressValue(0);
FileSearchResultList results; SearchResultItems results;
QString tempString; QString tempString;
if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) { if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) {
qCDebug(searchLog) << "- failed to get content for" << item.filePath; qCDebug(searchLog) << "- failed to get content for" << item.filePath;
@@ -270,12 +271,13 @@ void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &future
int pos = 0; int pos = 0;
while ((match = doGuardedMatch(line, pos)).hasMatch()) { while ((match = doGuardedMatch(line, pos)).hasMatch()) {
pos = match.capturedStart(); pos = match.capturedStart();
results << FileSearchResult(item.filePath, SearchResultItem result;
lineNr, result.setFilePath(item.filePath);
resultItemText, result.setMainRange(lineNr, pos, match.capturedLength());
pos, result.setDisplayText(resultItemText);
match.capturedLength(), result.setUserData(match.capturedTexts());
match.capturedTexts()); result.setUseTextEditorFont(true);
results << result;
if (match.capturedLength() == 0) if (match.capturedLength() == 0)
break; break;
pos += match.capturedLength(); pos += match.capturedLength();
@@ -299,12 +301,12 @@ struct SearchState
SearchState(const QString &term, FileIterator *iterator) : searchTerm(term), files(iterator) {} SearchState(const QString &term, FileIterator *iterator) : searchTerm(term), files(iterator) {}
QString searchTerm; QString searchTerm;
FileIterator *files = nullptr; FileIterator *files = nullptr;
FileSearchResultList cachedResults; SearchResultItems cachedResults;
int numFilesSearched = 0; int numFilesSearched = 0;
int numMatches = 0; int numMatches = 0;
}; };
SearchState initFileSearch(QFutureInterface<FileSearchResultList> &futureInterface, SearchState initFileSearch(QFutureInterface<SearchResultItems> &futureInterface,
const QString &searchTerm, FileIterator *files) const QString &searchTerm, FileIterator *files)
{ {
futureInterface.setProgressRange(0, files->maxProgress()); futureInterface.setProgressRange(0, files->maxProgress());
@@ -312,9 +314,9 @@ SearchState initFileSearch(QFutureInterface<FileSearchResultList> &futureInterfa
return SearchState(searchTerm, files); return SearchState(searchTerm, files);
} }
void collectSearchResults(QFutureInterface<FileSearchResultList> &futureInterface, void collectSearchResults(QFutureInterface<SearchResultItems> &futureInterface,
SearchState &state, SearchState &state,
const FileSearchResultList &results) const SearchResultItems &results)
{ {
state.numMatches += results.size(); state.numMatches += results.size();
state.cachedResults << results; state.cachedResults << results;
@@ -333,7 +335,7 @@ void collectSearchResults(QFutureInterface<FileSearchResultList> &futureInterfac
} }
} }
void cleanUpFileSearch(QFutureInterface<FileSearchResultList> &futureInterface, void cleanUpFileSearch(QFutureInterface<SearchResultItems> &futureInterface,
SearchState &state) SearchState &state)
{ {
if (!state.cachedResults.isEmpty()) { if (!state.cachedResults.isEmpty()) {
@@ -356,13 +358,13 @@ void cleanUpFileSearch(QFutureInterface<FileSearchResultList> &futureInterface,
} // namespace } // namespace
QFuture<FileSearchResultList> Utils::findInFiles(const QString &searchTerm, QFuture<SearchResultItems> Utils::findInFiles(const QString &searchTerm,
FileIterator *files, FileIterator *files,
QTextDocument::FindFlags flags, QTextDocument::FindFlags flags,
const QMap<FilePath, QString> &fileToContentsMap) const QMap<FilePath, QString> &fileToContentsMap)
{ {
return mapReduce(files->begin(), files->end(), return mapReduce(files->begin(), files->end(),
[searchTerm, files](QFutureInterface<FileSearchResultList> &futureInterface) { [searchTerm, files](QFutureInterface<SearchResultItems> &futureInterface) {
return initFileSearch(futureInterface, searchTerm, files); return initFileSearch(futureInterface, searchTerm, files);
}, },
FileSearch(searchTerm, flags, fileToContentsMap), FileSearch(searchTerm, flags, fileToContentsMap),
@@ -370,14 +372,14 @@ QFuture<FileSearchResultList> Utils::findInFiles(const QString &searchTerm,
&cleanUpFileSearch); &cleanUpFileSearch);
} }
QFuture<FileSearchResultList> Utils::findInFilesRegExp( QFuture<SearchResultItems> Utils::findInFilesRegExp(
const QString &searchTerm, const QString &searchTerm,
FileIterator *files, FileIterator *files,
QTextDocument::FindFlags flags, QTextDocument::FindFlags flags,
const QMap<FilePath, QString> &fileToContentsMap) const QMap<FilePath, QString> &fileToContentsMap)
{ {
return mapReduce(files->begin(), files->end(), return mapReduce(files->begin(), files->end(),
[searchTerm, files](QFutureInterface<FileSearchResultList> &futureInterface) { [searchTerm, files](QFutureInterface<SearchResultItems> &futureInterface) {
return initFileSearch(futureInterface, searchTerm, files); return initFileSearch(futureInterface, searchTerm, files);
}, },
FileSearchRegExp(searchTerm, flags, fileToContentsMap), FileSearchRegExp(searchTerm, flags, fileToContentsMap),

View File

@@ -6,8 +6,8 @@
#include "utils_global.h" #include "utils_global.h"
#include "filepath.h" #include "filepath.h"
#include "searchresultitem.h"
#include <QDir>
#include <QMap> #include <QMap>
#include <QSet> #include <QSet>
#include <QStack> #include <QStack>
@@ -152,54 +152,20 @@ private:
QList<Item *> m_items; QList<Item *> m_items;
}; };
class QTCREATOR_UTILS_EXPORT FileSearchResult QTCREATOR_UTILS_EXPORT QFuture<SearchResultItems> findInFiles(const QString &searchTerm,
{ FileIterator *files,
public: QTextDocument::FindFlags flags,
FileSearchResult() = default; const QMap<FilePath, QString> &fileToContentsMap = {});
FileSearchResult(const FilePath &fileName, int lineNumber, const QString &matchingLine,
int matchStart, int matchLength,
const QStringList &regexpCapturedTexts)
: fileName(fileName),
lineNumber(lineNumber),
matchingLine(matchingLine),
matchStart(matchStart),
matchLength(matchLength),
regexpCapturedTexts(regexpCapturedTexts)
{}
bool operator==(const FileSearchResult &o) const QTCREATOR_UTILS_EXPORT QFuture<SearchResultItems> findInFilesRegExp(
{
return fileName == o.fileName && lineNumber == o.lineNumber
&& matchingLine == o.matchingLine && matchStart == o.matchStart
&& matchLength == o.matchLength && regexpCapturedTexts == o.regexpCapturedTexts;
}
bool operator!=(const FileSearchResult &o) const { return !(*this == o); }
FilePath fileName;
int lineNumber;
QString matchingLine;
int matchStart;
int matchLength;
QStringList regexpCapturedTexts;
};
using FileSearchResultList = QList<FileSearchResult>;
QTCREATOR_UTILS_EXPORT QFuture<FileSearchResultList> findInFiles(
const QString &searchTerm, const QString &searchTerm,
FileIterator *files, FileIterator *files,
QTextDocument::FindFlags flags, QTextDocument::FindFlags flags,
const QMap<FilePath, QString> &fileToContentsMap = QMap<FilePath, QString>()); const QMap<FilePath, QString> &fileToContentsMap = {});
QTCREATOR_UTILS_EXPORT QFuture<FileSearchResultList> findInFilesRegExp( QTCREATOR_UTILS_EXPORT QString expandRegExpReplacement(const QString &replaceText,
const QString &searchTerm, const QStringList &capturedTexts);
FileIterator *files, QTCREATOR_UTILS_EXPORT QString matchCaseReplacement(const QString &originalText,
QTextDocument::FindFlags flags, const QString &replaceText);
const QMap<FilePath, QString> &fileToContentsMap = QMap<FilePath, QString>());
QTCREATOR_UTILS_EXPORT QString expandRegExpReplacement(const QString &replaceText, const QStringList &capturedTexts);
QTCREATOR_UTILS_EXPORT QString matchCaseReplacement(const QString &originalText, const QString &replaceText);
} // namespace Utils } // namespace Utils
Q_DECLARE_METATYPE(Utils::FileSearchResultList)

View File

@@ -45,10 +45,20 @@ SearchResultColor::SearchResultColor(const QColor &textBg, const QColor &textFg,
containingFunctionForeground = textForeground; containingFunctionForeground = textForeground;
} }
QTCREATOR_UTILS_EXPORT size_t qHash(SearchResultColor::Style style, uint seed) static QString displayText(const QString &line)
{ {
int a = int(style); QString result = line;
return ::qHash(a, seed); auto end = result.end();
for (auto it = result.begin(); it != end; ++it) {
if (!it->isSpace() && !it->isPrint())
*it = QChar('?');
}
return result;
}
void SearchResultItem::setDisplayText(const QString &text)
{
setLineText(displayText(text));
} }
void SearchResultItem::setMainRange(int line, int column, int length) void SearchResultItem::setMainRange(int line, int column, int length)
@@ -56,4 +66,29 @@ void SearchResultItem::setMainRange(int line, int column, int length)
m_mainRange = {{line, column}, {line, column + length}}; m_mainRange = {{line, column}, {line, column + length}};
} }
QTCREATOR_UTILS_EXPORT size_t qHash(SearchResultColor::Style style, uint seed)
{
int a = int(style);
return ::qHash(a, seed);
}
bool Search::TextPosition::operator==(const Search::TextPosition &other) const
{
return line == other.line && column == other.column;
}
bool Search::TextRange::operator==(const Search::TextRange &other) const
{
return begin == other.begin && end == other.end;
}
bool SearchResultItem::operator==(const SearchResultItem &other) const
{
return m_path == other.m_path && m_lineText == other.m_lineText
&& m_userData == other.m_userData && m_mainRange == other.m_mainRange
&& m_useTextEditorFont == other.m_useTextEditorFont
&& m_selectForReplacement == other.m_selectForReplacement && m_style == other.m_style
&& m_containingFunctionName == other.m_containingFunctionName;
}
} // namespace Utils } // namespace Utils

View File

@@ -28,6 +28,8 @@ public:
bool operator<(const TextPosition &other) const bool operator<(const TextPosition &other) const
{ return line < other.line || (line == other.line && column < other.column); } { return line < other.line || (line == other.line && column < other.column); }
bool operator==(const TextPosition &other) const;
bool operator!=(const TextPosition &other) const { return !(operator==(other)); }
}; };
class QTCREATOR_UTILS_EXPORT TextRange class QTCREATOR_UTILS_EXPORT TextRange
@@ -40,6 +42,8 @@ public:
TextPosition end; TextPosition end;
bool operator<(const TextRange &other) const { return begin < other.begin; } bool operator<(const TextRange &other) const { return begin < other.begin; }
bool operator==(const TextRange &other) const;
bool operator!=(const TextRange &other) const { return !(operator==(other)); }
}; };
} // namespace Search } // namespace Search
@@ -76,6 +80,7 @@ public:
QString lineText() const { return m_lineText; } QString lineText() const { return m_lineText; }
void setLineText(const QString &text) { m_lineText = text; } void setLineText(const QString &text) { m_lineText = text; }
void setDisplayText(const QString &text);
QIcon icon() const { return m_icon; } QIcon icon() const { return m_icon; }
void setIcon(const QIcon &icon) { m_icon = icon; } void setIcon(const QIcon &icon) { m_icon = icon; }
@@ -103,6 +108,9 @@ public:
m_containingFunctionName = containingFunctionName; m_containingFunctionName = containingFunctionName;
} }
bool operator==(const SearchResultItem &other) const;
bool operator!=(const SearchResultItem &other) const { return !(operator==(other)); }
private: private:
QStringList m_path; // hierarchy to the parent item of this item QStringList m_path; // hierarchy to the parent item of this item
QString m_lineText; // text to show for the item itself QString m_lineText; // text to show for the item itself

View File

@@ -45,7 +45,7 @@ public:
class GitGrepRunner class GitGrepRunner
{ {
using PromiseType = QPromise<FileSearchResultList>; using PromiseType = QPromise<SearchResultItems>;
public: public:
GitGrepRunner(const TextEditor::FileFindParameters &parameters) GitGrepRunner(const TextEditor::FileFindParameters &parameters)
@@ -67,23 +67,23 @@ public:
QStringList regexpCapturedTexts; QStringList regexpCapturedTexts;
}; };
void processLine(const QString &line, FileSearchResultList *resultList) const void processLine(const QString &line, SearchResultItems *resultList) const
{ {
if (line.isEmpty()) if (line.isEmpty())
return; return;
static const QLatin1String boldRed("\x1b[1;31m"); static const QLatin1String boldRed("\x1b[1;31m");
static const QLatin1String resetColor("\x1b[m"); static const QLatin1String resetColor("\x1b[m");
FileSearchResult single; SearchResultItem result;
const int lineSeparator = line.indexOf(QChar::Null); const int lineSeparator = line.indexOf(QChar::Null);
QString filePath = line.left(lineSeparator); QString filePath = line.left(lineSeparator);
if (!m_ref.isEmpty() && filePath.startsWith(m_ref)) if (!m_ref.isEmpty() && filePath.startsWith(m_ref))
filePath.remove(0, m_ref.length()); filePath.remove(0, m_ref.length());
single.fileName = m_directory.pathAppended(filePath); result.setFilePath(m_directory.pathAppended(filePath));
const int textSeparator = line.indexOf(QChar::Null, lineSeparator + 1); const int textSeparator = line.indexOf(QChar::Null, lineSeparator + 1);
single.lineNumber = line.mid(lineSeparator + 1, textSeparator - lineSeparator - 1).toInt(); const int lineNumber = line.mid(lineSeparator + 1, textSeparator - lineSeparator - 1).toInt();
QString text = line.mid(textSeparator + 1); QString text = line.mid(textSeparator + 1);
QRegularExpression regexp; QRegularExpression regexp;
QVector<Match> matches; QList<Match> matches;
if (m_parameters.flags & FindRegularExpression) { if (m_parameters.flags & FindRegularExpression) {
const QRegularExpression::PatternOptions patternOptions = const QRegularExpression::PatternOptions patternOptions =
(m_parameters.flags & FindCaseSensitively) (m_parameters.flags & FindCaseSensitively)
@@ -106,19 +106,18 @@ public:
matches.append(match); matches.append(match);
text = text.left(matchStart) + matchText + text.mid(matchEnd + resetColor.size()); text = text.left(matchStart) + matchText + text.mid(matchEnd + resetColor.size());
} }
single.matchingLine = text; result.setDisplayText(text);
for (const auto &match : std::as_const(matches)) { for (const auto &match : std::as_const(matches)) {
single.matchStart = match.matchStart; result.setMainRange(lineNumber, match.matchStart, match.matchLength);
single.matchLength = match.matchLength; result.setUserData(match.regexpCapturedTexts);
single.regexpCapturedTexts = match.regexpCapturedTexts; resultList->append(result);
resultList->append(single);
} }
} }
void read(PromiseType &fi, const QString &text) void read(PromiseType &fi, const QString &text)
{ {
FileSearchResultList resultList; SearchResultItems resultList;
QString t = text; QString t = text;
QTextStream stream(&t); QTextStream stream(&t);
while (!stream.atEnd() && !fi.isCanceled()) while (!stream.atEnd() && !fi.isCanceled())
@@ -272,7 +271,7 @@ void GitGrep::writeSettings(QSettings *settings) const
settings->setValue(GitGrepRef, m_treeLineEdit->text()); settings->setValue(GitGrepRef, m_treeLineEdit->text());
} }
QFuture<FileSearchResultList> GitGrep::executeSearch(const TextEditor::FileFindParameters &parameters, QFuture<SearchResultItems> GitGrep::executeSearch(const TextEditor::FileFindParameters &parameters,
TextEditor::BaseFileFind * /*baseFileFind*/) TextEditor::BaseFileFind * /*baseFileFind*/)
{ {
return Utils::asyncRun(GitGrepRunner(parameters)); return Utils::asyncRun(GitGrepRunner(parameters));

View File

@@ -30,7 +30,7 @@ public:
QVariant parameters() const override; QVariant parameters() const override;
void readSettings(QSettings *settings) override; void readSettings(QSettings *settings) override;
void writeSettings(QSettings *settings) const override; void writeSettings(QSettings *settings) const override;
QFuture<Utils::FileSearchResultList> executeSearch( QFuture<Utils::SearchResultItems> executeSearch(
const TextEditor::FileFindParameters &parameters, const TextEditor::FileFindParameters &parameters,
TextEditor::BaseFileFind *baseFileFind) override; TextEditor::BaseFileFind *baseFileFind) override;
Core::IEditor *openEditor(const Utils::SearchResultItem &item, Core::IEditor *openEditor(const Utils::SearchResultItem &item,

View File

@@ -73,7 +73,7 @@ bool isSilverSearcherAvailable()
return false; return false;
} }
void runSilverSeacher(QPromise<FileSearchResultList> &promise, FileFindParameters parameters) void runSilverSeacher(QPromise<SearchResultItems> &promise, FileFindParameters parameters)
{ {
const FilePath directory = FilePath::fromUserInput(parameters.additionalParameters.toString()); const FilePath directory = FilePath::fromUserInput(parameters.additionalParameters.toString());
QStringList arguments = {"--parallel", "--ackmate"}; QStringList arguments = {"--parallel", "--ackmate"};
@@ -120,7 +120,7 @@ void runSilverSeacher(QPromise<FileSearchResultList> &promise, FileFindParameter
regexp.setPatternOptions(patternOptions); regexp.setPatternOptions(patternOptions);
} }
SilverSearcher::SilverSearcherOutputParser parser(process.cleanedStdOut(), regexp); SilverSearcher::SilverSearcherOutputParser parser(process.cleanedStdOut(), regexp);
FileSearchResultList items = parser.parse(); const SearchResultItems items = parser.parse();
if (!items.isEmpty()) if (!items.isEmpty())
promise.addResult(items); promise.addResult(items);
} else { } else {
@@ -189,7 +189,7 @@ void FindInFilesSilverSearcher::writeSettings(QSettings *settings) const
settings->setValue(SearchOptionsString, m_searchOptionsLineEdit->text()); settings->setValue(SearchOptionsString, m_searchOptionsLineEdit->text());
} }
QFuture<FileSearchResultList> FindInFilesSilverSearcher::executeSearch( QFuture<SearchResultItems> FindInFilesSilverSearcher::executeSearch(
const FileFindParameters &parameters, BaseFileFind * /*baseFileFind*/) const FileFindParameters &parameters, BaseFileFind * /*baseFileFind*/)
{ {
return Utils::asyncRun(runSilverSeacher, parameters); return Utils::asyncRun(runSilverSeacher, parameters);

View File

@@ -31,7 +31,7 @@ public:
QVariant parameters() const override; QVariant parameters() const override;
void readSettings(QSettings *settings) override; void readSettings(QSettings *settings) override;
void writeSettings(QSettings *settings) const override; void writeSettings(QSettings *settings) const override;
QFuture<Utils::FileSearchResultList> executeSearch( QFuture<Utils::SearchResultItems> executeSearch(
const TextEditor::FileFindParameters &parameters, TextEditor::BaseFileFind *) override; const TextEditor::FileFindParameters &parameters, TextEditor::BaseFileFind *) override;
Core::IEditor *openEditor(const Utils::SearchResultItem &item, Core::IEditor *openEditor(const Utils::SearchResultItem &item,
const TextEditor::FileFindParameters &parameters) override; const TextEditor::FileFindParameters &parameters) override;

View File

@@ -11,47 +11,57 @@ using namespace Utils;
namespace SilverSearcher { namespace SilverSearcher {
namespace Internal { namespace Internal {
SearchResultItem searchResult(const FilePath &fileName, const QString &matchingLine,
int lineNumber, int matchStart, int matchLength)
{
SearchResultItem result;
result.setFilePath(fileName);
result.setLineText(matchingLine);
result.setMainRange(lineNumber, matchStart, matchLength);
return result;
}
void OutputParserTest::test_data() void OutputParserTest::test_data()
{ {
QTest::addColumn<QString>("parserOutput"); QTest::addColumn<QString>("parserOutput");
QTest::addColumn<FileSearchResultList>("results"); QTest::addColumn<SearchResultItems>("results");
QTest::addRow("nothing") << QString("\n") << FileSearchResultList(); QTest::addRow("nothing") << QString("\n") << SearchResultItems();
QTest::addRow("oneFileOneMatch") QTest::addRow("oneFileOneMatch")
<< QString(":/file/path/to/filename.h\n" << QString(":/file/path/to/filename.h\n"
"1;1 5:match\n") "1;1 5:match\n")
<< FileSearchResultList({{"/file/path/to/filename.h", 1, "match", 1, 5, {}}}); << SearchResultItems{searchResult("/file/path/to/filename.h", "match", 1, 1, 5)};
QTest::addRow("multipleFilesWithOneMatch") QTest::addRow("multipleFilesWithOneMatch")
<< QString(":/file/path/to/filename1.h\n" << QString(":/file/path/to/filename1.h\n"
"1;1 5:match\n" "1;1 5:match\n"
"\n" "\n"
":/file/path/to/filename2.h\n" ":/file/path/to/filename2.h\n"
"2;2 5: match\n") "2;2 5: match\n")
<< FileSearchResultList({{"/file/path/to/filename1.h", 1, "match", 1, 5, {}}, << SearchResultItems{searchResult("/file/path/to/filename1.h", "match", 1, 1, 5),
{"/file/path/to/filename2.h", 2, " match", 2, 5, {}}}); searchResult("/file/path/to/filename2.h", " match", 2, 2, 5)};
QTest::addRow("oneFileMultipleMatches") QTest::addRow("oneFileMultipleMatches")
<< QString(":/file/path/to/filename.h\n" << QString(":/file/path/to/filename.h\n"
"1;1 5,7 5:match match\n") "1;1 5,7 5:match match\n")
<< FileSearchResultList({{"/file/path/to/filename.h", 1, "match match", 1, 5, {}}, << SearchResultItems{searchResult("/file/path/to/filename.h", "match match", 1, 1, 5),
{"/file/path/to/filename.h", 1, "match match", 7, 5, {}}}); searchResult("/file/path/to/filename.h", "match match", 1, 7, 5)};
QTest::addRow("multipleFilesWithMultipleMatches") QTest::addRow("multipleFilesWithMultipleMatches")
<< QString(":/file/path/to/filename1.h\n" << QString(":/file/path/to/filename1.h\n"
"1;1 5,7 5:match match\n" "1;1 5,7 5:match match\n"
"\n" "\n"
":/file/path/to/filename2.h\n" ":/file/path/to/filename2.h\n"
"2;2 5,8 5: match match\n") "2;2 5,8 5: match match\n")
<< FileSearchResultList({{"/file/path/to/filename1.h", 1, "match match", 1, 5, {}}, << SearchResultItems{searchResult("/file/path/to/filename1.h", "match match", 1, 1, 5),
{"/file/path/to/filename1.h", 1, "match match", 7, 5, {}}, searchResult("/file/path/to/filename1.h", "match match", 1, 7, 5),
{"/file/path/to/filename2.h", 2, " match match", 2, 5, {}}, searchResult("/file/path/to/filename2.h", " match match", 2, 2, 5),
{"/file/path/to/filename2.h", 2, " match match", 8, 5, {}}}); searchResult("/file/path/to/filename2.h", " match match", 2, 8, 5)};
} }
void OutputParserTest::test() void OutputParserTest::test()
{ {
QFETCH(QString, parserOutput); QFETCH(QString, parserOutput);
QFETCH(FileSearchResultList, results); QFETCH(SearchResultItems, results);
SilverSearcher::SilverSearcherOutputParser ssop(parserOutput); SilverSearcher::SilverSearcherOutputParser ssop(parserOutput);
const FileSearchResultList items = ssop.parse(); const SearchResultItems items = ssop.parse();
QCOMPARE(items, results); QCOMPARE(items, results);
} }

View File

@@ -16,7 +16,7 @@ SilverSearcherOutputParser::SilverSearcherOutputParser(
hasRegexp = !regexp.pattern().isEmpty(); hasRegexp = !regexp.pattern().isEmpty();
} }
Utils::FileSearchResultList SilverSearcherOutputParser::parse() Utils::SearchResultItems SilverSearcherOutputParser::parse()
{ {
while (index < outputSize - 1) { while (index < outputSize - 1) {
if (output[index] == '\n') { if (output[index] == '\n') {
@@ -25,15 +25,15 @@ Utils::FileSearchResultList SilverSearcherOutputParser::parse()
} }
parseFilePath(); parseFilePath();
while (index < outputSize && output[index] != '\n') { while (index < outputSize && output[index] != '\n') {
parseLineNumber(); const int lineNumber = parseLineNumber();
if (index >= outputSize - 1) if (index >= outputSize - 1)
break; break;
int matches = parseMatches(); int matches = parseMatches(lineNumber);
if (index >= outputSize - 1) if (index >= outputSize - 1)
break; break;
parseText(); parseText();
for (int i = 0; i < matches; ++i) for (int i = 0; i < matches; ++i)
items[items.size() - i - 1].matchingLine = item.matchingLine; items[items.size() - i - 1].setDisplayText(item.lineText());
} }
} }
@@ -45,41 +45,41 @@ bool SilverSearcherOutputParser::parseFilePath()
int startIndex = ++index; int startIndex = ++index;
while (index < outputSize && output[index] != '\n') while (index < outputSize && output[index] != '\n')
++index; ++index;
item.fileName = Utils::FilePath::fromString(QString(output.data() + startIndex, index - startIndex)); item.setFilePath(Utils::FilePath::fromString(QString(output.data() + startIndex,
index - startIndex)));
++index; ++index;
return true; return true;
} }
bool SilverSearcherOutputParser::parseLineNumber() int SilverSearcherOutputParser::parseLineNumber()
{ {
int startIndex = index; int startIndex = index;
while (index < outputSize && output[++index] != ';') { } while (index < outputSize && output[++index] != ';') { }
item.lineNumber = QString(output.data() + startIndex, index - startIndex).toInt(); const int lineNumber = QString(output.data() + startIndex, index - startIndex).toInt();
++index; ++index;
return true; return lineNumber;
} }
bool SilverSearcherOutputParser::parseMatchIndex() int SilverSearcherOutputParser::parseMatchIndex()
{ {
int startIndex = index; int startIndex = index;
while (index < outputSize && output[++index] != ' ') { } while (index < outputSize && output[++index] != ' ') { }
item.matchStart = QString(output.data() + startIndex, index - startIndex).toInt(); const int lineStart = QString(output.data() + startIndex, index - startIndex).toInt();
++index; ++index;
return true; return lineStart;
} }
bool SilverSearcherOutputParser::parseMatchLength() int SilverSearcherOutputParser::parseMatchLength()
{ {
int startIndex = index; int startIndex = index;
while (index < outputSize && output[++index] != ':' && output[index] != ',') { } while (index < outputSize && output[++index] != ':' && output[index] != ',') { }
item.matchLength = QString(output.data() + startIndex, index - startIndex).toInt(); return QString(output.data() + startIndex, index - startIndex).toInt();
return true;
} }
int SilverSearcherOutputParser::parseMatches() int SilverSearcherOutputParser::parseMatches(int lineNumber)
{ {
int matches = 1; int matches = 1;
const int colon = output.indexOf(':', index); const int colon = output.indexOf(':', index);
@@ -94,11 +94,12 @@ int SilverSearcherOutputParser::parseMatches()
++matches; ++matches;
++index; ++index;
} }
parseMatchIndex(); const int lineStart = parseMatchIndex();
parseMatchLength(); const int lineLength = parseMatchLength();
item.setMainRange(lineNumber, lineStart, lineLength);
if (hasRegexp) { if (hasRegexp) {
const QString part = QString(text.mid(item.matchStart, item.matchLength)); const QString part = QString(text.mid(lineStart, lineLength));
item.regexpCapturedTexts = regexp.match(part).capturedTexts(); item.setUserData(regexp.match(part).capturedTexts());
} }
items << item; items << item;
} }
@@ -111,7 +112,8 @@ bool SilverSearcherOutputParser::parseText()
{ {
int startIndex = index; int startIndex = index;
while (index < outputSize && output[++index] != '\n') { } while (index < outputSize && output[++index] != '\n') { }
item.matchingLine = QString(output.data() + startIndex, index - startIndex);
item.setLineText(QString(output.data() + startIndex, index - startIndex));
++index; ++index;
return true; return true;
} }

View File

@@ -16,13 +16,13 @@ class SilverSearcherOutputParser
public: public:
SilverSearcherOutputParser(const QString &output, const QRegularExpression &regexp = {}); SilverSearcherOutputParser(const QString &output, const QRegularExpression &regexp = {});
Utils::FileSearchResultList parse(); Utils::SearchResultItems parse();
private: private:
int parseMatches(); int parseMatches(int lineNumber);
bool parseMatchLength(); int parseMatchLength();
bool parseMatchIndex(); int parseMatchIndex();
bool parseLineNumber(); int parseLineNumber();
bool parseFilePath(); bool parseFilePath();
bool parseText(); bool parseText();
@@ -31,8 +31,8 @@ private:
bool hasRegexp = false; bool hasRegexp = false;
int outputSize = 0; int outputSize = 0;
int index = 0; int index = 0;
Utils::FileSearchResult item; Utils::SearchResultItem item;
Utils::FileSearchResultList items; Utils::SearchResultItems items;
}; };
} // namespace SilverSearcher } // namespace SilverSearcher

View File

@@ -51,8 +51,7 @@ public:
QVariant parameters() const override { return {}; } QVariant parameters() const override { return {}; }
void readSettings(QSettings * /*settings*/) override {} void readSettings(QSettings * /*settings*/) override {}
void writeSettings(QSettings * /*settings*/) const override {} void writeSettings(QSettings * /*settings*/) const override {}
QFuture<FileSearchResultList> executeSearch( QFuture<SearchResultItems> executeSearch(const TextEditor::FileFindParameters &parameters,
const TextEditor::FileFindParameters &parameters,
BaseFileFind *baseFileFind) override BaseFileFind *baseFileFind) override
{ {
const auto func = parameters.flags & FindRegularExpression ? Utils::findInFilesRegExp const auto func = parameters.flags & FindRegularExpression ? Utils::findInFilesRegExp
@@ -208,34 +207,6 @@ void BaseFileFind::setCurrentSearchEngine(int index)
emit currentSearchEngineChanged(); emit currentSearchEngineChanged();
} }
static QString displayText(const QString &line)
{
QString result = line;
auto end = result.end();
for (auto it = result.begin(); it != end; ++it) {
if (!it->isSpace() && !it->isPrint())
*it = QChar('?');
}
return result;
}
static void displayResult(QFutureWatcher<FileSearchResultList> *watcher,
SearchResult *search, int index)
{
const FileSearchResultList results = watcher->resultAt(index);
SearchResultItems items;
for (const FileSearchResult &result : results) {
SearchResultItem item;
item.setFilePath(result.fileName);
item.setMainRange(result.lineNumber, result.matchStart, result.matchLength);
item.setLineText(displayText(result.matchingLine));
item.setUseTextEditorFont(true);
item.setUserData(result.regexpCapturedTexts);
items << item;
}
search->addResults(items, SearchResult::AddOrdered);
}
void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags, void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags,
SearchResultWindow::SearchMode searchMode) SearchResultWindow::SearchMode searchMode)
{ {
@@ -283,7 +254,7 @@ void BaseFileFind::runSearch(SearchResult *search)
{ {
const FileFindParameters parameters = search->userData().value<FileFindParameters>(); const FileFindParameters parameters = search->userData().value<FileFindParameters>();
SearchResultWindow::instance()->popup(IOutputPane::Flags(IOutputPane::ModeSwitch|IOutputPane::WithFocus)); SearchResultWindow::instance()->popup(IOutputPane::Flags(IOutputPane::ModeSwitch|IOutputPane::WithFocus));
auto watcher = new QFutureWatcher<FileSearchResultList>(); auto watcher = new QFutureWatcher<SearchResultItems>;
watcher->setPendingResultsLimit(1); watcher->setPendingResultsLimit(1);
// search is deleted if it is removed from search panel // search is deleted if it is removed from search panel
connect(search, &QObject::destroyed, watcher, &QFutureWatcherBase::cancel); connect(search, &QObject::destroyed, watcher, &QFutureWatcherBase::cancel);
@@ -293,14 +264,14 @@ void BaseFileFind::runSearch(SearchResult *search)
watcher->setPaused(paused); watcher->setPaused(paused);
}); });
connect(watcher, &QFutureWatcherBase::resultReadyAt, search, [watcher, search](int index) { connect(watcher, &QFutureWatcherBase::resultReadyAt, search, [watcher, search](int index) {
displayResult(watcher, search, index); search->addResults(watcher->resultAt(index), SearchResult::AddOrdered);
}); });
// auto-delete: // auto-delete:
connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater); connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
connect(watcher, &QFutureWatcherBase::finished, search, [watcher, search]() { connect(watcher, &QFutureWatcherBase::finished, search, [watcher, search]() {
search->finishSearch(watcher->isCanceled()); search->finishSearch(watcher->isCanceled());
}); });
QFuture<FileSearchResultList> future = executeSearch(parameters); QFuture<SearchResultItems> future = executeSearch(parameters);
watcher->setFuture(future); watcher->setFuture(future);
d->m_futureSynchronizer.addFuture(future); d->m_futureSynchronizer.addFuture(future);
FutureProgress *progress = ProgressManager::addTask(future, FutureProgress *progress = ProgressManager::addTask(future,
@@ -541,7 +512,7 @@ QVariant BaseFileFind::getAdditionalParameters(SearchResult *search)
return search->userData().value<FileFindParameters>().additionalParameters; return search->userData().value<FileFindParameters>().additionalParameters;
} }
QFuture<FileSearchResultList> BaseFileFind::executeSearch(const FileFindParameters &parameters) QFuture<SearchResultItems> BaseFileFind::executeSearch(const FileFindParameters &parameters)
{ {
return d->m_searchEngines[parameters.searchEngineIndex]->executeSearch(parameters, this); return d->m_searchEngines[parameters.searchEngineIndex]->executeSearch(parameters, this);
} }

View File

@@ -56,7 +56,7 @@ public:
virtual QVariant parameters() const = 0; virtual QVariant parameters() const = 0;
virtual void readSettings(QSettings *settings) = 0; virtual void readSettings(QSettings *settings) = 0;
virtual void writeSettings(QSettings *settings) const = 0; virtual void writeSettings(QSettings *settings) const = 0;
virtual QFuture<Utils::FileSearchResultList> executeSearch( virtual QFuture<Utils::SearchResultItems> executeSearch(
const FileFindParameters &parameters, BaseFileFind *baseFileFind) = 0; const FileFindParameters &parameters, BaseFileFind *baseFileFind) = 0;
virtual Core::IEditor *openEditor(const Utils::SearchResultItem &item, virtual Core::IEditor *openEditor(const Utils::SearchResultItem &item,
const FileFindParameters &parameters) = 0; const FileFindParameters &parameters) = 0;
@@ -97,7 +97,7 @@ protected:
virtual QString label() const = 0; // see Core::SearchResultWindow::startNewSearch virtual QString label() const = 0; // see Core::SearchResultWindow::startNewSearch
virtual QString toolTip() const = 0; // see Core::SearchResultWindow::startNewSearch, virtual QString toolTip() const = 0; // see Core::SearchResultWindow::startNewSearch,
// add %1 placeholder where the find flags should be put // add %1 placeholder where the find flags should be put
QFuture<Utils::FileSearchResultList> executeSearch(const FileFindParameters &parameters); QFuture<Utils::SearchResultItems> executeSearch(const FileFindParameters &parameters);
void writeCommonSettings(QSettings *settings); void writeCommonSettings(QSettings *settings);
void readCommonSettings(QSettings *settings, const QString &defaultFilter, const QString &defaultExclusionFilter); void readCommonSettings(QSettings *settings, const QString &defaultFilter, const QString &defaultExclusionFilter);

View File

@@ -61,6 +61,7 @@
#include <utils/minimizableinfobars.h> #include <utils/minimizableinfobars.h>
#include <utils/multitextcursor.h> #include <utils/multitextcursor.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/searchresultitem.h>
#include <utils/styledbar.h> #include <utils/styledbar.h>
#include <utils/stylehelper.h> #include <utils/stylehelper.h>
#include <utils/textutils.h> #include <utils/textutils.h>
@@ -790,7 +791,7 @@ public:
QScopedPointer<AutoCompleter> m_autoCompleter; QScopedPointer<AutoCompleter> m_autoCompleter;
CommentDefinition m_commentDefinition; CommentDefinition m_commentDefinition;
QFutureWatcher<FileSearchResultList> *m_searchWatcher = nullptr; QFutureWatcher<SearchResultItems> *m_searchWatcher = nullptr;
QVector<SearchResult> m_searchResults; QVector<SearchResult> m_searchResults;
QTimer m_scrollBarUpdateTimer; QTimer m_scrollBarUpdateTimer;
HighlightScrollBarController *m_highlightScrollBarController = nullptr; HighlightScrollBarController *m_highlightScrollBarController = nullptr;
@@ -846,10 +847,27 @@ public:
private: private:
TextEditorWidget * const m_editor; TextEditorWidget * const m_editor;
static QFutureWatcher<FileSearchResultList> *m_selectWatcher; static QFutureWatcher<SearchResultItems> *m_selectWatcher;
}; };
QFutureWatcher<FileSearchResultList> *TextEditorWidgetFind::m_selectWatcher = nullptr; static QTextCursor selectRange(QTextDocument *textDocument, const Search::TextRange &range,
TextEditorWidgetPrivate::SearchResult *searchResult = nullptr)
{
const int startLine = qMax(range.begin.line - 1, 0);
const int startColumn = qMax(range.begin.column, 0);
const int endLine = qMax(range.end.line - 1, 0);
const int endColumn = qMax(range.end.column, 0);
const int startPosition = textDocument->findBlockByNumber(startLine).position() + startColumn;
const int endPosition = textDocument->findBlockByNumber(endLine).position() + endColumn;
QTextCursor textCursor(textDocument);
textCursor.setPosition(startPosition);
textCursor.setPosition(endPosition, QTextCursor::KeepAnchor);
if (searchResult)
*searchResult = {startPosition + 1, endPosition + 1};
return textCursor;
}
QFutureWatcher<SearchResultItems> *TextEditorWidgetFind::m_selectWatcher = nullptr;
void TextEditorWidgetFind::selectAll(const QString &txt, FindFlags findFlags) void TextEditorWidgetFind::selectAll(const QString &txt, FindFlags findFlags)
{ {
@@ -858,18 +876,16 @@ void TextEditorWidgetFind::selectAll(const QString &txt, FindFlags findFlags)
cancelCurrentSelectAll(); cancelCurrentSelectAll();
m_selectWatcher = new QFutureWatcher<FileSearchResultList>(); m_selectWatcher = new QFutureWatcher<SearchResultItems>();
connect(m_selectWatcher, &QFutureWatcher<Utils::FileSearchResultList>::finished, connect(m_selectWatcher, &QFutureWatcher<SearchResultItems>::finished, this, [this] {
this, [this] { const QFuture<SearchResultItems> future = m_selectWatcher->future();
const QFuture<FileSearchResultList> future = m_selectWatcher->future();
m_selectWatcher->deleteLater(); m_selectWatcher->deleteLater();
m_selectWatcher = nullptr; m_selectWatcher = nullptr;
if (future.resultCount() <= 0) if (future.resultCount() <= 0)
return; return;
const FileSearchResultList &results = future.result(); const SearchResultItems &results = future.result();
const QTextCursor c(m_editor->document()); const auto cursorForResult = [this](const SearchResultItem &item) {
auto cursorForResult = [c](const FileSearchResult &r) { return selectRange(m_editor->document(), item.mainRange());
return Utils::Text::selectAt(c, r.lineNumber, r.matchStart + 1, r.matchLength);
}; };
QList<QTextCursor> cursors = Utils::transform(results, cursorForResult); QList<QTextCursor> cursors = Utils::transform(results, cursorForResult);
cursors = Utils::filtered(cursors, [this](const QTextCursor &c) { cursors = Utils::filtered(cursors, [this](const QTextCursor &c) {
@@ -6671,16 +6687,11 @@ void TextEditorWidgetPrivate::searchResultsReady(int beginIndex, int endIndex)
{ {
QVector<SearchResult> results; QVector<SearchResult> results;
for (int index = beginIndex; index < endIndex; ++index) { for (int index = beginIndex; index < endIndex; ++index) {
const FileSearchResultList resultList = m_searchWatcher->resultAt(index); const SearchResultItems resultList = m_searchWatcher->resultAt(index);
for (FileSearchResult result : resultList) { for (const SearchResultItem &result : resultList) {
const QTextBlock &block = q->document()->findBlockByNumber(result.lineNumber - 1); SearchResult searchResult;
const int matchStart = block.position() + result.matchStart; if (q->inFindScope(selectRange(q->document(), result.mainRange(), &searchResult)))
QTextCursor cursor(block); results << searchResult;
cursor.setPosition(matchStart);
cursor.setPosition(matchStart + result.matchLength, QTextCursor::KeepAnchor);
if (!q->inFindScope(cursor))
continue;
results << SearchResult{matchStart, result.matchLength};
} }
} }
m_searchResults << results; m_searchResults << results;
@@ -6726,10 +6737,10 @@ void TextEditorWidgetPrivate::highlightSearchResultsInScrollBar()
adjustScrollBarRanges(); adjustScrollBarRanges();
m_searchWatcher = new QFutureWatcher<FileSearchResultList>(); m_searchWatcher = new QFutureWatcher<SearchResultItems>;
connect(m_searchWatcher, &QFutureWatcher<FileSearchResultList>::resultsReadyAt, connect(m_searchWatcher, &QFutureWatcher<SearchResultItems>::resultsReadyAt,
this, &TextEditorWidgetPrivate::searchResultsReady); this, &TextEditorWidgetPrivate::searchResultsReady);
connect(m_searchWatcher, &QFutureWatcher<FileSearchResultList>::finished, connect(m_searchWatcher, &QFutureWatcher<SearchResultItems>::finished,
this, &TextEditorWidgetPrivate::searchFinished); this, &TextEditorWidgetPrivate::searchFinished);
m_searchWatcher->setPendingResultsLimit(10); m_searchWatcher->setPendingResultsLimit(10);
@@ -6775,7 +6786,7 @@ void TextEditorWidgetPrivate::addSearchResultsToScrollBar(const QVector<SearchRe
{ {
if (!m_highlightScrollBarController) if (!m_highlightScrollBarController)
return; return;
for (SearchResult result : results) { for (const SearchResult &result : results) {
const QTextBlock &block = q->document()->findBlock(result.start); const QTextBlock &block = q->document()->findBlock(result.start);
if (block.isValid() && block.isVisible()) { if (block.isValid() && block.isVisible()) {
const int firstLine = block.layout()->lineForTextPosition(result.start - block.position()).lineNumber(); const int firstLine = block.layout()->lineForTextPosition(result.start - block.position()).lineNumber();

View File

@@ -22,18 +22,30 @@ private slots:
void caseSensitive(); void caseSensitive();
void caseInSensitive(); void caseInSensitive();
void matchCaseReplacement(); void matchCaseReplacement();
private:
const FilePath m_filePath = FilePath::fromString(":/tst_filesearch/testfile.txt");
}; };
namespace { SearchResultItem searchResult(const FilePath &fileName, const QString &matchingLine,
const char * const FILENAME = ":/tst_filesearch/testfile.txt"; int lineNumber, int matchStart, int matchLength,
const QStringList &regexpCapturedTexts = {})
{
SearchResultItem result;
result.setFilePath(fileName);
result.setLineText(matchingLine);
result.setMainRange(lineNumber, matchStart, matchLength);
result.setUserData(regexpCapturedTexts);
result.setUseTextEditorFont(true);
return result;
}
void test_helper(const Utils::FileSearchResultList &expectedResults, void test_helper(const FilePath &filePath, const SearchResultItems &expectedResults,
const QString &term, const QString &term, QTextDocument::FindFlags flags = {},
QTextDocument::FindFlags flags, tst_FileSearch::RegExpFlag regexp = tst_FileSearch::NoRegExp) tst_FileSearch::RegExpFlag regexp = tst_FileSearch::NoRegExp)
{ {
Utils::FileIterator *it = new Utils::FileListIterator({FilePath::fromString(FILENAME)}, FileIterator *it = new FileListIterator({filePath}, {QTextCodec::codecForLocale()});
{QTextCodec::codecForLocale()}); QFutureWatcher<SearchResultItems> watcher;
QFutureWatcher<Utils::FileSearchResultList> watcher;
QSignalSpy ready(&watcher, &QFutureWatcherBase::resultsReadyAt); QSignalSpy ready(&watcher, &QFutureWatcherBase::resultsReadyAt);
if (regexp == tst_FileSearch::NoRegExp) if (regexp == tst_FileSearch::NoRegExp)
watcher.setFuture(Utils::findInFiles(term, it, flags)); watcher.setFuture(Utils::findInFiles(term, it, flags));
@@ -42,46 +54,53 @@ namespace {
watcher.future().waitForFinished(); watcher.future().waitForFinished();
QTest::qWait(100); // process events QTest::qWait(100); // process events
QCOMPARE(ready.count(), 1); QCOMPARE(ready.count(), 1);
Utils::FileSearchResultList results = watcher.resultAt(0); SearchResultItems results = watcher.resultAt(0);
QCOMPARE(results.count(), expectedResults.count()); QCOMPARE(results.count(), expectedResults.count());
for (int i = 0; i < expectedResults.size(); ++i) { for (int i = 0; i < expectedResults.size(); ++i)
QCOMPARE(results.at(i), expectedResults.at(i)); QCOMPARE(results.at(i), expectedResults.at(i));
}
}
} }
void tst_FileSearch::multipleResults() void tst_FileSearch::multipleResults()
{ {
Utils::FileSearchResultList expectedResults; SearchResultItems expectedResults;
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 2, QLatin1String("search to find multiple find results"), 10, 4, QStringList()); expectedResults << searchResult(m_filePath, "search to find multiple find results", 2, 10, 4);
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 2, QLatin1String("search to find multiple find results"), 24, 4, QStringList()); expectedResults << searchResult(m_filePath, "search to find multiple find results", 2, 24, 4);
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 4, QLatin1String("here you find another result"), 9, 4, QStringList()); expectedResults << searchResult(m_filePath, "here you find another result", 4, 9, 4);
test_helper(expectedResults, QLatin1String("find"), QTextDocument::FindFlags()); test_helper(m_filePath, expectedResults, "find");
expectedResults.clear(); expectedResults.clear();
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 5, QLatin1String("aaaaaaaa this line has 2 results for four a in a row"), 0, 4, QStringList()); expectedResults << searchResult(m_filePath,
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 5, QLatin1String("aaaaaaaa this line has 2 results for four a in a row"), 4, 4, QStringList()); "aaaaaaaa this line has 2 results for four a in a row",
test_helper(expectedResults, QLatin1String("aaaa"), QTextDocument::FindFlags()); 5, 0, 4);
expectedResults << searchResult(m_filePath,
"aaaaaaaa this line has 2 results for four a in a row",
5, 4, 4);
test_helper(m_filePath, expectedResults, "aaaa");
expectedResults.clear(); expectedResults.clear();
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 5, QLatin1String("aaaaaaaa this line has 2 results for four a in a row"), 0, 4, QStringList() << QLatin1String("aaaa")); expectedResults << searchResult(m_filePath,
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 5, QLatin1String("aaaaaaaa this line has 2 results for four a in a row"), 4, 4, QStringList() << QLatin1String("aaaa")); "aaaaaaaa this line has 2 results for four a in a row",
test_helper(expectedResults, QLatin1String("aaaa"), QTextDocument::FindFlags(), RegExp); 5, 0, 4, {"aaaa"});
expectedResults << searchResult(m_filePath,
"aaaaaaaa this line has 2 results for four a in a row",
5, 4, 4, {"aaaa"});
test_helper(m_filePath, expectedResults, "aaaa", {}, RegExp);
} }
void tst_FileSearch::caseSensitive() void tst_FileSearch::caseSensitive()
{ {
Utils::FileSearchResultList expectedResults; SearchResultItems expectedResults;
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 3, QLatin1String("search CaseSensitively for casesensitive"), 7, 13, QStringList()); expectedResults << searchResult(m_filePath, "search CaseSensitively for casesensitive",
test_helper(expectedResults, QLatin1String("CaseSensitive"), QTextDocument::FindCaseSensitively); 3, 7, 13);
test_helper(m_filePath, expectedResults, "CaseSensitive", QTextDocument::FindCaseSensitively);
} }
void tst_FileSearch::caseInSensitive() void tst_FileSearch::caseInSensitive()
{ {
Utils::FileSearchResultList expectedResults; SearchResultItems expectedResults;
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 3, QLatin1String("search CaseSensitively for casesensitive"), 7, 13, QStringList()); expectedResults << searchResult(m_filePath, "search CaseSensitively for casesensitive", 3, 7, 13);
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 3, QLatin1String("search CaseSensitively for casesensitive"), 27, 13, QStringList()); expectedResults << searchResult(m_filePath, "search CaseSensitively for casesensitive", 3, 27, 13);
test_helper(expectedResults, QLatin1String("CaseSensitive"), QTextDocument::FindFlags()); test_helper(m_filePath, expectedResults, "CaseSensitive");
} }
void tst_FileSearch::matchCaseReplacement() void tst_FileSearch::matchCaseReplacement()

View File

@@ -38,7 +38,6 @@ add_qtc_test(unittest GTEST
TEST_RELATIVE_LIBEXEC_PATH="${TEST_RELATIVE_LIBEXEC_PATH}" TEST_RELATIVE_LIBEXEC_PATH="${TEST_RELATIVE_LIBEXEC_PATH}"
SOURCES SOURCES
abstractviewmock.h abstractviewmock.h
compare-operators.h
conditionally-disabled-tests.h conditionally-disabled-tests.h
dynamicastmatcherdiagnosticcontainer-matcher.h dynamicastmatcherdiagnosticcontainer-matcher.h
eventspy.cpp eventspy.h eventspy.cpp eventspy.h

View File

@@ -1,25 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <utils/searchresultitem.h>
namespace Utils {
namespace Search {
inline
bool operator==(const TextPosition first, class TextPosition second)
{
return first.line == second.line
&& first.column == second.column;
}
inline
bool operator==(const TextRange first, class TextRange second)
{
return first.begin == second.begin
&& first.end == second.end;
}
}
}

View File

@@ -13,8 +13,6 @@
#include <gtest/gtest-printers.h> #include <gtest/gtest-printers.h>
#include <gtest/gtest-typed-test.h> #include <gtest/gtest-typed-test.h>
#include "compare-operators.h"
#include "conditionally-disabled-tests.h" #include "conditionally-disabled-tests.h"
#include "gtest-creator-printing.h" #include "gtest-creator-printing.h"
#include "gtest-llvm-printing.h" #include "gtest-llvm-printing.h"