92 lines · cpp
1//===-- SetVariableRequestHandler.cpp -------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DAP.h"10#include "EventHelper.h"11#include "JSONUtils.h"12#include "Protocol/ProtocolEvents.h"13#include "RequestHandler.h"14 15using namespace lldb_dap::protocol;16 17namespace lldb_dap {18 19/// Set the variable with the given name in the variable container to a new20/// value. Clients should only call this request if the corresponding capability21/// `supportsSetVariable` is true.22///23/// If a debug adapter implements both `setVariable` and `setExpression`,24/// a client will only use `setExpression` if the variable has an evaluateName25/// property.26llvm::Expected<SetVariableResponseBody>27SetVariableRequestHandler::Run(const SetVariableArguments &args) const {28 const auto args_name = llvm::StringRef(args.name);29 30 if (args.variablesReference == UINT64_MAX) {31 return llvm::make_error<DAPError>(32 llvm::formatv("invalid reference {}", args.variablesReference).str(),33 llvm::inconvertibleErrorCode(),34 /*show_user=*/false);35 }36 37 constexpr llvm::StringRef return_value_name = "(Return Value)";38 if (args_name == return_value_name)39 return llvm::make_error<DAPError>(40 "cannot change the value of the return value");41 42 lldb::SBValue variable =43 dap.variables.FindVariable(args.variablesReference, args_name);44 45 if (!variable.IsValid())46 return llvm::make_error<DAPError>("could not find variable in scope");47 48 lldb::SBError error;49 const bool success = variable.SetValueFromCString(args.value.c_str(), error);50 if (!success)51 return llvm::make_error<DAPError>(error.GetCString());52 53 VariableDescription desc(variable,54 dap.configuration.enableAutoVariableSummaries);55 56 SetVariableResponseBody body;57 body.value = desc.display_value;58 body.type = desc.display_type_name;59 60 // We don't know the index of the variable in our dap.variables61 // so always insert a new one to get its variablesReference.62 // is_permanent is false because debug console does not support63 // setVariable request.64 const int64_t new_var_ref =65 dap.variables.InsertVariable(variable, /*is_permanent=*/false);66 if (variable.MightHaveChildren()) {67 body.variablesReference = new_var_ref;68 if (desc.type_obj.IsArrayType())69 body.indexedVariables = variable.GetNumChildren();70 else71 body.namedVariables = variable.GetNumChildren();72 }73 74 if (const lldb::addr_t addr = variable.GetLoadAddress();75 addr != LLDB_INVALID_ADDRESS)76 body.memoryReference = addr;77 78 if (ValuePointsToCode(variable))79 body.valueLocationReference = new_var_ref;80 81 // Also send invalidated event to signal client that some variables82 // (e.g. references) can be changed.83 SendInvalidatedEvent(dap, {InvalidatedEventBody::eAreaVariables});84 85 // Also send memory event to signal client that variable memory was changed.86 SendMemoryEvent(dap, variable);87 88 return body;89}90 91} // namespace lldb_dap92