Skip to content

Commit 1cc60c1

Browse files
committed
Migrating breakpointLocations request to use typed RequestHandler
1 parent 367b91a commit 1cc60c1

File tree

7 files changed

+125
-139
lines changed

7 files changed

+125
-139
lines changed

lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp

+20-136
Original file line numberDiff line numberDiff line change
@@ -9,136 +9,22 @@
99
#include "DAP.h"
1010
#include "JSONUtils.h"
1111
#include "RequestHandler.h"
12+
#include <vector>
1213

1314
namespace lldb_dap {
1415

15-
// "BreakpointLocationsRequest": {
16-
// "allOf": [ { "$ref": "#/definitions/Request" }, {
17-
// "type": "object",
18-
// "description": "The `breakpointLocations` request returns all possible
19-
// locations for source breakpoints in a given range.\nClients should only
20-
// call this request if the corresponding capability
21-
// `supportsBreakpointLocationsRequest` is true.",
22-
// "properties": {
23-
// "command": {
24-
// "type": "string",
25-
// "enum": [ "breakpointLocations" ]
26-
// },
27-
// "arguments": {
28-
// "$ref": "#/definitions/BreakpointLocationsArguments"
29-
// }
30-
// },
31-
// "required": [ "command" ]
32-
// }]
33-
// },
34-
// "BreakpointLocationsArguments": {
35-
// "type": "object",
36-
// "description": "Arguments for `breakpointLocations` request.",
37-
// "properties": {
38-
// "source": {
39-
// "$ref": "#/definitions/Source",
40-
// "description": "The source location of the breakpoints; either
41-
// `source.path` or `source.sourceReference` must be specified."
42-
// },
43-
// "line": {
44-
// "type": "integer",
45-
// "description": "Start line of range to search possible breakpoint
46-
// locations in. If only the line is specified, the request returns all
47-
// possible locations in that line."
48-
// },
49-
// "column": {
50-
// "type": "integer",
51-
// "description": "Start position within `line` to search possible
52-
// breakpoint locations in. It is measured in UTF-16 code units and the
53-
// client capability `columnsStartAt1` determines whether it is 0- or
54-
// 1-based. If no column is given, the first position in the start line is
55-
// assumed."
56-
// },
57-
// "endLine": {
58-
// "type": "integer",
59-
// "description": "End line of range to search possible breakpoint
60-
// locations in. If no end line is given, then the end line is assumed to
61-
// be the start line."
62-
// },
63-
// "endColumn": {
64-
// "type": "integer",
65-
// "description": "End position within `endLine` to search possible
66-
// breakpoint locations in. It is measured in UTF-16 code units and the
67-
// client capability `columnsStartAt1` determines whether it is 0- or
68-
// 1-based. If no end column is given, the last position in the end line
69-
// is assumed."
70-
// }
71-
// },
72-
// "required": [ "source", "line" ]
73-
// },
74-
// "BreakpointLocationsResponse": {
75-
// "allOf": [ { "$ref": "#/definitions/Response" }, {
76-
// "type": "object",
77-
// "description": "Response to `breakpointLocations` request.\nContains
78-
// possible locations for source breakpoints.",
79-
// "properties": {
80-
// "body": {
81-
// "type": "object",
82-
// "properties": {
83-
// "breakpoints": {
84-
// "type": "array",
85-
// "items": {
86-
// "$ref": "#/definitions/BreakpointLocation"
87-
// },
88-
// "description": "Sorted set of possible breakpoint locations."
89-
// }
90-
// },
91-
// "required": [ "breakpoints" ]
92-
// }
93-
// },
94-
// "required": [ "body" ]
95-
// }]
96-
// },
97-
// "BreakpointLocation": {
98-
// "type": "object",
99-
// "description": "Properties of a breakpoint location returned from the
100-
// `breakpointLocations` request.",
101-
// "properties": {
102-
// "line": {
103-
// "type": "integer",
104-
// "description": "Start line of breakpoint location."
105-
// },
106-
// "column": {
107-
// "type": "integer",
108-
// "description": "The start position of a breakpoint location. Position
109-
// is measured in UTF-16 code units and the client capability
110-
// `columnsStartAt1` determines whether it is 0- or 1-based."
111-
// },
112-
// "endLine": {
113-
// "type": "integer",
114-
// "description": "The end line of breakpoint location if the location
115-
// covers a range."
116-
// },
117-
// "endColumn": {
118-
// "type": "integer",
119-
// "description": "The end position of a breakpoint location (if the
120-
// location covers a range). Position is measured in UTF-16 code units and
121-
// the client capability `columnsStartAt1` determines whether it is 0- or
122-
// 1-based."
123-
// }
124-
// },
125-
// "required": [ "line" ]
126-
// },
127-
void BreakpointLocationsRequestHandler::operator()(
128-
const llvm::json::Object &request) const {
129-
llvm::json::Object response;
130-
FillResponse(request, response);
131-
auto *arguments = request.getObject("arguments");
132-
auto *source = arguments->getObject("source");
133-
std::string path = GetString(source, "path").value_or("").str();
134-
const auto start_line = GetInteger<uint64_t>(arguments, "line")
135-
.value_or(LLDB_INVALID_LINE_NUMBER);
136-
const auto start_column = GetInteger<uint64_t>(arguments, "column")
137-
.value_or(LLDB_INVALID_COLUMN_NUMBER);
138-
const auto end_line =
139-
GetInteger<uint64_t>(arguments, "endLine").value_or(start_line);
140-
const auto end_column = GetInteger<uint64_t>(arguments, "endColumn")
141-
.value_or(std::numeric_limits<uint64_t>::max());
16+
/// The `breakpointLocations` request returns all possible locations for source
17+
/// breakpoints in a given range. Clients should only call this request if the
18+
/// corresponding capability `supportsBreakpointLocationsRequest` is true.
19+
llvm::Expected<protocol::BreakpointLocationsResponseBody>
20+
BreakpointLocationsRequestHandler::Run(
21+
const protocol::BreakpointLocationsArguments &args) const {
22+
std::string path = args.source.path.value_or("");
23+
uint32_t start_line = args.line;
24+
uint32_t start_column = args.column.value_or(LLDB_INVALID_COLUMN_NUMBER);
25+
uint32_t end_line = args.endLine.value_or(start_line);
26+
uint32_t end_column =
27+
args.endColumn.value_or(std::numeric_limits<uint32_t>::max());
14228

14329
lldb::SBFileSpec file_spec(path.c_str(), true);
14430
lldb::SBSymbolContextList compile_units =
@@ -191,18 +77,16 @@ void BreakpointLocationsRequestHandler::operator()(
19177
std::sort(locations.begin(), locations.end());
19278
locations.erase(llvm::unique(locations), locations.end());
19379

194-
llvm::json::Array locations_json;
80+
std::vector<protocol::BreakpointLocation> breakpoint_locations;
19581
for (auto &l : locations) {
196-
llvm::json::Object location;
197-
location.try_emplace("line", l.first);
198-
location.try_emplace("column", l.second);
199-
locations_json.emplace_back(std::move(location));
82+
protocol::BreakpointLocation lc;
83+
lc.line = l.first;
84+
lc.column = l.second;
85+
breakpoint_locations.push_back(std::move(lc));
20086
}
20187

202-
llvm::json::Object body;
203-
body.try_emplace("breakpoints", std::move(locations_json));
204-
response.try_emplace("body", std::move(body));
205-
dap.SendJSON(llvm::json::Value(std::move(response)));
88+
return protocol::BreakpointLocationsResponseBody{
89+
/*breakpoints=*/std::move(breakpoint_locations)};
20690
}
20791

20892
} // namespace lldb_dap

lldb/tools/lldb-dap/Handler/RequestHandler.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -204,14 +204,18 @@ class AttachRequestHandler : public LegacyRequestHandler {
204204
void operator()(const llvm::json::Object &request) const override;
205205
};
206206

207-
class BreakpointLocationsRequestHandler : public LegacyRequestHandler {
207+
class BreakpointLocationsRequestHandler
208+
: public RequestHandler<
209+
protocol::BreakpointLocationsArguments,
210+
llvm::Expected<protocol::BreakpointLocationsResponseBody>> {
208211
public:
209-
using LegacyRequestHandler::LegacyRequestHandler;
212+
using RequestHandler::RequestHandler;
210213
static llvm::StringLiteral GetCommand() { return "breakpointLocations"; }
211214
FeatureSet GetSupportedFeatures() const override {
212215
return {protocol::eAdapterFeatureBreakpointLocationsRequest};
213216
}
214-
void operator()(const llvm::json::Object &request) const override;
217+
llvm::Expected<protocol::BreakpointLocationsResponseBody>
218+
Run(const protocol::BreakpointLocationsArguments &args) const override;
215219
};
216220

217221
class CompletionsRequestHandler : public LegacyRequestHandler {

lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,23 @@ bool fromJSON(const json::Value &Params, Configuration &C, json::Path P) {
245245
parseSourceMap(Params, C.sourceMap, P);
246246
}
247247

248+
bool fromJSON(const json::Value &Params, BreakpointLocationsArguments &BLA,
249+
json::Path P) {
250+
json::ObjectMapper O(Params, P);
251+
return O && O.map("source", BLA.source) && O.map("line", BLA.line) &&
252+
O.mapOptional("column", BLA.column) &&
253+
O.mapOptional("endLine", BLA.endLine) &&
254+
O.mapOptional("endColumn", BLA.endColumn);
255+
}
256+
257+
llvm::json::Value toJSON(const BreakpointLocationsResponseBody &BLRB) {
258+
llvm::json::Array breakpoints_json;
259+
for (const auto &breakpoint : BLRB.breakpoints) {
260+
breakpoints_json.push_back(toJSON(breakpoint));
261+
}
262+
return llvm::json::Object{{"breakpoints", std::move(breakpoints_json)}};
263+
}
264+
248265
bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
249266
json::Path P) {
250267
json::ObjectMapper O(Params, P);

lldb/tools/lldb-dap/Protocol/ProtocolRequests.h

+38
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <cstdint>
3131
#include <optional>
3232
#include <string>
33+
#include <vector>
3334

3435
namespace lldb_dap::protocol {
3536

@@ -377,6 +378,43 @@ bool fromJSON(const llvm::json::Value &, StepOutArguments &, llvm::json::Path);
377378
/// body field is required.
378379
using StepOutResponse = VoidResponse;
379380

381+
/// Arguments for `breakpointLocations` request.
382+
struct BreakpointLocationsArguments {
383+
/// The source location of the breakpoints; either `source.path` or
384+
/// `source.sourceReference` must be specified.
385+
Source source;
386+
387+
/// Start line of range to search possible breakpoint locations in. If only
388+
/// the line is specified, the request returns all possible locations in that
389+
/// line.
390+
uint32_t line;
391+
392+
/// Start position within `line` to search possible breakpoint locations in.
393+
/// It is measured in UTF-16 code units and the client capability
394+
/// `columnsStartAt1` determines whether it is 0- or 1-based. If no column is
395+
/// given, the first position in the start line is assumed.
396+
std::optional<uint32_t> column;
397+
398+
/// End line of range to search possible breakpoint locations in. If no end
399+
/// line is given, then the end line is assumed to be the start line.
400+
std::optional<uint32_t> endLine;
401+
402+
/// End position within `endLine` to search possible breakpoint locations in.
403+
/// It is measured in UTF-16 code units and the client capability
404+
/// `columnsStartAt1` determines whether it is 0- or 1-based. If no end column
405+
/// is given, the last position in the end line is assumed.
406+
std::optional<uint32_t> endColumn;
407+
};
408+
bool fromJSON(const llvm::json::Value &, BreakpointLocationsArguments &,
409+
llvm::json::Path);
410+
411+
/// Response to `breakpointLocations` request.
412+
struct BreakpointLocationsResponseBody {
413+
/// Content of the source reference.
414+
std::vector<BreakpointLocation> breakpoints;
415+
};
416+
llvm::json::Value toJSON(const BreakpointLocationsResponseBody &);
417+
380418
} // namespace lldb_dap::protocol
381419

382420
#endif

lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,18 @@ bool fromJSON(const llvm::json::Value &Params, SteppingGranularity &SG,
254254
return true;
255255
}
256256

257+
json::Value toJSON(const BreakpointLocation &B) {
258+
json::Object result;
259+
260+
result.insert({"line", B.line});
261+
if (B.column)
262+
result.insert({"column", *B.column});
263+
if (B.endLine)
264+
result.insert({"endLine", *B.endLine});
265+
if (B.endColumn)
266+
result.insert({"endColumn", *B.endColumn});
267+
268+
return result;
269+
}
270+
257271
} // namespace lldb_dap::protocol

lldb/tools/lldb-dap/Protocol/ProtocolTypes.h

+21
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,27 @@ enum SteppingGranularity : unsigned {
322322
bool fromJSON(const llvm::json::Value &, SteppingGranularity &,
323323
llvm::json::Path);
324324

325+
/// Properties of a breakpoint location returned from the `breakpointLocations`
326+
/// request.
327+
struct BreakpointLocation {
328+
/// Start line of breakpoint location.
329+
uint32_t line;
330+
331+
/// The start position of a breakpoint location. Position is measured in
332+
/// UTF-16 code units and the client capability `columnsStartAt1` determines
333+
/// whether it is 0- or 1-based.
334+
std::optional<uint32_t> column;
335+
336+
/// The end line of breakpoint location if the location covers a range.
337+
std::optional<uint32_t> endLine;
338+
339+
/// The end position of a breakpoint location (if the location covers a
340+
/// range). Position is measured in UTF-16 code units and the client
341+
/// capability `columnsStartAt1` determines whether it is 0- or 1-based.
342+
std::optional<uint32_t> endColumn;
343+
};
344+
llvm::json::Value toJSON(const BreakpointLocation &);
345+
325346
} // namespace lldb_dap::protocol
326347

327348
#endif

llvm/include/llvm/Support/JSON.h

+8
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,14 @@ inline bool fromJSON(const Value &E, bool &Out, Path P) {
776776
P.report("expected boolean");
777777
return false;
778778
}
779+
inline bool fromJSON(const Value &E, unsigned int &Out, Path P) {
780+
if (auto S = E.getAsInteger()) {
781+
Out = *S;
782+
return true;
783+
}
784+
P.report("expected integer");
785+
return false;
786+
}
779787
inline bool fromJSON(const Value &E, uint64_t &Out, Path P) {
780788
if (auto S = E.getAsUINT64()) {
781789
Out = *S;

0 commit comments

Comments
 (0)