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()
|
MsvcParser::MsvcParser()
|
||||||
{
|
{
|
||||||
m_compileRegExp.setPattern("^([^\\(]+)\\((\\d+)\\)+\\s:[^:\\d]+(\\d+):(.*)$");
|
m_compileRegExp.setPattern("^([^\\(]+)\\((\\d+)\\)+\\s:([^:\\d]+)\\s([A-Z]+(\\d+):.*)$");
|
||||||
m_compileRegExp.setMinimal(true);
|
m_compileRegExp.setMinimal(true);
|
||||||
m_linkRegExp.setPattern("^([^\\(]+)\\s:[^:\\d]+(\\d+):(.*)$");
|
m_linkRegExp.setPattern("^([^\\(]+)\\s:[^:\\d]+(\\d+):(.*)$");
|
||||||
m_linkRegExp.setMinimal(true);
|
m_linkRegExp.setMinimal(true);
|
||||||
@@ -43,15 +43,25 @@ MsvcParser::MsvcParser()
|
|||||||
void MsvcParser::stdOutput(const QString &line)
|
void MsvcParser::stdOutput(const QString &line)
|
||||||
{
|
{
|
||||||
QString lne = line.trimmed();
|
QString lne = line.trimmed();
|
||||||
if (m_compileRegExp.indexIn(lne) > -1 && m_compileRegExp.numCaptures() == 4) {
|
qDebug() << "LINE:" << lne;
|
||||||
emit addTask(Task(toType(m_compileRegExp.cap(3).toInt()) /* task type */,
|
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(4) /* description */,
|
||||||
m_compileRegExp.cap(1) /* filename */,
|
m_compileRegExp.cap(1) /* filename */,
|
||||||
m_compileRegExp.cap(2).toInt() /* linenumber */,
|
m_compileRegExp.cap(2).toInt() /* linenumber */,
|
||||||
Constants::TASK_CATEGORY_COMPILE));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (m_linkRegExp.indexIn(lne) > -1 && m_linkRegExp.numCaptures() == 3) {
|
if (m_linkRegExp.indexIn(lne) > -1 && m_linkRegExp.numCaptures() == 3) {
|
||||||
|
qDebug() << " MATCHED linkRegExp!";
|
||||||
QString fileName = m_linkRegExp.cap(1);
|
QString fileName = m_linkRegExp.cap(1);
|
||||||
if (fileName.contains(QLatin1String("LINK"), Qt::CaseSensitive))
|
if (fileName.contains(QLatin1String("LINK"), Qt::CaseSensitive))
|
||||||
fileName.clear();
|
fileName.clear();
|
||||||
@@ -68,6 +78,8 @@ void MsvcParser::stdOutput(const QString &line)
|
|||||||
|
|
||||||
Task::TaskType MsvcParser::toType(int number)
|
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)
|
if (number == 0)
|
||||||
return Task::Unknown;
|
return Task::Unknown;
|
||||||
else if (number > 4000 && number < 5000)
|
else if (number > 4000 && number < 5000)
|
||||||
@@ -75,3 +87,73 @@ Task::TaskType MsvcParser::toType(int number)
|
|||||||
else
|
else
|
||||||
return Task::Error;
|
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 testGnuMakeParserParsing();
|
||||||
void testGnuMakeParserTaskMangling_data();
|
void testGnuMakeParserTaskMangling_data();
|
||||||
void testGnuMakeParserTaskMangling();
|
void testGnuMakeParserTaskMangling();
|
||||||
|
|
||||||
|
void testMsvcOutputParsers_data();
|
||||||
|
void testMsvcOutputParsers();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user