CustomParser: Add warning parser and output channel filter

There have been several requests on the mailing list or the
bug tracker to support parsing warnings for alien compilers
(sometimes slightly modified GCC).

Instead of natively supporting every compiler, users of less
frequently used compilers should use the custom parser to
parse errors and warnings.

The output channel filter for error and warning parser allows
to scan standard output, standard error or both channels.

Also added tests for twisted capture positions.

Task-number: QTCREATORBUG-11003
Change-Id: I5a5bd6f88cf21cde1c74962225067d4543693678
Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
This commit is contained in:
Andre Hartmann
2015-12-16 21:04:45 +01:00
committed by André Hartmann
parent 5a7d3e78db
commit 61a87799a3
7 changed files with 984 additions and 363 deletions

View File

@@ -150,6 +150,10 @@
\image qtcreator-custom-parser.png
The custom error parser enables you to capture errors and warnings separately.
You can configure the error parser in the \uicontrol Error tab and the warning
parser in the \uicontrol Warning tab:
\list 1
\li In the \uicontrol {Error message capture pattern} field, specify
@@ -163,6 +167,10 @@
expression groups to \uicontrol {File name}, \uicontrol {Line number},
and \uicontrol Message.
\li In the \uicontrol {Capture Output Channels} field, specify whether
messages from standard output, standard error, or both channels
should be captured.
\li In the \uicontrol {Test} group, you can test how the message that
you enter in the \uicontrol {Error message} field is matched when
using the current settings.

View File

