https://github.com/adrian-prantl updated https://github.com/llvm/llvm-project/pull/116727
>From 4a9a4b0346e711b596eb14ca9f92f157ae67e469 Mon Sep 17 00:00:00 2001 From: Adrian Prantl <apra...@apple.com> Date: Mon, 18 Nov 2024 17:33:10 -0800 Subject: [PATCH] [lldb] Improve rendering of inline diagnostics on the column by fixing the indentation and printing these annotations in the original order. Before a+b+c; ^ ^ ^ | | error: 3 | |note: 2b | error: 2a error: 1 After a+b+c; ^ ^ ^ | | error: 3 | error: 2a | note: 2b error: 1 --- lldb/source/Utility/DiagnosticsRendering.cpp | 35 +++++++++++-- .../Utility/DiagnosticsRenderingTest.cpp | 49 +++++++++---------- 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/lldb/source/Utility/DiagnosticsRendering.cpp b/lldb/source/Utility/DiagnosticsRendering.cpp index dfc47ac460ac9f..a20d82ad4eb678 100644 --- a/lldb/source/Utility/DiagnosticsRendering.cpp +++ b/lldb/source/Utility/DiagnosticsRendering.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Utility/DiagnosticsRendering.h" +#include <cstdint> using namespace lldb_private; using namespace lldb; @@ -98,7 +99,7 @@ void RenderDiagnosticDetails(Stream &stream, } // Sort the diagnostics. - auto sort = [](auto &ds) { + auto sort = [](std::vector<DiagnosticDetail> &ds) { std::stable_sort(ds.begin(), ds.end(), [](auto &d1, auto &d2) { auto l1 = d1.source_location.value_or(DiagnosticDetail::SourceLocation{}); auto l2 = d2.source_location.value_or(DiagnosticDetail::SourceLocation{}); @@ -130,6 +131,25 @@ void RenderDiagnosticDetails(Stream &stream, } stream << '\n'; + // Reverse the order within groups of diagnostics that are on the same column. + auto group = [](const std::vector<DiagnosticDetail> &details) { + uint16_t column = 0; + std::vector<DiagnosticDetail> result, group; + for (auto &d : details) { + if (d.source_location->column == column) { + group.push_back(d); + continue; + } + result.insert(result.end(), group.rbegin(), group.rend()); + group.clear(); + column = d.source_location->column; + group.push_back(d); + } + result.insert(result.end(), group.rbegin(), group.rend()); + return result; + }; + remaining_details = group(remaining_details); + // Work through each detail in reverse order using the vector/stack. bool did_print = false; for (auto detail = remaining_details.rbegin(); @@ -142,14 +162,19 @@ void RenderDiagnosticDetails(Stream &stream, for (auto &remaining_detail : llvm::ArrayRef(remaining_details).drop_back(1)) { uint16_t column = remaining_detail.source_location->column; - if (x_pos <= column) + // Is this a note with the same column as another diagnostic? + if (column == detail->source_location->column) + continue; + + if (column >= x_pos) { stream << std::string(column - x_pos, ' ') << vbar; - x_pos = column + 1; + x_pos = column + 1; + } } - // Print the line connecting the ^ with the error message. uint16_t column = detail->source_location->column; - if (x_pos <= column) + // Print the line connecting the ^ with the error message. + if (column >= x_pos) stream << std::string(column - x_pos, ' ') << joint << hbar << spacer; // Print a colorized string based on the message's severity type. diff --git a/lldb/unittests/Utility/DiagnosticsRenderingTest.cpp b/lldb/unittests/Utility/DiagnosticsRenderingTest.cpp index 1187f3f65f27fd..4e5e0bb7dc3552 100644 --- a/lldb/unittests/Utility/DiagnosticsRenderingTest.cpp +++ b/lldb/unittests/Utility/DiagnosticsRenderingTest.cpp @@ -29,15 +29,22 @@ TEST_F(ErrorDisplayTest, RenderStatus) { { // Test that diagnostics on the same column can be handled and all // three errors are diagnosed. - SourceLocation loc1 = {FileSpec{"a.c"}, 13, 11, 0, false, true}; - SourceLocation loc2 = {FileSpec{"a.c"}, 13, 13, 0, false, true}; + SourceLocation loc1 = {FileSpec{"a.c"}, 13, 5, 0, false, true}; + SourceLocation loc2 = {FileSpec{"a.c"}, 13, 7, 0, false, true}; + SourceLocation loc3 = {FileSpec{"a.c"}, 13, 9, 0, false, true}; std::string result = Render({DiagnosticDetail{loc1, eSeverityError, "1", "1"}, - DiagnosticDetail{loc1, eSeverityError, "2", "2"}, - DiagnosticDetail{loc2, eSeverityError, "3", "3"}}); - ASSERT_TRUE(StringRef(result).contains("error: 1")); - ASSERT_TRUE(StringRef(result).contains("error: 2")); - ASSERT_TRUE(StringRef(result).contains("error: 3")); + DiagnosticDetail{loc2, eSeverityError, "2a", "2a"}, + DiagnosticDetail{loc2, eSeverityInfo, "2b", "2b"}, + DiagnosticDetail{loc3, eSeverityError, "3", "3"}}); + llvm::SmallVector<StringRef> lines; + StringRef(result).split(lines, '\n'); + // 1234567890123 + ASSERT_EQ(lines[0], " ^ ^ ^"); + ASSERT_EQ(lines[1], " | | error: 3"); + ASSERT_EQ(lines[2], " | error: 2a"); + ASSERT_EQ(lines[3], " | note: 2b"); + ASSERT_EQ(lines[4], " error: 1"); } { // Test that diagnostics in reverse order are emitted correctly. @@ -68,16 +75,12 @@ TEST_F(ErrorDisplayTest, RenderStatus) { std::string result = Render({DiagnosticDetail{loc1, eSeverityError, "X", "X"}, DiagnosticDetail{loc2, eSeverityError, "Y", "Y"}}); - auto lines = StringRef(result).split('\n'); - auto line1 = lines.first; - lines = lines.second.split('\n'); - auto line2 = lines.first; - lines = lines.second.split('\n'); - auto line3 = lines.first; + llvm::SmallVector<StringRef> lines; + StringRef(result).split(lines, '\n'); // 1234567 - ASSERT_EQ(line1, "^~~ ^~~"); - ASSERT_EQ(line2, "| error: Y"); - ASSERT_EQ(line3, "error: X"); + ASSERT_EQ(lines[0], "^~~ ^~~"); + ASSERT_EQ(lines[1], "| error: Y"); + ASSERT_EQ(lines[2], "error: X"); } { // Test diagnostics on the same line are emitted correctly. @@ -86,15 +89,11 @@ TEST_F(ErrorDisplayTest, RenderStatus) { std::string result = Render({DiagnosticDetail{loc1, eSeverityError, "X", "X"}, DiagnosticDetail{loc2, eSeverityError, "Y", "Y"}}); - auto lines = StringRef(result).split('\n'); - auto line1 = lines.first; - lines = lines.second.split('\n'); - auto line2 = lines.first; - lines = lines.second.split('\n'); - auto line3 = lines.first; + llvm::SmallVector<StringRef> lines; + StringRef(result).split(lines, '\n'); // 1234567 - ASSERT_EQ(line1, " ^ ^"); - ASSERT_EQ(line2, " | error: Y"); - ASSERT_EQ(line3, " error: X"); + ASSERT_EQ(lines[0], " ^ ^"); + ASSERT_EQ(lines[1], " | error: Y"); + ASSERT_EQ(lines[2], " error: X"); } } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits