blob: 7d1608f59f9a477095a16cb797a9b29f944584f9 [file] [log] [blame]
//===-- ScopesRequestHandler.cpp ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "DAP.h"
#include "EventHelper.h"
#include "JSONUtils.h"
#include "RequestHandler.h"
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);
// 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
// sent and VS code doesn't allow multiple frames to show variables
// concurrently. If we select the thread and frame as the "scopes" requests
// 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
// 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
// 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,
/*in_scope_only=*/true);
dap.variables.globals = frame.GetVariables(/*arguments=*/false,
/*locals=*/false,
/*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)));
}
} // namespace lldb_dap