-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[lldb][lldb-dap] Migrate ScopesRequest to structured types #138116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cef462d
2f2a46d
1815d6b
7f7b3f6
78e50c5
0b5db4e
6519da9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,69 +7,56 @@ | |
//===----------------------------------------------------------------------===// | ||
|
||
#include "DAP.h" | ||
#include "EventHelper.h" | ||
#include "JSONUtils.h" | ||
#include "RequestHandler.h" | ||
|
||
using namespace lldb_dap::protocol; | ||
namespace lldb_dap { | ||
|
||
// "ScopesRequest": { | ||
// "allOf": [ { "$ref": "#/definitions/Request" }, { | ||
// "type": "object", | ||
// "description": "Scopes request; value of command field is 'scopes'. The | ||
// request returns the variable scopes for a given stackframe ID.", | ||
// "properties": { | ||
// "command": { | ||
// "type": "string", | ||
// "enum": [ "scopes" ] | ||
// }, | ||
// "arguments": { | ||
// "$ref": "#/definitions/ScopesArguments" | ||
// } | ||
// }, | ||
// "required": [ "command", "arguments" ] | ||
// }] | ||
// }, | ||
// "ScopesArguments": { | ||
// "type": "object", | ||
// "description": "Arguments for 'scopes' request.", | ||
// "properties": { | ||
// "frameId": { | ||
// "type": "integer", | ||
// "description": "Retrieve the scopes for this stackframe." | ||
// } | ||
// }, | ||
// "required": [ "frameId" ] | ||
// }, | ||
// "ScopesResponse": { | ||
// "allOf": [ { "$ref": "#/definitions/Response" }, { | ||
// "type": "object", | ||
// "description": "Response to 'scopes' request.", | ||
// "properties": { | ||
// "body": { | ||
// "type": "object", | ||
// "properties": { | ||
// "scopes": { | ||
// "type": "array", | ||
// "items": { | ||
// "$ref": "#/definitions/Scope" | ||
// }, | ||
// "description": "The scopes of the stackframe. If the array has | ||
// length zero, there are no scopes available." | ||
// } | ||
// }, | ||
// "required": [ "scopes" ] | ||
// } | ||
// }, | ||
// "required": [ "body" ] | ||
// }] | ||
// } | ||
void ScopesRequestHandler::operator()(const llvm::json::Object &request) const { | ||
llvm::json::Object response; | ||
FillResponse(request, response); | ||
llvm::json::Object body; | ||
const auto *arguments = request.getObject("arguments"); | ||
lldb::SBFrame frame = dap.GetLLDBFrame(*arguments); | ||
/// Creates a `protocol::Scope` struct. | ||
/// | ||
/// | ||
/// \param[in] name | ||
/// The value to place into the "name" key | ||
/// | ||
/// \param[in] variablesReference | ||
/// The value to place into the "variablesReference" key | ||
/// | ||
/// \param[in] namedVariables | ||
/// The value to place into the "namedVariables" key | ||
/// | ||
/// \param[in] expensive | ||
/// The value to place into the "expensive" key | ||
/// | ||
/// \return | ||
/// A `protocol::Scope` | ||
static Scope CreateScope(const llvm::StringRef name, int64_t variablesReference, | ||
int64_t namedVariables, bool expensive) { | ||
Scope scope; | ||
scope.name = name; | ||
|
||
// TODO: Support "arguments" and "return value" scope. | ||
// At the moment lldb-dap includes the arguments and return_value into the | ||
// "locals" scope. | ||
// vscode only expands the first non-expensive scope, this causes friction | ||
// if we add the arguments above the local scope as the locals scope will not | ||
// be expanded if we enter a function with arguments. It becomes more | ||
// annoying when the scope has arguments, return_value and locals. | ||
if (variablesReference == VARREF_LOCALS) | ||
scope.presentationHint = Scope::eScopePresentationHintLocals; | ||
else if (variablesReference == VARREF_REGS) | ||
scope.presentationHint = Scope::eScopePresentationHintRegisters; | ||
|
||
scope.variablesReference = variablesReference; | ||
scope.namedVariables = namedVariables; | ||
scope.expensive = expensive; | ||
|
||
return scope; | ||
} | ||
|
||
llvm::Expected<ScopesResponseBody> | ||
ScopesRequestHandler::Run(const ScopesArguments &args) const { | ||
lldb::SBFrame frame = dap.GetLLDBFrame(args.frameId); | ||
|
||
// As the user selects different stack frames in the GUI, a "scopes" request | ||
// will be sent to the DAP. This is the only way we know that the user has | ||
// selected a frame in a thread. There are no other notifications that are | ||
|
@@ -78,17 +65,16 @@ void ScopesRequestHandler::operator()(const llvm::json::Object &request) const { | |
// are sent, this allows users to type commands in the debugger console | ||
// with a backtick character to run lldb commands and these lldb commands | ||
// will now have the right context selected as they are run. If the user | ||
// types "`bt" into the debugger console and we had another thread selected | ||
// types "`bt" into the debugger console, and we had another thread selected | ||
// in the LLDB library, we would show the wrong thing to the user. If the | ||
// users switches threads with a lldb command like "`thread select 14", the | ||
// users switch threads with a lldb command like "`thread select 14", the | ||
// GUI will not update as there are no "event" notification packets that | ||
// allow us to change the currently selected thread or frame in the GUI that | ||
// I am aware of. | ||
if (frame.IsValid()) { | ||
frame.GetThread().GetProcess().SetSelectedThread(frame.GetThread()); | ||
frame.GetThread().SetSelectedFrame(frame.GetFrameID()); | ||
} | ||
|
||
dap.variables.locals = frame.GetVariables(/*arguments=*/true, | ||
/*locals=*/true, | ||
/*statics=*/false, | ||
|
@@ -98,9 +84,15 @@ void ScopesRequestHandler::operator()(const llvm::json::Object &request) const { | |
/*statics=*/true, | ||
/*in_scope_only=*/true); | ||
dap.variables.registers = frame.GetRegisters(); | ||
body.try_emplace("scopes", dap.CreateTopLevelScopes()); | ||
response.try_emplace("body", std::move(body)); | ||
dap.SendJSON(llvm::json::Value(std::move(response))); | ||
|
||
std::vector scopes = {CreateScope("Locals", VARREF_LOCALS, | ||
dap.variables.locals.GetSize(), false), | ||
CreateScope("Globals", VARREF_GLOBALS, | ||
dap.variables.globals.GetSize(), false), | ||
CreateScope("Registers", VARREF_REGS, | ||
dap.variables.registers.GetSize(), false)}; | ||
|
||
return ScopesResponseBody{std::move(scopes)}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I almost wonder if it would make more sense for some of this to move into the Maybe I think the intention is for the How does that sound to you? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it should be only in the scoped request since nothing outside is using the functionality. would be worth it to move it to the variables if there was another request that depends on getting all the scopes. |
||
} | ||
|
||
} // namespace lldb_dap |
Uh oh!
There was an error while loading. Please reload this page.