Skip to content

Commit f39b3a4

Browse files
committed
[lldb-dap] Migrate variables request protocol types.
This adds new protocol types for the 'variables' request. While implementing this, I removed the '$__lldb_extension' field we returned on the 'variables' request, since I think all the data can be retrieved from other DAP requests.
1 parent d906079 commit f39b3a4

File tree

12 files changed

+430
-441
lines changed

12 files changed

+430
-441
lines changed

lldb/test/API/tools/lldb-dap/optimized/TestDAP_optimized.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_stack_frame_name(self):
2828
parent_frame = self.dap_server.get_stackFrame(frameIndex=1)
2929
self.assertTrue(parent_frame["name"].endswith(" [opt]"))
3030

31-
@skipIfAsan # On ASAN builds this test intermittently fails https://github.com/llvm/llvm-project/issues/111061
31+
@skipIfAsan # On ASAN builds this test intermittently fails https://github.com/llvm/llvm-project/issues/111061
3232
@skipIfWindows
3333
def test_optimized_variable(self):
3434
"""Test optimized variable value contains error."""
@@ -50,9 +50,8 @@ def test_optimized_variable(self):
5050
value.startswith("<error:"),
5151
f"expect error for value: '{value}'",
5252
)
53-
error_msg = optimized_variable["$__lldb_extensions"]["error"]
5453
self.assertTrue(
55-
("could not evaluate DW_OP_entry_value: no parent function" in error_msg)
56-
or ("variable not available" in error_msg)
54+
("could not evaluate DW_OP_entry_value: no parent function" in value)
55+
or ("variable not available" in value)
5756
)
5857
self.continue_to_exit()

lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
"""
2-
Test lldb-dap setBreakpoints request
2+
Test lldb-dap variables request
33
"""
44

55
import os
66

7-
import dap_server
87
import lldbdap_testcase
9-
from lldbsuite.test import lldbutil
108
from lldbsuite.test.decorators import *
119
from lldbsuite.test.lldbtest import *
1210

@@ -168,15 +166,6 @@ def do_test_scopes_variables_setVariable_evaluate(
168166
"type": "int",
169167
"value": "1",
170168
},
171-
"$__lldb_extensions": {
172-
"equals": {
173-
"value": "1",
174-
},
175-
"declaration": {
176-
"equals": {"line": 12, "column": 14},
177-
"contains": {"path": ["lldb-dap", "variables", "main.cpp"]},
178-
},
179-
},
180169
},
181170
"argv": {
182171
"equals": {"type": "const char **"},
@@ -196,10 +185,6 @@ def do_test_scopes_variables_setVariable_evaluate(
196185
},
197186
"x": {"equals": {"type": "int"}},
198187
}
199-
if enableAutoVariableSummaries:
200-
verify_locals["pt"]["$__lldb_extensions"] = {
201-
"equals": {"autoSummary": "{x:11, y:22}"}
202-
}
203188

204189
verify_globals = {
205190
"s_local": {"equals": {"type": "float", "value": "2.25"}},

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,11 +540,14 @@ class ThreadsRequestHandler
540540
Run(const protocol::ThreadsArguments &) const override;
541541
};
542542

