Skip to content

Commit 9246649

Browse files
committed
When sending a DAP Output Event break each message into separate lines.
Previously, when output like `"hello\nworld\n"` was produced by lldb (or the process) the message would be sent as a single Output event. By being a single event this causes VS Code to treat this as a single message in the console when handling displaying and filtering in the Debug Console. Instead, with these changes we send each line as its own event. This results in VS Code representing each line of output from lldb-dap as an individual output message.
1 parent a16f0dc commit 9246649

File tree

5 files changed

+72
-6
lines changed

5 files changed

+72
-6
lines changed

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,11 @@ def collect_console(self, timeout_secs, pattern=None):
202202
"console", timeout_secs=timeout_secs, pattern=pattern
203203
)
204204

205+
def collect_stdout(self, timeout_secs, pattern=None):
206+
return self.dap_server.collect_output(
207+
"stdout", timeout_secs=timeout_secs, pattern=pattern
208+
)
209+
205210
def get_local_as_int(self, name, threadId=None):
206211
value = self.dap_server.get_local_variable_value(name, threadId=threadId)
207212
# 'value' may have the variable value and summary.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
C_SOURCES := main.c
2+
3+
include Makefile.rules
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
Test lldb-dap output events
3+
"""
4+
5+
import dap_server
6+
from lldbsuite.test.decorators import *
7+
from lldbsuite.test.lldbtest import *
8+
from lldbsuite.test import lldbutil
9+
import lldbdap_testcase
10+
import re
11+
12+
13+
class TestDAP_output(lldbdap_testcase.DAPTestCaseBase):
14+
def test_output(self):
15+
program = self.getBuildArtifact("a.out")
16+
self.build_and_launch(program)
17+
source = "main.c"
18+
main_source_path = self.getSourcePath(source)
19+
lines = [line_number(source, "// breakpoint 1")]
20+
breakpoint_ids = self.set_source_breakpoints(source, lines)
21+
self.continue_to_breakpoints(breakpoint_ids)
22+
23+
output = self.collect_stdout(
24+
timeout_secs=1.0,
25+
pattern="abcdef"
26+
)
27+
self.assertTrue(output and len(output) > 0, "expect no program output")
28+
29+
self.continue_to_exit()
30+
31+
output += self.get_stdout(timeout=lldbdap_testcase.DAPTestCaseBase.timeoutval)
32+
self.assertTrue(output and len(output) > 0, "expect no program output")
33+
self.assertIn(
34+
"abcdefghi\r\nhello world\r\n",
35+
output,
36+
'full output not found in: ' + output
37+
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <unistd.h>
4+
5+
int main() {
6+
printf("abc");
7+
printf("def");
8+
printf("ghi\n");
9+
printf("hello world\n"); // breakpoint 1
10+
return 0;
11+
}

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,6 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) {
294294
if (output.empty())
295295
return;
296296

297-
llvm::json::Object event(CreateEventObject("output"));
298-
llvm::json::Object body;
299297
const char *category = nullptr;
300298
switch (o) {
301299
case OutputType::Console:
@@ -311,10 +309,22 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) {
311309
category = "telemetry";
312310
break;
313311
}
314-
body.try_emplace("category", category);
315-
EmplaceSafeString(body, "output", output.str());
316-
event.try_emplace("body", std::move(body));
317-
SendJSON(llvm::json::Value(std::move(event)));
312+
313+
// Send each line of output as an individual event, including the newline if
314+
// present.
315+
::size_t idx = 0;
316+
do {
317+
::size_t end = output.find('\n', idx);
318+
if (end == llvm::StringRef::npos)
319+
end = output.size() - 1;
320+
llvm::json::Object event(CreateEventObject("output"));
321+
llvm::json::Object body;
322+
body.try_emplace("category", category);
323+
EmplaceSafeString(body, "output", output.slice(idx, end + 1).str());
324+
event.try_emplace("body", std::move(body));
325+
SendJSON(llvm::json::Value(std::move(event)));
326+
idx = end + 1;
327+
} while (idx < output.size());
318328
}
319329

320330
// interface ProgressStartEvent extends Event {

0 commit comments

Comments
 (0)