From c23cdd926262a977a987cd887be8f4fd02386d92 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 5 May 2021 18:21:22 +0200 Subject: Utils: Merge {synchronous,qtc}process.{h,cpp} file pairs Mechanical to prepare merging the actual classes. Adapting #includes. Change-Id: I77a2c28129287778bc870c30cb890cd26bc2e62b Reviewed-by: Christian Stenger --- src/libs/extensionsystem/pluginmanager.cpp | 2 +- src/libs/utils/CMakeLists.txt | 1 - src/libs/utils/buildablehelperlibrary.cpp | 1 - src/libs/utils/pathchooser.cpp | 7 +- src/libs/utils/qtcprocess.cpp | 588 +++++++++++++++++++- src/libs/utils/qtcprocess.h | 113 ++++ src/libs/utils/shellcommand.h | 6 +- src/libs/utils/synchronousprocess.cpp | 591 --------------------- src/libs/utils/synchronousprocess.h | 144 ----- src/libs/utils/utils-lib.pri | 2 - src/libs/utils/utils.qbs | 2 - src/plugins/android/androidavdmanager.cpp | 5 +- src/plugins/android/androidbuildapkstep.cpp | 1 - src/plugins/android/androidconfigurations.cpp | 2 +- .../android/androidcreatekeystorecertificate.cpp | 2 +- src/plugins/android/androiddeployqtstep.cpp | 1 - src/plugins/android/androidmanager.cpp | 2 +- src/plugins/android/androidrunnerworker.cpp | 1 - src/plugins/android/androidsdkmanager.cpp | 1 - src/plugins/android/androidsettingswidget.cpp | 1 - src/plugins/baremetal/iarewtoolchain.cpp | 1 - src/plugins/baremetal/keiltoolchain.cpp | 1 - src/plugins/baremetal/sdcctoolchain.cpp | 2 +- .../artisticstyle/artisticstylesettings.cpp | 2 +- src/plugins/beautifier/beautifierplugin.cpp | 2 +- .../beautifier/uncrustify/uncrustifysettings.cpp | 2 +- src/plugins/clangtools/clangtidyclazyrunner.cpp | 2 +- src/plugins/clangtools/clangtoolrunner.cpp | 2 +- src/plugins/clangtools/clangtoolsutils.cpp | 3 +- src/plugins/clangtools/executableinfo.cpp | 2 +- src/plugins/clearcase/clearcaseplugin.cpp | 2 +- src/plugins/cmakeprojectmanager/cmaketool.h | 2 +- src/plugins/coreplugin/plugininstallwizard.cpp | 2 +- src/plugins/cvs/cvsplugin.cpp | 2 +- src/plugins/debugger/debuggeritem.cpp | 2 +- src/plugins/debugger/debuggeritemmanager.cpp | 2 +- src/plugins/debugger/gdb/gdbengine.cpp | 1 - src/plugins/git/gerrit/gerritserver.cpp | 3 +- src/plugins/git/gitclient.cpp | 1 - src/plugins/git/gitgrep.cpp | 2 +- src/plugins/ios/iosconfigurations.cpp | 11 +- src/plugins/ios/iosprobe.cpp | 2 +- src/plugins/ios/iostoolhandler.cpp | 8 +- src/plugins/ios/simulatorcontrol.cpp | 2 +- src/plugins/languageclient/client.cpp | 8 +- src/plugins/mercurial/mercurialclient.cpp | 3 +- src/plugins/perforce/perforceplugin.cpp | 4 +- .../customwizard/customwizardscriptgenerator.cpp | 2 +- src/plugins/projectexplorer/gcctoolchain.cpp | 2 - src/plugins/projectexplorer/msvctoolchain.cpp | 1 - src/plugins/python/pythonsettings.cpp | 4 +- src/plugins/python/pythonutils.cpp | 1 - src/plugins/subversion/subversionclient.cpp | 8 +- src/plugins/subversion/subversionplugin.cpp | 2 +- src/plugins/texteditor/formattexteditor.cpp | 4 +- src/plugins/texteditor/highlightersettings.cpp | 2 +- src/plugins/vcsbase/vcsbaseclient.cpp | 2 +- src/plugins/vcsbase/vcsbaseclient.h | 2 +- src/plugins/vcsbase/vcsbaseplugin.cpp | 2 +- tests/auto/debugger/tst_dumpers.cpp | 6 - tests/manual/process/mainwindow.cpp | 2 +- 61 files changed, 767 insertions(+), 822 deletions(-) delete mode 100644 src/libs/utils/synchronousprocess.cpp delete mode 100644 src/libs/utils/synchronousprocess.h diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index ab83ed210b..8de3319f85 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -55,8 +55,8 @@ #include #include #include +#include #include -#include #ifdef WITH_TESTS #include diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index de4d340ad6..c499eaab40 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -151,7 +151,6 @@ add_qtc_library(Utils stringutils.cpp stringutils.h styledbar.cpp styledbar.h stylehelper.cpp stylehelper.h - synchronousprocess.cpp synchronousprocess.h templateengine.cpp templateengine.h temporarydirectory.cpp temporarydirectory.h temporaryfile.cpp temporaryfile.h diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index 835c876bc5..dba4ade975 100644 --- a/src/libs/utils/buildablehelperlibrary.cpp +++ b/src/libs/utils/buildablehelperlibrary.cpp @@ -25,7 +25,6 @@ #include "buildablehelperlibrary.h" #include "hostosinfo.h" -#include "synchronousprocess.h" #include "qtcprocess.h" #include diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index 3ee14ab466..ec3fe910ae 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -26,11 +26,10 @@ #include "pathchooser.h" #include "environment.h" -#include "qtcassert.h" -#include "macroexpander.h" - -#include "synchronousprocess.h" #include "hostosinfo.h" +#include "macroexpander.h" +#include "qtcassert.h" +#include "qtcprocess.h" #include "theme/theme.h" #include diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 51fb60f4ae..e8af30c7a5 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -24,17 +24,22 @@ ****************************************************************************/ #include "qtcprocess.h" -#include "stringutils.h" -#include -#include +#include "stringutils.h" +#include "executeondestruction.h" +#include "hostosinfo.h" +#include "qtcassert.h" +#include "qtcprocess.h" #include -#include #include +#include +#include #include #include +#include #include +#include #ifdef QT_GUI_LIB // qmlpuppet does not use that. @@ -42,6 +47,10 @@ #include #endif +#include +#include +#include + #ifdef Q_OS_WIN #define CALLBACK WINAPI #include @@ -1845,4 +1854,575 @@ QString QtcProcess::locateBinary(const QString &binary) return locateBinary(QString::fromLocal8Bit(path), binary); } + +/*! + \class Utils::SynchronousProcess + + \brief The SynchronousProcess class runs a synchronous process in its own + event loop that blocks only user input events. Thus, it allows for the GUI to + repaint and append output to log windows. + + The stdOut(), stdErr() signals are emitted unbuffered as the process + writes them. + + The stdOutBuffered(), stdErrBuffered() signals are emitted with complete + lines based on the '\\n' marker if they are enabled using + stdOutBufferedSignalsEnabled()/setStdErrBufferedSignalsEnabled(). + They would typically be used for log windows. + + There is a timeout handling that takes effect after the last data have been + read from stdout/stdin (as opposed to waitForFinished(), which measures time + since it was invoked). It is thus also suitable for slow processes that + continuously output data (like version system operations). + + The property timeOutMessageBoxEnabled influences whether a message box is + shown asking the user if they want to kill the process on timeout (default: false). + + There are also static utility functions for dealing with fully synchronous + processes, like reading the output with correct timeout handling. + + Caution: This class should NOT be used if there is a chance that the process + triggers opening dialog boxes (for example, by file watchers triggering), + as this will cause event loop problems. +*/ + +enum { debug = 0 }; +enum { syncDebug = 0 }; + +enum { defaultMaxHangTimerCount = 10 }; + +static Q_LOGGING_CATEGORY(processLog, "qtc.utils.synchronousprocess", QtWarningMsg); + +// ----------- SynchronousProcessResponse +void SynchronousProcessResponse::clear() +{ + result = StartFailed; + exitCode = -1; + rawStdOut.clear(); + rawStdErr.clear(); +} + +QString SynchronousProcessResponse::exitMessage(const QString &binary, int timeoutS) const +{ + switch (result) { + case Finished: + return SynchronousProcess::tr("The command \"%1\" finished successfully.").arg(QDir::toNativeSeparators(binary)); + case FinishedError: + return SynchronousProcess::tr("The command \"%1\" terminated with exit code %2.").arg(QDir::toNativeSeparators(binary)).arg(exitCode); + case TerminatedAbnormally: + return SynchronousProcess::tr("The command \"%1\" terminated abnormally.").arg(QDir::toNativeSeparators(binary)); + case StartFailed: + return SynchronousProcess::tr("The command \"%1\" could not be started.").arg(QDir::toNativeSeparators(binary)); + case Hang: + return SynchronousProcess::tr("The command \"%1\" did not respond within the timeout limit (%2 s).") + .arg(QDir::toNativeSeparators(binary)).arg(timeoutS); + } + return QString(); +} + +QByteArray SynchronousProcessResponse::allRawOutput() const +{ + if (!rawStdOut.isEmpty() && !rawStdErr.isEmpty()) { + QByteArray result = rawStdOut; + if (!result.endsWith('\n')) + result += '\n'; + result += rawStdErr; + return result; + } + return !rawStdOut.isEmpty() ? rawStdOut : rawStdErr; +} + +QString SynchronousProcessResponse::allOutput() const +{ + const QString out = stdOut(); + const QString err = stdErr(); + + if (!out.isEmpty() && !err.isEmpty()) { + QString result = out; + if (!result.endsWith('\n')) + result += '\n'; + result += err; + return result; + } + return !out.isEmpty() ? out : err; +} + +QString SynchronousProcessResponse::stdOut() const +{ + return QtcProcess::normalizeNewlines(codec->toUnicode(rawStdOut)); +} + +QString SynchronousProcessResponse::stdErr() const +{ + return QtcProcess::normalizeNewlines(codec->toUnicode(rawStdErr)); +} + +QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse& r) +{ + QDebug nsp = str.nospace(); + nsp << "SynchronousProcessResponse: result=" << r.result << " ex=" << r.exitCode << '\n' + << r.rawStdOut.size() << " bytes stdout, stderr=" << r.rawStdErr << '\n'; + return str; +} + +SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code) +{ + return code ? SynchronousProcessResponse::FinishedError + : SynchronousProcessResponse::Finished; +} + +// Data for one channel buffer (stderr/stdout) +class ChannelBuffer : public QObject +{ + Q_OBJECT + +public: + void clearForRun(); + + QString linesRead(); + void append(const QByteArray &text, bool emitSignals); + + QByteArray rawData; + QString incompleteLineBuffer; // lines not yet signaled + QTextCodec *codec = nullptr; // Not owner + std::unique_ptr codecState; + int rawDataPos = 0; + bool bufferedSignalsEnabled = false; + bool firstBuffer = true; + +signals: + void outputBuffered(const QString &text, bool firstTime); +}; + +void ChannelBuffer::clearForRun() +{ + firstBuffer = true; + rawDataPos = 0; + rawData.clear(); + codecState.reset(new QTextCodec::ConverterState); + incompleteLineBuffer.clear(); +} + +/* Check for complete lines read from the device and return them, moving the + * buffer position. */ +QString ChannelBuffer::linesRead() +{ + // Convert and append the new input to the buffer of incomplete lines + const char *start = rawData.constData() + rawDataPos; + const int len = rawData.size() - rawDataPos; + incompleteLineBuffer.append(codec->toUnicode(start, len, codecState.get())); + rawDataPos = rawData.size(); + + // Any completed lines in the incompleteLineBuffer? + const int lastLineIndex = qMax(incompleteLineBuffer.lastIndexOf('\n'), + incompleteLineBuffer.lastIndexOf('\r')); + if (lastLineIndex == -1) + return QString(); + + // Get completed lines and remove them from the incompleteLinesBuffer: + const QString lines = QtcProcess::normalizeNewlines(incompleteLineBuffer.left(lastLineIndex + 1)); + incompleteLineBuffer = incompleteLineBuffer.mid(lastLineIndex + 1); + + return lines; +} + +void ChannelBuffer::append(const QByteArray &text, bool emitSignals) +{ + if (text.isEmpty()) + return; + rawData += text; + if (!emitSignals) + return; + + // Buffered. Emit complete lines? + if (bufferedSignalsEnabled) { + const QString lines = linesRead(); + if (!lines.isEmpty()) { + emit outputBuffered(lines, firstBuffer); + firstBuffer = false; + } + } +} + +// ----------- SynchronousProcessPrivate +class SynchronousProcessPrivate { +public: + void clearForRun(); + + QTextCodec *m_codec = QTextCodec::codecForLocale(); + QtcProcess m_process; + QTimer m_timer; + QEventLoop m_eventLoop; + SynchronousProcessResponse m_result; + FilePath m_binary; + ChannelBuffer m_stdOut; + ChannelBuffer m_stdErr; + ExitCodeInterpreter m_exitCodeInterpreter = defaultExitCodeInterpreter; + + int m_hangTimerCount = 0; + int m_maxHangTimerCount = defaultMaxHangTimerCount; + bool m_startFailure = false; + bool m_timeOutMessageBoxEnabled = false; + bool m_waitingForUser = false; +}; + +void SynchronousProcessPrivate::clearForRun() +{ + m_hangTimerCount = 0; + m_stdOut.clearForRun(); + m_stdOut.codec = m_codec; + m_stdErr.clearForRun(); + m_stdErr.codec = m_codec; + m_result.clear(); + m_result.codec = m_codec; + m_startFailure = false; + m_binary = {}; +} + +// ----------- SynchronousProcess +SynchronousProcess::SynchronousProcess() : + d(new SynchronousProcessPrivate) +{ + d->m_timer.setInterval(1000); + connect(&d->m_timer, &QTimer::timeout, this, &SynchronousProcess::slotTimeout); + connect(&d->m_process, QOverload::of(&QProcess::finished), + this, &SynchronousProcess::finished); + connect(&d->m_process, &QProcess::errorOccurred, this, &SynchronousProcess::error); + connect(&d->m_process, &QProcess::readyReadStandardOutput, + this, [this]() { + d->m_hangTimerCount = 0; + processStdOut(true); + }); + connect(&d->m_process, &QProcess::readyReadStandardError, + this, [this]() { + d->m_hangTimerCount = 0; + processStdErr(true); + }); + connect(&d->m_stdOut, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdOutBuffered); + connect(&d->m_stdErr, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdErrBuffered); +} + +SynchronousProcess::~SynchronousProcess() +{ + disconnect(&d->m_timer, nullptr, this, nullptr); + disconnect(&d->m_process, nullptr, this, nullptr); + delete d; +} + +void SynchronousProcess::setTimeoutS(int timeoutS) +{ + if (timeoutS > 0) + d->m_maxHangTimerCount = qMax(2, timeoutS); + else + d->m_maxHangTimerCount = INT_MAX / 1000; +} + +int SynchronousProcess::timeoutS() const +{ + return d->m_maxHangTimerCount == (INT_MAX / 1000) ? -1 : d->m_maxHangTimerCount; +} + +void SynchronousProcess::setCodec(QTextCodec *c) +{ + QTC_ASSERT(c, return); + d->m_codec = c; +} + +QTextCodec *SynchronousProcess::codec() const +{ + return d->m_codec; +} + +bool SynchronousProcess::stdOutBufferedSignalsEnabled() const +{ + return d->m_stdOut.bufferedSignalsEnabled; +} + +void SynchronousProcess::setStdOutBufferedSignalsEnabled(bool v) +{ + d->m_stdOut.bufferedSignalsEnabled = v; +} + +bool SynchronousProcess::stdErrBufferedSignalsEnabled() const +{ + return d->m_stdErr.bufferedSignalsEnabled; +} + +void SynchronousProcess::setStdErrBufferedSignalsEnabled(bool v) +{ + d->m_stdErr.bufferedSignalsEnabled = v; +} + +Environment SynchronousProcess::environment() const +{ + return d->m_process.environment(); +} + +bool SynchronousProcess::timeOutMessageBoxEnabled() const +{ + return d->m_timeOutMessageBoxEnabled; +} + +void SynchronousProcess::setTimeOutMessageBoxEnabled(bool v) +{ + d->m_timeOutMessageBoxEnabled = v; +} + +void SynchronousProcess::setEnvironment(const Environment &e) +{ + d->m_process.setEnvironment(Environment(e)); +} + +void SynchronousProcess::setDisableUnixTerminal() +{ + d->m_process.setDisableUnixTerminal(); +} + +void SynchronousProcess::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter) +{ + QTC_ASSERT(interpreter, return); + d->m_exitCodeInterpreter = interpreter; +} + +ExitCodeInterpreter SynchronousProcess::exitCodeInterpreter() const +{ + return d->m_exitCodeInterpreter; +} + +void SynchronousProcess::setWorkingDirectory(const QString &workingDirectory) +{ + d->m_process.setWorkingDirectory(workingDirectory); +} + +QString SynchronousProcess::workingDirectory() const +{ + return d->m_process.workingDirectory(); +} + +QProcess::ProcessChannelMode SynchronousProcess::processChannelMode () const +{ + return d->m_process.processChannelMode(); +} + +void SynchronousProcess::setProcessChannelMode(QProcess::ProcessChannelMode m) +{ + d->m_process.setProcessChannelMode(m); +} + +#ifdef QT_GUI_LIB +static bool isGuiThread() +{ + return QThread::currentThread() == QCoreApplication::instance()->thread(); +} +#endif + +SynchronousProcessResponse SynchronousProcess::run(const CommandLine &cmd, + const QByteArray &writeData) +{ + // FIXME: Implement properly + if (cmd.executable().needsDevice()) { + QtcProcess proc; + proc.setEnvironment(Environment(d->m_process.environment())); + proc.setWorkingDirectory(d->m_process.workingDirectory()); + proc.setCommand(cmd); + + // writeData ? + proc.start(); + + proc.waitForFinished(); + + SynchronousProcessResponse res; + res.result = SynchronousProcessResponse::Finished; + res.exitCode = proc.exitCode(); + res.rawStdOut = proc.readAllStandardOutput(); + res.rawStdErr = proc.readAllStandardError(); + return res; + }; + + qCDebug(processLog).noquote() << "Starting:" << cmd.toUserOutput(); + ExecuteOnDestruction logResult([this] { + qCDebug(processLog) << d->m_result; + }); + + d->clearForRun(); + + d->m_binary = cmd.executable(); + // using QProcess::start() and passing program, args and OpenMode results in a different + // quoting of arguments than using QProcess::setArguments() beforehand and calling start() + // only with the OpenMode + d->m_process.setCommand(cmd); + if (!writeData.isEmpty()) { + connect(&d->m_process, &QProcess::started, this, [this, writeData] { + d->m_process.write(writeData); + d->m_process.closeWriteChannel(); + }); + } + d->m_process.setOpenMode(writeData.isEmpty() ? QIODevice::ReadOnly : QIODevice::ReadWrite); + d->m_process.start(); + + // On Windows, start failure is triggered immediately if the + // executable cannot be found in the path. Do not start the + // event loop in that case. + if (!d->m_startFailure) { + d->m_timer.start(); +#ifdef QT_GUI_LIB + if (isGuiThread()) + QApplication::setOverrideCursor(Qt::WaitCursor); +#endif + d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents); + processStdOut(false); + processStdErr(false); + + d->m_result.rawStdOut = d->m_stdOut.rawData; + d->m_result.rawStdErr = d->m_stdErr.rawData; + + d->m_timer.stop(); +#ifdef QT_GUI_LIB + if (isGuiThread()) + QApplication::restoreOverrideCursor(); +#endif + } + + return d->m_result; +} + +SynchronousProcessResponse SynchronousProcess::runBlocking(const CommandLine &cmd) +{ + // FIXME: Implement properly + if (cmd.executable().needsDevice()) { + QtcProcess proc; + proc.setEnvironment(Environment(d->m_process.environment())); + proc.setWorkingDirectory(d->m_process.workingDirectory()); + proc.setCommand(cmd); + + // writeData ? + proc.start(); + + proc.waitForFinished(); + + SynchronousProcessResponse res; + res.result = SynchronousProcessResponse::Finished; + res.exitCode = proc.exitCode(); + res.rawStdOut = proc.readAllStandardOutput(); + res.rawStdErr = proc.readAllStandardError(); + return res; + }; + + qCDebug(processLog).noquote() << "Starting blocking:" << cmd.toUserOutput(); + ExecuteOnDestruction logResult([this] { + qCDebug(processLog) << d->m_result; + }); + + d->clearForRun(); + + d->m_binary = cmd.executable(); + d->m_process.setOpenMode(QIODevice::ReadOnly); + d->m_process.setCommand(cmd); + d->m_process.start(); + if (!d->m_process.waitForStarted(d->m_maxHangTimerCount * 1000)) { + d->m_result.result = SynchronousProcessResponse::StartFailed; + return d->m_result; + } + d->m_process.closeWriteChannel(); + if (!d->m_process.waitForFinished(d->m_maxHangTimerCount * 1000)) { + d->m_result.result = SynchronousProcessResponse::Hang; + d->m_process.terminate(); + if (!d->m_process.waitForFinished(1000)) { + d->m_process.kill(); + d->m_process.waitForFinished(1000); + } + } + + if (d->m_process.state() != QProcess::NotRunning) + return d->m_result; + + d->m_result.exitCode = d->m_process.exitCode(); + if (d->m_result.result == SynchronousProcessResponse::StartFailed) { + if (d->m_process.exitStatus() != QProcess::NormalExit) + d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally; + else + d->m_result.result = (exitCodeInterpreter())(d->m_result.exitCode); + } + processStdOut(false); + processStdErr(false); + + d->m_result.rawStdOut = d->m_stdOut.rawData; + d->m_result.rawStdErr = d->m_stdErr.rawData; + + return d->m_result; +} + +bool SynchronousProcess::terminate() +{ + return d->m_process.stopProcess(); +} + +void SynchronousProcess::slotTimeout() +{ + if (!d->m_waitingForUser && (++d->m_hangTimerCount > d->m_maxHangTimerCount)) { + if (debug) + qDebug() << Q_FUNC_INFO << "HANG detected, killing"; + d->m_waitingForUser = true; + const bool terminate = !d->m_timeOutMessageBoxEnabled || askToKill(d->m_binary.toString()); + d->m_waitingForUser = false; + if (terminate) { + d->m_process.stopProcess(); + d->m_result.result = SynchronousProcessResponse::Hang; + } else { + d->m_hangTimerCount = 0; + } + } else { + if (debug) + qDebug() << Q_FUNC_INFO << d->m_hangTimerCount; + } +} + +void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e) +{ + if (debug) + qDebug() << Q_FUNC_INFO << exitCode << e; + d->m_hangTimerCount = 0; + + switch (e) { + case QProcess::NormalExit: + d->m_result.result = d->m_exitCodeInterpreter(exitCode); + d->m_result.exitCode = exitCode; + break; + case QProcess::CrashExit: + // Was hang detected before and killed? + if (d->m_result.result != SynchronousProcessResponse::Hang) + d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally; + d->m_result.exitCode = -1; + break; + } + d->m_eventLoop.quit(); +} + +void SynchronousProcess::error(QProcess::ProcessError e) +{ + d->m_hangTimerCount = 0; + if (debug) + qDebug() << Q_FUNC_INFO << e; + // Was hang detected before and killed? + if (d->m_result.result != SynchronousProcessResponse::Hang) + d->m_result.result = SynchronousProcessResponse::StartFailed; + d->m_startFailure = true; + d->m_eventLoop.quit(); +} + +void SynchronousProcess::processStdOut(bool emitSignals) +{ + // Handle binary data + d->m_stdOut.append(d->m_process.readAllStandardOutput(), emitSignals); +} + +void SynchronousProcess::processStdErr(bool emitSignals) +{ + // Handle binary data + d->m_stdErr.append(d->m_process.readAllStandardError(), emitSignals); +} + } // namespace Utils + +#include "qtcprocess.moc" + diff --git a/src/libs/utils/qtcprocess.h b/src/libs/utils/qtcprocess.h index d46bd41797..f16dd1764e 100644 --- a/src/libs/utils/qtcprocess.h +++ b/src/libs/utils/qtcprocess.h @@ -25,14 +25,61 @@ #pragma once +#include "utils_global.h" + #include "environment.h" #include +#include + +#include + +QT_FORWARD_DECLARE_CLASS(QDebug) namespace Utils { + class AbstractMacroExpander; namespace Internal { class QtcProcessPrivate; } +class SynchronousProcessPrivate; +class CommandLine; +class Environment; + +/* Result of SynchronousProcess execution */ +class QTCREATOR_UTILS_EXPORT SynchronousProcessResponse +{ +public: + enum Result { + // Finished with return code 0 + Finished, + // Finished with return code != 0 + FinishedError, + // Process terminated abnormally (kill) + TerminatedAbnormally, + // Executable could not be started + StartFailed, + // Hang, no output after time out + Hang }; + + void clear(); + + // Helper to format an exit message. + QString exitMessage(const QString &binary, int timeoutS) const; + + QByteArray allRawOutput() const; + QString allOutput() const; + + QString stdOut() const; + QString stdErr() const; + + Result result = StartFailed; + int exitCode = -1; + + QByteArray rawStdOut; + QByteArray rawStdErr; + QTextCodec *codec = QTextCodec::codecForLocale(); +}; + class QTCREATOR_UTILS_EXPORT QtcProcess : public QProcess { @@ -178,4 +225,70 @@ private: QProcessEnvironment processEnvironment() const = delete; }; +QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse &); + +using ExitCodeInterpreter = std::function; +QTCREATOR_UTILS_EXPORT SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code); + +class QTCREATOR_UTILS_EXPORT SynchronousProcess : public QObject +{ + Q_OBJECT +public: + SynchronousProcess(); + ~SynchronousProcess() override; + + /* Timeout for hanging processes (triggers after no more output + * occurs on stderr/stdout). */ + void setTimeoutS(int timeoutS); + int timeoutS() const; + + void setCodec(QTextCodec *c); + QTextCodec *codec() const; + + QProcess::ProcessChannelMode processChannelMode () const; + void setProcessChannelMode(QProcess::ProcessChannelMode m); + + bool stdOutBufferedSignalsEnabled() const; + void setStdOutBufferedSignalsEnabled(bool); + + bool stdErrBufferedSignalsEnabled() const; + void setStdErrBufferedSignalsEnabled(bool); + + bool timeOutMessageBoxEnabled() const; + void setTimeOutMessageBoxEnabled(bool); + + Environment environment() const; + void setEnvironment(const Environment &); + + void setWorkingDirectory(const QString &workingDirectory); + QString workingDirectory() const; + + // Unix: Do not give the child process a terminal for input prompting. + void setDisableUnixTerminal(); + + void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter); + ExitCodeInterpreter exitCodeInterpreter() const; + + // Starts a nested event loop and runs the command + SynchronousProcessResponse run(const CommandLine &cmd, const QByteArray &writeData = {}); + // Starts the command blocking the UI fully + SynchronousProcessResponse runBlocking(const CommandLine &cmd); + +signals: + void stdOutBuffered(const QString &lines, bool firstTime); + void stdErrBuffered(const QString &lines, bool firstTime); + +public slots: + bool terminate(); + +private: + void slotTimeout(); + void finished(int exitCode, QProcess::ExitStatus e); + void error(QProcess::ProcessError); + void processStdOut(bool emitSignals); + void processStdErr(bool emitSignals); + + SynchronousProcessPrivate *d; +}; + } // namespace Utils diff --git a/src/libs/utils/shellcommand.h b/src/libs/utils/shellcommand.h index 042a80eff5..5cf5a0c9f8 100644 --- a/src/libs/utils/shellcommand.h +++ b/src/libs/utils/shellcommand.h @@ -27,16 +27,13 @@ #include "utils_global.h" -#include "synchronousprocess.h" - -#include +#include "qtcprocess.h" #include QT_BEGIN_NAMESPACE class QMutex; class QVariant; -class QProcessEnvironment; template class QFutureInterface; template @@ -45,7 +42,6 @@ QT_END_NAMESPACE namespace Utils { -class CommandLine; namespace Internal { class ShellCommandPrivate; } class QTCREATOR_UTILS_EXPORT ProgressParser diff --git a/src/libs/utils/synchronousprocess.cpp b/src/libs/utils/synchronousprocess.cpp deleted file mode 100644 index 39a4bb9baf..0000000000 --- a/src/libs/utils/synchronousprocess.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "synchronousprocess.h" -#include "executeondestruction.h" -#include "hostosinfo.h" -#include "qtcassert.h" -#include "qtcprocess.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -/*! - \class Utils::SynchronousProcess - - \brief The SynchronousProcess class runs a synchronous process in its own - event loop that blocks only user input events. Thus, it allows for the GUI to - repaint and append output to log windows. - - The stdOut(), stdErr() signals are emitted unbuffered as the process - writes them. - - The stdOutBuffered(), stdErrBuffered() signals are emitted with complete - lines based on the '\\n' marker if they are enabled using - stdOutBufferedSignalsEnabled()/setStdErrBufferedSignalsEnabled(). - They would typically be used for log windows. - - There is a timeout handling that takes effect after the last data have been - read from stdout/stdin (as opposed to waitForFinished(), which measures time - since it was invoked). It is thus also suitable for slow processes that continously - output data (like version system operations). - - The property timeOutMessageBoxEnabled influences whether a message box is - shown asking the user if they want to kill the process on timeout (default: false). - - There are also static utility functions for dealing with fully synchronous - processes, like reading the output with correct timeout handling. - - Caution: This class should NOT be used if there is a chance that the process - triggers opening dialog boxes (for example, by file watchers triggering), - as this will cause event loop problems. -*/ - -enum { debug = 0 }; -enum { syncDebug = 0 }; - -enum { defaultMaxHangTimerCount = 10 }; - -namespace Utils { - -static Q_LOGGING_CATEGORY(processLog, "qtc.utils.synchronousprocess", QtWarningMsg); - -// ----------- SynchronousProcessResponse -void SynchronousProcessResponse::clear() -{ - result = StartFailed; - exitCode = -1; - rawStdOut.clear(); - rawStdErr.clear(); -} - -QString SynchronousProcessResponse::exitMessage(const QString &binary, int timeoutS) const -{ - switch (result) { - case Finished: - return SynchronousProcess::tr("The command \"%1\" finished successfully.").arg(QDir::toNativeSeparators(binary)); - case FinishedError: - return SynchronousProcess::tr("The command \"%1\" terminated with exit code %2.").arg(QDir::toNativeSeparators(binary)).arg(exitCode); - case TerminatedAbnormally: - return SynchronousProcess::tr("The command \"%1\" terminated abnormally.").arg(QDir::toNativeSeparators(binary)); - case StartFailed: - return SynchronousProcess::tr("The command \"%1\" could not be started.").arg(QDir::toNativeSeparators(binary)); - case Hang: - return SynchronousProcess::tr("The command \"%1\" did not respond within the timeout limit (%2 s).") - .arg(QDir::toNativeSeparators(binary)).arg(timeoutS); - } - return QString(); -} - -QByteArray SynchronousProcessResponse::allRawOutput() const -{ - if (!rawStdOut.isEmpty() && !rawStdErr.isEmpty()) { - QByteArray result = rawStdOut; - if (!result.endsWith('\n')) - result += '\n'; - result += rawStdErr; - return result; - } - return !rawStdOut.isEmpty() ? rawStdOut : rawStdErr; -} - -QString SynchronousProcessResponse::allOutput() const -{ - const QString out = stdOut(); - const QString err = stdErr(); - - if (!out.isEmpty() && !err.isEmpty()) { - QString result = out; - if (!result.endsWith('\n')) - result += '\n'; - result += err; - return result; - } - return !out.isEmpty() ? out : err; -} - -QString SynchronousProcessResponse::stdOut() const -{ - return QtcProcess::normalizeNewlines(codec->toUnicode(rawStdOut)); -} - -QString SynchronousProcessResponse::stdErr() const -{ - return QtcProcess::normalizeNewlines(codec->toUnicode(rawStdErr)); -} - -QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse& r) -{ - QDebug nsp = str.nospace(); - nsp << "SynchronousProcessResponse: result=" << r.result << " ex=" << r.exitCode << '\n' - << r.rawStdOut.size() << " bytes stdout, stderr=" << r.rawStdErr << '\n'; - return str; -} - -SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code) -{ - return code ? SynchronousProcessResponse::FinishedError - : SynchronousProcessResponse::Finished; -} - -// Data for one channel buffer (stderr/stdout) -class ChannelBuffer : public QObject -{ - Q_OBJECT - -public: - void clearForRun(); - - QString linesRead(); - void append(const QByteArray &text, bool emitSignals); - - QByteArray rawData; - QString incompleteLineBuffer; // lines not yet signaled - QTextCodec *codec = nullptr; // Not owner - std::unique_ptr codecState; - int rawDataPos = 0; - bool bufferedSignalsEnabled = false; - bool firstBuffer = true; - -signals: - void outputBuffered(const QString &text, bool firstTime); -}; - -void ChannelBuffer::clearForRun() -{ - firstBuffer = true; - rawDataPos = 0; - rawData.clear(); - codecState.reset(new QTextCodec::ConverterState); - incompleteLineBuffer.clear(); -} - -/* Check for complete lines read from the device and return them, moving the - * buffer position. */ -QString ChannelBuffer::linesRead() -{ - // Convert and append the new input to the buffer of incomplete lines - const char *start = rawData.constData() + rawDataPos; - const int len = rawData.size() - rawDataPos; - incompleteLineBuffer.append(codec->toUnicode(start, len, codecState.get())); - rawDataPos = rawData.size(); - - // Any completed lines in the incompleteLineBuffer? - const int lastLineIndex = qMax(incompleteLineBuffer.lastIndexOf('\n'), - incompleteLineBuffer.lastIndexOf('\r')); - if (lastLineIndex == -1) - return QString(); - - // Get completed lines and remove them from the incompleteLinesBuffer: - const QString lines = QtcProcess::normalizeNewlines(incompleteLineBuffer.left(lastLineIndex + 1)); - incompleteLineBuffer = incompleteLineBuffer.mid(lastLineIndex + 1); - - return lines; -} - -void ChannelBuffer::append(const QByteArray &text, bool emitSignals) -{ - if (text.isEmpty()) - return; - rawData += text; - if (!emitSignals) - return; - - // Buffered. Emit complete lines? - if (bufferedSignalsEnabled) { - const QString lines = linesRead(); - if (!lines.isEmpty()) { - emit outputBuffered(lines, firstBuffer); - firstBuffer = false; - } - } -} - -// ----------- SynchronousProcessPrivate -class SynchronousProcessPrivate { -public: - void clearForRun(); - - QTextCodec *m_codec = QTextCodec::codecForLocale(); - QtcProcess m_process; - QTimer m_timer; - QEventLoop m_eventLoop; - SynchronousProcessResponse m_result; - FilePath m_binary; - ChannelBuffer m_stdOut; - ChannelBuffer m_stdErr; - ExitCodeInterpreter m_exitCodeInterpreter = defaultExitCodeInterpreter; - - int m_hangTimerCount = 0; - int m_maxHangTimerCount = defaultMaxHangTimerCount; - bool m_startFailure = false; - bool m_timeOutMessageBoxEnabled = false; - bool m_waitingForUser = false; -}; - -void SynchronousProcessPrivate::clearForRun() -{ - m_hangTimerCount = 0; - m_stdOut.clearForRun(); - m_stdOut.codec = m_codec; - m_stdErr.clearForRun(); - m_stdErr.codec = m_codec; - m_result.clear(); - m_result.codec = m_codec; - m_startFailure = false; - m_binary = {}; -} - -// ----------- SynchronousProcess -SynchronousProcess::SynchronousProcess() : - d(new SynchronousProcessPrivate) -{ - d->m_timer.setInterval(1000); - connect(&d->m_timer, &QTimer::timeout, this, &SynchronousProcess::slotTimeout); - connect(&d->m_process, QOverload::of(&QProcess::finished), - this, &SynchronousProcess::finished); - connect(&d->m_process, &QProcess::errorOccurred, this, &SynchronousProcess::error); - connect(&d->m_process, &QProcess::readyReadStandardOutput, - this, [this]() { - d->m_hangTimerCount = 0; - processStdOut(true); - }); - connect(&d->m_process, &QProcess::readyReadStandardError, - this, [this]() { - d->m_hangTimerCount = 0; - processStdErr(true); - }); - connect(&d->m_stdOut, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdOutBuffered); - connect(&d->m_stdErr, &ChannelBuffer::outputBuffered, this, &SynchronousProcess::stdErrBuffered); -} - -SynchronousProcess::~SynchronousProcess() -{ - disconnect(&d->m_timer, nullptr, this, nullptr); - disconnect(&d->m_process, nullptr, this, nullptr); - delete d; -} - -void SynchronousProcess::setTimeoutS(int timeoutS) -{ - if (timeoutS > 0) - d->m_maxHangTimerCount = qMax(2, timeoutS); - else - d->m_maxHangTimerCount = INT_MAX / 1000; -} - -int SynchronousProcess::timeoutS() const -{ - return d->m_maxHangTimerCount == (INT_MAX / 1000) ? -1 : d->m_maxHangTimerCount; -} - -void SynchronousProcess::setCodec(QTextCodec *c) -{ - QTC_ASSERT(c, return); - d->m_codec = c; -} - -QTextCodec *SynchronousProcess::codec() const -{ - return d->m_codec; -} - -bool SynchronousProcess::stdOutBufferedSignalsEnabled() const -{ - return d->m_stdOut.bufferedSignalsEnabled; -} - -void SynchronousProcess::setStdOutBufferedSignalsEnabled(bool v) -{ - d->m_stdOut.bufferedSignalsEnabled = v; -} - -bool SynchronousProcess::stdErrBufferedSignalsEnabled() const -{ - return d->m_stdErr.bufferedSignalsEnabled; -} - -void SynchronousProcess::setStdErrBufferedSignalsEnabled(bool v) -{ - d->m_stdErr.bufferedSignalsEnabled = v; -} - -Environment SynchronousProcess::environment() const -{ - return d->m_process.environment(); -} - -bool SynchronousProcess::timeOutMessageBoxEnabled() const -{ - return d->m_timeOutMessageBoxEnabled; -} - -void SynchronousProcess::setTimeOutMessageBoxEnabled(bool v) -{ - d->m_timeOutMessageBoxEnabled = v; -} - -void SynchronousProcess::setEnvironment(const Environment &e) -{ - d->m_process.setEnvironment(Environment(e)); -} - -void SynchronousProcess::setDisableUnixTerminal() -{ - d->m_process.setDisableUnixTerminal(); -} - -void SynchronousProcess::setExitCodeInterpreter(const ExitCodeInterpreter &interpreter) -{ - QTC_ASSERT(interpreter, return); - d->m_exitCodeInterpreter = interpreter; -} - -ExitCodeInterpreter SynchronousProcess::exitCodeInterpreter() const -{ - return d->m_exitCodeInterpreter; -} - -void SynchronousProcess::setWorkingDirectory(const QString &workingDirectory) -{ - d->m_process.setWorkingDirectory(workingDirectory); -} - -QString SynchronousProcess::workingDirectory() const -{ - return d->m_process.workingDirectory(); -} - -QProcess::ProcessChannelMode SynchronousProcess::processChannelMode () const -{ - return d->m_process.processChannelMode(); -} - -void SynchronousProcess::setProcessChannelMode(QProcess::ProcessChannelMode m) -{ - d->m_process.setProcessChannelMode(m); -} - -static bool isGuiThread() -{ - return QThread::currentThread() == QCoreApplication::instance()->thread(); -} - -SynchronousProcessResponse SynchronousProcess::run(const CommandLine &cmd, - const QByteArray &writeData) -{ - qCDebug(processLog).noquote() << "Starting:" << cmd.toUserOutput(); - ExecuteOnDestruction logResult([this] { - qCDebug(processLog) << d->m_result; - }); - - d->clearForRun(); - - d->m_binary = cmd.executable(); - // using QProcess::start() and passing program, args and OpenMode results in a different - // quoting of arguments than using QProcess::setArguments() beforehand and calling start() - // only with the OpenMode - d->m_process.setCommand(cmd); - if (!writeData.isEmpty()) { - connect(&d->m_process, &QProcess::started, this, [this, writeData] { - d->m_process.write(writeData); - d->m_process.closeWriteChannel(); - }); - } - d->m_process.setOpenMode(writeData.isEmpty() ? QIODevice::ReadOnly : QIODevice::ReadWrite); - d->m_process.start(); - - // On Windows, start failure is triggered immediately if the - // executable cannot be found in the path. Do not start the - // event loop in that case. - if (!d->m_startFailure) { - d->m_timer.start(); - if (isGuiThread()) - QApplication::setOverrideCursor(Qt::WaitCursor); - d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents); - processStdOut(false); - processStdErr(false); - - d->m_result.rawStdOut = d->m_stdOut.rawData; - d->m_result.rawStdErr = d->m_stdErr.rawData; - - d->m_timer.stop(); - if (isGuiThread()) - QApplication::restoreOverrideCursor(); - } - - return d->m_result; -} - -SynchronousProcessResponse SynchronousProcess::runBlocking(const CommandLine &cmd) -{ - qCDebug(processLog).noquote() << "Starting blocking:" << cmd.toUserOutput(); - ExecuteOnDestruction logResult([this] { - qCDebug(processLog) << d->m_result; - }); - - d->clearForRun(); - - d->m_binary = cmd.executable(); - d->m_process.setOpenMode(QIODevice::ReadOnly); - d->m_process.setCommand(cmd); - d->m_process.start(); - if (!d->m_process.waitForStarted(d->m_maxHangTimerCount * 1000)) { - d->m_result.result = SynchronousProcessResponse::StartFailed; - return d->m_result; - } - d->m_process.closeWriteChannel(); - if (!d->m_process.waitForFinished(d->m_maxHangTimerCount * 1000)) { - d->m_result.result = SynchronousProcessResponse::Hang; - d->m_process.terminate(); - if (!d->m_process.waitForFinished(1000)) { - d->m_process.kill(); - d->m_process.waitForFinished(1000); - } - } - - if (d->m_process.state() != QProcess::NotRunning) - return d->m_result; - - d->m_result.exitCode = d->m_process.exitCode(); - if (d->m_result.result == SynchronousProcessResponse::StartFailed) { - if (d->m_process.exitStatus() != QProcess::NormalExit) - d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally; - else - d->m_result.result = (exitCodeInterpreter())(d->m_result.exitCode); - } - processStdOut(false); - processStdErr(false); - - d->m_result.rawStdOut = d->m_stdOut.rawData; - d->m_result.rawStdErr = d->m_stdErr.rawData; - - return d->m_result; -} - -bool SynchronousProcess::terminate() -{ - return d->m_process.stopProcess(); -} - -static inline bool askToKill(const QString &binary = QString()) -{ - if (!isGuiThread()) - return true; - const QString title = SynchronousProcess::tr("Process not Responding"); - QString msg = binary.isEmpty() ? - SynchronousProcess::tr("The process is not responding.") : - SynchronousProcess::tr("The process \"%1\" is not responding.").arg(QDir::toNativeSeparators(binary)); - msg += QLatin1Char(' '); - msg += SynchronousProcess::tr("Would you like to terminate it?"); - // Restore the cursor that is set to wait while running. - const bool hasOverrideCursor = QApplication::overrideCursor() != nullptr; - if (hasOverrideCursor) - QApplication::restoreOverrideCursor(); - QMessageBox::StandardButton answer = QMessageBox::question(nullptr, title, msg, QMessageBox::Yes|QMessageBox::No); - if (hasOverrideCursor) - QApplication::setOverrideCursor(Qt::WaitCursor); - return answer == QMessageBox::Yes; -} - -void SynchronousProcess::slotTimeout() -{ - if (!d->m_waitingForUser && (++d->m_hangTimerCount > d->m_maxHangTimerCount)) { - if (debug) - qDebug() << Q_FUNC_INFO << "HANG detected, killing"; - d->m_waitingForUser = true; - const bool terminate = !d->m_timeOutMessageBoxEnabled || askToKill(d->m_binary.toString()); - d->m_waitingForUser = false; - if (terminate) { - d->m_process.stopProcess(); - d->m_result.result = SynchronousProcessResponse::Hang; - } else { - d->m_hangTimerCount = 0; - } - } else { - if (debug) - qDebug() << Q_FUNC_INFO << d->m_hangTimerCount; - } -} - -void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e) -{ - if (debug) - qDebug() << Q_FUNC_INFO << exitCode << e; - d->m_hangTimerCount = 0; - - switch (e) { - case QProcess::NormalExit: - d->m_result.result = d->m_exitCodeInterpreter(exitCode); - d->m_result.exitCode = exitCode; - break; - case QProcess::CrashExit: - // Was hang detected before and killed? - if (d->m_result.result != SynchronousProcessResponse::Hang) - d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally; - d->m_result.exitCode = -1; - break; - } - d->m_eventLoop.quit(); -} - -void SynchronousProcess::error(QProcess::ProcessError e) -{ - d->m_hangTimerCount = 0; - if (debug) - qDebug() << Q_FUNC_INFO << e; - // Was hang detected before and killed? - if (d->m_result.result != SynchronousProcessResponse::Hang) - d->m_result.result = SynchronousProcessResponse::StartFailed; - d->m_startFailure = true; - d->m_eventLoop.quit(); -} - -void SynchronousProcess::processStdOut(bool emitSignals) -{ - // Handle binary data - d->m_stdOut.append(d->m_process.readAllStandardOutput(), emitSignals); -} - -void SynchronousProcess::processStdErr(bool emitSignals) -{ - // Handle binary data - d->m_stdErr.append(d->m_process.readAllStandardError(), emitSignals); -} - -} // namespace Utils - -#include "synchronousprocess.moc" diff --git a/src/libs/utils/synchronousprocess.h b/src/libs/utils/synchronousprocess.h deleted file mode 100644 index 3117cc85e2..0000000000 --- a/src/libs/utils/synchronousprocess.h +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include "utils_global.h" - -#include -#include - -#include - -QT_FORWARD_DECLARE_CLASS(QDebug) - -namespace Utils { - -class SynchronousProcessPrivate; -class CommandLine; -class Environment; - -/* Result of SynchronousProcess execution */ -class QTCREATOR_UTILS_EXPORT SynchronousProcessResponse -{ -public: - enum Result { - // Finished with return code 0 - Finished, - // Finished with return code != 0 - FinishedError, - // Process terminated abnormally (kill) - TerminatedAbnormally, - // Executable could not be started - StartFailed, - // Hang, no output after time out - Hang }; - - void clear(); - - // Helper to format an exit message. - QString exitMessage(const QString &binary, int timeoutS) const; - - QByteArray allRawOutput() const; - QString allOutput() const; - - QString stdOut() const; - QString stdErr() const; - - Result result = StartFailed; - int exitCode = -1; - - QByteArray rawStdOut; - QByteArray rawStdErr; - QTextCodec *codec = QTextCodec::codecForLocale(); -}; - -QTCREATOR_UTILS_EXPORT QDebug operator<<(QDebug str, const SynchronousProcessResponse &); - -using ExitCodeInterpreter = std::function; -QTCREATOR_UTILS_EXPORT SynchronousProcessResponse::Result defaultExitCodeInterpreter(int code); - -class QTCREATOR_UTILS_EXPORT SynchronousProcess : public QObject -{ - Q_OBJECT -public: - SynchronousProcess(); - ~SynchronousProcess() override; - - /* Timeout for hanging processes (triggers after no more output - * occurs on stderr/stdout). */ - void setTimeoutS(int timeoutS); - int timeoutS() const; - - void setCodec(QTextCodec *c); - QTextCodec *codec() const; - - QProcess::ProcessChannelMode processChannelMode () const; - void setProcessChannelMode(QProcess::ProcessChannelMode m); - - bool stdOutBufferedSignalsEnabled() const; - void setStdOutBufferedSignalsEnabled(bool); - - bool stdErrBufferedSignalsEnabled() const; - void setStdErrBufferedSignalsEnabled(bool); - - bool timeOutMessageBoxEnabled() const; - void setTimeOutMessageBoxEnabled(bool); - - Environment environment() const; - void setEnvironment(const Environment &); - - void setWorkingDirectory(const QString &workingDirectory); - QString workingDirectory() const; - - // Unix: Do not give the child process a terminal for input prompting. - void setDisableUnixTerminal(); - - void setExitCodeInterpreter(const ExitCodeInterpreter &interpreter); - ExitCodeInterpreter exitCodeInterpreter() const; - - // Starts a nested event loop and runs the command - SynchronousProcessResponse run(const CommandLine &cmd, const QByteArray &writeData = {}); - // Starts the command blocking the UI fully - SynchronousProcessResponse runBlocking(const CommandLine &cmd); - -signals: - void stdOutBuffered(const QString &lines, bool firstTime); - void stdErrBuffered(const QString &lines, bool firstTime); - -public slots: - bool terminate(); - -private: - void slotTimeout(); - void finished(int exitCode, QProcess::ExitStatus e); - void error(QProcess::ProcessError); - void processStdOut(bool emitSignals); - void processStdErr(bool emitSignals); - - SynchronousProcessPrivate *d; -}; - -} // namespace Utils diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index fb829bde6c..2d8162746a 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -60,7 +60,6 @@ SOURCES += \ $$PWD/classnamevalidatinglineedit.cpp \ $$PWD/fancylineedit.cpp \ $$PWD/qtcolorbutton.cpp \ - $$PWD/synchronousprocess.cpp \ $$PWD/savefile.cpp \ $$PWD/fileutils.cpp \ $$PWD/textfileformat.cpp \ @@ -188,7 +187,6 @@ HEADERS += \ $$PWD/fancylineedit.h \ $$PWD/qtcolorbutton.h \ $$PWD/consoleprocess.h \ - $$PWD/synchronousprocess.h \ $$PWD/savefile.h \ $$PWD/fileutils.h \ $$PWD/textfileformat.h \ diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index faeda9174c..a7da48d811 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -263,8 +263,6 @@ Project { "styledbar.h", "stylehelper.cpp", "stylehelper.h", - "synchronousprocess.cpp", - "synchronousprocess.h", "templateengine.cpp", "templateengine.h", "temporarydirectory.cpp", diff --git a/src/plugins/android/androidavdmanager.cpp b/src/plugins/android/androidavdmanager.cpp index 086b1da11b..1d98ea6c03 100644 --- a/src/plugins/android/androidavdmanager.cpp +++ b/src/plugins/android/androidavdmanager.cpp @@ -22,16 +22,19 @@ ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ + #include "androidavdmanager.h" #include "avdmanageroutputparser.h" #include + #include + #include #include +#include #include -#include #include #include diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp index d2af119b18..c05af5eb3f 100644 --- a/src/plugins/android/androidbuildapkstep.cpp +++ b/src/plugins/android/androidbuildapkstep.cpp @@ -59,7 +59,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index 4e13e9cc72..3251a0834a 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -57,9 +57,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/android/androidcreatekeystorecertificate.cpp b/src/plugins/android/androidcreatekeystorecertificate.cpp index 2417abf5a5..38405468b1 100644 --- a/src/plugins/android/androidcreatekeystorecertificate.cpp +++ b/src/plugins/android/androidcreatekeystorecertificate.cpp @@ -27,7 +27,7 @@ #include "androidconfigurations.h" #include "ui_androidcreatekeystorecertificate.h" -#include +#include #include #include diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp index b8a822b30b..8b49d82ef3 100644 --- a/src/plugins/android/androiddeployqtstep.cpp +++ b/src/plugins/android/androiddeployqtstep.cpp @@ -55,7 +55,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index f77bfa6d1e..33bdf5e1ac 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -53,8 +53,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index d23f37b2f7..90aebfb7d1 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp index 7f105ecbe0..3afdc157dd 100644 --- a/src/plugins/android/androidsdkmanager.cpp +++ b/src/plugins/android/androidsdkmanager.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index 51b837af0f..6f22e28c43 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -45,7 +45,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/baremetal/iarewtoolchain.cpp b/src/plugins/baremetal/iarewtoolchain.cpp index 6338dee137..5ae78f83d7 100644 --- a/src/plugins/baremetal/iarewtoolchain.cpp +++ b/src/plugins/baremetal/iarewtoolchain.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/baremetal/keiltoolchain.cpp b/src/plugins/baremetal/keiltoolchain.cpp index 9432039f4d..77da384443 100644 --- a/src/plugins/baremetal/keiltoolchain.cpp +++ b/src/plugins/baremetal/keiltoolchain.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/baremetal/sdcctoolchain.cpp b/src/plugins/baremetal/sdcctoolchain.cpp index 5d53ba18b7..3c6a8b377c 100644 --- a/src/plugins/baremetal/sdcctoolchain.cpp +++ b/src/plugins/baremetal/sdcctoolchain.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp index bc4079d1e5..81b3b26c56 100644 --- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp +++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp index f67495396c..534de41ce0 100644 --- a/src/plugins/beautifier/beautifierplugin.cpp +++ b/src/plugins/beautifier/beautifierplugin.cpp @@ -53,8 +53,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp index db538328e6..542feff2a0 100644 --- a/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp +++ b/src/plugins/beautifier/uncrustify/uncrustifysettings.cpp @@ -31,7 +31,7 @@ #include -#include +#include #include #include diff --git a/src/plugins/clangtools/clangtidyclazyrunner.cpp b/src/plugins/clangtools/clangtidyclazyrunner.cpp index b8f55e8374..3d3e83115a 100644 --- a/src/plugins/clangtools/clangtidyclazyrunner.cpp +++ b/src/plugins/clangtools/clangtidyclazyrunner.cpp @@ -34,8 +34,8 @@ #include #include -#include #include +#include #include #include diff --git a/src/plugins/clangtools/clangtoolrunner.cpp b/src/plugins/clangtools/clangtoolrunner.cpp index 78eb5764ca..464fe6388b 100644 --- a/src/plugins/clangtools/clangtoolrunner.cpp +++ b/src/plugins/clangtools/clangtoolrunner.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/clangtools/clangtoolsutils.cpp b/src/plugins/clangtools/clangtoolsutils.cpp index 4a32165786..ed09f84127 100644 --- a/src/plugins/clangtools/clangtoolsutils.cpp +++ b/src/plugins/clangtools/clangtoolsutils.cpp @@ -35,11 +35,10 @@ #include #include -#include #include #include #include -#include +#include #include diff --git a/src/plugins/clangtools/executableinfo.cpp b/src/plugins/clangtools/executableinfo.cpp index 795c6f0e1d..e663c0edcb 100644 --- a/src/plugins/clangtools/executableinfo.cpp +++ b/src/plugins/clangtools/executableinfo.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index 8b0589b533..1f18766034 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -60,9 +60,9 @@ #include #include #include +#include #include #include -#include #include #include diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h index 12a71c546c..ada086d1da 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.h +++ b/src/plugins/cmakeprojectmanager/cmaketool.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include QT_FORWARD_DECLARE_CLASS(QProcess) diff --git a/src/plugins/coreplugin/plugininstallwizard.cpp b/src/plugins/coreplugin/plugininstallwizard.cpp index 91230b658e..60ae9b49b1 100644 --- a/src/plugins/coreplugin/plugininstallwizard.cpp +++ b/src/plugins/coreplugin/plugininstallwizard.cpp @@ -36,8 +36,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index 8e90d3de18..3e7c12f85b 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -42,9 +42,9 @@ #include -#include #include #include +#include #include #include diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp index c324fe0361..be54dd0aad 100644 --- a/src/plugins/debugger/debuggeritem.cpp +++ b/src/plugins/debugger/debuggeritem.cpp @@ -35,8 +35,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/debugger/debuggeritemmanager.cpp b/src/plugins/debugger/debuggeritemmanager.cpp index 350393affe..c69f792564 100644 --- a/src/plugins/debugger/debuggeritemmanager.cpp +++ b/src/plugins/debugger/debuggeritemmanager.cpp @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index d365d2685a..01a17f383b 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -64,7 +64,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/git/gerrit/gerritserver.cpp b/src/plugins/git/gerrit/gerritserver.cpp index a0a6a65046..eca26f7bd8 100644 --- a/src/plugins/git/gerrit/gerritserver.cpp +++ b/src/plugins/git/gerrit/gerritserver.cpp @@ -31,8 +31,9 @@ #include #include + #include -#include +#include #include #include diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 4e75d7f6db..4e83d0b442 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -50,7 +50,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index 79c035cd72..4cc0d37110 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -39,8 +39,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp index 2997b37120..ef6652fb9e 100644 --- a/src/plugins/ios/iosconfigurations.cpp +++ b/src/plugins/ios/iosconfigurations.cpp @@ -31,10 +31,7 @@ #include "iosprobe.h" #include -#include -#include -#include -#include + #include #include #include @@ -42,14 +39,20 @@ #include #include #include + #include #include #include + #include #include #include #include +#include +#include +#include + #include #include #include diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp index 66518ad778..12d5daae0d 100644 --- a/src/plugins/ios/iosprobe.cpp +++ b/src/plugins/ios/iosprobe.cpp @@ -26,7 +26,7 @@ #include "iosprobe.h" #include -#include +#include #include #include diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index a63fdb9dfa..0d84f28c47 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -29,12 +29,14 @@ #include "iossimulator.h" #include "simulatorcontrol.h" -#include "debugger/debuggerconstants.h" #include -#include + +#include + #include +#include +#include #include -#include #include #include diff --git a/src/plugins/ios/simulatorcontrol.cpp b/src/plugins/ios/simulatorcontrol.cpp index 19dbe3c1bb..b2464a3307 100644 --- a/src/plugins/ios/simulatorcontrol.cpp +++ b/src/plugins/ios/simulatorcontrol.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #ifdef Q_OS_MAC #include diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index dc49f17a47..404cef6d45 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -34,6 +34,8 @@ #include #include #include +#include + #include #include #include @@ -41,8 +43,10 @@ #include #include #include + #include #include + #include #include #include @@ -52,10 +56,10 @@ #include #include #include + #include #include -#include -#include + #include #include diff --git a/src/plugins/mercurial/mercurialclient.cpp b/src/plugins/mercurial/mercurialclient.cpp index 60238fd65f..92708ac56d 100644 --- a/src/plugins/mercurial/mercurialclient.cpp +++ b/src/plugins/mercurial/mercurialclient.cpp @@ -35,10 +35,11 @@ #include #include #include -#include + #include #include #include +#include #include #include diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index aa797b865d..bc293bbb09 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -41,11 +41,13 @@ #include #include #include + #include + #include #include #include -#include +#include #include #include diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp index 1f8a7c0130..3a1595c089 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 89dc87e65c..65b01ee898 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -37,11 +37,9 @@ #include #include #include -#include #include #include #include -#include #include #include diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 4e91b8b599..8ca498f73c 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/src/plugins/python/pythonsettings.cpp b/src/plugins/python/pythonsettings.cpp index 5b1b8e119a..ffe8b83e02 100644 --- a/src/plugins/python/pythonsettings.cpp +++ b/src/plugins/python/pythonsettings.cpp @@ -28,7 +28,7 @@ #include "pythonconstants.h" #include -#include "coreplugin/icore.h" +#include #include #include @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/plugins/python/pythonutils.cpp b/src/plugins/python/pythonutils.cpp index 5f89ec14cf..7854935ff8 100644 --- a/src/plugins/python/pythonutils.cpp +++ b/src/plugins/python/pythonutils.cpp @@ -48,7 +48,6 @@ #include #include #include -#include #include #include diff --git a/src/plugins/subversion/subversionclient.cpp b/src/plugins/subversion/subversionclient.cpp index 2f1d930184..2a21a2d51b 100644 --- a/src/plugins/subversion/subversionclient.cpp +++ b/src/plugins/subversion/subversionclient.cpp @@ -28,20 +28,22 @@ #include "subversionplugin.h" #include "subversionsettings.h" +#include + #include #include #include #include #include #include -#include -#include + #include #include -#include #include #include +#include +#include #include #include diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index 6e71ab3d6d..fa16f7180b 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -57,8 +57,8 @@ #include #include #include +#include #include -#include #include #include diff --git a/src/plugins/texteditor/formattexteditor.cpp b/src/plugins/texteditor/formattexteditor.cpp index 54655de390..2b41d3ef0a 100644 --- a/src/plugins/texteditor/formattexteditor.cpp +++ b/src/plugins/texteditor/formattexteditor.cpp @@ -32,11 +32,11 @@ #include #include +#include +#include #include -#include #include #include -#include #include #include diff --git a/src/plugins/texteditor/highlightersettings.cpp b/src/plugins/texteditor/highlightersettings.cpp index 97d31ba999..765b30e958 100644 --- a/src/plugins/texteditor/highlightersettings.cpp +++ b/src/plugins/texteditor/highlightersettings.cpp @@ -31,8 +31,8 @@ #include #include +#include #include -#include #include #include diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index 9efee40788..c5ee483cee 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -36,7 +36,7 @@ #include #include -#include + #include #include #include diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h index 708eb174ff..dc532a31ec 100644 --- a/src/plugins/vcsbase/vcsbaseclient.h +++ b/src/plugins/vcsbase/vcsbaseclient.h @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include diff --git a/src/plugins/vcsbase/vcsbaseplugin.cpp b/src/plugins/vcsbase/vcsbaseplugin.cpp index 421c6ea819..031115a245 100644 --- a/src/plugins/vcsbase/vcsbaseplugin.cpp +++ b/src/plugins/vcsbase/vcsbaseplugin.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 01b4df2f1c..bbed7be63b 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -32,12 +32,6 @@ #include #include -#ifdef Q_OS_WIN -#ifdef Q_CC_MSVC -#include -#endif // Q_CC_MSVC -#endif // Q_OS_WIN - #include #include diff --git a/tests/manual/process/mainwindow.cpp b/tests/manual/process/mainwindow.cpp index 85a7b2ef9f..addd95e5a7 100644 --- a/tests/manual/process/mainwindow.cpp +++ b/tests/manual/process/mainwindow.cpp @@ -26,7 +26,7 @@ #include "mainwindow.h" #include -#include +#include #include #include -- cgit v1.2.3