From ade1762af3b7a07a4a4cb9588fd96994842a7c69 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Thu, 12 Aug 2010 16:29:58 +0200 Subject: [PATCH] Improve MSVC parser * Add unit test * Do not depend on magic error codes to decide whether we see an error or a warning. Instead us "error" or "warning" in the message Rationale: The heuristic that was used to decide on error/warning is just wrong going by the msvc documentation as it does not take the kind of error into account. Task-number: QTCREATORBUG-2048 --- src/plugins/projectexplorer/msvcparser.cpp | 96 +++++++++++++++++-- src/plugins/projectexplorer/projectexplorer.h | 3 + 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/src/plugins/projectexplorer/msvcparser.cpp b/src/plugins/projectexplorer/msvcparser.cpp index 085ca858f82..d1fd00a2e68 100644 --- a/src/plugins/projectexplorer/msvcparser.cpp +++ b/src/plugins/projectexplorer/msvcparser.cpp @@ -34,7 +34,7 @@ using namespace ProjectExplorer; MsvcParser::MsvcParser() { - m_compileRegExp.setPattern("^([^\\(]+)\\((\\d+)\\)+\\s:[^:\\d]+(\\d+):(.*)$"); + m_compileRegExp.setPattern("^([^\\(]+)\\((\\d+)\\)+\\s:([^:\\d]+)\\s([A-Z]+(\\d+):.*)$"); m_compileRegExp.setMinimal(true); m_linkRegExp.setPattern("^([^\\(]+)\\s:[^:\\d]+(\\d+):(.*)$"); m_linkRegExp.setMinimal(true); @@ -43,15 +43,25 @@ MsvcParser::MsvcParser() void MsvcParser::stdOutput(const QString &line) { QString lne = line.trimmed(); - if (m_compileRegExp.indexIn(lne) > -1 && m_compileRegExp.numCaptures() == 4) { - emit addTask(Task(toType(m_compileRegExp.cap(3).toInt()) /* task type */, - m_compileRegExp.cap(4) /* description */, - m_compileRegExp.cap(1) /* filename */, - m_compileRegExp.cap(2).toInt() /* linenumber */, - Constants::TASK_CATEGORY_COMPILE)); + qDebug() << "LINE:" << lne; + if (m_compileRegExp.indexIn(lne) > -1 && m_compileRegExp.numCaptures() == 5) { + qDebug() << " MATCHED compileRegExp!"; + Task task(Task::Unknown, + m_compileRegExp.cap(4) /* description */, + m_compileRegExp.cap(1) /* filename */, + m_compileRegExp.cap(2).toInt() /* linenumber */, + Constants::TASK_CATEGORY_COMPILE); + if (m_compileRegExp.cap(3) == QLatin1String(" warning")) + task.type = Task::Warning; + else if (m_compileRegExp.cap(3) == QLatin1String(" error")) + task.type = Task::Error; + else + task.type = toType(m_compileRegExp.cap(5).toInt()); + addTask(task); return; } if (m_linkRegExp.indexIn(lne) > -1 && m_linkRegExp.numCaptures() == 3) { + qDebug() << " MATCHED linkRegExp!"; QString fileName = m_linkRegExp.cap(1); if (fileName.contains(QLatin1String("LINK"), Qt::CaseSensitive)) fileName.clear(); @@ -68,6 +78,8 @@ void MsvcParser::stdOutput(const QString &line) Task::TaskType MsvcParser::toType(int number) { + // This is unfortunately not true for all possible kinds of errors, but better + // than not having a fallback at all! if (number == 0) return Task::Unknown; else if (number > 4000 && number < 5000) @@ -75,3 +87,73 @@ Task::TaskType MsvcParser::toType(int number) else return Task::Error; } + +// Unit tests: + +#ifdef WITH_TESTS +# include + +# include "projectexplorer.h" + +# include "projectexplorer/outputparser_test.h" + +using namespace ProjectExplorer::Internal; + +void ProjectExplorerPlugin::testMsvcOutputParsers_data() +{ + QTest::addColumn("input"); + QTest::addColumn("inputChannel"); + QTest::addColumn("childStdOutLines"); + QTest::addColumn("childStdErrLines"); + QTest::addColumn >("tasks"); + QTest::addColumn("outputLines"); + + + QTest::newRow("pass-through stdout") + << QString::fromLatin1("Sometext") << OutputParserTester::STDOUT + << QString::fromLatin1("Sometext") << QString() + << QList() + << QString(); + QTest::newRow("pass-through stderr") + << QString::fromLatin1("Sometext") << OutputParserTester::STDERR + << QString() << QString::fromLatin1("Sometext") + << QList() + << QString(); + + QTest::newRow("labeled error") + << QString::fromLatin1("qmlstandalone\\main.cpp(54) : error C4716: 'findUnresolvedModule' : must return a value") << OutputParserTester::STDOUT + << QString() << QString() + << (QList() << Task(Task::Error, + QLatin1String("C4716: 'findUnresolvedModule' : must return a value"), + QLatin1String("qmlstandalone\\main.cpp"), 54, + QLatin1String(ProjectExplorer::Constants::TASK_CATEGORY_COMPILE))) + << QString(); + + QTest::newRow("labeled warning") + << QString::fromLatin1("x:\\src\\plugins\\projectexplorer\\msvcparser.cpp(69) : warning C4100: 'something' : unreferenced formal parameter") << OutputParserTester::STDOUT + << QString() << QString() + << (QList() << Task(Task::Warning, + QLatin1String("C4100: 'something' : unreferenced formal parameter"), + QLatin1String("x:\\src\\plugins\\projectexplorer\\msvcparser.cpp"), 69, + QLatin1String(ProjectExplorer::Constants::TASK_CATEGORY_COMPILE))) + << QString(); + +} + +void ProjectExplorerPlugin::testMsvcOutputParsers() +{ + OutputParserTester testbench; + testbench.appendOutputParser(new MsvcParser); + QFETCH(QString, input); + QFETCH(OutputParserTester::Channel, inputChannel); + QFETCH(QList, tasks); + QFETCH(QString, childStdOutLines); + QFETCH(QString, childStdErrLines); + QFETCH(QString, outputLines); + + testbench.testParsing(input, inputChannel, + tasks, childStdOutLines, childStdErrLines, + outputLines); +} +#endif + diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index 900a504f58e..6233616e684 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -205,6 +205,9 @@ private slots: void testGnuMakeParserParsing(); void testGnuMakeParserTaskMangling_data(); void testGnuMakeParserTaskMangling(); + + void testMsvcOutputParsers_data(); + void testMsvcOutputParsers(); #endif private: