forked from qt-creator/qt-creator
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
This commit is contained in:
@@ -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 <QTest>
|
||||
|
||||
# include "projectexplorer.h"
|
||||
|
||||
# include "projectexplorer/outputparser_test.h"
|
||||
|
||||
using namespace ProjectExplorer::Internal;
|
||||
|
||||
void ProjectExplorerPlugin::testMsvcOutputParsers_data()
|
||||
{
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
|
||||
QTest::addColumn<QString>("childStdOutLines");
|
||||
QTest::addColumn<QString>("childStdErrLines");
|
||||
QTest::addColumn<QList<ProjectExplorer::Task> >("tasks");
|
||||
QTest::addColumn<QString>("outputLines");
|
||||
|
||||
|
||||
QTest::newRow("pass-through stdout")
|
||||
<< QString::fromLatin1("Sometext") << OutputParserTester::STDOUT
|
||||
<< QString::fromLatin1("Sometext") << QString()
|
||||
<< QList<ProjectExplorer::Task>()
|
||||
<< QString();
|
||||
QTest::newRow("pass-through stderr")
|
||||
<< QString::fromLatin1("Sometext") << OutputParserTester::STDERR
|
||||
<< QString() << QString::fromLatin1("Sometext")
|
||||
<< QList<ProjectExplorer::Task>()
|
||||
<< QString();
|
||||
|
||||
QTest::newRow("labeled error")
|
||||
<< QString::fromLatin1("qmlstandalone\\main.cpp(54) : error C4716: 'findUnresolvedModule' : must return a value") << OutputParserTester::STDOUT
|
||||
<< QString() << QString()
|
||||
<< (QList<ProjectExplorer::Task>() << 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<ProjectExplorer::Task>() << 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<Task>, tasks);
|
||||
QFETCH(QString, childStdOutLines);
|
||||
QFETCH(QString, childStdErrLines);
|
||||
QFETCH(QString, outputLines);
|
||||
|
||||
testbench.testParsing(input, inputChannel,
|
||||
tasks, childStdOutLines, childStdErrLines,
|
||||
outputLines);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -205,6 +205,9 @@ private slots:
|
||||
void testGnuMakeParserParsing();
|
||||
void testGnuMakeParserTaskMangling_data();
|
||||
void testGnuMakeParserTaskMangling();
|
||||
|
||||
void testMsvcOutputParsers_data();
|
||||
void testMsvcOutputParsers();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
Reference in New Issue
Block a user