ProjectExplorer: Add an "origin" field to the Task class

... and set it in some relevant contexts.

Change-Id: Id620ff8688617158d06240c92d52ad119e793c94
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2025-06-11 17:33:56 +02:00
parent 9d39379995
commit db698db171
20 changed files with 137 additions and 102 deletions

View File

@@ -40,6 +40,7 @@ void IarParser::newTask(const Task &task)
{ {
flush(); flush();
m_lastTask = task; m_lastTask = task;
m_lastTask.origin = "IAR compiler";
m_lines = 1; m_lines = 1;
} }

View File

@@ -2,16 +2,19 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "cmakeautogenparser.h" #include "cmakeautogenparser.h"
#include "cmakeoutputparser.h"
#include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <projectexplorer/projectexplorerconstants.h> #ifdef WITH_TESTS
#include <projectexplorer/outputparser_test.h>
#include <QTest>
#endif
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
namespace CMakeProjectManager { namespace CMakeProjectManager::Internal {
const char COMMON_ERROR_PATTERN[] = "^(AutoMoc|AUTOMOC|AutoUic).*error.*$"; const char COMMON_ERROR_PATTERN[] = "^(AutoMoc|AUTOMOC|AutoUic).*error.*$";
const char COMMON_WARNING_PATTERN[] = "^(AutoMoc|AUTOMOC|AutoUic).*warning.*$"; const char COMMON_WARNING_PATTERN[] = "^(AutoMoc|AUTOMOC|AutoUic).*warning.*$";
@@ -37,7 +40,7 @@ OutputLineParser::Result CMakeAutogenParser::handleLine(const QString &line, Out
case NONE: { case NONE: {
match = m_commonError.match(trimmedLine); match = m_commonError.match(trimmedLine);
if (match.hasMatch()) { if (match.hasMatch()) {
m_lastTask = BuildSystemTask(Task::Error, match.captured()); m_lastTask = CMakeTask(Task::Error, match.captured());
m_lines = 1; m_lines = 1;
m_expectedState = LINE_SEPARATOR; m_expectedState = LINE_SEPARATOR;
@@ -45,7 +48,7 @@ OutputLineParser::Result CMakeAutogenParser::handleLine(const QString &line, Out
} }
match = m_commonWarning.match(trimmedLine); match = m_commonWarning.match(trimmedLine);
if (match.hasMatch()) { if (match.hasMatch()) {
m_lastTask = BuildSystemTask(Task::Warning, match.captured()); m_lastTask = CMakeTask(Task::Warning, match.captured());
m_lines = 1; m_lines = 1;
m_expectedState = LINE_SEPARATOR; m_expectedState = LINE_SEPARATOR;
@@ -93,16 +96,8 @@ void CMakeAutogenParser::flush()
m_lines = 0; m_lines = 0;
} }
} // namespace CMakeProjectManager
#ifdef WITH_TESTS #ifdef WITH_TESTS
#include <projectexplorer/outputparser_test.h>
#include <QTest>
namespace CMakeProjectManager::Internal {
class CMakeAutogenParserTest final : public QObject class CMakeAutogenParserTest final : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -137,7 +132,7 @@ Consider to
- add #include "main.moc" - add #include "main.moc"
- enable SKIP_AUTOMOC for this file)" - enable SKIP_AUTOMOC for this file)"
<< OutputParserTester::STDERR << QStringList() << QStringList() << OutputParserTester::STDERR << QStringList() << QStringList()
<< (Tasks() << BuildSystemTask( << (Tasks() << CMakeTask(
Task::Error, Task::Error,
R"(AutoMoc error R"(AutoMoc error
"SRC:/main.cpp" "SRC:/main.cpp"
@@ -156,7 +151,7 @@ included by
"BIN:/src/quickcontrols/basic/impl/qtquickcontrols2basicstyleimplplugin_QtQuickControls2BasicStyleImplPlugin.cpp" "BIN:/src/quickcontrols/basic/impl/qtquickcontrols2basicstyleimplplugin_QtQuickControls2BasicStyleImplPlugin.cpp"
Process failed with return value 1)" << OutputParserTester::STDERR Process failed with return value 1)" << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << BuildSystemTask( << (Tasks() << CMakeTask(
Task::Error, Task::Error,
R"(AutoMoc subprocess error R"(AutoMoc subprocess error
The moc process failed to compile The moc process failed to compile
@@ -174,7 +169,7 @@ moc on "/home/alex/src/CMake/tests/solid.orig/solid/solid/device_p.h" !
Include "moc_device_p.cpp" for compatibility with strict mode (see Include "moc_device_p.cpp" for compatibility with strict mode (see
CMAKE_AUTOMOC_RELAXED_MODE).)" << OutputParserTester::STDERR CMAKE_AUTOMOC_RELAXED_MODE).)" << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << BuildSystemTask( << (Tasks() << CMakeTask(
Task::Warning, Task::Warning,
R"(AUTOMOC: warning: R"(AUTOMOC: warning:
/home/alex/src/CMake/tests/solid.orig/solid/solid/device.cpp: The file /home/alex/src/CMake/tests/solid.orig/solid/solid/device.cpp: The file
@@ -188,7 +183,7 @@ CMAKE_AUTOMOC_RELAXED_MODE).)"));
"SRC:/src/main.cpp" "SRC:/src/main.cpp"
includes the moc file "main.moc", but does not contain a Q_OBJECT, Q_GADGET, Q_NAMESPACE, Q_NAMESPACE_EXPORT, Q_GADGET_EXPORT, Q_ENUM_NS, K_PLUGIN_FACTORY, K_PLUGIN_CLASS, K_PLUGIN_FACTORY_WITH_JSON or K_PLUGIN_CLASS_WITH_JSON macro.)" includes the moc file "main.moc", but does not contain a Q_OBJECT, Q_GADGET, Q_NAMESPACE, Q_NAMESPACE_EXPORT, Q_GADGET_EXPORT, Q_ENUM_NS, K_PLUGIN_FACTORY, K_PLUGIN_CLASS, K_PLUGIN_FACTORY_WITH_JSON or K_PLUGIN_CLASS_WITH_JSON macro.)"
<< OutputParserTester::STDERR << QStringList() << QStringList() << OutputParserTester::STDERR << QStringList() << QStringList()
<< (Tasks() << BuildSystemTask( << (Tasks() << CMakeTask(
Task::Warning, Task::Warning,
R"(AutoMoc warning R"(AutoMoc warning
"SRC:/src/main.cpp" "SRC:/src/main.cpp"
@@ -202,7 +197,7 @@ but the user interface file "global.ui"
could not be found in the following directories could not be found in the following directories
"SRC:/monitor/ui")" << OutputParserTester::STDERR "SRC:/monitor/ui")" << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << BuildSystemTask( << (Tasks() << CMakeTask(
Task::Error, Task::Error,
R"(AutoUic error R"(AutoUic error
"SRC:/monitor/ui/LiveBoard.h" "SRC:/monitor/ui/LiveBoard.h"
@@ -230,8 +225,8 @@ QObject *createCMakeAutogenParserTest()
return new CMakeAutogenParserTest; return new CMakeAutogenParserTest;
} }
} // namespace CMakeProjectManager::Internal
#endif #endif
} // namespace CMakeProjectManager::Internal
#include "cmakeautogenparser.moc" #include "cmakeautogenparser.moc"

View File

@@ -3,16 +3,14 @@
#pragma once #pragma once
#include "cmake_global.h"
#include <projectexplorer/ioutputparser.h> #include <projectexplorer/ioutputparser.h>
#include <projectexplorer/task.h> #include <projectexplorer/task.h>
#include <QRegularExpression> #include <QRegularExpression>
namespace CMakeProjectManager { namespace CMakeProjectManager::Internal {
class CMAKE_EXPORT CMakeAutogenParser : public ProjectExplorer::OutputTaskParser class CMakeAutogenParser : public ProjectExplorer::OutputTaskParser
{ {
public: public:
explicit CMakeAutogenParser(); explicit CMakeAutogenParser();
@@ -33,9 +31,7 @@ private:
}; };
#ifdef WITH_TESTS #ifdef WITH_TESTS
namespace Internal {
QObject *createCMakeAutogenParserTest(); QObject *createCMakeAutogenParserTest();
}
#endif #endif
} // namespace CMakeProjectManager } // namespace CMakeProjectManager::Internal

View File

@@ -8,12 +8,15 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <projectexplorer/projectexplorerconstants.h> #ifdef WITH_TESTS
#include <projectexplorer/outputparser_test.h>
#include <QTest>
#endif
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
namespace CMakeProjectManager { namespace CMakeProjectManager::Internal {
const char COMMON_ERROR_PATTERN[] = "^CMake Error at (.*?):([0-9]*?)( \\((.*?)\\))?:"; const char COMMON_ERROR_PATTERN[] = "^CMake Error at (.*?):([0-9]*?)( \\((.*?)\\))?:";
const char NEXT_SUBERROR_PATTERN[] = "^CMake Error in (.*?):"; const char NEXT_SUBERROR_PATTERN[] = "^CMake Error in (.*?):";
@@ -57,7 +60,7 @@ FilePath CMakeOutputParser::resolvePath(const QString &path) const
OutputLineParser::Result CMakeOutputParser::handleLine(const QString &line, OutputFormat type) OutputLineParser::Result CMakeOutputParser::handleLine(const QString &line, OutputFormat type)
{ {
if (line.startsWith("ninja: build stopped")) { if (line.startsWith("ninja: build stopped")) {
m_lastTask = BuildSystemTask(Task::Error, line); m_lastTask = CMakeTask(Task::Error, line);
m_lines = 1; m_lines = 1;
flush(); flush();
return Status::Done; return Status::Done;
@@ -87,7 +90,7 @@ OutputLineParser::Result CMakeOutputParser::handleLine(const QString &line, Outp
if (match.hasMatch()) { if (match.hasMatch()) {
const FilePath path = resolvePath(match.captured(1)); const FilePath path = resolvePath(match.captured(1));
m_lastTask = BuildSystemTask(Task::Error, m_lastTask = CMakeTask(Task::Error,
QString(), QString(),
absoluteFilePath(path), absoluteFilePath(path),
match.captured(2).toInt()); match.captured(2).toInt());
@@ -104,7 +107,7 @@ OutputLineParser::Result CMakeOutputParser::handleLine(const QString &line, Outp
} }
match = m_nextSubError.match(trimmedLine); match = m_nextSubError.match(trimmedLine);
if (match.hasMatch()) { if (match.hasMatch()) {
m_lastTask = BuildSystemTask(Task::Error, QString(), m_lastTask = CMakeTask(Task::Error, QString(),
absoluteFilePath(FilePath::fromUserInput(match.captured(1)))); absoluteFilePath(FilePath::fromUserInput(match.captured(1))));
LinkSpecs linkSpecs; LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath( addLinkSpecForAbsoluteFilePath(
@@ -115,7 +118,7 @@ OutputLineParser::Result CMakeOutputParser::handleLine(const QString &line, Outp
match = m_commonWarning.match(trimmedLine); match = m_commonWarning.match(trimmedLine);
if (match.hasMatch()) { if (match.hasMatch()) {
const FilePath path = resolvePath(match.captured(2)); const FilePath path = resolvePath(match.captured(2));
m_lastTask = BuildSystemTask(Task::Warning, m_lastTask = CMakeTask(Task::Warning,
QString(), QString(),
absoluteFilePath(path), absoluteFilePath(path),
match.captured(3).toInt()); match.captured(3).toInt());
@@ -150,10 +153,10 @@ OutputLineParser::Result CMakeOutputParser::handleLine(const QString &line, Outp
flush(); flush();
const Task::TaskType type = const Task::TaskType type =
trimmedLine.contains(QLatin1String("Error")) ? Task::Error : Task::Warning; trimmedLine.contains(QLatin1String("Error")) ? Task::Error : Task::Warning;
m_lastTask = BuildSystemTask(type, QString()); m_lastTask = CMakeTask(type, QString());
return Status::InProgress; return Status::InProgress;
} else if (trimmedLine.startsWith("CMake Error: ")) { } else if (trimmedLine.startsWith("CMake Error: ")) {
m_lastTask = BuildSystemTask(Task::Error, trimmedLine.mid(13)); m_lastTask = CMakeTask(Task::Error, trimmedLine.mid(13));
m_lines = 1; m_lines = 1;
return Status::InProgress; return Status::InProgress;
} else if (trimmedLine.startsWith("-- ") || trimmedLine.startsWith(" * ")) { } else if (trimmedLine.startsWith("-- ") || trimmedLine.startsWith(" * ")) {
@@ -251,16 +254,8 @@ void CMakeOutputParser::flush()
m_callStackDetected = false; m_callStackDetected = false;
} }
} // CMakeProjectManager
#ifdef WITH_TESTS #ifdef WITH_TESTS
#include <projectexplorer/outputparser_test.h>
#include <QTest>
namespace CMakeProjectManager::Internal {
class CMakeOutputParserTest final : public QObject class CMakeOutputParserTest final : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -303,13 +298,13 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << CMakeTask(Task::Error,
"Cannot find source file:\n\n" "Cannot find source file:\n\n"
" unknownFile.qml\n\n" " unknownFile.qml\n\n"
"Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp\n" "Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp\n"
".hxx .in .txx", ".hxx .in .txx",
FilePath::fromUserInput("src/1/app/CMakeLists.txt"), 70) FilePath::fromUserInput("src/1/app/CMakeLists.txt"), 70)
<< BuildSystemTask(Task::Error, << CMakeTask(Task::Error,
"Cannot find source file:\n\n" "Cannot find source file:\n\n"
" CMakeLists.txt2\n\n" " CMakeLists.txt2\n\n"
"Tried extensions " "Tried extensions "
@@ -323,7 +318,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << CMakeTask(Task::Error,
"add_subdirectory given source \"app1\" which is not an existing directory.", "add_subdirectory given source \"app1\" which is not an existing directory.",
FilePath::fromUserInput("src/1/CMakeLists.txt"), 8)); FilePath::fromUserInput("src/1/CMakeLists.txt"), 8));
@@ -333,7 +328,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << CMakeTask(Task::Error,
"Unknown CMake command \"i_am_wrong_command\".", "Unknown CMake command \"i_am_wrong_command\".",
FilePath::fromUserInput("src/1/CMakeLists.txt"), 8)); FilePath::fromUserInput("src/1/CMakeLists.txt"), 8));
@@ -343,7 +338,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << CMakeTask(Task::Error,
"message called with incorrect number of arguments", "message called with incorrect number of arguments",
FilePath::fromUserInput("src/1/CMakeLists.txt"), 8)); FilePath::fromUserInput("src/1/CMakeLists.txt"), 8));
@@ -355,7 +350,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << CMakeTask(Task::Error,
"Parse error. Expected \"(\", got newline with text \"\n\".", "Parse error. Expected \"(\", got newline with text \"\n\".",
FilePath::fromUserInput("/test/path/CMakeLists.txt"), 9)); FilePath::fromUserInput("/test/path/CMakeLists.txt"), 9));
@@ -366,7 +361,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList{"Missing variable is:", "CMAKE_MAKE_PROGRAM"} << QStringList() << QStringList{"Missing variable is:", "CMAKE_MAKE_PROGRAM"}
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << CMakeTask(Task::Error,
"Error required internal CMake variable not set, " "Error required internal CMake variable not set, "
"cmake may be not be built correctly.")); "cmake may be not be built correctly."));
@@ -378,7 +373,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << CMakeTask(Task::Error,
"Parse error. Expected \"(\", got newline with text \"\n" "Parse error. Expected \"(\", got newline with text \"\n"
"\n" "\n"
"\".", "\".",
@@ -391,7 +386,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Warning, << CMakeTask(Task::Warning,
"Argument not separated from preceding token by whitespace.", "Argument not separated from preceding token by whitespace.",
FilePath::fromUserInput("/test/path/CMakeLists.txt"), 9)); FilePath::fromUserInput("/test/path/CMakeLists.txt"), 9));
@@ -401,7 +396,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Warning, << CMakeTask(Task::Warning,
"this is a warning", "this is a warning",
FilePath::fromUserInput("CMakeLists.txt"), 13)); FilePath::fromUserInput("CMakeLists.txt"), 13));
@@ -411,7 +406,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Warning, << CMakeTask(Task::Warning,
"this is an author warning", "this is an author warning",
FilePath::fromUserInput("CMakeLists.txt"), 15)); FilePath::fromUserInput("CMakeLists.txt"), 15));
@@ -439,7 +434,7 @@ void CMakeOutputParserTest::testCMakeOutputParser_data()
"(qt6_add_executable)\n" "(qt6_add_executable)\n"
" /Projects/Test-Project/CMakeLists.txt:13 (qt_add_executable)\n") " /Projects/Test-Project/CMakeLists.txt:13 (qt_add_executable)\n")
<< OutputParserTester::STDERR << QStringList() << QStringList() << OutputParserTester::STDERR << QStringList() << QStringList()
<< (Tasks() << BuildSystemTask( << (Tasks() << CMakeTask(
Task::Error, Task::Error,
"\n" "\n"
"Cannot find source file:\n" "Cannot find source file:\n"
@@ -480,8 +475,8 @@ QObject *createCMakeOutputParserTest()
return new CMakeOutputParserTest; return new CMakeOutputParserTest;
} }
} // CMakeProjectManager::Internal
#endif #endif
} // CMakeProjectManager::Internal
#include "cmakeoutputparser.moc" #include "cmakeoutputparser.moc"

View File

@@ -3,8 +3,6 @@
#pragma once #pragma once
#include "cmake_global.h"
#include <projectexplorer/ioutputparser.h> #include <projectexplorer/ioutputparser.h>
#include <projectexplorer/task.h> #include <projectexplorer/task.h>
@@ -14,9 +12,9 @@
#include <optional> #include <optional>
namespace CMakeProjectManager { namespace CMakeProjectManager::Internal {
class CMAKE_EXPORT CMakeOutputParser : public ProjectExplorer::OutputTaskParser class CMakeOutputParser : public ProjectExplorer::OutputTaskParser
{ {
public: public:
explicit CMakeOutputParser(); explicit CMakeOutputParser();
@@ -52,8 +50,19 @@ private:
CallStackLine m_errorOrWarningLine; CallStackLine m_errorOrWarningLine;
}; };
class CMakeTask : public ProjectExplorer::BuildSystemTask
{
public:
CMakeTask(TaskType type, const QString &description, const Utils::FilePath &file = {},
int line = -1)
: ProjectExplorer::BuildSystemTask(type, description, file, line)
{
origin = "CMake";
}
};
#ifdef WITH_TESTS #ifdef WITH_TESTS
namespace Internal { QObject *createCMakeOutputParserTest(); } QObject *createCMakeOutputParserTest();
#endif #endif
} // CMakeProjectManager } // namespace CMakeProjectManager::Internal

View File

@@ -17,18 +17,11 @@
#include <projectexplorer/buildsystem.h> #include <projectexplorer/buildsystem.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/taskhub.h> #include <projectexplorer/taskhub.h>
#include <projectexplorer/kitchooser.h>
#include <extensionsystem/invoker.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/macroexpander.h> #include <utils/macroexpander.h>
#include <utils/processinfo.h>
#include <utils/processinterface.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <utils/stringutils.h> #include <utils/stringutils.h>
#include <utils/stylehelper.h>
#include <utils/theme/theme.h> #include <utils/theme/theme.h>
using namespace Core; using namespace Core;
@@ -154,7 +147,7 @@ void CMakeProcess::run(const BuildDirParameters &parameters, const QStringList &
if (m_process->result() != ProcessResult::FinishedWithSuccess) { if (m_process->result() != ProcessResult::FinishedWithSuccess) {
const QString message = m_process->exitMessage(); const QString message = m_process->exitMessage();
BuildSystem::appendBuildSystemOutput(addCMakePrefix({{}, message}).join('\n')); BuildSystem::appendBuildSystemOutput(addCMakePrefix({{}, message}).join('\n'));
TaskHub::addTask(BuildSystemTask(Task::Error, message)); TaskHub::addTask(CMakeTask(Task::Error, message));
} }
emit finished(m_process->exitCode()); emit finished(m_process->exitCode());

View File

@@ -32,6 +32,7 @@ ClangParser::ClangParser() :
m_expectSnippet(false) m_expectSnippet(false)
{ {
setObjectName(QLatin1String("ClangParser")); setObjectName(QLatin1String("ClangParser"));
setOrigin("Clang compiler");
} }
QList<OutputLineParser *> ClangParser::clangParserSuite() QList<OutputLineParser *> ClangParser::clangParserSuite()

View File

@@ -118,6 +118,7 @@ private:
GccParser::GccParser() GccParser::GccParser()
{ {
setObjectName(QLatin1String("GCCParser")); setObjectName(QLatin1String("GCCParser"));
setOrigin("GCC compiler");
m_regExpIncluded.setPattern(QString::fromLatin1("\\bfrom\\s") + filePattern() m_regExpIncluded.setPattern(QString::fromLatin1("\\bfrom\\s") + filePattern()
+ QLatin1String("(\\d+)(:\\d+)?[,:]?$")); + QLatin1String("(\\d+)(:\\d+)?[,:]?$"));

View File

@@ -16,9 +16,19 @@ using namespace Utils;
namespace ProjectExplorer { namespace ProjectExplorer {
namespace { namespace {
// optional full path, make executable name, optional exe extension, optional number in square brackets, colon space class MakeTask : public BuildSystemTask
const char * const MAKEEXEC_PATTERN("^(.*?[/\\\\])?(mingw(32|64)-|g)?make(.exe)?(\\[\\d+\\])?:\\s"); {
const char * const MAKEFILE_PATTERN("^((.*?[/\\\\])?[Mm]akefile(\\.[a-zA-Z]+)?):(\\d+):\\s"); public:
MakeTask(TaskType type, const QString &description, const Utils::FilePath &file = {},
int line = -1) : BuildSystemTask(type, description, file, line)
{
origin = "make";
}
};
// optional full path, make executable name, optional exe extension, optional number in square brackets, colon space
const char * const MAKEEXEC_PATTERN("^(.*?[/\\\\])?(mingw(32|64)-|g)?make(.exe)?(\\[\\d+\\])?:\\s");
const char * const MAKEFILE_PATTERN("^((.*?[/\\\\])?[Mm]akefile(\\.[a-zA-Z]+)?):(\\d+):\\s");
} }
GnuMakeParser::GnuMakeParser() GnuMakeParser::GnuMakeParser()
@@ -104,7 +114,7 @@ OutputLineParser::Result GnuMakeParser::handleLine(const QString &line, OutputFo
const FilePath file = absoluteFilePath(FilePath::fromUserInput(match.captured(1))); const FilePath file = absoluteFilePath(FilePath::fromUserInput(match.captured(1)));
const int lineNo = match.captured(4).toInt(); const int lineNo = match.captured(4).toInt();
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, match, 1); addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, match, 1);
emitTask(BuildSystemTask(res.type, res.description, file, lineNo)); emitTask(MakeTask(res.type, res.description, file, lineNo));
} }
return {Status::Done, linkSpecs}; return {Status::Done, linkSpecs};
} }
@@ -114,7 +124,7 @@ OutputLineParser::Result GnuMakeParser::handleLine(const QString &line, OutputFo
if (res.isFatal) if (res.isFatal)
++m_fatalErrorCount; ++m_fatalErrorCount;
if (!m_suppressIssues) if (!m_suppressIssues)
emitTask(BuildSystemTask(res.type, res.description)); emitTask(MakeTask(res.type, res.description));
return Status::Done; return Status::Done;
} }
@@ -216,7 +226,7 @@ void ProjectExplorerTest::testGnuMakeParserParsing_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << MakeTask(Task::Error,
"No rule to make target `hello.c', needed by `hello.o'. Stop.")) "No rule to make target `hello.c', needed by `hello.o'. Stop."))
<< QStringList(); << QStringList();
@@ -228,7 +238,7 @@ void ProjectExplorerTest::testGnuMakeParserParsing_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << MakeTask(Task::Error,
"[.obj/debug-shared/gnumakeparser.o] Error 1")) "[.obj/debug-shared/gnumakeparser.o] Error 1"))
<< QStringList(); << QStringList();
@@ -238,7 +248,7 @@ void ProjectExplorerTest::testGnuMakeParserParsing_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << MakeTask(Task::Error,
"missing separator (did you mean TAB instead of 8 spaces?). Stop.", "missing separator (did you mean TAB instead of 8 spaces?). Stop.",
Utils::FilePath::fromUserInput("Makefile"), 360)) Utils::FilePath::fromUserInput("Makefile"), 360))
<< QStringList(); << QStringList();
@@ -250,7 +260,7 @@ void ProjectExplorerTest::testGnuMakeParserParsing_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << MakeTask(Task::Error,
"[debug/qplotaxis.o] Error 1")) "[debug/qplotaxis.o] Error 1"))
<< QStringList(); << QStringList();
@@ -260,7 +270,7 @@ void ProjectExplorerTest::testGnuMakeParserParsing_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << MakeTask(Task::Error,
"[dynlib.inst] Error -1073741819")) "[dynlib.inst] Error -1073741819"))
<< QStringList(); << QStringList();
@@ -270,7 +280,7 @@ void ProjectExplorerTest::testGnuMakeParserParsing_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Warning, << MakeTask(Task::Warning,
"jobserver unavailable: using -j1. Add `+' to parent make rule.")) "jobserver unavailable: using -j1. Add `+' to parent make rule."))
<< QStringList(); << QStringList();
@@ -288,7 +298,7 @@ void ProjectExplorerTest::testGnuMakeParserParsing_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << MakeTask(Task::Error,
"[sis] Error 2")) "[sis] Error 2"))
<< QStringList(); << QStringList();
@@ -298,7 +308,7 @@ void ProjectExplorerTest::testGnuMakeParserParsing_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << MakeTask(Task::Error,
"g++: Command not found")) "g++: Command not found"))
<< QStringList(); << QStringList();
@@ -308,7 +318,7 @@ void ProjectExplorerTest::testGnuMakeParserParsing_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Warning, << MakeTask(Task::Warning,
"overriding commands for target `xxxx.app/Contents/Info.plist'", "overriding commands for target `xxxx.app/Contents/Info.plist'",
"Makefile", 794)) "Makefile", 794))
<< QStringList(); << QStringList();
@@ -371,7 +381,7 @@ void ProjectExplorerTest::testGnuMakeParserTaskMangling()
testbench.testParsing( testbench.testParsing(
fi.fileName() + ":360: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.", fi.fileName() + ":360: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.",
OutputParserTester::STDERR, OutputParserTester::STDERR,
{BuildSystemTask(Task::Error, {MakeTask(Task::Error,
"missing separator (did you mean TAB instead of 8 spaces?). Stop.", "missing separator (did you mean TAB instead of 8 spaces?). Stop.",
FilePath::fromString(theMakeFile.fileName()), 360)}, FilePath::fromString(theMakeFile.fileName()), 360)},
{}, {}); {}, {});

