Skip to content

Commit

Permalink
Improve msvc output parser
Browse files Browse the repository at this point in the history
  • Loading branch information
arBmind committed Feb 1, 2025
1 parent 1bd3cac commit b765901
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 52 deletions.
11 changes: 0 additions & 11 deletions src/plugins/projectexplorer/ioutputparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,6 @@ const QList<OutputTaskParser::TaskInfo> OutputTaskParser::taskInfo() const
return d->scheduledTasks;
}

bool OutputTaskParser::hasCurrentTask() const
{
return !d->currentTask.isNull();
}

void OutputTaskParser::amendTaskDetails(const QString &originalLine)
{
d->currentTask.details.append(originalLine);
++d->lineCount;
}

void OutputTaskParser::scheduleTask(const Task &task, int outputLines, int skippedLines)
{
TaskInfo ts(task, outputLines, skippedLines);
Expand Down
3 changes: 0 additions & 3 deletions src/plugins/projectexplorer/ioutputparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ class PROJECTEXPLORER_EXPORT OutputTaskParser : public Utils::OutputLineParser
const QList<TaskInfo> taskInfo() const;

protected:
bool hasCurrentTask() const;
void amendTaskDetails(const QString &originalLine);

void flush() override;

void scheduleTask(const Task &task, int outputLines, int skippedLines = 0);
Expand Down
105 changes: 67 additions & 38 deletions src/plugins/projectexplorer/msvcparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,62 @@

using namespace Utils;

// As of MSVC 2015: "foo.cpp(42) :" -> "foo.cpp(42):"
static const char FILE_POS_PATTERN[] = "^(?:\\d+>)?(cl|LINK|.+?[^ ]) ?: ";
namespace {

static QPair<FilePath, int> parseFileName(const QString &input)
auto constexpr filePosRegexString() -> std::string_view {
// As of MSVC 2015: "foo.cpp(42) :" -> "foo.cpp(42):"
return R"(^(?:\d+>)?(cl|LINK|.+?[^ ]) ?: )";
}

struct FileData {
FilePath fileName{};
int lineNo{-1};
int columnNo{-1};
};

auto parseFileName(QStringView input) -> FileData
{
QString fileName = input;
if (fileName.startsWith("LINK") || fileName.startsWith("cl"))
return {{}, -1};
auto result = FileData{};

if (input.startsWith(QStringView{u"LINK "}) || input.startsWith(QStringView{u"cl "})){
return result;
}
auto& [fileName, lineNo, columnNo] = result;

// Extract linenumber (if it is there):
int linenumber = -1;
if (fileName.endsWith(')')) {
int pos = fileName.lastIndexOf('(');
if (pos >= 0) {
// clang-cl gives column, too: "foo.cpp(34,1)" as opposed to MSVC "foo.cpp(34)".
int endPos = fileName.indexOf(',', pos + 1);
if (endPos < 0)
endPos = fileName.size() - 1;
bool ok = false;
const int n = fileName.mid(pos + 1, endPos - pos - 1).toInt(&ok);
if (ok) {
fileName = fileName.left(pos);
linenumber = n;
if (input.size() > 2 && input.endsWith(')')) {
auto rit = input.rbegin() + 1;
auto rend = input.rend();
auto f = 0;
auto n = -1;
while (rit != rend) {
auto ch = *rit++;
if (ch.isDigit()) {
if (n < 0) {
n = ch.digitValue();
f = 10;
}
else {
n += ch.digitValue() * f;
f *= 10;
}
continue;
}
if (ch == u',') {
if (n >= 0) columnNo = n;
n = -1;
continue;
}
if (ch == u'(') {
if (n >= 0) lineNo = n;
input = input.sliced(0, rend - rit);
break;
}
break;
}
}
const QString normalized = FileUtils::normalizedPathName(fileName);
return {FilePath::fromUserInput(normalized), linenumber};
fileName = FilePath::fromUserInput(FileUtils::normalizedPathName(input.toString()));
return result;
}

using namespace ProjectExplorer;
Expand Down Expand Up @@ -74,13 +102,15 @@ static Task::TaskType taskType(const QString &category)
return type;
}

} // namespace

MsvcParser::MsvcParser()
{
setObjectName("MsvcParser");
m_compileRegExp.setPattern(QString(FILE_POS_PATTERN)
+ ".*(?:(warning|error) ([A-Z]+\\d{4} ?: )|note: )(.*)$");
m_compileRegExp.setPattern(QLatin1String(filePosRegexString())
+ R"(.*(?:(warning|error) ([A-Z]+\d{4} ?: )|note: )(.*)$)");
QTC_CHECK(m_compileRegExp.isValid());
m_additionalInfoRegExp.setPattern("^ (?:(could be |or )\\s*')?(.*)\\((\\d+)\\) : (.*)$");
m_additionalInfoRegExp.setPattern(R"(^ (?:(could be |or )\s*')?(.*)\((\d+)\) : (.*)$)");
QTC_CHECK(m_additionalInfoRegExp.isValid());
}

Expand Down Expand Up @@ -115,19 +145,19 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
m_isCaretDiagnostics = line.contains("/diagnostics:caret");
}
if (QRegularExpressionMatch match = m_compileRegExp.match(line); match.hasMatch()) {
QPair<FilePath, int> position = parseFileName(match.captured(1));
const FilePath filePath = absoluteFilePath(position.first);
auto [rawFileName, lineNo, columnNo] = parseFileName(match.captured(1));
const FilePath filePath = absoluteFilePath(rawFileName);
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, -1, match, 1);
const QString &description = match.captured(3) + match.captured(4).trimmed();
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, lineNo, columnNo, match, 1);
const auto description = match.captured(3) + match.captured(4).trimmed();
createOrAmendTask(
taskType(match.captured(2)),
description,
line,
false,
filePath,
position.second,
0,
lineNo,
columnNo > 0 ? columnNo : 0,
linkSpecs);
m_expectCode = m_isCaretDiagnostics;
return {Status::InProgress, linkSpecs};
Expand All @@ -144,7 +174,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
m_expectCode = m_isCaretDiagnostics;
return {Status::InProgress, linkSpecs};
}
if (hasCurrentTask()) {
if (!currentTask().isNull()) {
bool amend = false;
if (line.endsWith("^")) {
m_expectCode = false; // code was before
Expand All @@ -158,7 +188,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
amend = true;
}
if (amend) {
amendTaskDetails(line);
createOrAmendTask(Task::Unknown, {}, line, true);
return Status::InProgress;
}
}
Expand All @@ -176,7 +206,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
// ".\qwindowsgdinativeinterface.cpp(48,3) : error: unknown type name 'errr'"
static inline QString clangClCompilePattern()
{
return QLatin1String(FILE_POS_PATTERN) + " ?(warning|error): (.*)$";
return QLatin1String(filePosRegexString()) + " ?(warning|error): (.*)$";
}

ClangClParser::ClangClParser()
Expand Down Expand Up @@ -227,13 +257,12 @@ OutputLineParser::Result ClangClParser::handleLine(const QString &line, OutputFo
QRegularExpressionMatch match = m_compileRegExp.match(lne);
if (match.hasMatch()) {
flush();
const QPair<FilePath, int> position = parseFileName(match.captured(1));
const FilePath file = absoluteFilePath(position.first);
const int lineNo = position.second;
const auto [rawFileName, lineNo, columnNo] = parseFileName(match.captured(1));
const FilePath file = absoluteFilePath(rawFileName);
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, -1, match, 1);
addLinkSpecForAbsoluteFilePath(linkSpecs, file, lineNo, columnNo, match, 1);
createOrAmendTask(
taskType(match.captured(2)), match.captured(3).trimmed(), line, false, file, lineNo);
taskType(match.captured(2)), match.captured(3).trimmed(), line, false, file, lineNo, columnNo, linkSpecs);
return {Status::InProgress, linkSpecs};
}

Expand Down

0 comments on commit b765901

Please sign in to comment.