aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/android/androidbuildapkstep.cpp35
-rw-r--r--src/plugins/android/androidbuildapkstep.h1
-rw-r--r--src/plugins/android/androidpackageinstallationstep.cpp13
-rw-r--r--src/plugins/android/javaparser.cpp9
-rw-r--r--src/plugins/android/javaparser.h2
-rw-r--r--src/plugins/baremetal/iarewparser.cpp18
-rw-r--r--src/plugins/baremetal/iarewparser.h4
-rw-r--r--src/plugins/baremetal/iarewtoolchain.cpp2
-rw-r--r--src/plugins/baremetal/iarewtoolchain.h2
-rw-r--r--src/plugins/baremetal/keilparser.cpp46
-rw-r--r--src/plugins/baremetal/keilparser.h8
-rw-r--r--src/plugins/baremetal/keiltoolchain.cpp2
-rw-r--r--src/plugins/baremetal/keiltoolchain.h2
-rw-r--r--src/plugins/baremetal/sdccparser.cpp14
-rw-r--r--src/plugins/baremetal/sdccparser.h2
-rw-r--r--src/plugins/baremetal/sdcctoolchain.cpp2
-rw-r--r--src/plugins/baremetal/sdcctoolchain.h2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.cpp17
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildstep.h1
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeparser.cpp26
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeparser.h2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprocess.cpp13
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprocess.h5
-rw-r--r--src/plugins/cmakeprojectmanager/servermodereader.cpp10
-rw-r--r--src/plugins/cmakeprojectmanager/servermodereader.h3
-rw-r--r--src/plugins/coreplugin/outputwindow.cpp23
-rw-r--r--src/plugins/ios/iosbuildstep.cpp13
-rw-r--r--src/plugins/ios/iosdsymbuildstep.cpp10
-rw-r--r--src/plugins/ios/iosdsymbuildstep.h1
-rw-r--r--src/plugins/nim/project/nimblebuildstep.cpp23
-rw-r--r--src/plugins/nim/project/nimblebuildstep.h2
-rw-r--r--src/plugins/nim/project/nimcompilerbuildstep.cpp21
-rw-r--r--src/plugins/nim/project/nimcompilerbuildstep.h2
-rw-r--r--src/plugins/nim/project/nimtoolchain.cpp2
-rw-r--r--src/plugins/nim/project/nimtoolchain.h2
-rw-r--r--src/plugins/projectexplorer/CMakeLists.txt1
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.cpp65
-rw-r--r--src/plugins/projectexplorer/abstractprocessstep.h8
-rw-r--r--src/plugins/projectexplorer/ansifilterparser.cpp164
-rw-r--r--src/plugins/projectexplorer/ansifilterparser.h38
-rw-r--r--src/plugins/projectexplorer/buildmanager.cpp4
-rw-r--r--src/plugins/projectexplorer/buildstep.cpp10
-rw-r--r--src/plugins/projectexplorer/buildstep.h7
-rw-r--r--src/plugins/projectexplorer/clangparser.cpp26
-rw-r--r--src/plugins/projectexplorer/clangparser.h4
-rw-r--r--src/plugins/projectexplorer/compileoutputwindow.cpp103
-rw-r--r--src/plugins/projectexplorer/compileoutputwindow.h9
-rw-r--r--src/plugins/projectexplorer/customparser.cpp40
-rw-r--r--src/plugins/projectexplorer/customparser.h8
-rw-r--r--src/plugins/projectexplorer/customtoolchain.cpp2
-rw-r--r--src/plugins/projectexplorer/customtoolchain.h2
-rw-r--r--src/plugins/projectexplorer/gccparser.cpp33
-rw-r--r--src/plugins/projectexplorer/gccparser.h4
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.cpp6
-rw-r--r--src/plugins/projectexplorer/gcctoolchain.h6
-rw-r--r--src/plugins/projectexplorer/gnumakeparser.cpp18
-rw-r--r--src/plugins/projectexplorer/gnumakeparser.h2
-rw-r--r--src/plugins/projectexplorer/ioutputparser.cpp302
-rw-r--r--src/plugins/projectexplorer/ioutputparser.h93
-rw-r--r--src/plugins/projectexplorer/kit.cpp4
-rw-r--r--src/plugins/projectexplorer/kit.h4
-rw-r--r--src/plugins/projectexplorer/kitinformation.cpp2
-rw-r--r--src/plugins/projectexplorer/kitinformation.h2
-rw-r--r--src/plugins/projectexplorer/kitmanager.cpp2
-rw-r--r--src/plugins/projectexplorer/kitmanager.h4
-rw-r--r--src/plugins/projectexplorer/ldparser.cpp33
-rw-r--r--src/plugins/projectexplorer/ldparser.h2
-rw-r--r--src/plugins/projectexplorer/linuxiccparser.cpp19
-rw-r--r--src/plugins/projectexplorer/linuxiccparser.h4
-rw-r--r--src/plugins/projectexplorer/lldparser.cpp16
-rw-r--r--src/plugins/projectexplorer/lldparser.h2
-rw-r--r--src/plugins/projectexplorer/makestep.cpp12
-rw-r--r--src/plugins/projectexplorer/makestep.h1
-rw-r--r--src/plugins/projectexplorer/msvcparser.cpp43
-rw-r--r--src/plugins/projectexplorer/msvcparser.h6
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.cpp4
-rw-r--r--src/plugins/projectexplorer/msvctoolchain.h4
-rw-r--r--src/plugins/projectexplorer/osparser.cpp8
-rw-r--r--src/plugins/projectexplorer/osparser.h2
-rw-r--r--src/plugins/projectexplorer/outputparser_test.cpp73
-rw-r--r--src/plugins/projectexplorer/outputparser_test.h5
-rw-r--r--src/plugins/projectexplorer/parseissuesdialog.cpp12
-rw-r--r--src/plugins/projectexplorer/processstep.cpp9
-rw-r--r--src/plugins/projectexplorer/projectexplorer.pro2
-rw-r--r--src/plugins/projectexplorer/projectexplorer.qbs1
-rw-r--r--src/plugins/projectexplorer/toolchain.h5
-rw-r--r--src/plugins/projectexplorer/toolchainsettingsaccessor.cpp2
-rw-r--r--src/plugins/projectexplorer/xcodebuildparser.cpp14
-rw-r--r--src/plugins/projectexplorer/xcodebuildparser.h2
-rw-r--r--src/plugins/python/pythonrunconfiguration.cpp6
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildstep.cpp33
-rw-r--r--src/plugins/qbsprojectmanager/qbsbuildstep.h3
-rw-r--r--src/plugins/qbsprojectmanager/qbscleanstep.cpp2
-rw-r--r--src/plugins/qbsprojectmanager/qbsinstallstep.cpp3
-rw-r--r--src/plugins/qmakeprojectmanager/qmakemakestep.cpp43
-rw-r--r--src/plugins/qmakeprojectmanager/qmakemakestep.h1
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeparser.cpp25
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeparser.h2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakestep.cpp13
-rw-r--r--src/plugins/qmakeprojectmanager/qmakestep.h2
-rw-r--r--src/plugins/qtsupport/qtkitinformation.cpp2
-rw-r--r--src/plugins/qtsupport/qtkitinformation.h2
-rw-r--r--src/plugins/qtsupport/qtoutputformatter.cpp8
-rw-r--r--src/plugins/qtsupport/qtparser.cpp53
-rw-r--r--src/plugins/qtsupport/qtparser.h4
-rw-r--r--src/plugins/qtsupport/qttestparser.cpp9
-rw-r--r--src/plugins/qtsupport/qttestparser.h2
-rw-r--r--src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp4
-rw-r--r--src/plugins/vcsbase/vcsoutputformatter.h2
-rw-r--r--src/plugins/winrt/winrtpackagedeploymentstep.cpp4
110 files changed, 690 insertions, 1127 deletions
diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp
index 3112d22ae59..7bb6bbc4647 100644
--- a/src/plugins/android/androidbuildapkstep.cpp
+++ b/src/plugins/android/androidbuildapkstep.cpp
@@ -178,22 +178,6 @@ bool AndroidBuildApkStep::init()
return false;
}
- auto parser = new JavaParser;
- parser->setProjectFileList(Utils::transform(target()->project()->files(ProjectExplorer::Project::AllFiles),
- &Utils::FilePath::toString));
-
- const QString buildKey = target()->activeBuildKey();
- const ProjectNode *node = target()->project()->findNodeForBuildKey(buildKey);
-
- QString sourceDirName;
- if (node)
- sourceDirName = node->data(Constants::AndroidPackageSourceDir).toString();
-
- QFileInfo sourceDirInfo(sourceDirName);
- parser->setSourceDirectory(Utils::FilePath::fromString(sourceDirInfo.canonicalFilePath()));
- parser->setBuildDirectory(buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY));
- setOutputParser(parser);
-
m_openPackageLocationForRun = m_openPackageLocation;
if (m_buildAAB) {
@@ -218,6 +202,8 @@ bool AndroidBuildApkStep::init()
QString outputDir = buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY).toString();
+ const QString buildKey = target()->activeBuildKey();
+ const ProjectNode *node = project()->findNodeForBuildKey(buildKey);
if (node)
m_inputFile = node->data(Constants::AndroidDeploySettingsFile).toString();
@@ -285,6 +271,23 @@ bool AndroidBuildApkStep::init()
return true;
}
+void AndroidBuildApkStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ const auto parser = new JavaParser;
+ parser->setProjectFileList(Utils::transform(project()->files(ProjectExplorer::Project::AllFiles),
+ &Utils::FilePath::toString));
+ const QString buildKey = target()->activeBuildKey();
+ const ProjectNode *node = project()->findNodeForBuildKey(buildKey);
+ QString sourceDirName;
+ if (node)
+ sourceDirName = node->data(Constants::AndroidPackageSourceDir).toString();
+ QFileInfo sourceDirInfo(sourceDirName);
+ parser->setSourceDirectory(Utils::FilePath::fromString(sourceDirInfo.canonicalFilePath()));
+ parser->setBuildDirectory(buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY));
+ formatter->addLineParser(parser);
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
void AndroidBuildApkStep::showInGraphicalShell()
{
Core::FileUtils::showInGraphicalShell(Core::ICore::mainWindow(), m_packagePath);
diff --git a/src/plugins/android/androidbuildapkstep.h b/src/plugins/android/androidbuildapkstep.h
index e60d2b7f382..ab65a2d7f55 100644
--- a/src/plugins/android/androidbuildapkstep.h
+++ b/src/plugins/android/androidbuildapkstep.h
@@ -82,6 +82,7 @@ private:
void showInGraphicalShell();
bool init() override;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void processStarted() override;
void processFinished(int exitCode, QProcess::ExitStatus status) override;
diff --git a/src/plugins/android/androidpackageinstallationstep.cpp b/src/plugins/android/androidpackageinstallationstep.cpp
index 9fd25e92967..b16a8e864e8 100644
--- a/src/plugins/android/androidpackageinstallationstep.cpp
+++ b/src/plugins/android/androidpackageinstallationstep.cpp
@@ -60,6 +60,7 @@ public:
private:
bool init() final;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
void doRun() final;
QStringList m_androidDirsToClean;
@@ -111,10 +112,6 @@ bool AndroidPackageInstallationStep::init()
pp->setEnvironment(env);
pp->setCommandLine(cmd);
- setOutputParser(new GnuMakeParser());
- appendOutputParsers(target()->kit()->createOutputParsers());
- outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
-
m_androidDirsToClean.clear();
// don't remove gradle's cache, it takes ages to rebuild it.
m_androidDirsToClean << dirPath + "/assets";
@@ -123,6 +120,14 @@ bool AndroidPackageInstallationStep::init()
return AbstractProcessStep::init();
}
+void AndroidPackageInstallationStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ formatter->addLineParser(new GnuMakeParser);
+ formatter->addLineParsers(target()->kit()->createOutputParsers());
+ formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
void AndroidPackageInstallationStep::doRun()
{
QString error;
diff --git a/src/plugins/android/javaparser.cpp b/src/plugins/android/javaparser.cpp
index 9cf34789532..04035c851d6 100644
--- a/src/plugins/android/javaparser.cpp
+++ b/src/plugins/android/javaparser.cpp
@@ -51,7 +51,8 @@ void JavaParser::setSourceDirectory(const Utils::FilePath &sourceDirectory)
m_sourceDirectory = sourceDirectory;
}
-OutputTaskParser::Status JavaParser::handleLine(const QString &line, Utils::OutputFormat type)
+Utils::OutputLineParser::Result JavaParser::handleLine(const QString &line,
+ Utils::OutputFormat type)
{
Q_UNUSED(type);
if (m_javaRegExp.indexIn(line) == -1)
@@ -78,6 +79,8 @@ OutputTaskParser::Status JavaParser::handleLine(const QString &line, Utils::Outp
m_javaRegExp.cap(4).trimmed(),
absoluteFilePath(file),
lineno);
- emit addTask(task, 1);
- return Status::Done;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, m_javaRegExp, 2);
+ scheduleTask(task, 1);
+ return {Status::Done, linkSpecs};
}
diff --git a/src/plugins/android/javaparser.h b/src/plugins/android/javaparser.h
index 31cccbe98c4..09b19d5bdbe 100644
--- a/src/plugins/android/javaparser.h
+++ b/src/plugins/android/javaparser.h
@@ -45,7 +45,7 @@ public:
void setSourceDirectory(const Utils::FilePath &sourceDirectory);
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
QRegExp m_javaRegExp;
QStringList m_fileList;
diff --git a/src/plugins/baremetal/iarewparser.cpp b/src/plugins/baremetal/iarewparser.cpp
index b30bb82f2bb..5e8b97fa628 100644
--- a/src/plugins/baremetal/iarewparser.cpp
+++ b/src/plugins/baremetal/iarewparser.cpp
@@ -145,12 +145,12 @@ bool IarParser::parseErrorOrFatalErrorDetailsMessage2(const QString &lne)
return true;
}
-bool IarParser::parseWarningOrErrorOrFatalErrorDetailsMessage1(const QString &lne)
+OutputLineParser::Result IarParser::parseWarningOrErrorOrFatalErrorDetailsMessage1(const QString &lne)
{
const QRegularExpression re("^\"(.+)\",(\\d+)?\\s+(Warning|Error|Fatal error)\\[(.+)\\].+$");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
- return false;
+ return Status::NotHandled;
enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
MessageTypeIndex, MessageCodeIndex };
const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
@@ -164,7 +164,10 @@ bool IarParser::parseWarningOrErrorOrFatalErrorDetailsMessage1(const QString &ln
m_expectDescription = true;
m_expectSnippet = false;
m_expectFilePath = false;
- return true;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
+ FilePathIndex);
+ return {Status::InProgress, linkSpecs};
}
bool IarParser::parseErrorInCommandLineMessage(const QString &lne)
@@ -190,7 +193,7 @@ bool IarParser::parseErrorMessage1(const QString &lne)
return true;
}
-OutputTaskParser::Status IarParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result IarParser::handleLine(const QString &line, OutputFormat type)
{
const QString lne = rightTrimmed(line);
if (type == StdOutFormat) {
@@ -208,8 +211,9 @@ OutputTaskParser::Status IarParser::handleLine(const QString &line, OutputFormat
return Status::InProgress;
if (parseErrorOrFatalErrorDetailsMessage2(lne))
return Status::InProgress;
- if (parseWarningOrErrorOrFatalErrorDetailsMessage1(lne))
- return Status::InProgress;
+ const Result res = parseWarningOrErrorOrFatalErrorDetailsMessage1(lne);
+ if (res.status != Status::NotHandled)
+ return res;
if (m_expectFilePath) {
if (lne.endsWith(']')) {
@@ -256,7 +260,7 @@ void IarParser::flush()
Task t = m_lastTask;
m_lastTask.clear();
- emit addTask(t, m_lines, 1);
+ scheduleTask(t, m_lines, 1);
m_lines = 0;
}
diff --git a/src/plugins/baremetal/iarewparser.h b/src/plugins/baremetal/iarewparser.h
index 02ad25062dc..92b38bd26fa 100644
--- a/src/plugins/baremetal/iarewparser.h
+++ b/src/plugins/baremetal/iarewparser.h
@@ -48,11 +48,11 @@ private:
bool parseErrorOrFatalErrorDetailsMessage1(const QString &lne);
bool parseErrorOrFatalErrorDetailsMessage2(const QString &lne);
- bool parseWarningOrErrorOrFatalErrorDetailsMessage1(const QString &lne);
+ Result parseWarningOrErrorOrFatalErrorDetailsMessage1(const QString &lne);
bool parseErrorInCommandLineMessage(const QString &lne);
bool parseErrorMessage1(const QString &lne);
- Status handleLine(const QString &line, Utils::OutputFormat type) final;
+ Result handleLine(const QString &line, Utils::OutputFormat type) final;
void flush() final;
ProjectExplorer::Task m_lastTask;
diff --git a/src/plugins/baremetal/iarewtoolchain.cpp b/src/plugins/baremetal/iarewtoolchain.cpp
index b65ebf0d9c6..1ea9d013fe6 100644
--- a/src/plugins/baremetal/iarewtoolchain.cpp
+++ b/src/plugins/baremetal/iarewtoolchain.cpp
@@ -354,7 +354,7 @@ void IarToolChain::addToEnvironment(Environment &env) const
}
}
-QList<OutputTaskParser *> IarToolChain::createOutputParsers() const
+QList<Utils::OutputLineParser *> IarToolChain::createOutputParsers() const
{
return {new IarParser()};
}
diff --git a/src/plugins/baremetal/iarewtoolchain.h b/src/plugins/baremetal/iarewtoolchain.h
index b1706ab2ac8..82442f1817e 100644
--- a/src/plugins/baremetal/iarewtoolchain.h
+++ b/src/plugins/baremetal/iarewtoolchain.h
@@ -68,7 +68,7 @@ public:
const Utils::FilePath &,
const Utils::Environment &env) const final;
void addToEnvironment(Utils::Environment &env) const final;
- QList<ProjectExplorer::OutputTaskParser *> createOutputParsers() const final;
+ QList<Utils::OutputLineParser *> createOutputParsers() const final;
QVariantMap toMap() const final;
bool fromMap(const QVariantMap &data) final;
diff --git a/src/plugins/baremetal/keilparser.cpp b/src/plugins/baremetal/keilparser.cpp
index 094e59ab0fc..3e5032566b8 100644
--- a/src/plugins/baremetal/keilparser.cpp
+++ b/src/plugins/baremetal/keilparser.cpp
@@ -93,12 +93,12 @@ void KeilParser::amendDescription()
// ARM compiler specific parsers.
-bool KeilParser::parseArmWarningOrErrorDetailsMessage(const QString &lne)
+OutputLineParser::Result KeilParser::parseArmWarningOrErrorDetailsMessage(const QString &lne)
{
const QRegularExpression re("^\"(.+)\", line (\\d+).*:\\s+(Warning|Error):(\\s+|.+)([#|L].+)$");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
- return false;
+ return Status::NotHandled;
enum CaptureIndex { FilePathIndex = 1, LineNumberIndex,
MessageTypeIndex, MessageNoteIndex, DescriptionIndex };
const Utils::FilePath fileName = Utils::FilePath::fromUserInput(
@@ -107,7 +107,10 @@ bool KeilParser::parseArmWarningOrErrorDetailsMessage(const QString &lne)
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const QString descr = match.captured(DescriptionIndex);
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
- return true;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
+ FilePathIndex);
+ return {Status::InProgress, linkSpecs};
}
bool KeilParser::parseArmErrorOrFatalErorrMessage(const QString &lne)
@@ -125,12 +128,12 @@ bool KeilParser::parseArmErrorOrFatalErorrMessage(const QString &lne)
// MCS51 compiler specific parsers.
-bool KeilParser::parseMcs51WarningOrErrorDetailsMessage1(const QString &lne)
+OutputLineParser::Result KeilParser::parseMcs51WarningOrErrorDetailsMessage1(const QString &lne)
{
const QRegularExpression re("^\\*{3} (WARNING|ERROR) (\\w+) IN LINE (\\d+) OF (.+\\.\\S+): (.+)$");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
- return false;
+ return Status::NotHandled;
enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex, LineNumberIndex,
FilePathIndex, MessageTextIndex };
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
@@ -140,15 +143,18 @@ bool KeilParser::parseMcs51WarningOrErrorDetailsMessage1(const QString &lne)
const QString descr = QString("%1: %2").arg(match.captured(MessageCodeIndex),
match.captured(MessageTextIndex));
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
- return true;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
+ FilePathIndex);
+ return {Status::InProgress, linkSpecs};
}
-bool KeilParser::parseMcs51WarningOrErrorDetailsMessage2(const QString &lne)
+OutputLineParser::Result KeilParser::parseMcs51WarningOrErrorDetailsMessage2(const QString &lne)
{
const QRegularExpression re("^\\*{3} (WARNING|ERROR) (#\\w+) IN (\\d+) \\((.+), LINE \\d+\\): (.+)$");
const QRegularExpressionMatch match = re.match(lne);
if (!match.hasMatch())
- return false;
+ return Status::NotHandled;
enum CaptureIndex { MessageTypeIndex = 1, MessageCodeIndex, LineNumberIndex,
FilePathIndex, MessageTextIndex };
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
@@ -158,7 +164,10 @@ bool KeilParser::parseMcs51WarningOrErrorDetailsMessage2(const QString &lne)
const QString descr = QString("%1: %2").arg(match.captured(MessageCodeIndex),
match.captured(MessageTextIndex));
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
- return true;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
+ FilePathIndex);
+ return {Status::InProgress, linkSpecs};
}
bool KeilParser::parseMcs51WarningOrFatalErrorMessage(const QString &lne)
@@ -206,15 +215,17 @@ static bool hasDetailsPointer(const QString &trimmedLine)
return trimmedLine.contains('_');
}
-OutputTaskParser::Status KeilParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result KeilParser::handleLine(const QString &line, OutputFormat type)
{
QString lne = rightTrimmed(line);
if (type == StdOutFormat) {
// Check for MSC51 compiler specific patterns.
- const bool parsed = parseMcs51WarningOrErrorDetailsMessage1(lne)
- || parseMcs51WarningOrErrorDetailsMessage2(lne);
- if (parsed)
- return Status::InProgress;
+ Result res = parseMcs51WarningOrErrorDetailsMessage1(lne);
+ if (res.status != Status::NotHandled)
+ return res;
+ res = parseMcs51WarningOrErrorDetailsMessage2(lne);
+ if (res.status != Status::NotHandled)
+ return res;
if (parseMcs51WarningOrFatalErrorMessage(lne))
return Status::InProgress;
if (parseMcs51FatalErrorMessage2(lne))
@@ -247,8 +258,9 @@ OutputTaskParser::Status KeilParser::handleLine(const QString &line, OutputForma
}
// Check for ARM compiler specific patterns.
- if (parseArmWarningOrErrorDetailsMessage(lne))
- return Status::InProgress;
+ const Result res = parseArmWarningOrErrorDetailsMessage(lne);
+ if (res.status != Status::NotHandled)
+ return res;
if (parseArmErrorOrFatalErorrMessage(lne))
return Status::InProgress;
@@ -270,7 +282,7 @@ void KeilParser::flush()
Task t = m_lastTask;
m_lastTask.clear();
- emit addTask(t, m_lines, 1);
+ scheduleTask(t, m_lines, 1);
m_lines = 0;
}
diff --git a/src/plugins/baremetal/keilparser.h b/src/plugins/baremetal/keilparser.h
index d717e744535..f8f5f8b97d4 100644
--- a/src/plugins/baremetal/keilparser.h
+++ b/src/plugins/baremetal/keilparser.h
@@ -46,16 +46,16 @@ private:
void amendDescription();
// ARM compiler specific parsers.
- bool parseArmWarningOrErrorDetailsMessage(const QString &lne);
+ Result parseArmWarningOrErrorDetailsMessage(const QString &lne);
bool parseArmErrorOrFatalErorrMessage(const QString &lne);
// MCS51 compiler specific parsers.
- bool parseMcs51WarningOrErrorDetailsMessage1(const QString &lne);
- bool parseMcs51WarningOrErrorDetailsMessage2(const QString &lne);
+ Result parseMcs51WarningOrErrorDetailsMessage1(const QString &lne);
+ Result parseMcs51WarningOrErrorDetailsMessage2(const QString &lne);
bool parseMcs51WarningOrFatalErrorMessage(const QString &lne);
bool parseMcs51FatalErrorMessage2(const QString &lne);
- Status handleLine(const QString &line, Utils::OutputFormat type) final;
+ Result handleLine(const QString &line, Utils::OutputFormat type) final;
void flush() final;
ProjectExplorer::Task m_lastTask;
diff --git a/src/plugins/baremetal/keiltoolchain.cpp b/src/plugins/baremetal/keiltoolchain.cpp
index 922d38a4011..3eca05dcc65 100644
--- a/src/plugins/baremetal/keiltoolchain.cpp
+++ b/src/plugins/baremetal/keiltoolchain.cpp
@@ -506,7 +506,7 @@ void KeilToolChain::addToEnvironment(Environment &env) const
}
}
-QList<OutputTaskParser *> KeilToolChain::createOutputParsers() const
+QList<OutputLineParser *> KeilToolChain::createOutputParsers() const
{
return {new KeilParser};
}
diff --git a/src/plugins/baremetal/keiltoolchain.h b/src/plugins/baremetal/keiltoolchain.h
index 561db08bd11..3fd36d67962 100644
--- a/src/plugins/baremetal/keiltoolchain.h
+++ b/src/plugins/baremetal/keiltoolchain.h
@@ -69,7 +69,7 @@ public:
const Utils::FilePath &,
const Utils::Environment &env) const final;
void addToEnvironment(Utils::Environment &env) const final;
- QList<ProjectExplorer::OutputTaskParser *> createOutputParsers() const final;
+ QList<Utils::OutputLineParser *> createOutputParsers() const final;
QVariantMap toMap() const final;
bool fromMap(const QVariantMap &data) final;
diff --git a/src/plugins/baremetal/sdccparser.cpp b/src/plugins/baremetal/sdccparser.cpp
index 7cfd363d744..9ed21234d95 100644
--- a/src/plugins/baremetal/sdccparser.cpp
+++ b/src/plugins/baremetal/sdccparser.cpp
@@ -87,7 +87,7 @@ void SdccParser::amendDescription(const QString &desc)
++m_lines;
}
-OutputTaskParser::Status SdccParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result SdccParser::handleLine(const QString &line, OutputFormat type)
{
if (type == StdOutFormat)
return Status::NotHandled;
@@ -108,7 +108,10 @@ OutputTaskParser::Status SdccParser::handleLine(const QString &line, OutputForma
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const QString descr = match.captured(MessageTextIndex);
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
- return Status::InProgress;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
+ FilePathIndex);
+ return {Status::InProgress, linkSpecs};
}
re.setPattern("^(.+\\.\\S+):(\\d+): (Error|error|syntax error): (.+)$");
@@ -122,7 +125,10 @@ OutputTaskParser::Status SdccParser::handleLine(const QString &line, OutputForma
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
const QString descr = match.captured(MessageTextIndex);
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
- return Status::InProgress;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match,
+ FilePathIndex);
+ return {Status::InProgress, linkSpecs};
}
re.setPattern("^at (\\d+): (warning|error) \\d+: (.+)$");
@@ -161,7 +167,7 @@ void SdccParser::flush()
Task t = m_lastTask;
m_lastTask.clear();
- emit addTask(t, m_lines, 1);
+ scheduleTask(t, m_lines, 1);
m_lines = 0;
}
diff --git a/src/plugins/baremetal/sdccparser.h b/src/plugins/baremetal/sdccparser.h
index a8b6f2c0fd8..0b92b702258 100644
--- a/src/plugins/baremetal/sdccparser.h
+++ b/src/plugins/baremetal/sdccparser.h
@@ -45,7 +45,7 @@ private:
void newTask(const ProjectExplorer::Task &task);
void amendDescription(const QString &desc);
- Status handleLine(const QString &line, Utils::OutputFormat type) final;
+ Result handleLine(const QString &line, Utils::OutputFormat type) final;
void flush() final;
ProjectExplorer::Task m_lastTask;
diff --git a/src/plugins/baremetal/sdcctoolchain.cpp b/src/plugins/baremetal/sdcctoolchain.cpp
index 0039b32f213..36bc7945bba 100644
--- a/src/plugins/baremetal/sdcctoolchain.cpp
+++ b/src/plugins/baremetal/sdcctoolchain.cpp
@@ -307,7 +307,7 @@ void SdccToolChain::addToEnvironment(Environment &env) const
}
}
-QList<OutputTaskParser *> SdccToolChain::createOutputParsers() const
+QList<Utils::OutputLineParser *> SdccToolChain::createOutputParsers() const
{
return {new SdccParser};
}
diff --git a/src/plugins/baremetal/sdcctoolchain.h b/src/plugins/baremetal/sdcctoolchain.h
index 0ac575c9823..09aff331afb 100644
--- a/src/plugins/baremetal/sdcctoolchain.h
+++ b/src/plugins/baremetal/sdcctoolchain.h
@@ -69,7 +69,7 @@ public:
const Utils::FilePath &,
const Utils::Environment &env) const final;
void addToEnvironment(Utils::Environment &env) const final;
- QList<ProjectExplorer::OutputTaskParser *> createOutputParsers() const final;
+ QList<Utils::OutputLineParser *> createOutputParsers() const final;
QVariantMap toMap() const final;
bool fromMap(const QVariantMap &data) final;
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
index 0ece524c19f..aa9c3f6e6ec 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp
@@ -197,16 +197,19 @@ bool CMakeBuildStep::init()
pp->setCommandLine(cmakeCommand(rc));
pp->resolveAll();
- CMakeParser *cmakeParser = new CMakeParser;
- cmakeParser->setSourceDirectory(projectDirectory.toString());
- setOutputParser(cmakeParser);
- appendOutputParser(new GnuMakeParser);
- appendOutputParsers(target()->kit()->createOutputParsers());
- outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
-
return AbstractProcessStep::init();
}
+void CMakeBuildStep::setupOutputFormatter(Utils::OutputFormatter *formatter)
+{
+ CMakeParser *cmakeParser = new CMakeParser;
+ cmakeParser->setSourceDirectory(project()->projectDirectory().toString());
+ formatter->addLineParsers({cmakeParser, new GnuMakeParser});
+ formatter->addLineParsers(target()->kit()->createOutputParsers());
+ formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
void CMakeBuildStep::doRun()
{
// Make sure CMake state was written to disk before trying to build:
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.h b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
index cd41f77f412..1e5a4e71009 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildstep.h
+++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.h
@@ -83,6 +83,7 @@ private:
void ctor(ProjectExplorer::BuildStepList *bsl);
bool init() override;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
void doRun() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
diff --git a/src/plugins/cmakeprojectmanager/cmakeparser.cpp b/src/plugins/cmakeprojectmanager/cmakeparser.cpp
index a2dba99b1c5..2d8aa7c0227 100644
--- a/src/plugins/cmakeprojectmanager/cmakeparser.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeparser.cpp
@@ -54,10 +54,13 @@ CMakeParser::CMakeParser()
void CMakeParser::setSourceDirectory(const QString &sourceDir)
{
+ if (m_sourceDirectory)
+ emit searchDirExpired(FilePath::fromString(m_sourceDirectory.value().path()));
m_sourceDirectory = QDir(sourceDir);
+ emit addSearchDir(FilePath::fromString(sourceDir));
}
-OutputTaskParser::Status CMakeParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result CMakeParser::handleLine(const QString &line, OutputFormat type)
{
if (type != StdErrFormat)
return Status::NotHandled;
@@ -80,18 +83,23 @@ OutputTaskParser::Status CMakeParser::handleLine(const QString &line, OutputForm
QString path = m_sourceDirectory ? m_sourceDirectory->absoluteFilePath(
QDir::fromNativeSeparators(m_commonError.cap(1)))
: QDir::fromNativeSeparators(m_commonError.cap(1));
-
m_lastTask = BuildSystemTask(Task::Error,
QString(),
absoluteFilePath(FilePath::fromUserInput(path)),
m_commonError.cap(2).toInt());
m_lines = 1;
- return Status::InProgress;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line,
+ m_commonError, 1);
+ return {Status::InProgress, linkSpecs};
} else if (m_nextSubError.indexIn(trimmedLine) != -1) {
m_lastTask = BuildSystemTask(Task::Error, QString(),
absoluteFilePath(FilePath::fromUserInput(m_nextSubError.cap(1))));
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line,
+ m_nextSubError, 1);
m_lines = 1;
- return Status::InProgress;
+ return {Status::InProgress, linkSpecs};
} else if (trimmedLine.startsWith(QLatin1String(" ")) && !m_lastTask.isNull()) {
if (!m_lastTask.description.isEmpty())
m_lastTask.description.append(QLatin1Char(' '));
@@ -118,11 +126,15 @@ OutputTaskParser::Status CMakeParser::handleLine(const QString &line, OutputForm
{
QRegularExpressionMatch m = m_locationLine.match(trimmedLine);
QTC_CHECK(m.hasMatch());
- m_lastTask.file = Utils::FilePath::fromUserInput(trimmedLine.mid(0, m.capturedStart()));
+ m_lastTask.file = absoluteFilePath(FilePath::fromUserInput(
+ trimmedLine.mid(0, m.capturedStart())));
m_lastTask.line = m.captured(1).toInt();
m_expectTripleLineErrorData = LINE_DESCRIPTION;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, 0,
+ m.capturedStart());
+ return {Status::InProgress, linkSpecs};
}
- return Status::InProgress;
case LINE_DESCRIPTION:
m_lastTask.description = trimmedLine;
if (trimmedLine.endsWith(QLatin1Char('\"')))
@@ -149,7 +161,7 @@ void CMakeParser::flush()
return;
Task t = m_lastTask;
m_lastTask.clear();
- emit addTask(t, m_lines, 1);
+ scheduleTask(t, m_lines, 1);
m_lines = 0;
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeparser.h b/src/plugins/cmakeprojectmanager/cmakeparser.h
index dfcf6d0c1b0..b0cfc6f55a7 100644
--- a/src/plugins/cmakeprojectmanager/cmakeparser.h
+++ b/src/plugins/cmakeprojectmanager/cmakeparser.h
@@ -47,7 +47,7 @@ public:
void setSourceDirectory(const QString &sourceDir);
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
void flush() override;
enum TripleLineError { NONE, LINE_LOCATION, LINE_DESCRIPTION, LINE_DESCRIPTION2 };
diff --git a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp
index 0e6d7a52ffb..e500ac8c2ec 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprocess.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeprocess.cpp
@@ -94,17 +94,6 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
const auto parser = new CMakeParser;
parser->setSourceDirectory(srcDir);
m_parser.addLineParser(parser);
- QDir source = QDir(srcDir);
- connect(&m_parser, &IOutputParser::addTask, this,
- [source](const Task &task) {
- if (task.file.isEmpty() || task.file.toFileInfo().isAbsolute()) {
- TaskHub::addTask(task);
- } else {
- Task t = task;
- t.file = Utils::FilePath::fromString(source.absoluteFilePath(task.file.toString()));
- TaskHub::addTask(t);
- }
- });
// Always use the sourceDir: If we are triggered because the build directory is getting deleted
// then we are racing against CMakeCache.txt also getting deleted.
@@ -194,7 +183,7 @@ void CMakeProcess::processStandardError()
static QString rest;
rest = lineSplit(rest, m_process->readAllStandardError(), [this](const QString &s) {
- m_parser.handleStderr(s);
+ m_parser.appendMessage(s, Utils::StdErrFormat);
Core::MessageManager::write(s);
});
}
diff --git a/src/plugins/cmakeprojectmanager/cmakeprocess.h b/src/plugins/cmakeprojectmanager/cmakeprocess.h
index ed68f9f96c0..c63f54952ad 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprocess.h
+++ b/src/plugins/cmakeprojectmanager/cmakeprocess.h
@@ -27,8 +27,7 @@
#include "builddirparameters.h"
-#include <projectexplorer/ioutputparser.h>
-
+#include <utils/outputformatter.h>
#include <utils/qtcprocess.h>
#include <QElapsedTimer>
@@ -72,7 +71,7 @@ private:
void checkForCancelled();
std::unique_ptr<Utils::QtcProcess> m_process;
- ProjectExplorer::IOutputParser m_parser;
+ Utils::OutputFormatter m_parser;
std::unique_ptr<QFutureInterface<void>> m_future;
bool m_processWasCanceled = false;
QTimer m_cancelTimer;
diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp
index 85ead8eadd3..e9f9f994261 100644
--- a/src/plugins/cmakeprojectmanager/servermodereader.cpp
+++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp
@@ -64,14 +64,6 @@ ServerModeReader::ServerModeReader()
{
m_cmakeParser = new CMakeParser;
m_parser.addLineParser(m_cmakeParser);
- connect(&m_parser, &IOutputParser::addTask, this, [this](const Task &t) {
- Task editable(t);
- if (!editable.file.isEmpty()) {
- QDir srcDir(m_parameters.sourceDirectory.toString());
- editable.file = FilePath::fromString(srcDir.absoluteFilePath(editable.file.toString()));
- }
- TaskHub::addTask(editable);
- });
}
ServerModeReader::~ServerModeReader()
@@ -351,7 +343,7 @@ void ServerModeReader::createNewServer()
connect(m_cmakeServer.get(), &ServerMode::cmakeMessage, [this](const QString &m) {
const QStringList lines = m.split('\n');
for (const QString &l : lines) {
- m_parser.handleStderr(l);
+ m_parser.appendMessage(l, StdErrFormat);
Core::MessageManager::write(l);
}
});
diff --git a/src/plugins/cmakeprojectmanager/servermodereader.h b/src/plugins/cmakeprojectmanager/servermodereader.h
index a93b91e6fa9..66ab0a56be0 100644
--- a/src/plugins/cmakeprojectmanager/servermodereader.h
+++ b/src/plugins/cmakeprojectmanager/servermodereader.h
@@ -37,6 +37,7 @@
#include <memory>
namespace ProjectExplorer { class ProjectNode; }
+namespace Utils { class OutputFormatter; }
namespace CMakeProjectManager {
@@ -187,7 +188,7 @@ private:
QList<FileGroup *> m_fileGroups;
CMakeParser *m_cmakeParser = nullptr;
- ProjectExplorer::IOutputParser m_parser;
+ Utils::OutputFormatter m_parser;
#if defined(WITH_TESTS)
friend class CMakeProjectPlugin;
diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp
index 91504ff1a16..b27b91afc03 100644
--- a/src/plugins/coreplugin/outputwindow.cpp
+++ b/src/plugins/coreplugin/outputwindow.cpp
@@ -26,6 +26,7 @@
#include "outputwindow.h"
#include "actionmanager/actionmanager.h"
+#include "editormanager/editormanager.h"
#include "coreconstants.h"
#include "coreplugin.h"
#include "icore.h"
@@ -138,6 +139,11 @@ OutputWindow::OutputWindow(Context context, const QString &settingsKey, QWidget
Core::ICore::settings()->setValue(d->settingsKey, fontZoom());
});
+ connect(outputFormatter(), &OutputFormatter::openInEditorRequested, this,
+ [](const Utils::FilePath &fp, int line, int column) {
+ EditorManager::openEditorAt(fp.toString(), line, column);
+ });
+
undoAction->setEnabled(false);
redoAction->setEnabled(false);
cutAction->setEnabled(false);
@@ -528,12 +534,10 @@ private:
return Status::NotHandled;
}
- void reset() override { m_handling = false; }
-
bool m_handling = false;
};
-// Handles all lines starting with "B". No continuation logic
+// Handles all lines starting with "B". No continuation logic.
class TestFormatterB : public OutputLineParser
{
private:
@@ -571,18 +575,17 @@ void Internal::CorePlugin::testOutputFormatter()
" A trick\n"
" embedded carriage return\n"
"handled by B\n";
- OutputFormatter formatter;
- QPlainTextEdit textEdit;
- formatter.setPlainTextEdit(&textEdit);
- formatter.setLineParsers({new TestFormatterB, new TestFormatterA});
// Stress-test the implementation by providing the input in chunks, splitting at all possible
// offsets.
for (int i = 0; i < input.length(); ++i) {
- formatter.appendMessage(input.left(i), NormalMessageFormat);
- formatter.appendMessage(input.mid(i), NormalMessageFormat);
+ OutputFormatter formatter;
+ QPlainTextEdit textEdit;
+ formatter.setPlainTextEdit(&textEdit);
+ formatter.setLineParsers({new TestFormatterB, new TestFormatterA});
+ formatter.appendMessage(input.left(i), StdOutFormat);
+ formatter.appendMessage(input.mid(i), StdOutFormat);
QCOMPARE(textEdit.toPlainText(), output);
- formatter.clear();
}
}
#endif // WITH_TESTS
diff --git a/src/plugins/ios/iosbuildstep.cpp b/src/plugins/ios/iosbuildstep.cpp
index a8503d0fc65..9fbe292299b 100644
--- a/src/plugins/ios/iosbuildstep.cpp
+++ b/src/plugins/ios/iosbuildstep.cpp
@@ -82,6 +82,7 @@ public:
Utils::FilePath buildCommand() const;
bool init() final;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter);
void doRun() final;
bool fromMap(const QVariantMap &map) final;
QVariantMap toMap() const final;
@@ -222,13 +223,17 @@ bool IosBuildStep::init()
// That is mostly so that rebuild works on an already clean project
setIgnoreReturnValue(m_clean);
- setOutputParser(new GnuMakeParser());
- appendOutputParsers(target()->kit()->createOutputParsers());
- outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
-
return AbstractProcessStep::init();
}
+void IosBuildStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ formatter->addLineParser(new GnuMakeParser);
+ formatter->addLineParsers(target()->kit()->createOutputParsers());
+ formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
QVariantMap IosBuildStep::toMap() const
{
QVariantMap map(AbstractProcessStep::toMap());
diff --git a/src/plugins/ios/iosdsymbuildstep.cpp b/src/plugins/ios/iosdsymbuildstep.cpp
index f188630bc6a..3b11d069222 100644
--- a/src/plugins/ios/iosdsymbuildstep.cpp
+++ b/src/plugins/ios/iosdsymbuildstep.cpp
@@ -80,9 +80,6 @@ bool IosDsymBuildStep::init()
// That is mostly so that rebuild works on an already clean project
setIgnoreReturnValue(m_clean);
- appendOutputParsers(target()->kit()->createOutputParsers());
- outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
-
return AbstractProcessStep::init();
}
@@ -189,6 +186,13 @@ void IosDsymBuildStep::doRun()
AbstractProcessStep::doRun();
}
+void IosDsymBuildStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ formatter->setLineParsers(target()->kit()->createOutputParsers());
+ formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
BuildStepConfigWidget *IosDsymBuildStep::createConfigWidget()
{
return new IosDsymBuildStepConfigWidget(this);
diff --git a/src/plugins/ios/iosdsymbuildstep.h b/src/plugins/ios/iosdsymbuildstep.h
index effc6e5f914..7e08b1a6ad2 100644
--- a/src/plugins/ios/iosdsymbuildstep.h
+++ b/src/plugins/ios/iosdsymbuildstep.h
@@ -56,6 +56,7 @@ public:
private:
bool init() override;
void doRun() override;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &map) override;
diff --git a/src/plugins/nim/project/nimblebuildstep.cpp b/src/plugins/nim/project/nimblebuildstep.cpp
index 7beebc7ae93..1d29fbb1aa4 100644
--- a/src/plugins/nim/project/nimblebuildstep.cpp
+++ b/src/plugins/nim/project/nimblebuildstep.cpp
@@ -45,7 +45,7 @@ namespace {
class NimParser : public OutputTaskParser
{
- Status handleLine(const QString &lne, Utils::OutputFormat) override
+ Result handleLine(const QString &lne, Utils::OutputFormat) override
{
const QString line = lne.trimmed();
static QRegularExpression regex("(.+.nim)\\((\\d+), (\\d+)\\) (.+)",
@@ -74,9 +74,12 @@ class NimParser : public OutputTaskParser
else
return Status::NotHandled;
- emit addTask(CompileTask(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
- lineNumber));
- return Status::Done;
+ const CompileTask t(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
+ lineNumber);
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, match, 1);
+ scheduleTask(t, 1);
+ return {Status::Done, linkSpecs};
}
};
@@ -95,10 +98,6 @@ NimbleBuildStep::NimbleBuildStep(BuildStepList *parentList, Core::Id id)
bool NimbleBuildStep::init()
{
- auto parser = new NimParser();
- parser->addSearchDir(project()->projectDirectory());
- setOutputParser(parser);
-
ProcessParameters* params = processParameters();
params->setEnvironment(buildEnvironment());
params->setMacroExpander(macroExpander());
@@ -107,6 +106,14 @@ bool NimbleBuildStep::init()
return AbstractProcessStep::init();
}
+void NimbleBuildStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ const auto parser = new NimParser();
+ parser->addSearchDir(project()->projectDirectory());
+ formatter->addLineParser(parser);
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
BuildStepConfigWidget *NimbleBuildStep::createConfigWidget()
{
return new NimbleBuildStepWidget(this);
diff --git a/src/plugins/nim/project/nimblebuildstep.h b/src/plugins/nim/project/nimblebuildstep.h
index 3a3af510463..7d903e5135b 100644
--- a/src/plugins/nim/project/nimblebuildstep.h
+++ b/src/plugins/nim/project/nimblebuildstep.h
@@ -37,7 +37,7 @@ public:
NimbleBuildStep(ProjectExplorer::BuildStepList *parentList, Core::Id id);
bool init() override;
-
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
QString arguments() const;
diff --git a/src/plugins/nim/project/nimcompilerbuildstep.cpp b/src/plugins/nim/project/nimcompilerbuildstep.cpp
index 4950f20fbbf..9015a2002dd 100644
--- a/src/plugins/nim/project/nimcompilerbuildstep.cpp
+++ b/src/plugins/nim/project/nimcompilerbuildstep.cpp
@@ -47,7 +47,7 @@ namespace Nim {
class NimParser : public ProjectExplorer::OutputTaskParser
{
- Status handleLine(const QString &lne, Utils::OutputFormat) override
+ Result handleLine(const QString &lne, Utils::OutputFormat) override
{
const QString line = lne.trimmed();
static QRegularExpression regex("(.+.nim)\\((\\d+), (\\d+)\\) (.+)",
@@ -76,9 +76,12 @@ class NimParser : public ProjectExplorer::OutputTaskParser
else
return Status::NotHandled;
- emit addTask(CompileTask(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
- lineNumber));
- return Status::Done;
+ const CompileTask t(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
+ lineNumber);
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, match, 1);
+ scheduleTask(t, 1);
+ return {Status::Done, linkSpecs};
}
};
@@ -100,12 +103,12 @@ NimCompilerBuildStep::NimCompilerBuildStep(BuildStepList *parentList, Core::Id i
updateProcessParameters();
}
-bool NimCompilerBuildStep::init()
+void NimCompilerBuildStep::setupOutputFormatter(OutputFormatter *formatter)
{
- setOutputParser(new NimParser());
- appendOutputParsers(target()->kit()->createOutputParsers());
- outputParser()->addSearchDir(processParameters()->effectiveWorkingDirectory());
- return AbstractProcessStep::init();
+ formatter->addLineParser(new NimParser);
+ formatter->addLineParsers(target()->kit()->createOutputParsers());
+ formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
+ AbstractProcessStep::setupOutputFormatter(formatter);
}
BuildStepConfigWidget *NimCompilerBuildStep::createConfigWidget()
diff --git a/src/plugins/nim/project/nimcompilerbuildstep.h b/src/plugins/nim/project/nimcompilerbuildstep.h
index aca8750c06b..cd194e06ea9 100644
--- a/src/plugins/nim/project/nimcompilerbuildstep.h
+++ b/src/plugins/nim/project/nimcompilerbuildstep.h
@@ -41,7 +41,7 @@ public:
NimCompilerBuildStep(ProjectExplorer::BuildStepList *parentList, Core::Id id);
- bool init() override;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
bool fromMap(const QVariantMap &map) override;
diff --git a/src/plugins/nim/project/nimtoolchain.cpp b/src/plugins/nim/project/nimtoolchain.cpp
index 337e697e4fb..1d1cf4e1a7f 100644
--- a/src/plugins/nim/project/nimtoolchain.cpp
+++ b/src/plugins/nim/project/nimtoolchain.cpp
@@ -120,7 +120,7 @@ void NimToolChain::setCompilerCommand(const FilePath &compilerCommand)
parseVersion(compilerCommand, m_version);
}
-QList<OutputTaskParser *> NimToolChain::createOutputParsers() const
+QList<Utils::OutputLineParser *> NimToolChain::createOutputParsers() const
{
return {};
}
diff --git a/src/plugins/nim/project/nimtoolchain.h b/src/plugins/nim/project/nimtoolchain.h
index 7ef119af1e1..d61448e6a00 100644
--- a/src/plugins/nim/project/nimtoolchain.h
+++ b/src/plugins/nim/project/nimtoolchain.h
@@ -56,7 +56,7 @@ public:
Utils::FilePath compilerCommand() const final;
QString compilerVersion() const;
void setCompilerCommand(const Utils::FilePath &compilerCommand);
- QList<ProjectExplorer::OutputTaskParser *> createOutputParsers() const final;
+ QList<Utils::OutputLineParser *> createOutputParsers() const final;
std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> createConfigurationWidget() final;
QVariantMap toMap() const final;
diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt
index 24b7dbd6553..35ed62afc67 100644
--- a/src/plugins/projectexplorer/CMakeLists.txt
+++ b/src/plugins/projectexplorer/CMakeLists.txt
@@ -8,7 +8,6 @@ add_qtc_plugin(ProjectExplorer
addrunconfigdialog.cpp addrunconfigdialog.h
allprojectsfilter.cpp allprojectsfilter.h
allprojectsfind.cpp allprojectsfind.h
- ansifilterparser.cpp ansifilterparser.h
applicationlauncher.cpp applicationlauncher.h
appoutputpane.cpp appoutputpane.h
baseprojectwizarddialog.cpp baseprojectwizarddialog.h
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp
index 479cd309f34..1a9d18a9378 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.cpp
+++ b/src/plugins/projectexplorer/abstractprocessstep.cpp
@@ -24,7 +24,6 @@
****************************************************************************/
#include "abstractprocessstep.h"
-#include "ansifilterparser.h"
#include "buildconfiguration.h"
#include "buildstep.h"
#include "ioutputparser.h"
@@ -37,8 +36,8 @@
#include <coreplugin/reaper.h>
-#include <utils/fileinprojectfinder.h>
#include <utils/fileutils.h>
+#include <utils/outputformatter.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -106,27 +105,18 @@ public:
AbstractProcessStep *q;
std::unique_ptr<Utils::QtcProcess> m_process;
- IOutputParser m_outputParser;
ProcessParameters m_param;
bool m_ignoreReturnValue = false;
bool m_lowPriority = false;
std::unique_ptr<QTextDecoder> stdoutStream;
std::unique_ptr<QTextDecoder> stderrStream;
+ OutputFormatter *outputFormatter = nullptr;
};
AbstractProcessStep::AbstractProcessStep(BuildStepList *bsl, Core::Id id) :
BuildStep(bsl, id),
d(new Private(this))
{
- connect(&d->m_outputParser, &IOutputParser::addTask, this,
- [this](const Task &task, int linkedLines, int skipLines) {
- // Do not bother to report issues if we do not care about the results of
- // the buildstep anyway:
- // TODO: Does that make sense? The user might still want to know that
- // something failed, even if it wasn't fatal...
- if (!d->m_ignoreReturnValue)
- emit addTask(task, linkedLines, skipLines);
- });
}
AbstractProcessStep::~AbstractProcessStep()
@@ -134,36 +124,6 @@ AbstractProcessStep::~AbstractProcessStep()
delete d;
}
-/*!
- Deletes all existing output parsers and starts a new chain with the
- given parser.
-*/
-void AbstractProcessStep::setOutputParser(OutputTaskParser *parser)
-{
- d->m_outputParser.setLineParsers({parser});
-}
-
-/*!
- Appends the given output parser to the existing chain of parsers.
-*/
-void AbstractProcessStep::appendOutputParser(OutputTaskParser *parser)
-{
- if (!parser)
- return;
- d->m_outputParser.addLineParser(parser);
-}
-
-void AbstractProcessStep::appendOutputParsers(const QList<OutputTaskParser *> &parsers)
-{
- for (OutputTaskParser * const p : parsers)
- appendOutputParser(p);
-}
-
-IOutputParser *AbstractProcessStep::outputParser() const
-{
- return &d->m_outputParser;
-}
-
void AbstractProcessStep::emitFaultyConfigurationMessage()
{
emit addOutput(tr("Configuration is faulty. Check the Issues view for details."),
@@ -194,14 +154,16 @@ void AbstractProcessStep::setIgnoreReturnValue(bool b)
bool AbstractProcessStep::init()
{
- Utils::FileInProjectFinder fileFinder;
- fileFinder.setProjectDirectory(project()->projectDirectory());
- fileFinder.setProjectFiles(project()->files(Project::AllFiles));
- d->m_outputParser.addFilter(&Internal::filterAnsiEscapeCodes);
- d->m_outputParser.setFileFinder(fileFinder);
return !d->m_process;
}
+void AbstractProcessStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ formatter->setDemoteErrorsToWarnings(d->m_ignoreReturnValue);
+ d->outputFormatter = formatter;
+ BuildStep::setupOutputFormatter(formatter);
+}
+
/*!
Reimplemented from BuildStep::init(). You need to call this from
YourBuildStep::run().
@@ -257,7 +219,6 @@ void AbstractProcessStep::doRun()
if (!d->m_process->waitForStarted()) {
processStartupFailed();
d->m_process.reset();
- d->m_outputParser.clear();
finish(false);
return;
}
@@ -285,7 +246,6 @@ void AbstractProcessStep::cleanUp(QProcess *process)
processFinished(process->exitCode(), process->exitStatus());
const bool returnValue = processSucceeded(process->exitCode(), process->exitStatus()) || d->m_ignoreReturnValue;
- d->m_outputParser.clear();
d->m_process.reset();
// Report result
@@ -315,9 +275,6 @@ void AbstractProcessStep::processStarted()
void AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus status)
{
- d->m_outputParser.flush();
- d->m_outputParser.clear();
-
QString command = QDir::toNativeSeparators(d->m_param.effectiveCommand().toString());
if (status == QProcess::NormalExit && exitCode == 0) {
emit addOutput(tr("The process \"%1\" exited normally.").arg(command),
@@ -351,7 +308,7 @@ void AbstractProcessStep::processStartupFailed()
bool AbstractProcessStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
{
- if (outputParser()->hasFatalErrors())
+ if (d->outputFormatter->hasFatalErrors())
return false;
return exitCode == 0 && status == QProcess::NormalExit;
@@ -372,7 +329,6 @@ void AbstractProcessStep::processReadyReadStdOutput()
void AbstractProcessStep::stdOutput(const QString &output)
{
- d->m_outputParser.handleStdout(output);
emit addOutput(output, BuildStep::OutputFormat::Stdout, BuildStep::DontAppendNewline);
}
@@ -391,7 +347,6 @@ void AbstractProcessStep::processReadyReadStdError()
void AbstractProcessStep::stdError(const QString &output)
{
- d->m_outputParser.handleStderr(output);
emit addOutput(output, BuildStep::OutputFormat::Stderr, BuildStep::DontAppendNewline);
}
diff --git a/src/plugins/projectexplorer/abstractprocessstep.h b/src/plugins/projectexplorer/abstractprocessstep.h
index f6b720eb138..9431c3a97c0 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.h
+++ b/src/plugins/projectexplorer/abstractprocessstep.h
@@ -31,8 +31,6 @@
namespace Utils { class FilePath; }
namespace ProjectExplorer {
-
-class IOutputParser;
class OutputTaskParser;
class ProcessParameters;
@@ -47,17 +45,13 @@ public:
bool ignoreReturnValue();
void setIgnoreReturnValue(bool b);
- void setOutputParser(OutputTaskParser *parser);
- void appendOutputParser(OutputTaskParser *parser);
- void appendOutputParsers(const QList<OutputTaskParser *> &parsers);
- IOutputParser *outputParser() const;
-
void emitFaultyConfigurationMessage();
protected:
AbstractProcessStep(BuildStepList *bsl, Core::Id id);
~AbstractProcessStep() override;
bool init() override;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
void doRun() override;
void setLowPriority();
virtual void finish(bool success);
diff --git a/src/plugins/projectexplorer/ansifilterparser.cpp b/src/plugins/projectexplorer/ansifilterparser.cpp
deleted file mode 100644
index a4540845ce8..00000000000
--- a/src/plugins/projectexplorer/ansifilterparser.cpp
+++ /dev/null
@@ -1,164 +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 "ansifilterparser.h"
-
-#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,
- ANSI_CSI,
- ANSI_SEQUENCE,
- ANSI_WAITING_FOR_ST,
- ANSI_ST_STARTED
-};
-
-QString filterAnsiEscapeCodes(const QString &line)
-{
- QString result;
- result.reserve(line.count());
-
- static AnsiState state = PLAIN;
- foreach (const QChar c, line) {
- unsigned int val = c.unicode();
- switch (state) {
- case PLAIN:
- if (val == 27) // 'ESC'
- state = ANSI_START;
- else if (val == 155) // equivalent to 'ESC'-'['
- state = ANSI_CSI;
- else
- result.append(c);
- break;
- case ANSI_START:
- if (val == 91) // [
- state = ANSI_CSI;
- else if (val == 80 || val == 93 || val == 94 || val == 95) // 'P', ']', '^' and '_'
- state = ANSI_WAITING_FOR_ST;
- else if (val >= 64 && val <= 95)
- state = PLAIN;
- else
- state = ANSI_SEQUENCE;
- break;
- case ANSI_CSI:
- if (val >= 64 && val <= 126) // Anything between '@' and '~'
- state = PLAIN;
- break;
- case ANSI_SEQUENCE:
- if (val >= 64 && val <= 95) // Anything between '@' and '_'
- state = PLAIN;
- break;
- case ANSI_WAITING_FOR_ST:
- if (val == 7) // 'BEL'
- state = PLAIN;
- if (val == 27) // 'ESC'
- state = ANSI_ST_STARTED;
- break;
- case ANSI_ST_STARTED:
- if (val == 92) // '\'
- state = PLAIN;
- else
- state = ANSI_WAITING_FOR_ST;
- break;
- }
- }
- return result;
-}
-} // namespace Internal
-
-#ifdef WITH_TESTS
-void ProjectExplorerPlugin::testAnsiFilterOutputParser_data()
-{
- QTest::addColumn<QString>("input");
- QTest::addColumn<OutputParserTester::Channel>("inputChannel");
- QTest::addColumn<QString>("childStdOutLines");
- QTest::addColumn<QString>("childStdErrLines");
- QTest::addColumn<QString>("outputLines");
-
- QTest::newRow("pass-through stdout")
- << QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
- << QString::fromLatin1("Sometext\n") << QString();
- QTest::newRow("pass-through stderr")
- << QString::fromLatin1("Sometext") << OutputParserTester::STDERR
- << QString() << QString::fromLatin1("Sometext\n");
-
- QString input = QString::fromLatin1("te") + QChar(27) + QString::fromLatin1("Nst");
- QTest::newRow("ANSI: ESC-N")
- << input << OutputParserTester::STDOUT
- << QString::fromLatin1("test\n") << QString();
- input = QString::fromLatin1("te") + QChar(27) + QLatin1String("^ignored") + QChar(27) + QLatin1String("\\st");
- QTest::newRow("ANSI: ESC-^ignoredESC-\\")
- << input << OutputParserTester::STDOUT
- << QString::fromLatin1("test\n") << QString();
- input = QString::fromLatin1("te") + QChar(27) + QLatin1String("]0;ignored") + QChar(7) + QLatin1String("st");
- QTest::newRow("ANSI: window title change")
- << input << OutputParserTester::STDOUT
- << QString::fromLatin1("test\n") << QString();
- input = QString::fromLatin1("te") + QChar(27) + QLatin1String("[Ast");
- QTest::newRow("ANSI: cursor up")
- << input << OutputParserTester::STDOUT
- << QString::fromLatin1("test\n") << QString();
- input = QString::fromLatin1("te") + QChar(27) + QLatin1String("[2Ast");
- QTest::newRow("ANSI: cursor up (with int parameter)")
- << input << OutputParserTester::STDOUT
- << QString::fromLatin1("test\n") << QString();
- input = QString::fromLatin1("te") + QChar(27) + QLatin1String("[2;3Hst");
- QTest::newRow("ANSI: position cursor")
- << input << OutputParserTester::STDOUT
- << QString::fromLatin1("test\n") << QString();
- input = QString::fromLatin1("te") + QChar(27) + QLatin1String("[31;1mst");
- QTest::newRow("ANSI: bold red")
- << input << OutputParserTester::STDOUT
- << QString::fromLatin1("test\n") << QString();
-}
-
-void ProjectExplorerPlugin::testAnsiFilterOutputParser()
-{
- OutputParserTester testbench;
- testbench.addFilter(&Internal::filterAnsiEscapeCodes);
- QFETCH(QString, input);
- QFETCH(OutputParserTester::Channel, inputChannel);
- QFETCH(QString, childStdOutLines);
- QFETCH(QString, childStdErrLines);
-
- testbench.testParsing(input, inputChannel,
- Tasks(), childStdOutLines, childStdErrLines,
- QString());
-}
-
-#endif
-
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/ansifilterparser.h b/src/plugins/projectexplorer/ansifilterparser.h
deleted file mode 100644
index b3ec351c357..00000000000
--- a/src/plugins/projectexplorer/ansifilterparser.h
+++ /dev/null
@@ -1,38 +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 "ioutputparser.h"
-
-#include "projectexplorer_export.h"
-
-namespace ProjectExplorer {
-namespace Internal {
-
-QString filterAnsiEscapeCodes(const QString &line);
-
-} // namespace Internal
-} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp
index 08bfa57de03..e13d12c9d8c 100644
--- a/src/plugins/projectexplorer/buildmanager.cpp
+++ b/src/plugins/projectexplorer/buildmanager.cpp
@@ -46,6 +46,7 @@
#include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <extensionsystem/pluginmanager.h>
+#include <utils/outputformatter.h>
#include <utils/runextensions.h>
#include <utils/stringutils.h>
@@ -680,6 +681,7 @@ void BuildManager::nextStep()
}
static const auto finishedHandler = [](bool success) {
+ d->m_outputWindow->outputFormatter()->flush();
d->m_lastStepSucceeded = success;
disconnect(d->m_currentBuildStep, nullptr, instance(), nullptr);
BuildManager::nextBuildQueue();
@@ -688,6 +690,8 @@ void BuildManager::nextStep()
Qt::QueuedConnection);
connect(d->m_currentBuildStep, &BuildStep::progress,
instance(), &BuildManager::progressChanged);
+ d->m_outputWindow->outputFormatter()->reset();
+ d->m_currentBuildStep->setupOutputFormatter(d->m_outputWindow->outputFormatter());
d->m_currentBuildStep->run();
} else {
d->m_running = false;
diff --git a/src/plugins/projectexplorer/buildstep.cpp b/src/plugins/projectexplorer/buildstep.cpp
index 319eaf69b66..b7edd0d21a7 100644
--- a/src/plugins/projectexplorer/buildstep.cpp
+++ b/src/plugins/projectexplorer/buildstep.cpp
@@ -36,6 +36,8 @@
#include <coreplugin/variablechooser.h>
#include <utils/algorithm.h>
+#include <utils/fileinprojectfinder.h>
+#include <utils/outputformatter.h>
#include <utils/qtcassert.h>
#include <utils/runextensions.h>
@@ -254,6 +256,14 @@ QString BuildStep::fallbackWorkingDirectory() const
return {Constants::DEFAULT_WORKING_DIR_ALTERNATE};
}
+void BuildStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ Utils::FileInProjectFinder fileFinder;
+ fileFinder.setProjectDirectory(project()->projectDirectory());
+ fileFinder.setProjectFiles(project()->files(Project::AllFiles));
+ formatter->setFileFinder(fileFinder);
+}
+
void BuildStep::reportRunResult(QFutureInterface<bool> &fi, bool success)
{
fi.reportResult(success);
diff --git a/src/plugins/projectexplorer/buildstep.h b/src/plugins/projectexplorer/buildstep.h
index b8dd6b67181..048b798ba48 100644
--- a/src/plugins/projectexplorer/buildstep.h
+++ b/src/plugins/projectexplorer/buildstep.h
@@ -44,6 +44,7 @@ namespace Utils {
class Environment;
class FilePath;
class MacroExpander;
+class OutputFormatter;
} // Utils
namespace ProjectExplorer {
@@ -91,6 +92,8 @@ public:
Utils::MacroExpander *macroExpander() const;
QString fallbackWorkingDirectory() const;
+ virtual void setupOutputFormatter(Utils::OutputFormatter *formatter);
+
enum class OutputFormat {
Stdout, Stderr, // These are for forwarded output from external tools
NormalMessage, ErrorMessage // These are for messages from Creator itself
@@ -117,8 +120,8 @@ public:
signals:
/// Adds a \p task to the Issues pane.
- /// Do note that for linking compile output with tasks, you should first emit the task
- /// and then emit the output. \p linkedOutput lines will be linked. And the last \p skipLines will
+ /// Do note that for linking compile output with tasks, you should first emit the output
+ /// and then emit the task. \p linkedOutput lines will be linked. And the last \p skipLines will
/// be skipped.
void addTask(const ProjectExplorer::Task &task, int linkedOutputLines = 0, int skipLines = 0);
diff --git a/src/plugins/projectexplorer/clangparser.cpp b/src/plugins/projectexplorer/clangparser.cpp
index 5b6739e5448..4df1d5bff7a 100644
--- a/src/plugins/projectexplorer/clangparser.cpp
+++ b/src/plugins/projectexplorer/clangparser.cpp
@@ -55,12 +55,12 @@ ClangParser::ClangParser() :
setObjectName(QLatin1String("ClangParser"));
}
-QList<OutputTaskParser *> ClangParser::clangParserSuite()
+QList<OutputLineParser *> ClangParser::clangParserSuite()
{
return {new ClangParser, new Internal::LldParser, new LdParser};
}
-OutputTaskParser::Status ClangParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result ClangParser::handleLine(const QString &line, OutputFormat type)
{
if (type != StdErrFormat)
return Status::NotHandled;
@@ -82,11 +82,12 @@ OutputTaskParser::Status ClangParser::handleLine(const QString &line, OutputForm
match = m_inLineRegExp.match(lne);
if (match.hasMatch()) {
m_expectSnippet = true;
- newTask(CompileTask(Task::Unknown,
- lne.trimmed(),
- absoluteFilePath(FilePath::fromUserInput(match.captured(2))),
- match.captured(3).toInt() /* line */));
- return Status::InProgress;
+ const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(2)));
+ const int lineNo = match.captured(3).toInt();
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 2);
+ newTask(CompileTask(Task::Unknown, lne.trimmed(), filePath, lineNo));
+ return {Status::InProgress, linkSpecs};
}
match = m_messageRegExp.match(lne);
@@ -96,10 +97,10 @@ OutputTaskParser::Status ClangParser::handleLine(const QString &line, OutputForm
int lineNo = match.captured(4).toInt(&ok);
if (!ok)
lineNo = match.captured(5).toInt(&ok);
- newTask(CompileTask(taskType(match.captured(7)),
- match.captured(8),
- absoluteFilePath(FilePath::fromUserInput(match.captured(1))),
- lineNo));
+ const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 1);
+ newTask(CompileTask(taskType(match.captured(7)), match.captured(8), filePath, lineNo));
return Status::InProgress;
}
@@ -255,8 +256,7 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
<< (Tasks()
<< CompileTask(Task::Unknown,
"Note: No relevant classes found. No output generated.",
- FilePath::fromUserInput("/home/qtwebkithelpviewer.h"),
- 0))
+ FilePath::fromUserInput("/home/qtwebkithelpviewer.h")))
<< QString();
}
diff --git a/src/plugins/projectexplorer/clangparser.h b/src/plugins/projectexplorer/clangparser.h
index 13b2d9ece65..5b61d0cbaad 100644
--- a/src/plugins/projectexplorer/clangparser.h
+++ b/src/plugins/projectexplorer/clangparser.h
@@ -39,12 +39,12 @@ class PROJECTEXPLORER_EXPORT ClangParser : public ProjectExplorer::GccParser
public:
ClangParser();
- static QList<OutputTaskParser *> clangParserSuite();
+ static QList<Utils::OutputLineParser *> clangParserSuite();
static Core::Id id();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
QRegularExpression m_commandRegExp;
QRegularExpression m_inLineRegExp;
diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp
index 832318b4199..27c08886337 100644
--- a/src/plugins/projectexplorer/compileoutputwindow.cpp
+++ b/src/plugins/projectexplorer/compileoutputwindow.cpp
@@ -24,12 +24,14 @@
****************************************************************************/
#include "compileoutputwindow.h"
+
#include "buildmanager.h"
-#include "showoutputtaskhandler.h"
-#include "task.h"
+#include "ioutputparser.h"
#include "projectexplorer.h"
#include "projectexplorericons.h"
#include "projectexplorersettings.h"
+#include "showoutputtaskhandler.h"
+#include "task.h"
#include "taskhub.h"
#include <coreplugin/outputwindow.h>
@@ -40,7 +42,8 @@
#include <texteditor/texteditorsettings.h>
#include <texteditor/fontsettings.h>
#include <texteditor/behaviorsettings.h>
-#include <utils/outputformat.h>
+#include <utils/algorithm.h>
+#include <utils/outputformatter.h>
#include <utils/proxyaction.h>
#include <utils/theme/theme.h>
#include <utils/utilsicons.h>
@@ -67,74 +70,29 @@ const char WRAP_OUTPUT_KEY[] = "ProjectExplorer/Settings/WrapBuildOutput";
const char MAX_LINES_KEY[] = "ProjectExplorer/Settings/MaxBuildOutputLines";
const char OPTIONS_PAGE_ID[] = "C.ProjectExplorer.CompileOutputOptions";
-class CompileOutputTextEdit : public Core::OutputWindow
-{
- Q_OBJECT
-public:
- CompileOutputTextEdit(const Core::Context &context) : Core::OutputWindow(context, SETTINGS_KEY)
- {
- setMouseTracking(true);
- }
-
- void addTask(const Task &task, int blocknumber)
- {
- m_taskids.insert(blocknumber, task.taskId);
- }
-
- void clearTasks()
- {
- m_taskids.clear();
- }
-
-protected:
- void mouseMoveEvent(QMouseEvent *ev) override
- {
- const int line = cursorForPosition(ev->pos()).block().blockNumber();
- if (m_taskids.contains(line) && m_mousePressButton == Qt::NoButton)
- viewport()->setCursor(Qt::PointingHandCursor);
- else
- viewport()->setCursor(Qt::IBeamCursor);
- QPlainTextEdit::mouseMoveEvent(ev);
- }
-
- void mousePressEvent(QMouseEvent *ev) override
- {
- m_mousePressPosition = ev->pos();
- m_mousePressButton = ev->button();
- QPlainTextEdit::mousePressEvent(ev);
- }
-
- void mouseReleaseEvent(QMouseEvent *ev) override
- {
- if ((m_mousePressPosition - ev->pos()).manhattanLength() < 4
- && m_mousePressButton == Qt::LeftButton) {
- int line = cursorForPosition(ev->pos()).block().blockNumber();
- if (unsigned taskid = m_taskids.value(line, 0))
- TaskHub::showTaskInEditor(taskid);
- }
-
- m_mousePressButton = Qt::NoButton;
- QPlainTextEdit::mouseReleaseEvent(ev);
- }
-
-private:
- QHash<int, unsigned int> m_taskids; //Map blocknumber to taskId
- QPoint m_mousePressPosition;
- Qt::MouseButton m_mousePressButton = Qt::NoButton;
-};
-
CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) :
m_cancelBuildButton(new QToolButton),
m_settingsButton(new QToolButton)
{
Core::Context context(C_COMPILE_OUTPUT);
- m_outputWindow = new CompileOutputTextEdit(context);
+ m_outputWindow = new Core::OutputWindow(context, SETTINGS_KEY);
m_outputWindow->setWindowTitle(displayName());
m_outputWindow->setWindowIcon(Icons::WINDOW.icon());
m_outputWindow->setReadOnly(true);
m_outputWindow->setUndoRedoEnabled(false);
m_outputWindow->setMaxCharCount(Core::Constants::DEFAULT_MAX_CHAR_COUNT);
+ outputFormatter()->overridePostPrintAction([this](Utils::OutputLineParser *parser) {
+ if (const auto taskParser = qobject_cast<OutputTaskParser *>(parser)) {
+ int offset = 0;
+ Utils::reverseForeach(taskParser->taskInfo(), [this, &offset](const OutputTaskParser::TaskInfo &ti) {
+ registerPositionOf(ti.task, ti.linkedLines, ti.skippedLines, offset);
+ offset += ti.linkedLines;
+ });
+ }
+ parser->runPostPrintActions();
+ });
+
// Let selected text be colored as if the text edit was editable,
// otherwise the highlight for searching is too light
QPalette p = m_outputWindow->palette();
@@ -254,7 +212,6 @@ void CompileOutputWindow::appendText(const QString &text, BuildStep::OutputForma
void CompileOutputWindow::clearContents()
{
m_outputWindow->clear();
- m_outputWindow->clearTasks();
m_taskPositions.clear();
}
@@ -287,22 +244,17 @@ bool CompileOutputWindow::canNavigate() const
return false;
}
-void CompileOutputWindow::registerPositionOf(const Task &task, int linkedOutputLines, int skipLines)
+void CompileOutputWindow::registerPositionOf(const Task &task, int linkedOutputLines, int skipLines,
+ int offset)
{
if (linkedOutputLines <= 0)
return;
- const int charNumber = m_outputWindow->document()->characterCount();
- if (charNumber > m_outputWindow->maxCharCount())
- return;
-
- const int blocknumber = m_outputWindow->document()->blockCount();
- const int startLine = blocknumber - linkedOutputLines + 1 - skipLines;
- const int endLine = blocknumber - skipLines;
- m_taskPositions.insert(task.taskId, qMakePair(startLine, endLine));
+ const int blocknumber = m_outputWindow->document()->blockCount() - offset - 1;
+ const int firstLine = blocknumber - linkedOutputLines - skipLines;
+ const int lastLine = firstLine + linkedOutputLines - 1;
- for (int i = startLine; i <= endLine; ++i)
- m_outputWindow->addTask(task, i);
+ m_taskPositions.insert(task.taskId, qMakePair(firstLine, lastLine));
}
bool CompileOutputWindow::knowsPositionOf(const Task &task)
@@ -340,6 +292,11 @@ void CompileOutputWindow::setSettings(const CompileOutputSettings &settings)
updateFromSettings();
}
+Utils::OutputFormatter *CompileOutputWindow::outputFormatter() const
+{
+ return m_outputWindow->outputFormatter();
+}
+
void CompileOutputWindow::updateFilter()
{
m_outputWindow->updateFilterProperties(filterText(), filterCaseSensitivity(),
@@ -415,5 +372,3 @@ CompileOutputSettingsPage::CompileOutputSettingsPage()
} // Internal
} // ProjectExplorer
-
-#include "compileoutputwindow.moc"
diff --git a/src/plugins/projectexplorer/compileoutputwindow.h b/src/plugins/projectexplorer/compileoutputwindow.h
index adea3aca802..caed6e8d66c 100644
--- a/src/plugins/projectexplorer/compileoutputwindow.h
+++ b/src/plugins/projectexplorer/compileoutputwindow.h
@@ -37,6 +37,9 @@ QT_BEGIN_NAMESPACE
class QToolButton;
QT_END_NAMESPACE
+namespace Core { class OutputWindow; }
+namespace Utils { class OutputFormatter; }
+
namespace ProjectExplorer {
class Task;
@@ -70,7 +73,7 @@ public:
void appendText(const QString &text, BuildStep::OutputFormat format);
- void registerPositionOf(const Task &task, int linkedOutputLines, int skipLines);
+ void registerPositionOf(const Task &task, int linkedOutputLines, int skipLines, int offset = 0);
bool knowsPositionOf(const Task &task);
void showPositionOf(const Task &task);
@@ -79,6 +82,8 @@ public:
const CompileOutputSettings &settings() const { return m_settings; }
void setSettings(const CompileOutputSettings &settings);
+ Utils::OutputFormatter *outputFormatter() const;
+
private:
void updateFilter() override;
@@ -86,7 +91,7 @@ private:
void storeSettings() const;
void updateFromSettings();
- CompileOutputTextEdit *m_outputWindow;
+ Core::OutputWindow *m_outputWindow;
QHash<unsigned int, QPair<int, int>> m_taskPositions;
ShowOutputTaskHandler *m_handler;
QToolButton *m_cancelBuildButton;
diff --git a/src/plugins/projectexplorer/customparser.cpp b/src/plugins/projectexplorer/customparser.cpp
index cff4893f760..dfd588fe201 100644
--- a/src/plugins/projectexplorer/customparser.cpp
+++ b/src/plugins/projectexplorer/customparser.cpp
@@ -129,45 +129,51 @@ Core::Id CustomParser::id()
return Core::Id("ProjectExplorer.OutputParser.Custom");
}
-OutputTaskParser::Status CustomParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result CustomParser::handleLine(const QString &line, OutputFormat type)
{
const CustomParserExpression::CustomParserChannel channel = type == StdErrFormat
? CustomParserExpression::ParseStdErrChannel
: CustomParserExpression::ParseStdOutChannel;
- if (parseLine(line, channel))
- return Status::Done;
- return Status::NotHandled;
+ return parseLine(line, channel);
}
-bool CustomParser::hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
- const CustomParserExpression &expression, Task::TaskType taskType)
+OutputLineParser::Result CustomParser::hasMatch(
+ const QString &line,
+ CustomParserExpression::CustomParserChannel channel,
+ const CustomParserExpression &expression,
+ Task::TaskType taskType
+ )
{
if (!(channel & expression.channel()))
- return false;
+ return Status::NotHandled;
if (expression.pattern().isEmpty())
- return false;
+ return Status::NotHandled;
const QRegularExpressionMatch match = expression.match(line);
if (!match.hasMatch())
- return false;
+ return Status::NotHandled;
const FilePath fileName = absoluteFilePath(FilePath::fromString(
match.captured(expression.fileNameCap())));
const int lineNumber = match.captured(expression.lineNumberCap()).toInt();
const QString message = match.captured(expression.messageCap());
-
- emit addTask(CompileTask(taskType, message, fileName, lineNumber), 1);
- return true;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, fileName, lineNumber, match,
+ expression.fileNameCap());
+ scheduleTask(CompileTask(taskType, message, fileName, lineNumber), 1);
+ return Status::Done;
}
-bool CustomParser::parseLine(const QString &rawLine, CustomParserExpression::CustomParserChannel channel)
+OutputLineParser::Result CustomParser::parseLine(
+ const QString &rawLine,
+ CustomParserExpression::CustomParserChannel channel
+ )
{
const QString line = rawLine.trimmed();
-
- if (hasMatch(line, channel, m_error, Task::Error))
- return true;
-
+ const Result res = hasMatch(line, channel, m_error, Task::Error);
+ if (res.status != Status::NotHandled)
+ return res;
return hasMatch(line, channel, m_warning, Task::Warning);
}
diff --git a/src/plugins/projectexplorer/customparser.h b/src/plugins/projectexplorer/customparser.h
index a7e7d15d7f6..00069f117f6 100644
--- a/src/plugins/projectexplorer/customparser.h
+++ b/src/plugins/projectexplorer/customparser.h
@@ -91,11 +91,11 @@ public:
static Core::Id id();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
- bool hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
- const CustomParserExpression &expression, Task::TaskType taskType);
- bool parseLine(const QString &rawLine, CustomParserExpression::CustomParserChannel channel);
+ Result hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
+ const CustomParserExpression &expression, Task::TaskType taskType);
+ Result parseLine(const QString &rawLine, CustomParserExpression::CustomParserChannel channel);
CustomParserExpression m_error;
CustomParserExpression m_warning;
diff --git a/src/plugins/projectexplorer/customtoolchain.cpp b/src/plugins/projectexplorer/customtoolchain.cpp
index 8c95e58921a..abe682a48e5 100644
--- a/src/plugins/projectexplorer/customtoolchain.cpp
+++ b/src/plugins/projectexplorer/customtoolchain.cpp
@@ -196,7 +196,7 @@ QStringList CustomToolChain::suggestedMkspecList() const
return m_mkspecs;
}
-QList<OutputTaskParser *> CustomToolChain::createOutputParsers() const
+QList<Utils::OutputLineParser *> CustomToolChain::createOutputParsers() const
{
if (m_outputParserId == GccParser::id())
return GccParser::gccParserSuite();
diff --git a/src/plugins/projectexplorer/customtoolchain.h b/src/plugins/projectexplorer/customtoolchain.h
index 8274241695c..dc57fe35032 100644
--- a/src/plugins/projectexplorer/customtoolchain.h
+++ b/src/plugins/projectexplorer/customtoolchain.h
@@ -84,7 +84,7 @@ public:
const Utils::Environment &env) const override;
void addToEnvironment(Utils::Environment &env) const override;
QStringList suggestedMkspecList() const override;
- QList<OutputTaskParser *> createOutputParsers() const override;
+ QList<Utils::OutputLineParser *> createOutputParsers() const override;
QStringList headerPathsList() const;
void setHeaderPaths(const QStringList &list);
diff --git a/src/plugins/projectexplorer/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp
index a0bcf92fd6f..2e55e9178f9 100644
--- a/src/plugins/projectexplorer/gccparser.cpp
+++ b/src/plugins/projectexplorer/gccparser.cpp
@@ -66,7 +66,7 @@ Core::Id GccParser::id()
return Core::Id("ProjectExplorer.OutputParser.Gcc");
}
-QList<OutputTaskParser *> GccParser::gccParserSuite()
+QList<OutputLineParser *> GccParser::gccParserSuite()
{
return {new GccParser, new Internal::LldParser, new LdParser};
}
@@ -84,7 +84,7 @@ void GccParser::flush()
return;
Task t = m_currentTask;
m_currentTask.clear();
- emit addTask(t, m_lines, 1);
+ scheduleTask(t, m_lines, 1);
m_lines = 0;
}
@@ -107,11 +107,9 @@ void GccParser::amendDescription(const QString &desc, bool monospaced)
return;
}
-OutputTaskParser::Status GccParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result GccParser::handleLine(const QString &line, OutputFormat type)
{
if (type == StdOutFormat) {
- // TODO: The "flush on channel switch" logic could possibly also done centrally.
- // But see MSVC with the stdout/stderr switches because of jom
flush();
return Status::NotHandled;
}
@@ -146,7 +144,6 @@ OutputTaskParser::Status GccParser::handleLine(const QString &line, OutputFormat
match = m_regExp.match(lne);
if (match.hasMatch()) {
- Utils::FilePath filename = Utils::FilePath::fromUserInput(match.captured(1));
int lineno = match.captured(3).toInt();
Task::TaskType type = Task::Unknown;
QString description = match.captured(8);
@@ -161,17 +158,21 @@ OutputTaskParser::Status GccParser::handleLine(const QString &line, OutputFormat
if (match.captured(5).startsWith(QLatin1Char('#')))
description = match.captured(5) + description;
- newTask(CompileTask(type, description, absoluteFilePath(filename), lineno));
- return Status::InProgress;
+ const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineno, match, 1);
+ newTask(CompileTask(type, description, filePath, lineno));
+ return {Status::InProgress, linkSpecs};
}
match = m_regExpIncluded.match(lne);
if (match.hasMatch()) {
- newTask(CompileTask(Task::Unknown,
- lne.trimmed() /* description */,
- absoluteFilePath(Utils::FilePath::fromUserInput(match.captured(1))),
- match.captured(3).toInt() /* linenumber */));
- return Status::InProgress;
+ const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
+ const int lineNo = match.captured(3).toInt();
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 1);
+ newTask(CompileTask(Task::Unknown, lne.trimmed() /* description */, filePath, lineNo));
+ return {Status::InProgress, linkSpecs};
} else if (lne.startsWith(' ') && !m_currentTask.isNull()) {
amendDescription(lne, true);
return Status::InProgress;
@@ -681,8 +682,7 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< (Tasks()
<< CompileTask(Task::Unknown,
"In file included from <command-line>:0:0:",
- FilePath::fromUserInput("<command-line>"),
- 0)
+ FilePath::fromUserInput("<command-line>"))
<< CompileTask(Task::Warning,
"\"STUPID_DEFINE\" redefined",
FilePath::fromUserInput("./mw.h"),
@@ -1009,8 +1009,7 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
<< (Tasks()
<< CompileTask(Task::Unknown,
"Note: No relevant classes found. No output generated.",
- FilePath::fromUserInput("/home/qtwebkithelpviewer.h"),
- 0))
+ FilePath::fromUserInput("/home/qtwebkithelpviewer.h")))
<< QString();
QTest::newRow("GCC 9 output")
diff --git a/src/plugins/projectexplorer/gccparser.h b/src/plugins/projectexplorer/gccparser.h
index 46b4de42d1c..76afb536684 100644
--- a/src/plugins/projectexplorer/gccparser.h
+++ b/src/plugins/projectexplorer/gccparser.h
@@ -42,7 +42,7 @@ public:
static Core::Id id();
- static QList<OutputTaskParser *> gccParserSuite();
+ static QList<OutputLineParser *> gccParserSuite();
protected:
void newTask(const Task &task);
@@ -51,7 +51,7 @@ protected:
void amendDescription(const QString &desc, bool monospaced);
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
QRegularExpression m_regExp;
QRegularExpression m_regExpIncluded;
diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp
index 22054d6828a..81a0b015b0f 100644
--- a/src/plugins/projectexplorer/gcctoolchain.cpp
+++ b/src/plugins/projectexplorer/gcctoolchain.cpp
@@ -731,7 +731,7 @@ FilePath GccToolChain::makeCommand(const Environment &environment) const
return tmp.isEmpty() ? FilePath::fromString("make") : tmp;
}
-QList<OutputTaskParser *> GccToolChain::createOutputParsers() const
+QList<OutputLineParser *> GccToolChain::createOutputParsers() const
{
return GccParser::gccParserSuite();
}
@@ -1628,7 +1628,7 @@ LanguageExtensions ClangToolChain::defaultLanguageExtensions() const
return LanguageExtension::Gnu;
}
-QList<OutputTaskParser *> ClangToolChain::createOutputParsers() const
+QList<OutputLineParser *> ClangToolChain::createOutputParsers() const
{
return ClangParser::clangParserSuite();
}
@@ -1898,7 +1898,7 @@ LanguageExtensions LinuxIccToolChain::languageExtensions(const QStringList &cxxf
return extensions;
}
-QList<OutputTaskParser *> LinuxIccToolChain::createOutputParsers() const
+QList<OutputLineParser *> LinuxIccToolChain::createOutputParsers() const
{
return LinuxIccParser::iccParserSuite();
}
diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h
index 4e22ba05efd..72c693ea2cc 100644
--- a/src/plugins/projectexplorer/gcctoolchain.h
+++ b/src/plugins/projectexplorer/gcctoolchain.h
@@ -94,7 +94,7 @@ public:
void addToEnvironment(Utils::Environment &env) const override;
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
QStringList suggestedMkspecList() const override;
- QList<OutputTaskParser *> createOutputParsers() const override;
+ QList<Utils::OutputLineParser *> createOutputParsers() const override;
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &data) override;
@@ -226,7 +226,7 @@ public:
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
Utils::WarningFlags warningFlags(const QStringList &cflags) const override;
- QList<OutputTaskParser *> createOutputParsers() const override;
+ QList<Utils::OutputLineParser *> createOutputParsers() const override;
QStringList suggestedMkspecList() const override;
void addToEnvironment(Utils::Environment &env) const override;
@@ -286,7 +286,7 @@ class PROJECTEXPLORER_EXPORT LinuxIccToolChain : public GccToolChain
public:
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
- QList<OutputTaskParser *> createOutputParsers() const override;
+ QList<Utils::OutputLineParser *> createOutputParsers() const override;
QStringList suggestedMkspecList() const override;
diff --git a/src/plugins/projectexplorer/gnumakeparser.cpp b/src/plugins/projectexplorer/gnumakeparser.cpp
index 53d0db07a8a..6bb7442e0ca 100644
--- a/src/plugins/projectexplorer/gnumakeparser.cpp
+++ b/src/plugins/projectexplorer/gnumakeparser.cpp
@@ -100,10 +100,10 @@ void GnuMakeParser::emitTask(const ProjectExplorer::Task &task)
{
if (task.type == Task::Error) // Assume that all make errors will be follow up errors.
m_suppressIssues = true;
- emit addTask(task, 1, 0);
+ scheduleTask(task, 1, 0);
}
-OutputTaskParser::Status GnuMakeParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result GnuMakeParser::handleLine(const QString &line, OutputFormat type)
{
const QString lne = rightTrimmed(line);
if (type == StdOutFormat) {
@@ -119,19 +119,21 @@ OutputTaskParser::Status GnuMakeParser::handleLine(const QString &line, OutputFo
}
QRegularExpressionMatch match = m_errorInMakefile.match(lne);
if (match.hasMatch()) {
- Result res = parseDescription(match.captured(5));
+ ProjectExplorer::Result res = parseDescription(match.captured(5));
if (res.isFatal)
++m_fatalErrorCount;
+ LinkSpecs linkSpecs;
if (!m_suppressIssues) {
- emitTask(BuildSystemTask(res.type, res.description,
- absoluteFilePath(FilePath::fromUserInput(match.captured(1))),
- match.captured(4).toInt() /* line */));
+ const FilePath file = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
+ const int lineNo = match.captured(4).toInt();
+ addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, match, 1);
+ emitTask(BuildSystemTask(res.type, res.description, file, lineNo));
}
- return Status::Done;
+ return {Status::Done, linkSpecs};
}
match = m_makeLine.match(lne);
if (match.hasMatch()) {
- Result res = parseDescription(match.captured(6));
+ ProjectExplorer::Result res = parseDescription(match.captured(6));
if (res.isFatal)
++m_fatalErrorCount;
if (!m_suppressIssues)
diff --git a/src/plugins/projectexplorer/gnumakeparser.h b/src/plugins/projectexplorer/gnumakeparser.h
index 5a2f247a4fd..21c77213b19 100644
--- a/src/plugins/projectexplorer/gnumakeparser.h
+++ b/src/plugins/projectexplorer/gnumakeparser.h
@@ -40,7 +40,7 @@ public:
explicit GnuMakeParser();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
bool hasFatalErrors() const override;
void emitTask(const ProjectExplorer::Task &task);
diff --git a/src/plugins/projectexplorer/ioutputparser.cpp b/src/plugins/projectexplorer/ioutputparser.cpp
index 98f39fb4db1..72d4e28fe11 100644
--- a/src/plugins/projectexplorer/ioutputparser.cpp
+++ b/src/plugins/projectexplorer/ioutputparser.cpp
@@ -24,15 +24,9 @@
****************************************************************************/
#include "ioutputparser.h"
-#include "task.h"
-
-#include <utils/algorithm.h>
-#include <utils/fileinprojectfinder.h>
-#include <utils/synchronousprocess.h>
-#include <QDir>
-#include <QFileInfo>
-#include <QPointer>
+#include "task.h"
+#include "taskhub.h"
/*!
@@ -76,296 +70,32 @@ namespace ProjectExplorer {
class OutputTaskParser::Private
{
public:
- Utils::FilePaths searchDirs;
- Utils::FileInProjectFinder *fileFinder = nullptr;
- QPointer<const OutputTaskParser> redirectionDetector;
- bool skipFileExistsCheck = false;
+ QList<TaskInfo> scheduledTasks;
};
-OutputTaskParser::OutputTaskParser() : d(new Private)
-{
-}
+OutputTaskParser::OutputTaskParser() : d(new Private) { }
OutputTaskParser::~OutputTaskParser() { delete d; }
-void OutputTaskParser::addSearchDir(const Utils::FilePath &dir)
-{
- d->searchDirs << dir;
-}
-
-void OutputTaskParser::dropSearchDir(const Utils::FilePath &dir)
-{
- const int idx = d->searchDirs.lastIndexOf(dir);
-
- // TODO: This apparently triggers. Find out why and either remove the assertion (if it's legit)
- // or fix the culprit.
- QTC_ASSERT(idx != -1, return);
-
- d->searchDirs.removeAt(idx);
-}
-
-const Utils::FilePaths OutputTaskParser::searchDirectories() const
-{
- return d->searchDirs;
-}
-
-// The redirection mechanism is needed for broken build tools (e.g. xcodebuild) that get invoked
-// indirectly as part of the build process and redirect their child processes' stderr output
-// to stdout. A parser might be able to detect this condition and inform interested
-// other parsers that they need to interpret stdout data as stderr.
-void OutputTaskParser::setRedirectionDetector(const OutputTaskParser *detector)
-{
- d->redirectionDetector = detector;
-}
-
-bool OutputTaskParser::needsRedirection() const
-{
- return d->redirectionDetector && (d->redirectionDetector->hasDetectedRedirection()
- || d->redirectionDetector->needsRedirection());
-}
-
-void OutputTaskParser::setFileFinder(Utils::FileInProjectFinder *finder)
-{
- d->fileFinder = finder;
-}
-
-Utils::FilePath OutputTaskParser::absoluteFilePath(const Utils::FilePath &filePath)
-{
- if (filePath.isEmpty() || filePath.toFileInfo().isAbsolute())
- return filePath;
- Utils::FilePaths candidates;
- for (const Utils::FilePath &dir : searchDirectories()) {
- const Utils::FilePath candidate = dir.pathAppended(filePath.toString());
- if (candidate.exists() || d->skipFileExistsCheck)
- candidates << candidate;
- }
- if (candidates.count() == 1)
- return Utils::FilePath::fromString(QDir::cleanPath(candidates.first().toString()));
-
- QString fp = filePath.toString();
- while (fp.startsWith("../"))
- fp.remove(0, 3);
- bool found = false;
- candidates = d->fileFinder->findFile(QUrl::fromLocalFile(fp), &found);
- if (found && candidates.size() == 1)
- return candidates.first();
-
- return filePath;
-}
-
-QString OutputTaskParser::rightTrimmed(const QString &in)
-{
- int pos = in.length();
- for (; pos > 0; --pos) {
- if (!in.at(pos - 1).isSpace())
- break;
- }
- return in.mid(0, pos);
-}
-
-#ifdef WITH_TESTS
-void OutputTaskParser::skipFileExistsCheck()
-{
- d->skipFileExistsCheck = true;
-}
-#endif
-
-class IOutputParser::OutputChannelState
-{
-public:
- using LineHandler = void (IOutputParser::*)(const QString &line);
-
- OutputChannelState(IOutputParser *parser, Utils::OutputFormat type)
- : parser(parser), type(type) {}
-
- void handleData(const QString &newData)
- {
- pendingData += newData;
- pendingData = Utils::SynchronousProcess::normalizeNewlines(pendingData);
- while (true) {
- const int eolPos = pendingData.indexOf('\n');
- if (eolPos == -1)
- break;
- const QString line = pendingData.left(eolPos + 1);
- pendingData.remove(0, eolPos + 1);
- parser->handleLine(line, type);
- }
- }
-
- void flush()
- {
- if (!pendingData.isEmpty()) {
- parser->handleLine(pendingData, type);
- pendingData.clear();
- }
- }
-
- IOutputParser * const parser;
- const Utils::OutputFormat type;
- QString pendingData;
-};
-
-class IOutputParser::IOutputParserPrivate
-{
-public:
- IOutputParserPrivate(IOutputParser *parser)
- : stdoutState(parser, Utils::StdOutFormat),
- stderrState(parser, Utils::StdErrFormat)
- {}
-
- QList<OutputTaskParser *> lineParsers;
- OutputTaskParser *nextParser = nullptr;
- QList<Filter> filters;
- Utils::FileInProjectFinder fileFinder;
- OutputChannelState stdoutState;
- OutputChannelState stderrState;
-};
-
-IOutputParser::IOutputParser() : d(new IOutputParserPrivate(this))
-{
-}
-
-IOutputParser::~IOutputParser()
-{
- clear();
- delete d;
-}
-
-void IOutputParser::handleStdout(const QString &data)
-{
- d->stdoutState.handleData(data);
-}
-
-void IOutputParser::handleStderr(const QString &data)
-{
- d->stderrState.handleData(data);
-}
-
-void IOutputParser::handleLine(const QString &line, Utils::OutputFormat type)
-{
- const QString cleanLine = filteredLine(line);
- if (d->nextParser) {
- switch (d->nextParser->handleLine(cleanLine, outputTypeForParser(d->nextParser, type))) {
- case OutputTaskParser::Status::Done:
- d->nextParser = nullptr;
- return;
- case OutputTaskParser::Status::InProgress:
- return;
- case OutputTaskParser::Status::NotHandled:
- d->nextParser = nullptr;
- break;
- }
- }
- QTC_CHECK(!d->nextParser);
- for (OutputTaskParser * const lineParser : d->lineParsers) {
- switch (lineParser->handleLine(cleanLine, outputTypeForParser(lineParser, type))) {
- case OutputTaskParser::Status::Done:
- return;
- case OutputTaskParser::Status::InProgress:
- d->nextParser = lineParser;
- return;
- case OutputTaskParser::Status::NotHandled:
- break;
- }
- }
-}
-
-QString IOutputParser::filteredLine(const QString &line) const
-{
- QString l = line;
- for (const IOutputParser::Filter &f : qAsConst(d->filters))
- l = f(l);
- return l;
-}
-
-void IOutputParser::setupLineParser(OutputTaskParser *parser)
-{
- parser->setFileFinder(&d->fileFinder);
- connect(parser, &OutputTaskParser::addTask, this, &IOutputParser::addTask);
- connect(parser, &OutputTaskParser::newSearchDir, this, &IOutputParser::addSearchDir);
- connect(parser, &OutputTaskParser::searchDirExpired, this, &IOutputParser::dropSearchDir);
-}
-
-bool IOutputParser::hasFatalErrors() const
-{
- return Utils::anyOf(d->lineParsers, [](const OutputTaskParser *p) {
- return p->hasFatalErrors();
- });
-}
-
-void IOutputParser::flush()
-{
- d->stdoutState.flush();
- d->stderrState.flush();
- for (OutputTaskParser * const p : qAsConst(d->lineParsers))
- p->flush();
-}
-
-void IOutputParser::clear()
-{
- d->nextParser = nullptr;
- d->filters.clear();
- qDeleteAll(d->lineParsers);
- d->lineParsers.clear();
- d->stdoutState.pendingData.clear();
- d->stderrState.pendingData.clear();
- d->fileFinder = Utils::FileInProjectFinder();
-}
-
-void IOutputParser::addLineParser(OutputTaskParser *parser)
-{
- setupLineParser(parser);
- d->lineParsers << parser;
-}
-
-void IOutputParser::addLineParsers(const QList<OutputTaskParser *> &parsers)
-{
- for (OutputTaskParser * const p : qAsConst(parsers))
- addLineParser(p);
-}
-
-void IOutputParser::setLineParsers(const QList<OutputTaskParser *> &parsers)
-{
- qDeleteAll(d->lineParsers);
- d->lineParsers.clear();
- addLineParsers(parsers);
-}
-
-void IOutputParser::setFileFinder(const Utils::FileInProjectFinder &finder)
-{
- d->fileFinder = finder;
-}
-
-#ifdef WITH_TESTS
-QList<OutputTaskParser *> IOutputParser::lineParsers() const
-{
- return d->lineParsers;
-}
-#endif // WITH_TESTS
-
-void IOutputParser::addFilter(const Filter &filter)
-{
- d->filters << filter;
-}
-
-void IOutputParser::addSearchDir(const Utils::FilePath &dir)
+const QList<OutputTaskParser::TaskInfo> OutputTaskParser::taskInfo() const
{
- for (OutputTaskParser * const p : qAsConst(d->lineParsers))
- p->addSearchDir(dir);
+ return d->scheduledTasks;
}
-void IOutputParser::dropSearchDir(const Utils::FilePath &dir)
+void OutputTaskParser::scheduleTask(const Task &task, int outputLines, int skippedLines)
{
- for (OutputTaskParser * const p : qAsConst(d->lineParsers))
- p->dropSearchDir(dir);
+ TaskInfo ts(task, outputLines, skippedLines);
+ if (ts.task.type == Task::Error && demoteErrorsToWarnings())
+ ts.task.type = Task::Warning;
+ d->scheduledTasks << ts;
+ QTC_CHECK(d->scheduledTasks.size() <= 2);
}
-Utils::OutputFormat IOutputParser::outputTypeForParser(const OutputTaskParser *parser,
- Utils::OutputFormat type) const
+void OutputTaskParser::runPostPrintActions()
{
- if (type == Utils::StdOutFormat && parser->needsRedirection())
- return Utils::StdErrFormat;
- return type;
+ for (const TaskInfo &t : qAsConst(d->scheduledTasks))
+ TaskHub::addTask(t.task);
+ d->scheduledTasks.clear();
}
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/ioutputparser.h b/src/plugins/projectexplorer/ioutputparser.h
index efe717f1f0e..9a8ce59be1b 100644
--- a/src/plugins/projectexplorer/ioutputparser.h
+++ b/src/plugins/projectexplorer/ioutputparser.h
@@ -28,103 +28,38 @@
#include "projectexplorer_export.h"
#include "buildstep.h"
-#include <utils/fileutils.h>
-#include <utils/outputformat.h>
+#include <utils/outputformatter.h>
#include <functional>
-namespace Utils { class FileInProjectFinder; }
-
namespace ProjectExplorer {
class Task;
-class PROJECTEXPLORER_EXPORT OutputTaskParser : public QObject
+class PROJECTEXPLORER_EXPORT OutputTaskParser : public Utils::OutputLineParser
{
Q_OBJECT
public:
OutputTaskParser();
~OutputTaskParser() override;
- void addSearchDir(const Utils::FilePath &dir);
- void dropSearchDir(const Utils::FilePath &dir);
- const Utils::FilePaths searchDirectories() const;
-
- enum class Status { Done, InProgress, NotHandled };
- virtual Status handleLine(const QString &line, Utils::OutputFormat type) = 0;
-
- virtual bool hasFatalErrors() const { return false; }
- virtual void flush() {}
-
- void setRedirectionDetector(const OutputTaskParser *detector);
- bool needsRedirection() const;
- virtual bool hasDetectedRedirection() const { return false; }
-
- void setFileFinder(Utils::FileInProjectFinder *finder);
-
-#ifdef WITH_TESTS
- void skipFileExistsCheck();
-#endif
-
-signals:
- void newSearchDir(const Utils::FilePath &dir);
- void searchDirExpired(const Utils::FilePath &dir);
- void addTask(const ProjectExplorer::Task &task, int linkedOutputLines = 0, int skipLines = 0);
+ class TaskInfo
+ {
+ public:
+ TaskInfo(const Task &t, int l, int s) : task(t), linkedLines(l), skippedLines(s) {}
+ Task task;
+ int linkedLines = 0;
+ int skippedLines = 0;
+ };
+ const QList<TaskInfo> taskInfo() const;
protected:
- static QString rightTrimmed(const QString &in);
- Utils::FilePath absoluteFilePath(const Utils::FilePath &filePath);
+ void scheduleTask(const Task &task, int outputLines, int skippedLines = 0);
private:
+ void runPostPrintActions() override;
+
class Private;
Private * const d;
};
-// Documentation inside.
-class PROJECTEXPLORER_EXPORT IOutputParser : public QObject
-{
- Q_OBJECT
-public:
- IOutputParser();
- ~IOutputParser() override;
-
- void handleStdout(const QString &data);
- void handleStderr(const QString &data);
-
- bool hasFatalErrors() const;
-
- using Filter = std::function<QString(const QString &)>;
- void addFilter(const Filter &filter);
-
- // Forwards to line parsers. Add those before.
- void addSearchDir(const Utils::FilePath &dir);
- void dropSearchDir(const Utils::FilePath &dir);
-
- void flush();
- void clear();
-
- void addLineParser(OutputTaskParser *parser);
- void addLineParsers(const QList<OutputTaskParser *> &parsers);
- void setLineParsers(const QList<OutputTaskParser *> &parsers);
-
- void setFileFinder(const Utils::FileInProjectFinder &finder);
-
-#ifdef WITH_TESTS
- QList<OutputTaskParser *> lineParsers() const;
-#endif
-
-signals:
- void addTask(const ProjectExplorer::Task &task, int linkedOutputLines = 0, int skipLines = 0);
-
-private:
- void handleLine(const QString &line, Utils::OutputFormat type);
- QString filteredLine(const QString &line) const;
- void setupLineParser(OutputTaskParser *parser);
- Utils::OutputFormat outputTypeForParser(const OutputTaskParser *parser,
- Utils::OutputFormat type) const;
-
- class OutputChannelState;
- class IOutputParserPrivate;
- IOutputParserPrivate * const d;
-};
-
} // namespace ProjectExplorer
diff --git a/src/plugins/projectexplorer/kit.cpp b/src/plugins/projectexplorer/kit.cpp
index 0cd845e5d39..e8ff3cab483 100644
--- a/src/plugins/projectexplorer/kit.cpp
+++ b/src/plugins/projectexplorer/kit.cpp
@@ -559,9 +559,9 @@ void Kit::addToEnvironment(Environment &env) const
aspect->addToEnvironment(this, env);
}
-QList<OutputTaskParser *> Kit::createOutputParsers() const
+QList<OutputLineParser *> Kit::createOutputParsers() const
{
- QList<OutputTaskParser *> parsers{new OsParser};
+ QList<OutputLineParser *> parsers{new OsParser};
for (KitAspect *aspect : KitManager::kitAspects())
parsers << aspect->createOutputParsers(this);
return parsers;
diff --git a/src/plugins/projectexplorer/kit.h b/src/plugins/projectexplorer/kit.h
index 8408eab788a..871e2265682 100644
--- a/src/plugins/projectexplorer/kit.h
+++ b/src/plugins/projectexplorer/kit.h
@@ -38,10 +38,10 @@
namespace Utils {
class Environment;
class MacroExpander;
+class OutputLineParser;
} // namespace Utils
namespace ProjectExplorer {
-class OutputTaskParser;
namespace Internal {
class KitManagerPrivate;
@@ -116,7 +116,7 @@ public:
bool isEqual(const Kit *other) const;
void addToEnvironment(Utils::Environment &env) const;
- QList<OutputTaskParser *> createOutputParsers() const;
+ QList<Utils::OutputLineParser *> createOutputParsers() const;
QString toHtml(const Tasks &additional = Tasks(), const QString &extraText = QString()) const;
Kit *clone(bool keepName = false) const;
diff --git a/src/plugins/projectexplorer/kitinformation.cpp b/src/plugins/projectexplorer/kitinformation.cpp
index 590a777b143..9d67eed17a0 100644
--- a/src/plugins/projectexplorer/kitinformation.cpp
+++ b/src/plugins/projectexplorer/kitinformation.cpp
@@ -557,7 +557,7 @@ void ToolChainKitAspect::addToMacroExpander(Kit *kit, Utils::MacroExpander *expa
});
}
-QList<OutputTaskParser *> ToolChainKitAspect::createOutputParsers(const Kit *k) const
+QList<Utils::OutputLineParser *> ToolChainKitAspect::createOutputParsers(const Kit *k) const
{
for (const Core::Id langId : {Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID}) {
if (const ToolChain * const tc = toolChain(k, langId))
diff --git a/src/plugins/projectexplorer/kitinformation.h b/src/plugins/projectexplorer/kitinformation.h
index 6b5c77dc979..d8558b88616 100644
--- a/src/plugins/projectexplorer/kitinformation.h
+++ b/src/plugins/projectexplorer/kitinformation.h
@@ -85,7 +85,7 @@ public:
void addToEnvironment(const Kit *k, Utils::Environment &env) const override;
void addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const override;
- QList<OutputTaskParser *> createOutputParsers(const Kit *k) const override;
+ QList<Utils::OutputLineParser *> createOutputParsers(const Kit *k) const override;
QSet<Core::Id> availableFeatures(const Kit *k) const override;
static Core::Id id();
diff --git a/src/plugins/projectexplorer/kitmanager.cpp b/src/plugins/projectexplorer/kitmanager.cpp
index 5d82fe6e284..1eab4633f54 100644
--- a/src/plugins/projectexplorer/kitmanager.cpp
+++ b/src/plugins/projectexplorer/kitmanager.cpp
@@ -677,7 +677,7 @@ void KitAspect::addToEnvironment(const Kit *k, Environment &env) const
Q_UNUSED(env)
}
-QList<OutputTaskParser *> KitAspect::createOutputParsers(const Kit *k) const
+QList<OutputLineParser *> KitAspect::createOutputParsers(const Kit *k) const
{
Q_UNUSED(k)
return {};
diff --git a/src/plugins/projectexplorer/kitmanager.h b/src/plugins/projectexplorer/kitmanager.h
index 31565eec5c5..f55380c5733 100644
--- a/src/plugins/projectexplorer/kitmanager.h
+++ b/src/plugins/projectexplorer/kitmanager.h
@@ -42,11 +42,11 @@ namespace Utils {
class Environment;
class FilePath;
class MacroExpander;
+class OutputLineParser;
} // namespace Utils
namespace ProjectExplorer {
class Task;
-class OutputTaskParser;
class KitAspectWidget;
class KitManager;
@@ -91,7 +91,7 @@ public:
virtual KitAspectWidget *createConfigWidget(Kit *) const = 0;
virtual void addToEnvironment(const Kit *k, Utils::Environment &env) const;
- virtual QList<OutputTaskParser *> createOutputParsers(const Kit *k) const;
+ virtual QList<Utils::OutputLineParser *> createOutputParsers(const Kit *k) const;
virtual QString displayNamePostfix(const Kit *k) const;
diff --git a/src/plugins/projectexplorer/ldparser.cpp b/src/plugins/projectexplorer/ldparser.cpp
index 55ef296bf82..135401dd1c4 100644
--- a/src/plugins/projectexplorer/ldparser.cpp
+++ b/src/plugins/projectexplorer/ldparser.cpp
@@ -54,7 +54,7 @@ LdParser::LdParser()
QTC_CHECK(m_regExpGccNames.isValid());
}
-OutputTaskParser::Status LdParser::handleLine(const QString &line, Utils::OutputFormat type)
+Utils::OutputLineParser::Result LdParser::handleLine(const QString &line, Utils::OutputFormat type)
{
if (type != Utils::StdErrFormat)
return Status::NotHandled;
@@ -80,20 +80,24 @@ OutputTaskParser::Status LdParser::handleLine(const QString &line, Utils::Output
m_incompleteTask.description.append('\n').append(lne);
static const QRegularExpression locRegExp(" (?<symbol>\\S+) in (?<file>\\S+)");
const QRegularExpressionMatch match = locRegExp.match(lne);
- if (match.hasMatch())
- m_incompleteTask.setFile(Utils::FilePath::fromString(match.captured("file")));
- return Status::InProgress;
+ LinkSpecs linkSpecs;
+ if (match.hasMatch()) {
+ m_incompleteTask.setFile(absoluteFilePath(Utils::FilePath::fromString(
+ match.captured("file"))));
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_incompleteTask.file, 0, match, "file");
+ }
+ return {Status::InProgress, linkSpecs};
}
if (lne.startsWith("collect2:") || lne.startsWith("collect2.exe:")) {
- emit addTask(CompileTask(Task::Error, lne /* description */), 1);
+ scheduleTask(CompileTask(Task::Error, lne /* description */), 1);
return Status::Done;
}
QRegularExpressionMatch match = m_ranlib.match(lne);
if (match.hasMatch()) {
QString description = match.captured(2);
- emit addTask(CompileTask(Task::Warning, description), 1);
+ scheduleTask(CompileTask(Task::Warning, description), 1);
return Status::Done;
}
@@ -107,7 +111,7 @@ OutputTaskParser::Status LdParser::handleLine(const QString &line, Utils::Output
} else if (description.startsWith(QLatin1String("fatal: "))) {
description = description.mid(7);
}
- emit addTask(CompileTask(type, description), 1);
+ scheduleTask(CompileTask(type, description), 1);
return Status::Done;
}
@@ -117,12 +121,15 @@ OutputTaskParser::Status LdParser::handleLine(const QString &line, Utils::Output
int lineno = match.captured(7).toInt(&ok);
if (!ok)
lineno = -1;
- Utils::FilePath filename = Utils::FilePath::fromUserInput(match.captured(1));
+ Utils::FilePath filename
+ = absoluteFilePath(Utils::FilePath::fromUserInput(match.captured(1)));
+ int capIndex = 1;
const QString sourceFileName = match.captured(4);
if (!sourceFileName.isEmpty()
&& !sourceFileName.startsWith(QLatin1String("(.text"))
&& !sourceFileName.startsWith(QLatin1String("(.data"))) {
- filename = Utils::FilePath::fromUserInput(sourceFileName);
+ filename = absoluteFilePath(Utils::FilePath::fromUserInput(sourceFileName));
+ capIndex = 4;
}
QString description = match.captured(8).trimmed();
Task::TaskType type = Task::Error;
@@ -137,8 +144,10 @@ OutputTaskParser::Status LdParser::handleLine(const QString &line, Utils::Output
type = Task::Warning;
description = description.mid(9);
}
- emit addTask(CompileTask(type, description, absoluteFilePath(filename), lineno), 1);
- return Status::Done;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, filename, lineno, match, capIndex);
+ scheduleTask(CompileTask(type, description, filename, lineno), 1);
+ return {Status::Done, linkSpecs};
}
return Status::NotHandled;
@@ -150,5 +159,5 @@ void LdParser::flush()
return;
const Task t = m_incompleteTask;
m_incompleteTask.clear();
- emit addTask(t);
+ scheduleTask(t, 1);
}
diff --git a/src/plugins/projectexplorer/ldparser.h b/src/plugins/projectexplorer/ldparser.h
index fc3d9590759..56f94f52c70 100644
--- a/src/plugins/projectexplorer/ldparser.h
+++ b/src/plugins/projectexplorer/ldparser.h
@@ -39,7 +39,7 @@ class LdParser : public ProjectExplorer::OutputTaskParser
public:
LdParser();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
void flush() override;
QRegularExpression m_ranlib;
diff --git a/src/plugins/projectexplorer/linuxiccparser.cpp b/src/plugins/projectexplorer/linuxiccparser.cpp
index 812f10961ff..49bdbcdc2ad 100644
--- a/src/plugins/projectexplorer/linuxiccparser.cpp
+++ b/src/plugins/projectexplorer/linuxiccparser.cpp
@@ -65,7 +65,7 @@ LinuxIccParser::LinuxIccParser() :
QTC_CHECK(m_pchInfoLine.isValid());
}
-OutputTaskParser::Status LinuxIccParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result LinuxIccParser::handleLine(const QString &line, OutputFormat type)
{
if (type != Utils::StdErrFormat)
return Status::NotHandled;
@@ -81,10 +81,11 @@ OutputTaskParser::Status LinuxIccParser::handleLine(const QString &line, OutputF
type = Task::Error;
else if (category == QLatin1String("warning"))
type = Task::Warning;
- m_temporary = CompileTask(type,
- m_firstLine.cap(6).trimmed(),
- absoluteFilePath(Utils::FilePath::fromUserInput(m_firstLine.cap(1))),
- m_firstLine.cap(2).toInt());
+ const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(m_firstLine.cap(1)));
+ const int lineNo = m_firstLine.cap(2).toInt();
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, m_firstLine, 1);
+ m_temporary = CompileTask(type, m_firstLine.cap(6).trimmed(), filePath, lineNo);
m_lines = 1;
m_expectFirstLine = false;
@@ -107,7 +108,7 @@ OutputTaskParser::Status LinuxIccParser::handleLine(const QString &line, OutputF
}
if (!m_expectFirstLine && line.trimmed().isEmpty()) { // last Line
m_expectFirstLine = true;
- emit addTask(m_temporary, m_lines);
+ scheduleTask(m_temporary, m_lines);
m_temporary = Task();
return Status::Done;
}
@@ -129,7 +130,7 @@ Core::Id LinuxIccParser::id()
return Core::Id("ProjectExplorer.OutputParser.Icc");
}
-QList<OutputTaskParser *> LinuxIccParser::iccParserSuite()
+QList<OutputLineParser *> LinuxIccParser::iccParserSuite()
{
return {new LinuxIccParser, new Internal::LldParser, new LdParser};
}
@@ -140,7 +141,7 @@ void LinuxIccParser::flush()
return;
Task t = m_temporary;
m_temporary.clear();
- emit addTask(t, m_lines, 1);
+ scheduleTask(t, m_lines, 1);
}
#ifdef WITH_TESTS
@@ -237,7 +238,7 @@ void ProjectExplorerPlugin::testLinuxIccOutputParsers_data()
<< (Tasks()
<< CompileTask(Task::Unknown,
"Note: No relevant classes found. No output generated.",
- FilePath::fromUserInput("/home/qtwebkithelpviewer.h"), 0))
+ FilePath::fromUserInput("/home/qtwebkithelpviewer.h"), -1))
<< QString();
}
diff --git a/src/plugins/projectexplorer/linuxiccparser.h b/src/plugins/projectexplorer/linuxiccparser.h
index f5a1dd0096f..44ff094c05e 100644
--- a/src/plugins/projectexplorer/linuxiccparser.h
+++ b/src/plugins/projectexplorer/linuxiccparser.h
@@ -41,10 +41,10 @@ public:
static Core::Id id();
- static QList<OutputTaskParser *> iccParserSuite();
+ static QList<Utils::OutputLineParser *> iccParserSuite();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
void flush() override;
QRegExp m_firstLine;
diff --git a/src/plugins/projectexplorer/lldparser.cpp b/src/plugins/projectexplorer/lldparser.cpp
index c9384614897..aee20ea7957 100644
--- a/src/plugins/projectexplorer/lldparser.cpp
+++ b/src/plugins/projectexplorer/lldparser.cpp
@@ -35,14 +35,14 @@
namespace ProjectExplorer {
namespace Internal {
-OutputTaskParser::Status LldParser::handleLine(const QString &line, Utils::OutputFormat type)
+Utils::OutputLineParser::Result LldParser::handleLine(const QString &line, Utils::OutputFormat type)
{
if (type != Utils::StdErrFormat)
return Status::NotHandled;
const QString trimmedLine = rightTrimmed(line);
if (trimmedLine.contains("error:") && trimmedLine.contains("lld")) {
- emit addTask(CompileTask(Task::Error, trimmedLine));
+ scheduleTask(CompileTask(Task::Error, trimmedLine), 1);
return Status::Done;
}
static const QStringList prefixes{">>> referenced by ", ">>> defined at ", ">>> "};
@@ -65,11 +65,13 @@ OutputTaskParser::Status LldParser::handleLine(const QString &line, Utils::Outpu
else
filePathOffset = prefix.length();
const int filePathLen = locOffset == -1 ? -1 : locOffset - filePathOffset;
- const auto file = Utils::FilePath::fromUserInput(
- trimmedLine.mid(filePathOffset, filePathLen).trimmed());
- emit addTask(CompileTask(Task::Unknown, trimmedLine.mid(4).trimmed(),
- absoluteFilePath(file), lineNo));
- return Status::Done;
+ const auto file = absoluteFilePath(Utils::FilePath::fromUserInput(
+ trimmedLine.mid(filePathOffset, filePathLen).trimmed()));
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, filePathOffset, filePathLen);
+ scheduleTask(CompileTask(Task::Unknown, trimmedLine.mid(4).trimmed(),
+ file, lineNo), 1);
+ return {Status::Done, linkSpecs};
}
return Status::NotHandled;
}
diff --git a/src/plugins/projectexplorer/lldparser.h b/src/plugins/projectexplorer/lldparser.h
index d071d0264c2..f9bb4388aa9 100644
--- a/src/plugins/projectexplorer/lldparser.h
+++ b/src/plugins/projectexplorer/lldparser.h
@@ -32,7 +32,7 @@ namespace Internal {
class LldParser : public OutputTaskParser
{
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
};
} // namespace Internal
diff --git a/src/plugins/projectexplorer/makestep.cpp b/src/plugins/projectexplorer/makestep.cpp
index cd873d5ea75..ec5cafe6626 100644
--- a/src/plugins/projectexplorer/makestep.cpp
+++ b/src/plugins/projectexplorer/makestep.cpp
@@ -102,13 +102,17 @@ bool MakeStep::init()
// That is mostly so that rebuild works on an already clean project
setIgnoreReturnValue(isClean());
- setOutputParser(new GnuMakeParser());
- appendOutputParsers(target()->kit()->createOutputParsers());
- outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
-
return AbstractProcessStep::init();
}
+void MakeStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ formatter->addLineParser(new GnuMakeParser());
+ formatter->addLineParsers(target()->kit()->createOutputParsers());
+ formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
void MakeStep::setClean(bool clean)
{
m_clean = clean;
diff --git a/src/plugins/projectexplorer/makestep.h b/src/plugins/projectexplorer/makestep.h
index bd02090bec1..decc0b0fccd 100644
--- a/src/plugins/projectexplorer/makestep.h
+++ b/src/plugins/projectexplorer/makestep.h
@@ -54,6 +54,7 @@ public:
void setAvailableBuildTargets(const QStringList &buildTargets);
bool init() override;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
bool buildsTarget(const QString &target) const;
void setBuildTarget(const QString &target, bool on);
diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp
index 151fb52faa2..ac68bd3b679 100644
--- a/src/plugins/projectexplorer/msvcparser.cpp
+++ b/src/plugins/projectexplorer/msvcparser.cpp
@@ -105,7 +105,7 @@ Core::Id MsvcParser::id()
return Core::Id("ProjectExplorer.OutputParser.Msvc");
}
-OutputTaskParser::Status MsvcParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result MsvcParser::handleLine(const QString &line, OutputFormat type)
{
if (type == OutputFormat::StdOutFormat) {
QRegularExpressionMatch match = m_additionalInfoRegExp.match(line);
@@ -137,8 +137,9 @@ OutputTaskParser::Status MsvcParser::handleLine(const QString &line, OutputForma
return Status::InProgress;
}
- if (processCompileLine(line))
- return Status::InProgress;
+ const Result res = processCompileLine(line);
+ if (res.status != Status::NotHandled)
+ return res;
if (handleNmakeJomMessage(line, &m_lastTask)) {
m_lines = 1;
return Status::InProgress;
@@ -148,17 +149,20 @@ OutputTaskParser::Status MsvcParser::handleLine(const QString &line, OutputForma
+ match.captured(4).trimmed();
if (!match.captured(1).isEmpty())
description.chop(1); // Remove trailing quote
- m_lastTask = CompileTask(Task::Unknown, description,
- absoluteFilePath(FilePath::fromUserInput(match.captured(2))),
- match.captured(3).toInt() /* linenumber */);
+ const FilePath filePath = absoluteFilePath(FilePath::fromUserInput(match.captured(2)));
+ const int lineNo = match.captured(3).toInt();
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, match, 2);
+ m_lastTask = CompileTask(Task::Unknown, description, filePath, lineNo);
m_lines = 1;
- return Status::InProgress;
+ return {Status::InProgress, linkSpecs};
}
return Status::NotHandled;
}
- if (processCompileLine(line))
- return Status::InProgress;
+ const Result res = processCompileLine(line);
+ if (res.status != Status::NotHandled)
+ return res;
// Jom outputs errors to stderr
if (handleNmakeJomMessage(line, &m_lastTask)) {
m_lines = 1;
@@ -167,20 +171,23 @@ OutputTaskParser::Status MsvcParser::handleLine(const QString &line, OutputForma
return Status::NotHandled;
}
-bool MsvcParser::processCompileLine(const QString &line)
+MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
{
flush();
QRegularExpressionMatch match = m_compileRegExp.match(line);
if (match.hasMatch()) {
QPair<FilePath, int> position = parseFileName(match.captured(1));
+ const FilePath filePath = absoluteFilePath(position.first);
m_lastTask = CompileTask(taskType(match.captured(2)),
match.captured(3) + match.captured(4).trimmed(), // description
- absoluteFilePath(position.first), position.second);
+ filePath, position.second);
m_lines = 1;
- return true;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match, 1);
+ return {Status::InProgress, linkSpecs};
}
- return false;
+ return Status::NotHandled;
}
void MsvcParser::flush()
@@ -190,7 +197,7 @@ void MsvcParser::flush()
Task t = m_lastTask;
m_lastTask.clear();
- emit addTask(t, m_lines, 1);
+ scheduleTask(t, m_lines, 1);
}
// --------------------------------------------------------------------------
@@ -220,7 +227,7 @@ static inline bool isClangCodeMarker(const QString &trimmedLine)
[] (QChar c) { return c != ' ' && c != '^' && c != '~'; });
}
-OutputTaskParser::Status ClangClParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result ClangClParser::handleLine(const QString &line, OutputFormat type)
{
if (type == StdOutFormat) {
if (handleNmakeJomMessage(line, &m_lastTask)) {
@@ -257,7 +264,9 @@ OutputTaskParser::Status ClangClParser::handleLine(const QString &line, OutputFo
m_lastTask = CompileTask(taskType(match.captured(2)), match.captured(3).trimmed(),
absoluteFilePath(position.first), position.second);
m_linkedLines = 1;
- return Status::InProgress;
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_lastTask.file, m_lastTask.line, match, 1);
+ return {Status::InProgress, linkSpecs};
}
if (!m_lastTask.isNull()) {
@@ -278,7 +287,7 @@ OutputTaskParser::Status ClangClParser::handleLine(const QString &line, OutputFo
void ClangClParser::flush()
{
if (!m_lastTask.isNull()) {
- emit addTask(m_lastTask, m_linkedLines, 1);
+ scheduleTask(m_lastTask, m_linkedLines, 1);
m_lastTask.clear();
}
}
diff --git a/src/plugins/projectexplorer/msvcparser.h b/src/plugins/projectexplorer/msvcparser.h
index 3f71263ee89..f2b8d47d97c 100644
--- a/src/plugins/projectexplorer/msvcparser.h
+++ b/src/plugins/projectexplorer/msvcparser.h
@@ -43,10 +43,10 @@ public:
static Core::Id id();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
void flush() override;
- bool processCompileLine(const QString &line);
+ Result processCompileLine(const QString &line);
QRegularExpression m_compileRegExp;
QRegularExpression m_additionalInfoRegExp;
@@ -63,7 +63,7 @@ public:
ClangClParser();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
void flush() override;
const QRegularExpression m_compileRegExp;
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index f486a52202f..a2332739bc1 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -1169,7 +1169,7 @@ void MsvcToolChain::rescanForCompiler()
});
}
-QList<OutputTaskParser *> MsvcToolChain::createOutputParsers() const
+QList<OutputLineParser *> MsvcToolChain::createOutputParsers() const
{
return {new MsvcParser};
}
@@ -1656,7 +1656,7 @@ QStringList ClangClToolChain::suggestedMkspecList() const
return {mkspec, "win32-clang-msvc"};
}
-QList<OutputTaskParser *> ClangClToolChain::createOutputParsers() const
+QList<OutputLineParser *> ClangClToolChain::createOutputParsers() const
{
return {new ClangClParser};
}
diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h
index 4d40c0a25d8..7731598cb1f 100644
--- a/src/plugins/projectexplorer/msvctoolchain.h
+++ b/src/plugins/projectexplorer/msvctoolchain.h
@@ -89,7 +89,7 @@ public:
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
Utils::FilePath compilerCommand() const override;
- QList<OutputTaskParser *> createOutputParsers() const override;
+ QList<Utils::OutputLineParser *> createOutputParsers() const override;
QString varsBatArg() const { return m_varsBatArg; }
QString varsBat() const { return m_vcvarsBat; }
@@ -174,7 +174,7 @@ public:
QStringList suggestedMkspecList() const override;
void addToEnvironment(Utils::Environment &env) const override;
Utils::FilePath compilerCommand() const override;
- QList<OutputTaskParser *> createOutputParsers() const override;
+ QList<Utils::OutputLineParser *> createOutputParsers() const override;
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &data) override;
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override;
diff --git a/src/plugins/projectexplorer/osparser.cpp b/src/plugins/projectexplorer/osparser.cpp
index 3ea1dcc1199..9a1f11a0bad 100644
--- a/src/plugins/projectexplorer/osparser.cpp
+++ b/src/plugins/projectexplorer/osparser.cpp
@@ -36,18 +36,18 @@ OsParser::OsParser()
setObjectName(QLatin1String("OsParser"));
}
-OutputTaskParser::Status OsParser::handleLine(const QString &line, Utils::OutputFormat type)
+Utils::OutputLineParser::Result OsParser::handleLine(const QString &line, Utils::OutputFormat type)
{
if (type == Utils::StdOutFormat) {
if (Utils::HostOsInfo::isWindowsHost()) {
const QString trimmed = line.trimmed();
if (trimmed == QLatin1String("The process cannot access the file because it is "
"being used by another process.")) {
- emit addTask(CompileTask(Task::Error, tr(
+ scheduleTask(CompileTask(Task::Error, tr(
"The process cannot access the file because it is being used "
"by another process.\n"
"Please close all running instances of your application before "
- "starting a build.")));
+ "starting a build.")), 1);
m_hasFatalError = true;
return Status::Done;
}
@@ -57,7 +57,7 @@ OutputTaskParser::Status OsParser::handleLine(const QString &line, Utils::Output
if (Utils::HostOsInfo::isLinuxHost()) {
const QString trimmed = line.trimmed();
if (trimmed.contains(QLatin1String(": error while loading shared libraries:"))) {
- emit addTask(CompileTask(Task::Error, trimmed));
+ scheduleTask(CompileTask(Task::Error, trimmed), 1);
return Status::Done;
}
}
diff --git a/src/plugins/projectexplorer/osparser.h b/src/plugins/projectexplorer/osparser.h
index f33551648ab..d3e97eee6e3 100644
--- a/src/plugins/projectexplorer/osparser.h
+++ b/src/plugins/projectexplorer/osparser.h
@@ -41,7 +41,7 @@ public:
OsParser();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
bool hasFatalErrors() const override { return m_hasFatalError; }
bool m_hasFatalError = false;
diff --git a/src/plugins/projectexplorer/outputparser_test.cpp b/src/plugins/projectexplorer/outputparser_test.cpp
index 8caec11242e..8516a84de08 100644
--- a/src/plugins/projectexplorer/outputparser_test.cpp
+++ b/src/plugins/projectexplorer/outputparser_test.cpp
@@ -24,7 +24,9 @@
****************************************************************************/
#include "outputparser_test.h"
+#include "projectexplorer.h"
#include "task.h"
+#include "taskhub.h"
#if defined(WITH_TESTS)
@@ -41,11 +43,16 @@ static inline QByteArray msgFileComparisonFail(const Utils::FilePath &f1, const
// test functions:
OutputParserTester::OutputParserTester()
{
- connect(this, &IOutputParser::addTask, this, [this](const Task &t) {
+ connect(TaskHub::instance(), &TaskHub::taskAdded, this, [this](const Task &t) {
m_receivedTasks.append(t);
});
}
+OutputParserTester::~OutputParserTester()
+{
+ TaskHub::instance()->disconnect(this);
+}
+
void OutputParserTester::testParsing(const QString &lines,
Channel inputChannel,
Tasks tasks,
@@ -60,9 +67,9 @@ void OutputParserTester::testParsing(const QString &lines,
reset();
if (inputChannel == STDOUT)
- handleStdout(lines + '\n');
+ appendMessage(lines + '\n', Utils::StdOutFormat);
else
- handleStderr(lines + '\n');
+ appendMessage(lines + '\n', Utils::StdErrFormat);
flush();
// delete the parser(s) to test
@@ -102,7 +109,7 @@ TestTerminator::TestTerminator(OutputParserTester *t) :
m_tester(t)
{ }
-OutputTaskParser::Status TestTerminator::handleLine(const QString &line, Utils::OutputFormat type)
+Utils::OutputLineParser::Result TestTerminator::handleLine(const QString &line, Utils::OutputFormat type)
{
QTC_CHECK(line.endsWith('\n'));
if (type == Utils::StdOutFormat)
@@ -112,6 +119,64 @@ OutputTaskParser::Status TestTerminator::handleLine(const QString &line, Utils::
return Status::Done;
}
+void ProjectExplorerPlugin::testAnsiFilterOutputParser_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<OutputParserTester::Channel>("inputChannel");
+ QTest::addColumn<QString>("childStdOutLines");
+ QTest::addColumn<QString>("childStdErrLines");
+ QTest::addColumn<QString>("outputLines");
+
+ QTest::newRow("pass-through stdout")
+ << QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
+ << QString::fromLatin1("Sometext\n") << QString();
+ QTest::newRow("pass-through stderr")
+ << QString::fromLatin1("Sometext") << OutputParserTester::STDERR
+ << QString() << QString::fromLatin1("Sometext\n");
+
+ QString input = QString::fromLatin1("te") + QChar(27) + QString::fromLatin1("Nst");
+ QTest::newRow("ANSI: ESC-N")
+ << input << OutputParserTester::STDOUT
+ << QString::fromLatin1("test\n") << QString();
+ input = QString::fromLatin1("te") + QChar(27) + QLatin1String("^ignored") + QChar(27) + QLatin1String("\\st");
+ QTest::newRow("ANSI: ESC-^ignoredESC-\\")
+ << input << OutputParserTester::STDOUT
+ << QString::fromLatin1("test\n") << QString();
+ input = QString::fromLatin1("te") + QChar(27) + QLatin1String("]0;ignored") + QChar(7) + QLatin1String("st");
+ QTest::newRow("ANSI: window title change")
+ << input << OutputParserTester::STDOUT
+ << QString::fromLatin1("test\n") << QString();
+ input = QString::fromLatin1("te") + QChar(27) + QLatin1String("[Ast");
+ QTest::newRow("ANSI: cursor up")
+ << input << OutputParserTester::STDOUT
+ << QString::fromLatin1("test\n") << QString();
+ input = QString::fromLatin1("te") + QChar(27) + QLatin1String("[2Ast");
+ QTest::newRow("ANSI: cursor up (with int parameter)")
+ << input << OutputParserTester::STDOUT
+ << QString::fromLatin1("test\n") << QString();
+ input = QString::fromLatin1("te") + QChar(27) + QLatin1String("[2;3Hst");
+ QTest::newRow("ANSI: position cursor")
+ << input << OutputParserTester::STDOUT
+ << QString::fromLatin1("test\n") << QString();
+ input = QString::fromLatin1("te") + QChar(27) + QLatin1String("[31;1mst");
+ QTest::newRow("ANSI: bold red")
+ << input << OutputParserTester::STDOUT
+ << QString::fromLatin1("test\n") << QString();
+}
+
+void ProjectExplorerPlugin::testAnsiFilterOutputParser()
+{
+ OutputParserTester testbench;
+ QFETCH(QString, input);
+ QFETCH(OutputParserTester::Channel, inputChannel);
+ QFETCH(QString, childStdOutLines);
+ QFETCH(QString, childStdErrLines);
+
+ testbench.testParsing(input, inputChannel,
+ Tasks(), childStdOutLines, childStdErrLines,
+ QString());
+}
+
} // namespace ProjectExplorer
#endif
diff --git a/src/plugins/projectexplorer/outputparser_test.h b/src/plugins/projectexplorer/outputparser_test.h
index 86dd0481343..b41b9a1f87a 100644
--- a/src/plugins/projectexplorer/outputparser_test.h
+++ b/src/plugins/projectexplorer/outputparser_test.h
@@ -36,7 +36,7 @@ namespace ProjectExplorer {
class TestTerminator;
-class PROJECTEXPLORER_EXPORT OutputParserTester : public IOutputParser
+class PROJECTEXPLORER_EXPORT OutputParserTester : public Utils::OutputFormatter
{
Q_OBJECT
@@ -47,6 +47,7 @@ public:
};
OutputParserTester();
+ ~OutputParserTester();
// test functions:
void testParsing(const QString &lines, Channel inputChannel,
@@ -81,7 +82,7 @@ public:
TestTerminator(OutputParserTester *t);
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
OutputParserTester *m_tester = nullptr;
};
diff --git a/src/plugins/projectexplorer/parseissuesdialog.cpp b/src/plugins/projectexplorer/parseissuesdialog.cpp
index b1a38607e35..5a53574d93f 100644
--- a/src/plugins/projectexplorer/parseissuesdialog.cpp
+++ b/src/plugins/projectexplorer/parseissuesdialog.cpp
@@ -136,13 +136,13 @@ ParseIssuesDialog::~ParseIssuesDialog()
}
static void parse(QFutureInterface<void> &future, const QString &output,
- const std::unique_ptr<IOutputParser> &parser, bool isStderr)
+ const std::unique_ptr<Utils::OutputFormatter> &parser, bool isStderr)
{
const QStringList lines = output.split('\n');
future.setProgressRange(0, lines.count());
- const auto parserFunc = isStderr ? &IOutputParser::handleStderr : &IOutputParser::handleStdout;
+ const Utils::OutputFormat format = isStderr ? Utils::StdErrFormat : Utils::StdOutFormat;
for (const QString &line : lines) {
- (parser.get()->*parserFunc)(line + '\n');
+ parser->appendMessage(line + '\n', format);
future.setProgressValue(future.progressValue() + 1);
if (future.isCanceled())
return;
@@ -151,17 +151,17 @@ static void parse(QFutureInterface<void> &future, const QString &output,
void ParseIssuesDialog::accept()
{
- const QList<OutputTaskParser *> lineParsers = d->kitChooser.currentKit()->createOutputParsers();
+ const QList<Utils::OutputLineParser *> lineParsers =
+ d->kitChooser.currentKit()->createOutputParsers();
if (lineParsers.isEmpty()) {
QMessageBox::critical(this, tr("Cannot Parse"), tr("Cannot parse: The chosen kit does "
"not provide an output parser."));
return;
}
- std::unique_ptr<IOutputParser> parser(new IOutputParser);
+ std::unique_ptr<Utils::OutputFormatter> parser(new Utils::OutputFormatter);
parser->setLineParsers(lineParsers);
if (d->clearTasksCheckBox.isChecked())
TaskHub::clearTasks();
- connect(parser.get(), &IOutputParser::addTask, [](const Task &t) { TaskHub::addTask(t); });
const QFuture<void> f = Utils::runAsync(&parse, d->compileOutputEdit.toPlainText(),
std::move(parser), d->stderrCheckBox.isChecked());
Core::ProgressManager::addTask(f, tr("Parsing build output"),
diff --git a/src/plugins/projectexplorer/processstep.cpp b/src/plugins/projectexplorer/processstep.cpp
index ea8de1cb3b5..035b816ff07 100644
--- a/src/plugins/projectexplorer/processstep.cpp
+++ b/src/plugins/projectexplorer/processstep.cpp
@@ -35,6 +35,7 @@
#include "target.h"
#include <utils/fileutils.h>
+#include <utils/outputformatter.h>
using namespace Utils;
@@ -53,6 +54,7 @@ public:
ProcessStep(BuildStepList *bsl, Core::Id id);
bool init() final;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter);
void setupProcessParameters(ProcessParameters *pp);
BaseStringAspect *m_command;
@@ -100,10 +102,15 @@ ProcessStep::ProcessStep(BuildStepList *bsl, Core::Id id)
bool ProcessStep::init()
{
setupProcessParameters(processParameters());
- appendOutputParsers(target()->kit()->createOutputParsers());
return AbstractProcessStep::init();
}
+void ProcessStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ formatter->addLineParsers(target()->kit()->createOutputParsers());
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
void ProcessStep::setupProcessParameters(ProcessParameters *pp)
{
QString workingDirectory = m_workingDirectory->value();
diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro
index 4f9b5dd4f7a..4a8f9621989 100644
--- a/src/plugins/projectexplorer/projectexplorer.pro
+++ b/src/plugins/projectexplorer/projectexplorer.pro
@@ -11,7 +11,6 @@ HEADERS += projectexplorer.h \
abi.h \
abiwidget.h \
addrunconfigdialog.h \
- ansifilterparser.h \
buildaspects.h \
buildinfo.h \
buildpropertiessettings.h \
@@ -172,7 +171,6 @@ SOURCES += projectexplorer.cpp \
abi.cpp \
abiwidget.cpp \
addrunconfigdialog.cpp \
- ansifilterparser.cpp \
buildaspects.cpp \
buildinfo.cpp \
buildpropertiessettingspage.cpp \
diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs
index 6398533ca43..38efedd2102 100644
--- a/src/plugins/projectexplorer/projectexplorer.qbs
+++ b/src/plugins/projectexplorer/projectexplorer.qbs
@@ -27,7 +27,6 @@ Project {
"addrunconfigdialog.cpp", "addrunconfigdialog.h",
"allprojectsfilter.cpp", "allprojectsfilter.h",
"allprojectsfind.cpp", "allprojectsfind.h",
- "ansifilterparser.cpp", "ansifilterparser.h",
"applicationlauncher.cpp", "applicationlauncher.h",
"appoutputpane.cpp", "appoutputpane.h",
"baseprojectwizarddialog.cpp", "baseprojectwizarddialog.h",
diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h
index cc98793bded..b2dbc7ca9a4 100644
--- a/src/plugins/projectexplorer/toolchain.h
+++ b/src/plugins/projectexplorer/toolchain.h
@@ -47,6 +47,8 @@
#include <functional>
#include <memory>
+namespace Utils { class OutputLineParser; }
+
namespace ProjectExplorer {
namespace Internal { class ToolChainPrivate; }
@@ -64,7 +66,6 @@ QString languageId(Language l);
} // namespace Deprecated
class Abi;
-class OutputTaskParser;
class ToolChainConfigWidget;
class ToolChainFactory;
class Kit;
@@ -150,7 +151,7 @@ public:
Core::Id language() const;
virtual Utils::FilePath compilerCommand() const = 0;
- virtual QList<OutputTaskParser *> createOutputParsers() const = 0;
+ virtual QList<Utils::OutputLineParser *> createOutputParsers() const = 0;
virtual bool operator ==(const ToolChain &) const;
diff --git a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
index 43c9655d836..dd6e540b1aa 100644
--- a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
+++ b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp
@@ -324,7 +324,7 @@ public:
void addToEnvironment(Environment &env) const override { Q_UNUSED(env) }
FilePath makeCommand(const Environment &) const override { return FilePath::fromString("make"); }
FilePath compilerCommand() const override { return Utils::FilePath::fromString("/tmp/test/gcc"); }
- QList<OutputTaskParser *> createOutputParsers() const override { return {}; }
+ QList<OutputLineParser *> createOutputParsers() const override { return {}; }
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override { return nullptr; }
bool operator ==(const ToolChain &other) const override {
if (!ToolChain::operator==(other))
diff --git a/src/plugins/projectexplorer/xcodebuildparser.cpp b/src/plugins/projectexplorer/xcodebuildparser.cpp
index 4b5d9e4c7ef..9b6486e5d5a 100644
--- a/src/plugins/projectexplorer/xcodebuildparser.cpp
+++ b/src/plugins/projectexplorer/xcodebuildparser.cpp
@@ -52,7 +52,7 @@ XcodebuildParser::XcodebuildParser()
QTC_CHECK(m_buildRe.isValid());
}
-OutputTaskParser::Status XcodebuildParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result XcodebuildParser::handleLine(const QString &line, OutputFormat type)
{
const QString lne = rightTrimmed(line);
if (type == StdOutFormat) {
@@ -69,12 +69,16 @@ OutputTaskParser::Status XcodebuildParser::handleLine(const QString &line, Outpu
return Status::Done;
}
if (lne.endsWith(QLatin1String(signatureChangeEndsWithPattern))) {
+ const int filePathEndPos = lne.size()
+ - QLatin1String(signatureChangeEndsWithPattern).size();
CompileTask task(Task::Warning,
tr("Replacing signature"),
absoluteFilePath(FilePath::fromString(
- lne.left(lne.size() - QLatin1String(signatureChangeEndsWithPattern).size()))));
- emit addTask(task, 1);
- return Status::Done;
+ lne.left(filePathEndPos))));
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, task.file, task.line, 0, filePathEndPos);
+ scheduleTask(task, 1);
+ return {Status::Done, linkSpecs};
}
}
return Status::NotHandled;
@@ -83,7 +87,7 @@ OutputTaskParser::Status XcodebuildParser::handleLine(const QString &line, Outpu
++m_fatalErrorCount;
m_xcodeBuildParserState = UnknownXcodebuildState;
// unfortunately the m_lastTarget, m_lastProject might not be in sync
- emit addTask(CompileTask(Task::Error, tr("Xcodebuild failed.")));
+ scheduleTask(CompileTask(Task::Error, tr("Xcodebuild failed.")), 1);
}
if (m_xcodeBuildParserState == OutsideXcodebuild)
return Status::NotHandled;
diff --git a/src/plugins/projectexplorer/xcodebuildparser.h b/src/plugins/projectexplorer/xcodebuildparser.h
index 5c91315d74a..9342cd37854 100644
--- a/src/plugins/projectexplorer/xcodebuildparser.h
+++ b/src/plugins/projectexplorer/xcodebuildparser.h
@@ -47,7 +47,7 @@ public:
XcodebuildParser();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
bool hasDetectedRedirection() const override;
bool hasFatalErrors() const override { return m_fatalErrorCount > 0; }
diff --git a/src/plugins/python/pythonrunconfiguration.cpp b/src/plugins/python/pythonrunconfiguration.cpp
index 0e43cb3eea1..42dad98cb10 100644
--- a/src/plugins/python/pythonrunconfiguration.cpp
+++ b/src/plugins/python/pythonrunconfiguration.cpp
@@ -126,12 +126,6 @@ private:
return true;
}
- void reset() override
- {
- m_inTraceBack = false;
- m_tasks.clear();
- }
-
const QRegularExpression filePattern;
QList<Task> m_tasks;
bool m_inTraceBack;
diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
index d403ad05895..062f48e15bf 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
+++ b/src/plugins/qbsprojectmanager/qbsbuildstep.cpp
@@ -34,12 +34,12 @@
#include <coreplugin/icore.h>
#include <coreplugin/variablechooser.h>
#include <projectexplorer/buildsteplist.h>
-#include <projectexplorer/ioutputparser.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtversionmanager.h>
#include <utils/macroexpander.h>
+#include <utils/outputformatter.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
@@ -155,7 +155,6 @@ QbsBuildStep::~QbsBuildStep()
doCancel();
if (m_session)
m_session->disconnect(this);
- delete m_parser;
}
bool QbsBuildStep::init()
@@ -168,11 +167,6 @@ bool QbsBuildStep::init()
if (!bc)
return false;
- delete m_parser;
- m_parser = new IOutputParser;
- m_parser->setLineParsers(target()->kit()->createOutputParsers());
- connect(m_parser, &ProjectExplorer::IOutputParser::addTask, this, &QbsBuildStep::addTask);
-
m_changedFiles = bc->changedFiles();
m_activeFileTags = bc->activeFileTags();
m_products = bc->products();
@@ -180,6 +174,12 @@ bool QbsBuildStep::init()
return true;
}
+void QbsBuildStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ formatter->addLineParsers(target()->kit()->createOutputParsers());
+ BuildStep::setupOutputFormatter(formatter);
+}
+
void QbsBuildStep::doRun()
{
// We need a pre-build parsing step in order not to lose project file changes done
@@ -371,35 +371,24 @@ void QbsBuildStep::handleProcessResult(
const QStringList &stdErr,
bool success)
{
+ Q_UNUSED(workingDir);
const bool hasOutput = !stdOut.isEmpty() || !stdErr.isEmpty();
if (success && !hasOutput)
return;
- if (m_parser)
- m_parser->addSearchDir(workingDir);
emit addOutput(executable.toUserOutput() + ' ' + QtcProcess::joinArgs(arguments),
OutputFormat::Stdout);
- for (const QString &line : stdErr) {
- if (m_parser)
- m_parser->handleStderr(line + '\n');
+ for (const QString &line : stdErr)
emit addOutput(line, OutputFormat::Stderr);
- }
- for (const QString &line : stdOut) {
- if (m_parser)
- m_parser->handleStdout(line + '\n');
+ for (const QString &line : stdOut)
emit addOutput(line, OutputFormat::Stdout);
- }
- if (m_parser) {
- m_parser->flush();
- m_parser->dropSearchDir(workingDir);
- }
}
void QbsBuildStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type, const QString &message,
const QString &file, int line)
{
- emit addTask(CompileTask(type, message, FilePath::fromString(file), line), 1);
emit addOutput(message, OutputFormat::Stdout);
+ emit addTask(CompileTask(type, message, FilePath::fromString(file), line), 1);
}
QString QbsBuildStep::buildVariant() const
diff --git a/src/plugins/qbsprojectmanager/qbsbuildstep.h b/src/plugins/qbsprojectmanager/qbsbuildstep.h
index f0906936b64..d257662bdb2 100644
--- a/src/plugins/qbsprojectmanager/qbsbuildstep.h
+++ b/src/plugins/qbsprojectmanager/qbsbuildstep.h
@@ -30,7 +30,6 @@
#include <projectexplorer/buildstep.h>
#include <projectexplorer/task.h>
-namespace ProjectExplorer { class IOutputParser; }
namespace Utils { class FancyLineEdit; }
namespace QbsProjectManager {
@@ -81,6 +80,7 @@ signals:
private:
bool init() override;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
void doRun() override;
void doCancel() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
@@ -134,7 +134,6 @@ private:
QString m_currentTask;
int m_maxProgress;
bool m_lastWasSuccess;
- ProjectExplorer::IOutputParser *m_parser = nullptr;
bool m_parsingProject = false;
bool m_parsingAfterBuild = false;
diff --git a/src/plugins/qbsprojectmanager/qbscleanstep.cpp b/src/plugins/qbsprojectmanager/qbscleanstep.cpp
index 07adf568d24..44d33728960 100644
--- a/src/plugins/qbsprojectmanager/qbscleanstep.cpp
+++ b/src/plugins/qbsprojectmanager/qbscleanstep.cpp
@@ -160,8 +160,8 @@ void QbsCleanStep::handleProgress(int value)
void QbsCleanStep::createTaskAndOutput(ProjectExplorer::Task::TaskType type, const QString &message, const QString &file, int line)
{
- emit addTask(CompileTask(type, message, Utils::FilePath::fromString(file), line), 1);
emit addOutput(message, OutputFormat::Stdout);
+ emit addTask(CompileTask(type, message, Utils::FilePath::fromString(file), line), 1);
}
// --------------------------------------------------------------------
diff --git a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
index f3e3164e1e3..9ad460e48e5 100644
--- a/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
+++ b/src/plugins/qbsprojectmanager/qbsinstallstep.cpp
@@ -202,9 +202,8 @@ void QbsInstallStep::handleProgress(int value)
void QbsInstallStep::createTaskAndOutput(Task::TaskType type, const QString &message,
const Utils::FilePath &file, int line)
{
- const CompileTask task(type, message, file, line);
- emit addTask(task, 1);
emit addOutput(message, OutputFormat::Stdout);
+ emit addTask(CompileTask(type, message, file, line), 1);
}
void QbsInstallStep::setRemoveFirst(bool rf)
diff --git a/src/plugins/qmakeprojectmanager/qmakemakestep.cpp b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp
index 6ff538f70ad..8a105d66660 100644
--- a/src/plugins/qmakeprojectmanager/qmakemakestep.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakemakestep.cpp
@@ -164,25 +164,6 @@ bool QmakeMakeStep::init()
pp->setCommandLine(makeCmd);
pp->resolveAll();
- setOutputParser(new ProjectExplorer::GnuMakeParser());
- ToolChain *tc = ToolChainKitAspect::cxxToolChain(target()->kit());
- OutputTaskParser *xcodeBuildParser = nullptr;
- if (tc && tc->targetAbi().os() == Abi::DarwinOS) {
- xcodeBuildParser = new XcodebuildParser;
- appendOutputParser(xcodeBuildParser);
- }
- QList<OutputTaskParser *> additionalParsers = target()->kit()->createOutputParsers();
-
- // make may cause qmake to be run, add last to make sure it has a low priority.
- additionalParsers << new QMakeParser;
-
- if (xcodeBuildParser) {
- for (OutputTaskParser * const p : qAsConst(additionalParsers))
- p->setRedirectionDetector(xcodeBuildParser);
- }
- appendOutputParsers(additionalParsers);
- outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
-
auto rootNode = dynamic_cast<QmakeProFileNode *>(project()->rootProjectNode());
QTC_ASSERT(rootNode, return false);
m_scriptTarget = rootNode->projectType() == ProjectType::ScriptTemplate;
@@ -199,6 +180,30 @@ bool QmakeMakeStep::init()
return AbstractProcessStep::init();
}
+void QmakeMakeStep::setupOutputFormatter(Utils::OutputFormatter *formatter)
+{
+ formatter->addLineParser(new ProjectExplorer::GnuMakeParser());
+ ToolChain *tc = ToolChainKitAspect::cxxToolChain(target()->kit());
+ OutputTaskParser *xcodeBuildParser = nullptr;
+ if (tc && tc->targetAbi().os() == Abi::DarwinOS) {
+ xcodeBuildParser = new XcodebuildParser;
+ formatter->addLineParser(xcodeBuildParser);
+ }
+ QList<Utils::OutputLineParser *> additionalParsers = target()->kit()->createOutputParsers();
+
+ // make may cause qmake to be run, add last to make sure it has a low priority.
+ additionalParsers << new QMakeParser;
+
+ if (xcodeBuildParser) {
+ for (Utils::OutputLineParser * const p : qAsConst(additionalParsers))
+ p->setRedirectionDetector(xcodeBuildParser);
+ }
+ formatter->addLineParsers(additionalParsers);
+ formatter->addSearchDir(processParameters()->effectiveWorkingDirectory());
+
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
void QmakeMakeStep::doRun()
{
if (m_scriptTarget || m_ignoredNonTopLevelBuild) {
diff --git a/src/plugins/qmakeprojectmanager/qmakemakestep.h b/src/plugins/qmakeprojectmanager/qmakemakestep.h
index 29e5898e01c..ea4fc72b66f 100644
--- a/src/plugins/qmakeprojectmanager/qmakemakestep.h
+++ b/src/plugins/qmakeprojectmanager/qmakemakestep.h
@@ -52,6 +52,7 @@ public:
private:
void finish(bool success) override;
bool init() override;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
void doRun() override;
QStringList displayArguments() const override;
diff --git a/src/plugins/qmakeprojectmanager/qmakeparser.cpp b/src/plugins/qmakeprojectmanager/qmakeparser.cpp
index 20633f397df..64e08bf675a 100644
--- a/src/plugins/qmakeprojectmanager/qmakeparser.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeparser.cpp
@@ -40,7 +40,7 @@ QMakeParser::QMakeParser() : m_error(QLatin1String("^(.+):(\\d+):\\s(.+)$"))
m_error.setMinimal(true);
}
-OutputTaskParser::Status QMakeParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result QMakeParser::handleLine(const QString &line, OutputFormat type)
{
if (type != Utils::StdErrFormat)
return Status::NotHandled;
@@ -49,11 +49,14 @@ OutputTaskParser::Status QMakeParser::handleLine(const QString &line, OutputForm
QString fileName = m_error.cap(1);
Task::TaskType type = Task::Error;
const QString description = m_error.cap(3);
+ int fileNameOffset = m_error.pos(1);
if (fileName.startsWith(QLatin1String("WARNING: "))) {
type = Task::Warning;
fileName = fileName.mid(9);
+ fileNameOffset += 9;
} else if (fileName.startsWith(QLatin1String("ERROR: "))) {
fileName = fileName.mid(7);
+ fileNameOffset += 7;
}
if (description.startsWith(QLatin1String("note:"), Qt::CaseInsensitive))
type = Task::Unknown;
@@ -61,23 +64,25 @@ OutputTaskParser::Status QMakeParser::handleLine(const QString &line, OutputForm
type = Task::Warning;
else if (description.startsWith(QLatin1String("error:"), Qt::CaseInsensitive))
type = Task::Error;
- emit addTask(BuildSystemTask(type,
- description,
- absoluteFilePath(FilePath::fromUserInput(fileName)),
- m_error.cap(2).toInt() /* line */),
- 1);
- return Status::Done;
+
+ BuildSystemTask t(type, description, absoluteFilePath(FilePath::fromUserInput(fileName)),
+ m_error.cap(2).toInt() /* line */);
+ LinkSpecs linkSpecs;
+ addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, fileNameOffset,
+ fileName.length());
+ scheduleTask(t, 1);
+ return {Status::Done, linkSpecs};
}
if (lne.startsWith(QLatin1String("Project ERROR: "))
|| lne.startsWith(QLatin1String("ERROR: "))) {
const QString description = lne.mid(lne.indexOf(QLatin1Char(':')) + 2);
- emit addTask(BuildSystemTask(Task::Error, description), 1);
+ scheduleTask(BuildSystemTask(Task::Error, description), 1);
return Status::Done;
}
if (lne.startsWith(QLatin1String("Project WARNING: "))
|| lne.startsWith(QLatin1String("WARNING: "))) {
const QString description = lne.mid(lne.indexOf(QLatin1Char(':')) + 2);
- emit addTask(BuildSystemTask(Task::Warning, description), 1);
+ scheduleTask(BuildSystemTask(Task::Warning, description), 1);
return Status::Done;
}
return Status::NotHandled;
@@ -174,7 +179,7 @@ void QmakeProjectManagerPlugin::testQmakeOutputParsers_data()
<< (Tasks()
<< BuildSystemTask(Task::Unknown,
"Note: No relevant classes found. No output generated.",
- FilePath::fromUserInput("/home/qtwebkithelpviewer.h"), 0))
+ FilePath::fromUserInput("/home/qtwebkithelpviewer.h"), -1))
<< QString();
}
diff --git a/src/plugins/qmakeprojectmanager/qmakeparser.h b/src/plugins/qmakeprojectmanager/qmakeparser.h
index 14c5b20d88f..210e5e576c9 100644
--- a/src/plugins/qmakeprojectmanager/qmakeparser.h
+++ b/src/plugins/qmakeprojectmanager/qmakeparser.h
@@ -41,7 +41,7 @@ public:
QMakeParser();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
QRegExp m_error;
};
diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp
index 7d1a418249e..424e12f5437 100644
--- a/src/plugins/qmakeprojectmanager/qmakestep.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp
@@ -225,8 +225,6 @@ bool QMakeStep::init()
pp->setWorkingDirectory(workingDirectory);
pp->setEnvironment(qmakeBc->environment());
- setOutputParser(new QMakeParser);
-
QmakeProFileNode *node = static_cast<QmakeProFileNode *>(qmakeBc->project()->rootProjectNode());
if (qmakeBc->subNodeBuild())
node = qmakeBc->subNodeBuild();
@@ -254,6 +252,13 @@ bool QMakeStep::init()
return AbstractProcessStep::init();
}
+void QMakeStep::setupOutputFormatter(OutputFormatter *formatter)
+{
+ formatter->addLineParser(new QMakeParser);
+ m_outputFormatter = formatter;
+ AbstractProcessStep::setupOutputFormatter(formatter);
+}
+
void QMakeStep::doRun()
{
if (m_scriptTemplate) {
@@ -332,7 +337,7 @@ void QMakeStep::runNextCommand()
case State::IDLE:
return;
case State::RUN_QMAKE:
- setOutputParser(new QMakeParser);
+ m_outputFormatter->setLineParsers({new QMakeParser});
m_nextState = (m_runMakeQmake ? State::RUN_MAKE_QMAKE_ALL : State::POST_PROCESS);
startOneCommand(m_qmakeCommand);
return;
@@ -340,7 +345,7 @@ void QMakeStep::runNextCommand()
{
auto *parser = new GnuMakeParser;
parser->addSearchDir(processParameters()->workingDirectory());
- setOutputParser(parser);
+ m_outputFormatter->setLineParsers({parser});
m_nextState = State::POST_PROCESS;
startOneCommand(m_makeCommand);
}
diff --git a/src/plugins/qmakeprojectmanager/qmakestep.h b/src/plugins/qmakeprojectmanager/qmakestep.h
index 6475757e167..05710e10836 100644
--- a/src/plugins/qmakeprojectmanager/qmakestep.h
+++ b/src/plugins/qmakeprojectmanager/qmakestep.h
@@ -121,6 +121,7 @@ public:
QmakeBuildConfiguration *qmakeBuildConfiguration() const;
QmakeBuildSystem *qmakeBuildSystem() const;
bool init() override;
+ void setupOutputFormatter(Utils::OutputFormatter *formatter) override;
void doRun() override;
ProjectExplorer::BuildStepConfigWidget *createConfigWidget() override;
void setForced(bool b);
@@ -192,6 +193,7 @@ private:
bool m_runMakeQmake = false;
bool m_scriptTemplate = false;
QStringList m_selectedAbis;
+ Utils::OutputFormatter *m_outputFormatter = nullptr;
};
diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp
index 61f554b99d8..070f8c4860f 100644
--- a/src/plugins/qtsupport/qtkitinformation.cpp
+++ b/src/plugins/qtsupport/qtkitinformation.cpp
@@ -288,7 +288,7 @@ void QtKitAspect::addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environ
version->addToEnvironment(k, env);
}
-QList<OutputTaskParser *> QtKitAspect::createOutputParsers(const Kit *k) const
+QList<Utils::OutputLineParser *> QtKitAspect::createOutputParsers(const Kit *k) const
{
if (qtVersion(k))
return {new Internal::QtTestParser, new QtParser};
diff --git a/src/plugins/qtsupport/qtkitinformation.h b/src/plugins/qtsupport/qtkitinformation.h
index dacd3e6f51e..b494ec09a4a 100644
--- a/src/plugins/qtsupport/qtkitinformation.h
+++ b/src/plugins/qtsupport/qtkitinformation.h
@@ -54,7 +54,7 @@ public:
ItemList toUserOutput(const ProjectExplorer::Kit *k) const override;
void addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const override;
- QList<ProjectExplorer::OutputTaskParser *> createOutputParsers(const ProjectExplorer::Kit *k) const override;
+ QList<Utils::OutputLineParser *> createOutputParsers(const ProjectExplorer::Kit *k) const override;
void addToMacroExpander(ProjectExplorer::Kit *kit, Utils::MacroExpander *expander) const override;
static Core::Id id();
diff --git a/src/plugins/qtsupport/qtoutputformatter.cpp b/src/plugins/qtsupport/qtoutputformatter.cpp
index 66ebffc433e..9c1803bf3d6 100644
--- a/src/plugins/qtsupport/qtoutputformatter.cpp
+++ b/src/plugins/qtsupport/qtoutputformatter.cpp
@@ -79,7 +79,7 @@ public:
FileInProjectFinder projectFinder;
};
-class QtOutputLineParser : public QObject, public OutputLineParser
+class QtOutputLineParser : public OutputLineParser
{
public:
explicit QtOutputLineParser(Target *target);
@@ -482,11 +482,11 @@ void QtSupportPlugin::testQtOutputFormatter_appendMessage()
QFETCH(QTextCharFormat, inputFormat);
QFETCH(QTextCharFormat, outputFormat);
if (outputFormat == QTextCharFormat())
- outputFormat = formatter.charFormat(DebugFormat);
+ outputFormat = formatter.charFormat(StdOutFormat);
if (inputFormat != QTextCharFormat())
formatter.overrideTextCharFormat(inputFormat);
- formatter.appendMessage(inputText, DebugFormat);
+ formatter.appendMessage(inputText, StdOutFormat);
formatter.flush();
QCOMPARE(edit.toPlainText(), outputText);
@@ -509,7 +509,7 @@ void QtSupportPlugin::testQtOutputFormatter_appendMixedAssertAndAnsi()
"file://test.cpp:123 "
"Blue\n";
- formatter.appendMessage(inputText, DebugFormat);
+ formatter.appendMessage(inputText, StdOutFormat);
QCOMPARE(edit.toPlainText(), outputText);
diff --git a/src/plugins/qtsupport/qtparser.cpp b/src/plugins/qtsupport/qtparser.cpp
index 1c53feb247d..b376e9911c4 100644
--- a/src/plugins/qtsupport/qtparser.cpp
+++ b/src/plugins/qtsupport/qtparser.cpp
@@ -28,9 +28,18 @@
#include <projectexplorer/task.h>
#include <projectexplorer/projectexplorerconstants.h>
-using namespace QtSupport;
+#include <QFileInfo>
+
+#ifdef WITH_TESTS
+#include "qtsupportplugin.h"
+#include <projectexplorer/outputparser_test.h>
+#include <QTest>
+#endif
+
using namespace ProjectExplorer;
+namespace QtSupport {
+
// opt. drive letter + filename: (2 brackets)
#define FILE_PATTERN "^(([A-Za-z]:)?[^:]+\\.[^:]+)"
@@ -43,7 +52,7 @@ QtParser::QtParser() :
m_translationRegExp.setMinimal(true);
}
-OutputTaskParser::Status QtParser::handleLine(const QString &line, Utils::OutputFormat type)
+Utils::OutputLineParser::Result QtParser::handleLine(const QString &line, Utils::OutputFormat type)
{
if (type != Utils::StdErrFormat)
return Status::NotHandled;
@@ -60,20 +69,25 @@ OutputTaskParser::Status QtParser::handleLine(const QString &line, Utils::Output
type = Task::Warning;
if (level.compare(QLatin1String("Note"), Qt::CaseInsensitive) == 0)
type = Task::Unknown;
- CompileTask task(type, m_mocRegExp.cap(5).trimmed() /* description */,
- absoluteFilePath(Utils::FilePath::fromUserInput(m_mocRegExp.cap(1))),
- lineno);
- emit addTask(task, 1);
- return Status::Done;
+ LinkSpecs linkSpecs;
+ const Utils::FilePath file
+ = absoluteFilePath(Utils::FilePath::fromUserInput(m_mocRegExp.cap(1)));
+ addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineno, m_mocRegExp, 1);
+ CompileTask task(type, m_mocRegExp.cap(5).trimmed() /* description */, file, lineno);
+ scheduleTask(task, 1);
+ return {Status::Done, linkSpecs};
}
if (m_translationRegExp.indexIn(lne) > -1) {
Task::TaskType type = Task::Warning;
if (m_translationRegExp.cap(1) == QLatin1String("Error"))
type = Task::Error;
- CompileTask task(type, m_translationRegExp.cap(2),
- absoluteFilePath(Utils::FilePath::fromUserInput(m_translationRegExp.cap(3))));
- emit addTask(task, 1);
- return Status::Done;
+ LinkSpecs linkSpecs;
+ const Utils::FilePath file
+ = absoluteFilePath(Utils::FilePath::fromUserInput(m_translationRegExp.cap(3)));
+ addLinkSpecForAbsoluteFilePath(linkSpecs, file, 0, m_translationRegExp, 3);
+ CompileTask task(type, m_translationRegExp.cap(2), file);
+ scheduleTask(task, 1);
+ return {Status::Done, linkSpecs};
}
return Status::NotHandled;
}
@@ -81,14 +95,7 @@ OutputTaskParser::Status QtParser::handleLine(const QString &line, Utils::Output
// Unit tests:
#ifdef WITH_TESTS
-# include <QTest>
-
-# include "qtsupportplugin.h"
-# include <projectexplorer/projectexplorerconstants.h>
-# include <projectexplorer/outputparser_test.h>
-
-using namespace ProjectExplorer;
-using namespace QtSupport::Internal;
+namespace Internal {
void QtSupportPlugin::testQtOutputParser_data()
{
@@ -139,7 +146,7 @@ void QtSupportPlugin::testQtOutputParser_data()
<< QString() << QString()
<< (Tasks() << CompileTask(Task::Warning,
QLatin1String("No relevant classes found. No output generated."),
- Utils::FilePath::fromUserInput(QLatin1String("..\\untitled\\errorfile.h")), 0))
+ Utils::FilePath::fromUserInput(QLatin1String("..\\untitled\\errorfile.h")), -1))
<< QString();
QTest::newRow("moc warning 2")
<< QString::fromLatin1("c:\\code\\test.h(96): Warning: Property declaration ) has no READ accessor function. The property will be invalid.")
@@ -155,7 +162,7 @@ void QtSupportPlugin::testQtOutputParser_data()
<< QString() << QString()
<< (Tasks() << CompileTask(Task::Unknown,
QLatin1String("No relevant classes found. No output generated."),
- Utils::FilePath::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), 0))
+ Utils::FilePath::fromUserInput(QLatin1String("/home/qtwebkithelpviewer.h")), -1))
<< QString();
QTest::newRow("ninja with moc")
<< QString::fromLatin1("E:/sandbox/creator/loaden/src/libs/utils/iwelcomepage.h(54): Error: Undefined interface")
@@ -188,4 +195,8 @@ void QtSupportPlugin::testQtOutputParser()
testbench.testParsing(input, inputChannel, tasks, childStdOutLines, childStdErrLines, outputLines);
}
+
+} // namespace Internal
#endif
+
+} // namespace QtSupport
diff --git a/src/plugins/qtsupport/qtparser.h b/src/plugins/qtsupport/qtparser.h
index 5f891a2cf31..e70661f6483 100644
--- a/src/plugins/qtsupport/qtparser.h
+++ b/src/plugins/qtsupport/qtparser.h
@@ -42,10 +42,10 @@ public:
QtParser();
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
QRegExp m_mocRegExp;
QRegExp m_translationRegExp;
};
-} // namespace ProjectExplorer
+} // namespace QtSupport
diff --git a/src/plugins/qtsupport/qttestparser.cpp b/src/plugins/qtsupport/qttestparser.cpp
index cf75303658c..1e8a572f4a6 100644
--- a/src/plugins/qtsupport/qttestparser.cpp
+++ b/src/plugins/qtsupport/qttestparser.cpp
@@ -47,7 +47,7 @@ using namespace Utils;
namespace QtSupport {
namespace Internal {
-OutputTaskParser::Status QtTestParser::handleLine(const QString &line, OutputFormat type)
+OutputLineParser::Result QtTestParser::handleLine(const QString &line, OutputFormat type)
{
if (type != StdOutFormat)
return Status::NotHandled;
@@ -69,11 +69,14 @@ OutputTaskParser::Status QtTestParser::handleLine(const QString &line, OutputFor
QTC_CHECK(locationPattern.isValid());
const QRegularExpressionMatch match = locationPattern.match(theLine);
if (match.hasMatch()) {
+ LinkSpecs linkSpecs;
m_currentTask.file = absoluteFilePath(FilePath::fromString(
QDir::fromNativeSeparators(match.captured("file"))));
m_currentTask.line = match.captured("line").toInt();
+ addLinkSpecForAbsoluteFilePath(linkSpecs, m_currentTask.file, m_currentTask.line, match,
+ "file");
emitCurrentTask();
- return Status::Done;
+ return {Status::Done, linkSpecs};
}
m_currentTask.description.append('\n').append(theLine);
return Status::InProgress;
@@ -82,7 +85,7 @@ OutputTaskParser::Status QtTestParser::handleLine(const QString &line, OutputFor
void QtTestParser::emitCurrentTask()
{
if (!m_currentTask.isNull()) {
- emit addTask(m_currentTask);
+ scheduleTask(m_currentTask, 1);
m_currentTask.clear();
}
}
diff --git a/src/plugins/qtsupport/qttestparser.h b/src/plugins/qtsupport/qttestparser.h
index 2ed4e78bf9a..8e76eaba40b 100644
--- a/src/plugins/qtsupport/qttestparser.h
+++ b/src/plugins/qtsupport/qttestparser.h
@@ -35,7 +35,7 @@ class QtTestParser : public ProjectExplorer::OutputTaskParser
{
Q_OBJECT
private:
- Status handleLine(const QString &line, Utils::OutputFormat type) override;
+ Result handleLine(const QString &line, Utils::OutputFormat type) override;
void flush() override { emitCurrentTask(); }
void emitCurrentTask();
diff --git a/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp b/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp
index 6a552296d10..7d24e38fb63 100644
--- a/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp
+++ b/src/plugins/remotelinux/abstractremotelinuxdeploystep.cpp
@@ -139,15 +139,15 @@ void AbstractRemoteLinuxDeployStep::handleProgressMessage(const QString &message
void AbstractRemoteLinuxDeployStep::handleErrorMessage(const QString &message)
{
- emit addTask(DeploymentTask(Task::Error, message), 1); // TODO correct?
emit addOutput(message, OutputFormat::ErrorMessage);
+ emit addTask(DeploymentTask(Task::Error, message), 1); // TODO correct?
d->hasError = true;
}
void AbstractRemoteLinuxDeployStep::handleWarningMessage(const QString &message)
{
- emit addTask(DeploymentTask(Task::Warning, message), 1); // TODO correct?
emit addOutput(message, OutputFormat::ErrorMessage);
+ emit addTask(DeploymentTask(Task::Warning, message), 1); // TODO correct?
}
void AbstractRemoteLinuxDeployStep::handleFinished()
diff --git a/src/plugins/vcsbase/vcsoutputformatter.h b/src/plugins/vcsbase/vcsoutputformatter.h
index e4ebfc6fee8..0b9486e2a91 100644
--- a/src/plugins/vcsbase/vcsoutputformatter.h
+++ b/src/plugins/vcsbase/vcsoutputformatter.h
@@ -31,7 +31,7 @@ QT_FORWARD_DECLARE_CLASS(QMenu)
namespace VcsBase {
-class VcsOutputLineParser : public QObject, public Utils::OutputLineParser
+class VcsOutputLineParser : public Utils::OutputLineParser
{
Q_OBJECT
public:
diff --git a/src/plugins/winrt/winrtpackagedeploymentstep.cpp b/src/plugins/winrt/winrtpackagedeploymentstep.cpp
index 32a474775bd..5c2759672a3 100644
--- a/src/plugins/winrt/winrtpackagedeploymentstep.cpp
+++ b/src/plugins/winrt/winrtpackagedeploymentstep.cpp
@@ -347,14 +347,14 @@ QString WinRtPackageDeploymentStep::defaultWinDeployQtArguments() const
void WinRtPackageDeploymentStep::raiseError(const QString &errorMessage)
{
- emit addTask(DeploymentTask(Task::Error, errorMessage), 1);
emit addOutput(errorMessage, BuildStep::OutputFormat::ErrorMessage);
+ emit addTask(DeploymentTask(Task::Error, errorMessage), 1);
}
void WinRtPackageDeploymentStep::raiseWarning(const QString &warningMessage)
{
- emit addTask(DeploymentTask(Task::Warning, warningMessage), 1);
emit addOutput(warningMessage, BuildStep::OutputFormat::NormalMessage);
+ emit addTask(DeploymentTask(Task::Warning, warningMessage), 1);
}
bool WinRtPackageDeploymentStep::parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *icons, QString *executable)