Diagnostics: Add error code to the Diagnostic

Allows this to be formatted similarly to the severity.

Change-Id: I74cd863d8f1d94089ce753ab76a2c70784eb5553
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/33938
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ben Clayton
2020-11-26 17:49:22 +00:00
committed by Commit Bot service account
parent 61ec48b99e
commit f32a3c1f35
9 changed files with 167 additions and 140 deletions

View File

@@ -43,6 +43,9 @@ class Diagnostic {
Source source;
/// message is the text associated with the diagnostic.
std::string message;
/// code is the error code, for example a validation error might have the code
/// `"v-0001"`.
const char* code = nullptr;
};
/// List is a container of Diagnostic messages.

View File

@@ -16,6 +16,7 @@
#include <algorithm>
#include <sstream>
#include <vector>
#include "src/diagnostic/diagnostic.h"
#include "src/diagnostic/printer.h"
@@ -24,38 +25,29 @@ namespace tint {
namespace diag {
namespace {
template <typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& stream,
Severity severity) {
const char* to_str(Severity severity) {
switch (severity) {
case Severity::Info:
stream << "info";
break;
return "info";
case Severity::Warning:
stream << "warning";
break;
return "warning";
case Severity::Error:
stream << "error";
break;
return "error";
case Severity::Fatal:
stream << "fatal";
break;
return "fatal";
}
return stream;
return "";
}
template <typename CharT, typename Traits>
std::basic_ostream<CharT, Traits>& operator<<(
std::basic_ostream<CharT, Traits>& stream,
const Source::Location& location) {
std::string to_str(const Source::Location& location) {
std::stringstream ss;
if (location.line > 0) {
stream << location.line;
ss << location.line;
if (location.column > 0) {
stream << ":" << location.column;
ss << ":" << location.column;
}
}
return stream;
return ss.str();
}
} // namespace
@@ -134,40 +126,59 @@ void Formatter::format(const List& list, Printer* printer) const {
void Formatter::format(const Diagnostic& diag, State& state) const {
auto const& src = diag.source;
auto const& rng = src.range;
bool has_code = diag.code != nullptr && diag.code[0] != '\0';
state.set_style({Color::kDefault, true});
bool emit_colon = true;
struct TextAndColor {
std::string text;
Color color;
bool bold = false;
};
std::vector<TextAndColor> prefix;
prefix.reserve(6);
if (style_.print_file && src.file != nullptr && !src.file->path.empty()) {
state << src.file->path;
if (rng.begin.line > 0) {
state << ":" << rng.begin;
prefix.emplace_back(TextAndColor{src.file->path + ":" + to_str(rng.begin),
Color::kDefault});
} else {
prefix.emplace_back(TextAndColor{src.file->path, Color::kDefault});
}
} else if (rng.begin.line > 0) {
state << rng.begin;
} else {
// No position infomation was printed, so don't start the line with a colon.
emit_colon = false;
prefix.emplace_back(TextAndColor{to_str(rng.begin), Color::kDefault});
}
Color severity_color = Color::kDefault;
switch (diag.severity) {
case Severity::Warning:
severity_color = Color::kYellow;
break;
case Severity::Error:
case Severity::Fatal:
severity_color = Color::kRed;
break;
default:
break;
}
if (style_.print_severity) {
switch (diag.severity) {
case Severity::Warning:
state.set_style({Color::kYellow, true});
break;
case Severity::Error:
case Severity::Fatal:
state.set_style({Color::kRed, true});
break;
default:
break;
prefix.emplace_back(
TextAndColor{to_str(diag.severity), severity_color, true});
}
if (has_code) {
prefix.emplace_back(TextAndColor{diag.code, severity_color});
}
for (size_t i = 0; i < prefix.size(); i++) {
if (i > 0) {
state << " ";
}
state << " " << diag.severity << ": ";
// A colon was just printed, don't repeat it.
emit_colon = false;
state.set_style({prefix[i].color, prefix[i].bold});
state << prefix[i].text;
}
state.set_style({Color::kDefault, true});
if (emit_colon) {
if (!prefix.empty()) {
state << ": ";
}
state << diag.message;

View File

@@ -37,7 +37,8 @@ class DiagFormatterTest : public testing::Test {
Diagnostic diag_warn{Severity::Warning,
Source{Source::Range{{2, 14}, {2, 18}}, &file}, "grrr"};
Diagnostic diag_err{Severity::Error,
Source{Source::Range{{3, 16}, {3, 21}}, &file}, "hiss"};
Source{Source::Range{{3, 16}, {3, 21}}, &file}, "hiss",
"abc123"};
Diagnostic diag_fatal{Severity::Fatal,
Source{Source::Range{{4, 16}, {4, 19}}, &file},
"nothing"};
@@ -48,7 +49,7 @@ TEST_F(DiagFormatterTest, Simple) {
auto got = fmt.format(List{diag_info, diag_warn, diag_err, diag_fatal});
auto* expect = R"(1:14: purr
2:14: grrr
3:16: hiss
3:16 abc123: hiss
4:16: nothing)";
ASSERT_EQ(expect, got);
}
@@ -66,7 +67,7 @@ TEST_F(DiagFormatterTest, WithFile) {
auto got = fmt.format(List{diag_info, diag_warn, diag_err, diag_fatal});
auto* expect = R"(file.name:1:14: purr
file.name:2:14: grrr
file.name:3:16: hiss
file.name:3:16 abc123: hiss
file.name:4:16: nothing)";
ASSERT_EQ(expect, got);
}
@@ -76,7 +77,7 @@ TEST_F(DiagFormatterTest, WithSeverity) {
auto got = fmt.format(List{diag_info, diag_warn, diag_err, diag_fatal});
auto* expect = R"(1:14 info: purr
2:14 warning: grrr
3:16 error: hiss
3:16 error abc123: hiss
4:16 fatal: nothing)";
ASSERT_EQ(expect, got);
}
@@ -92,7 +93,7 @@ the cat says meow
the dog says woof
^^^^
3:16: hiss
3:16 abc123: hiss
the snake says quack
^^^^^
@@ -114,7 +115,7 @@ file.name:2:14 warning: grrr
the dog says woof
^^^^
file.name:3:16 error: hiss
file.name:3:16 error abc123: hiss
the snake says quack
^^^^^