@@ -40,20 +40,83 @@
using namespace Utils;
using namespace ProjectExplorer;
CustomParserSettings::CustomParserSettings() :
fileNameCap(1),
lineNumberCap(2),
messageCap(3)
{ }
bool CustomParserExpression::operator ==(const CustomParserExpression &other) const
{
return pattern() == other.pattern() && fileNameCap() == other.fileNameCap()
&& lineNumberCap() == other.lineNumberCap() && messageCap() == other.messageCap()
&& channel() == other.channel() && example() == other.example();
}
QString CustomParserExpression::pattern() const
{
return m_regExp.pattern();
}
void ProjectExplorer::CustomParserExpression::setPattern(const QString &pattern)
{
m_regExp.setPattern(pattern);
QTC_CHECK(m_regExp.isValid());
}
CustomParserExpression::CustomParserChannel CustomParserExpression::channel() const
{
return m_channel;
}
void CustomParserExpression::setChannel(CustomParserExpression::CustomParserChannel channel)
{
QTC_ASSERT(channel > ParseNoChannel && channel <= ParseBothChannels,
channel = ParseBothChannels);
m_channel = channel;
}
QString CustomParserExpression::example() const
{
return m_example;
}
void CustomParserExpression::setExample(const QString &example)
{
m_example = example;
}
int CustomParserExpression::messageCap() const
{
return m_messageCap;
}
void CustomParserExpression::setMessageCap(int messageCap)
{
m_messageCap = messageCap;
}
int CustomParserExpression::lineNumberCap() const
{
return m_lineNumberCap;
}
void CustomParserExpression::setLineNumberCap(int lineNumberCap)
{
m_lineNumberCap = lineNumberCap;
}
int CustomParserExpression::fileNameCap() const
{
return m_fileNameCap;
}
void CustomParserExpression::setFileNameCap(int fileNameCap)
{
m_fileNameCap = fileNameCap;
}
bool CustomParserSettings::operator ==(const CustomParserSettings &other) const
{
return errorPattern == other.errorPattern && fileNameCap == other.fileNameCap
&& lineNumberCap == other.lineNumberCap && messageCap == other.messageCap;
return error == other.error && warning == other.warning;
}
CustomParser::CustomParser(const CustomParserSettings &settings) :
m_parserChannels(ParseBothChannels)
CustomParser::CustomParser(const CustomParserSettings &settings)
{
setObjectName(QLatin1String("CustomParser"));
@@ -64,91 +127,60 @@ CustomParser::~CustomParser()
{
}
void CustomParser::setErrorPattern(const QString &errorPattern)
{
m_errorRegExp.setPattern(errorPattern);
QTC_CHECK(m_errorRegExp.isValid());
}
QString CustomParser::errorPattern() const
{
return m_errorRegExp.pattern();
}
int CustomParser::lineNumberCap() const
{
return m_lineNumberCap;
}
void CustomParser::setLineNumberCap(int lineNumberCap)
{
m_lineNumberCap = lineNumberCap;
}
int CustomParser::fileNameCap() const
{
return m_fileNameCap;
}
void CustomParser::setFileNameCap(int fileNameCap)
{
m_fileNameCap = fileNameCap;
}
int CustomParser::messageCap() const
{
return m_messageCap;
}
void CustomParser::setMessageCap(int messageCap)
{
m_messageCap = messageCap;
}
void CustomParser::stdError(const QString &line)
{
if (m_parserChannels & ParseStdErrChannel)
if (parseLine(line))
return;
if (parseLine(line, CustomParserExpression::ParseStdErrChannel))
return;
IOutputParser::stdError(line);
}
void CustomParser::stdOutput(const QString &line)
{
if (m_parserChannels & ParseStdOutChannel)
if (parseLine(line))
return;
if (parseLine(line, CustomParserExpression::ParseStdOutChannel))
return;
IOutputParser::stdOutput(line);
}
void CustomParser::setSettings(const CustomParserSettings &settings)
{
setErrorPattern(settings.errorPattern);
setFileNameCap(settings.fileNameCap);
setLineNumberCap(settings.lineNumberCap);
setMessageCap(settings.messageCap);
m_error = settings.error;
m_warning = settings.warning;
}
bool CustomParser::parseLine(const QString &rawLine)
bool CustomParser::hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
const CustomParserExpression &expression, Task::TaskType taskType)
{
if (m_errorRegExp.pattern().isEmpty())
if (!(channel & expression.channel()))
return false;
const QRegularExpressionMatch match = m_errorRegExp.match(rawLine.trimmed());
if (expression.pattern().isEmpty())
return false;
const QRegularExpressionMatch match = expression.match(line);
if (!match.hasMatch())
return false;
const FileName fileName = FileName::fromUserInput(match.captured(m_fileNameCap));
const int lineNumber = match.captured(m_lineNumberCap).toInt();
const QString message = match.captured(m_messageCap);
const FileName fileName = FileName::fromUserInput(match.captured(expression.fileNameCap()));
const int lineNumber = match.captured(expression.lineNumberCap()).toInt();
const QString message = match.captured(expression.messageCap());
Task task = Task(Task::Error, message, fileName, lineNumber, Constants::TASK_CATEGORY_COMPILE);
const Task task = Task(taskType, message, fileName, lineNumber, Constants::TASK_CATEGORY_COMPILE);
emit addTask(task, 1);
return true;
}
bool CustomParser::parseLine(const QString &rawLine, CustomParserExpression::CustomParserChannel channel)
{
const QString line = rawLine.trimmed();
if (hasMatch(line, channel, m_error, Task::Error))
return true;
return hasMatch(line, channel, m_warning, Task::Warning);
}
// Unit tests:
#ifdef WITH_TESTS
@@ -162,10 +194,16 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
{
QTest::addColumn<QString>("input");
QTest::addColumn<OutputParserTester::Channel>("inputChannel");
QTest::addColumn<QString>("pattern");
QTest::addColumn<int>("fileNameCap");
QTest::addColumn<int>("lineNumberCap");
QTest::addColumn<int>("messageCap");
QTest::addColumn<CustomParserExpression::CustomParserChannel>("filterErrorChannel");
QTest::addColumn<CustomParserExpression::CustomParserChannel>("filterWarningChannel");
QTest::addColumn<QString>("errorPattern");
QTest::addColumn<int>("errorFileNameCap");
QTest::addColumn<int>("errorLineNumberCap");
QTest::addColumn<int>("errorMessageCap");
QTest::addColumn<QString>("warningPattern");
QTest::addColumn<int>("warningFileNameCap");
QTest::addColumn<int>("warningLineNumberCap");
QTest::addColumn<int>("warningMessageCap");
QTest::addColumn<QString>("childStdOutLines");
QTest::addColumn<QString>("childStdErrLines");
QTest::addColumn<QList<Task> >("tasks");
@@ -175,11 +213,12 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
const QString simplePattern = QLatin1String("^([a-z]+\\.[a-z]+):(\\d+): error: ([^\\s].+)$");
const FileName fileName = FileName::fromUserInput(QLatin1String("main.c"));
QTest::newRow("empty pattern")
QTest::newRow("empty patterns")
<< QString::fromLatin1("Sometext")
<< OutputParserTester::STDOUT
<< QString::fromLatin1("")
<< 1 << 2 << 3
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< QString() << 1 << 2 << 3
<< QString() << 1 << 2 << 3
<< QString::fromLatin1("Sometext\n") << QString()
<< QList<Task>()
<< QString();
@@ -187,8 +226,9 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
QTest::newRow("pass-through stdout")
<< QString::fromLatin1("Sometext")
<< OutputParserTester::STDOUT
<< simplePattern
<< 1 << 2 << 3
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< simplePattern << 1 << 2 << 3
<< QString() << 1 << 2 << 3
<< QString::fromLatin1("Sometext\n") << QString()
<< QList<Task>()
<< QString();
@@ -196,35 +236,59 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
QTest::newRow("pass-through stderr")
<< QString::fromLatin1("Sometext")
<< OutputParserTester::STDERR
<< simplePattern
<< 1 << 2 << 3
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< simplePattern << 1 << 2 << 3
<< QString() << 1 << 2 << 3
<< QString() << QString::fromLatin1("Sometext\n")
<< QList<Task>()
<< QString();
const QString simpleError = QLatin1String("main.c:9: error: `sfasdf' undeclared (first use this function)");
const QString simpleErrorPassThrough = simpleError + QLatin1Char('\n');
const QString message = QLatin1String("`sfasdf' undeclared (first use this function)");
QTest::newRow("simple error")
<< simpleError
<< OutputParserTester::STDERR
<< simplePattern
<< 1 << 2 << 3
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< simplePattern << 1 << 2 << 3
<< QString() << 0 << 0 << 0
<< QString() << QString()
<< (QList<Task>()
<< Task(Task::Error, message, fileName, 9, categoryCompile)
)
<< QString();
const QString simpleError2 = QLatin1String("Error: main.c:19: `sfasdf' undeclared (first use this function)");
const QString simplePattern2 = QLatin1String("^Error: ([a-z]+\\.[a-z]+):(\\d+): ([^\\s].+)$");
QTest::newRow("simple error on wrong channel")
<< simpleError
<< OutputParserTester::STDOUT
<< CustomParserExpression::ParseStdErrChannel << CustomParserExpression::ParseBothChannels
<< simplePattern << 1 << 2 << 3
<< QString() << 0 << 0 << 0
<< simpleErrorPassThrough << QString()
<< QList<Task>()
<< QString();
QTest::newRow("simple error on other wrong channel")
<< simpleError
<< OutputParserTester::STDERR
<< CustomParserExpression::ParseStdOutChannel << CustomParserExpression::ParseBothChannels
<< simplePattern << 1 << 2 << 3
<< QString() << 0 << 0 << 0
<< QString() << simpleErrorPassThrough
<< QList<Task>()
<< QString();
const QString simpleError2 = QLatin1String("Error: Line 19 in main.c: `sfasdf' undeclared (first use this function)");
const QString simplePattern2 = QLatin1String("^Error: Line (\\d+) in ([a-z]+\\.[a-z]+): ([^\\s].+)$");
const int lineNumber2 = 19;
QTest::newRow("another simple error on stderr")
<< simpleError2
<< OutputParserTester::STDERR
<< simplePattern2
<< 1 << 2 << 3
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< simplePattern2 << 2 << 1 << 3
<< QString() << 1 << 2 << 3
<< QString() << QString()
<< (QList<Task>()
<< Task(Task::Error, message, fileName, lineNumber2, categoryCompile)
@@ -234,14 +298,91 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
QTest::newRow("another simple error on stdout")
<< simpleError2
<< OutputParserTester::STDOUT
<< simplePattern2
<< 1 << 2 << 3
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< simplePattern2 << 2 << 1 << 3
<< QString() << 1 << 2 << 3
<< QString() << QString()
<< (QList<Task>()
<< Task(Task::Error, message, fileName, lineNumber2, categoryCompile)
)
<< QString();
const QString simpleWarningPattern = QLatin1String("^([a-z]+\\.[a-z]+):(\\d+): warning: ([^\\s].+)$");
const QString simpleWarning = QLatin1String("main.c:1234: warning: `helloWorld' declared but not used");
const QString warningMessage = QLatin1String("`helloWorld' declared but not used");
QTest::newRow("simple warning")
<< simpleWarning
<< OutputParserTester::STDERR
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< QString() << 1 << 2 << 3
<< simpleWarningPattern << 1 << 2 << 3
<< QString() << QString()
<< (QList<Task>()
<< Task(Task::Warning, warningMessage, fileName, 1234, categoryCompile)
)
<< QString();
const QString simpleWarning2 = QLatin1String("Warning: `helloWorld' declared but not used (main.c:19)");
const QString simpleWarningPassThrough2 = simpleWarning2 + QLatin1Char('\n');
const QString simpleWarningPattern2 = QLatin1String("^Warning: (.*) \\(([a-z]+\\.[a-z]+):(\\d+)\\)$");
QTest::newRow("another simple warning on stdout")
<< simpleWarning2
<< OutputParserTester::STDOUT
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseStdOutChannel
<< simplePattern2 << 1 << 2 << 3
<< simpleWarningPattern2 << 2 << 3 << 1
<< QString() << QString()
<< (QList<Task>()
<< Task(Task::Warning, warningMessage, fileName, lineNumber2, categoryCompile)
)
<< QString();
QTest::newRow("warning on wrong channel")
<< simpleWarning2
<< OutputParserTester::STDOUT
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseStdErrChannel
<< QString() << 1 << 2 << 3
<< simpleWarningPattern2 << 2 << 3 << 1
<< simpleWarningPassThrough2 << QString()
<< QList<Task>()
<< QString();
QTest::newRow("warning on other wrong channel")
<< simpleWarning2
<< OutputParserTester::STDERR
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseStdOutChannel
<< QString() << 1 << 2 << 3
<< simpleWarningPattern2 << 2 << 3 << 1
<< QString() << simpleWarningPassThrough2
<< QList<Task>()
<< QString();
QTest::newRow("error and *warning*")
<< simpleWarning
<< OutputParserTester::STDERR
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< simplePattern << 1 << 2 << 3
<< simpleWarningPattern << 1 << 2 << 3
<< QString() << QString()
<< (QList<Task>()
<< Task(Task::Warning, warningMessage, fileName, 1234, categoryCompile)
)
<< QString();
QTest::newRow("*error* when equal pattern")
<< simpleError
<< OutputParserTester::STDERR
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< simplePattern << 1 << 2 << 3
<< simplePattern << 1 << 2 << 3
<< QString() << QString()
<< (QList<Task>()
<< Task(Task::Error, message, fileName, 9, categoryCompile)
)
<< QString();
const QString unitTestError = QLatin1String("../LedDriver/LedDriverTest.c:63: FAIL: Expected 0x0080 Was 0xffff");
const FileName unitTestFileName = FileName::fromUserInput(QLatin1String("../LedDriver/LedDriverTest.c"));
const QString unitTestMessage = QLatin1String("Expected 0x0080 Was 0xffff");
@@ -251,8 +392,9 @@ void ProjectExplorerPlugin::testCustomOutputParsers_data()
QTest::newRow("unit test error")
<< unitTestError
<< OutputParserTester::STDOUT
<< unitTestPattern
<< 1 << 2 << 3
<< CustomParserExpression::ParseBothChannels << CustomParserExpression::ParseBothChannels
<< unitTestPattern << 1 << 2 << 3
<< QString() << 1 << 2 << 3
<< QString() << QString()
<< (QList<Task>()
<< Task(Task::Error, unitTestMessage, unitTestFileName, unitTestLineNumber, categoryCompile)
@@ -264,20 +406,35 @@ void ProjectExplorerPlugin::testCustomOutputParsers()
{
QFETCH(QString, input);
QFETCH(OutputParserTester::Channel, inputChannel);
QFETCH(QString, pattern);
QFETCH(int, fileNameCap);
QFETCH(int, lineNumberCap);
QFETCH(int, messageCap);
QFETCH(CustomParserExpression::CustomParserChannel, filterErrorChannel);
QFETCH(CustomParserExpression::CustomParserChannel, filterWarningChannel);
QFETCH(QString, errorPattern);
QFETCH(int, errorFileNameCap);
QFETCH(int, errorLineNumberCap);
QFETCH(int, errorMessageCap);
QFETCH(QString, warningPattern);
QFETCH(int, warningFileNameCap);
QFETCH(int, warningLineNumberCap);
QFETCH(int, warningMessageCap);
QFETCH(QString, childStdOutLines);
QFETCH(QString, childStdErrLines);
QFETCH(QList<Task>, tasks);
QFETCH(QString, outputLines);
CustomParserSettings settings;
settings.error.setPattern(errorPattern);
settings.error.setFileNameCap(errorFileNameCap);
settings.error.setLineNumberCap(errorLineNumberCap);
settings.error.setMessageCap(errorMessageCap);
settings.error.setChannel(filterErrorChannel);
settings.warning.setPattern(warningPattern);
settings.warning.setFileNameCap(warningFileNameCap);
settings.warning.setLineNumberCap(warningLineNumberCap);
settings.warning.setMessageCap(warningMessageCap);
settings.warning.setChannel(filterWarningChannel);
CustomParser *parser = new CustomParser;
parser->setErrorPattern(pattern);
parser->setFileNameCap(fileNameCap);
parser->setLineNumberCap(lineNumberCap);
parser->setMessageCap(messageCap);
parser->setSettings(settings);
OutputParserTester testbench;
testbench.appendOutputParser(parser);

View File

@@ -39,39 +39,28 @@
namespace ProjectExplorer {
class CustomParserSettings
class CustomParserExpression
{
public:
CustomParserSettings();
bool operator ==(const CustomParserSettings &other) const;
bool operator !=(const CustomParserSettings &other) const { return !operator==(other); }
QString errorPattern;
int fileNameCap;
int lineNumberCap;
int messageCap;
};
class CustomParser : public ProjectExplorer::IOutputParser
{
public:
enum CustomParserChannels {
enum CustomParserChannel {
ParseNoChannel = 0,
ParseStdErrChannel = 1,
ParseStdOutChannel = 2,
ParseBothChannels = 3
};
CustomParser(const CustomParserSettings &settings = CustomParserSettings());
~CustomParser();
void stdError(const QString &line);
void stdOutput(const QString &line);
bool operator ==(const CustomParserExpression &other) const;
void setSettings(const CustomParserSettings &settings);
QString pattern() const;
void setPattern(const QString &pattern);
QRegularExpressionMatch match(const QString &line) const { return m_regExp.match(line); }
CustomParserExpression::CustomParserChannel channel() const;
void setChannel(CustomParserExpression::CustomParserChannel channel);
QString example() const;
void setExample(const QString &example);
void setErrorPattern(const QString &errorPattern);
QString errorPattern() const;
int fileNameCap() const;
void setFileNameCap(int fileNameCap);
int lineNumberCap() const;
@@ -80,16 +69,45 @@ public:
void setMessageCap(int messageCap);
private:
bool parseLine(const QString &rawLine);
QRegularExpression m_regExp;
CustomParserExpression::CustomParserChannel m_channel = ParseBothChannels;
QString m_example;
int m_fileNameCap = 1;
int m_lineNumberCap = 2;
int m_messageCap = 3;
};
QRegularExpression m_errorRegExp;
int m_fileNameCap;
int m_lineNumberCap;
int m_messageCap;
class CustomParserSettings
{
public:
bool operator ==(const CustomParserSettings &other) const;
bool operator !=(const CustomParserSettings &other) const { return !operator==(other); }
CustomParserChannels m_parserChannels;
CustomParserExpression error;
CustomParserExpression warning;
};
class CustomParser : public ProjectExplorer::IOutputParser
{
public:
CustomParser(const CustomParserSettings &settings = CustomParserSettings());
~CustomParser();
void stdError(const QString &line);
void stdOutput(const QString &line);
void setSettings(const CustomParserSettings &settings);
private:
bool hasMatch(const QString &line, CustomParserExpression::CustomParserChannel channel,
const CustomParserExpression &expression, Task::TaskType taskType);
bool parseLine(const QString &rawLine, CustomParserExpression::CustomParserChannel channel);
CustomParserExpression m_error;
CustomParserExpression m_warning;
};
} // namespace ProjectExplorer
Q_DECLARE_METATYPE(ProjectExplorer::CustomParserExpression::CustomParserChannel);
#endif // CUSTOMPARSER_H

View File

@@ -31,6 +31,7 @@
#include "customparserconfigdialog.h"
#include "ui_customparserconfigdialog.h"
#include <QLineEdit>
#include <QPushButton>
#include <QRegularExpression>
@@ -44,10 +45,15 @@ CustomParserConfigDialog::CustomParserConfigDialog(QDialog *parent) :
ui->setupUi(this);
connect(ui->errorPattern, SIGNAL(textChanged(QString)), this, SLOT(changed()));
connect(ui->errorMessage, SIGNAL(textChanged(QString)), this, SLOT(changed()));
connect(ui->fileNameCap, SIGNAL(valueChanged(int)), this, SLOT(changed()));
connect(ui->lineNumberCap, SIGNAL(valueChanged(int)), this, SLOT(changed()));
connect(ui->messageCap, SIGNAL(valueChanged(int)), this, SLOT(changed()));
connect(ui->errorOutputMessage, SIGNAL(textChanged(QString)), this, SLOT(changed()));
connect(ui->errorFileNameCap, SIGNAL(valueChanged(int)), this, SLOT(changed()));
connect(ui->errorLineNumberCap, SIGNAL(valueChanged(int)), this, SLOT(changed()));
connect(ui->errorMessageCap, SIGNAL(valueChanged(int)), this, SLOT(changed()));
connect(ui->warningPattern, SIGNAL(textChanged(QString)), this, SLOT(changed()));
connect(ui->warningOutputMessage, SIGNAL(textChanged(QString)), this, SLOT(changed()));
connect(ui->warningFileNameCap, SIGNAL(valueChanged(int)), this, SLOT(changed()));
connect(ui->warningLineNumberCap, SIGNAL(valueChanged(int)), this, SLOT(changed()));
connect(ui->warningMessageCap, SIGNAL(valueChanged(int)), this, SLOT(changed()));
changed();
m_dirty = false;
@@ -60,33 +66,58 @@ CustomParserConfigDialog::~CustomParserConfigDialog()
void CustomParserConfigDialog::setExampleSettings()
{
setErrorPattern(QLatin1String("#error (.*):(\\d+): (.*)$"));
setFileNameCap(1);
setLineNumberCap(2);
setMessageCap(3);
ui->errorMessage->setText(QLatin1String("#error /home/user/src/test.c:891: Unknown identifier `test`"));
setErrorPattern(QLatin1String("#error (.*):(\\d+): (.*)"));
setErrorFileNameCap(1);
setErrorLineNumberCap(2);
setErrorMessageCap(3);
setErrorChannel(CustomParserExpression::ParseBothChannels);
setWarningPattern(QLatin1String("#warning (.*):(\\d+): (.*)"));
setWarningFileNameCap(1);
setWarningLineNumberCap(2);
setWarningMessageCap(3);
setWarningChannel(CustomParserExpression::ParseBothChannels);
ui->errorOutputMessage->setText(
QLatin1String("#error /home/user/src/test.c:891: Unknown identifier `test`"));
ui->warningOutputMessage->setText(
QLatin1String("#warning /home/user/src/test.c:49: Unreferenced variable `test`"));
}
void CustomParserConfigDialog::setSettings(const CustomParserSettings &settings)
{
if (settings.errorPattern.isEmpty()) {
if (settings.error.pattern().isEmpty() && settings.warning.pattern().isEmpty()) {
setExampleSettings();
return;
}
setErrorPattern(settings.errorPattern);
setFileNameCap(settings.fileNameCap);
setLineNumberCap(settings.lineNumberCap);
setMessageCap(settings.messageCap);
setErrorPattern(settings.error.pattern());
setErrorFileNameCap(settings.error.fileNameCap());
setErrorLineNumberCap(settings.error.lineNumberCap());
setErrorMessageCap(settings.error.messageCap());
setErrorChannel(settings.error.channel());
setErrorExample(settings.error.example());
setWarningPattern(settings.warning.pattern());
setWarningFileNameCap(settings.warning.fileNameCap());
setWarningLineNumberCap(settings.warning.lineNumberCap());
setWarningMessageCap(settings.warning.messageCap());
setWarningChannel(settings.warning.channel());
setWarningExample(settings.warning.example());
}
CustomParserSettings CustomParserConfigDialog::settings() const
{
CustomParserSettings result;
result.errorPattern = errorPattern();
result.fileNameCap = fileNameCap();
result.lineNumberCap = lineNumberCap();
result.messageCap = messageCap();
result.error.setPattern(errorPattern());
result.error.setFileNameCap(errorFileNameCap());
result.error.setLineNumberCap(errorLineNumberCap());
result.error.setMessageCap(errorMessageCap());
result.error.setChannel(errorChannel());
result.error.setExample(errorExample());
result.warning.setPattern(warningPattern());
result.warning.setFileNameCap(warningFileNameCap());
result.warning.setLineNumberCap(warningLineNumberCap());
result.warning.setMessageCap(warningMessageCap());
result.warning.setChannel(warningChannel());
result.warning.setExample(warningExample());
return result;
}
@@ -100,34 +131,128 @@ QString CustomParserConfigDialog::errorPattern() const
return ui->errorPattern->text();
}
void CustomParserConfigDialog::setFileNameCap(int fileNameCap)
void CustomParserConfigDialog::setErrorFileNameCap(int fileNameCap)
{
ui->fileNameCap->setValue(fileNameCap);
ui->errorFileNameCap->setValue(fileNameCap);
}
int CustomParserConfigDialog::fileNameCap() const
int CustomParserConfigDialog::errorFileNameCap() const
{
return ui->fileNameCap->value();
return ui->errorFileNameCap->value();
}
void CustomParserConfigDialog::setLineNumberCap(int lineNumberCap)
void CustomParserConfigDialog::setErrorLineNumberCap(int lineNumberCap)
{
ui->lineNumberCap->setValue(lineNumberCap);
ui->errorLineNumberCap->setValue(lineNumberCap);
}
int CustomParserConfigDialog::lineNumberCap() const
int CustomParserConfigDialog::errorLineNumberCap() const
{
return ui->lineNumberCap->value();
return ui->errorLineNumberCap->value();
}
void CustomParserConfigDialog::setMessageCap(int messageCap)
void CustomParserConfigDialog::setErrorMessageCap(int messageCap)
{
ui->messageCap->setValue(messageCap);
ui->errorMessageCap->setValue(messageCap);
}
int CustomParserConfigDialog::messageCap() const
int CustomParserConfigDialog::errorMessageCap() const
{
return ui->messageCap->value();
return ui->errorMessageCap->value();
}
void CustomParserConfigDialog::setErrorChannel(CustomParserExpression::CustomParserChannel errorChannel)
{
ui->errorStdErrChannel->setChecked(
errorChannel & static_cast<int>(CustomParserExpression::ParseStdErrChannel));
ui->errorStdOutChannel->setChecked(
errorChannel & static_cast<int>(CustomParserExpression::ParseStdOutChannel));
}
CustomParserExpression::CustomParserChannel CustomParserConfigDialog::errorChannel() const
{
if (ui->errorStdErrChannel->isChecked() && !ui->errorStdOutChannel->isChecked())
return CustomParserExpression::ParseStdErrChannel;
if (ui->errorStdOutChannel->isChecked() && !ui->errorStdErrChannel->isChecked())
return CustomParserExpression::ParseStdOutChannel;
return CustomParserExpression::ParseBothChannels;
}
void CustomParserConfigDialog::setErrorExample(const QString &errorExample)
{
ui->errorOutputMessage->setText(errorExample);
}
QString CustomParserConfigDialog::errorExample() const
{
return ui->errorOutputMessage->text();
}
void CustomParserConfigDialog::setWarningPattern(const QString &warningPattern)
{
ui->warningPattern->setText(warningPattern);
}
QString CustomParserConfigDialog::warningPattern() const
{
return ui->warningPattern->text();
}
void CustomParserConfigDialog::setWarningFileNameCap(int warningFileNameCap)
{
ui->warningFileNameCap->setValue(warningFileNameCap);
}
int CustomParserConfigDialog::warningFileNameCap() const
{
return ui->warningFileNameCap->value();
}
void CustomParserConfigDialog::setWarningLineNumberCap(int warningLineNumberCap)
{
ui->warningLineNumberCap->setValue(warningLineNumberCap);
}
int CustomParserConfigDialog::warningLineNumberCap() const
{
return ui->warningLineNumberCap->value();
}
void CustomParserConfigDialog::setWarningMessageCap(int warningMessageCap)
{
ui->warningMessageCap->setValue(warningMessageCap);
}
int CustomParserConfigDialog::warningMessageCap() const
{
return ui->warningMessageCap->value();
}
void CustomParserConfigDialog::setWarningChannel(CustomParserExpression::CustomParserChannel warningChannel)
{
ui->warningStdErrChannel->setChecked(
warningChannel & static_cast<int>(CustomParserExpression::ParseStdErrChannel));
ui->warningStdOutChannel->setChecked(
warningChannel & static_cast<int>(CustomParserExpression::ParseStdOutChannel));
}
CustomParserExpression::CustomParserChannel CustomParserConfigDialog::warningChannel() const
{
if (ui->warningStdErrChannel->isChecked() && !ui->warningStdOutChannel->isChecked())
return CustomParserExpression::ParseStdErrChannel;
if (ui->warningStdOutChannel->isChecked() && !ui->warningStdErrChannel->isChecked())
return CustomParserExpression::ParseStdOutChannel;
return CustomParserExpression::ParseBothChannels;
}
void CustomParserConfigDialog::setWarningExample(const QString &warningExample)
{
ui->warningOutputMessage->setText(warningExample);
}
QString CustomParserConfigDialog::warningExample() const
{
return ui->warningOutputMessage->text();
}
bool CustomParserConfigDialog::isDirty() const
@@ -135,37 +260,60 @@ bool CustomParserConfigDialog::isDirty() const
return m_dirty;
}
void CustomParserConfigDialog::changed()
bool CustomParserConfigDialog::checkPattern(QLineEdit *pattern, const QString &outputText,
QString *errorMessage, QRegularExpressionMatch *match)
{
QRegularExpression rx;
rx.setPattern(ui->errorPattern->text());
rx.setPattern(pattern->text());
QPalette palette;
palette.setColor(QPalette::Text, rx.isValid() ? Qt::black : Qt::red);
ui->errorPattern->setPalette(palette);
ui->errorPattern->setToolTip(rx.isValid() ? QString() : rx.errorString());
pattern->setPalette(palette);
pattern->setToolTip(rx.isValid() ? QString() : rx.errorString());
const QRegularExpressionMatch match = rx.match(ui->errorMessage->text());
if (rx.pattern().isEmpty() || !rx.isValid() || !match.hasMatch()) {
QString error = QLatin1String("<font color=\"red\">") + tr("Not applicable:") + QLatin1Char(' ');
*match = rx.match(outputText);
if (rx.pattern().isEmpty() || !rx.isValid() || !match->hasMatch()) {
*errorMessage = QLatin1String("<font color=\"red\">") + tr("Not applicable:") + QLatin1Char(' ');
if (rx.pattern().isEmpty())
error += tr("Pattern is empty.");
*errorMessage += tr("Pattern is empty.");
else if (!rx.isValid())
error += rx.errorString();
*errorMessage += rx.errorString();
else if (outputText.isEmpty())
*errorMessage += tr("No message given.");
else
error += tr("Pattern does not match the message.");
*errorMessage += tr("Pattern does not match the message.");
ui->fileNameTest->setText(error);
ui->lineNumberTest->setText(error);
ui->messageTest->setText(error);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
return;
return false;
}
ui->fileNameTest->setText(match.captured(ui->fileNameCap->value()));
ui->lineNumberTest->setText(match.captured(ui->lineNumberCap->value()));
ui->messageTest->setText(match.captured(ui->messageCap->value()));
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
errorMessage->clear();
return true;
}
void CustomParserConfigDialog::changed()
{
QRegularExpressionMatch match;
QString errorMessage;
if (checkPattern(ui->errorPattern, ui->errorOutputMessage->text(), &errorMessage, &match)) {
ui->errorFileNameTest->setText(match.captured(ui->errorFileNameCap->value()));
ui->errorLineNumberTest->setText(match.captured(ui->errorLineNumberCap->value()));
ui->errorMessageTest->setText(match.captured(ui->errorMessageCap->value()));
} else {
ui->errorFileNameTest->setText(errorMessage);
ui->errorLineNumberTest->setText(errorMessage);
ui->errorMessageTest->setText(errorMessage);
}
if (checkPattern(ui->warningPattern, ui->warningOutputMessage->text(), &errorMessage, &match)) {
ui->warningFileNameTest->setText(match.captured(ui->warningFileNameCap->value()));
ui->warningLineNumberTest->setText(match.captured(ui->warningLineNumberCap->value()));
ui->warningMessageTest->setText(match.captured(ui->warningMessageCap->value()));
} else {
ui->warningFileNameTest->setText(errorMessage);
ui->warningLineNumberTest->setText(errorMessage);
ui->warningMessageTest->setText(errorMessage);
}
m_dirty = true;
}

View File

@@ -35,6 +35,10 @@
#include <QDialog>
QT_BEGIN_NAMESPACE
class QLineEdit;
QT_END_NAMESPACE
namespace ProjectExplorer {
namespace Internal {
@@ -53,18 +57,38 @@ public:
CustomParserSettings settings() const;
void setErrorPattern(const QString &errorPattern);
QString errorPattern() const;
void setFileNameCap(int fileNameCap);
int fileNameCap() const;
void setLineNumberCap(int lineNumberCap);
int lineNumberCap() const;
void setMessageCap(int messageCap);
int messageCap() const;
void setErrorFileNameCap(int errorFileNameCap);
int errorFileNameCap() const;
void setErrorLineNumberCap(int errorLineNumberCap);
int errorLineNumberCap() const;
void setErrorMessageCap(int errorMessageCap);
int errorMessageCap() const;
void setErrorChannel(CustomParserExpression::CustomParserChannel errorChannel);
CustomParserExpression::CustomParserChannel errorChannel() const;
void setErrorExample(const QString &errorExample);
QString errorExample() const;
void setWarningPattern(const QString &warningPattern);
QString warningPattern() const;
void setWarningFileNameCap(int warningFileNameCap);
int warningFileNameCap() const;
void setWarningLineNumberCap(int warningLineNumberCap);
int warningLineNumberCap() const;
void setWarningMessageCap(int warningMessageCap);
int warningMessageCap() const;
void setWarningChannel(CustomParserExpression::CustomParserChannel warningChannel);
CustomParserExpression::CustomParserChannel warningChannel() const;
void setWarningExample(const QString &warningExample);
QString warningExample() const;
bool isDirty() const;
private slots:
void changed();
private:
bool checkPattern(QLineEdit *pattern, const QString &outputText,
QString *errorMessage, QRegularExpressionMatch *match);
Ui::CustomParserConfigDialog *ui;
bool m_dirty;
};

View File

@@ -6,188 +6,414 @@
<rect>
<x>0</x>
<y>0</y>
<width>470</width>
<height>368</height>
<width>516</width>
<height>480</height>
</rect>
</property>
<property name="windowTitle">
<string>Custom Parser</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>&amp;Error message capture pattern:</string>
</property>
<property name="buddy">
<cstring>errorPattern</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="errorPattern">
<property name="text">
<string>#error (.*):(\d+): (.*)$</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="capturePositionsGroup">
<property name="title">
<string>Capture Positions</string>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;File name:</string>
</property>
<property name="buddy">
<cstring>fileNameCap</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&amp;Line number:</string>
</property>
<property name="buddy">
<cstring>lineNumberCap</cstring>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>&amp;Message:</string>
</property>
<property name="buddy">
<cstring>messageCap</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSpinBox" name="fileNameCap">
<property name="maximum">
<number>9</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="lineNumberCap">
<property name="maximum">
<number>9</number>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="messageCap">
<property name="maximum">
<number>9</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
</layout>
<widget class="QWidget" name="tabError">
<attribute name="title">
<string>Error</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>&amp;Error message capture pattern:</string>
</property>
<property name="buddy">
<cstring>errorPattern</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="errorPattern">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="errorCapturePositionsGroup">
<property name="title">
<string>Capture Positions</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;File name:</string>
</property>
<property name="buddy">
<cstring>errorFileNameCap</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&amp;Line number:</string>
</property>
<property name="buddy">
<cstring>errorLineNumberCap</cstring>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>&amp;Message:</string>
</property>
<property name="buddy">
<cstring>errorMessageCap</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSpinBox" name="errorFileNameCap">
<property name="maximum">
<number>9</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="errorLineNumberCap">
<property name="maximum">
<number>9</number>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="errorMessageCap">
<property name="maximum">
<number>9</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="errorCaptureChannelsGroup">
<property name="title">
<string>Capture Output Channels</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="errorStdOutChannel">
<property name="text">
<string>Standard output</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="errorStdErrChannel">
<property name="text">
<string>Standard error</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="errorTestGroup">
<property name="title">
<string>Test</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>E&amp;rror message:</string>
</property>
<property name="buddy">
<cstring>errorOutputMessage</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="errorOutputMessage">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>File name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="errorFileNameTest">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Line number:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="errorLineNumberTest">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Message:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="errorMessageTest">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabWarning">
<attribute name="title">
<string>Warning</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Warning message capture pattern:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="warningPattern">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="warningCapturePositionsGroup">
<property name="title">
<string>Capture Positions</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="2">
<widget class="QSpinBox" name="warningLineNumberCap">
<property name="maximum">
<number>9</number>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QSpinBox" name="warningMessageCap">
<property name="maximum">
<number>9</number>
</property>
<property name="value">
<number>3</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_12">
<property name="text">
<string>&amp;Line number:</string>
</property>
<property name="buddy">
<cstring>errorLineNumberCap</cstring>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>&amp;File name:</string>
</property>
<property name="buddy">
<cstring>errorFileNameCap</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="warningFileNameCap">
<property name="maximum">
<number>9</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_13">
<property name="text">
<string>&amp;Message:</string>
</property>
<property name="buddy">
<cstring>errorMessageCap</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="warningOutputChannelsGroup">
<property name="title">
<string>Capture Output Channels</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="warningStdOutChannel">
<property name="text">
<string>Standard output</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="warningStdErrChannel">
<property name="text">
<string>Standard error</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="warningTestGroup">
<property name="title">
<string>Test</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QLabel" name="label_14">
<property name="text">
<string>Warning message:</string>
</property>
<property name="buddy">
<cstring>errorOutputMessage</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="warningOutputMessage">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>File name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="warningFileNameTest">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Line number:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="warningLineNumberTest">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Message:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="warningMessageTest">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QGroupBox" name="testGroup">
<property name="title">
<string>Test</string>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>E&amp;rror message:</string>
</property>
<property name="buddy">
<cstring>errorMessage</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="errorMessage">
<property name="text">
<string>#error /home/user/src/test.c:891: Unknown identifier `test`</string>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>File name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="fileNameTest">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Line number:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="lineNumberTest">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Message:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="messageTest">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>22</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
@@ -200,10 +426,10 @@
</widget>
<tabstops>
<tabstop>errorPattern</tabstop>
<tabstop>fileNameCap</tabstop>
<tabstop>lineNumberCap</tabstop>
<tabstop>messageCap</tabstop>
<tabstop>errorMessage</tabstop>
<tabstop>errorFileNameCap</tabstop>
<tabstop>errorLineNumberCap</tabstop>
<tabstop>errorMessageCap</tabstop>
<tabstop>errorOutputMessage</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>

View File

@@ -69,6 +69,19 @@ static const char cxx11FlagsKeyC[] = "ProjectExplorer.CustomToolChain.Cxx11Flags
static const char mkspecsKeyC[] = "ProjectExplorer.CustomToolChain.Mkspecs";
static const char outputParserKeyC[] = "ProjectExplorer.CustomToolChain.OutputParser";
static const char errorPatternKeyC[] = "ProjectExplorer.CustomToolChain.ErrorPattern";
static const char errorLineNumberCapKeyC[] = "ProjectExplorer.CustomToolChain.ErrorLineNumberCap";
static const char errorFileNameCapKeyC[] = "ProjectExplorer.CustomToolChain.ErrorFileNameCap";
static const char errorMessageCapKeyC[] = "ProjectExplorer.CustomToolChain.ErrorMessageCap";
static const char errorChannelKeyC[] = "ProjectExplorer.CustomToolChain.ErrorChannel";
static const char errorExampleKeyC[] = "ProjectExplorer.CustomToolChain.ErrorExample";
static const char warningPatternKeyC[] = "ProjectExplorer.CustomToolChain.WarningPattern";
static const char warningLineNumberCapKeyC[] = "ProjectExplorer.CustomToolChain.WarningLineNumberCap";
static const char warningFileNameCapKeyC[] = "ProjectExplorer.CustomToolChain.WarningFileNameCap";
static const char warningMessageCapKeyC[] = "ProjectExplorer.CustomToolChain.WarningMessageCap";
static const char warningChannelKeyC[] = "ProjectExplorer.CustomToolChain.WarningChannel";
static const char warningExampleKeyC[] = "ProjectExplorer.CustomToolChain.WarningExample";
// TODO Creator 4.1: remove (added in 3.7 for compatibility)
static const char lineNumberCapKeyC[] = "ProjectExplorer.CustomToolChain.LineNumberCap";
static const char fileNameCapKeyC[] = "ProjectExplorer.CustomToolChain.FileNameCap";
static const char messageCapKeyC[] = "ProjectExplorer.CustomToolChain.MessageCap";
@@ -282,10 +295,18 @@ QVariantMap CustomToolChain::toMap() const
data.insert(QLatin1String(cxx11FlagsKeyC), m_cxx11Flags);
data.insert(QLatin1String(mkspecsKeyC), mkspecs());
data.insert(QLatin1String(outputParserKeyC), m_outputParser);
data.insert(QLatin1String(errorPatternKeyC), m_customParserSettings.errorPattern);
data.insert(QLatin1String(fileNameCapKeyC), m_customParserSettings.fileNameCap);
data.insert(QLatin1String(lineNumberCapKeyC), m_customParserSettings.lineNumberCap);
data.insert(QLatin1String(messageCapKeyC), m_customParserSettings.messageCap);
data.insert(QLatin1String(errorPatternKeyC), m_customParserSettings.error.pattern());
data.insert(QLatin1String(errorFileNameCapKeyC), m_customParserSettings.error.fileNameCap());
data.insert(QLatin1String(errorLineNumberCapKeyC), m_customParserSettings.error.lineNumberCap());
data.insert(QLatin1String(errorMessageCapKeyC), m_customParserSettings.error.messageCap());
data.insert(QLatin1String(errorChannelKeyC), m_customParserSettings.error.channel());
data.insert(QLatin1String(errorExampleKeyC), m_customParserSettings.error.example());
data.insert(QLatin1String(warningPatternKeyC), m_customParserSettings.warning.pattern());
data.insert(QLatin1String(warningFileNameCapKeyC), m_customParserSettings.warning.fileNameCap());
data.insert(QLatin1String(warningLineNumberCapKeyC), m_customParserSettings.warning.lineNumberCap());
data.insert(QLatin1String(warningMessageCapKeyC), m_customParserSettings.warning.messageCap());
data.insert(QLatin1String(warningChannelKeyC), m_customParserSettings.warning.channel());
data.insert(QLatin1String(warningExampleKeyC), m_customParserSettings.warning.example());
return data;
}
@@ -303,10 +324,29 @@ bool CustomToolChain::fromMap(const QVariantMap &data)
m_cxx11Flags = data.value(QLatin1String(cxx11FlagsKeyC)).toStringList();
setMkspecs(data.value(QLatin1String(mkspecsKeyC)).toString());
m_outputParser = (OutputParser)data.value(QLatin1String(outputParserKeyC)).toInt();
m_customParserSettings.errorPattern = data.value(QLatin1String(errorPatternKeyC)).toString();
m_customParserSettings.fileNameCap = data.value(QLatin1String(fileNameCapKeyC)).toInt();
m_customParserSettings.lineNumberCap = data.value(QLatin1String(lineNumberCapKeyC)).toInt();
m_customParserSettings.messageCap = data.value(QLatin1String(messageCapKeyC)).toInt();
m_customParserSettings.error.setPattern(data.value(QLatin1String(errorPatternKeyC)).toString());
m_customParserSettings.error.setFileNameCap(data.value(QLatin1String(errorFileNameCapKeyC)).toInt());
m_customParserSettings.error.setLineNumberCap(data.value(QLatin1String(errorLineNumberCapKeyC)).toInt());
m_customParserSettings.error.setMessageCap(data.value(QLatin1String(errorMessageCapKeyC)).toInt());
m_customParserSettings.error.setChannel(
static_cast<CustomParserExpression::CustomParserChannel>(data.value(QLatin1String(errorChannelKeyC)).toInt()));
m_customParserSettings.error.setExample(data.value(QLatin1String(errorExampleKeyC)).toString());
m_customParserSettings.warning.setPattern(data.value(QLatin1String(warningPatternKeyC)).toString());
m_customParserSettings.warning.setFileNameCap(data.value(QLatin1String(warningFileNameCapKeyC)).toInt());
m_customParserSettings.warning.setLineNumberCap(data.value(QLatin1String(warningLineNumberCapKeyC)).toInt());
m_customParserSettings.warning.setMessageCap(data.value(QLatin1String(warningMessageCapKeyC)).toInt());
m_customParserSettings.warning.setChannel(
static_cast<CustomParserExpression::CustomParserChannel>(data.value(QLatin1String(warningChannelKeyC)).toInt()));
m_customParserSettings.warning.setExample(data.value(QLatin1String(warningExampleKeyC)).toString());
// TODO Creator 4.1: remove (added in 3.7 for compatibility)
if (m_customParserSettings.error.fileNameCap() == 0)
m_customParserSettings.error.setFileNameCap(data.value(QLatin1String(fileNameCapKeyC)).toInt());
if (m_customParserSettings.error.lineNumberCap() == 0)
m_customParserSettings.error.setLineNumberCap(data.value(QLatin1String(lineNumberCapKeyC)).toInt());
if (m_customParserSettings.error.messageCap() == 0)
m_customParserSettings.error.setMessageCap(data.value(QLatin1String(messageCapKeyC)).toInt());
QTC_ASSERT(m_outputParser >= Gcc && m_outputParser < OutputParserCount, return false);
return true;