From 64d209c24bb618fee5e0d4ba427d656c3b71e5ff Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Thu, 1 Jun 2023 21:04:18 +0200 Subject: [PATCH] SilverSearcher: Reuse searchInProcessOutput() Change-Id: Ifc28a88c7bd0de94ea78c5f3eaaa2179b0aee600 Reviewed-by: Qt CI Bot Reviewed-by: Orgad Shaneh --- .../findinfilessilversearcher.cpp | 127 +++++------------- .../silversearcher/silversearcherparser.cpp | 31 ++--- .../silversearcher/silversearcherparser.h | 15 +-- 3 files changed, 48 insertions(+), 125 deletions(-) diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index 313d23eda27..6cf428bb64f 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -59,114 +59,51 @@ static bool isSilverSearcherAvailable() && silverSearcherProcess.cleanedStdOut().contains("ag version"); } -static std::optional regExpFromParameters(const FileFindParameters ¶meters) -{ - if (!(parameters.flags & FindRegularExpression)) - return {}; - - const QRegularExpression::PatternOptions patternOptions - = (parameters.flags & FindCaseSensitively) - ? QRegularExpression::NoPatternOption - : QRegularExpression::CaseInsensitiveOption; - QRegularExpression regExp; - regExp.setPattern(parameters.text); - regExp.setPatternOptions(patternOptions); - return regExp; -} - static void runSilverSeacher(QPromise &promise, const FileFindParameters ¶meters) { - const FilePath directory = FilePath::fromUserInput(parameters.additionalParameters.toString()); - QStringList arguments = {"--parallel", "--ackmate"}; + const auto setupProcess = [parameters](Process &process) { + const FilePath directory + = FilePath::fromUserInput(parameters.additionalParameters.toString()); + QStringList arguments = {"--parallel", "--ackmate"}; - if (parameters.flags & FindCaseSensitively) - arguments << "-s"; - else - arguments << "-i"; + if (parameters.flags & FindCaseSensitively) + arguments << "-s"; + else + arguments << "-i"; - if (parameters.flags & FindWholeWords) - arguments << "-w"; + if (parameters.flags & FindWholeWords) + arguments << "-w"; - if (!(parameters.flags & FindRegularExpression)) - arguments << "-Q"; + if (!(parameters.flags & FindRegularExpression)) + arguments << "-Q"; - for (const QString &filter : std::as_const(parameters.exclusionFilters)) - arguments << "--ignore" << filter; + for (const QString &filter : std::as_const(parameters.exclusionFilters)) + arguments << "--ignore" << filter; - QString nameFiltersAsRegExp; - for (const QString &filter : std::as_const(parameters.nameFilters)) - nameFiltersAsRegExp += QString("(%1)|").arg(convertWildcardToRegex(filter)); - nameFiltersAsRegExp.remove(nameFiltersAsRegExp.length() - 1, 1); + QString nameFiltersAsRegExp; + for (const QString &filter : std::as_const(parameters.nameFilters)) + nameFiltersAsRegExp += QString("(%1)|").arg(convertWildcardToRegex(filter)); + nameFiltersAsRegExp.remove(nameFiltersAsRegExp.length() - 1, 1); - arguments << "-G" << nameFiltersAsRegExp; + arguments << "-G" << nameFiltersAsRegExp; - const SilverSearcherSearchOptions params = parameters.searchEngineParameters - .value(); - if (!params.searchOptions.isEmpty()) - arguments << params.searchOptions.split(' '); + const SilverSearcherSearchOptions params = parameters.searchEngineParameters + .value(); + if (!params.searchOptions.isEmpty()) + arguments << params.searchOptions.split(' '); - arguments << "--" << parameters.text << directory.normalizedPathName().toString(); + arguments << "--" << parameters.text << directory.normalizedPathName().toString(); + process.setCommand({"ag", arguments}); + }; - QEventLoop loop; + FilePath lastFilePath; + const auto outputParser = [&lastFilePath](const QFuture &future, const QString &input, + const std::optional ®Exp) { + return SilverSearcher::parse(future, input, regExp, &lastFilePath); + }; - Process process; - process.setCommand({"ag", arguments}); - ParserState parserState; - const std::optional regExp = regExpFromParameters(parameters); - QStringList outputBuffer; - // The states transition exactly in this order: - enum State { BelowLimit, AboveLimit, Paused, Resumed }; - State state = BelowLimit; - process.setStdOutCallback([&process, &loop, &promise, &state, &outputBuffer, &parserState, - regExp](const QString &output) { - if (promise.isCanceled()) { - process.close(); - loop.quit(); - return; - } - // The SearchResultWidget is going to pause the search anyway, so start buffering - // the output. - if (state == AboveLimit || state == Paused) { - outputBuffer.append(output); - } else { - SilverSearcher::parse(promise, output, &parserState, regExp); - if (state == BelowLimit && parserState.m_reportedResultsCount > 200000) - state = AboveLimit; - } - }); - QObject::connect(&process, &Process::done, &loop, [&loop, &promise, &state] { - if (state == BelowLimit || state == Resumed || promise.isCanceled()) - loop.quit(); - }); - - process.start(); - if (process.state() == QProcess::NotRunning) - return; - - QFutureWatcher watcher; - QFuture future(promise.future()); - QObject::connect(&watcher, &QFutureWatcherBase::canceled, &loop, [&process, &loop] { - process.close(); - loop.quit(); - }); - QObject::connect(&watcher, &QFutureWatcherBase::paused, &loop, [&state] { state = Paused; }); - QObject::connect(&watcher, &QFutureWatcherBase::resumed, &loop, - [&process, &loop, &promise, &state, &outputBuffer, &parserState, regExp] { - state = Resumed; - for (const QString &output : outputBuffer) { - if (promise.isCanceled()) { - process.close(); - loop.quit(); - } - SilverSearcher::parse(promise, output, &parserState, regExp); - } - outputBuffer.clear(); - if (process.state() == QProcess::NotRunning) - loop.quit(); - }); - watcher.setFuture(future); - loop.exec(QEventLoop::ExcludeUserInputEvents); + TextEditor::searchInProcessOutput(promise, parameters, setupProcess, outputParser); } } // namespace diff --git a/src/plugins/silversearcher/silversearcherparser.cpp b/src/plugins/silversearcher/silversearcherparser.cpp index 9cdf5211a67..1a2f5e55e87 100644 --- a/src/plugins/silversearcher/silversearcherparser.cpp +++ b/src/plugins/silversearcher/silversearcherparser.cpp @@ -3,8 +3,6 @@ #include "silversearcherparser.h" -#include - using namespace Utils; namespace SilverSearcher { @@ -96,28 +94,28 @@ static bool parseLineHits(QStringView *remainingInput, QList> *h return true; } -void parse(QPromise &promise, const QString &input, - ParserState *parserState, const std::optional ®Exp) +SearchResultItems parse(const QFuture &future, const QString &input, + const std::optional ®Exp, FilePath *lastFilePath) { - QTC_ASSERT(parserState, return); + QTC_ASSERT(lastFilePath, return {}); SearchResultItems items; QStringView remainingInput(input); while (true) { - if (promise.isCanceled()) - return; + if (future.isCanceled()) + return {}; if (remainingInput.isEmpty()) break; const QStringView filePathLine = nextLine(&remainingInput); if (filePathLine.isEmpty()) { - parserState->m_lastFilePath = {}; // Clear the parser state + *lastFilePath = {}; // Clear the parser state continue; } if (filePathLine.startsWith(':')) - parserState->m_lastFilePath = FilePath::fromPathPart(filePathLine.mid(1)); + *lastFilePath = FilePath::fromPathPart(filePathLine.mid(1)); while (true) { QStringView hitLine = nextLine(&remainingInput); @@ -133,7 +131,7 @@ void parse(QPromise &promise, const QString &input, break; SearchResultItem item; - item.setFilePath(parserState->m_lastFilePath); + item.setFilePath(*lastFilePath); item.setDisplayText(hitLine.toString()); item.setUseTextEditorFont(true); for (const QPair &hit : hits) { @@ -145,20 +143,15 @@ void parse(QPromise &promise, const QString &input, } } } - if (!items.isEmpty()) - promise.addResult(items); - - parserState->m_reportedResultsCount += items.count(); + return items; } SearchResultItems parse(const QString &input, const std::optional ®Exp) { - QPromise promise; + QPromise promise; promise.start(); - ParserState dummy; - SilverSearcher::parse(promise, input, &dummy, regExp); - promise.finish(); - return promise.future().resultCount() ? promise.future().result() : SearchResultItems(); + FilePath dummy; + return SilverSearcher::parse(promise.future(), input, regExp, &dummy); } } // namespace SilverSearcher diff --git a/src/plugins/silversearcher/silversearcherparser.h b/src/plugins/silversearcher/silversearcherparser.h index 1cc5ccb773c..67b3e124f42 100644 --- a/src/plugins/silversearcher/silversearcherparser.h +++ b/src/plugins/silversearcher/silversearcherparser.h @@ -5,23 +5,16 @@ #include -#include +#include #include namespace Utils { class FilePath; } namespace SilverSearcher { -class ParserState -{ -public: - Utils::FilePath m_lastFilePath; - int m_reportedResultsCount = 0; -}; - -void parse(QPromise &promise, const QString &input, - ParserState *parserState = nullptr, - const std::optional ®Exp = {}); +Utils::SearchResultItems parse(const QFuture &future, const QString &input, + const std::optional ®Exp, + Utils::FilePath *lastFilePath); Utils::SearchResultItems parse(const QString &input, const std::optional ®Exp = {});