https://github.com/DrSergei updated https://github.com/llvm/llvm-project/pull/222906
>From e588ddf8a2cf448bec6eb4f5a76115e4ab214d39 Mon Sep 17 00:00:00 2001 From: Sergei Druzhkov <[email protected]> Date: Fri, 11 Sep 2026 10:30:43 +0300 Subject: [PATCH 1/2] [lldb-dap] Fix logpoint to breakpoint conversion --- .../lldb-dap/breakpoint/TestDAP_logpoints.py | 63 +++++++++++++++++++ lldb/tools/lldb-dap/SourceBreakpoint.cpp | 5 ++ 2 files changed, 68 insertions(+) diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py index 635387f593cf7..527b6d90314ee 100644 --- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py +++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py @@ -78,6 +78,69 @@ def test_logMessage_basic(self): ) session.continue_to_exit() + def check_logpoint_to_breakpoint_conversion(self, log_message): + session = self.build_and_create_session() + initial_stop = self.stop_at_before_loop_line(session) + loop_line = line_number("main.cpp", "// break loop") + after_loop_line = line_number("main.cpp", "// after loop") + log_prefix = "This is log message for " + + [logpoint_id, post_loop_breakpoint_id] = session.resolve_source_breakpoints( + self.main_path, + [ + SourceBreakpoint(loop_line, logMessage=log_prefix + "{i}"), + SourceBreakpoint(after_loop_line), + ], + ) + + # Change logpoint to usual breakpoint and check that id preserved. + [breakpoint_id, _] = session.resolve_source_breakpoints( + self.main_path, + [ + SourceBreakpoint(loop_line, logMessage=log_message), + SourceBreakpoint(after_loop_line), + ], + ) + self.assertEqual(breakpoint_id, logpoint_id) + + # Check that stop works as expected for updated logpoint. + loop_stop = session.continue_to_breakpoint(breakpoint_id) + frame = session.top_frame_from(loop_stop) + self.assertEqual(frame.locals["i"].value_as_int, 0) + captured = session.collect_console(after=initial_stop, until=loop_stop) + self.assertNotIn(log_prefix, captured.seen_texts) + + # Change breakpoint to logpoint back. + [restored_id, _] = session.resolve_source_breakpoints( + self.main_path, + [ + SourceBreakpoint(loop_line, logMessage=log_prefix + "{i}"), + SourceBreakpoint(after_loop_line), + ], + ) + self.assertEqual(restored_id, logpoint_id) + + # Check that logpoint prints messages. + post_loop_stop = session.continue_to_breakpoint(post_loop_breakpoint_id) + captured = session.collect_console(after=loop_stop, until=post_loop_stop) + messages = [ + line + for line in captured.seen_texts.splitlines() + if line.startswith(log_prefix) + ] + self.assertEqual(messages, [log_prefix + str(i) for i in range(1, 10)]) + session.continue_to_exit() + + @skipIfWindows + def test_logmessage_none(self): + """Tests removing logMessage restores a stopping breakpoint.""" + self.check_logpoint_to_breakpoint_conversion(None) + + @skipIfWindows + def test_logmessage_empty(self): + """Tests clearing logMessage restores a stopping breakpoint.""" + self.check_logpoint_to_breakpoint_conversion("") + @skipIfWindows def test_logmessage_advanced(self): """Tests breakpoint logmessage functionality for complex expression.""" diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp index fbc995e8a6e3f..e44ac6bfb1785 100644 --- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp +++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp @@ -281,6 +281,11 @@ lldb::SBError SourceBreakpoint::FormatLogText(llvm::StringRef text, void SourceBreakpoint::SetLogMessage() { m_log_message_parts.clear(); + if (m_log_message.empty()) { + m_bp.SetCallback(nullptr, nullptr); + return; + } + // Contains unmatched open curly braces indices. std::vector<int> unmatched_curly_braces; >From 626ad94f9743efa87761bb5c9c5a0182fcd9bf38 Mon Sep 17 00:00:00 2001 From: Sergei Druzhkov <[email protected]> Date: Fri, 11 Sep 2026 18:54:22 +0300 Subject: [PATCH 2/2] Fix review comments --- .../lldb-dap/breakpoint/TestDAP_logpoints.py | 16 ++++------------ lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp | 11 +++++++---- lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 2 +- lldb/tools/lldb-dap/SourceBreakpoint.cpp | 3 +-- lldb/unittests/DAP/ProtocolTypesTest.cpp | 11 +++++++++++ 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py index 527b6d90314ee..4d968286880db 100644 --- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py +++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_logpoints.py @@ -78,7 +78,9 @@ def test_logMessage_basic(self): ) session.continue_to_exit() - def check_logpoint_to_breakpoint_conversion(self, log_message): + @skipIfWindows + def test_logmessage_claeared(self): + """Tests removing logMessage restores a stopping breakpoint.""" session = self.build_and_create_session() initial_stop = self.stop_at_before_loop_line(session) loop_line = line_number("main.cpp", "// break loop") @@ -97,7 +99,7 @@ def check_logpoint_to_breakpoint_conversion(self, log_message): [breakpoint_id, _] = session.resolve_source_breakpoints( self.main_path, [ - SourceBreakpoint(loop_line, logMessage=log_message), + SourceBreakpoint(loop_line, logMessage=None), SourceBreakpoint(after_loop_line), ], ) @@ -131,16 +133,6 @@ def check_logpoint_to_breakpoint_conversion(self, log_message): self.assertEqual(messages, [log_prefix + str(i) for i in range(1, 10)]) session.continue_to_exit() - @skipIfWindows - def test_logmessage_none(self): - """Tests removing logMessage restores a stopping breakpoint.""" - self.check_logpoint_to_breakpoint_conversion(None) - - @skipIfWindows - def test_logmessage_empty(self): - """Tests clearing logMessage restores a stopping breakpoint.""" - self.check_logpoint_to_breakpoint_conversion("") - @skipIfWindows def test_logmessage_advanced(self): """Tests breakpoint logmessage functionality for complex expression.""" diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp index b70aeb661f3e1..fab46c75a6a4a 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp @@ -855,10 +855,13 @@ bool fromJSON(const llvm::json::Value &Params, Breakpoint &BP, bool fromJSON(const llvm::json::Value &Params, SourceBreakpoint &SB, llvm::json::Path P) { llvm::json::ObjectMapper O(Params, P); - return O && O.map("line", SB.line) && O.mapOptional("column", SB.column) && + std::optional<String> log_message; + if (!(O && O.mapOptional("logMessage", log_message))) + return false; + SB.logMessage = log_message.value_or(""); + return O.map("line", SB.line) && O.mapOptional("column", SB.column) && O.mapOptional("condition", SB.condition) && O.mapOptional("hitCondition", SB.hitCondition) && - O.mapOptional("logMessage", SB.logMessage) && O.mapOptional("mode", SB.mode); } @@ -871,8 +874,8 @@ llvm::json::Value toJSON(const SourceBreakpoint &SB) { result.insert({"condition", *SB.condition}); if (SB.hitCondition) result.insert({"hitCondition", *SB.hitCondition}); - if (SB.logMessage) - result.insert({"logMessage", *SB.logMessage}); + if (!SB.logMessage.empty()) + result.insert({"logMessage", SB.logMessage}); if (SB.mode) result.insert({"mode", *SB.mode}); diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h index 39eaeb064ccd2..2b4a32e29d809 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h @@ -689,7 +689,7 @@ struct SourceBreakpoint { /// capability `supportsLogPoints` is true. /// If either `hitCondition` or `condition` is specified, then the message /// should only be logged if those conditions are met. - std::optional<String> logMessage; + String logMessage; /// The mode of this breakpoint. If defined, this must be one of the /// `breakpointModes` the debug adapter advertised in its `Capabilities`. diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp index e44ac6bfb1785..82a07f1f99552 100644 --- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp +++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp @@ -33,8 +33,7 @@ namespace lldb_dap { SourceBreakpoint::SourceBreakpoint(DAP &dap, const protocol::SourceBreakpoint &breakpoint) : Breakpoint(dap, breakpoint.condition, breakpoint.hitCondition), - m_log_message(breakpoint.logMessage.value_or("")), - m_line(breakpoint.line), + m_log_message(breakpoint.logMessage), m_line(breakpoint.line), m_column(breakpoint.column.value_or(LLDB_INVALID_COLUMN_NUMBER)) {} llvm::Error SourceBreakpoint::SetBreakpoint(const protocol::Source &source) { diff --git a/lldb/unittests/DAP/ProtocolTypesTest.cpp b/lldb/unittests/DAP/ProtocolTypesTest.cpp index 996b6e3ec6ba5..38d8f554e3984 100644 --- a/lldb/unittests/DAP/ProtocolTypesTest.cpp +++ b/lldb/unittests/DAP/ProtocolTypesTest.cpp @@ -163,6 +163,17 @@ TEST(ProtocolTypesTest, SourceBreakpoint) { EXPECT_EQ(source_breakpoint.mode, deserialized_source_breakpoint->mode); } +TEST(ProtocolTypesTest, SourceBreakpointOptionalLogMessage) { + for (StringRef json : {R"({"line": 0, "logMessage": null})", R"({"line": 0})", + R"({"line": 0, "logMessage": ""})"}) { + Expected<SourceBreakpoint> source_breakpoint = + parse<SourceBreakpoint>(json); + ASSERT_THAT_EXPECTED(source_breakpoint, Succeeded()); + EXPECT_EQ(source_breakpoint->line, 0u); + EXPECT_TRUE(source_breakpoint->logMessage.empty()); + } +} + TEST(ProtocolTypesTest, FunctionBreakpoint) { FunctionBreakpoint function_breakpoint; function_breakpoint.name = "myFunction"; _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
