forked from qt-creator/qt-creator
Output parsers: Replace the chaining approach
Use "flat" aggregation instead. This is another step towards the formatter/parser merger. Along the way, also fix some some subclasses (mostly in BareMetal) that erroneously forwarded handled output to other parsers. Task-number: QTCREATORBUG-22665 Change-Id: I12947349ca663d2e6bbfc99efd069d69e2b54969 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -112,9 +112,7 @@ bool AndroidPackageInstallationStep::init()
|
|||||||
pp->setCommandLine(cmd);
|
pp->setCommandLine(cmd);
|
||||||
|
|
||||||
setOutputParser(new GnuMakeParser());
|
setOutputParser(new GnuMakeParser());
|
||||||
IOutputParser *parser = target()->kit()->createOutputParser();
|
appendOutputParsers(target()->kit()->createOutputParsers());
|
||||||
if (parser)
|
|
||||||
appendOutputParser(parser);
|
|
||||||
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
||||||
|
|
||||||
m_androidDirsToClean.clear();
|
m_androidDirsToClean.clear();
|
||||||
|
@@ -51,39 +51,33 @@ void JavaParser::setSourceDirectory(const Utils::FilePath &sourceDirectory)
|
|||||||
m_sourceDirectory = sourceDirectory;
|
m_sourceDirectory = sourceDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaParser::handleLine(const QString &line, Utils::OutputFormat type)
|
IOutputParser::Status JavaParser::doHandleLine(const QString &line, Utils::OutputFormat type)
|
||||||
{
|
{
|
||||||
parse(line);
|
Q_UNUSED(type);
|
||||||
IOutputParser::handleLine(line, type);
|
if (m_javaRegExp.indexIn(line) == -1)
|
||||||
}
|
return Status::NotHandled;
|
||||||
|
|
||||||
void JavaParser::parse(const QString &line)
|
bool ok;
|
||||||
{
|
int lineno = m_javaRegExp.cap(3).toInt(&ok);
|
||||||
if (m_javaRegExp.indexIn(line) > -1) {
|
if (!ok)
|
||||||
bool ok;
|
lineno = -1;
|
||||||
int lineno = m_javaRegExp.cap(3).toInt(&ok);
|
Utils::FilePath file = Utils::FilePath::fromUserInput(m_javaRegExp.cap(2));
|
||||||
if (!ok)
|
if (file.isChildOf(m_buildDirectory)) {
|
||||||
lineno = -1;
|
Utils::FilePath relativePath = file.relativeChildPath(m_buildDirectory);
|
||||||
Utils::FilePath file = Utils::FilePath::fromUserInput(m_javaRegExp.cap(2));
|
file = m_sourceDirectory.pathAppended(relativePath.toString());
|
||||||
if (file.isChildOf(m_buildDirectory)) {
|
}
|
||||||
Utils::FilePath relativePath = file.relativeChildPath(m_buildDirectory);
|
if (file.toFileInfo().isRelative()) {
|
||||||
file = m_sourceDirectory.pathAppended(relativePath.toString());
|
for (int i = 0; i < m_fileList.size(); i++)
|
||||||
}
|
if (m_fileList[i].endsWith(file.toString())) {
|
||||||
|
file = Utils::FilePath::fromString(m_fileList[i]);
|
||||||
if (file.toFileInfo().isRelative()) {
|
break;
|
||||||
for (int i = 0; i < m_fileList.size(); i++)
|
}
|
||||||
if (m_fileList[i].endsWith(file.toString())) {
|
|
||||||
file = Utils::FilePath::fromString(m_fileList[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CompileTask task(Task::Error,
|
|
||||||
m_javaRegExp.cap(4).trimmed(),
|
|
||||||
absoluteFilePath(file),
|
|
||||||
lineno);
|
|
||||||
emit addTask(task, 1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CompileTask task(Task::Error,
|
||||||
|
m_javaRegExp.cap(4).trimmed(),
|
||||||
|
absoluteFilePath(file),
|
||||||
|
lineno);
|
||||||
|
emit addTask(task, 1);
|
||||||
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
@@ -45,8 +45,7 @@ public:
|
|||||||
void setSourceDirectory(const Utils::FilePath &sourceDirectory);
|
void setSourceDirectory(const Utils::FilePath &sourceDirectory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
void parse(const QString &line);
|
|
||||||
|
|
||||||
QRegExp m_javaRegExp;
|
QRegExp m_javaRegExp;
|
||||||
QStringList m_fileList;
|
QStringList m_fileList;
|
||||||
|
@@ -190,67 +190,56 @@ bool IarParser::parseErrorMessage1(const QString &lne)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IarParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status IarParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type == StdOutFormat)
|
|
||||||
stdOutput(line);
|
|
||||||
else
|
|
||||||
stdError(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IarParser::stdError(const QString &line)
|
|
||||||
{
|
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
|
||||||
|
|
||||||
const QString lne = rightTrimmed(line);
|
const QString lne = rightTrimmed(line);
|
||||||
|
if (type == StdOutFormat) {
|
||||||
|
// The call sequence has the meaning!
|
||||||
|
const bool leastOneParsed = parseErrorInCommandLineMessage(lne)
|
||||||
|
|| parseErrorMessage1(lne);
|
||||||
|
if (!leastOneParsed) {
|
||||||
|
doFlush();
|
||||||
|
return Status::NotHandled;
|
||||||
|
}
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
|
||||||
if (parseErrorOrFatalErrorDetailsMessage1(lne))
|
if (parseErrorOrFatalErrorDetailsMessage1(lne))
|
||||||
return;
|
return Status::InProgress;
|
||||||
if (parseErrorOrFatalErrorDetailsMessage2(lne))
|
if (parseErrorOrFatalErrorDetailsMessage2(lne))
|
||||||
return;
|
return Status::InProgress;
|
||||||
if (parseWarningOrErrorOrFatalErrorDetailsMessage1(lne))
|
if (parseWarningOrErrorOrFatalErrorDetailsMessage1(lne))
|
||||||
return;
|
return Status::InProgress;
|
||||||
|
|
||||||
if (lne.isEmpty()) {
|
if (m_expectFilePath) {
|
||||||
//
|
|
||||||
} else if (!lne.startsWith(' ')) {
|
|
||||||
return;
|
|
||||||
} else if (m_expectFilePath) {
|
|
||||||
if (lne.endsWith(']')) {
|
if (lne.endsWith(']')) {
|
||||||
const QString lastPart = lne.left(lne.size() - 1);
|
const QString lastPart = lne.left(lne.size() - 1);
|
||||||
m_filePathParts.push_back(lastPart);
|
m_filePathParts.push_back(lastPart);
|
||||||
|
doFlush();
|
||||||
|
return Status::Done;
|
||||||
} else {
|
} else {
|
||||||
m_filePathParts.push_back(lne);
|
m_filePathParts.push_back(lne);
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
} else if (m_expectSnippet) {
|
}
|
||||||
|
if (m_expectSnippet && lne.startsWith(' ')) {
|
||||||
if (!lne.endsWith("Fatal error detected, aborting.")) {
|
if (!lne.endsWith("Fatal error detected, aborting.")) {
|
||||||
m_snippets.push_back(lne);
|
m_snippets.push_back(lne);
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
} else if (m_expectDescription) {
|
} else if (m_expectDescription) {
|
||||||
if (!lne.startsWith(" ")) {
|
if (!lne.startsWith(" ")) {
|
||||||
m_descriptionParts.push_back(lne.trimmed());
|
m_descriptionParts.push_back(lne.trimmed());
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doFlush();
|
if (!m_lastTask.isNull()) {
|
||||||
}
|
doFlush();
|
||||||
|
return Status::Done;
|
||||||
|
}
|
||||||
|
|
||||||
void IarParser::stdOutput(const QString &line)
|
return Status::NotHandled;
|
||||||
{
|
|
||||||
IOutputParser::handleLine(line, StdOutFormat);
|
|
||||||
|
|
||||||
const QString lne = rightTrimmed(line);
|
|
||||||
|
|
||||||
// The call sequence has the meaning!
|
|
||||||
const bool leastOneParsed = parseErrorInCommandLineMessage(lne)
|
|
||||||
|| parseErrorMessage1(lne);
|
|
||||||
if (!leastOneParsed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
doFlush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IarParser::doFlush()
|
void IarParser::doFlush()
|
||||||
@@ -308,7 +297,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
QTest::newRow("Error in command line")
|
QTest::newRow("Error in command line")
|
||||||
<< QString::fromLatin1("Error in command line: Some error")
|
<< QString::fromLatin1("Error in command line: Some error")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("Error in command line: Some error\n")
|
<< QString()
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"Error in command line: Some error"))
|
"Error in command line: Some error"))
|
||||||
@@ -317,7 +306,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
QTest::newRow("Linker error")
|
QTest::newRow("Linker error")
|
||||||
<< QString::fromLatin1("Error[e46]: Some error")
|
<< QString::fromLatin1("Error[e46]: Some error")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("Error[e46]: Some error\n")
|
<< QString()
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"[e46]: Some error"))
|
"[e46]: Some error"))
|
||||||
@@ -329,8 +318,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
" Some warning \"foo\" bar")
|
" Some warning \"foo\" bar")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
|
<< QString()
|
||||||
" Some warning \"foo\" bar\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"[Pe223]: Some warning \"foo\" bar",
|
"[Pe223]: Some warning \"foo\" bar",
|
||||||
Utils::FilePath::fromUserInput("c:\\foo\\main.c"),
|
Utils::FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -344,10 +332,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
" Some warning")
|
" Some warning")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1(" some_detail;\n"
|
<< QString()
|
||||||
" ^\n"
|
|
||||||
"\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
|
|
||||||
" Some warning\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"[Pe223]: Some warning\n"
|
"[Pe223]: Some warning\n"
|
||||||
" some_detail;\n"
|
" some_detail;\n"
|
||||||
@@ -362,9 +347,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
" , split")
|
" , split")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\",63 Warning[Pe223]:\n"
|
<< QString()
|
||||||
" Some warning\n"
|
|
||||||
" , split\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"[Pe223]: Some warning, split",
|
"[Pe223]: Some warning, split",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -376,8 +359,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
" Some error")
|
" Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\",63 Error[Pe223]:\n"
|
<< QString()
|
||||||
" Some error\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"[Pe223]: Some error",
|
"[Pe223]: Some error",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -391,10 +373,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
" Some error")
|
" Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1(" some_detail;\n"
|
<< QString()
|
||||||
" ^\n"
|
|
||||||
"\"c:\\foo\\main.c\",63 Error[Pe223]:\n"
|
|
||||||
" Some error\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"[Pe223]: Some error\n"
|
"[Pe223]: Some error\n"
|
||||||
" some_detail;\n"
|
" some_detail;\n"
|
||||||
@@ -409,9 +388,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
" , split")
|
" , split")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\",63 Error[Pe223]:\n"
|
<< QString()
|
||||||
" Some error\n"
|
|
||||||
" , split\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"[Pe223]: Some error, split",
|
"[Pe223]: Some error, split",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -425,10 +402,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
"]")
|
"]")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("Error[Li005]: Some error \"foo\" [referenced from c:\\fo\n"
|
<< QString()
|
||||||
" o\\bar\\mai\n"
|
|
||||||
" n.c.o\n"
|
|
||||||
"]\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"[Li005]: Some error \"foo\"",
|
"[Li005]: Some error \"foo\"",
|
||||||
FilePath::fromUserInput("c:\\foo\\bar\\main.c.o")))
|
FilePath::fromUserInput("c:\\foo\\bar\\main.c.o")))
|
||||||
@@ -441,10 +415,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
"Fatal error detected, aborting.")
|
"Fatal error detected, aborting.")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("Fatal error[Su011]: Some error:\n"
|
<< QString()
|
||||||
" c:\\foo.c\n"
|
|
||||||
" c:\\bar.c\n"
|
|
||||||
"Fatal error detected, aborting.\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"[Su011]: Some error:\n"
|
"[Su011]: Some error:\n"
|
||||||
" c:\\foo.c\n"
|
" c:\\foo.c\n"
|
||||||
@@ -455,7 +426,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
<< QString::fromLatin1("At end of source Error[Pe040]: Some error \";\"")
|
<< QString::fromLatin1("At end of source Error[Pe040]: Some error \";\"")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("At end of source Error[Pe040]: Some error \";\"\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"[Pe040]: Some error \";\""))
|
"[Pe040]: Some error \";\""))
|
||||||
<< QString();
|
<< QString();
|
||||||
@@ -464,7 +435,7 @@ void BareMetalPlugin::testIarOutputParsers_data()
|
|||||||
void BareMetalPlugin::testIarOutputParsers()
|
void BareMetalPlugin::testIarOutputParsers()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new IarParser);
|
testbench.addLineParser(new IarParser);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -52,9 +52,7 @@ private:
|
|||||||
bool parseErrorInCommandLineMessage(const QString &lne);
|
bool parseErrorInCommandLineMessage(const QString &lne);
|
||||||
bool parseErrorMessage1(const QString &lne);
|
bool parseErrorMessage1(const QString &lne);
|
||||||
|
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) final;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) final;
|
||||||
void stdError(const QString &line);
|
|
||||||
void stdOutput(const QString &line);
|
|
||||||
void doFlush() final;
|
void doFlush() final;
|
||||||
|
|
||||||
ProjectExplorer::Task m_lastTask;
|
ProjectExplorer::Task m_lastTask;
|
||||||
|
@@ -354,9 +354,9 @@ void IarToolChain::addToEnvironment(Environment &env) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *IarToolChain::outputParser() const
|
QList<IOutputParser *> IarToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
return new IarParser;
|
return {new IarParser()};
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap IarToolChain::toMap() const
|
QVariantMap IarToolChain::toMap() const
|
||||||
|
@@ -68,7 +68,7 @@ public:
|
|||||||
const Utils::FilePath &,
|
const Utils::FilePath &,
|
||||||
const Utils::Environment &env) const final;
|
const Utils::Environment &env) const final;
|
||||||
void addToEnvironment(Utils::Environment &env) const final;
|
void addToEnvironment(Utils::Environment &env) const final;
|
||||||
ProjectExplorer::IOutputParser *outputParser() const final;
|
QList<ProjectExplorer::IOutputParser *> outputParsers() const final;
|
||||||
|
|
||||||
QVariantMap toMap() const final;
|
QVariantMap toMap() const final;
|
||||||
bool fromMap(const QVariantMap &data) final;
|
bool fromMap(const QVariantMap &data) final;
|
||||||
|
@@ -190,34 +190,6 @@ bool KeilParser::parseMcs51FatalErrorMessage2(const QString &lne)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeilParser::handleLine(const QString &line, OutputFormat type)
|
|
||||||
{
|
|
||||||
if (type == StdOutFormat)
|
|
||||||
stdOutput(line);
|
|
||||||
else
|
|
||||||
stdError(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeilParser::stdError(const QString &line)
|
|
||||||
{
|
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
|
||||||
|
|
||||||
const QString lne = rightTrimmed(line);
|
|
||||||
|
|
||||||
// Check for ARM compiler specific patterns.
|
|
||||||
if (parseArmWarningOrErrorDetailsMessage(lne))
|
|
||||||
return;
|
|
||||||
if (parseArmErrorOrFatalErorrMessage(lne))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (lne.startsWith(' ')) {
|
|
||||||
m_snippets.push_back(lne);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
doFlush();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool hasDetailsEntry(const QString &trimmedLine)
|
static bool hasDetailsEntry(const QString &trimmedLine)
|
||||||
{
|
{
|
||||||
const QRegularExpression re("^([0-9A-F]{4})");
|
const QRegularExpression re("^([0-9A-F]{4})");
|
||||||
@@ -234,46 +206,59 @@ static bool hasDetailsPointer(const QString &trimmedLine)
|
|||||||
return trimmedLine.contains('_');
|
return trimmedLine.contains('_');
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeilParser::stdOutput(const QString &line)
|
IOutputParser::Status KeilParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
IOutputParser::handleLine(line, StdOutFormat);
|
|
||||||
|
|
||||||
QString lne = rightTrimmed(line);
|
QString lne = rightTrimmed(line);
|
||||||
|
if (type == StdOutFormat) {
|
||||||
// Check for MSC51 compiler specific patterns.
|
// Check for MSC51 compiler specific patterns.
|
||||||
const bool parsed = parseMcs51WarningOrErrorDetailsMessage1(lne)
|
const bool parsed = parseMcs51WarningOrErrorDetailsMessage1(lne)
|
||||||
|| parseMcs51WarningOrErrorDetailsMessage2(lne);
|
|| parseMcs51WarningOrErrorDetailsMessage2(lne);
|
||||||
if (!parsed) {
|
if (parsed)
|
||||||
|
return Status::InProgress;
|
||||||
if (parseMcs51WarningOrFatalErrorMessage(lne))
|
if (parseMcs51WarningOrFatalErrorMessage(lne))
|
||||||
return;
|
return Status::InProgress;
|
||||||
if (parseMcs51FatalErrorMessage2(lne))
|
if (parseMcs51FatalErrorMessage2(lne))
|
||||||
return;
|
return Status::InProgress;
|
||||||
|
|
||||||
|
if (m_lastTask.isNull()) {
|
||||||
|
// Check for details, which are comes on a previous
|
||||||
|
// lines, before the message.
|
||||||
|
|
||||||
|
// This code handles the details in a form like:
|
||||||
|
// 0000 24 ljmp usb_stub_isr ; (00) Setup data available.
|
||||||
|
// *** _____________________________________^
|
||||||
|
// 003C 54 ljmp usb_stub_isr ; (3C) EP8 in/out.
|
||||||
|
// *** _____________________________________^
|
||||||
|
if (hasDetailsEntry(lne) || hasDetailsPointer(lne)) {
|
||||||
|
lne.replace(0, 4, " ");
|
||||||
|
m_snippets.push_back(lne);
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check for details, which are comes on a next
|
||||||
|
// lines, after the message.
|
||||||
|
if (lne.startsWith(' ')) {
|
||||||
|
m_snippets.push_back(lne);
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doFlush();
|
||||||
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_lastTask.isNull()) {
|
// Check for ARM compiler specific patterns.
|
||||||
// Check for details, which are comes on a previous
|
if (parseArmWarningOrErrorDetailsMessage(lne))
|
||||||
// lines, before the message.
|
return Status::InProgress;
|
||||||
|
if (parseArmErrorOrFatalErorrMessage(lne))
|
||||||
|
return Status::InProgress;
|
||||||
|
|
||||||
// This code handles the details in a form like:
|
if (lne.startsWith(' ')) {
|
||||||
// 0000 24 ljmp usb_stub_isr ; (00) Setup data available.
|
m_snippets.push_back(lne);
|
||||||
// *** _____________________________________^
|
return Status::InProgress;
|
||||||
// 003C 54 ljmp usb_stub_isr ; (3C) EP8 in/out.
|
|
||||||
// *** _____________________________________^
|
|
||||||
if (hasDetailsEntry(lne) || hasDetailsPointer(lne)) {
|
|
||||||
lne.replace(0, 4, " ");
|
|
||||||
m_snippets.push_back(lne);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Check for details, which are comes on a next
|
|
||||||
// lines, after the message.
|
|
||||||
if (lne.startsWith(' ')) {
|
|
||||||
m_snippets.push_back(lne);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doFlush();
|
doFlush();
|
||||||
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeilParser::doFlush()
|
void KeilParser::doFlush()
|
||||||
@@ -328,7 +313,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Warning: #1234: Some warning")
|
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Warning: #1234: Some warning")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Warning: #1234: Some warning\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"#1234: Some warning",
|
"#1234: Some warning",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -341,9 +326,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
" ^")
|
" ^")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Warning: #1234: Some warning\n"
|
<< QString()
|
||||||
" int f;\n"
|
|
||||||
" ^\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"#1234: Some warning\n"
|
"#1234: Some warning\n"
|
||||||
" int f;\n"
|
" int f;\n"
|
||||||
@@ -356,7 +339,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Error: #1234: Some error")
|
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Error: #1234: Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Error: #1234: Some error\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"#1234: Some error",
|
"#1234: Some error",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -367,7 +350,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
<< QString::fromLatin1("\"flash.sct\", line 51 (column 20): Error: L1234: Some error")
|
<< QString::fromLatin1("\"flash.sct\", line 51 (column 20): Error: L1234: Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"flash.sct\", line 51 (column 20): Error: L1234: Some error\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"L1234: Some error",
|
"L1234: Some error",
|
||||||
FilePath::fromUserInput("flash.sct"),
|
FilePath::fromUserInput("flash.sct"),
|
||||||
@@ -380,9 +363,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
" ^")
|
" ^")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 63: Error: #1234: Some error\n"
|
<< QString()
|
||||||
" int f;\n"
|
|
||||||
" ^\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"#1234: Some error\n"
|
"#1234: Some error\n"
|
||||||
" int f;\n"
|
" int f;\n"
|
||||||
@@ -395,7 +376,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 71: Error: At end of source: #40: Some error")
|
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 71: Error: At end of source: #40: Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("\"c:\\foo\\main.c\", line 71: Error: At end of source: #40: Some error\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"#40: Some error",
|
"#40: Some error",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -406,7 +387,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
<< QString::fromLatin1("Error: L6226E: Some error.")
|
<< QString::fromLatin1("Error: L6226E: Some error.")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("Error: L6226E: Some error.\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"L6226E: Some error."))
|
"L6226E: Some error."))
|
||||||
<< QString();
|
<< QString();
|
||||||
@@ -417,7 +398,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
QTest::newRow("MCS51: Assembler simple warning")
|
QTest::newRow("MCS51: Assembler simple warning")
|
||||||
<< QString::fromLatin1("*** WARNING #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some warning")
|
<< QString::fromLatin1("*** WARNING #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some warning")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("*** WARNING #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some warning\n")
|
<< QString()
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"#A9: Some warning",
|
"#A9: Some warning",
|
||||||
@@ -428,7 +409,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
QTest::newRow("MCS51: Assembler simple error")
|
QTest::newRow("MCS51: Assembler simple error")
|
||||||
<< QString::fromLatin1("*** ERROR #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some error")
|
<< QString::fromLatin1("*** ERROR #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some error")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("*** ERROR #A9 IN 15 (c:\\foo\\dscr.a51, LINE 15): Some error\n")
|
<< QString()
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"#A9: Some error",
|
"#A9: Some error",
|
||||||
@@ -441,9 +422,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
" Some detail 1\n"
|
" Some detail 1\n"
|
||||||
" Some detail N")
|
" Some detail N")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("A51 FATAL ERROR -\n"
|
<< QString()
|
||||||
" Some detail 1\n"
|
|
||||||
" Some detail N\n")
|
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"Assembler fatal error\n"
|
"Assembler fatal error\n"
|
||||||
@@ -456,9 +435,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
"*** ___^\n"
|
"*** ___^\n"
|
||||||
"*** ERROR #A45 IN 28 (d:\\foo.a51, LINE 28): Some error")
|
"*** ERROR #A45 IN 28 (d:\\foo.a51, LINE 28): Some error")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("01AF Some detail\n"
|
<< QString()
|
||||||
"*** ___^\n"
|
|
||||||
"*** ERROR #A45 IN 28 (d:\\foo.a51, LINE 28): Some error\n")
|
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"#A45: Some error\n"
|
"#A45: Some error\n"
|
||||||
@@ -472,7 +449,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
QTest::newRow("MCS51: Compiler simple warning")
|
QTest::newRow("MCS51: Compiler simple warning")
|
||||||
<< QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning")
|
<< QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning\n")
|
<< QString()
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"C123: Some warning",
|
"C123: Some warning",
|
||||||
@@ -483,7 +460,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
QTest::newRow("MCS51: Compiler extended warning")
|
QTest::newRow("MCS51: Compiler extended warning")
|
||||||
<< QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning : 'extended text'")
|
<< QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning : 'extended text'")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("*** WARNING C123 IN LINE 13 OF c:\\foo.c: Some warning : 'extended text'\n")
|
<< QString()
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"C123: Some warning : 'extended text'",
|
"C123: Some warning : 'extended text'",
|
||||||
@@ -494,7 +471,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
QTest::newRow("MCS51: Compiler simple error")
|
QTest::newRow("MCS51: Compiler simple error")
|
||||||
<< QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error")
|
<< QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error\n")
|
<< QString()
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"C123: Some error",
|
"C123: Some error",
|
||||||
@@ -505,7 +482,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
QTest::newRow("MCS51: Compiler extended error")
|
QTest::newRow("MCS51: Compiler extended error")
|
||||||
<< QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error : 'extended text'")
|
<< QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error : 'extended text'")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("*** ERROR C123 IN LINE 13 OF c:\\foo.c: Some error : 'extended text'\n")
|
<< QString()
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"C123: Some error : 'extended text'",
|
"C123: Some error : 'extended text'",
|
||||||
@@ -518,9 +495,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
" Some detail 1\n"
|
" Some detail 1\n"
|
||||||
" Some detail N")
|
" Some detail N")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("C51 FATAL-ERROR -\n"
|
<< QString()
|
||||||
" Some detail 1\n"
|
|
||||||
" Some detail N\n")
|
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"Compiler fatal error\n"
|
"Compiler fatal error\n"
|
||||||
@@ -533,8 +508,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
<< QString::fromLatin1("*** WARNING L16: Some warning\n"
|
<< QString::fromLatin1("*** WARNING L16: Some warning\n"
|
||||||
" Some detail 1")
|
" Some detail 1")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("*** WARNING L16: Some warning\n"
|
<< QString()
|
||||||
" Some detail 1\n")
|
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"L16: Some warning\n"
|
"L16: Some warning\n"
|
||||||
@@ -544,7 +518,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
QTest::newRow("MCS51: Linker simple fatal error")
|
QTest::newRow("MCS51: Linker simple fatal error")
|
||||||
<< QString::fromLatin1("*** FATAL ERROR L456: Some error")
|
<< QString::fromLatin1("*** FATAL ERROR L456: Some error")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("*** FATAL ERROR L456: Some error\n")
|
<< QString()
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"L456: Some error"))
|
"L456: Some error"))
|
||||||
@@ -555,9 +529,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
" Some detail 1\n"
|
" Some detail 1\n"
|
||||||
" Some detail N")
|
" Some detail N")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDOUT
|
||||||
<< QString::fromLatin1("*** FATAL ERROR L456: Some error\n"
|
<< QString()
|
||||||
" Some detail 1\n"
|
|
||||||
" Some detail N\n")
|
|
||||||
<< QString()
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"L456: Some error\n"
|
"L456: Some error\n"
|
||||||
@@ -569,7 +541,7 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
void BareMetalPlugin::testKeilOutputParsers()
|
void BareMetalPlugin::testKeilOutputParsers()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new KeilParser);
|
testbench.addLineParser(new KeilParser);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -55,9 +55,7 @@ private:
|
|||||||
bool parseMcs51WarningOrFatalErrorMessage(const QString &lne);
|
bool parseMcs51WarningOrFatalErrorMessage(const QString &lne);
|
||||||
bool parseMcs51FatalErrorMessage2(const QString &lne);
|
bool parseMcs51FatalErrorMessage2(const QString &lne);
|
||||||
|
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) final;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) final;
|
||||||
void stdError(const QString &line);
|
|
||||||
void stdOutput(const QString &line);
|
|
||||||
void doFlush() final;
|
void doFlush() final;
|
||||||
|
|
||||||
ProjectExplorer::Task m_lastTask;
|
ProjectExplorer::Task m_lastTask;
|
||||||
|
@@ -374,9 +374,9 @@ void KeilToolChain::addToEnvironment(Environment &env) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *KeilToolChain::outputParser() const
|
QList<IOutputParser *> KeilToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
return new KeilParser;
|
return {new KeilParser};
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap KeilToolChain::toMap() const
|
QVariantMap KeilToolChain::toMap() const
|
||||||
|
@@ -69,7 +69,7 @@ public:
|
|||||||
const Utils::FilePath &,
|
const Utils::FilePath &,
|
||||||
const Utils::Environment &env) const final;
|
const Utils::Environment &env) const final;
|
||||||
void addToEnvironment(Utils::Environment &env) const final;
|
void addToEnvironment(Utils::Environment &env) const final;
|
||||||
ProjectExplorer::IOutputParser *outputParser() const final;
|
QList<ProjectExplorer::IOutputParser *> outputParsers() const final;
|
||||||
|
|
||||||
QVariantMap toMap() const final;
|
QVariantMap toMap() const final;
|
||||||
bool fromMap(const QVariantMap &data) final;
|
bool fromMap(const QVariantMap &data) final;
|
||||||
|
@@ -87,17 +87,10 @@ void SdccParser::amendDescription(const QString &desc)
|
|||||||
++m_lines;
|
++m_lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdccParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status SdccParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type == StdOutFormat)
|
if (type == StdOutFormat)
|
||||||
stdOutput(line);
|
return Status::NotHandled;
|
||||||
else
|
|
||||||
stdError(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SdccParser::stdError(const QString &line)
|
|
||||||
{
|
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
|
||||||
|
|
||||||
const QString lne = rightTrimmed(line);
|
const QString lne = rightTrimmed(line);
|
||||||
|
|
||||||
@@ -115,7 +108,7 @@ void SdccParser::stdError(const QString &line)
|
|||||||
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
|
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
|
||||||
const QString descr = match.captured(MessageTextIndex);
|
const QString descr = match.captured(MessageTextIndex);
|
||||||
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
|
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
re.setPattern("^(.+\\.\\S+):(\\d+): (Error|error|syntax error): (.+)$");
|
re.setPattern("^(.+\\.\\S+):(\\d+): (Error|error|syntax error): (.+)$");
|
||||||
@@ -129,7 +122,7 @@ void SdccParser::stdError(const QString &line)
|
|||||||
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
|
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
|
||||||
const QString descr = match.captured(MessageTextIndex);
|
const QString descr = match.captured(MessageTextIndex);
|
||||||
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
|
newTask(CompileTask(type, descr, absoluteFilePath(fileName), lineno));
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
re.setPattern("^at (\\d+): (warning|error) \\d+: (.+)$");
|
re.setPattern("^at (\\d+): (warning|error) \\d+: (.+)$");
|
||||||
@@ -139,7 +132,7 @@ void SdccParser::stdError(const QString &line)
|
|||||||
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
|
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
|
||||||
const QString descr = match.captured(MessageTextIndex);
|
const QString descr = match.captured(MessageTextIndex);
|
||||||
newTask(CompileTask(type, descr));
|
newTask(CompileTask(type, descr));
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
re.setPattern("^\\?ASlink-(Warning|Error)-(.+)$");
|
re.setPattern("^\\?ASlink-(Warning|Error)-(.+)$");
|
||||||
@@ -149,20 +142,16 @@ void SdccParser::stdError(const QString &line)
|
|||||||
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
|
const Task::TaskType type = taskType(match.captured(MessageTypeIndex));
|
||||||
const QString descr = match.captured(MessageTextIndex);
|
const QString descr = match.captured(MessageTextIndex);
|
||||||
newTask(CompileTask(type, descr));
|
newTask(CompileTask(type, descr));
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_lastTask.isNull()) {
|
if (!m_lastTask.isNull()) {
|
||||||
amendDescription(lne);
|
amendDescription(lne);
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
doFlush();
|
doFlush();
|
||||||
}
|
return Status::NotHandled;
|
||||||
|
|
||||||
void SdccParser::stdOutput(const QString &line)
|
|
||||||
{
|
|
||||||
IOutputParser::handleLine(line, StdOutFormat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdccParser::doFlush()
|
void SdccParser::doFlush()
|
||||||
@@ -215,7 +204,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: Error: Some error")
|
<< QString::fromLatin1("c:\\foo\\main.c:63: Error: Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: Error: Some error\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"Some error",
|
"Some error",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -226,7 +215,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: warning 123: Some warning")
|
<< QString::fromLatin1("c:\\foo\\main.c:63: warning 123: Some warning")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: warning 123: Some warning\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"Some warning",
|
"Some warning",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -239,9 +228,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
" details #2")
|
" details #2")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: warning 123: Some warning\n"
|
<< QString()
|
||||||
"details #1\n"
|
|
||||||
" details #2\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"Some warning\n"
|
"Some warning\n"
|
||||||
"details #1\n"
|
"details #1\n"
|
||||||
@@ -254,7 +241,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: error: Some error")
|
<< QString::fromLatin1("c:\\foo\\main.c:63: error: Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: error: Some error\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"Some error",
|
"Some error",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -265,7 +252,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: error 123: Some error")
|
<< QString::fromLatin1("c:\\foo\\main.c:63: error 123: Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: error 123: Some error\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"Some error",
|
"Some error",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -278,9 +265,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
" details #2")
|
" details #2")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: error 123: Some error\n"
|
<< QString()
|
||||||
"details #1\n"
|
|
||||||
" details #2\n")
|
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"Some error\n"
|
"Some error\n"
|
||||||
"details #1\n"
|
"details #1\n"
|
||||||
@@ -293,7 +278,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: syntax error: Some error")
|
<< QString::fromLatin1("c:\\foo\\main.c:63: syntax error: Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("c:\\foo\\main.c:63: syntax error: Some error\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"Some error",
|
"Some error",
|
||||||
FilePath::fromUserInput("c:\\foo\\main.c"),
|
FilePath::fromUserInput("c:\\foo\\main.c"),
|
||||||
@@ -304,7 +289,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
<< QString::fromLatin1("at 1: error 123: Some error")
|
<< QString::fromLatin1("at 1: error 123: Some error")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("at 1: error 123: Some error\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"Some error"))
|
"Some error"))
|
||||||
<< QString();
|
<< QString();
|
||||||
@@ -313,7 +298,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
<< QString::fromLatin1("at 1: warning 123: Some warning")
|
<< QString::fromLatin1("at 1: warning 123: Some warning")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("at 1: warning 123: Some warning\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"Some warning"))
|
"Some warning"))
|
||||||
<< QString();
|
<< QString();
|
||||||
@@ -322,7 +307,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
<< QString::fromLatin1("?ASlink-Warning-Couldn't find library 'foo.lib'")
|
<< QString::fromLatin1("?ASlink-Warning-Couldn't find library 'foo.lib'")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("?ASlink-Warning-Couldn't find library 'foo.lib'\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Warning,
|
<< (Tasks() << CompileTask(Task::Warning,
|
||||||
"Couldn't find library 'foo.lib'"))
|
"Couldn't find library 'foo.lib'"))
|
||||||
<< QString();
|
<< QString();
|
||||||
@@ -331,7 +316,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
<< QString::fromLatin1("?ASlink-Error-<cannot open> : \"foo.rel\"")
|
<< QString::fromLatin1("?ASlink-Error-<cannot open> : \"foo.rel\"")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QString::fromLatin1("?ASlink-Error-<cannot open> : \"foo.rel\"\n")
|
<< QString()
|
||||||
<< (Tasks() << CompileTask(Task::Error,
|
<< (Tasks() << CompileTask(Task::Error,
|
||||||
"<cannot open> : \"foo.rel\""))
|
"<cannot open> : \"foo.rel\""))
|
||||||
<< QString();
|
<< QString();
|
||||||
@@ -340,7 +325,7 @@ void BareMetalPlugin::testSdccOutputParsers_data()
|
|||||||
void BareMetalPlugin::testSdccOutputParsers()
|
void BareMetalPlugin::testSdccOutputParsers()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new SdccParser);
|
testbench.addLineParser(new SdccParser);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -45,9 +45,7 @@ private:
|
|||||||
void newTask(const ProjectExplorer::Task &task);
|
void newTask(const ProjectExplorer::Task &task);
|
||||||
void amendDescription(const QString &desc);
|
void amendDescription(const QString &desc);
|
||||||
|
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) final;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) final;
|
||||||
void stdError(const QString &line);
|
|
||||||
void stdOutput(const QString &line);
|
|
||||||
void doFlush() final;
|
void doFlush() final;
|
||||||
|
|
||||||
ProjectExplorer::Task m_lastTask;
|
ProjectExplorer::Task m_lastTask;
|
||||||
|
@@ -307,9 +307,9 @@ void SdccToolChain::addToEnvironment(Environment &env) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *SdccToolChain::outputParser() const
|
QList<IOutputParser *> SdccToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
return new SdccParser;
|
return {new SdccParser};
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap SdccToolChain::toMap() const
|
QVariantMap SdccToolChain::toMap() const
|
||||||
|
@@ -69,7 +69,7 @@ public:
|
|||||||
const Utils::FilePath &,
|
const Utils::FilePath &,
|
||||||
const Utils::Environment &env) const final;
|
const Utils::Environment &env) const final;
|
||||||
void addToEnvironment(Utils::Environment &env) const final;
|
void addToEnvironment(Utils::Environment &env) const final;
|
||||||
ProjectExplorer::IOutputParser *outputParser() const final;
|
QList<ProjectExplorer::IOutputParser *> outputParsers() const final;
|
||||||
|
|
||||||
QVariantMap toMap() const final;
|
QVariantMap toMap() const final;
|
||||||
bool fromMap(const QVariantMap &data) final;
|
bool fromMap(const QVariantMap &data) final;
|
||||||
|
@@ -214,9 +214,7 @@ bool CMakeBuildStep::init()
|
|||||||
cmakeParser->setSourceDirectory(projectDirectory.toString());
|
cmakeParser->setSourceDirectory(projectDirectory.toString());
|
||||||
setOutputParser(cmakeParser);
|
setOutputParser(cmakeParser);
|
||||||
appendOutputParser(new GnuMakeParser);
|
appendOutputParser(new GnuMakeParser);
|
||||||
IOutputParser *parser = target()->kit()->createOutputParser();
|
appendOutputParsers(target()->kit()->createOutputParsers());
|
||||||
if (parser)
|
|
||||||
appendOutputParser(parser);
|
|
||||||
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
||||||
|
|
||||||
return AbstractProcessStep::init();
|
return AbstractProcessStep::init();
|
||||||
|
@@ -57,22 +57,21 @@ void CMakeParser::setSourceDirectory(const QString &sourceDir)
|
|||||||
m_sourceDirectory = QDir(sourceDir);
|
m_sourceDirectory = QDir(sourceDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status CMakeParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type != StdErrFormat) {
|
if (type != StdErrFormat)
|
||||||
IOutputParser::handleLine(line, type);
|
return Status::NotHandled;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString trimmedLine = rightTrimmed(line);
|
QString trimmedLine = rightTrimmed(line);
|
||||||
switch (m_expectTripleLineErrorData) {
|
switch (m_expectTripleLineErrorData) {
|
||||||
case NONE:
|
case NONE:
|
||||||
if (trimmedLine.isEmpty() && !m_lastTask.isNull()) {
|
if (trimmedLine.isEmpty() && !m_lastTask.isNull()) {
|
||||||
if (m_skippedFirstEmptyLine)
|
if (m_skippedFirstEmptyLine) {
|
||||||
doFlush();
|
doFlush();
|
||||||
else
|
return Status::InProgress;
|
||||||
m_skippedFirstEmptyLine = true;
|
}
|
||||||
return;
|
m_skippedFirstEmptyLine = true;
|
||||||
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
if (m_skippedFirstEmptyLine)
|
if (m_skippedFirstEmptyLine)
|
||||||
m_skippedFirstEmptyLine = false;
|
m_skippedFirstEmptyLine = false;
|
||||||
@@ -87,35 +86,34 @@ void CMakeParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
absoluteFilePath(FilePath::fromUserInput(path)),
|
absoluteFilePath(FilePath::fromUserInput(path)),
|
||||||
m_commonError.cap(2).toInt());
|
m_commonError.cap(2).toInt());
|
||||||
m_lines = 1;
|
m_lines = 1;
|
||||||
return;
|
return Status::InProgress;
|
||||||
} else if (m_nextSubError.indexIn(trimmedLine) != -1) {
|
} else if (m_nextSubError.indexIn(trimmedLine) != -1) {
|
||||||
m_lastTask = BuildSystemTask(Task::Error, QString(),
|
m_lastTask = BuildSystemTask(Task::Error, QString(),
|
||||||
absoluteFilePath(FilePath::fromUserInput(m_nextSubError.cap(1))));
|
absoluteFilePath(FilePath::fromUserInput(m_nextSubError.cap(1))));
|
||||||
m_lines = 1;
|
m_lines = 1;
|
||||||
return;
|
return Status::InProgress;
|
||||||
} else if (trimmedLine.startsWith(QLatin1String(" ")) && !m_lastTask.isNull()) {
|
} else if (trimmedLine.startsWith(QLatin1String(" ")) && !m_lastTask.isNull()) {
|
||||||
if (!m_lastTask.description.isEmpty())
|
if (!m_lastTask.description.isEmpty())
|
||||||
m_lastTask.description.append(QLatin1Char(' '));
|
m_lastTask.description.append(QLatin1Char(' '));
|
||||||
m_lastTask.description.append(trimmedLine.trimmed());
|
m_lastTask.description.append(trimmedLine.trimmed());
|
||||||
++m_lines;
|
++m_lines;
|
||||||
return;
|
return Status::InProgress;
|
||||||
} else if (trimmedLine.endsWith(QLatin1String("in cmake code at"))) {
|
} else if (trimmedLine.endsWith(QLatin1String("in cmake code at"))) {
|
||||||
m_expectTripleLineErrorData = LINE_LOCATION;
|
m_expectTripleLineErrorData = LINE_LOCATION;
|
||||||
doFlush();
|
doFlush();
|
||||||
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 = BuildSystemTask(type, QString());
|
||||||
return;
|
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 = BuildSystemTask(Task::Error, trimmedLine.mid(13));
|
||||||
m_lines = 1;
|
m_lines = 1;
|
||||||
return;
|
return Status::InProgress;
|
||||||
} else if (trimmedLine.startsWith("-- ") || trimmedLine.startsWith(" * ")) {
|
} else if (trimmedLine.startsWith("-- ") || trimmedLine.startsWith(" * ")) {
|
||||||
// Do not pass on lines starting with "-- " or "* ". Those are typical CMake output
|
// Do not pass on lines starting with "-- " or "* ". Those are typical CMake output
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
return Status::NotHandled;
|
||||||
return;
|
|
||||||
case LINE_LOCATION:
|
case LINE_LOCATION:
|
||||||
{
|
{
|
||||||
QRegularExpressionMatch m = m_locationLine.match(trimmedLine);
|
QRegularExpressionMatch m = m_locationLine.match(trimmedLine);
|
||||||
@@ -124,7 +122,7 @@ void CMakeParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
m_lastTask.line = m.captured(1).toInt();
|
m_lastTask.line = m.captured(1).toInt();
|
||||||
m_expectTripleLineErrorData = LINE_DESCRIPTION;
|
m_expectTripleLineErrorData = LINE_DESCRIPTION;
|
||||||
}
|
}
|
||||||
return;
|
return Status::InProgress;
|
||||||
case LINE_DESCRIPTION:
|
case LINE_DESCRIPTION:
|
||||||
m_lastTask.description = trimmedLine;
|
m_lastTask.description = trimmedLine;
|
||||||
if (trimmedLine.endsWith(QLatin1Char('\"')))
|
if (trimmedLine.endsWith(QLatin1Char('\"')))
|
||||||
@@ -132,14 +130,15 @@ void CMakeParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
else {
|
else {
|
||||||
m_expectTripleLineErrorData = NONE;
|
m_expectTripleLineErrorData = NONE;
|
||||||
doFlush();
|
doFlush();
|
||||||
|
return Status::Done;
|
||||||
}
|
}
|
||||||
return;
|
return Status::InProgress;
|
||||||
case LINE_DESCRIPTION2:
|
case LINE_DESCRIPTION2:
|
||||||
m_lastTask.description.append(QLatin1Char('\n'));
|
m_lastTask.description.append(QLatin1Char('\n'));
|
||||||
m_lastTask.description.append(trimmedLine);
|
m_lastTask.description.append(trimmedLine);
|
||||||
m_expectTripleLineErrorData = NONE;
|
m_expectTripleLineErrorData = NONE;
|
||||||
doFlush();
|
doFlush();
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +300,7 @@ void Internal::CMakeProjectPlugin::testCMakeParser_data()
|
|||||||
void Internal::CMakeProjectPlugin::testCMakeParser()
|
void Internal::CMakeProjectPlugin::testCMakeParser()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new CMakeParser);
|
testbench.addLineParser(new CMakeParser);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -45,7 +45,7 @@ public:
|
|||||||
void setSourceDirectory(const QString &sourceDir);
|
void setSourceDirectory(const QString &sourceDir);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
void doFlush() override;
|
void doFlush() override;
|
||||||
|
|
||||||
enum TripleLineError { NONE, LINE_LOCATION, LINE_DESCRIPTION, LINE_DESCRIPTION2 };
|
enum TripleLineError { NONE, LINE_LOCATION, LINE_DESCRIPTION, LINE_DESCRIPTION2 };
|
||||||
|
@@ -223,9 +223,7 @@ bool IosBuildStep::init()
|
|||||||
setIgnoreReturnValue(m_clean);
|
setIgnoreReturnValue(m_clean);
|
||||||
|
|
||||||
setOutputParser(new GnuMakeParser());
|
setOutputParser(new GnuMakeParser());
|
||||||
IOutputParser *parser = target()->kit()->createOutputParser();
|
appendOutputParsers(target()->kit()->createOutputParsers());
|
||||||
if (parser)
|
|
||||||
appendOutputParser(parser);
|
|
||||||
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
||||||
|
|
||||||
return AbstractProcessStep::init();
|
return AbstractProcessStep::init();
|
||||||
|
@@ -80,9 +80,8 @@ bool IosDsymBuildStep::init()
|
|||||||
// That is mostly so that rebuild works on an already clean project
|
// That is mostly so that rebuild works on an already clean project
|
||||||
setIgnoreReturnValue(m_clean);
|
setIgnoreReturnValue(m_clean);
|
||||||
|
|
||||||
setOutputParser(target()->kit()->createOutputParser());
|
appendOutputParsers(target()->kit()->createOutputParsers());
|
||||||
if (outputParser())
|
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
||||||
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
|
||||||
|
|
||||||
return AbstractProcessStep::init();
|
return AbstractProcessStep::init();
|
||||||
}
|
}
|
||||||
|
@@ -45,15 +45,9 @@ namespace {
|
|||||||
|
|
||||||
class NimParser : public IOutputParser
|
class NimParser : public IOutputParser
|
||||||
{
|
{
|
||||||
private:
|
Status doHandleLine(const QString &lne, Utils::OutputFormat) override
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override
|
|
||||||
{
|
|
||||||
parseLine(line.trimmed());
|
|
||||||
IOutputParser::handleLine(line, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void parseLine(const QString &line)
|
|
||||||
{
|
{
|
||||||
|
const QString line = lne.trimmed();
|
||||||
static QRegularExpression regex("(.+.nim)\\((\\d+), (\\d+)\\) (.+)",
|
static QRegularExpression regex("(.+.nim)\\((\\d+), (\\d+)\\) (.+)",
|
||||||
QRegularExpression::OptimizeOnFirstUsageOption);
|
QRegularExpression::OptimizeOnFirstUsageOption);
|
||||||
static QRegularExpression warning("(Warning):(.*)",
|
static QRegularExpression warning("(Warning):(.*)",
|
||||||
@@ -63,13 +57,13 @@ private:
|
|||||||
|
|
||||||
QRegularExpressionMatch match = regex.match(line);
|
QRegularExpressionMatch match = regex.match(line);
|
||||||
if (!match.hasMatch())
|
if (!match.hasMatch())
|
||||||
return;
|
return Status::NotHandled;
|
||||||
const QString filename = match.captured(1);
|
const QString filename = match.captured(1);
|
||||||
bool lineOk = false;
|
bool lineOk = false;
|
||||||
const int lineNumber = match.captured(2).toInt(&lineOk);
|
const int lineNumber = match.captured(2).toInt(&lineOk);
|
||||||
const QString message = match.captured(4);
|
const QString message = match.captured(4);
|
||||||
if (!lineOk)
|
if (!lineOk)
|
||||||
return;
|
return Status::NotHandled;
|
||||||
|
|
||||||
Task::TaskType type = Task::Unknown;
|
Task::TaskType type = Task::Unknown;
|
||||||
|
|
||||||
@@ -78,10 +72,11 @@ private:
|
|||||||
else if (error.match(message).hasMatch())
|
else if (error.match(message).hasMatch())
|
||||||
type = Task::Error;
|
type = Task::Error;
|
||||||
else
|
else
|
||||||
return;
|
return Status::NotHandled;
|
||||||
|
|
||||||
emit addTask(CompileTask(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
|
emit addTask(CompileTask(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
|
||||||
lineNumber));
|
lineNumber));
|
||||||
|
return Status::Done;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -47,14 +47,9 @@ namespace Nim {
|
|||||||
|
|
||||||
class NimParser : public ProjectExplorer::IOutputParser
|
class NimParser : public ProjectExplorer::IOutputParser
|
||||||
{
|
{
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override
|
Status doHandleLine(const QString &lne, Utils::OutputFormat) override
|
||||||
{
|
|
||||||
parseLine(line.trimmed());
|
|
||||||
IOutputParser::handleLine(line, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void parseLine(const QString &line)
|
|
||||||
{
|
{
|
||||||
|
const QString line = lne.trimmed();
|
||||||
static QRegularExpression regex("(.+.nim)\\((\\d+), (\\d+)\\) (.+)",
|
static QRegularExpression regex("(.+.nim)\\((\\d+), (\\d+)\\) (.+)",
|
||||||
QRegularExpression::OptimizeOnFirstUsageOption);
|
QRegularExpression::OptimizeOnFirstUsageOption);
|
||||||
static QRegularExpression warning("(Warning):(.*)",
|
static QRegularExpression warning("(Warning):(.*)",
|
||||||
@@ -64,13 +59,13 @@ class NimParser : public ProjectExplorer::IOutputParser
|
|||||||
|
|
||||||
QRegularExpressionMatch match = regex.match(line);
|
QRegularExpressionMatch match = regex.match(line);
|
||||||
if (!match.hasMatch())
|
if (!match.hasMatch())
|
||||||
return;
|
return Status::NotHandled;
|
||||||
const QString filename = match.captured(1);
|
const QString filename = match.captured(1);
|
||||||
bool lineOk = false;
|
bool lineOk = false;
|
||||||
const int lineNumber = match.captured(2).toInt(&lineOk);
|
const int lineNumber = match.captured(2).toInt(&lineOk);
|
||||||
const QString message = match.captured(4);
|
const QString message = match.captured(4);
|
||||||
if (!lineOk)
|
if (!lineOk)
|
||||||
return;
|
return Status::NotHandled;
|
||||||
|
|
||||||
Task::TaskType type = Task::Unknown;
|
Task::TaskType type = Task::Unknown;
|
||||||
|
|
||||||
@@ -79,10 +74,11 @@ class NimParser : public ProjectExplorer::IOutputParser
|
|||||||
else if (error.match(message).hasMatch())
|
else if (error.match(message).hasMatch())
|
||||||
type = Task::Error;
|
type = Task::Error;
|
||||||
else
|
else
|
||||||
return;
|
return Status::NotHandled;
|
||||||
|
|
||||||
emit addTask(CompileTask(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
|
emit addTask(CompileTask(type, message, absoluteFilePath(FilePath::fromUserInput(filename)),
|
||||||
lineNumber));
|
lineNumber));
|
||||||
|
return Status::Done;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -107,8 +103,7 @@ NimCompilerBuildStep::NimCompilerBuildStep(BuildStepList *parentList, Core::Id i
|
|||||||
bool NimCompilerBuildStep::init()
|
bool NimCompilerBuildStep::init()
|
||||||
{
|
{
|
||||||
setOutputParser(new NimParser());
|
setOutputParser(new NimParser());
|
||||||
if (IOutputParser *parser = target()->kit()->createOutputParser())
|
appendOutputParsers(target()->kit()->createOutputParsers());
|
||||||
appendOutputParser(parser);
|
|
||||||
outputParser()->addSearchDir(processParameters()->effectiveWorkingDirectory());
|
outputParser()->addSearchDir(processParameters()->effectiveWorkingDirectory());
|
||||||
return AbstractProcessStep::init();
|
return AbstractProcessStep::init();
|
||||||
}
|
}
|
||||||
@@ -308,7 +303,7 @@ void NimPlugin::testNimParser_data()
|
|||||||
QTest::newRow("Parse error string")
|
QTest::newRow("Parse error string")
|
||||||
<< QString::fromLatin1("main.nim(23, 1) Error: undeclared identifier: 'x'")
|
<< QString::fromLatin1("main.nim(23, 1) Error: undeclared identifier: 'x'")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString("") << QString("main.nim(23, 1) Error: undeclared identifier: 'x'\n")
|
<< QString() << QString()
|
||||||
<< Tasks({CompileTask(Task::Error,
|
<< Tasks({CompileTask(Task::Error,
|
||||||
"Error: undeclared identifier: 'x'",
|
"Error: undeclared identifier: 'x'",
|
||||||
FilePath::fromUserInput("main.nim"), 23)})
|
FilePath::fromUserInput("main.nim"), 23)})
|
||||||
@@ -317,7 +312,7 @@ void NimPlugin::testNimParser_data()
|
|||||||
QTest::newRow("Parse warning string")
|
QTest::newRow("Parse warning string")
|
||||||
<< QString::fromLatin1("lib/pure/parseopt.nim(56, 34) Warning: quoteIfContainsWhite is deprecated [Deprecated]")
|
<< QString::fromLatin1("lib/pure/parseopt.nim(56, 34) Warning: quoteIfContainsWhite is deprecated [Deprecated]")
|
||||||
<< OutputParserTester::STDERR
|
<< OutputParserTester::STDERR
|
||||||
<< QString("") << QString("lib/pure/parseopt.nim(56, 34) Warning: quoteIfContainsWhite is deprecated [Deprecated]\n")
|
<< QString() << QString()
|
||||||
<< Tasks({CompileTask(Task::Warning,
|
<< Tasks({CompileTask(Task::Warning,
|
||||||
"Warning: quoteIfContainsWhite is deprecated [Deprecated]",
|
"Warning: quoteIfContainsWhite is deprecated [Deprecated]",
|
||||||
FilePath::fromUserInput("lib/pure/parseopt.nim"), 56)})
|
FilePath::fromUserInput("lib/pure/parseopt.nim"), 56)})
|
||||||
@@ -327,7 +322,7 @@ void NimPlugin::testNimParser_data()
|
|||||||
void NimPlugin::testNimParser()
|
void NimPlugin::testNimParser()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new NimParser);
|
testbench.addLineParser(new NimParser);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -120,9 +120,9 @@ void NimToolChain::setCompilerCommand(const FilePath &compilerCommand)
|
|||||||
parseVersion(compilerCommand, m_version);
|
parseVersion(compilerCommand, m_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *NimToolChain::outputParser() const
|
QList<IOutputParser *> NimToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> NimToolChain::createConfigurationWidget()
|
std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> NimToolChain::createConfigurationWidget()
|
||||||
|
@@ -56,7 +56,7 @@ public:
|
|||||||
Utils::FilePath compilerCommand() const final;
|
Utils::FilePath compilerCommand() const final;
|
||||||
QString compilerVersion() const;
|
QString compilerVersion() const;
|
||||||
void setCompilerCommand(const Utils::FilePath &compilerCommand);
|
void setCompilerCommand(const Utils::FilePath &compilerCommand);
|
||||||
ProjectExplorer::IOutputParser *outputParser() const final;
|
QList<ProjectExplorer::IOutputParser *> outputParsers() const final;
|
||||||
std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> createConfigurationWidget() final;
|
std::unique_ptr<ProjectExplorer::ToolChainConfigWidget> createConfigurationWidget() final;
|
||||||
|
|
||||||
QVariantMap toMap() const final;
|
QVariantMap toMap() const final;
|
||||||
|
@@ -106,11 +106,10 @@ public:
|
|||||||
|
|
||||||
AbstractProcessStep *q;
|
AbstractProcessStep *q;
|
||||||
std::unique_ptr<Utils::QtcProcess> m_process;
|
std::unique_ptr<Utils::QtcProcess> m_process;
|
||||||
std::unique_ptr<IOutputParser> m_outputParserChain;
|
IOutputParser m_outputParser;
|
||||||
ProcessParameters m_param;
|
ProcessParameters m_param;
|
||||||
Utils::FileInProjectFinder m_fileFinder;
|
Utils::FileInProjectFinder m_fileFinder;
|
||||||
bool m_ignoreReturnValue = false;
|
bool m_ignoreReturnValue = false;
|
||||||
bool m_skipFlush = false;
|
|
||||||
bool m_lowPriority = false;
|
bool m_lowPriority = false;
|
||||||
std::unique_ptr<QTextDecoder> stdoutStream;
|
std::unique_ptr<QTextDecoder> stdoutStream;
|
||||||
std::unique_ptr<QTextDecoder> stderrStream;
|
std::unique_ptr<QTextDecoder> stderrStream;
|
||||||
@@ -120,6 +119,8 @@ AbstractProcessStep::AbstractProcessStep(BuildStepList *bsl, Core::Id id) :
|
|||||||
BuildStep(bsl, id),
|
BuildStep(bsl, id),
|
||||||
d(new Private(this))
|
d(new Private(this))
|
||||||
{
|
{
|
||||||
|
connect(&d->m_outputParser, &IOutputParser::addTask,
|
||||||
|
this, &AbstractProcessStep::taskAdded);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractProcessStep::~AbstractProcessStep()
|
AbstractProcessStep::~AbstractProcessStep()
|
||||||
@@ -130,16 +131,10 @@ AbstractProcessStep::~AbstractProcessStep()
|
|||||||
/*!
|
/*!
|
||||||
Deletes all existing output parsers and starts a new chain with the
|
Deletes all existing output parsers and starts a new chain with the
|
||||||
given parser.
|
given parser.
|
||||||
|
|
||||||
Derived classes need to call this function.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void AbstractProcessStep::setOutputParser(IOutputParser *parser)
|
void AbstractProcessStep::setOutputParser(IOutputParser *parser)
|
||||||
{
|
{
|
||||||
parser->addFilter(&Internal::filterAnsiEscapeCodes);
|
d->m_outputParser.setLineParsers({parser});
|
||||||
d->m_outputParserChain.reset(parser);
|
|
||||||
connect(d->m_outputParserChain.get(), &IOutputParser::addTask,
|
|
||||||
this, &AbstractProcessStep::taskAdded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -149,14 +144,18 @@ void AbstractProcessStep::appendOutputParser(IOutputParser *parser)
|
|||||||
{
|
{
|
||||||
if (!parser)
|
if (!parser)
|
||||||
return;
|
return;
|
||||||
|
d->m_outputParser.addLineParser(parser);
|
||||||
|
}
|
||||||
|
|
||||||
QTC_ASSERT(d->m_outputParserChain, return);
|
void AbstractProcessStep::appendOutputParsers(const QList<IOutputParser *> &parsers)
|
||||||
d->m_outputParserChain->appendOutputParser(parser);
|
{
|
||||||
|
for (IOutputParser * const p : parsers)
|
||||||
|
appendOutputParser(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *AbstractProcessStep::outputParser() const
|
IOutputParser *AbstractProcessStep::outputParser() const
|
||||||
{
|
{
|
||||||
return d->m_outputParserChain.get();
|
return &d->m_outputParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractProcessStep::emitFaultyConfigurationMessage()
|
void AbstractProcessStep::emitFaultyConfigurationMessage()
|
||||||
@@ -189,6 +188,7 @@ void AbstractProcessStep::setIgnoreReturnValue(bool b)
|
|||||||
|
|
||||||
bool AbstractProcessStep::init()
|
bool AbstractProcessStep::init()
|
||||||
{
|
{
|
||||||
|
d->m_outputParser.addFilter(&Internal::filterAnsiEscapeCodes);
|
||||||
d->m_fileFinder.setProjectDirectory(project()->projectDirectory());
|
d->m_fileFinder.setProjectDirectory(project()->projectDirectory());
|
||||||
d->m_fileFinder.setProjectFiles(project()->files(Project::AllFiles));
|
d->m_fileFinder.setProjectFiles(project()->files(Project::AllFiles));
|
||||||
return !d->m_process;
|
return !d->m_process;
|
||||||
@@ -244,7 +244,7 @@ void AbstractProcessStep::doRun()
|
|||||||
if (!d->m_process->waitForStarted()) {
|
if (!d->m_process->waitForStarted()) {
|
||||||
processStartupFailed();
|
processStartupFailed();
|
||||||
d->m_process.reset();
|
d->m_process.reset();
|
||||||
d->m_outputParserChain.reset();
|
d->m_outputParser.clear();
|
||||||
finish(false);
|
finish(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -272,7 +272,7 @@ void AbstractProcessStep::cleanUp(QProcess *process)
|
|||||||
processFinished(process->exitCode(), process->exitStatus());
|
processFinished(process->exitCode(), process->exitStatus());
|
||||||
const bool returnValue = processSucceeded(process->exitCode(), process->exitStatus()) || d->m_ignoreReturnValue;
|
const bool returnValue = processSucceeded(process->exitCode(), process->exitStatus()) || d->m_ignoreReturnValue;
|
||||||
|
|
||||||
d->m_outputParserChain.reset();
|
d->m_outputParser.clear();
|
||||||
d->m_process.reset();
|
d->m_process.reset();
|
||||||
|
|
||||||
// Report result
|
// Report result
|
||||||
@@ -302,8 +302,8 @@ void AbstractProcessStep::processStarted()
|
|||||||
|
|
||||||
void AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus status)
|
void AbstractProcessStep::processFinished(int exitCode, QProcess::ExitStatus status)
|
||||||
{
|
{
|
||||||
if (d->m_outputParserChain)
|
d->m_outputParser.flush();
|
||||||
d->m_outputParserChain->flush();
|
d->m_outputParser.clear();
|
||||||
|
|
||||||
QString command = QDir::toNativeSeparators(d->m_param.effectiveCommand().toString());
|
QString command = QDir::toNativeSeparators(d->m_param.effectiveCommand().toString());
|
||||||
if (status == QProcess::NormalExit && exitCode == 0) {
|
if (status == QProcess::NormalExit && exitCode == 0) {
|
||||||
@@ -338,7 +338,7 @@ void AbstractProcessStep::processStartupFailed()
|
|||||||
|
|
||||||
bool AbstractProcessStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
|
bool AbstractProcessStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
|
||||||
{
|
{
|
||||||
if (outputParser() && outputParser()->hasFatalErrors())
|
if (outputParser()->hasFatalErrors())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return exitCode == 0 && status == QProcess::NormalExit;
|
return exitCode == 0 && status == QProcess::NormalExit;
|
||||||
@@ -359,8 +359,7 @@ void AbstractProcessStep::processReadyReadStdOutput()
|
|||||||
|
|
||||||
void AbstractProcessStep::stdOutput(const QString &output)
|
void AbstractProcessStep::stdOutput(const QString &output)
|
||||||
{
|
{
|
||||||
if (d->m_outputParserChain)
|
d->m_outputParser.handleStdout(output);
|
||||||
d->m_outputParserChain->handleStdout(output);
|
|
||||||
emit addOutput(output, BuildStep::OutputFormat::Stdout, BuildStep::DontAppendNewline);
|
emit addOutput(output, BuildStep::OutputFormat::Stdout, BuildStep::DontAppendNewline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,8 +378,7 @@ void AbstractProcessStep::processReadyReadStdError()
|
|||||||
|
|
||||||
void AbstractProcessStep::stdError(const QString &output)
|
void AbstractProcessStep::stdError(const QString &output)
|
||||||
{
|
{
|
||||||
if (d->m_outputParserChain)
|
d->m_outputParser.handleStderr(output);
|
||||||
d->m_outputParserChain->handleStderr(output);
|
|
||||||
emit addOutput(output, BuildStep::OutputFormat::Stderr, BuildStep::DontAppendNewline);
|
emit addOutput(output, BuildStep::OutputFormat::Stderr, BuildStep::DontAppendNewline);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,13 +394,6 @@ void AbstractProcessStep::taskAdded(const Task &task, int linkedOutputLines, int
|
|||||||
if (d->m_ignoreReturnValue)
|
if (d->m_ignoreReturnValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// flush out any pending tasks before proceeding:
|
|
||||||
if (!d->m_skipFlush && d->m_outputParserChain) {
|
|
||||||
d->m_skipFlush = true;
|
|
||||||
d->m_outputParserChain->flushTasks();
|
|
||||||
d->m_skipFlush = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Task editable(task);
|
Task editable(task);
|
||||||
QString filePath = task.file.toString();
|
QString filePath = task.file.toString();
|
||||||
if (!filePath.isEmpty() && !filePath.startsWith('<') && !QDir::isAbsolutePath(filePath)) {
|
if (!filePath.isEmpty() && !filePath.startsWith('<') && !QDir::isAbsolutePath(filePath)) {
|
||||||
|
@@ -48,6 +48,7 @@ public:
|
|||||||
|
|
||||||
void setOutputParser(IOutputParser *parser);
|
void setOutputParser(IOutputParser *parser);
|
||||||
void appendOutputParser(IOutputParser *parser);
|
void appendOutputParser(IOutputParser *parser);
|
||||||
|
void appendOutputParsers(const QList<IOutputParser *> &parsers);
|
||||||
IOutputParser *outputParser() const;
|
IOutputParser *outputParser() const;
|
||||||
|
|
||||||
void emitFaultyConfigurationMessage();
|
void emitFaultyConfigurationMessage();
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "clangparser.h"
|
#include "clangparser.h"
|
||||||
#include "ldparser.h"
|
#include "ldparser.h"
|
||||||
|
#include "lldparser.h"
|
||||||
#include "projectexplorerconstants.h"
|
#include "projectexplorerconstants.h"
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
@@ -54,25 +55,28 @@ ClangParser::ClangParser() :
|
|||||||
setObjectName(QLatin1String("ClangParser"));
|
setObjectName(QLatin1String("ClangParser"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangParser::handleLine(const QString &line, OutputFormat type)
|
QList<IOutputParser *> ClangParser::clangParserSuite()
|
||||||
{
|
{
|
||||||
if (type != StdErrFormat) {
|
return {new ClangParser, new Internal::LldParser, new LdParser};
|
||||||
IOutputParser::handleLine(line, type);
|
}
|
||||||
return;
|
|
||||||
}
|
IOutputParser::Status ClangParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
|
{
|
||||||
|
if (type != StdErrFormat)
|
||||||
|
return Status::NotHandled;
|
||||||
const QString lne = rightTrimmed(line);
|
const QString lne = rightTrimmed(line);
|
||||||
QRegularExpressionMatch match = m_summaryRegExp.match(lne);
|
QRegularExpressionMatch match = m_summaryRegExp.match(lne);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
doFlush();
|
doFlush();
|
||||||
m_expectSnippet = false;
|
m_expectSnippet = false;
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = m_commandRegExp.match(lne);
|
match = m_commandRegExp.match(lne);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
m_expectSnippet = true;
|
m_expectSnippet = true;
|
||||||
newTask(CompileTask(taskType(match.captured(3)), match.captured(4)));
|
newTask(CompileTask(taskType(match.captured(3)), match.captured(4)));
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = m_inLineRegExp.match(lne);
|
match = m_inLineRegExp.match(lne);
|
||||||
@@ -82,7 +86,7 @@ void ClangParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
lne.trimmed(),
|
lne.trimmed(),
|
||||||
absoluteFilePath(FilePath::fromUserInput(match.captured(2))),
|
absoluteFilePath(FilePath::fromUserInput(match.captured(2))),
|
||||||
match.captured(3).toInt() /* line */));
|
match.captured(3).toInt() /* line */));
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = m_messageRegExp.match(lne);
|
match = m_messageRegExp.match(lne);
|
||||||
@@ -96,22 +100,22 @@ void ClangParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
match.captured(8),
|
match.captured(8),
|
||||||
absoluteFilePath(FilePath::fromUserInput(match.captured(1))),
|
absoluteFilePath(FilePath::fromUserInput(match.captured(1))),
|
||||||
lineNo));
|
lineNo));
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = m_codesignRegExp.match(lne);
|
match = m_codesignRegExp.match(lne);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
m_expectSnippet = true;
|
m_expectSnippet = true;
|
||||||
newTask(CompileTask(Task::Error, match.captured(1)));
|
newTask(CompileTask(Task::Error, match.captured(1)));
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_expectSnippet) {
|
if (m_expectSnippet) {
|
||||||
amendDescription(lne, true);
|
amendDescription(lne, true);
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Id ClangParser::id()
|
Core::Id ClangParser::id()
|
||||||
@@ -259,7 +263,7 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
|
|||||||
void ProjectExplorerPlugin::testClangOutputParser()
|
void ProjectExplorerPlugin::testClangOutputParser()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new ClangParser);
|
testbench.setLineParsers(ClangParser::clangParserSuite());
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -39,10 +39,12 @@ class PROJECTEXPLORER_EXPORT ClangParser : public ProjectExplorer::GccParser
|
|||||||
public:
|
public:
|
||||||
ClangParser();
|
ClangParser();
|
||||||
|
|
||||||
|
static QList<IOutputParser *> clangParserSuite();
|
||||||
|
|
||||||
static Core::Id id();
|
static Core::Id id();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
|
|
||||||
QRegularExpression m_commandRegExp;
|
QRegularExpression m_commandRegExp;
|
||||||
QRegularExpression m_inLineRegExp;
|
QRegularExpression m_inLineRegExp;
|
||||||
|
@@ -129,14 +129,14 @@ Core::Id CustomParser::id()
|
|||||||
return Core::Id("ProjectExplorer.OutputParser.Custom");
|
return Core::Id("ProjectExplorer.OutputParser.Custom");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CustomParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status CustomParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
const CustomParserExpression::CustomParserChannel channel = type == StdErrFormat
|
const CustomParserExpression::CustomParserChannel channel = type == StdErrFormat
|
||||||
? CustomParserExpression::ParseStdErrChannel
|
? CustomParserExpression::ParseStdErrChannel
|
||||||
: CustomParserExpression::ParseStdOutChannel;
|
: CustomParserExpression::ParseStdOutChannel;
|
||||||
if (parseLine(line, channel))
|
if (parseLine(line, channel))
|
||||||
return;
|
return Status::Done;
|
||||||
IOutputParser::handleLine(line, type);
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CustomParser::hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
|
bool CustomParser::hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
|
||||||
@@ -467,7 +467,7 @@ void ProjectExplorerPlugin::testCustomOutputParsers()
|
|||||||
parser->skipFileExistsCheck();
|
parser->skipFileExistsCheck();
|
||||||
|
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(parser);
|
testbench.addLineParser(parser);
|
||||||
testbench.testParsing(input, inputChannel,
|
testbench.testParsing(input, inputChannel,
|
||||||
tasks, childStdOutLines, childStdErrLines,
|
tasks, childStdOutLines, childStdErrLines,
|
||||||
outputLines);
|
outputLines);
|
||||||
|
@@ -91,7 +91,7 @@ public:
|
|||||||
static Core::Id id();
|
static Core::Id id();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
|
|
||||||
bool hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
|
bool hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
|
||||||
const CustomParserExpression &expression, Task::TaskType taskType);
|
const CustomParserExpression &expression, Task::TaskType taskType);
|
||||||
|
@@ -196,19 +196,19 @@ QStringList CustomToolChain::suggestedMkspecList() const
|
|||||||
return m_mkspecs;
|
return m_mkspecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *CustomToolChain::outputParser() const
|
QList<IOutputParser *> CustomToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
if (m_outputParserId == GccParser::id())
|
if (m_outputParserId == GccParser::id())
|
||||||
return new GccParser;
|
return GccParser::gccParserSuite();
|
||||||
if (m_outputParserId == ClangParser::id())
|
if (m_outputParserId == ClangParser::id())
|
||||||
return new ClangParser;
|
return ClangParser::clangParserSuite();
|
||||||
if (m_outputParserId == LinuxIccParser::id())
|
if (m_outputParserId == LinuxIccParser::id())
|
||||||
return new LinuxIccParser;
|
return LinuxIccParser::iccParserSuite();
|
||||||
if (m_outputParserId == MsvcParser::id())
|
if (m_outputParserId == MsvcParser::id())
|
||||||
return new MsvcParser;
|
return {new MsvcParser};
|
||||||
if (m_outputParserId == CustomParser::id())
|
if (m_outputParserId == CustomParser::id())
|
||||||
return new CustomParser(m_customParserSettings);
|
return {new CustomParser(m_customParserSettings)};
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList CustomToolChain::headerPathsList() const
|
QStringList CustomToolChain::headerPathsList() const
|
||||||
|
@@ -84,7 +84,7 @@ public:
|
|||||||
const Utils::Environment &env) const override;
|
const Utils::Environment &env) const override;
|
||||||
void addToEnvironment(Utils::Environment &env) const override;
|
void addToEnvironment(Utils::Environment &env) const override;
|
||||||
QStringList suggestedMkspecList() const override;
|
QStringList suggestedMkspecList() const override;
|
||||||
IOutputParser *outputParser() const override;
|
QList<IOutputParser *> outputParsers() const override;
|
||||||
QStringList headerPathsList() const;
|
QStringList headerPathsList() const;
|
||||||
void setHeaderPaths(const QStringList &list);
|
void setHeaderPaths(const QStringList &list);
|
||||||
|
|
||||||
|
@@ -59,84 +59,6 @@ GccParser::GccParser()
|
|||||||
// optional .exe postfix
|
// optional .exe postfix
|
||||||
m_regExpGccNames.setPattern(QLatin1String(COMMAND_PATTERN));
|
m_regExpGccNames.setPattern(QLatin1String(COMMAND_PATTERN));
|
||||||
QTC_CHECK(m_regExpGccNames.isValid());
|
QTC_CHECK(m_regExpGccNames.isValid());
|
||||||
|
|
||||||
appendOutputParser(new Internal::LldParser);
|
|
||||||
appendOutputParser(new LdParser);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GccParser::stdError(const QString &line)
|
|
||||||
{
|
|
||||||
QString lne = rightTrimmed(line);
|
|
||||||
|
|
||||||
// Blacklist some lines to not handle them:
|
|
||||||
if (lne.startsWith(QLatin1String("TeamBuilder ")) ||
|
|
||||||
lne.startsWith(QLatin1String("distcc["))) {
|
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle misc issues:
|
|
||||||
if (lne.startsWith(QLatin1String("ERROR:")) ||
|
|
||||||
lne == QLatin1String("* cpp failed")) {
|
|
||||||
newTask(CompileTask(Task::Error, lne /* description */));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QRegularExpressionMatch match = m_regExpGccNames.match(lne);
|
|
||||||
if (match.hasMatch()) {
|
|
||||||
QString description = lne.mid(match.capturedLength());
|
|
||||||
Task::TaskType type = Task::Error;
|
|
||||||
if (description.startsWith(QLatin1String("warning: "))) {
|
|
||||||
type = Task::Warning;
|
|
||||||
description = description.mid(9);
|
|
||||||
} else if (description.startsWith(QLatin1String("fatal: "))) {
|
|
||||||
description = description.mid(7);
|
|
||||||
}
|
|
||||||
newTask(CompileTask(type, description));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
if (match.captured(7) == QLatin1String("warning"))
|
|
||||||
type = Task::Warning;
|
|
||||||
else if (match.captured(7) == QLatin1String("error") ||
|
|
||||||
description.startsWith(QLatin1String("undefined reference to")) ||
|
|
||||||
description.startsWith(QLatin1String("multiple definition of")))
|
|
||||||
type = Task::Error;
|
|
||||||
// Prepend "#warning" or "#error" if that triggered the match on (warning|error)
|
|
||||||
// We want those to show how the warning was triggered
|
|
||||||
if (match.captured(5).startsWith(QLatin1Char('#')))
|
|
||||||
description = match.captured(5) + description;
|
|
||||||
|
|
||||||
newTask(CompileTask(type, description, absoluteFilePath(filename), lineno));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
} else if (lne.startsWith(' ') && !m_currentTask.isNull()) {
|
|
||||||
amendDescription(lne, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
doFlush();
|
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GccParser::stdOutput(const QString &line)
|
|
||||||
{
|
|
||||||
doFlush();
|
|
||||||
IOutputParser::handleLine(line, StdOutFormat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Id GccParser::id()
|
Core::Id GccParser::id()
|
||||||
@@ -144,6 +66,11 @@ Core::Id GccParser::id()
|
|||||||
return Core::Id("ProjectExplorer.OutputParser.Gcc");
|
return Core::Id("ProjectExplorer.OutputParser.Gcc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<IOutputParser *> GccParser::gccParserSuite()
|
||||||
|
{
|
||||||
|
return {new GccParser, new Internal::LldParser, new LdParser};
|
||||||
|
}
|
||||||
|
|
||||||
void GccParser::newTask(const Task &task)
|
void GccParser::newTask(const Task &task)
|
||||||
{
|
{
|
||||||
doFlush();
|
doFlush();
|
||||||
@@ -180,12 +107,78 @@ void GccParser::amendDescription(const QString &desc, bool monospaced)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GccParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status GccParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type == StdOutFormat)
|
if (type == StdOutFormat) {
|
||||||
stdOutput(line);
|
// TODO: The "flush on channel switch" logic could possibly also done centrally.
|
||||||
else
|
// But see MSVC with the stdout/stderr switches because of jom
|
||||||
stdError(line);
|
doFlush();
|
||||||
|
return Status::NotHandled;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString lne = rightTrimmed(line);
|
||||||
|
|
||||||
|
// Blacklist some lines to not handle them:
|
||||||
|
if (lne.startsWith(QLatin1String("TeamBuilder ")) ||
|
||||||
|
lne.startsWith(QLatin1String("distcc["))) {
|
||||||
|
return Status::NotHandled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle misc issues:
|
||||||
|
if (lne.startsWith(QLatin1String("ERROR:")) || lne == QLatin1String("* cpp failed")) {
|
||||||
|
newTask(CompileTask(Task::Error, lne /* description */));
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRegularExpressionMatch match = m_regExpGccNames.match(lne);
|
||||||
|
if (match.hasMatch()) {
|
||||||
|
QString description = lne.mid(match.capturedLength());
|
||||||
|
Task::TaskType type = Task::Error;
|
||||||
|
if (description.startsWith(QLatin1String("warning: "))) {
|
||||||
|
type = Task::Warning;
|
||||||
|
description = description.mid(9);
|
||||||
|
} else if (description.startsWith(QLatin1String("fatal: "))) {
|
||||||
|
description = description.mid(7);
|
||||||
|
}
|
||||||
|
newTask(CompileTask(type, description));
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (match.captured(7) == QLatin1String("warning"))
|
||||||
|
type = Task::Warning;
|
||||||
|
else if (match.captured(7) == QLatin1String("error") ||
|
||||||
|
description.startsWith(QLatin1String("undefined reference to")) ||
|
||||||
|
description.startsWith(QLatin1String("multiple definition of")))
|
||||||
|
type = Task::Error;
|
||||||
|
// Prepend "#warning" or "#error" if that triggered the match on (warning|error)
|
||||||
|
// We want those to show how the warning was triggered
|
||||||
|
if (match.captured(5).startsWith(QLatin1Char('#')))
|
||||||
|
description = match.captured(5) + description;
|
||||||
|
|
||||||
|
newTask(CompileTask(type, description, absoluteFilePath(filename), lineno));
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
} else if (lne.startsWith(' ') && !m_currentTask.isNull()) {
|
||||||
|
amendDescription(lne, true);
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
doFlush();
|
||||||
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unit tests:
|
// Unit tests:
|
||||||
@@ -1130,7 +1123,7 @@ void ProjectExplorerPlugin::testGccOutputParsers_data()
|
|||||||
void ProjectExplorerPlugin::testGccOutputParsers()
|
void ProjectExplorerPlugin::testGccOutputParsers()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new GccParser);
|
testbench.setLineParsers(GccParser::gccParserSuite());
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -42,6 +42,8 @@ public:
|
|||||||
|
|
||||||
static Core::Id id();
|
static Core::Id id();
|
||||||
|
|
||||||
|
static QList<IOutputParser *> gccParserSuite();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void newTask(const Task &task);
|
void newTask(const Task &task);
|
||||||
void doFlush() override;
|
void doFlush() override;
|
||||||
@@ -49,10 +51,7 @@ protected:
|
|||||||
void amendDescription(const QString &desc, bool monospaced);
|
void amendDescription(const QString &desc, bool monospaced);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
|
|
||||||
void stdError(const QString &line);
|
|
||||||
void stdOutput(const QString &line);
|
|
||||||
|
|
||||||
QRegularExpression m_regExp;
|
QRegularExpression m_regExp;
|
||||||
QRegularExpression m_regExpIncluded;
|
QRegularExpression m_regExpIncluded;
|
||||||
|
@@ -731,9 +731,9 @@ FilePath GccToolChain::makeCommand(const Environment &environment) const
|
|||||||
return tmp.isEmpty() ? FilePath::fromString("make") : tmp;
|
return tmp.isEmpty() ? FilePath::fromString("make") : tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *GccToolChain::outputParser() const
|
QList<IOutputParser *> GccToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
return new GccParser;
|
return GccParser::gccParserSuite();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GccToolChain::resetToolChain(const FilePath &path)
|
void GccToolChain::resetToolChain(const FilePath &path)
|
||||||
@@ -1628,9 +1628,9 @@ LanguageExtensions ClangToolChain::defaultLanguageExtensions() const
|
|||||||
return LanguageExtension::Gnu;
|
return LanguageExtension::Gnu;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *ClangToolChain::outputParser() const
|
QList<IOutputParser *> ClangToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
return new ClangParser;
|
return ClangParser::clangParserSuite();
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -1898,9 +1898,9 @@ LanguageExtensions LinuxIccToolChain::languageExtensions(const QStringList &cxxf
|
|||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *LinuxIccToolChain::outputParser() const
|
QList<IOutputParser *> LinuxIccToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
return new LinuxIccParser;
|
return LinuxIccParser::iccParserSuite();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList LinuxIccToolChain::suggestedMkspecList() const
|
QStringList LinuxIccToolChain::suggestedMkspecList() const
|
||||||
|
@@ -94,7 +94,7 @@ public:
|
|||||||
void addToEnvironment(Utils::Environment &env) const override;
|
void addToEnvironment(Utils::Environment &env) const override;
|
||||||
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
|
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
|
||||||
QStringList suggestedMkspecList() const override;
|
QStringList suggestedMkspecList() const override;
|
||||||
IOutputParser *outputParser() const override;
|
QList<IOutputParser *> outputParsers() const override;
|
||||||
|
|
||||||
QVariantMap toMap() const override;
|
QVariantMap toMap() const override;
|
||||||
bool fromMap(const QVariantMap &data) override;
|
bool fromMap(const QVariantMap &data) override;
|
||||||
@@ -226,7 +226,7 @@ public:
|
|||||||
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
|
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
|
||||||
Utils::WarningFlags warningFlags(const QStringList &cflags) const override;
|
Utils::WarningFlags warningFlags(const QStringList &cflags) const override;
|
||||||
|
|
||||||
IOutputParser *outputParser() const override;
|
QList<IOutputParser *> outputParsers() const override;
|
||||||
|
|
||||||
QStringList suggestedMkspecList() const override;
|
QStringList suggestedMkspecList() const override;
|
||||||
void addToEnvironment(Utils::Environment &env) const override;
|
void addToEnvironment(Utils::Environment &env) const override;
|
||||||
@@ -286,7 +286,7 @@ class PROJECTEXPLORER_EXPORT LinuxIccToolChain : public GccToolChain
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
|
Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const override;
|
||||||
IOutputParser *outputParser() const override;
|
QList<IOutputParser *> outputParsers() const override;
|
||||||
|
|
||||||
QStringList suggestedMkspecList() const override;
|
QStringList suggestedMkspecList() const override;
|
||||||
|
|
||||||
|
@@ -56,35 +56,6 @@ GnuMakeParser::GnuMakeParser()
|
|||||||
QTC_CHECK(m_errorInMakefile.isValid());
|
QTC_CHECK(m_errorInMakefile.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GnuMakeParser::handleLine(const QString &line, OutputFormat type)
|
|
||||||
{
|
|
||||||
if (type == StdOutFormat)
|
|
||||||
stdOutput(line);
|
|
||||||
else
|
|
||||||
stdError(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GnuMakeParser::hasFatalErrors() const
|
|
||||||
{
|
|
||||||
return (m_fatalErrorCount > 0) || IOutputParser::hasFatalErrors();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GnuMakeParser::stdOutput(const QString &line)
|
|
||||||
{
|
|
||||||
const QString lne = rightTrimmed(line);
|
|
||||||
|
|
||||||
QRegularExpressionMatch match = m_makeDir.match(lne);
|
|
||||||
if (match.hasMatch()) {
|
|
||||||
if (match.captured(6) == QLatin1String("Leaving"))
|
|
||||||
dropSearchDir(FilePath::fromString(match.captured(7)));
|
|
||||||
else
|
|
||||||
addSearchDir(FilePath::fromString(match.captured(7)));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IOutputParser::handleLine(line, StdOutFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Result {
|
class Result {
|
||||||
public:
|
public:
|
||||||
Result() = default;
|
Result() = default;
|
||||||
@@ -125,13 +96,29 @@ static Result parseDescription(const QString &description)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GnuMakeParser::stdError(const QString &line)
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOutputParser::Status GnuMakeParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
const QString lne = rightTrimmed(line);
|
const QString lne = rightTrimmed(line);
|
||||||
|
if (type == StdOutFormat) {
|
||||||
|
QRegularExpressionMatch match = m_makeDir.match(lne);
|
||||||
|
if (match.hasMatch()) {
|
||||||
|
if (match.captured(6) == QLatin1String("Leaving"))
|
||||||
|
emit searchDirOut(FilePath::fromString(match.captured(7)));
|
||||||
|
else
|
||||||
|
emit searchDirIn(FilePath::fromString(match.captured(7)));
|
||||||
|
return Status::Done;
|
||||||
|
}
|
||||||
|
return Status::NotHandled;
|
||||||
|
}
|
||||||
QRegularExpressionMatch match = m_errorInMakefile.match(lne);
|
QRegularExpressionMatch match = m_errorInMakefile.match(lne);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
flush();
|
|
||||||
Result res = parseDescription(match.captured(5));
|
Result res = parseDescription(match.captured(5));
|
||||||
if (res.isFatal)
|
if (res.isFatal)
|
||||||
++m_fatalErrorCount;
|
++m_fatalErrorCount;
|
||||||
@@ -140,27 +127,24 @@ void GnuMakeParser::stdError(const QString &line)
|
|||||||
absoluteFilePath(FilePath::fromUserInput(match.captured(1))),
|
absoluteFilePath(FilePath::fromUserInput(match.captured(1))),
|
||||||
match.captured(4).toInt() /* line */));
|
match.captured(4).toInt() /* line */));
|
||||||
}
|
}
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
match = m_makeLine.match(lne);
|
match = m_makeLine.match(lne);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
flush();
|
|
||||||
Result res = parseDescription(match.captured(6));
|
Result res = parseDescription(match.captured(6));
|
||||||
if (res.isFatal)
|
if (res.isFatal)
|
||||||
++m_fatalErrorCount;
|
++m_fatalErrorCount;
|
||||||
if (!m_suppressIssues)
|
if (!m_suppressIssues)
|
||||||
emitTask(BuildSystemTask(res.type, res.description));
|
emitTask(BuildSystemTask(res.type, res.description));
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GnuMakeParser::emitTask(const ProjectExplorer::Task &task)
|
bool GnuMakeParser::hasFatalErrors() const
|
||||||
{
|
{
|
||||||
if (task.type == Task::Error) // Assume that all make errors will be follow up errors.
|
return (m_fatalErrorCount > 0) || IOutputParser::hasFatalErrors();
|
||||||
m_suppressIssues = true;
|
|
||||||
emit addTask(task, 1, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // ProjectExplorer
|
} // ProjectExplorer
|
||||||
@@ -371,7 +355,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing()
|
|||||||
connect(&testbench, &OutputParserTester::aboutToDeleteParser,
|
connect(&testbench, &OutputParserTester::aboutToDeleteParser,
|
||||||
tester, &GnuMakeParserTester::parserIsAboutToBeDeleted);
|
tester, &GnuMakeParserTester::parserIsAboutToBeDeleted);
|
||||||
|
|
||||||
testbench.appendOutputParser(childParser);
|
testbench.addLineParser(childParser);
|
||||||
QFETCH(QStringList, extraSearchDirs);
|
QFETCH(QStringList, extraSearchDirs);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
@@ -381,11 +365,11 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing()
|
|||||||
QFETCH(QString, outputLines);
|
QFETCH(QString, outputLines);
|
||||||
QFETCH(QStringList, additionalSearchDirs);
|
QFETCH(QStringList, additionalSearchDirs);
|
||||||
|
|
||||||
FilePaths searchDirs = childParser->searchDirectories();
|
FilePaths searchDirs = testbench.searchDirectories();
|
||||||
|
|
||||||
// add extra directories:
|
// add extra directories:
|
||||||
foreach (const QString &dir, extraSearchDirs)
|
foreach (const QString &dir, extraSearchDirs)
|
||||||
childParser->addSearchDir(FilePath::fromString(dir));
|
testbench.addSearchDir(FilePath::fromString(dir));
|
||||||
|
|
||||||
testbench.testParsing(input, inputChannel,
|
testbench.testParsing(input, inputChannel,
|
||||||
tasks, childStdOutLines, childStdErrLines,
|
tasks, childStdOutLines, childStdErrLines,
|
||||||
@@ -418,7 +402,7 @@ void ProjectExplorerPlugin::testGnuMakeParserTaskMangling()
|
|||||||
|
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
auto *childParser = new GnuMakeParser;
|
auto *childParser = new GnuMakeParser;
|
||||||
testbench.appendOutputParser(childParser);
|
testbench.addLineParser(childParser);
|
||||||
childParser->addSearchDir(FilePath::fromString(fi.absolutePath()));
|
childParser->addSearchDir(FilePath::fromString(fi.absolutePath()));
|
||||||
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.",
|
||||||
|
@@ -40,12 +40,9 @@ public:
|
|||||||
explicit GnuMakeParser();
|
explicit GnuMakeParser();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
bool hasFatalErrors() const override;
|
bool hasFatalErrors() const override;
|
||||||
|
|
||||||
void stdOutput(const QString &line);
|
|
||||||
void stdError(const QString &line);
|
|
||||||
|
|
||||||
void emitTask(const ProjectExplorer::Task &task);
|
void emitTask(const ProjectExplorer::Task &task);
|
||||||
|
|
||||||
QRegularExpression m_makeDir;
|
QRegularExpression m_makeDir;
|
||||||
|
@@ -26,10 +26,12 @@
|
|||||||
#include "ioutputparser.h"
|
#include "ioutputparser.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class ProjectExplorer::IOutputParser
|
\class ProjectExplorer::IOutputParser
|
||||||
@@ -41,21 +43,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn void ProjectExplorer::IOutputParser::appendOutputParser(IOutputParser *parser)
|
\fn ProjectExplorer::IOutputParser::Status ProjectExplorer::IOutputParser::doHandleLine(const QString &line, Utils::OutputFormat type)
|
||||||
|
|
||||||
Appends a subparser to this parser, of which IOutputParser will take
|
|
||||||
ownership.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn IOutputParser *ProjectExplorer::IOutputParser::childParser() const
|
|
||||||
|
|
||||||
Returns the head of this parser's output parser children. IOutputParser
|
|
||||||
keeps ownership.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn void ProjectExplorer::IOutputParser::handleLine(const QString &line, Utils::OutputFormat type)
|
|
||||||
|
|
||||||
Called once for each line of standard output or standard error to parse.
|
Called once for each line of standard output or standard error to parse.
|
||||||
*/
|
*/
|
||||||
@@ -66,28 +54,12 @@
|
|||||||
This is mainly a Symbian specific quirk.
|
This is mainly a Symbian specific quirk.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn void ProjectExplorer::IOutputParser::addOutput(const QString &string, ProjectExplorer::BuildStep::OutputFormat format)
|
|
||||||
|
|
||||||
Should be emitted whenever some additional information should be added to the
|
|
||||||
output.
|
|
||||||
|
|
||||||
\note This is additional information. There is no need to add each line.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn void ProjectExplorer::IOutputParser::addTask(const ProjectExplorer::Task &task)
|
\fn void ProjectExplorer::IOutputParser::addTask(const ProjectExplorer::Task &task)
|
||||||
|
|
||||||
Should be emitted for each task seen in the output.
|
Should be emitted for each task seen in the output.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn void ProjectExplorer::IOutputParser::taskAdded(const ProjectExplorer::Task &task)
|
|
||||||
|
|
||||||
Subparsers have their addTask signal connected to this slot.
|
|
||||||
This function can be overwritten to change the task.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn void ProjectExplorer::IOutputParser::doFlush()
|
\fn void ProjectExplorer::IOutputParser::doFlush()
|
||||||
|
|
||||||
@@ -121,14 +93,14 @@ public:
|
|||||||
break;
|
break;
|
||||||
const QString line = pendingData.left(eolPos + 1);
|
const QString line = pendingData.left(eolPos + 1);
|
||||||
pendingData.remove(0, eolPos + 1);
|
pendingData.remove(0, eolPos + 1);
|
||||||
parser->handleLine(parser->filteredLine(line), type);
|
parser->handleLine(line, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush()
|
void flush()
|
||||||
{
|
{
|
||||||
if (!pendingData.isEmpty()) {
|
if (!pendingData.isEmpty()) {
|
||||||
parser->handleLine(parser->filteredLine(pendingData), type);
|
parser->handleLine(pendingData, type);
|
||||||
pendingData.clear();
|
pendingData.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,11 +118,13 @@ public:
|
|||||||
stderrState(parser, Utils::StdErrFormat)
|
stderrState(parser, Utils::StdErrFormat)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
IOutputParser *childParser = nullptr;
|
QList<IOutputParser *> lineParsers;
|
||||||
|
IOutputParser *nextParser = nullptr;
|
||||||
QList<Filter> filters;
|
QList<Filter> filters;
|
||||||
Utils::FilePaths searchDirs;
|
Utils::FilePaths searchDirs;
|
||||||
OutputChannelState stdoutState;
|
OutputChannelState stdoutState;
|
||||||
OutputChannelState stderrState;
|
OutputChannelState stderrState;
|
||||||
|
QPointer<const IOutputParser> redirectionDetector;
|
||||||
bool skipFileExistsCheck = false;
|
bool skipFileExistsCheck = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -160,7 +134,7 @@ IOutputParser::IOutputParser() : d(new IOutputParserPrivate(this))
|
|||||||
|
|
||||||
IOutputParser::~IOutputParser()
|
IOutputParser::~IOutputParser()
|
||||||
{
|
{
|
||||||
delete d->childParser;
|
clear();
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,46 +148,44 @@ void IOutputParser::handleStderr(const QString &data)
|
|||||||
d->stderrState.handleData(data);
|
d->stderrState.handleData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IOutputParser::appendOutputParser(IOutputParser *parser)
|
IOutputParser::Status IOutputParser::doHandleLine(const QString &line, Utils::OutputFormat type)
|
||||||
{
|
{
|
||||||
if (!parser)
|
Q_UNUSED(line);
|
||||||
return;
|
Q_UNUSED(type);
|
||||||
if (d->childParser) {
|
return Status::NotHandled;
|
||||||
d->childParser->appendOutputParser(parser);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
d->childParser = parser;
|
|
||||||
connect(parser, &IOutputParser::addTask, this, &IOutputParser::addTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
IOutputParser *IOutputParser::childParser() const
|
|
||||||
{
|
|
||||||
return d->childParser;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IOutputParser::setChildParser(IOutputParser *parser)
|
|
||||||
{
|
|
||||||
if (d->childParser != parser)
|
|
||||||
delete d->childParser;
|
|
||||||
d->childParser = parser;
|
|
||||||
if (parser)
|
|
||||||
connect(parser, &IOutputParser::addTask, this, &IOutputParser::addTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IOutputParser::handleLine(const QString &line, Utils::OutputFormat type)
|
|
||||||
{
|
|
||||||
if (d->childParser)
|
|
||||||
d->childParser->handleLine(line, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IOutputParser::skipFileExistsCheck()
|
|
||||||
{
|
|
||||||
d->skipFileExistsCheck = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IOutputParser::doFlush() { }
|
void IOutputParser::doFlush() { }
|
||||||
|
|
||||||
|
void IOutputParser::handleLine(const QString &line, Utils::OutputFormat type)
|
||||||
|
{
|
||||||
|
const QString cleanLine = filteredLine(line);
|
||||||
|
if (d->nextParser) {
|
||||||
|
switch (d->nextParser->doHandleLine(cleanLine, outputTypeForParser(d->nextParser, type))) {
|
||||||
|
case Status::Done:
|
||||||
|
d->nextParser = nullptr;
|
||||||
|
return;
|
||||||
|
case Status::InProgress:
|
||||||
|
return;
|
||||||
|
case Status::NotHandled:
|
||||||
|
d->nextParser = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QTC_CHECK(!d->nextParser);
|
||||||
|
for (IOutputParser * const lineParser : d->lineParsers) {
|
||||||
|
switch (lineParser->doHandleLine(cleanLine, outputTypeForParser(lineParser, type))) {
|
||||||
|
case Status::Done:
|
||||||
|
return;
|
||||||
|
case Status::InProgress:
|
||||||
|
d->nextParser = lineParser;
|
||||||
|
return;
|
||||||
|
case Status::NotHandled:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString IOutputParser::filteredLine(const QString &line) const
|
QString IOutputParser::filteredLine(const QString &line) const
|
||||||
{
|
{
|
||||||
QString l = line;
|
QString l = line;
|
||||||
@@ -222,26 +194,70 @@ QString IOutputParser::filteredLine(const QString &line) const
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IOutputParser::connectLineParser(IOutputParser *parser)
|
||||||
|
{
|
||||||
|
connect(parser, &IOutputParser::addTask, this, &IOutputParser::addTask);
|
||||||
|
connect(parser, &IOutputParser::searchDirIn, this, &IOutputParser::addSearchDir);
|
||||||
|
connect(parser, &IOutputParser::searchDirOut, this, &IOutputParser::dropSearchDir);
|
||||||
|
}
|
||||||
|
|
||||||
bool IOutputParser::hasFatalErrors() const
|
bool IOutputParser::hasFatalErrors() const
|
||||||
{
|
{
|
||||||
return d->childParser && d->childParser->hasFatalErrors();
|
return Utils::anyOf(d->lineParsers, [](const IOutputParser *p) { return p->hasFatalErrors(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void IOutputParser::flush()
|
void IOutputParser::flush()
|
||||||
{
|
{
|
||||||
flushTasks();
|
|
||||||
d->stdoutState.flush();
|
d->stdoutState.flush();
|
||||||
d->stderrState.flush();
|
d->stderrState.flush();
|
||||||
flushTasks();
|
doFlush();
|
||||||
|
for (IOutputParser * const p : qAsConst(d->lineParsers))
|
||||||
|
p->doFlush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IOutputParser::flushTasks()
|
void IOutputParser::clear()
|
||||||
{
|
{
|
||||||
doFlush();
|
d->nextParser = nullptr;
|
||||||
if (d->childParser)
|
d->redirectionDetector.clear();
|
||||||
d->childParser->flushTasks();
|
d->filters.clear();
|
||||||
|
d->searchDirs.clear();
|
||||||
|
qDeleteAll(d->lineParsers);
|
||||||
|
d->lineParsers.clear();
|
||||||
|
d->stdoutState.pendingData.clear();
|
||||||
|
d->stderrState.pendingData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IOutputParser::addLineParser(IOutputParser *parser)
|
||||||
|
{
|
||||||
|
connectLineParser(parser);
|
||||||
|
d->lineParsers << parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOutputParser::addLineParsers(const QList<IOutputParser *> &parsers)
|
||||||
|
{
|
||||||
|
for (IOutputParser * const p : qAsConst(parsers))
|
||||||
|
addLineParser(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOutputParser::setLineParsers(const QList<IOutputParser *> &parsers)
|
||||||
|
{
|
||||||
|
qDeleteAll(d->lineParsers);
|
||||||
|
d->lineParsers.clear();
|
||||||
|
addLineParsers(parsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_TESTS
|
||||||
|
QList<IOutputParser *> IOutputParser::lineParsers() const
|
||||||
|
{
|
||||||
|
return d->lineParsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IOutputParser::skipFileExistsCheck()
|
||||||
|
{
|
||||||
|
d->skipFileExistsCheck = true;
|
||||||
|
}
|
||||||
|
#endif // WITH_TESTS
|
||||||
|
|
||||||
QString IOutputParser::rightTrimmed(const QString &in)
|
QString IOutputParser::rightTrimmed(const QString &in)
|
||||||
{
|
{
|
||||||
int pos = in.length();
|
int pos = in.length();
|
||||||
@@ -260,8 +276,8 @@ void IOutputParser::addFilter(const Filter &filter)
|
|||||||
void IOutputParser::addSearchDir(const Utils::FilePath &dir)
|
void IOutputParser::addSearchDir(const Utils::FilePath &dir)
|
||||||
{
|
{
|
||||||
d->searchDirs << dir;
|
d->searchDirs << dir;
|
||||||
if (d->childParser)
|
for (IOutputParser * const p : qAsConst(d->lineParsers))
|
||||||
d->childParser->addSearchDir(dir);
|
p->addSearchDir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IOutputParser::dropSearchDir(const Utils::FilePath &dir)
|
void IOutputParser::dropSearchDir(const Utils::FilePath &dir)
|
||||||
@@ -269,8 +285,8 @@ void IOutputParser::dropSearchDir(const Utils::FilePath &dir)
|
|||||||
const int idx = d->searchDirs.lastIndexOf(dir);
|
const int idx = d->searchDirs.lastIndexOf(dir);
|
||||||
QTC_ASSERT(idx != -1, return);
|
QTC_ASSERT(idx != -1, return);
|
||||||
d->searchDirs.removeAt(idx);
|
d->searchDirs.removeAt(idx);
|
||||||
if (d->childParser)
|
for (IOutputParser * const p : qAsConst(d->lineParsers))
|
||||||
d->childParser->dropSearchDir(dir);
|
p->dropSearchDir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Utils::FilePaths IOutputParser::searchDirectories() const
|
const Utils::FilePaths IOutputParser::searchDirectories() const
|
||||||
@@ -293,4 +309,27 @@ Utils::FilePath IOutputParser::absoluteFilePath(const Utils::FilePath &filePath)
|
|||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 IOutputParser::setRedirectionDetector(const IOutputParser *detector)
|
||||||
|
{
|
||||||
|
d->redirectionDetector = detector;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IOutputParser::needsRedirection() const
|
||||||
|
{
|
||||||
|
return d->redirectionDetector && (d->redirectionDetector->hasDetectedRedirection()
|
||||||
|
|| d->redirectionDetector->needsRedirection());
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::OutputFormat IOutputParser::outputTypeForParser(const IOutputParser *parser,
|
||||||
|
Utils::OutputFormat type) const
|
||||||
|
{
|
||||||
|
if (type == Utils::StdOutFormat && parser->needsRedirection())
|
||||||
|
return Utils::StdErrFormat;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -47,11 +47,6 @@ public:
|
|||||||
void handleStdout(const QString &data);
|
void handleStdout(const QString &data);
|
||||||
void handleStderr(const QString &data);
|
void handleStderr(const QString &data);
|
||||||
|
|
||||||
void appendOutputParser(IOutputParser *parser);
|
|
||||||
|
|
||||||
IOutputParser *childParser() const;
|
|
||||||
void setChildParser(IOutputParser *parser);
|
|
||||||
|
|
||||||
virtual bool hasFatalErrors() const;
|
virtual bool hasFatalErrors() const;
|
||||||
|
|
||||||
using Filter = std::function<QString(const QString &)>;
|
using Filter = std::function<QString(const QString &)>;
|
||||||
@@ -60,25 +55,44 @@ public:
|
|||||||
void addSearchDir(const Utils::FilePath &dir);
|
void addSearchDir(const Utils::FilePath &dir);
|
||||||
void dropSearchDir(const Utils::FilePath &dir);
|
void dropSearchDir(const Utils::FilePath &dir);
|
||||||
const Utils::FilePaths searchDirectories() const;
|
const Utils::FilePaths searchDirectories() const;
|
||||||
void skipFileExistsCheck(); // For testing only
|
|
||||||
|
|
||||||
void flush(); // flush pending tasks & output
|
void flush();
|
||||||
void flushTasks(); // flush pending tasks only
|
void clear();
|
||||||
|
|
||||||
|
void addLineParser(IOutputParser *parser);
|
||||||
|
void addLineParsers(const QList<IOutputParser *> &parsers);
|
||||||
|
void setLineParsers(const QList<IOutputParser *> &parsers);
|
||||||
|
|
||||||
|
#ifdef WITH_TESTS
|
||||||
|
QList<IOutputParser *> lineParsers() const;
|
||||||
|
void skipFileExistsCheck();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void setRedirectionDetector(const IOutputParser *detector);
|
||||||
|
|
||||||
static QString rightTrimmed(const QString &in);
|
static QString rightTrimmed(const QString &in);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void searchDirIn(const Utils::FilePath &dir);
|
||||||
|
void searchDirOut(const Utils::FilePath &dir);
|
||||||
void addTask(const ProjectExplorer::Task &task, int linkedOutputLines = 0, int skipLines = 0);
|
void addTask(const ProjectExplorer::Task &task, int linkedOutputLines = 0, int skipLines = 0);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void handleLine(const QString &line, Utils::OutputFormat type);
|
enum class Status { Done, InProgress, NotHandled };
|
||||||
|
|
||||||
Utils::FilePath absoluteFilePath(const Utils::FilePath &filePath);
|
Utils::FilePath absoluteFilePath(const Utils::FilePath &filePath);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual Status doHandleLine(const QString &line, Utils::OutputFormat type);
|
||||||
virtual void doFlush();
|
virtual void doFlush();
|
||||||
|
virtual bool hasDetectedRedirection() const { return false; }
|
||||||
|
|
||||||
|
void handleLine(const QString &line, Utils::OutputFormat type);
|
||||||
QString filteredLine(const QString &line) const;
|
QString filteredLine(const QString &line) const;
|
||||||
|
void connectLineParser(IOutputParser *parser);
|
||||||
|
bool needsRedirection() const;
|
||||||
|
Utils::OutputFormat outputTypeForParser(const IOutputParser *parser,
|
||||||
|
Utils::OutputFormat type) const;
|
||||||
|
|
||||||
class OutputChannelState;
|
class OutputChannelState;
|
||||||
class IOutputParserPrivate;
|
class IOutputParserPrivate;
|
||||||
|
@@ -559,12 +559,12 @@ void Kit::addToEnvironment(Environment &env) const
|
|||||||
aspect->addToEnvironment(this, env);
|
aspect->addToEnvironment(this, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *Kit::createOutputParser() const
|
QList<IOutputParser *> Kit::createOutputParsers() const
|
||||||
{
|
{
|
||||||
auto first = new OsParser;
|
QList<IOutputParser *> parsers{new OsParser};
|
||||||
for (KitAspect *aspect : KitManager::kitAspects())
|
for (KitAspect *aspect : KitManager::kitAspects())
|
||||||
first->appendOutputParser(aspect->createOutputParser(this));
|
parsers << aspect->createOutputParsers(this);
|
||||||
return first;
|
return parsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Kit::toHtml(const Tasks &additional, const QString &extraText) const
|
QString Kit::toHtml(const Tasks &additional, const QString &extraText) const
|
||||||
|
@@ -116,7 +116,7 @@ public:
|
|||||||
bool isEqual(const Kit *other) const;
|
bool isEqual(const Kit *other) const;
|
||||||
|
|
||||||
void addToEnvironment(Utils::Environment &env) const;
|
void addToEnvironment(Utils::Environment &env) const;
|
||||||
IOutputParser *createOutputParser() const;
|
QList<IOutputParser *> createOutputParsers() const;
|
||||||
|
|
||||||
QString toHtml(const Tasks &additional = Tasks(), const QString &extraText = QString()) const;
|
QString toHtml(const Tasks &additional = Tasks(), const QString &extraText = QString()) const;
|
||||||
Kit *clone(bool keepName = false) const;
|
Kit *clone(bool keepName = false) const;
|
||||||
|
@@ -557,14 +557,13 @@ void ToolChainKitAspect::addToMacroExpander(Kit *kit, Utils::MacroExpander *expa
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<IOutputParser *> ToolChainKitAspect::createOutputParsers(const Kit *k) const
|
||||||
IOutputParser *ToolChainKitAspect::createOutputParser(const Kit *k) const
|
|
||||||
{
|
{
|
||||||
for (const Core::Id langId : {Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID}) {
|
for (const Core::Id langId : {Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID}) {
|
||||||
if (const ToolChain * const tc = toolChain(k, langId))
|
if (const ToolChain * const tc = toolChain(k, langId))
|
||||||
return tc->outputParser();
|
return tc->outputParsers();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<Core::Id> ToolChainKitAspect::availableFeatures(const Kit *k) const
|
QSet<Core::Id> ToolChainKitAspect::availableFeatures(const Kit *k) const
|
||||||
|
@@ -84,7 +84,7 @@ public:
|
|||||||
|
|
||||||
void addToEnvironment(const Kit *k, Utils::Environment &env) const override;
|
void addToEnvironment(const Kit *k, Utils::Environment &env) const override;
|
||||||
void addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const override;
|
void addToMacroExpander(Kit *kit, Utils::MacroExpander *expander) const override;
|
||||||
IOutputParser *createOutputParser(const Kit *k) const override;
|
QList<IOutputParser *> createOutputParsers(const Kit *k) const override;
|
||||||
QSet<Core::Id> availableFeatures(const Kit *k) const override;
|
QSet<Core::Id> availableFeatures(const Kit *k) const override;
|
||||||
|
|
||||||
static Core::Id id();
|
static Core::Id id();
|
||||||
|
@@ -677,10 +677,10 @@ void KitAspect::addToEnvironment(const Kit *k, Environment &env) const
|
|||||||
Q_UNUSED(env)
|
Q_UNUSED(env)
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *KitAspect::createOutputParser(const Kit *k) const
|
QList<IOutputParser *> KitAspect::createOutputParsers(const Kit *k) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(k)
|
Q_UNUSED(k)
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString KitAspect::displayNamePostfix(const Kit *k) const
|
QString KitAspect::displayNamePostfix(const Kit *k) const
|
||||||
|
@@ -91,7 +91,7 @@ public:
|
|||||||
virtual KitAspectWidget *createConfigWidget(Kit *) const = 0;
|
virtual KitAspectWidget *createConfigWidget(Kit *) const = 0;
|
||||||
|
|
||||||
virtual void addToEnvironment(const Kit *k, Utils::Environment &env) const;
|
virtual void addToEnvironment(const Kit *k, Utils::Environment &env) const;
|
||||||
virtual IOutputParser *createOutputParser(const Kit *k) const;
|
virtual QList<IOutputParser *> createOutputParsers(const Kit *k) const;
|
||||||
|
|
||||||
virtual QString displayNamePostfix(const Kit *k) const;
|
virtual QString displayNamePostfix(const Kit *k) const;
|
||||||
|
|
||||||
|
@@ -54,27 +54,27 @@ LdParser::LdParser()
|
|||||||
QTC_CHECK(m_regExpGccNames.isValid());
|
QTC_CHECK(m_regExpGccNames.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LdParser::handleLine(const QString &line, Utils::OutputFormat type)
|
IOutputParser::Status LdParser::doHandleLine(const QString &line, Utils::OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type != Utils::StdErrFormat) {
|
if (type != Utils::StdErrFormat)
|
||||||
IOutputParser::handleLine(line, type);
|
return Status::NotHandled;
|
||||||
return;
|
|
||||||
}
|
|
||||||
QString lne = rightTrimmed(line);
|
QString lne = rightTrimmed(line);
|
||||||
if (!lne.isEmpty() && !lne.at(0).isSpace() && !m_incompleteTask.isNull())
|
if (!lne.isEmpty() && !lne.at(0).isSpace() && !m_incompleteTask.isNull()) {
|
||||||
flush();
|
doFlush();
|
||||||
|
return Status::NotHandled;
|
||||||
|
}
|
||||||
|
|
||||||
if (lne.startsWith(QLatin1String("TeamBuilder "))
|
if (lne.startsWith(QLatin1String("TeamBuilder "))
|
||||||
|| lne.startsWith(QLatin1String("distcc["))
|
|| lne.startsWith(QLatin1String("distcc["))
|
||||||
|| lne.contains(QLatin1String("ar: creating "))) {
|
|| lne.contains(QLatin1String("ar: creating "))) {
|
||||||
IOutputParser::handleLine(line, Utils::StdErrFormat);
|
return Status::NotHandled;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ld on macOS
|
// ld on macOS
|
||||||
if (lne.startsWith("Undefined symbols for architecture") && lne.endsWith(":")) {
|
if (lne.startsWith("Undefined symbols for architecture") && lne.endsWith(":")) {
|
||||||
m_incompleteTask = CompileTask(Task::Error, lne);
|
m_incompleteTask = CompileTask(Task::Error, lne);
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
if (!m_incompleteTask.isNull() && lne.startsWith(" ")) {
|
if (!m_incompleteTask.isNull() && lne.startsWith(" ")) {
|
||||||
m_incompleteTask.description.append('\n').append(lne);
|
m_incompleteTask.description.append('\n').append(lne);
|
||||||
@@ -82,19 +82,19 @@ void LdParser::handleLine(const QString &line, Utils::OutputFormat type)
|
|||||||
const QRegularExpressionMatch match = locRegExp.match(lne);
|
const QRegularExpressionMatch match = locRegExp.match(lne);
|
||||||
if (match.hasMatch())
|
if (match.hasMatch())
|
||||||
m_incompleteTask.setFile(Utils::FilePath::fromString(match.captured("file")));
|
m_incompleteTask.setFile(Utils::FilePath::fromString(match.captured("file")));
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lne.startsWith("collect2:") || lne.startsWith("collect2.exe:")) {
|
if (lne.startsWith("collect2:") || lne.startsWith("collect2.exe:")) {
|
||||||
emit addTask(CompileTask(Task::Error, lne /* description */), 1);
|
emit addTask(CompileTask(Task::Error, lne /* description */), 1);
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRegularExpressionMatch match = m_ranlib.match(lne);
|
QRegularExpressionMatch match = m_ranlib.match(lne);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
QString description = match.captured(2);
|
QString description = match.captured(2);
|
||||||
emit addTask(CompileTask(Task::Warning, description), 1);
|
emit addTask(CompileTask(Task::Warning, description), 1);
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = m_regExpGccNames.match(lne);
|
match = m_regExpGccNames.match(lne);
|
||||||
@@ -108,7 +108,7 @@ void LdParser::handleLine(const QString &line, Utils::OutputFormat type)
|
|||||||
description = description.mid(7);
|
description = description.mid(7);
|
||||||
}
|
}
|
||||||
emit addTask(CompileTask(type, description), 1);
|
emit addTask(CompileTask(type, description), 1);
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = m_regExpLinker.match(lne);
|
match = m_regExpLinker.match(lne);
|
||||||
@@ -138,10 +138,10 @@ void LdParser::handleLine(const QString &line, Utils::OutputFormat type)
|
|||||||
description = description.mid(9);
|
description = description.mid(9);
|
||||||
}
|
}
|
||||||
emit addTask(CompileTask(type, description, absoluteFilePath(filename), lineno), 1);
|
emit addTask(CompileTask(type, description, absoluteFilePath(filename), lineno), 1);
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser::handleLine(line, Utils::StdErrFormat);
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LdParser::doFlush()
|
void LdParser::doFlush()
|
||||||
|
@@ -39,7 +39,7 @@ class LdParser : public ProjectExplorer::IOutputParser
|
|||||||
public:
|
public:
|
||||||
LdParser();
|
LdParser();
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
void doFlush() override;
|
void doFlush() override;
|
||||||
|
|
||||||
QRegularExpression m_ranlib;
|
QRegularExpression m_ranlib;
|
||||||
|
@@ -63,21 +63,15 @@ LinuxIccParser::LinuxIccParser() :
|
|||||||
m_pchInfoLine.setPattern(QLatin1String("^\".*\": (creating|using) precompiled header file \".*\"\n$"));
|
m_pchInfoLine.setPattern(QLatin1String("^\".*\": (creating|using) precompiled header file \".*\"\n$"));
|
||||||
m_pchInfoLine.setMinimal(true);
|
m_pchInfoLine.setMinimal(true);
|
||||||
QTC_CHECK(m_pchInfoLine.isValid());
|
QTC_CHECK(m_pchInfoLine.isValid());
|
||||||
|
|
||||||
appendOutputParser(new Internal::LldParser);
|
|
||||||
appendOutputParser(new LdParser);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxIccParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status LinuxIccParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type != Utils::StdErrFormat) {
|
if (type != Utils::StdErrFormat)
|
||||||
IOutputParser::handleLine(line, type);
|
return Status::NotHandled;
|
||||||
return;
|
|
||||||
}
|
if (m_pchInfoLine.indexIn(line) != -1)
|
||||||
if (m_pchInfoLine.indexIn(line) != -1) {
|
return Status::Done; // totally ignore this line
|
||||||
// totally ignore this line
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_expectFirstLine && m_firstLine.indexIn(line) != -1) {
|
if (m_expectFirstLine && m_firstLine.indexIn(line) != -1) {
|
||||||
// Clear out old task
|
// Clear out old task
|
||||||
@@ -94,7 +88,9 @@ void LinuxIccParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
|
|
||||||
m_lines = 1;
|
m_lines = 1;
|
||||||
m_expectFirstLine = false;
|
m_expectFirstLine = false;
|
||||||
} else if (!m_expectFirstLine && m_caretLine.indexIn(line) != -1) {
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
if (!m_expectFirstLine && m_caretLine.indexIn(line) != -1) {
|
||||||
// Format the last line as code
|
// Format the last line as code
|
||||||
QTextLayout::FormatRange fr;
|
QTextLayout::FormatRange fr;
|
||||||
fr.start = m_temporary.description.lastIndexOf(QLatin1Char('\n')) + 1;
|
fr.start = m_temporary.description.lastIndexOf(QLatin1Char('\n')) + 1;
|
||||||
@@ -107,20 +103,25 @@ void LinuxIccParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
fr2.length = 1;
|
fr2.length = 1;
|
||||||
fr2.format.setFontWeight(QFont::Bold);
|
fr2.format.setFontWeight(QFont::Bold);
|
||||||
m_temporary.formats.append(fr2);
|
m_temporary.formats.append(fr2);
|
||||||
} else if (!m_expectFirstLine && line.trimmed().isEmpty()) { // last Line
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
if (!m_expectFirstLine && line.trimmed().isEmpty()) { // last Line
|
||||||
m_expectFirstLine = true;
|
m_expectFirstLine = true;
|
||||||
emit addTask(m_temporary, m_lines);
|
emit addTask(m_temporary, m_lines);
|
||||||
m_temporary = Task();
|
m_temporary = Task();
|
||||||
} else if (!m_expectFirstLine && m_continuationLines.indexIn(line) != -1) {
|
return Status::Done;
|
||||||
|
}
|
||||||
|
if (!m_expectFirstLine && m_continuationLines.indexIn(line) != -1) {
|
||||||
m_temporary.description.append(QLatin1Char('\n'));
|
m_temporary.description.append(QLatin1Char('\n'));
|
||||||
m_indent = 0;
|
m_indent = 0;
|
||||||
while (m_indent < line.length() && line.at(m_indent).isSpace())
|
while (m_indent < line.length() && line.at(m_indent).isSpace())
|
||||||
m_indent++;
|
m_indent++;
|
||||||
m_temporary.description.append(m_continuationLines.cap(1).trimmed());
|
m_temporary.description.append(m_continuationLines.cap(1).trimmed());
|
||||||
++m_lines;
|
++m_lines;
|
||||||
} else {
|
return Status::InProgress;
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
|
||||||
}
|
}
|
||||||
|
QTC_CHECK(m_temporary.isNull());
|
||||||
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Id LinuxIccParser::id()
|
Core::Id LinuxIccParser::id()
|
||||||
@@ -128,6 +129,11 @@ Core::Id LinuxIccParser::id()
|
|||||||
return Core::Id("ProjectExplorer.OutputParser.Icc");
|
return Core::Id("ProjectExplorer.OutputParser.Icc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<IOutputParser *> LinuxIccParser::iccParserSuite()
|
||||||
|
{
|
||||||
|
return {new LinuxIccParser, new Internal::LldParser, new LdParser};
|
||||||
|
}
|
||||||
|
|
||||||
void LinuxIccParser::doFlush()
|
void LinuxIccParser::doFlush()
|
||||||
{
|
{
|
||||||
if (m_temporary.isNull())
|
if (m_temporary.isNull())
|
||||||
@@ -238,7 +244,7 @@ void ProjectExplorerPlugin::testLinuxIccOutputParsers_data()
|
|||||||
void ProjectExplorerPlugin::testLinuxIccOutputParsers()
|
void ProjectExplorerPlugin::testLinuxIccOutputParsers()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new LinuxIccParser);
|
testbench.setLineParsers(LinuxIccParser::iccParserSuite());
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -41,8 +41,10 @@ public:
|
|||||||
|
|
||||||
static Core::Id id();
|
static Core::Id id();
|
||||||
|
|
||||||
|
static QList<IOutputParser *> iccParserSuite();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
void doFlush() override;
|
void doFlush() override;
|
||||||
|
|
||||||
QRegExp m_firstLine;
|
QRegExp m_firstLine;
|
||||||
|
@@ -35,16 +35,15 @@
|
|||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
void LldParser::handleLine(const QString &line, Utils::OutputFormat type)
|
IOutputParser::Status LldParser::doHandleLine(const QString &line, Utils::OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type != Utils::StdErrFormat) {
|
if (type != Utils::StdErrFormat)
|
||||||
IOutputParser::handleLine(line, type);
|
return Status::NotHandled;
|
||||||
return;
|
|
||||||
}
|
|
||||||
const QString trimmedLine = rightTrimmed(line);
|
const QString trimmedLine = rightTrimmed(line);
|
||||||
if (trimmedLine.contains("error:") && trimmedLine.contains("lld")) {
|
if (trimmedLine.contains("error:") && trimmedLine.contains("lld")) {
|
||||||
emit addTask(CompileTask(Task::Error, trimmedLine));
|
emit addTask(CompileTask(Task::Error, trimmedLine));
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
static const QStringList prefixes{">>> referenced by ", ">>> defined at ", ">>> "};
|
static const QStringList prefixes{">>> referenced by ", ">>> defined at ", ">>> "};
|
||||||
for (const QString &prefix : prefixes) {
|
for (const QString &prefix : prefixes) {
|
||||||
@@ -70,9 +69,9 @@ void LldParser::handleLine(const QString &line, Utils::OutputFormat type)
|
|||||||
trimmedLine.mid(filePathOffset, filePathLen).trimmed());
|
trimmedLine.mid(filePathOffset, filePathLen).trimmed());
|
||||||
emit addTask(CompileTask(Task::Unknown, trimmedLine.mid(4).trimmed(),
|
emit addTask(CompileTask(Task::Unknown, trimmedLine.mid(4).trimmed(),
|
||||||
absoluteFilePath(file), lineNo));
|
absoluteFilePath(file), lineNo));
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
IOutputParser::handleLine(line, Utils::StdErrFormat);
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -32,7 +32,7 @@ namespace Internal {
|
|||||||
|
|
||||||
class LldParser : public IOutputParser
|
class LldParser : public IOutputParser
|
||||||
{
|
{
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -103,9 +103,7 @@ bool MakeStep::init()
|
|||||||
setIgnoreReturnValue(isClean());
|
setIgnoreReturnValue(isClean());
|
||||||
|
|
||||||
setOutputParser(new GnuMakeParser());
|
setOutputParser(new GnuMakeParser());
|
||||||
IOutputParser *parser = target()->kit()->createOutputParser();
|
appendOutputParsers(target()->kit()->createOutputParsers());
|
||||||
if (parser)
|
|
||||||
appendOutputParser(parser);
|
|
||||||
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
||||||
|
|
||||||
return AbstractProcessStep::init();
|
return AbstractProcessStep::init();
|
||||||
|
@@ -100,79 +100,71 @@ MsvcParser::MsvcParser()
|
|||||||
QTC_CHECK(m_additionalInfoRegExp.isValid());
|
QTC_CHECK(m_additionalInfoRegExp.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MsvcParser::stdOutput(const QString &line)
|
|
||||||
{
|
|
||||||
QRegularExpressionMatch match = m_additionalInfoRegExp.match(line);
|
|
||||||
if (line.startsWith(" ") && !match.hasMatch()) {
|
|
||||||
if (m_lastTask.isNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_lastTask.description.append('\n');
|
|
||||||
m_lastTask.description.append(line.mid(8));
|
|
||||||
// trim trailing spaces:
|
|
||||||
int i = 0;
|
|
||||||
for (i = m_lastTask.description.length() - 1; i >= 0; --i) {
|
|
||||||
if (!m_lastTask.description.at(i).isSpace())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_lastTask.description.truncate(i + 1);
|
|
||||||
|
|
||||||
if (m_lastTask.formats.isEmpty()) {
|
|
||||||
QTextLayout::FormatRange fr;
|
|
||||||
fr.start = m_lastTask.description.indexOf('\n') + 1;
|
|
||||||
fr.length = m_lastTask.description.length() - fr.start;
|
|
||||||
fr.format.setFontItalic(true);
|
|
||||||
m_lastTask.formats.append(fr);
|
|
||||||
} else {
|
|
||||||
m_lastTask.formats[0].length = m_lastTask.description.length() - m_lastTask.formats[0].start;
|
|
||||||
}
|
|
||||||
++m_lines;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (processCompileLine(line))
|
|
||||||
return;
|
|
||||||
if (handleNmakeJomMessage(line, &m_lastTask)) {
|
|
||||||
m_lines = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (match.hasMatch()) {
|
|
||||||
QString description = match.captured(1)
|
|
||||||
+ 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 */);
|
|
||||||
m_lines = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
IOutputParser::handleLine(line, StdOutFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MsvcParser::stdError(const QString &line)
|
|
||||||
{
|
|
||||||
if (processCompileLine(line))
|
|
||||||
return;
|
|
||||||
// Jom outputs errors to stderr
|
|
||||||
if (handleNmakeJomMessage(line, &m_lastTask)) {
|
|
||||||
m_lines = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
Core::Id MsvcParser::id()
|
Core::Id MsvcParser::id()
|
||||||
{
|
{
|
||||||
return Core::Id("ProjectExplorer.OutputParser.Msvc");
|
return Core::Id("ProjectExplorer.OutputParser.Msvc");
|
||||||
}
|
}
|
||||||
|
|
||||||
void MsvcParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status MsvcParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type == OutputFormat::StdOutFormat)
|
if (type == OutputFormat::StdOutFormat) {
|
||||||
stdOutput(line);
|
QRegularExpressionMatch match = m_additionalInfoRegExp.match(line);
|
||||||
else
|
if (line.startsWith(" ") && !match.hasMatch()) {
|
||||||
stdError(line);
|
if (m_lastTask.isNull())
|
||||||
|
return Status::NotHandled;
|
||||||
|
|
||||||
|
m_lastTask.description.append('\n');
|
||||||
|
m_lastTask.description.append(line.mid(8));
|
||||||
|
// trim trailing spaces:
|
||||||
|
int i = 0;
|
||||||
|
for (i = m_lastTask.description.length() - 1; i >= 0; --i) {
|
||||||
|
if (!m_lastTask.description.at(i).isSpace())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_lastTask.description.truncate(i + 1);
|
||||||
|
|
||||||
|
if (m_lastTask.formats.isEmpty()) {
|
||||||
|
QTextLayout::FormatRange fr;
|
||||||
|
fr.start = m_lastTask.description.indexOf('\n') + 1;
|
||||||
|
fr.length = m_lastTask.description.length() - fr.start;
|
||||||
|
fr.format.setFontItalic(true);
|
||||||
|
m_lastTask.formats.append(fr);
|
||||||
|
} else {
|
||||||
|
m_lastTask.formats[0].length = m_lastTask.description.length()
|
||||||
|
- m_lastTask.formats[0].start;
|
||||||
|
}
|
||||||
|
++m_lines;
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processCompileLine(line))
|
||||||
|
return Status::InProgress;
|
||||||
|
if (handleNmakeJomMessage(line, &m_lastTask)) {
|
||||||
|
m_lines = 1;
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
if (match.hasMatch()) {
|
||||||
|
QString description = match.captured(1)
|
||||||
|
+ 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 */);
|
||||||
|
m_lines = 1;
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
return Status::NotHandled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processCompileLine(line))
|
||||||
|
return Status::InProgress;
|
||||||
|
// Jom outputs errors to stderr
|
||||||
|
if (handleNmakeJomMessage(line, &m_lastTask)) {
|
||||||
|
m_lines = 1;
|
||||||
|
return Status::InProgress;
|
||||||
|
}
|
||||||
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MsvcParser::processCompileLine(const QString &line)
|
bool MsvcParser::processCompileLine(const QString &line)
|
||||||
@@ -220,24 +212,6 @@ ClangClParser::ClangClParser()
|
|||||||
QTC_CHECK(m_compileRegExp.isValid());
|
QTC_CHECK(m_compileRegExp.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangClParser::handleLine(const QString &line, OutputFormat type)
|
|
||||||
{
|
|
||||||
if (type == StdOutFormat)
|
|
||||||
stdOutput(line);
|
|
||||||
else
|
|
||||||
stdError(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClangClParser::stdOutput(const QString &line)
|
|
||||||
{
|
|
||||||
if (handleNmakeJomMessage(line, &m_lastTask)) {
|
|
||||||
m_linkedLines = 1;
|
|
||||||
doFlush();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
IOutputParser::handleLine(line, StdOutFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for a code marker '~~~~ ^ ~~~~~~~~~~~~' underlining above code.
|
// Check for a code marker '~~~~ ^ ~~~~~~~~~~~~' underlining above code.
|
||||||
static inline bool isClangCodeMarker(const QString &trimmedLine)
|
static inline bool isClangCodeMarker(const QString &trimmedLine)
|
||||||
{
|
{
|
||||||
@@ -246,51 +220,59 @@ static inline bool isClangCodeMarker(const QString &trimmedLine)
|
|||||||
[] (QChar c) { return c != ' ' && c != '^' && c != '~'; });
|
[] (QChar c) { return c != ' ' && c != '^' && c != '~'; });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangClParser::stdError(const QString &lineIn)
|
IOutputParser::Status ClangClParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
const QString line = IOutputParser::rightTrimmed(lineIn); // Strip \r\n.
|
if (type == StdOutFormat) {
|
||||||
|
if (handleNmakeJomMessage(line, &m_lastTask)) {
|
||||||
|
m_linkedLines = 1;
|
||||||
|
doFlush();
|
||||||
|
return Status::Done;
|
||||||
|
}
|
||||||
|
return Status::NotHandled;
|
||||||
|
}
|
||||||
|
const QString lne = IOutputParser::rightTrimmed(line); // Strip \n.
|
||||||
|
|
||||||
if (handleNmakeJomMessage(line, &m_lastTask)) {
|
if (handleNmakeJomMessage(lne, &m_lastTask)) {
|
||||||
m_linkedLines = 1;
|
m_linkedLines = 1;
|
||||||
doFlush();
|
doFlush();
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish a sequence of warnings/errors: "2 warnings generated."
|
// Finish a sequence of warnings/errors: "2 warnings generated."
|
||||||
if (!line.isEmpty() && line.at(0).isDigit() && line.endsWith("generated.")) {
|
if (!lne.isEmpty() && lne.at(0).isDigit() && lne.endsWith("generated.")) {
|
||||||
doFlush();
|
doFlush();
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a new error message by a sequence of "In file included from " which is to be skipped.
|
// Start a new error message by a sequence of "In file included from " which is to be skipped.
|
||||||
if (line.startsWith("In file included from ")) {
|
if (lne.startsWith("In file included from ")) {
|
||||||
doFlush();
|
doFlush();
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRegularExpressionMatch match = m_compileRegExp.match(line);
|
QRegularExpressionMatch match = m_compileRegExp.match(lne);
|
||||||
if (match.hasMatch()) {
|
if (match.hasMatch()) {
|
||||||
doFlush();
|
doFlush();
|
||||||
const QPair<FilePath, int> position = parseFileName(match.captured(1));
|
const QPair<FilePath, int> position = parseFileName(match.captured(1));
|
||||||
m_lastTask = CompileTask(taskType(match.captured(2)), match.captured(3).trimmed(),
|
m_lastTask = CompileTask(taskType(match.captured(2)), match.captured(3).trimmed(),
|
||||||
absoluteFilePath(position.first), position.second);
|
absoluteFilePath(position.first), position.second);
|
||||||
m_linkedLines = 1;
|
m_linkedLines = 1;
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_lastTask.isNull()) {
|
if (!m_lastTask.isNull()) {
|
||||||
const QString trimmed = line.trimmed();
|
const QString trimmed = lne.trimmed();
|
||||||
if (isClangCodeMarker(trimmed)) {
|
if (isClangCodeMarker(trimmed)) {
|
||||||
doFlush();
|
doFlush();
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
m_lastTask.description.append('\n');
|
m_lastTask.description.append('\n');
|
||||||
m_lastTask.description.append(trimmed);
|
m_lastTask.description.append(trimmed);
|
||||||
++m_linkedLines;
|
++m_linkedLines;
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser::handleLine(lineIn, StdErrFormat);
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangClParser::doFlush()
|
void ClangClParser::doFlush()
|
||||||
@@ -566,7 +548,7 @@ void ProjectExplorerPlugin::testMsvcOutputParsers_data()
|
|||||||
void ProjectExplorerPlugin::testMsvcOutputParsers()
|
void ProjectExplorerPlugin::testMsvcOutputParsers()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new MsvcParser);
|
testbench.addLineParser(new MsvcParser);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
@@ -645,7 +627,7 @@ void ProjectExplorerPlugin::testClangClOutputParsers_data()
|
|||||||
void ProjectExplorerPlugin::testClangClOutputParsers()
|
void ProjectExplorerPlugin::testClangClOutputParsers()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new ClangClParser);
|
testbench.addLineParser(new ClangClParser);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -43,11 +43,9 @@ public:
|
|||||||
static Core::Id id();
|
static Core::Id id();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
void doFlush() override;
|
void doFlush() override;
|
||||||
|
|
||||||
void stdOutput(const QString &line);
|
|
||||||
void stdError(const QString &line);
|
|
||||||
bool processCompileLine(const QString &line);
|
bool processCompileLine(const QString &line);
|
||||||
|
|
||||||
QRegularExpression m_compileRegExp;
|
QRegularExpression m_compileRegExp;
|
||||||
@@ -65,12 +63,9 @@ public:
|
|||||||
ClangClParser();
|
ClangClParser();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
void doFlush() override;
|
void doFlush() override;
|
||||||
|
|
||||||
void stdOutput(const QString &line);
|
|
||||||
void stdError(const QString &line);
|
|
||||||
|
|
||||||
const QRegularExpression m_compileRegExp;
|
const QRegularExpression m_compileRegExp;
|
||||||
Task m_lastTask;
|
Task m_lastTask;
|
||||||
int m_linkedLines = 0;
|
int m_linkedLines = 0;
|
||||||
|
@@ -1169,9 +1169,9 @@ void MsvcToolChain::rescanForCompiler()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *MsvcToolChain::outputParser() const
|
QList<IOutputParser *> MsvcToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
return new MsvcParser;
|
return {new MsvcParser};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MsvcToolChain::setupVarsBat(const Abi &abi, const QString &varsBat, const QString &varsBatArg)
|
void MsvcToolChain::setupVarsBat(const Abi &abi, const QString &varsBat, const QString &varsBatArg)
|
||||||
@@ -1656,9 +1656,9 @@ QStringList ClangClToolChain::suggestedMkspecList() const
|
|||||||
return {mkspec, "win32-clang-msvc"};
|
return {mkspec, "win32-clang-msvc"};
|
||||||
}
|
}
|
||||||
|
|
||||||
IOutputParser *ClangClToolChain::outputParser() const
|
QList<IOutputParser *> ClangClToolChain::outputParsers() const
|
||||||
{
|
{
|
||||||
return new ClangClParser;
|
return {new ClangClParser};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QString llvmDirKey()
|
static inline QString llvmDirKey()
|
||||||
|
@@ -89,7 +89,7 @@ public:
|
|||||||
|
|
||||||
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
|
Utils::FilePath makeCommand(const Utils::Environment &environment) const override;
|
||||||
Utils::FilePath compilerCommand() const override;
|
Utils::FilePath compilerCommand() const override;
|
||||||
IOutputParser *outputParser() const override;
|
QList<IOutputParser *> outputParsers() const override;
|
||||||
|
|
||||||
QString varsBatArg() const { return m_varsBatArg; }
|
QString varsBatArg() const { return m_varsBatArg; }
|
||||||
QString varsBat() const { return m_vcvarsBat; }
|
QString varsBat() const { return m_vcvarsBat; }
|
||||||
@@ -174,7 +174,7 @@ public:
|
|||||||
QStringList suggestedMkspecList() const override;
|
QStringList suggestedMkspecList() const override;
|
||||||
void addToEnvironment(Utils::Environment &env) const override;
|
void addToEnvironment(Utils::Environment &env) const override;
|
||||||
Utils::FilePath compilerCommand() const override;
|
Utils::FilePath compilerCommand() const override;
|
||||||
IOutputParser *outputParser() const override;
|
QList<IOutputParser *> outputParsers() const override;
|
||||||
QVariantMap toMap() const override;
|
QVariantMap toMap() const override;
|
||||||
bool fromMap(const QVariantMap &data) override;
|
bool fromMap(const QVariantMap &data) override;
|
||||||
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override;
|
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override;
|
||||||
|
@@ -36,39 +36,30 @@ OsParser::OsParser()
|
|||||||
setObjectName(QLatin1String("OsParser"));
|
setObjectName(QLatin1String("OsParser"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OsParser::handleLine(const QString &line, Utils::OutputFormat type)
|
IOutputParser::Status OsParser::doHandleLine(const QString &line, Utils::OutputFormat type)
|
||||||
{
|
|
||||||
if (type == Utils::StdOutFormat)
|
|
||||||
stdOutput(line);
|
|
||||||
else
|
|
||||||
stdError(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OsParser::stdError(const QString &line)
|
|
||||||
{
|
{
|
||||||
|
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(
|
||||||
|
"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.")));
|
||||||
|
m_hasFatalError = true;
|
||||||
|
return Status::Done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Status::NotHandled;
|
||||||
|
}
|
||||||
if (Utils::HostOsInfo::isLinuxHost()) {
|
if (Utils::HostOsInfo::isLinuxHost()) {
|
||||||
const QString trimmed = line.trimmed();
|
const QString trimmed = line.trimmed();
|
||||||
if (trimmed.contains(QLatin1String(": error while loading shared libraries:")))
|
if (trimmed.contains(QLatin1String(": error while loading shared libraries:"))) {
|
||||||
emit addTask(CompileTask(Task::Error, trimmed));
|
emit addTask(CompileTask(Task::Error, trimmed));
|
||||||
}
|
return Status::Done;
|
||||||
IOutputParser::handleLine(line, Utils::StdErrFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OsParser::stdOutput(const QString &line)
|
|
||||||
{
|
|
||||||
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(
|
|
||||||
"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.")));
|
|
||||||
m_hasFatalError = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IOutputParser::handleLine(line, Utils::StdOutFormat);
|
return Status::NotHandled;
|
||||||
}
|
|
||||||
|
|
||||||
bool OsParser::hasFatalErrors() const
|
|
||||||
{
|
|
||||||
return m_hasFatalError || IOutputParser::hasFatalErrors();
|
|
||||||
}
|
}
|
||||||
|
@@ -41,11 +41,8 @@ public:
|
|||||||
OsParser();
|
OsParser();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
bool hasFatalErrors() const override;
|
bool hasFatalErrors() const override { return m_hasFatalError; }
|
||||||
|
|
||||||
void stdError(const QString &line);
|
|
||||||
void stdOutput(const QString &line);
|
|
||||||
|
|
||||||
bool m_hasFatalError = false;
|
bool m_hasFatalError = false;
|
||||||
};
|
};
|
||||||
|
@@ -53,12 +53,11 @@ void OutputParserTester::testParsing(const QString &lines,
|
|||||||
const QString &childStdErrLines,
|
const QString &childStdErrLines,
|
||||||
const QString &outputLines)
|
const QString &outputLines)
|
||||||
{
|
{
|
||||||
if (!m_terminator) {
|
const auto terminator = new TestTerminator(this);
|
||||||
m_terminator = new TestTerminator(this);
|
if (!lineParsers().isEmpty())
|
||||||
appendOutputParser(m_terminator);
|
terminator->setRedirectionDetector(lineParsers().last());
|
||||||
}
|
addLineParser(terminator);
|
||||||
reset();
|
reset();
|
||||||
Q_ASSERT(childParser());
|
|
||||||
|
|
||||||
if (inputChannel == STDOUT)
|
if (inputChannel == STDOUT)
|
||||||
handleStdout(lines + '\n');
|
handleStdout(lines + '\n');
|
||||||
@@ -68,7 +67,7 @@ void OutputParserTester::testParsing(const QString &lines,
|
|||||||
|
|
||||||
// delete the parser(s) to test
|
// delete the parser(s) to test
|
||||||
emit aboutToDeleteParser();
|
emit aboutToDeleteParser();
|
||||||
setChildParser(nullptr);
|
setLineParsers({});
|
||||||
|
|
||||||
QCOMPARE(m_receivedOutput, outputLines);
|
QCOMPARE(m_receivedOutput, outputLines);
|
||||||
QCOMPARE(m_receivedStdErrChildLine, childStdErrLines);
|
QCOMPARE(m_receivedStdErrChildLine, childStdErrLines);
|
||||||
@@ -103,13 +102,14 @@ TestTerminator::TestTerminator(OutputParserTester *t) :
|
|||||||
m_tester(t)
|
m_tester(t)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void TestTerminator::handleLine(const QString &line, Utils::OutputFormat type)
|
IOutputParser::Status TestTerminator::doHandleLine(const QString &line, Utils::OutputFormat type)
|
||||||
{
|
{
|
||||||
QVERIFY(line.endsWith('\n'));
|
QTC_CHECK(line.endsWith('\n'));
|
||||||
if (type == Utils::StdOutFormat)
|
if (type == Utils::StdOutFormat)
|
||||||
m_tester->m_receivedStdOutChildLine.append(line);
|
m_tester->m_receivedStdOutChildLine.append(line);
|
||||||
else
|
else
|
||||||
m_tester->m_receivedStdErrChildLine.append(line);
|
m_tester->m_receivedStdErrChildLine.append(line);
|
||||||
|
return Status::Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -69,7 +69,6 @@ private:
|
|||||||
QString m_receivedStdOutChildLine;
|
QString m_receivedStdOutChildLine;
|
||||||
Tasks m_receivedTasks;
|
Tasks m_receivedTasks;
|
||||||
QString m_receivedOutput;
|
QString m_receivedOutput;
|
||||||
TestTerminator *m_terminator = nullptr;
|
|
||||||
|
|
||||||
friend class TestTerminator;
|
friend class TestTerminator;
|
||||||
};
|
};
|
||||||
@@ -82,7 +81,7 @@ public:
|
|||||||
TestTerminator(OutputParserTester *t);
|
TestTerminator(OutputParserTester *t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
|
|
||||||
OutputParserTester *m_tester = nullptr;
|
OutputParserTester *m_tester = nullptr;
|
||||||
};
|
};
|
||||||
|
@@ -151,12 +151,14 @@ static void parse(QFutureInterface<void> &future, const QString &output,
|
|||||||
|
|
||||||
void ParseIssuesDialog::accept()
|
void ParseIssuesDialog::accept()
|
||||||
{
|
{
|
||||||
std::unique_ptr<IOutputParser> parser(d->kitChooser.currentKit()->createOutputParser());
|
const QList<IOutputParser *> lineParsers = d->kitChooser.currentKit()->createOutputParsers();
|
||||||
if (!parser) {
|
if (lineParsers.isEmpty()) {
|
||||||
QMessageBox::critical(this, tr("Cannot Parse"), tr("Cannot parse: The chosen kit does "
|
QMessageBox::critical(this, tr("Cannot Parse"), tr("Cannot parse: The chosen kit does "
|
||||||
"not provide an output parser."));
|
"not provide an output parser."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
std::unique_ptr<IOutputParser> parser(new IOutputParser);
|
||||||
|
parser->setLineParsers(lineParsers);
|
||||||
if (d->clearTasksCheckBox.isChecked())
|
if (d->clearTasksCheckBox.isChecked())
|
||||||
TaskHub::clearTasks();
|
TaskHub::clearTasks();
|
||||||
connect(parser.get(), &IOutputParser::addTask, [](const Task &t) { TaskHub::addTask(t); });
|
connect(parser.get(), &IOutputParser::addTask, [](const Task &t) { TaskHub::addTask(t); });
|
||||||
|
@@ -100,7 +100,7 @@ ProcessStep::ProcessStep(BuildStepList *bsl, Core::Id id)
|
|||||||
bool ProcessStep::init()
|
bool ProcessStep::init()
|
||||||
{
|
{
|
||||||
setupProcessParameters(processParameters());
|
setupProcessParameters(processParameters());
|
||||||
setOutputParser(target()->kit()->createOutputParser());
|
appendOutputParsers(target()->kit()->createOutputParsers());
|
||||||
return AbstractProcessStep::init();
|
return AbstractProcessStep::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -150,7 +150,7 @@ public:
|
|||||||
Core::Id language() const;
|
Core::Id language() const;
|
||||||
|
|
||||||
virtual Utils::FilePath compilerCommand() const = 0;
|
virtual Utils::FilePath compilerCommand() const = 0;
|
||||||
virtual IOutputParser *outputParser() const = 0;
|
virtual QList<IOutputParser *> outputParsers() const = 0;
|
||||||
|
|
||||||
virtual bool operator ==(const ToolChain &) const;
|
virtual bool operator ==(const ToolChain &) const;
|
||||||
|
|
||||||
|
@@ -324,7 +324,7 @@ public:
|
|||||||
void addToEnvironment(Environment &env) const override { Q_UNUSED(env) }
|
void addToEnvironment(Environment &env) const override { Q_UNUSED(env) }
|
||||||
FilePath makeCommand(const Environment &) const override { return FilePath::fromString("make"); }
|
FilePath makeCommand(const Environment &) const override { return FilePath::fromString("make"); }
|
||||||
FilePath compilerCommand() const override { return Utils::FilePath::fromString("/tmp/test/gcc"); }
|
FilePath compilerCommand() const override { return Utils::FilePath::fromString("/tmp/test/gcc"); }
|
||||||
IOutputParser *outputParser() const override { return nullptr; }
|
QList<IOutputParser *> outputParsers() const override { return {}; }
|
||||||
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override { return nullptr; }
|
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override { return nullptr; }
|
||||||
bool operator ==(const ToolChain &other) const override {
|
bool operator ==(const ToolChain &other) const override {
|
||||||
if (!ToolChain::operator==(other))
|
if (!ToolChain::operator==(other))
|
||||||
|
@@ -52,61 +52,47 @@ XcodebuildParser::XcodebuildParser()
|
|||||||
QTC_CHECK(m_buildRe.isValid());
|
QTC_CHECK(m_buildRe.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void XcodebuildParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status XcodebuildParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
|
||||||
if (type == StdOutFormat)
|
|
||||||
stdOutput(line);
|
|
||||||
else
|
|
||||||
stdError(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool XcodebuildParser::hasFatalErrors() const
|
|
||||||
{
|
|
||||||
return (m_fatalErrorCount > 0) || IOutputParser::hasFatalErrors();
|
|
||||||
}
|
|
||||||
|
|
||||||
void XcodebuildParser::stdOutput(const QString &line)
|
|
||||||
{
|
{
|
||||||
const QString lne = rightTrimmed(line);
|
const QString lne = rightTrimmed(line);
|
||||||
if (m_buildRe.indexIn(lne) > -1) {
|
if (type == StdOutFormat) {
|
||||||
m_xcodeBuildParserState = InXcodebuild;
|
if (m_buildRe.indexIn(lne) > -1) {
|
||||||
m_lastTarget = m_buildRe.cap(2);
|
m_xcodeBuildParserState = InXcodebuild;
|
||||||
m_lastProject = m_buildRe.cap(3);
|
m_lastTarget = m_buildRe.cap(2);
|
||||||
return;
|
m_lastProject = m_buildRe.cap(3);
|
||||||
}
|
return Status::Done;
|
||||||
if (m_xcodeBuildParserState == InXcodebuild || m_xcodeBuildParserState == UnknownXcodebuildState) {
|
|
||||||
if (m_successRe.indexIn(lne) > -1) {
|
|
||||||
m_xcodeBuildParserState = OutsideXcodebuild;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (lne.endsWith(QLatin1String(signatureChangeEndsWithPattern))) {
|
if (m_xcodeBuildParserState == InXcodebuild
|
||||||
CompileTask task(Task::Warning,
|
|| m_xcodeBuildParserState == UnknownXcodebuildState) {
|
||||||
tr("Replacing signature"),
|
if (m_successRe.indexIn(lne) > -1) {
|
||||||
absoluteFilePath(FilePath::fromString(
|
m_xcodeBuildParserState = OutsideXcodebuild;
|
||||||
lne.left(lne.size() - QLatin1String(signatureChangeEndsWithPattern).size()))));
|
return Status::Done;
|
||||||
emit addTask(task, 1);
|
}
|
||||||
return;
|
if (lne.endsWith(QLatin1String(signatureChangeEndsWithPattern))) {
|
||||||
|
CompileTask task(Task::Warning,
|
||||||
|
tr("Replacing signature"),
|
||||||
|
absoluteFilePath(FilePath::fromString(
|
||||||
|
lne.left(lne.size() - QLatin1String(signatureChangeEndsWithPattern).size()))));
|
||||||
|
emit addTask(task, 1);
|
||||||
|
return Status::Done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
IOutputParser::handleLine(line, StdErrFormat); // ??
|
return Status::NotHandled;
|
||||||
} else {
|
|
||||||
IOutputParser::handleLine(line, StdOutFormat);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void XcodebuildParser::stdError(const QString &line)
|
|
||||||
{
|
|
||||||
const QString lne = rightTrimmed(line);
|
|
||||||
if (m_failureRe.indexIn(lne) > -1) {
|
if (m_failureRe.indexIn(lne) > -1) {
|
||||||
++m_fatalErrorCount;
|
++m_fatalErrorCount;
|
||||||
m_xcodeBuildParserState = UnknownXcodebuildState;
|
m_xcodeBuildParserState = UnknownXcodebuildState;
|
||||||
// unfortunately the m_lastTarget, m_lastProject might not be in sync
|
// unfortunately the m_lastTarget, m_lastProject might not be in sync
|
||||||
emit addTask(CompileTask(Task::Error, tr("Xcodebuild failed.")));
|
emit addTask(CompileTask(Task::Error, tr("Xcodebuild failed.")));
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_xcodeBuildParserState == OutsideXcodebuild) { // also forward if UnknownXcodebuildState ?
|
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (m_xcodeBuildParserState == OutsideXcodebuild)
|
||||||
|
return Status::NotHandled;
|
||||||
|
return Status::Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XcodebuildParser::hasDetectedRedirection() const
|
||||||
|
{
|
||||||
|
return m_xcodeBuildParserState != OutsideXcodebuild;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
@@ -268,7 +254,7 @@ void ProjectExplorerPlugin::testXcodebuildParserParsing()
|
|||||||
connect(&testbench, &OutputParserTester::aboutToDeleteParser,
|
connect(&testbench, &OutputParserTester::aboutToDeleteParser,
|
||||||
tester, &XcodebuildParserTester::onAboutToDeleteParser);
|
tester, &XcodebuildParserTester::onAboutToDeleteParser);
|
||||||
|
|
||||||
testbench.appendOutputParser(childParser);
|
testbench.addLineParser(childParser);
|
||||||
QFETCH(ProjectExplorer::XcodebuildParser::XcodebuildStatus, initialStatus);
|
QFETCH(ProjectExplorer::XcodebuildParser::XcodebuildStatus, initialStatus);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
|
@@ -47,11 +47,9 @@ public:
|
|||||||
XcodebuildParser();
|
XcodebuildParser();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
bool hasFatalErrors() const override;
|
bool hasDetectedRedirection() const override;
|
||||||
|
bool hasFatalErrors() const override { return m_fatalErrorCount > 0; }
|
||||||
void stdOutput(const QString &line);
|
|
||||||
void stdError(const QString &line);
|
|
||||||
|
|
||||||
int m_fatalErrorCount = 0;
|
int m_fatalErrorCount = 0;
|
||||||
QRegExp m_failureRe;
|
QRegExp m_failureRe;
|
||||||
|
@@ -169,9 +169,9 @@ bool QbsBuildStep::init()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
delete m_parser;
|
delete m_parser;
|
||||||
m_parser = target()->kit()->createOutputParser();
|
m_parser = new IOutputParser;
|
||||||
if (m_parser)
|
m_parser->setLineParsers(target()->kit()->createOutputParsers());
|
||||||
connect(m_parser, &ProjectExplorer::IOutputParser::addTask, this, &QbsBuildStep::addTask);
|
connect(m_parser, &ProjectExplorer::IOutputParser::addTask, this, &QbsBuildStep::addTask);
|
||||||
|
|
||||||
m_changedFiles = bc->changedFiles();
|
m_changedFiles = bc->changedFiles();
|
||||||
m_activeFileTags = bc->activeFileTags();
|
m_activeFileTags = bc->activeFileTags();
|
||||||
|
@@ -166,14 +166,22 @@ bool QmakeMakeStep::init()
|
|||||||
|
|
||||||
setOutputParser(new ProjectExplorer::GnuMakeParser());
|
setOutputParser(new ProjectExplorer::GnuMakeParser());
|
||||||
ToolChain *tc = ToolChainKitAspect::cxxToolChain(target()->kit());
|
ToolChain *tc = ToolChainKitAspect::cxxToolChain(target()->kit());
|
||||||
if (tc && tc->targetAbi().os() == Abi::DarwinOS)
|
IOutputParser *xcodeBuildParser = nullptr;
|
||||||
appendOutputParser(new XcodebuildParser);
|
if (tc && tc->targetAbi().os() == Abi::DarwinOS) {
|
||||||
IOutputParser *parser = target()->kit()->createOutputParser();
|
xcodeBuildParser = new XcodebuildParser;
|
||||||
if (parser)
|
appendOutputParser(xcodeBuildParser);
|
||||||
appendOutputParser(parser);
|
}
|
||||||
|
QList<IOutputParser *> 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 (IOutputParser * const p : qAsConst(additionalParsers))
|
||||||
|
p->setRedirectionDetector(xcodeBuildParser);
|
||||||
|
}
|
||||||
|
appendOutputParsers(additionalParsers);
|
||||||
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
outputParser()->addSearchDir(pp->effectiveWorkingDirectory());
|
||||||
appendOutputParser(new QMakeParser); // make may cause qmake to be run, add last to make sure
|
|
||||||
// it has a low priority.
|
|
||||||
|
|
||||||
auto rootNode = dynamic_cast<QmakeProFileNode *>(project()->rootProjectNode());
|
auto rootNode = dynamic_cast<QmakeProFileNode *>(project()->rootProjectNode());
|
||||||
QTC_ASSERT(rootNode, return false);
|
QTC_ASSERT(rootNode, return false);
|
||||||
|
@@ -40,12 +40,10 @@ QMakeParser::QMakeParser() : m_error(QLatin1String("^(.+):(\\d+):\\s(.+)$"))
|
|||||||
m_error.setMinimal(true);
|
m_error.setMinimal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMakeParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status QMakeParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type != Utils::StdErrFormat) {
|
if (type != Utils::StdErrFormat)
|
||||||
IOutputParser::handleLine(line, type);
|
return Status::NotHandled;
|
||||||
return;
|
|
||||||
}
|
|
||||||
QString lne = rightTrimmed(line);
|
QString lne = rightTrimmed(line);
|
||||||
if (m_error.indexIn(lne) > -1) {
|
if (m_error.indexIn(lne) > -1) {
|
||||||
QString fileName = m_error.cap(1);
|
QString fileName = m_error.cap(1);
|
||||||
@@ -68,21 +66,21 @@ void QMakeParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
absoluteFilePath(FilePath::fromUserInput(fileName)),
|
absoluteFilePath(FilePath::fromUserInput(fileName)),
|
||||||
m_error.cap(2).toInt() /* line */),
|
m_error.cap(2).toInt() /* line */),
|
||||||
1);
|
1);
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
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);
|
||||||
emit addTask(BuildSystemTask(Task::Error, description), 1);
|
emit addTask(BuildSystemTask(Task::Error, description), 1);
|
||||||
return;
|
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);
|
||||||
emit addTask(BuildSystemTask(Task::Warning, description), 1);
|
emit addTask(BuildSystemTask(Task::Warning, description), 1);
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
IOutputParser::handleLine(line, StdErrFormat);
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // QmakeProjectManager
|
} // QmakeProjectManager
|
||||||
@@ -183,7 +181,7 @@ void QmakeProjectManagerPlugin::testQmakeOutputParsers_data()
|
|||||||
void QmakeProjectManagerPlugin::testQmakeOutputParsers()
|
void QmakeProjectManagerPlugin::testQmakeOutputParsers()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new QMakeParser);
|
testbench.addLineParser(new QMakeParser);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -41,7 +41,7 @@ public:
|
|||||||
QMakeParser();
|
QMakeParser();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
|
|
||||||
QRegExp m_error;
|
QRegExp m_error;
|
||||||
};
|
};
|
||||||
|
@@ -288,14 +288,11 @@ void QtKitAspect::addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environ
|
|||||||
version->addToEnvironment(k, env);
|
version->addToEnvironment(k, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProjectExplorer::IOutputParser *QtKitAspect::createOutputParser(const ProjectExplorer::Kit *k) const
|
QList<IOutputParser *> QtKitAspect::createOutputParsers(const Kit *k) const
|
||||||
{
|
{
|
||||||
if (qtVersion(k)) {
|
if (qtVersion(k))
|
||||||
const auto parser = new Internal::QtTestParser;
|
return {new Internal::QtTestParser, new QtParser};
|
||||||
parser->appendOutputParser(new QtParser);
|
return {};
|
||||||
return parser;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class QtMacroSubProvider
|
class QtMacroSubProvider
|
||||||
|
@@ -54,7 +54,7 @@ public:
|
|||||||
ItemList toUserOutput(const ProjectExplorer::Kit *k) const override;
|
ItemList toUserOutput(const ProjectExplorer::Kit *k) const override;
|
||||||
|
|
||||||
void addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const override;
|
void addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const override;
|
||||||
ProjectExplorer::IOutputParser *createOutputParser(const ProjectExplorer::Kit *k) const override;
|
QList<ProjectExplorer::IOutputParser *> createOutputParsers(const ProjectExplorer::Kit *k) const override;
|
||||||
void addToMacroExpander(ProjectExplorer::Kit *kit, Utils::MacroExpander *expander) const override;
|
void addToMacroExpander(ProjectExplorer::Kit *kit, Utils::MacroExpander *expander) const override;
|
||||||
|
|
||||||
static Core::Id id();
|
static Core::Id id();
|
||||||
|
@@ -43,12 +43,11 @@ QtParser::QtParser() :
|
|||||||
m_translationRegExp.setMinimal(true);
|
m_translationRegExp.setMinimal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtParser::handleLine(const QString &line, Utils::OutputFormat type)
|
IOutputParser::Status QtParser::doHandleLine(const QString &line, Utils::OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type != Utils::StdErrFormat) {
|
if (type != Utils::StdErrFormat)
|
||||||
IOutputParser::handleLine(line, type);
|
return Status::NotHandled;
|
||||||
return;
|
|
||||||
}
|
|
||||||
QString lne = rightTrimmed(line);
|
QString lne = rightTrimmed(line);
|
||||||
if (m_mocRegExp.indexIn(lne) > -1) {
|
if (m_mocRegExp.indexIn(lne) > -1) {
|
||||||
bool ok;
|
bool ok;
|
||||||
@@ -65,7 +64,7 @@ void QtParser::handleLine(const QString &line, Utils::OutputFormat type)
|
|||||||
absoluteFilePath(Utils::FilePath::fromUserInput(m_mocRegExp.cap(1))),
|
absoluteFilePath(Utils::FilePath::fromUserInput(m_mocRegExp.cap(1))),
|
||||||
lineno);
|
lineno);
|
||||||
emit addTask(task, 1);
|
emit addTask(task, 1);
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
if (m_translationRegExp.indexIn(lne) > -1) {
|
if (m_translationRegExp.indexIn(lne) > -1) {
|
||||||
Task::TaskType type = Task::Warning;
|
Task::TaskType type = Task::Warning;
|
||||||
@@ -74,9 +73,9 @@ void QtParser::handleLine(const QString &line, Utils::OutputFormat type)
|
|||||||
CompileTask task(type, m_translationRegExp.cap(2),
|
CompileTask task(type, m_translationRegExp.cap(2),
|
||||||
absoluteFilePath(Utils::FilePath::fromUserInput(m_translationRegExp.cap(3))));
|
absoluteFilePath(Utils::FilePath::fromUserInput(m_translationRegExp.cap(3))));
|
||||||
emit addTask(task, 1);
|
emit addTask(task, 1);
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
IOutputParser::handleLine(line, Utils::StdErrFormat);
|
return Status::NotHandled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unit tests:
|
// Unit tests:
|
||||||
@@ -179,7 +178,7 @@ void QtSupportPlugin::testQtOutputParser_data()
|
|||||||
void QtSupportPlugin::testQtOutputParser()
|
void QtSupportPlugin::testQtOutputParser()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new QtParser);
|
testbench.addLineParser(new QtParser);
|
||||||
QFETCH(QString, input);
|
QFETCH(QString, input);
|
||||||
QFETCH(OutputParserTester::Channel, inputChannel);
|
QFETCH(OutputParserTester::Channel, inputChannel);
|
||||||
QFETCH(Tasks, tasks);
|
QFETCH(Tasks, tasks);
|
||||||
|
@@ -42,7 +42,7 @@ public:
|
|||||||
QtParser();
|
QtParser();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
|
|
||||||
QRegExp m_mocRegExp;
|
QRegExp m_mocRegExp;
|
||||||
QRegExp m_translationRegExp;
|
QRegExp m_translationRegExp;
|
||||||
|
@@ -47,12 +47,11 @@ using namespace Utils;
|
|||||||
namespace QtSupport {
|
namespace QtSupport {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
void QtTestParser::handleLine(const QString &line, OutputFormat type)
|
IOutputParser::Status QtTestParser::doHandleLine(const QString &line, OutputFormat type)
|
||||||
{
|
{
|
||||||
if (type != StdOutFormat) {
|
if (type != StdOutFormat)
|
||||||
IOutputParser::handleLine(line, type);
|
return Status::NotHandled;
|
||||||
return;
|
|
||||||
}
|
|
||||||
const QString theLine = rightTrimmed(line);
|
const QString theLine = rightTrimmed(line);
|
||||||
static const QRegularExpression triggerPattern("^(?:XPASS|FAIL!) : .+$");
|
static const QRegularExpression triggerPattern("^(?:XPASS|FAIL!) : .+$");
|
||||||
QTC_CHECK(triggerPattern.isValid());
|
QTC_CHECK(triggerPattern.isValid());
|
||||||
@@ -60,12 +59,10 @@ void QtTestParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
emitCurrentTask();
|
emitCurrentTask();
|
||||||
m_currentTask = Task(Task::Error, theLine, FilePath(), -1,
|
m_currentTask = Task(Task::Error, theLine, FilePath(), -1,
|
||||||
Constants::TASK_CATEGORY_AUTOTEST);
|
Constants::TASK_CATEGORY_AUTOTEST);
|
||||||
return;
|
return Status::InProgress;
|
||||||
}
|
|
||||||
if (m_currentTask.isNull()) {
|
|
||||||
IOutputParser::handleLine(line, StdOutFormat);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (m_currentTask.isNull())
|
||||||
|
return Status::NotHandled;
|
||||||
static const QRegularExpression locationPattern(HostOsInfo::isWindowsHost()
|
static const QRegularExpression locationPattern(HostOsInfo::isWindowsHost()
|
||||||
? QString(QT_TEST_FAIL_WIN_REGEXP)
|
? QString(QT_TEST_FAIL_WIN_REGEXP)
|
||||||
: QString(QT_TEST_FAIL_UNIX_REGEXP));
|
: QString(QT_TEST_FAIL_UNIX_REGEXP));
|
||||||
@@ -76,9 +73,10 @@ void QtTestParser::handleLine(const QString &line, OutputFormat type)
|
|||||||
QDir::fromNativeSeparators(match.captured("file"))));
|
QDir::fromNativeSeparators(match.captured("file"))));
|
||||||
m_currentTask.line = match.captured("line").toInt();
|
m_currentTask.line = match.captured("line").toInt();
|
||||||
emitCurrentTask();
|
emitCurrentTask();
|
||||||
return;
|
return Status::Done;
|
||||||
}
|
}
|
||||||
m_currentTask.description.append('\n').append(theLine);
|
m_currentTask.description.append('\n').append(theLine);
|
||||||
|
return Status::InProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtTestParser::emitCurrentTask()
|
void QtTestParser::emitCurrentTask()
|
||||||
@@ -93,7 +91,7 @@ void QtTestParser::emitCurrentTask()
|
|||||||
void QtSupportPlugin::testQtTestOutputParser()
|
void QtSupportPlugin::testQtTestOutputParser()
|
||||||
{
|
{
|
||||||
OutputParserTester testbench;
|
OutputParserTester testbench;
|
||||||
testbench.appendOutputParser(new QtTestParser);
|
testbench.addLineParser(new QtTestParser);
|
||||||
const QString input = "random output\n"
|
const QString input = "random output\n"
|
||||||
"PASS : MyTest::someTest()\n"
|
"PASS : MyTest::someTest()\n"
|
||||||
"XPASS : MyTest::someTest()\n"
|
"XPASS : MyTest::someTest()\n"
|
||||||
|
@@ -35,7 +35,7 @@ class QtTestParser : public ProjectExplorer::IOutputParser
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
void handleLine(const QString &line, Utils::OutputFormat type) override;
|
Status doHandleLine(const QString &line, Utils::OutputFormat type) override;
|
||||||
void doFlush() override { emitCurrentTask(); }
|
void doFlush() override { emitCurrentTask(); }
|
||||||
|
|
||||||
void emitCurrentTask();
|
void emitCurrentTask();
|
||||||
|
@@ -54,19 +54,20 @@ CompilerOutputProcessor::~CompilerOutputProcessor()
|
|||||||
|
|
||||||
void CompilerOutputProcessor::start()
|
void CompilerOutputProcessor::start()
|
||||||
{
|
{
|
||||||
ProjectExplorer::OsParser parser;
|
ProjectExplorer::IOutputParser parser;
|
||||||
parser.appendOutputParser(new QmakeProjectManager::QMakeParser);
|
parser.addLineParser(new ProjectExplorer::OsParser);
|
||||||
parser.appendOutputParser(new ProjectExplorer::GnuMakeParser);
|
parser.addLineParser(new QmakeProjectManager::QMakeParser);
|
||||||
parser.appendOutputParser(new QtSupport::QtParser);
|
parser.addLineParser(new ProjectExplorer::GnuMakeParser);
|
||||||
|
parser.addLineParser(new QtSupport::QtParser);
|
||||||
switch (m_compilerType) {
|
switch (m_compilerType) {
|
||||||
case CompilerTypeGcc:
|
case CompilerTypeGcc:
|
||||||
parser.appendOutputParser(new ProjectExplorer::GccParser);
|
parser.addLineParsers(ProjectExplorer::GccParser::gccParserSuite());
|
||||||
break;
|
break;
|
||||||
case CompilerTypeClang:
|
case CompilerTypeClang:
|
||||||
parser.appendOutputParser(new ProjectExplorer::ClangParser);
|
parser.addLineParsers(ProjectExplorer::ClangParser::clangParserSuite());
|
||||||
break;
|
break;
|
||||||
case CompilerTypeMsvc:
|
case CompilerTypeMsvc:
|
||||||
parser.appendOutputParser(new ProjectExplorer::MsvcParser);
|
parser.addLineParser(new ProjectExplorer::MsvcParser);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user