See More

#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); }