Skip to content

Commit 437c69f

Browse files
committed
[lldb][lldb-dap] Migrate 'Scopes' to structured types.
1 parent 6c4dd8d commit 437c69f

File tree

6 files changed

+199
-12
lines changed

6 files changed

+199
-12
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,17 @@ class PauseRequestHandler : public LegacyRequestHandler {
423423
void operator()(const llvm::json::Object &request) const override;
424424
};
425425

426+
class ScopesRequestHandler2 final
427+
: public RequestHandler<protocol::ScopesArguments,
428+
llvm::Expected<protocol::ScopesResponseBody>> {
429+
public:
430+
using RequestHandler::RequestHandler;
431+
static llvm::StringLiteral GetCommand() { return "scopes"; }
432+
433+
llvm::Expected<protocol::ScopesResponseBody>
434+
Run(const protocol::ScopesArguments &args) const override;
435+
};
436+
426437
class ScopesRequestHandler : public LegacyRequestHandler {
427438
public:
428439
using LegacyRequestHandler::LegacyRequestHandler;

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ namespace lldb_dap {
6464
// "required": [ "body" ]
6565
// }]
6666
// }
67+
68+
llvm::Expected<protocol::ScopesResponseBody>
69+
ScopesRequestHandler2::Run(const protocol::ScopesArguments &args) const {
70+
// lldb::SBFrame frame = dap.GetLLDBFrame()
71+
return llvm::createStringError("something");
72+
};
6773
void ScopesRequestHandler::operator()(const llvm::json::Object &request) const {
6874
llvm::json::Object response;
6975
FillResponse(request, response);

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,19 @@ bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
260260
O.mapOptional("runInTerminal", LRA.runInTerminal) &&
261261
parseEnv(Params, LRA.env, P) && parseTimeout(Params, LRA.timeout, P);
262262
}
263+
bool fromJSON(const llvm::json::Value &Params, ScopesArguments &SCA,
264+
llvm::json::Path P) {
265+
json::ObjectMapper O(Params, P);
266+
return O && O.map("frameId", SCA.frameId);
267+
}
268+
269+
llvm::json::Value toJSON(const ScopesResponseBody &SCR) {
270+
llvm::json::Array body;
271+
for (const Scope &scope : SCR.scopes) {
272+
body.emplace_back(toJSON(scope));
273+
}
274+
return body;
275+
}
263276

264277
bool fromJSON(const json::Value &Params, SourceArguments &SA, json::Path P) {
265278
json::ObjectMapper O(Params, P);

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,19 @@ bool fromJSON(const llvm::json::Value &, LaunchRequestArguments &,
294294
/// field is required.
295295
using LaunchResponseBody = VoidResponse;
296296

297+
struct ScopesArguments {
298+
/// Retrieve the scopes for the stack frame identified by `frameId`. The
299+
/// `frameId` must have been obtained in the current suspended state. See
300+
/// 'Lifetime of Object References' in the Overview section for details.
301+
uint64_t frameId;
302+
};
303+
bool fromJSON(const llvm::json::Value &, ScopesArguments &, llvm::json::Path);
304+
305+
struct ScopesResponseBody {
306+
std::vector<Scope> scopes;
307+
};
308+
llvm::json::Value toJSON(const ScopesResponseBody &);
309+
297310
/// Arguments for `source` request.
298311
struct SourceArguments {
299312
/// Specifies the source content to load. Either `source.path` or

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

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,18 @@ using namespace llvm;
1616

1717
namespace lldb_dap::protocol {
1818

19-
bool fromJSON(const json::Value &Params, PresentationHint &PH, json::Path P) {
19+
bool fromJSON(const json::Value &Params, Source::PresentationHint &PH,
20+
json::Path P) {
2021
auto rawHint = Params.getAsString();
2122
if (!rawHint) {
2223
P.report("expected a string");
2324
return false;
2425
}
25-
std::optional<PresentationHint> hint =
26-
StringSwitch<std::optional<PresentationHint>>(*rawHint)
27-
.Case("normal", ePresentationHintNormal)
28-
.Case("emphasize", ePresentationHintEmphasize)
29-
.Case("deemphasize", ePresentationHintDeemphasize)
26+
std::optional<Source::PresentationHint> hint =
27+
StringSwitch<std::optional<Source::PresentationHint>>(*rawHint)
28+
.Case("normal", Source::ePresentationHintNormal)
29+
.Case("emphasize", Source::ePresentationHintEmphasize)
30+
.Case("deemphasize", Source::ePresentationHintDeemphasize)
3031
.Default(std::nullopt);
3132
if (!hint) {
3233
P.report("unexpected value");
@@ -36,12 +37,38 @@ bool fromJSON(const json::Value &Params, PresentationHint &PH, json::Path P) {
3637
return true;
3738
}
3839

40+
llvm::json::Value toJSON(const Source::PresentationHint &PH) {
41+
switch (PH) {
42+
case Source::ePresentationHintNormal:
43+
return "normal";
44+
case Source ::ePresentationHintEmphasize:
45+
return "emphasize";
46+
case Source::ePresentationHintDeemphasize:
47+
return "deemphasize";
48+
}
49+
llvm_unreachable("Fully covered switch above");
50+
}
51+
3952
bool fromJSON(const json::Value &Params, Source &S, json::Path P) {
4053
json::ObjectMapper O(Params, P);
4154
return O && O.map("name", S.name) && O.map("path", S.path) &&
4255
O.map("presentationHint", S.presentationHint) &&
4356
O.map("sourceReference", S.sourceReference);
4457
}
58+
llvm::json::Value toJSON(const Source &S) {
59+
json::Object result;
60+
61+
if (S.name.has_value())
62+
result.insert({"name", S.name});
63+
if (S.path.has_value())
64+
result.insert({"path", S.path});
65+
if (S.sourceReference.has_value())
66+
result.insert({"sourceReference", S.sourceReference});
67+
if (S.presentationHint.has_value())
68+
result.insert({"presentationHint", S.presentationHint});
69+
70+
return result;
71+
}
4572

4673
json::Value toJSON(const ExceptionBreakpointsFilter &EBF) {
4774
json::Object result{{"filter", EBF.filter}, {"label", EBF.label}};
@@ -233,6 +260,55 @@ json::Value toJSON(const Capabilities &C) {
233260
return result;
234261
}
235262

263+
llvm::json::Value toJSON(const Scope &SC) {
264+
llvm::json::Object result{{"name", SC.name},
265+
{"variablesReference", SC.variablesReference},
266+
{"expensive", SC.expensive}};
267+
268+
if (SC.presentationHint.has_value()) {
269+
llvm::StringRef presentationHint;
270+
switch (*SC.presentationHint) {
271+
case Scope::ePresentationHintArguments:
272+
presentationHint = "arguments";
273+
break;
274+
case Scope::ePresentationHintLocals:
275+
presentationHint = "locals";
276+
break;
277+
case Scope::ePresentationHintRegisters:
278+
presentationHint = "registers";
279+
break;
280+
case Scope::ePresentationHintReturnValue:
281+
presentationHint = "returnValue";
282+
break;
283+
}
284+
285+
result.insert({"presentationHint", presentationHint});
286+
}
287+
288+
if (SC.namedVariables.has_value())
289+
result.insert({"namedVariables", SC.namedVariables});
290+
291+
if (SC.indexedVariables.has_value())
292+
result.insert({"indexedVariables", SC.indexedVariables});
293+
294+
if (SC.source.has_value())
295+
result.insert({"source", SC.source});
296+
297+
if (SC.line.has_value())
298+
result.insert({"line", SC.line});
299+
300+
if (SC.column.has_value())
301+
result.insert({"column", SC.column});
302+
303+
if (SC.endLine.has_value())
304+
result.insert({"endLine", SC.endLine});
305+
306+
if (SC.endColumn.has_value())
307+
result.insert({"endColumn", SC.endColumn});
308+
309+
return result;
310+
}
311+
236312
bool fromJSON(const llvm::json::Value &Params, SteppingGranularity &SG,
237313
llvm::json::Path P) {
238314
auto raw_granularity = Params.getAsString();

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

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/ADT/DenseSet.h"
2424
#include "llvm/Support/JSON.h"
2525
#include <cstdint>
26+
#include <lldb/lldb-enumerations.h>
2627
#include <optional>
2728
#include <string>
2829

@@ -268,16 +269,15 @@ struct Capabilities {
268269
};
269270
llvm::json::Value toJSON(const Capabilities &);
270271

271-
enum PresentationHint : unsigned {
272-
ePresentationHintNormal,
273-
ePresentationHintEmphasize,
274-
ePresentationHintDeemphasize,
275-
};
276-
277272
/// A `Source` is a descriptor for source code. It is returned from the debug
278273
/// adapter as part of a `StackFrame` and it is used by clients when specifying
279274
/// breakpoints.
280275
struct Source {
276+
enum PresentationHint : unsigned {
277+
ePresentationHintNormal,
278+
ePresentationHintEmphasize,
279+
ePresentationHintDeemphasize,
280+
};
281281
/// The short name of the source. Every source returned from the debug adapter
282282
/// has a name. When sending a source to the debug adapter this name is
283283
/// optional.
@@ -302,6 +302,74 @@ struct Source {
302302
// unsupported keys: origin, sources, adapterData, checksums
303303
};
304304
bool fromJSON(const llvm::json::Value &, Source &, llvm::json::Path);
305+
llvm::json::Value toJSON(const Source &);
306+
307+
/// A `Scope` is a named container for variables. Optionally a scope can map to
308+
/// a source or a range within a source.
309+
struct Scope {
310+
enum PresentationHint : unsigned {
311+
ePresentationHintArguments,
312+
ePresentationHintLocals,
313+
ePresentationHintRegisters,
314+
ePresentationHintReturnValue
315+
};
316+
/// Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This
317+
/// string is shown in the UI as is and can be translated.
318+
////
319+
std::string name;
320+
321+
/// A hint for how to present this scope in the UI. If this attribute is
322+
/// missing, the scope is shown with a generic UI.
323+
/// Values:
324+
/// 'arguments': Scope contains method arguments.
325+
/// 'locals': Scope contains local variables.
326+
/// 'registers': Scope contains registers. Only a single `registers` scope
327+
/// should be returned from a `scopes` request.
328+
/// 'returnValue': Scope contains one or more return values.
329+
/// etc.
330+
std::optional<PresentationHint> presentationHint;
331+
332+
/// The variables of this scope can be retrieved by passing the value of
333+
/// `variablesReference` to the `variables` request as long as execution
334+
/// remains suspended. See 'Lifetime of Object References' in the Overview
335+
/// section for details.
336+
////
337+
uint64_t variablesReference;
338+
339+
/// The number of named variables in this scope.
340+
/// The client can use this information to present the variables in a paged UI
341+
/// and fetch them in chunks.
342+
std::optional<uint64_t> namedVariables;
343+
344+
/// The number of indexed variables in this scope.
345+
/// The client can use this information to present the variables in a paged UI
346+
/// and fetch them in chunks.
347+
std::optional<uint64_t> indexedVariables;
348+
349+
/// The source for this scope.
350+
std::optional<Source> source;
351+
352+
/// If true, the number of variables in this scope is large or expensive to
353+
/// retrieve.
354+
bool expensive;
355+
356+
/// The start line of the range covered by this scope.
357+
std::optional<uint64_t> line;
358+
359+
/// Start position of the range covered by the scope. It is measured in UTF-16
360+
/// code units and the client capability `columnsStartAt1` determines whether
361+
/// it is 0- or 1-based.
362+
std::optional<uint64_t> column;
363+
364+
/// The end line of the range covered by this scope.
365+
std::optional<uint64_t> endLine;
366+
367+
/// End position of the range covered by the scope. It is measured in UTF-16
368+
/// code units and the client capability `columnsStartAt1` determines whether
369+
/// it is 0- or 1-based.
370+
std::optional<uint64_t> endColumn;
371+
};
372+
llvm::json::Value toJSON(const Scope &);
305373

306374
/// The granularity of one `step` in the stepping requests `next`, `stepIn`,
307375
/// `stepOut` and `stepBack`.

0 commit comments

Comments
 (0)