#include
#include
#include
#include
namespace {
// Strips the first character (\n)
std::string S(const std::string &s) {
return s.substr(1, s.size());
}
}
using LCompilers::diag::Diagnostic;
using LCompilers::diag::Level;
using LCompilers::diag::Stage;
using LCompilers::diag::Label;
using LCompilers::Location;
using LCompilers::LocationManager;
TEST_CASE("Error Render: no labels") {
std::string out, ref;
out = render_diagnostic_human(Diagnostic(
"Error no label",
Level::Error, Stage::Parser
), false
);
ref = S(R"""(
syntax error: Error no label
)""");
CHECK(out == ref);
out = render_diagnostic_human(Diagnostic(
"Error no label",
Level::Error, Stage::Semantic
), false
);
ref = S(R"""(
semantic error: Error no label
)""");
CHECK(out == ref);
out = render_diagnostic_human(Diagnostic(
"Error no label",
Level::Warning, Stage::Semantic
), false
);
ref = S(R"""(
warning: Error no label
)""");
CHECK(out == ref);
}
TEST_CASE("Error Render: primary/secondary labels, single line") {
// All combinations of primary error labels
std::string out, ref, input;
Location loc1, loc2, loc3;
LocationManager lm;
input = "One line text\n";
{
std::ofstream out("input.txt");
out << input;
LocationManager::FileLocations fl;
fl.in_filename = "input.txt";
lm.get_newlines(input, fl.in_newlines);
fl.out_start.push_back(0);
fl.in_start.push_back(0);
fl.in_start.push_back(input.size());
fl.out_start.push_back(input.size());
lm.files.push_back(fl);
lm.file_ends.push_back(input.size());
}
loc1.first = 4;
loc1.last = 7;
loc2.first = 9;
loc2.last = 12;
loc3.first = 0;
loc3.last = 2;
// 1 Label 1 Span
auto d = Diagnostic(
"Error with label no message",
Level::Error, Stage::Semantic, {
Label("", {loc1})
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with label no message
--> input.txt:1:5
|
1 | One line text
| ^^^^
)""");
CHECK(out == ref);
// 1 Label 2 Spans
d = Diagnostic(
"Error with label and message",
Level::Error, Stage::Semantic, {
Label("label message", {loc1, loc2})
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with label and message
--> input.txt:1:5
|
1 | One line text
| ^^^^ ^^^^ label message
)""");
CHECK(out == ref);
// 1 Label 3 Spans
d = Diagnostic(
"Error with label and message",
Level::Error, Stage::Semantic, {
Label("label message", {loc1, loc2, loc3})
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with label and message
--> input.txt:1:5
|
1 | One line text
| ^^^^ ^^^^ label message
|
1 | One line text
| ^^^ label message
)""");
CHECK(out == ref);
// 2 Label 1 Span
d = Diagnostic(
"Error with two labels and message",
Level::Error, Stage::Semantic, {
Label("label1 message", {loc1}),
Label("label2 message", {loc2})
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with two labels and message
--> input.txt:1:5
|
1 | One line text
| ^^^^ label1 message
|
1 | One line text
| ^^^^ label2 message
)""");
CHECK(out == ref);
// 3 Label 1 Span
d = Diagnostic(
"Error with two labels and message",
Level::Error, Stage::Semantic, {
Label("label1 message", {loc1}),
Label("label2 message", {loc2}),
Label("label3 message", {loc3})
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with two labels and message
--> input.txt:1:5
|
1 | One line text
| ^^^^ label1 message
|
1 | One line text
| ^^^^ label2 message
|
1 | One line text
| ^^^ label3 message
)""");
CHECK(out == ref);
// 3 Label 1 Span, one primary, two secondary
d = Diagnostic(
"Error with two labels and message",
Level::Error, Stage::Semantic, {
Label("label1 primary message", {loc1}),
Label("label2 secondary message", {loc2}, false),
Label("label3 secondary message", {loc3}, false)
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with two labels and message
--> input.txt:1:5
|
1 | One line text
| ^^^^ label1 primary message
|
1 | One line text
| ~~~~ label2 secondary message
|
1 | One line text
| ~~~ label3 secondary message
)""");
CHECK(out == ref);
// 3 Label 2 Spans, secondary, primary, secondary
d = Diagnostic(
"Error with three labels and message, two spans",
Level::Error, Stage::Semantic, {
Label("label1 secondary message", {loc1, loc2}, false),
Label("label2 primary message", {loc3, loc2}),
Label("label3 secondary message", {loc3}, false)
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with three labels and message, two spans
--> input.txt:1:5
|
1 | One line text
| ~~~~ ~~~~ label1 secondary message
|
1 | One line text
| ^^^ ^^^^ label2 primary message
|
1 | One line text
| ~~~ label3 secondary message
)""");
CHECK(out == ref);
}
TEST_CASE("Error Render: primary/secondary labels, multi line") {
std::string out, ref, input;
Location loc1, loc2, loc3;
LocationManager lm;
input = "One line text\nSecond line text\nThird line text\n";
{
std::ofstream out("input.txt");
out << input;
LocationManager::FileLocations fl;
fl.in_filename = "input.txt";
lm.get_newlines(input, fl.in_newlines);
fl.out_start.push_back(0);
fl.in_start.push_back(0);
fl.in_start.push_back(input.size());
fl.out_start.push_back(input.size());
lm.files.push_back(fl);
lm.file_ends.push_back(input.size());
}
loc1.first = 4; // 1 line
loc1.last = 24; // 2 line
loc2.first = 9; // 1 text
loc2.last = 35; // 3 Third
loc3.first = 0; // 1 One
loc3.last = 2; // 3 Third
// 1 Label 1 Span
auto d = Diagnostic(
"Error with label no message",
Level::Error, Stage::Semantic, {
Label("Multilines", {loc1})
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with label no message
--> input.txt:1:5 - 2:11
|
1 | One line text
| ^^^^^^^^^...
...
|
2 | Second line text
| ...^^^^^^^^^^^ Multilines
)""");
CHECK(out == ref);
// 1 Label 2 Span
d = Diagnostic(
"Error with label, two spans",
Level::Error, Stage::Semantic, {
Label("Two spans", {loc1, loc2})
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with label, two spans
--> input.txt:1:5 - 2:11
|
1 | One line text
| ^^^^^^^^^...
...
|
2 | Second line text
| ...^^^^^^^^^^^ Two spans
|
1 | One line text
| ^^^^...
...
|
3 | Third line text
| ...^^^^^ Two spans
)""");
CHECK(out == ref);
// 1 Label 2 Span
d = Diagnostic(
"Error with label, two spans",
Level::Error, Stage::Semantic, {
Label("Two spans", {loc3, loc2})
}
);
out = render_diagnostic_human(d, lm, false, false);
ref = S(R"""(
semantic error: Error with label, two spans
--> input.txt:1:1
|
1 | One line text
| ^^^ Two spans
|
1 | One line text
| ^^^^...
...
|
3 | Third line text
| ...^^^^^ Two spans
)""");
CHECK(out == ref);
}