1089227feSAdrian Prantl #include "lldb/Utility/DiagnosticsRendering.h" 2089227feSAdrian Prantl #include "lldb/Utility/StreamString.h" 3089227feSAdrian Prantl #include "gtest/gtest.h" 4089227feSAdrian Prantl 5089227feSAdrian Prantl using namespace lldb_private; 6089227feSAdrian Prantl using namespace lldb; 7089227feSAdrian Prantl using llvm::StringRef; 8089227feSAdrian Prantl namespace { 9089227feSAdrian Prantl class ErrorDisplayTest : public ::testing::Test {}; 10089227feSAdrian Prantl 11089227feSAdrian Prantl std::string Render(std::vector<DiagnosticDetail> details) { 12089227feSAdrian Prantl StreamString stream; 13089227feSAdrian Prantl RenderDiagnosticDetails(stream, 0, true, details); 14089227feSAdrian Prantl return stream.GetData(); 15089227feSAdrian Prantl } 16089227feSAdrian Prantl } // namespace 17089227feSAdrian Prantl 18089227feSAdrian Prantl TEST_F(ErrorDisplayTest, RenderStatus) { 19889e6ad2SAdrian Prantl using SourceLocation = DiagnosticDetail::SourceLocation; 20089227feSAdrian Prantl { 21889e6ad2SAdrian Prantl SourceLocation inline_loc; 22889e6ad2SAdrian Prantl inline_loc.in_user_input = true; 23089227feSAdrian Prantl std::string result = 24089227feSAdrian Prantl Render({DiagnosticDetail{inline_loc, eSeverityError, "foo", ""}}); 25089227feSAdrian Prantl ASSERT_TRUE(StringRef(result).contains("error:")); 26089227feSAdrian Prantl ASSERT_TRUE(StringRef(result).contains("foo")); 27089227feSAdrian Prantl } 28889e6ad2SAdrian Prantl 29889e6ad2SAdrian Prantl { 30889e6ad2SAdrian Prantl // Test that diagnostics on the same column can be handled and all 31889e6ad2SAdrian Prantl // three errors are diagnosed. 32*6b4f6754SAdrian Prantl SourceLocation loc1 = {FileSpec{"a.c"}, 13, 5, 0, false, true}; 33*6b4f6754SAdrian Prantl SourceLocation loc2 = {FileSpec{"a.c"}, 13, 7, 0, false, true}; 34*6b4f6754SAdrian Prantl SourceLocation loc3 = {FileSpec{"a.c"}, 13, 9, 0, false, true}; 35889e6ad2SAdrian Prantl std::string result = 36889e6ad2SAdrian Prantl Render({DiagnosticDetail{loc1, eSeverityError, "1", "1"}, 37*6b4f6754SAdrian Prantl DiagnosticDetail{loc2, eSeverityError, "2a", "2a"}, 38*6b4f6754SAdrian Prantl DiagnosticDetail{loc2, eSeverityInfo, "2b", "2b"}, 39*6b4f6754SAdrian Prantl DiagnosticDetail{loc3, eSeverityError, "3", "3"}}); 40*6b4f6754SAdrian Prantl llvm::SmallVector<StringRef> lines; 41*6b4f6754SAdrian Prantl StringRef(result).split(lines, '\n'); 42*6b4f6754SAdrian Prantl // 1234567890123 43*6b4f6754SAdrian Prantl ASSERT_EQ(lines[0], " ^ ^ ^"); 44*6b4f6754SAdrian Prantl ASSERT_EQ(lines[1], " | | error: 3"); 45*6b4f6754SAdrian Prantl ASSERT_EQ(lines[2], " | error: 2a"); 46*6b4f6754SAdrian Prantl ASSERT_EQ(lines[3], " | note: 2b"); 47*6b4f6754SAdrian Prantl ASSERT_EQ(lines[4], " error: 1"); 48889e6ad2SAdrian Prantl } 49889e6ad2SAdrian Prantl { 50889e6ad2SAdrian Prantl // Test that diagnostics in reverse order are emitted correctly. 51889e6ad2SAdrian Prantl SourceLocation loc1 = {FileSpec{"a.c"}, 1, 20, 0, false, true}; 52889e6ad2SAdrian Prantl SourceLocation loc2 = {FileSpec{"a.c"}, 2, 10, 0, false, true}; 53889e6ad2SAdrian Prantl std::string result = 54889e6ad2SAdrian Prantl Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"}, 55889e6ad2SAdrian Prantl DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}}); 5674e1554dSAdrian Prantl // Unintuitively the later diagnostic appears first in the string: 5774e1554dSAdrian Prantl // ^ ^ 5874e1554dSAdrian Prantl // | second 5974e1554dSAdrian Prantl // first 6074e1554dSAdrian Prantl ASSERT_GT(StringRef(result).find("Y"), StringRef(result).find("X")); 61889e6ad2SAdrian Prantl } 62889e6ad2SAdrian Prantl { 63889e6ad2SAdrian Prantl // Test that diagnostics in reverse order are emitted correctly. 6474e1554dSAdrian Prantl SourceLocation loc1 = {FileSpec{"a.c"}, 1, 10, 0, false, true}; 65889e6ad2SAdrian Prantl SourceLocation loc2 = {FileSpec{"a.c"}, 1, 20, 0, false, true}; 66889e6ad2SAdrian Prantl std::string result = 67889e6ad2SAdrian Prantl Render({DiagnosticDetail{loc2, eSeverityError, "X", "X"}, 68889e6ad2SAdrian Prantl DiagnosticDetail{loc1, eSeverityError, "Y", "Y"}}); 6974e1554dSAdrian Prantl ASSERT_GT(StringRef(result).find("Y"), StringRef(result).find("X")); 70889e6ad2SAdrian Prantl } 718046f15dSAdrian Prantl { 728046f15dSAdrian Prantl // Test that range diagnostics are emitted correctly. 738046f15dSAdrian Prantl SourceLocation loc1 = {FileSpec{"a.c"}, 1, 1, 3, false, true}; 748046f15dSAdrian Prantl SourceLocation loc2 = {FileSpec{"a.c"}, 1, 5, 3, false, true}; 758046f15dSAdrian Prantl std::string result = 768046f15dSAdrian Prantl Render({DiagnosticDetail{loc1, eSeverityError, "X", "X"}, 778046f15dSAdrian Prantl DiagnosticDetail{loc2, eSeverityError, "Y", "Y"}}); 78*6b4f6754SAdrian Prantl llvm::SmallVector<StringRef> lines; 79*6b4f6754SAdrian Prantl StringRef(result).split(lines, '\n'); 808046f15dSAdrian Prantl // 1234567 81*6b4f6754SAdrian Prantl ASSERT_EQ(lines[0], "^~~ ^~~"); 82*6b4f6754SAdrian Prantl ASSERT_EQ(lines[1], "| error: Y"); 83*6b4f6754SAdrian Prantl ASSERT_EQ(lines[2], "error: X"); 848b2dff96SAdrian Prantl } 858b2dff96SAdrian Prantl { 868b2dff96SAdrian Prantl // Test diagnostics on the same line are emitted correctly. 878b2dff96SAdrian Prantl SourceLocation loc1 = {FileSpec{"a.c"}, 1, 2, 0, false, true}; 888b2dff96SAdrian Prantl SourceLocation loc2 = {FileSpec{"a.c"}, 1, 6, 0, false, true}; 898b2dff96SAdrian Prantl std::string result = 908b2dff96SAdrian Prantl Render({DiagnosticDetail{loc1, eSeverityError, "X", "X"}, 918b2dff96SAdrian Prantl DiagnosticDetail{loc2, eSeverityError, "Y", "Y"}}); 92*6b4f6754SAdrian Prantl llvm::SmallVector<StringRef> lines; 93*6b4f6754SAdrian Prantl StringRef(result).split(lines, '\n'); 948b2dff96SAdrian Prantl // 1234567 95*6b4f6754SAdrian Prantl ASSERT_EQ(lines[0], " ^ ^"); 96*6b4f6754SAdrian Prantl ASSERT_EQ(lines[1], " | error: Y"); 97*6b4f6754SAdrian Prantl ASSERT_EQ(lines[2], " error: X"); 988046f15dSAdrian Prantl } 99089227feSAdrian Prantl } 100