diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp index b8902ea98ad..fce8f478185 100644 --- a/src/plugins/projectexplorer/abstractprocessstep.cpp +++ b/src/plugins/projectexplorer/abstractprocessstep.cpp @@ -136,10 +136,10 @@ AbstractProcessStep::~AbstractProcessStep() void AbstractProcessStep::setOutputParser(IOutputParser *parser) { - d->m_outputParserChain.reset(new AnsiFilterParser); - d->m_outputParserChain->appendOutputParser(parser); - - connect(d->m_outputParserChain.get(), &IOutputParser::addTask, this, &AbstractProcessStep::taskAdded); + parser->addFilter(&Internal::filterAnsiEscapeCodes); + d->m_outputParserChain.reset(parser); + connect(d->m_outputParserChain.get(), &IOutputParser::addTask, + this, &AbstractProcessStep::taskAdded); } /*! diff --git a/src/plugins/projectexplorer/ansifilterparser.cpp b/src/plugins/projectexplorer/ansifilterparser.cpp index a2db2c1a6f9..a4540845ce8 100644 --- a/src/plugins/projectexplorer/ansifilterparser.cpp +++ b/src/plugins/projectexplorer/ansifilterparser.cpp @@ -25,7 +25,18 @@ #include "ansifilterparser.h" -namespace { +#ifdef WITH_TESTS +#include "projectexplorer.h" +#include "outputparser_test.h" +#include "task.h" + +#include +#endif // WITH_TESTS + + +namespace ProjectExplorer { +namespace Internal { + enum AnsiState { PLAIN, ANSI_START, @@ -34,26 +45,8 @@ enum AnsiState { ANSI_WAITING_FOR_ST, ANSI_ST_STARTED }; -} // namespace -using namespace ProjectExplorer; - -AnsiFilterParser::AnsiFilterParser() -{ - setObjectName(QLatin1String("AnsiFilterParser")); -} - -void AnsiFilterParser::stdOutput(const QString &line) -{ - IOutputParser::stdOutput(filterLine(line)); -} - -void AnsiFilterParser::stdError(const QString &line) -{ - IOutputParser::stdError(filterLine(line)); -} - -QString AnsiFilterParser::filterLine(const QString &line) +QString filterAnsiEscapeCodes(const QString &line) { QString result; result.reserve(line.count()); @@ -104,15 +97,9 @@ QString AnsiFilterParser::filterLine(const QString &line) } return result; } +} // namespace Internal -// Unit tests: #ifdef WITH_TESTS -# include - -# include "projectexplorer.h" -# include "outputparser_test.h" -# include "task.h" - void ProjectExplorerPlugin::testAnsiFilterOutputParser_data() { QTest::addColumn("input"); @@ -161,7 +148,7 @@ void ProjectExplorerPlugin::testAnsiFilterOutputParser_data() void ProjectExplorerPlugin::testAnsiFilterOutputParser() { OutputParserTester testbench; - testbench.appendOutputParser(new AnsiFilterParser); + testbench.addFilter(&Internal::filterAnsiEscapeCodes); QFETCH(QString, input); QFETCH(OutputParserTester::Channel, inputChannel); QFETCH(QString, childStdOutLines); @@ -173,3 +160,5 @@ void ProjectExplorerPlugin::testAnsiFilterOutputParser() } #endif + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/ansifilterparser.h b/src/plugins/projectexplorer/ansifilterparser.h index 6e19915a580..b3ec351c357 100644 --- a/src/plugins/projectexplorer/ansifilterparser.h +++ b/src/plugins/projectexplorer/ansifilterparser.h @@ -30,18 +30,9 @@ #include "projectexplorer_export.h" namespace ProjectExplorer { +namespace Internal { -class PROJECTEXPLORER_EXPORT AnsiFilterParser : public IOutputParser -{ - Q_OBJECT - -public: - AnsiFilterParser(); - void stdOutput(const QString &line) override; - void stdError(const QString &line) override; - -private: - QString filterLine(const QString &line); -}; +QString filterAnsiEscapeCodes(const QString &line); +} // namespace Internal } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/ioutputparser.cpp b/src/plugins/projectexplorer/ioutputparser.cpp index 5a77a7384b5..3190c52f1a6 100644 --- a/src/plugins/projectexplorer/ioutputparser.cpp +++ b/src/plugins/projectexplorer/ioutputparser.cpp @@ -111,8 +111,9 @@ class OutputChannelState public: using LineHandler = void (IOutputParser::*)(const QString &line); - OutputChannelState(IOutputParser *parser, LineHandler lineHandler) - : parser(parser), lineHandler(lineHandler) {} + OutputChannelState(IOutputParser *parser, LineHandler lineHandler, + QList &filters) + : parser(parser), lineHandler(lineHandler), filters(filters) {} void handleData(const QString &newData) { @@ -124,20 +125,30 @@ public: break; const QString line = pendingData.left(eolPos + 1); pendingData.remove(0, eolPos + 1); - (parser->*lineHandler)(line); + (parser->*lineHandler)(filteredLine(line)); } } void flush() { if (!pendingData.isEmpty()) { - (parser->*lineHandler)(pendingData); + (parser->*lineHandler)(filteredLine(pendingData)); pendingData.clear(); } } + QString filteredLine(const QString &line) + { + QString l = line; + for (const IOutputParser::Filter &f : filters) + l = f(l); + return l; + } + + IOutputParser * const parser; - LineHandler lineHandler; + const LineHandler lineHandler; + QList &filters; QString pendingData; }; @@ -145,11 +156,12 @@ class IOutputParser::IOutputParserPrivate { public: IOutputParserPrivate(IOutputParser *parser) - : stdoutState(parser, &IOutputParser::stdOutput), - stderrState(parser, &IOutputParser::stdError) + : stdoutState(parser, &IOutputParser::stdOutput, filters), + stderrState(parser, &IOutputParser::stdError, filters) {} IOutputParser *childParser = nullptr; + QList filters; Utils::FilePath workingDir; OutputChannelState stdoutState; OutputChannelState stderrState; @@ -261,4 +273,9 @@ QString IOutputParser::rightTrimmed(const QString &in) return in.mid(0, pos); } +void IOutputParser::addFilter(const Filter &filter) +{ + d->filters << filter; +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/ioutputparser.h b/src/plugins/projectexplorer/ioutputparser.h index cbebbf49d58..e288873fd35 100644 --- a/src/plugins/projectexplorer/ioutputparser.h +++ b/src/plugins/projectexplorer/ioutputparser.h @@ -30,6 +30,8 @@ #include +#include + namespace ProjectExplorer { class Task; @@ -51,6 +53,9 @@ public: virtual bool hasFatalErrors() const; + using Filter = std::function; + void addFilter(const Filter &filter); + void setWorkingDirectory(const Utils::FilePath &fn); void flush(); // flush pending tasks & output