View File

@@ -60,6 +60,7 @@ public:
QList<TaskInfo> scheduledTasks; QList<TaskInfo> scheduledTasks;
Task currentTask; Task currentTask;
LinkSpecs linkSpecs; LinkSpecs linkSpecs;
QString origin;
int lineCount = 0; int lineCount = 0;
bool targetLinkFixed = false; bool targetLinkFixed = false;
}; };
@@ -140,6 +141,7 @@ void OutputTaskParser::createOrAmendTask(
flush(); flush();
d->currentTask = CompileTask(type, description, file, line, column); d->currentTask = CompileTask(type, description, file, line, column);
d->currentTask.details.append(originalLine); d->currentTask.details.append(originalLine);
d->currentTask.origin = d->origin;
d->linkSpecs = linkSpecs; d->linkSpecs = linkSpecs;
d->lineCount = 1; d->lineCount = 1;
return; return;
@@ -212,4 +214,10 @@ void OutputTaskParser::flush()
d->lineCount = 0; d->lineCount = 0;
d->targetLinkFixed = false; d->targetLinkFixed = false;
} }
void OutputTaskParser::setOrigin(const QString &source)
{
d->origin = source;
}
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -30,6 +30,7 @@ public:
protected: protected:
void flush() override; void flush() override;
void setOrigin(const QString &source);
void scheduleTask(const Task &task, int outputLines, int skippedLines = 0); void scheduleTask(const Task &task, int outputLines, int skippedLines = 0);
void setDetailsFormat(Task &task, const LinkSpecs &linkSpecs = {}); void setDetailsFormat(Task &task, const LinkSpecs &linkSpecs = {});
void fixTargetLink(); void fixTargetLink();

