forked from qt-creator/qt-creator
ProjectExplorer: Dissolve the AnsiFilterParser class
This class was different from all the other output parsers in that its only responsibility was to pre-process the output before it was passed to the real parsers. We now make this explicit by introducing the concept of a filter function and turning the AnsiFilterParser class into one of those. This also gets rid of a case where the order of output parsers in the chain matters, which we want to move away from. Task-number: QTCREATORBUG-22665 Change-Id: Ica135e54ab43cf2ca8186073dc2487c906d4b38d Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@@ -25,7 +25,18 @@
|
||||
|
||||
#include "ansifilterparser.h"
|
||||
|
||||
namespace {
|
||||
#ifdef WITH_TESTS
|
||||
#include "projectexplorer.h"
|
||||
#include "outputparser_test.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <QTest>
|
||||
#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 <QTest>
|
||||
|
||||
# include "projectexplorer.h"
|
||||
# include "outputparser_test.h"
|
||||
# include "task.h"
|
||||
|
||||
void ProjectExplorerPlugin::testAnsiFilterOutputParser_data()
|
||||
{
|
||||
QTest::addColumn<QString>("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
|
||||
|
@@ -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
|
||||
|
@@ -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<IOutputParser::Filter> &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<IOutputParser::Filter> &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<Filter> 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
|
||||
|
@@ -30,6 +30,8 @@
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class Task;
|
||||
|
||||
@@ -51,6 +53,9 @@ public:
|
||||
|
||||
virtual bool hasFatalErrors() const;
|
||||
|
||||
using Filter = std::function<QString(const QString &)>;
|
||||
void addFilter(const Filter &filter);
|
||||
|
||||
void setWorkingDirectory(const Utils::FilePath &fn);
|
||||
|
||||
void flush(); // flush pending tasks & output
|
||||
|
Reference in New Issue
Block a user