Skip to content

Commit bdd754c

Browse files
committed
Also adding OutputEventHandler to add another type that has more complex usage.
Directly setting the event handlers on the DAP object and using the previous naming convention of 'Send<event>' instead of 'on<event>'.
1 parent ab4e9d8 commit bdd754c

17 files changed

+317
-183
lines changed

lldb/tools/lldb-dap/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ add_lldb_tool(lldb-dap
3939

4040
Events/ExitedEventHandler.cpp
4141
Events/ProcessEventHandler.cpp
42+
Events/OutputEventHandler.cpp
4243

4344
Handler/ResponseHandler.cpp
4445
Handler/AttachRequestHandler.cpp

lldb/tools/lldb-dap/DAP.cpp

Lines changed: 18 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,8 @@ DAP::DAP(llvm::StringRef path, std::ofstream *log,
8383
configuration_done_sent(false), waiting_for_run_in_terminal(false),
8484
progress_event_reporter(
8585
[&](const ProgressEvent &event) { SendJSON(event.ToJSON()); }),
86-
reverse_request_seq(0), repl_mode(default_repl_mode),
87-
onExited(ExitedEventHandler(*this)),
88-
onProcess(ProcessEventHandler(*this)) {}
86+
reverse_request_seq(0), repl_mode(default_repl_mode), SendExited(*this),
87+
SendProcess(*this), SendOutput(*this) {}
8988

9089
DAP::~DAP() = default;
9190

@@ -205,12 +204,12 @@ llvm::Error DAP::ConfigureIO(std::FILE *overrideOut, std::FILE *overrideErr) {
205204
in = lldb::SBFile(std::fopen(DEV_NULL, "r"), /*transfer_ownership=*/true);
206205

207206
if (auto Error = out.RedirectTo(overrideOut, [this](llvm::StringRef output) {
208-
SendOutput(OutputType::Stdout, output);
207+
SendOutput(output, OutputCategory::Stdout);
209208
}))
210209
return Error;
211210

212211
if (auto Error = err.RedirectTo(overrideErr, [this](llvm::StringRef output) {
213-
SendOutput(OutputType::Stderr, output);
212+
SendOutput(output, OutputCategory::Stderr);
214213
}))
215214
return Error;
216215

@@ -249,103 +248,6 @@ void DAP::Send(const protocol::Message &message) {
249248
transport.GetClientName());
250249
}
251250

252-
// "OutputEvent": {
253-
// "allOf": [ { "$ref": "#/definitions/Event" }, {
254-
// "type": "object",
255-
// "description": "Event message for 'output' event type. The event
256-
// indicates that the target has produced some output.",
257-
// "properties": {
258-
// "event": {
259-
// "type": "string",
260-
// "enum": [ "output" ]
261-
// },
262-
// "body": {
263-
// "type": "object",
264-
// "properties": {
265-
// "category": {
266-
// "type": "string",
267-
// "description": "The output category. If not specified,
268-
// 'console' is assumed.",
269-
// "_enum": [ "console", "stdout", "stderr", "telemetry" ]
270-
// },
271-
// "output": {
272-
// "type": "string",
273-
// "description": "The output to report."
274-
// },
275-
// "variablesReference": {
276-
// "type": "number",
277-
// "description": "If an attribute 'variablesReference' exists
278-
// and its value is > 0, the output contains
279-
// objects which can be retrieved by passing
280-
// variablesReference to the VariablesRequest."
281-
// },
282-
// "source": {
283-
// "$ref": "#/definitions/Source",
284-
// "description": "An optional source location where the output
285-
// was produced."
286-
// },
287-
// "line": {
288-
// "type": "integer",
289-
// "description": "An optional source location line where the
290-
// output was produced."
291-
// },
292-
// "column": {
293-
// "type": "integer",
294-
// "description": "An optional source location column where the
295-
// output was produced."
296-
// },
297-
// "data": {
298-
// "type":["array","boolean","integer","null","number","object",
299-
// "string"],
300-
// "description": "Optional data to report. For the 'telemetry'
301-
// category the data will be sent to telemetry, for
302-
// the other categories the data is shown in JSON
303-
// format."
304-
// }
305-
// },
306-
// "required": ["output"]
307-
// }
308-
// },
309-
// "required": [ "event", "body" ]
310-
// }]
311-
// }
312-
void DAP::SendOutput(OutputType o, const llvm::StringRef output) {
313-
if (output.empty())
314-
return;
315-
316-
const char *category = nullptr;
317-
switch (o) {
318-
case OutputType::Console:
319-
category = "console";
320-
break;
321-
case OutputType::Stdout:
322-
category = "stdout";
323-
break;
324-
case OutputType::Stderr:
325-
category = "stderr";
326-
break;
327-
case OutputType::Telemetry:
328-
category = "telemetry";
329-
break;
330-
}
331-
332-
// Send each line of output as an individual event, including the newline if
333-
// present.
334-
::size_t idx = 0;
335-
do {
336-
::size_t end = output.find('\n', idx);
337-
if (end == llvm::StringRef::npos)
338-
end = output.size() - 1;
339-
llvm::json::Object event(CreateEventObject("output"));
340-
llvm::json::Object body;
341-
body.try_emplace("category", category);
342-
EmplaceSafeString(body, "output", output.slice(idx, end + 1).str());
343-
event.try_emplace("body", std::move(body));
344-
SendJSON(llvm::json::Value(std::move(event)));
345-
idx = end + 1;
346-
} while (idx < output.size());
347-
}
348-
349251
// interface ProgressStartEvent extends Event {
350252
// event: 'progressStart';
351253
//
@@ -444,16 +346,17 @@ void DAP::SendProgressEvent(uint64_t progress_id, const char *message,
444346
progress_event_reporter.Push(progress_id, message, completed, total);
445347
}
446348

447-
void __attribute__((format(printf, 3, 4)))
448-
DAP::SendFormattedOutput(OutputType o, const char *format, ...) {
449-
char buffer[1024];
450-
va_list args;
451-
va_start(args, format);
452-
int actual_length = vsnprintf(buffer, sizeof(buffer), format, args);
453-
va_end(args);
454-
SendOutput(
455-
o, llvm::StringRef(buffer, std::min<int>(actual_length, sizeof(buffer))));
456-
}
349+
// void __attribute__((format(printf, 3, 4)))
350+
// DAP::SendFormattedOutput(OutputType o, const char *format, ...) {
351+
// char buffer[1024];
352+
// va_list args;
353+
// va_start(args, format);
354+
// int actual_length = vsnprintf(buffer, sizeof(buffer), format, args);
355+
// va_end(args);
356+
// SendOutput(
357+
// o, llvm::StringRef(buffer, std::min<int>(actual_length,
358+
// sizeof(buffer))));
359+
// }
457360

458361
ExceptionBreakpoint *DAP::GetExceptionBPFromStopReason(lldb::SBThread &thread) {
459362
const auto num = thread.GetStopReasonDataCount();
@@ -567,7 +470,7 @@ bool DAP::RunLLDBCommands(llvm::StringRef prefix,
567470
bool required_command_failed = false;
568471
std::string output =
569472
::RunLLDBCommands(debugger, prefix, commands, required_command_failed);
570-
SendOutput(OutputType::Console, output);
473+
SendOutput(output);
571474
return !required_command_failed;
572475
}
573476

@@ -1044,8 +947,7 @@ void DAP::SetFrameFormat(llvm::StringRef format) {
1044947
lldb::SBError error;
1045948
frame_format = lldb::SBFormat(format.str().c_str(), error);
1046949
if (error.Fail()) {
1047-
SendOutput(OutputType::Console,
1048-
llvm::formatv(
950+
SendOutput(llvm::formatv(
1049951
"The provided frame format '{0}' couldn't be parsed: {1}\n",
1050952
format, error.GetCString())
1051953
.str());
@@ -1058,8 +960,7 @@ void DAP::SetThreadFormat(llvm::StringRef format) {
1058960
lldb::SBError error;
1059961
thread_format = lldb::SBFormat(format.str().c_str(), error);
1060962
if (error.Fail()) {
1061-
SendOutput(OutputType::Console,
1062-
llvm::formatv(
963+
SendOutput(llvm::formatv(
1063964
"The provided thread format '{0}' couldn't be parsed: {1}\n",
1064965
format, error.GetCString())
1065966
.str());

lldb/tools/lldb-dap/DAP.h

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLDB_TOOLS_LLDB_DAP_DAP_H
1111

1212
#include "DAPForward.h"
13+
#include "Events/EventHandler.h"
1314
#include "ExceptionBreakpoint.h"
1415
#include "FunctionBreakpoint.h"
1516
#include "InstructionBreakpoint.h"
@@ -58,11 +59,6 @@ typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
5859
typedef llvm::DenseMap<lldb::addr_t, InstructionBreakpoint>
5960
InstructionBreakpointMap;
6061

61-
/// A debug adapter initiated event.
62-
template <typename... Args> using OutgoingEvent = std::function<void(Args...)>;
63-
64-
enum class OutputType { Console, Stdout, Stderr, Telemetry };
65-
6662
/// Buffer size for handling output events.
6763
constexpr uint64_t OutputBufferSize = (1u << 12);
6864

@@ -236,11 +232,13 @@ struct DAP {
236232
/// Typed Events Handlers
237233
/// @{
238234

239-
/// onExited sends an event that the debuggee has exited.
240-
OutgoingEvent<> onExited;
241-
/// onProcess sends an event that indicates that the debugger has begun
242-
/// debugging a new process.
243-
OutgoingEvent<> onProcess;
235+
/// Sends an event that the debuggee has exited.
236+
ExitedEventHandler SendExited;
237+
/// Sends an event that indicates that the debugger has begun debugging a new
238+
/// process.
239+
ProcessEventHandler SendProcess;
240+
/// Sends an event that indicates the target has produced some output.
241+
OutputEventHandler SendOutput;
244242

245243
/// @}
246244

@@ -263,14 +261,9 @@ struct DAP {
263261
/// Send the given message to the client
264262
void Send(const protocol::Message &message);
265263

266-
void SendOutput(OutputType o, const llvm::StringRef output);
267-
268264
void SendProgressEvent(uint64_t progress_id, const char *message,
269265
uint64_t completed, uint64_t total);
270266

271-
void __attribute__((format(printf, 3, 4)))
272-
SendFormattedOutput(OutputType o, const char *format, ...);
273-
274267
static int64_t GetNextSourceReference();
275268

276269
ExceptionBreakpoint *GetExceptionBPFromStopReason(lldb::SBThread &thread);

lldb/tools/lldb-dap/EventHelper.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "EventHelper.h"
1010
#include "DAP.h"
11+
#include "Events/EventHandler.h"
1112
#include "JSONUtils.h"
1213
#include "LLDBUtils.h"
1314
#include "lldb/API/SBFileSpec.h"
@@ -128,9 +129,9 @@ void SendStdOutStdErr(DAP &dap, lldb::SBProcess &process) {
128129
char buffer[OutputBufferSize];
129130
size_t count;
130131
while ((count = process.GetSTDOUT(buffer, sizeof(buffer))) > 0)
131-
dap.SendOutput(OutputType::Stdout, llvm::StringRef(buffer, count));
132+
dap.SendOutput(llvm::StringRef(buffer, count), OutputCategory::Stdout);
132133
while ((count = process.GetSTDERR(buffer, sizeof(buffer))) > 0)
133-
dap.SendOutput(OutputType::Stderr, llvm::StringRef(buffer, count));
134+
dap.SendOutput(llvm::StringRef(buffer, count), OutputCategory::Stderr);
134135
}
135136

136137
// Send a "continued" event to indicate the process is in the running state.

lldb/tools/lldb-dap/Events/EventHandler.h

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,47 +9,51 @@
99
#ifndef LLDB_TOOLS_LLDB_DAP_EVENTS_EVENT_HANDLER
1010
#define LLDB_TOOLS_LLDB_DAP_EVENTS_EVENT_HANDLER
1111

12-
#include "DAP.h"
13-
#include "Protocol/ProtocolBase.h"
12+
#include "DAPForward.h"
1413
#include "Protocol/ProtocolEvents.h"
15-
#include "lldb/API/SBProcess.h"
14+
#include "llvm/ADT/StringRef.h"
1615

1716
namespace lldb_dap {
1817

19-
template <typename Body, typename... Args> class BaseEventHandler {
18+
/// An event handler for triggering DAP events.
19+
class EventHandler {
2020
public:
21-
BaseEventHandler(DAP &dap) : dap(dap) {}
22-
23-
virtual ~BaseEventHandler() = default;
24-
25-
virtual llvm::StringLiteral getEvent() const = 0;
26-
virtual Body Handler(Args...) const = 0;
27-
28-
void operator()(Args... args) const {
29-
Body body = Handler(args...);
30-
protocol::Event event{/*event=*/getEvent().str(), /*body=*/std::move(body)};
31-
dap.Send(event);
32-
}
21+
EventHandler(DAP &dap) : dap(dap) {}
22+
virtual ~EventHandler() = default;
3323

3424
protected:
3525
DAP &dap;
3626
};
3727

3828
/// Handler for the event indicates that the debuggee has exited and returns its
3929
/// exit code.
40-
class ExitedEventHandler : public BaseEventHandler<protocol::ExitedEventBody> {
30+
class ExitedEventHandler : public EventHandler {
31+
public:
32+
using EventHandler::EventHandler;
33+
static constexpr llvm::StringLiteral event = "exited";
34+
void operator()(lldb::SBProcess &process) const;
35+
};
36+
37+
using ProcessStartMethod = protocol::ProcessEventBody::StartMethod;
38+
39+
/// Handler for the event indicates that the debugger has begun debugging a new
40+
/// process. Either one that it has launched, or one that it has attached to.
41+
class ProcessEventHandler : public EventHandler {
4142
public:
42-
using BaseEventHandler::BaseEventHandler;
43-
llvm::StringLiteral getEvent() const override { return "exited"; }
44-
protocol::ExitedEventBody Handler() const override;
43+
using EventHandler::EventHandler;
44+
static constexpr llvm::StringLiteral event = "process";
45+
void operator()(lldb::SBTarget &target, ProcessStartMethod startMethod) const;
4546
};
4647

47-
class ProcessEventHandler
48-
: public BaseEventHandler<protocol::ProcessEventBody> {
48+
using OutputCategory = protocol::OutputEventBody::Category;
49+
50+
/// Handle for the event indicates that the target has produced some output.
51+
class OutputEventHandler : public EventHandler {
4952
public:
50-
using BaseEventHandler::BaseEventHandler;
51-
llvm::StringLiteral getEvent() const override { return "process"; }
52-
protocol::ProcessEventBody Handler() const override;
53+
using EventHandler::EventHandler;
54+
static constexpr llvm::StringLiteral event = "output";
55+
void operator()(llvm::StringRef output,
56+
OutputCategory category = OutputCategory::Console) const;
5357
};
5458

5559
} // end namespace lldb_dap

lldb/tools/lldb-dap/Events/ExitedEventHandler.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,20 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "DAP.h"
910
#include "Events/EventHandler.h"
1011
#include "lldb/API/SBProcess.h"
1112

1213
namespace lldb_dap {
1314

14-
protocol::ExitedEventBody ExitedEventHandler::Handler() const {
15+
void ExitedEventHandler::operator()(lldb::SBProcess &process) const {
16+
if (!process.IsValid())
17+
return;
18+
1519
protocol::ExitedEventBody body;
16-
body.exitCode = dap.target.GetProcess().GetExitStatus();
17-
return body;
20+
body.exitCode = process.GetExitStatus();
21+
dap.Send(protocol::Event{/*event=*/ExitedEventHandler::event.str(),
22+
/*body=*/std::move(body)});
1823
}
1924

2025
} // namespace lldb_dap

0 commit comments

Comments
 (0)