Clang: Improve parser

Do not pass on snippet lines to child parser where they might cause
confusion.

Change-Id: Ia30726842b0b0a4c2871c3b8e56539d9b79ccfd8
Reviewed-on: http://codereview.qt.nokia.com/343
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com>
This commit is contained in:
Tobias Hunger
2011-06-04 19:29:57 +02:00
parent 82272d9c22
commit f3bc321f76
2 changed files with 41 additions and 40 deletions

View File

@@ -48,23 +48,30 @@ ClangParser::ClangParser() :
m_commandRegExp(QLatin1String("^clang(\\+\\+)?: +(fatal +)?(warning|error|note): (.*)$")), m_commandRegExp(QLatin1String("^clang(\\+\\+)?: +(fatal +)?(warning|error|note): (.*)$")),
m_inLineRegExp(QLatin1String("^In (.*) included from (.*):(\\d+):$")), m_inLineRegExp(QLatin1String("^In (.*) included from (.*):(\\d+):$")),
m_messageRegExp(QLatin1String("^") + QLatin1String(FILE_PATTERN) + QLatin1String("(:(\\d+):\\d+|\\((\\d+)\\) *): +(fatal +)?(error|warning|note): (.*)$")), m_messageRegExp(QLatin1String("^") + QLatin1String(FILE_PATTERN) + QLatin1String("(:(\\d+):\\d+|\\((\\d+)\\) *): +(fatal +)?(error|warning|note): (.*)$")),
m_summaryRegExp(QLatin1String("^\\d+ (warnings?|errors?)( and \\d (warnings?|errors?))? generated.$")) m_summaryRegExp(QLatin1String("^\\d+ (warnings?|errors?)( and \\d (warnings?|errors?))? generated.$")),
m_expectSnippet(false)
{ {
setObjectName(QLatin1String("ClangParser")); setObjectName(QLatin1String("ClangParser"));
appendOutputParser(new LdParser); appendOutputParser(new LdParser);
} }
ClangParser::~ClangParser()
{
emitTask();
}
void ClangParser::stdError(const QString &line) void ClangParser::stdError(const QString &line)
{ {
const QString lne = line.left(line.count() - 1); const QString lne = line.left(line.count() - 1);
if (m_summaryRegExp.indexIn(lne) > -1) { if (m_summaryRegExp.indexIn(lne) > -1) {
emitTask(); emitTask();
m_expectSnippet = false;
return; return;
} }
if (m_commandRegExp.indexIn(lne) > -1) { if (m_commandRegExp.indexIn(lne) > -1) {
m_codeSnippet.clear(); m_expectSnippet = true;
newTask(Task::Error, newTask(Task::Error,
m_commandRegExp.cap(4), m_commandRegExp.cap(4),
QString(), /* filename */ QString(), /* filename */
@@ -78,7 +85,7 @@ void ClangParser::stdError(const QString &line)
} }
if (m_inLineRegExp.indexIn(lne) > -1) { if (m_inLineRegExp.indexIn(lne) > -1) {
m_codeSnippet.clear(); m_expectSnippet = true;
newTask(Task::Unknown, newTask(Task::Unknown,
lne.trimmed(), lne.trimmed(),
m_inLineRegExp.cap(2), /* filename */ m_inLineRegExp.cap(2), /* filename */
@@ -88,7 +95,7 @@ void ClangParser::stdError(const QString &line)
} }
if (m_messageRegExp.indexIn(lne) > -1) { if (m_messageRegExp.indexIn(lne) > -1) {
m_codeSnippet.clear(); m_expectSnippet = true;
bool ok = false; bool ok = false;
int lineNo = m_messageRegExp.cap(4).toInt(&ok); int lineNo = m_messageRegExp.cap(4).toInt(&ok);
if (!ok) if (!ok)
@@ -105,40 +112,18 @@ void ClangParser::stdError(const QString &line)
return; return;
} }
if (!m_codeSnippet.isEmpty()) { if (m_expectSnippet && !m_currentTask.isNull()) {
bool caretSeen = false; QTextLayout::FormatRange fr;
bool valid = true; fr.start = m_currentTask.description.count() + 1;
for (int i = 0; i < lne.count() && valid; ++i) { fr.length = lne.count() + 1;
if (QChar(' ') == lne.at(i)) fr.format.setFontFamily("Monospaced");
continue; fr.format.setFontStyleHint(QFont::TypeWriter);
if (QChar('~') == lne.at(i)) m_currentTask.description.append(QLatin1Char('\n'));
continue; m_currentTask.description.append(lne);
if (QChar('^') == lne.at(i)) { m_currentTask.formats.append(fr);
if (caretSeen) return;
valid = false;
else
caretSeen = true;
continue;
}
valid = false;
}
if (valid && caretSeen) {
QTextLayout::FormatRange fr;
fr.start = m_currentTask.description.count() + 1;
fr.length = m_codeSnippet.count() + lne.count() + 1;
fr.format.setFontFamily("Monospaced");
fr.format.setFontStyleHint(QFont::TypeWriter);
m_currentTask.description.append(QLatin1Char('\n'));
m_currentTask.description.append(m_codeSnippet);
m_currentTask.description.append(QLatin1Char('\n'));
m_currentTask.description.append(lne);
m_currentTask.formats.append(fr);
return;
}
} }
m_codeSnippet = lne;
IOutputParser::stdError(line); IOutputParser::stdError(line);
} }
@@ -212,7 +197,7 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
"class Q_CORE_EXPORT QSysInfo {\n" "class Q_CORE_EXPORT QSysInfo {\n"
" ^") " ^")
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("class Q_CORE_EXPORT QSysInfo {\n") << QString() << QString()
<< (QList<ProjectExplorer::Task>() << (QList<ProjectExplorer::Task>()
<< Task(Task::Unknown, << Task(Task::Unknown,
QLatin1String("In file included from ..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qnamespace.h:45:"), QLatin1String("In file included from ..\\..\\..\\QtSDK1.1\\Desktop\\Qt\\4.7.3\\mingw\\include/QtCore/qnamespace.h:45:"),
@@ -230,7 +215,7 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
"# define Q_CORE_EXPORT Q_DECL_IMPORT\n" "# define Q_CORE_EXPORT Q_DECL_IMPORT\n"
" ^") " ^")
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("# define Q_CORE_EXPORT Q_DECL_IMPORT\n") << QString() << QString()
<< (QList<ProjectExplorer::Task>() << (QList<ProjectExplorer::Task>()
<< Task(Task::Unknown, << Task(Task::Unknown,
QLatin1String("instantiated from:\n" QLatin1String("instantiated from:\n"
@@ -244,7 +229,7 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
"#include <bits/c++config.h>\n" "#include <bits/c++config.h>\n"
" ^") " ^")
<< OutputParserTester::STDERR << OutputParserTester::STDERR
<< QString() << QString::fromLatin1("#include <bits/c++config.h>\n") << QString() << QString()
<< (QList<ProjectExplorer::Task>() << (QList<ProjectExplorer::Task>()
<< Task(Task::Error, << Task(Task::Error,
QLatin1String("'bits/c++config.h' file not found\n" QLatin1String("'bits/c++config.h' file not found\n"
@@ -253,6 +238,21 @@ void ProjectExplorerPlugin::testClangOutputParser_data()
QLatin1String("/usr/include/c++/4.6/utility"), 68, QLatin1String("/usr/include/c++/4.6/utility"), 68,
Constants::TASK_CATEGORY_COMPILE)) Constants::TASK_CATEGORY_COMPILE))
<< QString(); << QString();
QTest::newRow("line confusion")
<< QString::fromLatin1("/home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp:567:51: warning: ?: has lower precedence than +; + will be evaluated first [-Wparentheses]\n"
" int x = option->rect.x() + horizontal ? 2 : 6;\n"
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^")
<< OutputParserTester::STDERR
<< QString() << QString()
<< (QList<ProjectExplorer::Task>()
<< Task(Task::Warning,
QLatin1String("?: has lower precedence than +; + will be evaluated first [-Wparentheses]\n"
" int x = option->rect.x() + horizontal ? 2 : 6;\n"
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^"),
QLatin1String("/home/code/src/creator/src/plugins/coreplugin/manhattanstyle.cpp"), 567,
Constants::TASK_CATEGORY_COMPILE))
<< QString();
} }
void ProjectExplorerPlugin::testClangOutputParser() void ProjectExplorerPlugin::testClangOutputParser()

View File

@@ -45,6 +45,7 @@ class ClangParser : public ProjectExplorer::IOutputParser
public: public:
ClangParser(); ClangParser();
~ClangParser();
void stdError(const QString &line); void stdError(const QString &line);
private: private:
@@ -57,7 +58,7 @@ private:
QRegExp m_inLineRegExp; QRegExp m_inLineRegExp;
QRegExp m_messageRegExp; QRegExp m_messageRegExp;
QRegExp m_summaryRegExp; QRegExp m_summaryRegExp;
QString m_codeSnippet; bool m_expectSnippet;
Task m_currentTask; Task m_currentTask;
}; };