forked from qt-creator/qt-creator
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:
@@ -7,6 +7,7 @@
|
||||
#include "filepath.h"
|
||||
#include "mapreduce.h"
|
||||
#include "qtcassert.h"
|
||||
#include "searchresultitem.h"
|
||||
#include "stringutils.h"
|
||||
#include "utilstr.h"
|
||||
#include "utiltypes.h"
|
||||
@@ -69,7 +70,7 @@ public:
|
||||
FileSearch(const QString &searchTerm,
|
||||
QTextDocument::FindFlags flags,
|
||||
const QMap<FilePath, QString> &fileToContentsMap);
|
||||
void operator()(QFutureInterface<FileSearchResultList> &futureInterface,
|
||||
void operator()(QFutureInterface<SearchResultItems> &futureInterface,
|
||||
const FileIterator::Item &item) const;
|
||||
|
||||
private:
|
||||
@@ -91,7 +92,7 @@ public:
|
||||
QTextDocument::FindFlags flags,
|
||||
const QMap<FilePath, QString> &fileToContentsMap);
|
||||
FileSearchRegExp(const FileSearchRegExp &other);
|
||||
void operator()(QFutureInterface<FileSearchResultList> &futureInterface,
|
||||
void operator()(QFutureInterface<SearchResultItems> &futureInterface,
|
||||
const FileIterator::Item &item) const;
|
||||
|
||||
private:
|
||||
@@ -117,7 +118,7 @@ FileSearch::FileSearch(const QString &searchTerm,
|
||||
termDataUpper = searchTermUpper.constData();
|
||||
}
|
||||
|
||||
void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterface,
|
||||
void FileSearch::operator()(QFutureInterface<SearchResultItems> &futureInterface,
|
||||
const FileIterator::Item &item) const
|
||||
{
|
||||
if (futureInterface.isCanceled())
|
||||
@@ -125,7 +126,7 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
|
||||
qCDebug(searchLog) << "Searching in" << item.filePath;
|
||||
futureInterface.setProgressRange(0, 1);
|
||||
futureInterface.setProgressValue(0);
|
||||
FileSearchResultList results;
|
||||
SearchResultItems results;
|
||||
QString tempString;
|
||||
if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) {
|
||||
qCDebug(searchLog) << "- failed to get content for" << item.filePath;
|
||||
@@ -190,13 +191,13 @@ void FileSearch::operator()(QFutureInterface<FileSearchResultList> &futureInterf
|
||||
}
|
||||
}
|
||||
if (equal) {
|
||||
const QString resultItemText = clippedText(chunk, MAX_LINE_SIZE);
|
||||
results << FileSearchResult(item.filePath,
|
||||
lineNr,
|
||||
resultItemText,
|
||||
regionPtr - chunkPtr,
|
||||
termMaxIndex + 1,
|
||||
QStringList());
|
||||
SearchResultItem result;
|
||||
result.setFilePath(item.filePath);
|
||||
result.setMainRange(lineNr, regionPtr - chunkPtr, termMaxIndex + 1);
|
||||
result.setDisplayText(clippedText(chunk, MAX_LINE_SIZE));
|
||||
result.setUserData(QStringList());
|
||||
result.setUseTextEditorFont(true);
|
||||
results << result;
|
||||
regionPtr += termMaxIndex; // another +1 done by for-loop
|
||||
}
|
||||
}
|
||||
@@ -238,7 +239,7 @@ QRegularExpressionMatch FileSearchRegExp::doGuardedMatch(const QString &line, in
|
||||
return expression.match(line, offset);
|
||||
}
|
||||
|
||||
void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &futureInterface,
|
||||
void FileSearchRegExp::operator()(QFutureInterface<SearchResultItems> &futureInterface,
|
||||
const FileIterator::Item &item) const
|
||||
{
|
||||
if (!expression.isValid()) {
|
||||
@@ -250,7 +251,7 @@ void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &future
|
||||
qCDebug(searchLog) << "Searching in" << item.filePath;
|
||||
futureInterface.setProgressRange(0, 1);
|
||||
futureInterface.setProgressValue(0);
|
||||
FileSearchResultList results;
|
||||
SearchResultItems results;
|
||||
QString tempString;
|
||||
if (!getFileContent(item.filePath, item.encoding, &tempString, fileToContentsMap)) {
|
||||
qCDebug(searchLog) << "- failed to get content for" << item.filePath;
|
||||
@@ -270,12 +271,13 @@ void FileSearchRegExp::operator()(QFutureInterface<FileSearchResultList> &future
|
||||
int pos = 0;
|
||||
while ((match = doGuardedMatch(line, pos)).hasMatch()) {
|
||||
pos = match.capturedStart();
|
||||
results << FileSearchResult(item.filePath,
|
||||
lineNr,
|
||||
resultItemText,
|
||||
pos,
|
||||
match.capturedLength(),
|
||||
match.capturedTexts());
|
||||
SearchResultItem result;
|
||||
result.setFilePath(item.filePath);
|
||||
result.setMainRange(lineNr, pos, match.capturedLength());
|
||||
result.setDisplayText(resultItemText);
|
||||
result.setUserData(match.capturedTexts());
|
||||
result.setUseTextEditorFont(true);
|
||||
results << result;
|
||||
if (match.capturedLength() == 0)
|
||||
break;
|
||||
pos += match.capturedLength();
|
||||
@@ -299,12 +301,12 @@ struct SearchState
|
||||
SearchState(const QString &term, FileIterator *iterator) : searchTerm(term), files(iterator) {}
|
||||
QString searchTerm;
|
||||
FileIterator *files = nullptr;
|
||||
FileSearchResultList cachedResults;
|
||||
SearchResultItems cachedResults;
|
||||
int numFilesSearched = 0;
|
||||
int numMatches = 0;
|
||||
};
|
||||
|
||||
SearchState initFileSearch(QFutureInterface<FileSearchResultList> &futureInterface,
|
||||
SearchState initFileSearch(QFutureInterface<SearchResultItems> &futureInterface,
|
||||
const QString &searchTerm, FileIterator *files)
|
||||
{
|
||||
futureInterface.setProgressRange(0, files->maxProgress());
|
||||
@@ -312,9 +314,9 @@ SearchState initFileSearch(QFutureInterface<FileSearchResultList> &futureInterfa
|
||||
return SearchState(searchTerm, files);
|
||||
}
|
||||
|
||||
void collectSearchResults(QFutureInterface<FileSearchResultList> &futureInterface,
|
||||
void collectSearchResults(QFutureInterface<SearchResultItems> &futureInterface,
|
||||
SearchState &state,
|
||||
const FileSearchResultList &results)
|
||||
const SearchResultItems &results)
|
||||
{
|
||||
state.numMatches += results.size();
|
||||
state.cachedResults << results;
|
||||
@@ -333,7 +335,7 @@ void collectSearchResults(QFutureInterface<FileSearchResultList> &futureInterfac
|
||||
}
|
||||
}
|
||||
|
||||
void cleanUpFileSearch(QFutureInterface<FileSearchResultList> &futureInterface,
|
||||
void cleanUpFileSearch(QFutureInterface<SearchResultItems> &futureInterface,
|
||||
SearchState &state)
|
||||
{
|
||||
if (!state.cachedResults.isEmpty()) {
|
||||
@@ -356,13 +358,13 @@ void cleanUpFileSearch(QFutureInterface<FileSearchResultList> &futureInterface,
|
||||
|
||||
} // namespace
|
||||
|
||||
QFuture<FileSearchResultList> Utils::findInFiles(const QString &searchTerm,
|
||||
FileIterator *files,
|
||||
QTextDocument::FindFlags flags,
|
||||
const QMap<FilePath, QString> &fileToContentsMap)
|
||||
QFuture<SearchResultItems> Utils::findInFiles(const QString &searchTerm,
|
||||
FileIterator *files,
|
||||
QTextDocument::FindFlags flags,
|
||||
const QMap<FilePath, QString> &fileToContentsMap)
|
||||
{
|
||||
return mapReduce(files->begin(), files->end(),
|
||||
[searchTerm, files](QFutureInterface<FileSearchResultList> &futureInterface) {
|
||||
[searchTerm, files](QFutureInterface<SearchResultItems> &futureInterface) {
|
||||
return initFileSearch(futureInterface, searchTerm, files);
|
||||
},
|
||||
FileSearch(searchTerm, flags, fileToContentsMap),
|
||||
@@ -370,14 +372,14 @@ QFuture<FileSearchResultList> Utils::findInFiles(const QString &searchTerm,
|
||||
&cleanUpFileSearch);
|
||||
}
|
||||
|
||||
QFuture<FileSearchResultList> Utils::findInFilesRegExp(
|
||||
QFuture<SearchResultItems> Utils::findInFilesRegExp(
|
||||
const QString &searchTerm,
|
||||
FileIterator *files,
|
||||
QTextDocument::FindFlags flags,
|
||||
const QMap<FilePath, QString> &fileToContentsMap)
|
||||
{
|
||||
return mapReduce(files->begin(), files->end(),
|
||||
[searchTerm, files](QFutureInterface<FileSearchResultList> &futureInterface) {
|
||||
[searchTerm, files](QFutureInterface<SearchResultItems> &futureInterface) {
|
||||
return initFileSearch(futureInterface, searchTerm, files);
|
||||
},
|
||||
FileSearchRegExp(searchTerm, flags, fileToContentsMap),
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include "utils_global.h"
|
||||
|
||||
#include "filepath.h"
|
||||
#include "searchresultitem.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QStack>
|
||||
@@ -152,54 +152,20 @@ private:
|
||||
QList<Item *> m_items;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT FileSearchResult
|
||||
{
|
||||
public:
|
||||
FileSearchResult() = default;
|
||||
FileSearchResult(const FilePath &fileName, int lineNumber, const QString &matchingLine,
|
||||
int matchStart, int matchLength,
|
||||
const QStringList ®expCapturedTexts)
|
||||
: fileName(fileName),
|
||||
lineNumber(lineNumber),
|
||||
matchingLine(matchingLine),
|
||||
matchStart(matchStart),
|
||||
matchLength(matchLength),
|
||||
regexpCapturedTexts(regexpCapturedTexts)
|
||||
{}
|
||||
QTCREATOR_UTILS_EXPORT QFuture<SearchResultItems> findInFiles(const QString &searchTerm,
|
||||
FileIterator *files,
|
||||
QTextDocument::FindFlags flags,
|
||||
const QMap<FilePath, QString> &fileToContentsMap = {});
|
||||
|
||||
bool operator==(const FileSearchResult &o) const
|
||||
{
|
||||
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(
|
||||
QTCREATOR_UTILS_EXPORT QFuture<SearchResultItems> findInFilesRegExp(
|
||||
const QString &searchTerm,
|
||||
FileIterator *files,
|
||||
QTextDocument::FindFlags flags,
|
||||
const QMap<FilePath, QString> &fileToContentsMap = QMap<FilePath, QString>());
|
||||
const QMap<FilePath, QString> &fileToContentsMap = {});
|
||||
|
||||
QTCREATOR_UTILS_EXPORT QFuture<FileSearchResultList> findInFilesRegExp(
|
||||
const QString &searchTerm,
|
||||
FileIterator *files,
|
||||
QTextDocument::FindFlags flags,
|
||||
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);
|
||||
QTCREATOR_UTILS_EXPORT QString expandRegExpReplacement(const QString &replaceText,
|
||||
const QStringList &capturedTexts);
|
||||
QTCREATOR_UTILS_EXPORT QString matchCaseReplacement(const QString &originalText,
|
||||
const QString &replaceText);
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
Q_DECLARE_METATYPE(Utils::FileSearchResultList)
|
||||
|
||||
@@ -45,10 +45,20 @@ SearchResultColor::SearchResultColor(const QColor &textBg, const QColor &textFg,
|
||||
containingFunctionForeground = textForeground;
|
||||
}
|
||||
|
||||
QTCREATOR_UTILS_EXPORT size_t qHash(SearchResultColor::Style style, uint seed)
|
||||
static QString displayText(const QString &line)
|
||||
{
|
||||
int a = int(style);
|
||||
return ::qHash(a, seed);
|
||||
QString result = line;
|
||||
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)
|
||||
@@ -56,4 +66,29 @@ void SearchResultItem::setMainRange(int line, int column, int 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
|
||||
|
||||
@@ -28,6 +28,8 @@ public:
|
||||
|
||||
bool operator<(const TextPosition &other) const
|
||||
{ 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
|
||||
@@ -40,6 +42,8 @@ public:
|
||||
TextPosition end;
|
||||
|
||||
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
|
||||
@@ -76,6 +80,7 @@ public:
|
||||
|
||||
QString lineText() const { return m_lineText; }
|
||||
void setLineText(const QString &text) { m_lineText = text; }
|
||||
void setDisplayText(const QString &text);
|
||||
|
||||
QIcon icon() const { return m_icon; }
|
||||
void setIcon(const QIcon &icon) { m_icon = icon; }
|
||||
@@ -103,6 +108,9 @@ public:
|
||||
m_containingFunctionName = containingFunctionName;
|
||||
}
|
||||
|
||||
bool operator==(const SearchResultItem &other) const;
|
||||
bool operator!=(const SearchResultItem &other) const { return !(operator==(other)); }
|
||||
|
||||
private:
|
||||
QStringList m_path; // hierarchy to the parent item of this item
|
||||
QString m_lineText; // text to show for the item itself
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
|
||||
class GitGrepRunner
|
||||
{
|
||||
using PromiseType = QPromise<FileSearchResultList>;
|
||||
using PromiseType = QPromise<SearchResultItems>;
|
||||
|
||||
public:
|
||||
GitGrepRunner(const TextEditor::FileFindParameters ¶meters)
|
||||
@@ -67,23 +67,23 @@ public:
|
||||
QStringList regexpCapturedTexts;
|
||||
};
|
||||
|
||||
void processLine(const QString &line, FileSearchResultList *resultList) const
|
||||
void processLine(const QString &line, SearchResultItems *resultList) const
|
||||
{
|
||||
if (line.isEmpty())
|
||||
return;
|
||||
static const QLatin1String boldRed("\x1b[1;31m");
|
||||
static const QLatin1String resetColor("\x1b[m");
|
||||
FileSearchResult single;
|
||||
SearchResultItem result;
|
||||
const int lineSeparator = line.indexOf(QChar::Null);
|
||||
QString filePath = line.left(lineSeparator);
|
||||
if (!m_ref.isEmpty() && filePath.startsWith(m_ref))
|
||||
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);
|
||||
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);
|
||||
QRegularExpression regexp;
|
||||
QVector<Match> matches;
|
||||
QList<Match> matches;
|
||||
if (m_parameters.flags & FindRegularExpression) {
|
||||
const QRegularExpression::PatternOptions patternOptions =
|
||||
(m_parameters.flags & FindCaseSensitively)
|
||||
@@ -106,19 +106,18 @@ public:
|
||||
matches.append(match);
|
||||
text = text.left(matchStart) + matchText + text.mid(matchEnd + resetColor.size());
|
||||
}
|
||||
single.matchingLine = text;
|
||||
result.setDisplayText(text);
|
||||
|
||||
for (const auto &match : std::as_const(matches)) {
|
||||
single.matchStart = match.matchStart;
|
||||
single.matchLength = match.matchLength;
|
||||
single.regexpCapturedTexts = match.regexpCapturedTexts;
|
||||
resultList->append(single);
|
||||
result.setMainRange(lineNumber, match.matchStart, match.matchLength);
|
||||
result.setUserData(match.regexpCapturedTexts);
|
||||
resultList->append(result);
|
||||
}
|
||||
}
|
||||
|
||||
void read(PromiseType &fi, const QString &text)
|
||||
{
|
||||
FileSearchResultList resultList;
|
||||
SearchResultItems resultList;
|
||||
QString t = text;
|
||||
QTextStream stream(&t);
|
||||
while (!stream.atEnd() && !fi.isCanceled())
|
||||
@@ -272,7 +271,7 @@ void GitGrep::writeSettings(QSettings *settings) const
|
||||
settings->setValue(GitGrepRef, m_treeLineEdit->text());
|
||||
}
|
||||
|
||||
QFuture<FileSearchResultList> GitGrep::executeSearch(const TextEditor::FileFindParameters ¶meters,
|
||||
QFuture<SearchResultItems> GitGrep::executeSearch(const TextEditor::FileFindParameters ¶meters,
|
||||
TextEditor::BaseFileFind * /*baseFileFind*/)
|
||||
{
|
||||
return Utils::asyncRun(GitGrepRunner(parameters));
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
QVariant parameters() const override;
|
||||
void readSettings(QSettings *settings) override;
|
||||
void writeSettings(QSettings *settings) const override;
|
||||
QFuture<Utils::FileSearchResultList> executeSearch(
|
||||
QFuture<Utils::SearchResultItems> executeSearch(
|
||||
const TextEditor::FileFindParameters ¶meters,
|
||||
TextEditor::BaseFileFind *baseFileFind) override;
|
||||
Core::IEditor *openEditor(const Utils::SearchResultItem &item,
|
||||
|
||||
@@ -73,7 +73,7 @@ bool isSilverSearcherAvailable()
|
||||
return false;
|
||||
}
|
||||
|
||||
void runSilverSeacher(QPromise<FileSearchResultList> &promise, FileFindParameters parameters)
|
||||
void runSilverSeacher(QPromise<SearchResultItems> &promise, FileFindParameters parameters)
|
||||
{
|
||||
const FilePath directory = FilePath::fromUserInput(parameters.additionalParameters.toString());
|
||||
QStringList arguments = {"--parallel", "--ackmate"};
|
||||
@@ -120,7 +120,7 @@ void runSilverSeacher(QPromise<FileSearchResultList> &promise, FileFindParameter
|
||||
regexp.setPatternOptions(patternOptions);
|
||||
}
|
||||
SilverSearcher::SilverSearcherOutputParser parser(process.cleanedStdOut(), regexp);
|
||||
FileSearchResultList items = parser.parse();
|
||||
const SearchResultItems items = parser.parse();
|
||||
if (!items.isEmpty())
|
||||
promise.addResult(items);
|
||||
} else {
|
||||
@@ -189,7 +189,7 @@ void FindInFilesSilverSearcher::writeSettings(QSettings *settings) const
|
||||
settings->setValue(SearchOptionsString, m_searchOptionsLineEdit->text());
|
||||
}
|
||||
|
||||
QFuture<FileSearchResultList> FindInFilesSilverSearcher::executeSearch(
|
||||
QFuture<SearchResultItems> FindInFilesSilverSearcher::executeSearch(
|
||||
const FileFindParameters ¶meters, BaseFileFind * /*baseFileFind*/)
|
||||
{
|
||||
return Utils::asyncRun(runSilverSeacher, parameters);
|
||||
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
QVariant parameters() const override;
|
||||
void readSettings(QSettings *settings) override;
|
||||
void writeSettings(QSettings *settings) const override;
|
||||
QFuture<Utils::FileSearchResultList> executeSearch(
|
||||
QFuture<Utils::SearchResultItems> executeSearch(
|
||||
const TextEditor::FileFindParameters ¶meters, TextEditor::BaseFileFind *) override;
|
||||
Core::IEditor *openEditor(const Utils::SearchResultItem &item,
|
||||
const TextEditor::FileFindParameters ¶meters) override;
|
||||
|
||||
@@ -11,47 +11,57 @@ using namespace Utils;
|
||||
namespace SilverSearcher {
|
||||
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()
|
||||
{
|
||||
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")
|
||||
<< QString(":/file/path/to/filename.h\n"
|
||||
"1;1 5:match\n")
|
||||
<< FileSearchResultList({{"/file/path/to/filename.h", 1, "match", 1, 5, {}}});
|
||||
<< QString(":/file/path/to/filename.h\n"
|
||||
"1;1 5:match\n")
|
||||
<< SearchResultItems{searchResult("/file/path/to/filename.h", "match", 1, 1, 5)};
|
||||
QTest::addRow("multipleFilesWithOneMatch")
|
||||
<< QString(":/file/path/to/filename1.h\n"
|
||||
"1;1 5:match\n"
|
||||
"\n"
|
||||
":/file/path/to/filename2.h\n"
|
||||
"2;2 5: match\n")
|
||||
<< FileSearchResultList({{"/file/path/to/filename1.h", 1, "match", 1, 5, {}},
|
||||
{"/file/path/to/filename2.h", 2, " match", 2, 5, {}}});
|
||||
<< QString(":/file/path/to/filename1.h\n"
|
||||
"1;1 5:match\n"
|
||||
"\n"
|
||||
":/file/path/to/filename2.h\n"
|
||||
"2;2 5: match\n")
|
||||
<< SearchResultItems{searchResult("/file/path/to/filename1.h", "match", 1, 1, 5),
|
||||
searchResult("/file/path/to/filename2.h", " match", 2, 2, 5)};
|
||||
QTest::addRow("oneFileMultipleMatches")
|
||||
<< QString(":/file/path/to/filename.h\n"
|
||||
"1;1 5,7 5:match match\n")
|
||||
<< FileSearchResultList({{"/file/path/to/filename.h", 1, "match match", 1, 5, {}},
|
||||
{"/file/path/to/filename.h", 1, "match match", 7, 5, {}}});
|
||||
<< QString(":/file/path/to/filename.h\n"
|
||||
"1;1 5,7 5:match match\n")
|
||||
<< SearchResultItems{searchResult("/file/path/to/filename.h", "match match", 1, 1, 5),
|
||||
searchResult("/file/path/to/filename.h", "match match", 1, 7, 5)};
|
||||
QTest::addRow("multipleFilesWithMultipleMatches")
|
||||
<< QString(":/file/path/to/filename1.h\n"
|
||||
"1;1 5,7 5:match match\n"
|
||||
"\n"
|
||||
":/file/path/to/filename2.h\n"
|
||||
"2;2 5,8 5: match match\n")
|
||||
<< FileSearchResultList({{"/file/path/to/filename1.h", 1, "match match", 1, 5, {}},
|
||||
{"/file/path/to/filename1.h", 1, "match match", 7, 5, {}},
|
||||
{"/file/path/to/filename2.h", 2, " match match", 2, 5, {}},
|
||||
{"/file/path/to/filename2.h", 2, " match match", 8, 5, {}}});
|
||||
<< QString(":/file/path/to/filename1.h\n"
|
||||
"1;1 5,7 5:match match\n"
|
||||
"\n"
|
||||
":/file/path/to/filename2.h\n"
|
||||
"2;2 5,8 5: match match\n")
|
||||
<< SearchResultItems{searchResult("/file/path/to/filename1.h", "match match", 1, 1, 5),
|
||||
searchResult("/file/path/to/filename1.h", "match match", 1, 7, 5),
|
||||
searchResult("/file/path/to/filename2.h", " match match", 2, 2, 5),
|
||||
searchResult("/file/path/to/filename2.h", " match match", 2, 8, 5)};
|
||||
}
|
||||
|
||||
void OutputParserTest::test()
|
||||
{
|
||||
QFETCH(QString, parserOutput);
|
||||
QFETCH(FileSearchResultList, results);
|
||||
QFETCH(SearchResultItems, results);
|
||||
SilverSearcher::SilverSearcherOutputParser ssop(parserOutput);
|
||||
const FileSearchResultList items = ssop.parse();
|
||||
const SearchResultItems items = ssop.parse();
|
||||
QCOMPARE(items, results);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ SilverSearcherOutputParser::SilverSearcherOutputParser(
|
||||
hasRegexp = !regexp.pattern().isEmpty();
|
||||
}
|
||||
|
||||
Utils::FileSearchResultList SilverSearcherOutputParser::parse()
|
||||
Utils::SearchResultItems SilverSearcherOutputParser::parse()
|
||||
{
|
||||
while (index < outputSize - 1) {
|
||||
if (output[index] == '\n') {
|
||||
@@ -25,15 +25,15 @@ Utils::FileSearchResultList SilverSearcherOutputParser::parse()
|
||||
}
|
||||
parseFilePath();
|
||||
while (index < outputSize && output[index] != '\n') {
|
||||
parseLineNumber();
|
||||
const int lineNumber = parseLineNumber();
|
||||
if (index >= outputSize - 1)
|
||||
break;
|
||||
int matches = parseMatches();
|
||||
int matches = parseMatches(lineNumber);
|
||||
if (index >= outputSize - 1)
|
||||
break;
|
||||
parseText();
|
||||
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;
|
||||
while (index < outputSize && output[index] != '\n')
|
||||
++index;
|
||||
item.fileName = Utils::FilePath::fromString(QString(output.data() + startIndex, index - startIndex));
|
||||
item.setFilePath(Utils::FilePath::fromString(QString(output.data() + startIndex,
|
||||
index - startIndex)));
|
||||
++index;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SilverSearcherOutputParser::parseLineNumber()
|
||||
int SilverSearcherOutputParser::parseLineNumber()
|
||||
{
|
||||
int startIndex = 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;
|
||||
return true;
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
bool SilverSearcherOutputParser::parseMatchIndex()
|
||||
int SilverSearcherOutputParser::parseMatchIndex()
|
||||
{
|
||||
int startIndex = 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;
|
||||
return true;
|
||||
return lineStart;
|
||||
}
|
||||
|
||||
bool SilverSearcherOutputParser::parseMatchLength()
|
||||
int SilverSearcherOutputParser::parseMatchLength()
|
||||
{
|
||||
int startIndex = index;
|
||||
while (index < outputSize && output[++index] != ':' && output[index] != ',') { }
|
||||
|
||||
item.matchLength = QString(output.data() + startIndex, index - startIndex).toInt();
|
||||
return true;
|
||||
return QString(output.data() + startIndex, index - startIndex).toInt();
|
||||
}
|
||||
|
||||
int SilverSearcherOutputParser::parseMatches()
|
||||
int SilverSearcherOutputParser::parseMatches(int lineNumber)
|
||||
{
|
||||
int matches = 1;
|
||||
const int colon = output.indexOf(':', index);
|
||||
@@ -94,11 +94,12 @@ int SilverSearcherOutputParser::parseMatches()
|
||||
++matches;
|
||||
++index;
|
||||
}
|
||||
parseMatchIndex();
|
||||
parseMatchLength();
|
||||
const int lineStart = parseMatchIndex();
|
||||
const int lineLength = parseMatchLength();
|
||||
item.setMainRange(lineNumber, lineStart, lineLength);
|
||||
if (hasRegexp) {
|
||||
const QString part = QString(text.mid(item.matchStart, item.matchLength));
|
||||
item.regexpCapturedTexts = regexp.match(part).capturedTexts();
|
||||
const QString part = QString(text.mid(lineStart, lineLength));
|
||||
item.setUserData(regexp.match(part).capturedTexts());
|
||||
}
|
||||
items << item;
|
||||
}
|
||||
@@ -111,7 +112,8 @@ bool SilverSearcherOutputParser::parseText()
|
||||
{
|
||||
int startIndex = index;
|
||||
while (index < outputSize && output[++index] != '\n') { }
|
||||
item.matchingLine = QString(output.data() + startIndex, index - startIndex);
|
||||
|
||||
item.setLineText(QString(output.data() + startIndex, index - startIndex));
|
||||
++index;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -16,13 +16,13 @@ class SilverSearcherOutputParser
|
||||
public:
|
||||
SilverSearcherOutputParser(const QString &output, const QRegularExpression ®exp = {});
|
||||
|
||||
Utils::FileSearchResultList parse();
|
||||
Utils::SearchResultItems parse();
|
||||
|
||||
private:
|
||||
int parseMatches();
|
||||
bool parseMatchLength();
|
||||
bool parseMatchIndex();
|
||||
bool parseLineNumber();
|
||||
int parseMatches(int lineNumber);
|
||||
int parseMatchLength();
|
||||
int parseMatchIndex();
|
||||
int parseLineNumber();
|
||||
bool parseFilePath();
|
||||
bool parseText();
|
||||
|
||||
@@ -31,8 +31,8 @@ private:
|
||||
bool hasRegexp = false;
|
||||
int outputSize = 0;
|
||||
int index = 0;
|
||||
Utils::FileSearchResult item;
|
||||
Utils::FileSearchResultList items;
|
||||
Utils::SearchResultItem item;
|
||||
Utils::SearchResultItems items;
|
||||
};
|
||||
|
||||
} // namespace SilverSearcher
|
||||
|
||||
@@ -51,9 +51,8 @@ public:
|
||||
QVariant parameters() const override { return {}; }
|
||||
void readSettings(QSettings * /*settings*/) override {}
|
||||
void writeSettings(QSettings * /*settings*/) const override {}
|
||||
QFuture<FileSearchResultList> executeSearch(
|
||||
const TextEditor::FileFindParameters ¶meters,
|
||||
BaseFileFind *baseFileFind) override
|
||||
QFuture<SearchResultItems> executeSearch(const TextEditor::FileFindParameters ¶meters,
|
||||
BaseFileFind *baseFileFind) override
|
||||
{
|
||||
const auto func = parameters.flags & FindRegularExpression ? Utils::findInFilesRegExp
|
||||
: Utils::findInFiles;
|
||||
@@ -208,34 +207,6 @@ void BaseFileFind::setCurrentSearchEngine(int index)
|
||||
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,
|
||||
SearchResultWindow::SearchMode searchMode)
|
||||
{
|
||||
@@ -283,7 +254,7 @@ void BaseFileFind::runSearch(SearchResult *search)
|
||||
{
|
||||
const FileFindParameters parameters = search->userData().value<FileFindParameters>();
|
||||
SearchResultWindow::instance()->popup(IOutputPane::Flags(IOutputPane::ModeSwitch|IOutputPane::WithFocus));
|
||||
auto watcher = new QFutureWatcher<FileSearchResultList>();
|
||||
auto watcher = new QFutureWatcher<SearchResultItems>;
|
||||
watcher->setPendingResultsLimit(1);
|
||||
// search is deleted if it is removed from search panel
|
||||
connect(search, &QObject::destroyed, watcher, &QFutureWatcherBase::cancel);
|
||||
@@ -293,14 +264,14 @@ void BaseFileFind::runSearch(SearchResult *search)
|
||||
watcher->setPaused(paused);
|
||||
});
|
||||
connect(watcher, &QFutureWatcherBase::resultReadyAt, search, [watcher, search](int index) {
|
||||
displayResult(watcher, search, index);
|
||||
search->addResults(watcher->resultAt(index), SearchResult::AddOrdered);
|
||||
});
|
||||
// auto-delete:
|
||||
connect(watcher, &QFutureWatcherBase::finished, watcher, &QObject::deleteLater);
|
||||
connect(watcher, &QFutureWatcherBase::finished, search, [watcher, search]() {
|
||||
search->finishSearch(watcher->isCanceled());
|
||||
});
|
||||
QFuture<FileSearchResultList> future = executeSearch(parameters);
|
||||
QFuture<SearchResultItems> future = executeSearch(parameters);
|
||||
watcher->setFuture(future);
|
||||
d->m_futureSynchronizer.addFuture(future);
|
||||
FutureProgress *progress = ProgressManager::addTask(future,
|
||||
@@ -541,7 +512,7 @@ QVariant BaseFileFind::getAdditionalParameters(SearchResult *search)
|
||||
return search->userData().value<FileFindParameters>().additionalParameters;
|
||||
}
|
||||
|
||||
QFuture<FileSearchResultList> BaseFileFind::executeSearch(const FileFindParameters ¶meters)
|
||||
QFuture<SearchResultItems> BaseFileFind::executeSearch(const FileFindParameters ¶meters)
|
||||
{
|
||||
return d->m_searchEngines[parameters.searchEngineIndex]->executeSearch(parameters, this);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
virtual QVariant parameters() const = 0;
|
||||
virtual void readSettings(QSettings *settings) = 0;
|
||||
virtual void writeSettings(QSettings *settings) const = 0;
|
||||
virtual QFuture<Utils::FileSearchResultList> executeSearch(
|
||||
virtual QFuture<Utils::SearchResultItems> executeSearch(
|
||||
const FileFindParameters ¶meters, BaseFileFind *baseFileFind) = 0;
|
||||
virtual Core::IEditor *openEditor(const Utils::SearchResultItem &item,
|
||||
const FileFindParameters ¶meters) = 0;
|
||||
@@ -97,7 +97,7 @@ protected:
|
||||
virtual QString label() 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
|
||||
QFuture<Utils::FileSearchResultList> executeSearch(const FileFindParameters ¶meters);
|
||||
QFuture<Utils::SearchResultItems> executeSearch(const FileFindParameters ¶meters);
|
||||
|
||||
void writeCommonSettings(QSettings *settings);
|
||||
void readCommonSettings(QSettings *settings, const QString &defaultFilter, const QString &defaultExclusionFilter);
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include <utils/minimizableinfobars.h>
|
||||
#include <utils/multitextcursor.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/searchresultitem.h>
|
||||
#include <utils/styledbar.h>
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/textutils.h>
|
||||
@@ -790,7 +791,7 @@ public:
|
||||
QScopedPointer<AutoCompleter> m_autoCompleter;
|
||||
CommentDefinition m_commentDefinition;
|
||||
|
||||
QFutureWatcher<FileSearchResultList> *m_searchWatcher = nullptr;
|
||||
QFutureWatcher<SearchResultItems> *m_searchWatcher = nullptr;
|
||||
QVector<SearchResult> m_searchResults;
|
||||
QTimer m_scrollBarUpdateTimer;
|
||||
HighlightScrollBarController *m_highlightScrollBarController = nullptr;
|
||||
@@ -846,10 +847,27 @@ public:
|
||||
|
||||
private:
|
||||
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)
|
||||
{
|
||||
@@ -858,26 +876,24 @@ void TextEditorWidgetFind::selectAll(const QString &txt, FindFlags findFlags)
|
||||
|
||||
cancelCurrentSelectAll();
|
||||
|
||||
m_selectWatcher = new QFutureWatcher<FileSearchResultList>();
|
||||
connect(m_selectWatcher, &QFutureWatcher<Utils::FileSearchResultList>::finished,
|
||||
this, [this] {
|
||||
const QFuture<FileSearchResultList> future = m_selectWatcher->future();
|
||||
m_selectWatcher->deleteLater();
|
||||
m_selectWatcher = nullptr;
|
||||
if (future.resultCount() <= 0)
|
||||
return;
|
||||
const FileSearchResultList &results = future.result();
|
||||
const QTextCursor c(m_editor->document());
|
||||
auto cursorForResult = [c](const FileSearchResult &r) {
|
||||
return Utils::Text::selectAt(c, r.lineNumber, r.matchStart + 1, r.matchLength);
|
||||
};
|
||||
QList<QTextCursor> cursors = Utils::transform(results, cursorForResult);
|
||||
cursors = Utils::filtered(cursors, [this](const QTextCursor &c) {
|
||||
return m_editor->inFindScope(c);
|
||||
});
|
||||
m_editor->setMultiTextCursor(MultiTextCursor(cursors));
|
||||
m_editor->setFocus();
|
||||
});
|
||||
m_selectWatcher = new QFutureWatcher<SearchResultItems>();
|
||||
connect(m_selectWatcher, &QFutureWatcher<SearchResultItems>::finished, this, [this] {
|
||||
const QFuture<SearchResultItems> future = m_selectWatcher->future();
|
||||
m_selectWatcher->deleteLater();
|
||||
m_selectWatcher = nullptr;
|
||||
if (future.resultCount() <= 0)
|
||||
return;
|
||||
const SearchResultItems &results = future.result();
|
||||
const auto cursorForResult = [this](const SearchResultItem &item) {
|
||||
return selectRange(m_editor->document(), item.mainRange());
|
||||
};
|
||||
QList<QTextCursor> cursors = Utils::transform(results, cursorForResult);
|
||||
cursors = Utils::filtered(cursors, [this](const QTextCursor &c) {
|
||||
return m_editor->inFindScope(c);
|
||||
});
|
||||
m_editor->setMultiTextCursor(MultiTextCursor(cursors));
|
||||
m_editor->setFocus();
|
||||
});
|
||||
|
||||
const FilePath &fileName = m_editor->textDocument()->filePath();
|
||||
QMap<FilePath, QString> fileToContentsMap;
|
||||
@@ -6671,16 +6687,11 @@ void TextEditorWidgetPrivate::searchResultsReady(int beginIndex, int endIndex)
|
||||
{
|
||||
QVector<SearchResult> results;
|
||||
for (int index = beginIndex; index < endIndex; ++index) {
|
||||
const FileSearchResultList resultList = m_searchWatcher->resultAt(index);
|
||||
for (FileSearchResult result : resultList) {
|
||||
const QTextBlock &block = q->document()->findBlockByNumber(result.lineNumber - 1);
|
||||
const int matchStart = block.position() + result.matchStart;
|
||||
QTextCursor cursor(block);
|
||||
cursor.setPosition(matchStart);
|
||||
cursor.setPosition(matchStart + result.matchLength, QTextCursor::KeepAnchor);
|
||||
if (!q->inFindScope(cursor))
|
||||
continue;
|
||||
results << SearchResult{matchStart, result.matchLength};
|
||||
const SearchResultItems resultList = m_searchWatcher->resultAt(index);
|
||||
for (const SearchResultItem &result : resultList) {
|
||||
SearchResult searchResult;
|
||||
if (q->inFindScope(selectRange(q->document(), result.mainRange(), &searchResult)))
|
||||
results << searchResult;
|
||||
}
|
||||
}
|
||||
m_searchResults << results;
|
||||
@@ -6726,10 +6737,10 @@ void TextEditorWidgetPrivate::highlightSearchResultsInScrollBar()
|
||||
|
||||
adjustScrollBarRanges();
|
||||
|
||||
m_searchWatcher = new QFutureWatcher<FileSearchResultList>();
|
||||
connect(m_searchWatcher, &QFutureWatcher<FileSearchResultList>::resultsReadyAt,
|
||||
m_searchWatcher = new QFutureWatcher<SearchResultItems>;
|
||||
connect(m_searchWatcher, &QFutureWatcher<SearchResultItems>::resultsReadyAt,
|
||||
this, &TextEditorWidgetPrivate::searchResultsReady);
|
||||
connect(m_searchWatcher, &QFutureWatcher<FileSearchResultList>::finished,
|
||||
connect(m_searchWatcher, &QFutureWatcher<SearchResultItems>::finished,
|
||||
this, &TextEditorWidgetPrivate::searchFinished);
|
||||
m_searchWatcher->setPendingResultsLimit(10);
|
||||
|
||||
@@ -6775,7 +6786,7 @@ void TextEditorWidgetPrivate::addSearchResultsToScrollBar(const QVector<SearchRe
|
||||
{
|
||||
if (!m_highlightScrollBarController)
|
||||
return;
|
||||
for (SearchResult result : results) {
|
||||
for (const SearchResult &result : results) {
|
||||
const QTextBlock &block = q->document()->findBlock(result.start);
|
||||
if (block.isValid() && block.isVisible()) {
|
||||
const int firstLine = block.layout()->lineForTextPosition(result.start - block.position()).lineNumber();
|
||||
|
||||
@@ -22,66 +22,85 @@ private slots:
|
||||
void caseSensitive();
|
||||
void caseInSensitive();
|
||||
void matchCaseReplacement();
|
||||
|
||||
private:
|
||||
const FilePath m_filePath = FilePath::fromString(":/tst_filesearch/testfile.txt");
|
||||
};
|
||||
|
||||
namespace {
|
||||
const char * const FILENAME = ":/tst_filesearch/testfile.txt";
|
||||
SearchResultItem searchResult(const FilePath &fileName, const QString &matchingLine,
|
||||
int lineNumber, int matchStart, int matchLength,
|
||||
const QStringList ®expCapturedTexts = {})
|
||||
{
|
||||
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,
|
||||
const QString &term,
|
||||
QTextDocument::FindFlags flags, tst_FileSearch::RegExpFlag regexp = tst_FileSearch::NoRegExp)
|
||||
{
|
||||
Utils::FileIterator *it = new Utils::FileListIterator({FilePath::fromString(FILENAME)},
|
||||
{QTextCodec::codecForLocale()});
|
||||
QFutureWatcher<Utils::FileSearchResultList> watcher;
|
||||
QSignalSpy ready(&watcher, &QFutureWatcherBase::resultsReadyAt);
|
||||
if (regexp == tst_FileSearch::NoRegExp)
|
||||
watcher.setFuture(Utils::findInFiles(term, it, flags));
|
||||
else
|
||||
watcher.setFuture(Utils::findInFilesRegExp(term, it, flags));
|
||||
watcher.future().waitForFinished();
|
||||
QTest::qWait(100); // process events
|
||||
QCOMPARE(ready.count(), 1);
|
||||
Utils::FileSearchResultList results = watcher.resultAt(0);
|
||||
QCOMPARE(results.count(), expectedResults.count());
|
||||
for (int i = 0; i < expectedResults.size(); ++i) {
|
||||
QCOMPARE(results.at(i), expectedResults.at(i));
|
||||
}
|
||||
}
|
||||
void test_helper(const FilePath &filePath, const SearchResultItems &expectedResults,
|
||||
const QString &term, QTextDocument::FindFlags flags = {},
|
||||
tst_FileSearch::RegExpFlag regexp = tst_FileSearch::NoRegExp)
|
||||
{
|
||||
FileIterator *it = new FileListIterator({filePath}, {QTextCodec::codecForLocale()});
|
||||
QFutureWatcher<SearchResultItems> watcher;
|
||||
QSignalSpy ready(&watcher, &QFutureWatcherBase::resultsReadyAt);
|
||||
if (regexp == tst_FileSearch::NoRegExp)
|
||||
watcher.setFuture(Utils::findInFiles(term, it, flags));
|
||||
else
|
||||
watcher.setFuture(Utils::findInFilesRegExp(term, it, flags));
|
||||
watcher.future().waitForFinished();
|
||||
QTest::qWait(100); // process events
|
||||
QCOMPARE(ready.count(), 1);
|
||||
SearchResultItems results = watcher.resultAt(0);
|
||||
QCOMPARE(results.count(), expectedResults.count());
|
||||
for (int i = 0; i < expectedResults.size(); ++i)
|
||||
QCOMPARE(results.at(i), expectedResults.at(i));
|
||||
}
|
||||
|
||||
void tst_FileSearch::multipleResults()
|
||||
{
|
||||
Utils::FileSearchResultList expectedResults;
|
||||
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 2, QLatin1String("search to find multiple find results"), 10, 4, QStringList());
|
||||
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 2, QLatin1String("search to find multiple find results"), 24, 4, QStringList());
|
||||
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 4, QLatin1String("here you find another result"), 9, 4, QStringList());
|
||||
test_helper(expectedResults, QLatin1String("find"), QTextDocument::FindFlags());
|
||||
SearchResultItems expectedResults;
|
||||
expectedResults << searchResult(m_filePath, "search to find multiple find results", 2, 10, 4);
|
||||
expectedResults << searchResult(m_filePath, "search to find multiple find results", 2, 24, 4);
|
||||
expectedResults << searchResult(m_filePath, "here you find another result", 4, 9, 4);
|
||||
test_helper(m_filePath, expectedResults, "find");
|
||||
|
||||
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 << FileSearchResult(FilePath::fromString(FILENAME), 5, QLatin1String("aaaaaaaa this line has 2 results for four a in a row"), 4, 4, QStringList());
|
||||
test_helper(expectedResults, QLatin1String("aaaa"), QTextDocument::FindFlags());
|
||||
expectedResults << searchResult(m_filePath,
|
||||
"aaaaaaaa this line has 2 results for four a in a row",
|
||||
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 << FileSearchResult(FilePath::fromString(FILENAME), 5, QLatin1String("aaaaaaaa this line has 2 results for four a in a row"), 0, 4, QStringList() << QLatin1String("aaaa"));
|
||||
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 5, QLatin1String("aaaaaaaa this line has 2 results for four a in a row"), 4, 4, QStringList() << QLatin1String("aaaa"));
|
||||
test_helper(expectedResults, QLatin1String("aaaa"), QTextDocument::FindFlags(), RegExp);
|
||||
expectedResults << searchResult(m_filePath,
|
||||
"aaaaaaaa this line has 2 results for four a in a row",
|
||||
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()
|
||||
{
|
||||
Utils::FileSearchResultList expectedResults;
|
||||
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 3, QLatin1String("search CaseSensitively for casesensitive"), 7, 13, QStringList());
|
||||
test_helper(expectedResults, QLatin1String("CaseSensitive"), QTextDocument::FindCaseSensitively);
|
||||
SearchResultItems expectedResults;
|
||||
expectedResults << searchResult(m_filePath, "search CaseSensitively for casesensitive",
|
||||
3, 7, 13);
|
||||
test_helper(m_filePath, expectedResults, "CaseSensitive", QTextDocument::FindCaseSensitively);
|
||||
}
|
||||
|
||||
void tst_FileSearch::caseInSensitive()
|
||||
{
|
||||
Utils::FileSearchResultList expectedResults;
|
||||
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 3, QLatin1String("search CaseSensitively for casesensitive"), 7, 13, QStringList());
|
||||
expectedResults << FileSearchResult(FilePath::fromString(FILENAME), 3, QLatin1String("search CaseSensitively for casesensitive"), 27, 13, QStringList());
|
||||
test_helper(expectedResults, QLatin1String("CaseSensitive"), QTextDocument::FindFlags());
|
||||
SearchResultItems expectedResults;
|
||||
expectedResults << searchResult(m_filePath, "search CaseSensitively for casesensitive", 3, 7, 13);
|
||||
expectedResults << searchResult(m_filePath, "search CaseSensitively for casesensitive", 3, 27, 13);
|
||||
test_helper(m_filePath, expectedResults, "CaseSensitive");
|
||||
}
|
||||
|
||||
void tst_FileSearch::matchCaseReplacement()
|
||||
|
||||
@@ -38,7 +38,6 @@ add_qtc_test(unittest GTEST
|
||||
TEST_RELATIVE_LIBEXEC_PATH="${TEST_RELATIVE_LIBEXEC_PATH}"
|
||||
SOURCES
|
||||
abstractviewmock.h
|
||||
compare-operators.h
|
||||
conditionally-disabled-tests.h
|
||||
dynamicastmatcherdiagnosticcontainer-matcher.h
|
||||
eventspy.cpp eventspy.h
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,6 @@
|
||||
#include <gtest/gtest-printers.h>
|
||||
#include <gtest/gtest-typed-test.h>
|
||||
|
||||
#include "compare-operators.h"
|
||||
|
||||
#include "conditionally-disabled-tests.h"
|
||||
#include "gtest-creator-printing.h"
|
||||
#include "gtest-llvm-printing.h"
|
||||
|
||||
Reference in New Issue
Block a user