forked from qt-creator/qt-creator
BareMetal: Handle details preceding it message in the KEIL parser
We need to handle a multi-line error messages from the KEIL A51 assembler: http://www.keil.com/support/man/docs/a51/a51_er_nonfatalerror.htm This assembler produces an error messages in the form like: 00B0 114 ljmp usb_stub_isr ; (B0) GPIF operation complete. *** _____________________________________^ *** ERROR #A45 IN 114 (autovec_keil.a51, LINE 114): UNDEFINED SYMBOL 00B4 116 ljmp usb_stub_isr ; (B4) GPIF waveform. *** _____________________________________^ *** ERROR #A45 IN 116 (autovec_keil.a51, LINE 116): UNDEFINED SYMBOL where the details places before than a main message text. This patch handles this error messages, but with an one limitation in that a details should start with a four hexadecimal letters (in a common case it can not contains that letters at all). Change-Id: I0c9bf7ab72e1aef32498af5a1ef29c9221c185d5 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -70,20 +70,24 @@ void KeilParser::newTask(const Task &task)
|
|||||||
m_lines = 1;
|
m_lines = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeilParser::amendDescription(const QString &desc)
|
void KeilParser::amendDescription()
|
||||||
{
|
{
|
||||||
const int start = m_lastTask.description.count() + 1;
|
while (!m_snippets.isEmpty()) {
|
||||||
m_lastTask.description.append(QLatin1Char('\n'));
|
const QString snippet = m_snippets.takeFirst();
|
||||||
m_lastTask.description.append(desc);
|
|
||||||
|
|
||||||
QTextLayout::FormatRange fr;
|
const int start = m_lastTask.description.count() + 1;
|
||||||
fr.start = start;
|
m_lastTask.description.append('\n');
|
||||||
fr.length = m_lastTask.description.count() + 1;
|
m_lastTask.description.append(snippet);
|
||||||
fr.format.setFont(TextEditor::TextEditorSettings::fontSettings().font());
|
|
||||||
fr.format.setFontStyleHint(QFont::Monospace);
|
|
||||||
m_lastTask.formats.append(fr);
|
|
||||||
|
|
||||||
++m_lines;
|
QTextLayout::FormatRange fr;
|
||||||
|
fr.start = start;
|
||||||
|
fr.length = m_lastTask.description.count() + 1;
|
||||||
|
fr.format.setFont(TextEditor::TextEditorSettings::fontSettings().font());
|
||||||
|
fr.format.setFontStyleHint(QFont::Monospace);
|
||||||
|
m_lastTask.formats.append(fr);
|
||||||
|
|
||||||
|
++m_lines;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ARM compiler specific parsers.
|
// ARM compiler specific parsers.
|
||||||
@@ -205,18 +209,34 @@ void KeilParser::stdError(const QString &line)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (lne.startsWith(QLatin1Char(' '))) {
|
if (lne.startsWith(QLatin1Char(' '))) {
|
||||||
amendDescription(lne);
|
m_snippets.push_back(lne);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
doFlush();
|
doFlush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hasDetailsEntry(const QString &trimmedLine)
|
||||||
|
{
|
||||||
|
const QRegularExpression re("^([0-9A-F]{4})");
|
||||||
|
const QRegularExpressionMatch match = re.match(trimmedLine);
|
||||||
|
return match.hasMatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool hasDetailsPointer(const QString &trimmedLine)
|
||||||
|
{
|
||||||
|
if (!trimmedLine.startsWith("*** "))
|
||||||
|
return false;
|
||||||
|
if (!trimmedLine.endsWith('^'))
|
||||||
|
return false;
|
||||||
|
return trimmedLine.contains('_');
|
||||||
|
}
|
||||||
|
|
||||||
void KeilParser::stdOutput(const QString &line)
|
void KeilParser::stdOutput(const QString &line)
|
||||||
{
|
{
|
||||||
IOutputParser::stdOutput(line);
|
IOutputParser::stdOutput(line);
|
||||||
|
|
||||||
const QString lne = rightTrimmed(line);
|
QString lne = rightTrimmed(line);
|
||||||
|
|
||||||
// Check for MSC51 compiler specific patterns.
|
// Check for MSC51 compiler specific patterns.
|
||||||
const bool parsed = parseMcs51WarningOrErrorDetailsMessage1(lne)
|
const bool parsed = parseMcs51WarningOrErrorDetailsMessage1(lne)
|
||||||
@@ -228,9 +248,27 @@ void KeilParser::stdOutput(const QString &line)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lne.startsWith(QLatin1Char(' '))) {
|
if (m_lastTask.isNull()) {
|
||||||
amendDescription(lne);
|
// Check for details, which are comes on a previous
|
||||||
return;
|
// 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;
|
||||||
|
}
|
||||||
|
} 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();
|
||||||
@@ -241,6 +279,8 @@ void KeilParser::doFlush()
|
|||||||
if (m_lastTask.isNull())
|
if (m_lastTask.isNull())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
amendDescription();
|
||||||
|
|
||||||
Task t = m_lastTask;
|
Task t = m_lastTask;
|
||||||
m_lastTask.clear();
|
m_lastTask.clear();
|
||||||
emit addTask(t, m_lines, 1);
|
emit addTask(t, m_lines, 1);
|
||||||
@@ -425,6 +465,24 @@ void BareMetalPlugin::testKeilOutputParsers_data()
|
|||||||
categoryCompile))
|
categoryCompile))
|
||||||
<< QString();
|
<< QString();
|
||||||
|
|
||||||
|
QTest::newRow("MCS51: Assembler details error")
|
||||||
|
<< QString::fromLatin1("01AF Some detail\n"
|
||||||
|
"*** ___^\n"
|
||||||
|
"*** ERROR #A45 IN 28 (d:\\foo.a51, LINE 28): Some error")
|
||||||
|
<< OutputParserTester::STDOUT
|
||||||
|
<< QString::fromLatin1("01AF Some detail\n"
|
||||||
|
"*** ___^\n"
|
||||||
|
"*** ERROR #A45 IN 28 (d:\\foo.a51, LINE 28): Some error\n")
|
||||||
|
<< QString()
|
||||||
|
<< (Tasks() << Task(Task::Error,
|
||||||
|
QLatin1String("#A45: Some error\n"
|
||||||
|
" Some detail\n"
|
||||||
|
" ___^"),
|
||||||
|
Utils::FilePath::fromUserInput(QLatin1String("d:\\foo.a51")),
|
||||||
|
28,
|
||||||
|
categoryCompile))
|
||||||
|
<< QString();
|
||||||
|
|
||||||
// Compiler messages.
|
// Compiler messages.
|
||||||
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")
|
||||||
|
@@ -43,7 +43,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void newTask(const ProjectExplorer::Task &task);
|
void newTask(const ProjectExplorer::Task &task);
|
||||||
void amendDescription(const QString &desc);
|
void amendDescription();
|
||||||
|
|
||||||
// ARM compiler specific parsers.
|
// ARM compiler specific parsers.
|
||||||
bool parseArmWarningOrErrorDetailsMessage(const QString &lne);
|
bool parseArmWarningOrErrorDetailsMessage(const QString &lne);
|
||||||
@@ -61,6 +61,7 @@ private:
|
|||||||
|
|
||||||
ProjectExplorer::Task m_lastTask;
|
ProjectExplorer::Task m_lastTask;
|
||||||
int m_lines = 0;
|
int m_lines = 0;
|
||||||
|
QStringList m_snippets;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
Reference in New Issue
Block a user