View File

@@ -20,6 +20,7 @@ namespace ProjectExplorer::Internal {
LdParser::LdParser() LdParser::LdParser()
{ {
setObjectName(QLatin1String("LdParser")); setObjectName(QLatin1String("LdParser"));
setOrigin("ld linker");
} }
OutputLineParser::Result LdParser::handleLine(const QString &line, OutputFormat type) OutputLineParser::Result LdParser::handleLine(const QString &line, OutputFormat type)

View File

@@ -4,7 +4,6 @@
#include "linuxiccparser.h" #include "linuxiccparser.h"
#include "ldparser.h" #include "ldparser.h"
#include "lldparser.h" #include "lldparser.h"
#include "projectexplorerconstants.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -15,6 +14,8 @@ namespace ProjectExplorer {
LinuxIccParser::LinuxIccParser() LinuxIccParser::LinuxIccParser()
{ {
setObjectName(QLatin1String("LinuxIccParser")); setObjectName(QLatin1String("LinuxIccParser"));
setOrigin("ICC compiler");
// main.cpp(53): error #308: function \"AClass::privatefunc\" (declared at line 4 of \"main.h\") is inaccessible // main.cpp(53): error #308: function \"AClass::privatefunc\" (declared at line 4 of \"main.h\") is inaccessible
m_firstLine.setPattern(QLatin1String("^([^\\(\\)]+?)" // filename (cap 1) m_firstLine.setPattern(QLatin1String("^([^\\(\\)]+?)" // filename (cap 1)

View File

@@ -77,6 +77,8 @@ static Task::TaskType taskType(const QString &category)
MsvcParser::MsvcParser() MsvcParser::MsvcParser()
{ {
setObjectName("MsvcParser"); setObjectName("MsvcParser");
setOrigin("MSVC compiler");
m_compileRegExp.setPattern(QString(FILE_POS_PATTERN) m_compileRegExp.setPattern(QString(FILE_POS_PATTERN)
+ ".*(?:(warning|error) ([A-Z]+\\d{4} ?: )|note: )(.*)$"); + ".*(?:(warning|error) ([A-Z]+\\d{4} ?: )|note: )(.*)$");
QTC_CHECK(m_compileRegExp.isValid()); QTC_CHECK(m_compileRegExp.isValid());

View File

@@ -71,6 +71,7 @@ public:
int movedLine = -1; // contains a line number if the line was moved in the editor int movedLine = -1; // contains a line number if the line was moved in the editor
int column = 0; int column = 0;
Utils::Id category; Utils::Id category;
QString origin;
// Having a container of QTextLayout::FormatRange in Task isn't that great // Having a container of QTextLayout::FormatRange in Task isn't that great
// It would be cleaner to split up the text into // It would be cleaner to split up the text into

View File

@@ -179,7 +179,9 @@ QbsBuildSystem::QbsBuildSystem(BuildConfiguration *bc)
}); });
connect(m_session, &QbsSession::errorOccurred, this, [](QbsSession::Error e) { connect(m_session, &QbsSession::errorOccurred, this, [](QbsSession::Error e) {
const QString msg = Tr::tr("Fatal qbs error: %1").arg(QbsSession::errorString(e)); const QString msg = Tr::tr("Fatal qbs error: %1").arg(QbsSession::errorString(e));
TaskHub::addTask(BuildSystemTask(Task::Error, msg)); BuildSystemTask t(Task::Error, msg);
t.origin = "qbs";
TaskHub::addTask(t);
}); });
connect(m_session, &QbsSession::fileListUpdated, this, &QbsBuildSystem::delayParsing); connect(m_session, &QbsSession::fileListUpdated, this, &QbsBuildSystem::delayParsing);

View File

@@ -723,8 +723,11 @@ QString ErrorInfo::toString() const
void ErrorInfo::generateTasks(ProjectExplorer::Task::TaskType type) const void ErrorInfo::generateTasks(ProjectExplorer::Task::TaskType type) const
{ {
for (const ErrorInfoItem &item : items) for (const ErrorInfoItem &item : items) {
TaskHub::addTask(BuildSystemTask(type, item.description, item.filePath, item.line)); BuildSystemTask t(type, item.description, item.filePath, item.line);
t.origin = "qbs";
TaskHub::addTask(t);
}
} }
void forAllProducts(const QJsonObject &project, const WorkerFunction &productFunction) void forAllProducts(const QJsonObject &project, const WorkerFunction &productFunction)

View File

@@ -11,6 +11,7 @@ using namespace ProjectExplorer;
using namespace Utils; using namespace Utils;
namespace QmakeProjectManager { namespace QmakeProjectManager {
using namespace Internal;
QMakeParser::QMakeParser() : m_error(QLatin1String("^(.+?):(\\d+?):\\s(.+?)$")) QMakeParser::QMakeParser() : m_error(QLatin1String("^(.+?):(\\d+?):\\s(.+?)$"))
{ {
@@ -43,7 +44,7 @@ OutputLineParser::Result QMakeParser::handleLine(const QString &line, OutputForm
else if (description.startsWith(QLatin1String("error:"), Qt::CaseInsensitive)) else if (description.startsWith(QLatin1String("error:"), Qt::CaseInsensitive))
type = Task::Error; type = Task::Error;
BuildSystemTask t(type, description, absoluteFilePath(FilePath::fromUserInput(fileName)), QmakeTask t(type, description, absoluteFilePath(FilePath::fromUserInput(fileName)),
match.captured(2).toInt() /* line */); match.captured(2).toInt() /* line */);
LinkSpecs linkSpecs; LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, t.column, fileNameOffset, addLinkSpecForAbsoluteFilePath(linkSpecs, t.file, t.line, t.column, fileNameOffset,
@@ -54,13 +55,13 @@ OutputLineParser::Result QMakeParser::handleLine(const QString &line, OutputForm
if (lne.startsWith(QLatin1String("Project ERROR: ")) if (lne.startsWith(QLatin1String("Project ERROR: "))
|| lne.startsWith(QLatin1String("ERROR: "))) { || lne.startsWith(QLatin1String("ERROR: "))) {
const QString description = lne.mid(lne.indexOf(QLatin1Char(':')) + 2); const QString description = lne.mid(lne.indexOf(QLatin1Char(':')) + 2);
scheduleTask(BuildSystemTask(Task::Error, description), 1); scheduleTask(QmakeTask(Task::Error, description), 1);
return Status::Done; return Status::Done;
} }
if (lne.startsWith(QLatin1String("Project WARNING: ")) if (lne.startsWith(QLatin1String("Project WARNING: "))
|| lne.startsWith(QLatin1String("WARNING: "))) { || lne.startsWith(QLatin1String("WARNING: "))) {
const QString description = lne.mid(lne.indexOf(QLatin1Char(':')) + 2); const QString description = lne.mid(lne.indexOf(QLatin1Char(':')) + 2);
scheduleTask(BuildSystemTask(Task::Warning, description), 1); scheduleTask(QmakeTask(Task::Warning, description), 1);
return Status::Done; return Status::Done;
} }
return Status::NotHandled; return Status::NotHandled;
@@ -109,7 +110,7 @@ void QmakeOutputParserTest::testQmakeOutputParsers_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << QmakeTask(Task::Error,
"undefined file")); "undefined file"));
QTest::newRow("qMake Parse Error") QTest::newRow("qMake Parse Error")
@@ -117,7 +118,7 @@ void QmakeOutputParserTest::testQmakeOutputParsers_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Error, << QmakeTask(Task::Error,
"Parse Error ('sth odd')", "Parse Error ('sth odd')",
FilePath::fromUserInput("e:\\project.pro"), FilePath::fromUserInput("e:\\project.pro"),
14)); 14));
@@ -127,7 +128,7 @@ void QmakeOutputParserTest::testQmakeOutputParsers_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Warning, << QmakeTask(Task::Warning,
"bearer module might require ReadUserData capability")); "bearer module might require ReadUserData capability"));
QTest::newRow("qMake warning 2") QTest::newRow("qMake warning 2")
@@ -135,7 +136,7 @@ void QmakeOutputParserTest::testQmakeOutputParsers_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Warning, << QmakeTask(Task::Warning,
"Failure to find: blackberrycreatepackagestepconfigwidget.cpp")); "Failure to find: blackberrycreatepackagestepconfigwidget.cpp"));
QTest::newRow("qMake warning with location") QTest::newRow("qMake warning with location")
@@ -143,7 +144,7 @@ void QmakeOutputParserTest::testQmakeOutputParsers_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Warning, << QmakeTask(Task::Warning,
"Unescaped backslashes are deprecated.", "Unescaped backslashes are deprecated.",
FilePath::fromUserInput("e:\\QtSDK\\Simulator\\Qt\\msvc2008\\lib\\qtmaind.prl"), 1)); FilePath::fromUserInput("e:\\QtSDK\\Simulator\\Qt\\msvc2008\\lib\\qtmaind.prl"), 1));
@@ -152,7 +153,7 @@ void QmakeOutputParserTest::testQmakeOutputParsers_data()
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QStringList() << QStringList() << QStringList() << QStringList()
<< (Tasks() << (Tasks()
<< BuildSystemTask(Task::Unknown, << QmakeTask(Task::Unknown,
"Note: No relevant classes found. No output generated.", "Note: No relevant classes found. No output generated.",
FilePath::fromUserInput("/home/qtwebkithelpviewer.h"), -1)); FilePath::fromUserInput("/home/qtwebkithelpviewer.h"), -1));
} }