543-
class VariablesRequestHandler : public LegacyRequestHandler {
543+
class VariablesRequestHandler
544+
: public RequestHandler<protocol::VariablesArguments,
545+
llvm::Expected<protocol::VariablesResponseBody>> {
544546
public:
545-
using LegacyRequestHandler::LegacyRequestHandler;
547+
using RequestHandler::RequestHandler;
546548
static llvm::StringLiteral GetCommand() { return "variables"; }
547-
void operator()(const llvm::json::Object &request) const override;
549+
llvm::Expected<protocol::VariablesResponseBody>
550+
Run(const protocol::VariablesArguments &) const override;
548551
};
549552

550553
class LocationsRequestHandler : public LegacyRequestHandler {

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

Lines changed: 31 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -8,107 +8,37 @@
88

99
#include "DAP.h"
1010
#include "EventHelper.h"
11+
#include "Handler/RequestHandler.h"
1112
#include "JSONUtils.h"
12-
#include "RequestHandler.h"
13+
#include "ProtocolUtils.h"
14+
15+
using namespace llvm;
16+
using namespace lldb_dap::protocol;
1317

1418
namespace lldb_dap {
1519

16-
// "VariablesRequest": {
17-
// "allOf": [ { "$ref": "#/definitions/Request" }, {
18-
// "type": "object",
19-
// "description": "Variables request; value of command field is 'variables'.
20-
// Retrieves all child variables for the given variable reference. An
21-
// optional filter can be used to limit the fetched children to either named
22-
// or indexed children.", "properties": {
23-
// "command": {
24-
// "type": "string",
25-
// "enum": [ "variables" ]
26-
// },
27-
// "arguments": {
28-
// "$ref": "#/definitions/VariablesArguments"
29-
// }
30-
// },
31-
// "required": [ "command", "arguments" ]
32-
// }]
33-
// },
34-
// "VariablesArguments": {
35-
// "type": "object",
36-
// "description": "Arguments for 'variables' request.",
37-
// "properties": {
38-
// "variablesReference": {
39-
// "type": "integer",
40-
// "description": "The Variable reference."
41-
// },
42-
// "filter": {
43-
// "type": "string",
44-
// "enum": [ "indexed", "named" ],
45-
// "description": "Optional filter to limit the child variables to either
46-
// named or indexed. If ommited, both types are fetched."
47-
// },
48-
// "start": {
49-
// "type": "integer",
50-
// "description": "The index of the first variable to return; if omitted
51-
// children start at 0."
52-
// },
53-
// "count": {
54-
// "type": "integer",
55-
// "description": "The number of variables to return. If count is missing
56-
// or 0, all variables are returned."
57-
// },
58-
// "format": {
59-
// "$ref": "#/definitions/ValueFormat",
60-
// "description": "Specifies details on how to format the Variable
61-
// values."
62-
// }
63-
// },
64-
// "required": [ "variablesReference" ]
65-
// },
66-
// "VariablesResponse": {
67-
// "allOf": [ { "$ref": "#/definitions/Response" }, {
68-
// "type": "object",
69-
// "description": "Response to 'variables' request.",
70-
// "properties": {
71-
// "body": {
72-
// "type": "object",
73-
// "properties": {
74-
// "variables": {
75-
// "type": "array",
76-
// "items": {
77-
// "$ref": "#/definitions/Variable"
78-
// },
79-
// "description": "All (or a range) of variables for the given
80-
// variable reference."
81-
// }
82-
// },
83-
// "required": [ "variables" ]
84-
// }
85-
// },
86-
// "required": [ "body" ]
87-
// }]
88-
// }
89-
void VariablesRequestHandler::operator()(
90-
const llvm::json::Object &request) const {
91-
llvm::json::Object response;
92-
FillResponse(request, response);
93-
llvm::json::Array variables;
94-
const auto *arguments = request.getObject("arguments");
95-
const auto variablesReference =
96-
GetInteger<uint64_t>(arguments, "variablesReference").value_or(0);
97-
const auto start = GetInteger<int64_t>(arguments, "start").value_or(0);
98-
const auto count = GetInteger<int64_t>(arguments, "count").value_or(0);
20+
/// Retrieves all child variables for the given variable reference.
21+
///
22+
/// A filter can be used to limit the fetched children to either named or
23+
/// indexed children.
24+
Expected<VariablesResponseBody>
25+
VariablesRequestHandler::Run(const VariablesArguments &arguments) const {
26+
uint64_t var_ref = arguments.variablesReference;
27+
uint64_t count = arguments.count;
28+
uint64_t start = arguments.start;
9929
bool hex = false;
100-
const auto *format = arguments->getObject("format");
101-
if (format)
102-
hex = GetBoolean(format, "hex").value_or(false);
30+
if (arguments.format)
31+
hex = arguments.format->hex.value_or(false);
32+
33+
std::vector<Variable> variables;
10334

104-
if (lldb::SBValueList *top_scope =
105-
dap.variables.GetTopLevelScope(variablesReference)) {
35+
if (lldb::SBValueList *top_scope = dap.variables.GetTopLevelScope(var_ref)) {
10636
// variablesReference is one of our scopes, not an actual variable it is
10737
// asking for the list of args, locals or globals.
10838
int64_t start_idx = 0;
10939
int64_t num_children = 0;
11040

111-
if (variablesReference == VARREF_REGS) {
41+
if (var_ref == VARREF_REGS) {
11242
// Change the default format of any pointer sized registers in the first
11343
// register set to be the lldb::eFormatAddressInfo so we show the pointer
11444
// and resolve what the pointer resolves to. Only change the format if the
@@ -128,7 +58,7 @@ void VariablesRequestHandler::operator()(
12858
}
12959

13060
num_children = top_scope->GetSize();
131-
if (num_children == 0 && variablesReference == VARREF_LOCALS) {
61+
if (num_children == 0 && var_ref == VARREF_LOCALS) {
13262
// Check for an error in the SBValueList that might explain why we don't
13363
// have locals. If we have an error display it as the sole value in the
13464
// the locals.
@@ -145,12 +75,11 @@ void VariablesRequestHandler::operator()(
14575
// errors are only set when there is a problem that the user could
14676
// fix, so no error will show up when you have no debug info, only when
14777
// we do have debug info and something that is fixable can be done.
148-
llvm::json::Object object;
149-
EmplaceSafeString(object, "name", "<error>");
150-
EmplaceSafeString(object, "type", "const char *");
151-
EmplaceSafeString(object, "value", var_err);
152-
object.try_emplace("variablesReference", (int64_t)0);
153-
variables.emplace_back(std::move(object));
78+
Variable var;
79+
var.name = "<error>";
80+
var.type = "const char *";
81+
var.value = var_err;
82+
variables.emplace_back(var);
15483
}
15584
}
15685
const int64_t end_idx = start_idx + ((count == 0) ? num_children : count);
@@ -165,7 +94,7 @@ void VariablesRequestHandler::operator()(
16594
}
16695

16796
// Show return value if there is any ( in the local top frame )
168-
if (variablesReference == VARREF_LOCALS) {
97+
if (var_ref == VARREF_LOCALS) {
16998
auto process = dap.target.GetProcess();
17099
auto selected_thread = process.GetSelectedThread();
171100
lldb::SBValue stop_return_value = selected_thread.GetStopReturnValue();
@@ -204,14 +133,13 @@ void VariablesRequestHandler::operator()(
204133
} else {
205134
// We are expanding a variable that has children, so we will return its
206135
// children.
207-
lldb::SBValue variable = dap.variables.GetVariable(variablesReference);
136+
lldb::SBValue variable = dap.variables.GetVariable(var_ref);
208137
if (variable.IsValid()) {
209138
auto addChild = [&](lldb::SBValue child,
210139
std::optional<std::string> custom_name = {}) {
211140
if (!child.IsValid())
212141
return;
213-
bool is_permanent =
214-
dap.variables.IsPermanentVariableReference(variablesReference);
142+
bool is_permanent = dap.variables.IsPermanentVariableReference(var_ref);
215143
int64_t var_ref = dap.variables.InsertVariable(child, is_permanent);
216144
variables.emplace_back(CreateVariable(
217145
child, var_ref, hex, dap.configuration.enableAutoVariableSummaries,
@@ -233,10 +161,8 @@ void VariablesRequestHandler::operator()(
233161
addChild(variable.GetNonSyntheticValue(), "[raw]");
234162
}
235163
}
236-
llvm::json::Object body;
237-
body.try_emplace("variables", std::move(variables));
238-
response.try_emplace("body", std::move(body));
239-
dap.SendJSON(llvm::json::Value(std::move(response)));
164+
165+
return VariablesResponseBody{variables};
240166
}
241167

242168
} // namespace lldb_dap

0 commit comments

Comments
 (0)