summaryrefslogtreecommitdiff
path: root/src/plugins/projectexplorer/abstractprocessstep.cpp
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2020-03-31 14:34:08 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2020-04-07 08:13:58 +0000
commitb15d1951a21e3d0f3c2f41a32f9e26b473f60ddf (patch)
tree65a49851baf637a30b3c683e8e7bfa6176567027 /src/plugins/projectexplorer/abstractprocessstep.cpp
parent45e7b78dc3a25c42f19d4275e7b678cfbd4c5771 (diff)
downloadqt-creator-b15d1951a21e3d0f3c2f41a32f9e26b473f60ddf.tar.gz
ProjectExplorer: Let IOutputParser handle newlines
This makes IOutputParser structurally more similar to Utils::OutputFormatter, which makes it simpler to explore possibilities of somehow uniting these two related classes. Task-number: QTCREATORBUG-22665 Change-Id: Ibb12ab6c8c785d863b9a921102a929864d0a5251 Reviewed-by: hjk <hjk@qt.io>
Diffstat (limited to 'src/plugins/projectexplorer/abstractprocessstep.cpp')
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.cpp78
1 files changed, 20 insertions, 58 deletions
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp
index c4d8ae8dc4..b8902ea98a 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.cpp
+++ b/src/plugins/projectexplorer/abstractprocessstep.cpp
@@ -45,6 +45,7 @@
#include <QDir>
#include <QHash>
#include <QPair>
+#include <QTextDecoder>
#include <QUrl>
#include <algorithm>
@@ -108,15 +109,11 @@ public:
std::unique_ptr<IOutputParser> m_outputParserChain;
ProcessParameters m_param;
Utils::FileInProjectFinder m_fileFinder;
- QByteArray deferredText;
bool m_ignoreReturnValue = false;
bool m_skipFlush = false;
bool m_lowPriority = false;
-
- void readData(void (AbstractProcessStep::*func)(const QString &), bool isUtf8 = false);
- void processLine(const QByteArray &data,
- void (AbstractProcessStep::*func)(const QString &),
- bool isUtf8 = false);
+ std::unique_ptr<QTextDecoder> stdoutStream;
+ std::unique_ptr<QTextDecoder> stderrStream;
};
AbstractProcessStep::AbstractProcessStep(BuildStepList *bsl, Core::Id id) :
@@ -224,6 +221,10 @@ void AbstractProcessStep::doRun()
return;
}
+ d->stdoutStream = std::make_unique<QTextDecoder>(buildEnvironment().hasKey("VSLANG")
+ ? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForLocale());
+ d->stderrStream = std::make_unique<QTextDecoder>(QTextCodec::codecForLocale());
+
d->m_process.reset(new Utils::QtcProcess());
d->m_process->setUseCtrlCStub(Utils::HostOsInfo::isWindowsHost());
d->m_process->setWorkingDirectory(wd.absolutePath());
@@ -347,40 +348,7 @@ void AbstractProcessStep::processReadyReadStdOutput()
{
if (!d->m_process)
return;
- d->m_process->setReadChannel(QProcess::StandardOutput);
- const bool utf8Output = buildEnvironment().hasKey("VSLANG");
- d->readData(&AbstractProcessStep::stdOutput, utf8Output);
-}
-
-void AbstractProcessStep::Private::readData(void (AbstractProcessStep::*func)(const QString &),
- bool isUtf8)
-{
- while (m_process->bytesAvailable()) {
- const bool hasLine = m_process->canReadLine();
- const QByteArray data = hasLine ? m_process->readLine() : m_process->readAll();
- int startPos = 0;
- int crPos = -1;
- while ((crPos = data.indexOf('\r', startPos)) >= 0) {
- if (data.size() > crPos + 1 && data.at(crPos + 1) == '\n')
- break;
- processLine(data.mid(startPos, crPos - startPos + 1), func, isUtf8);
- startPos = crPos + 1;
- }
- if (hasLine)
- processLine(data.mid(startPos), func, isUtf8);
- else if (startPos < data.count())
- deferredText += data.mid(startPos);
- }
-}
-
-void AbstractProcessStep::Private::processLine(const QByteArray &data,
- void (AbstractProcessStep::*func)(const QString &),
- bool isUtf8)
-{
- const QByteArray text = deferredText + data;
- deferredText.clear();
- const QString line = isUtf8 ? QString::fromUtf8(text) : QString::fromLocal8Bit(text);
- (q->*func)(line);
+ stdOutput(d->stdoutStream->toUnicode(d->m_process->readAllStandardOutput()));
}
/*!
@@ -389,19 +357,18 @@ void AbstractProcessStep::Private::processLine(const QByteArray &data,
The default implementation adds the line to the application output window.
*/
-void AbstractProcessStep::stdOutput(const QString &line)
+void AbstractProcessStep::stdOutput(const QString &output)
{
if (d->m_outputParserChain)
- d->m_outputParserChain->stdOutput(line);
- emit addOutput(line, BuildStep::OutputFormat::Stdout, BuildStep::DontAppendNewline);
+ d->m_outputParserChain->handleStdout(output);
+ emit addOutput(output, BuildStep::OutputFormat::Stdout, BuildStep::DontAppendNewline);
}
void AbstractProcessStep::processReadyReadStdError()
{
if (!d->m_process)
return;
- d->m_process->setReadChannel(QProcess::StandardError);
- d->readData(&AbstractProcessStep::stdError);
+ stdError(d->stderrStream->toUnicode(d->m_process->readAllStandardError()));
}
/*!
@@ -410,11 +377,11 @@ void AbstractProcessStep::processReadyReadStdError()
The default implementation adds the line to the application output window.
*/
-void AbstractProcessStep::stdError(const QString &line)
+void AbstractProcessStep::stdError(const QString &output)
{
if (d->m_outputParserChain)
- d->m_outputParserChain->stdError(line);
- emit addOutput(line, BuildStep::OutputFormat::Stderr, BuildStep::DontAppendNewline);
+ d->m_outputParserChain->handleStderr(output);
+ emit addOutput(output, BuildStep::OutputFormat::Stderr, BuildStep::DontAppendNewline);
}
void AbstractProcessStep::finish(bool success)
@@ -432,7 +399,7 @@ void AbstractProcessStep::taskAdded(const Task &task, int linkedOutputLines, int
// flush out any pending tasks before proceeding:
if (!d->m_skipFlush && d->m_outputParserChain) {
d->m_skipFlush = true;
- d->m_outputParserChain->flush();
+ d->m_outputParserChain->flushTasks();
d->m_skipFlush = false;
}
@@ -463,15 +430,10 @@ void AbstractProcessStep::slotProcessFinished(int, QProcess::ExitStatus)
QProcess *process = d->m_process.get();
if (!process) // Happens when the process was canceled and handed over to the Reaper.
process = qobject_cast<QProcess *>(sender()); // The process was canceled!
-
- const QString stdErrLine = process ? QString::fromLocal8Bit(process->readAllStandardError()) : QString();
- for (const QString &l : stdErrLine.split('\n'))
- stdError(l);
-
- const QString stdOutLine = process ? QString::fromLocal8Bit(process->readAllStandardOutput()) : QString();
- for (const QString &l : stdOutLine.split('\n'))
- stdOutput(l);
-
+ if (process) {
+ stdError(d->stderrStream->toUnicode(process->readAllStandardError()));
+ stdOutput(d->stdoutStream->toUnicode(process->readAllStandardOutput()));
+ }
cleanUp(process);
}