View File

@@ -22,8 +22,22 @@ private:
const QRegularExpression m_error; const QRegularExpression m_error;
}; };
namespace Internal {
class QmakeTask : public ProjectExplorer::BuildSystemTask
{
public:
QmakeTask(TaskType type, const QString &description, const Utils::FilePath &file = {},
int line = -1)
: ProjectExplorer::BuildSystemTask(type, description, file, line)
{
origin = "qmake";
}
};
#ifdef WITH_TESTS #ifdef WITH_TESTS
namespace Internal { QObject *createQmakeOutputParserTest(); } QObject *createQmakeOutputParserTest();
#endif #endif
} // namespace Internal
} // namespace QmakeProjectManager } // namespace QmakeProjectManager

View File

@@ -6,6 +6,7 @@
#include "qmakebuildconfiguration.h" #include "qmakebuildconfiguration.h"
#include "qmakenodes.h" #include "qmakenodes.h"
#include "qmakenodetreebuilder.h" #include "qmakenodetreebuilder.h"
#include "qmakeparser.h"
#include "qmakeprojectimporter.h" #include "qmakeprojectimporter.h"
#include "qmakeprojectmanagerconstants.h" #include "qmakeprojectmanagerconstants.h"
#include "qmakeprojectmanagertr.h" #include "qmakeprojectmanagertr.h"
@@ -18,7 +19,6 @@
#include <cppeditor/cppmodelmanager.h> #include <cppeditor/cppmodelmanager.h>
#include <cppeditor/generatedcodemodelsupport.h> #include <cppeditor/generatedcodemodelsupport.h>
#include <cppeditor/projectinfo.h>
#include <projectexplorer/buildinfo.h> #include <projectexplorer/buildinfo.h>
#include <projectexplorer/buildmanager.h> #include <projectexplorer/buildmanager.h>
@@ -831,7 +831,7 @@ FilePath QmakeBuildSystem::buildDir(const FilePath &proFilePath) const
void QmakeBuildSystem::proFileParseError(const QString &errorMessage, const FilePath &filePath) void QmakeBuildSystem::proFileParseError(const QString &errorMessage, const FilePath &filePath)
{ {
TaskHub::addTask(BuildSystemTask(Task::Error, errorMessage, filePath)); TaskHub::addTask(QmakeTask(Task::Error, errorMessage, filePath));
} }
QtSupport::ProFileReader *QmakeBuildSystem::createProFileReader(const QmakeProFile *qmakeProFile) QtSupport::ProFileReader *QmakeBuildSystem::createProFileReader(const QmakeProFile *qmakeProFile)