698 lines · cpp
1//===-- ProtocolRequests.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 "Protocol/ProtocolRequests.h"10#include "JSONUtils.h"11#include "Protocol/ProtocolTypes.h"12#include "lldb/lldb-defines.h"13#include "llvm/ADT/DenseMap.h"14#include "llvm/ADT/StringMap.h"15#include "llvm/ADT/StringRef.h"16#include "llvm/Support/Base64.h"17#include "llvm/Support/JSON.h"18#include <utility>19 20using namespace llvm;21 22// The 'env' field is either an object as a map of strings or as an array of23// strings formatted like 'key=value'.24static bool parseEnv(const json::Value &Params, StringMap<std::string> &env,25 json::Path P) {26 const json::Object *O = Params.getAsObject();27 if (!O) {28 P.report("expected object");29 return false;30 }31 32 const json::Value *value = O->get("env");33 if (!value)34 return true;35 36 if (const json::Object *env_obj = value->getAsObject()) {37 for (const auto &kv : *env_obj) {38 const std::optional<StringRef> value = kv.second.getAsString();39 if (!value) {40 P.field("env").field(kv.first).report("expected string value");41 return false;42 }43 env.insert({kv.first.str(), value->str()});44 }45 return true;46 }47 48 if (const json::Array *env_arr = value->getAsArray()) {49 for (size_t i = 0; i < env_arr->size(); ++i) {50 const std::optional<StringRef> value = (*env_arr)[i].getAsString();51 if (!value) {52 P.field("env").index(i).report("expected string");53 return false;54 }55 std::pair<StringRef, StringRef> kv = value->split("=");56 env.insert({kv.first, kv.second.str()});57 }58 59 return true;60 }61 62 P.field("env").report("invalid format, expected array or object");63 return false;64}65 66static bool parseTimeout(const json::Value &Params, std::chrono::seconds &S,67 json::Path P) {68 const json::Object *O = Params.getAsObject();69 if (!O) {70 P.report("expected object");71 return false;72 }73 74 const json::Value *value = O->get("timeout");75 if (!value)76 return true;77 std::optional<double> timeout = value->getAsNumber();78 if (!timeout) {79 P.field("timeout").report("expected number");80 return false;81 }82 83 S = std::chrono::duration_cast<std::chrono::seconds>(84 std::chrono::duration<double>(*value->getAsNumber()));85 return true;86}87 88static bool89parseSourceMap(const json::Value &Params,90 std::vector<std::pair<std::string, std::string>> &sourceMap,91 json::Path P) {92 const json::Object *O = Params.getAsObject();93 if (!O) {94 P.report("expected object");95 return false;96 }97 98 const json::Value *value = O->get("sourceMap");99 if (!value)100 return true;101 102 if (const json::Object *map_obj = value->getAsObject()) {103 for (const auto &kv : *map_obj) {104 const std::optional<StringRef> value = kv.second.getAsString();105 if (!value) {106 P.field("sourceMap").field(kv.first).report("expected string value");107 return false;108 }109 sourceMap.emplace_back(std::make_pair(kv.first.str(), value->str()));110 }111 return true;112 }113 114 if (const json::Array *env_arr = value->getAsArray()) {115 for (size_t i = 0; i < env_arr->size(); ++i) {116 const json::Array *kv = (*env_arr)[i].getAsArray();117 if (!kv) {118 P.field("sourceMap").index(i).report("expected array");119 return false;120 }121 if (kv->size() != 2) {122 P.field("sourceMap").index(i).report("expected array of pairs");123 return false;124 }125 const std::optional<StringRef> first = (*kv)[0].getAsString();126 if (!first) {127 P.field("sourceMap").index(0).report("expected string");128 return false;129 }130 const std::optional<StringRef> second = (*kv)[1].getAsString();131 if (!second) {132 P.field("sourceMap").index(1).report("expected string");133 return false;134 }135 sourceMap.emplace_back(std::make_pair(*first, second->str()));136 }137 138 return true;139 }140 141 P.report("invalid format, expected array or object");142 return false;143}144 145namespace lldb_dap::protocol {146 147bool fromJSON(const json::Value &Params, CancelArguments &CA, json::Path P) {148 json::ObjectMapper O(Params, P);149 return O && O.map("requestId", CA.requestId) &&150 O.map("progressId", CA.progressId);151}152 153bool fromJSON(const json::Value &Params, DisconnectArguments &DA,154 json::Path P) {155 json::ObjectMapper O(Params, P);156 return O && O.mapOptional("restart", DA.restart) &&157 O.mapOptional("terminateDebuggee", DA.terminateDebuggee) &&158 O.mapOptional("suspendDebuggee", DA.suspendDebuggee);159}160 161bool fromJSON(const json::Value &Params, PathFormat &PF, json::Path P) {162 auto rawPathFormat = Params.getAsString();163 if (!rawPathFormat) {164 P.report("expected a string");165 return false;166 }167 168 std::optional<PathFormat> pathFormat =169 StringSwitch<std::optional<PathFormat>>(*rawPathFormat)170 .Case("path", ePatFormatPath)171 .Case("uri", ePathFormatURI)172 .Default(std::nullopt);173 if (!pathFormat) {174 P.report("unexpected value, expected 'path' or 'uri'");175 return false;176 }177 178 PF = *pathFormat;179 return true;180}181 182static const StringMap<ClientFeature> ClientFeatureByKey{183 {"supportsVariableType", eClientFeatureVariableType},184 {"supportsVariablePaging", eClientFeatureVariablePaging},185 {"supportsRunInTerminalRequest", eClientFeatureRunInTerminalRequest},186 {"supportsMemoryReferences", eClientFeatureMemoryReferences},187 {"supportsProgressReporting", eClientFeatureProgressReporting},188 {"supportsInvalidatedEvent", eClientFeatureInvalidatedEvent},189 {"supportsMemoryEvent", eClientFeatureMemoryEvent},190 {"supportsArgsCanBeInterpretedByShell",191 eClientFeatureArgsCanBeInterpretedByShell},192 {"supportsStartDebuggingRequest", eClientFeatureStartDebuggingRequest},193 {"supportsANSIStyling", eClientFeatureANSIStyling}};194 195bool fromJSON(const json::Value &Params, InitializeRequestArguments &IRA,196 json::Path P) {197 json::ObjectMapper OM(Params, P);198 if (!OM)199 return false;200 201 const json::Object *O = Params.getAsObject();202 203 for (auto &kv : ClientFeatureByKey) {204 const json::Value *value_ref = O->get(kv.first());205 if (!value_ref)206 continue;207 208 const std::optional<bool> value = value_ref->getAsBoolean();209 if (!value) {210 P.field(kv.first()).report("expected bool");211 return false;212 }213 214 if (*value)215 IRA.supportedFeatures.insert(kv.second);216 }217 218 return OM.map("adapterID", IRA.adapterID) &&219 OM.map("clientID", IRA.clientID) &&220 OM.map("clientName", IRA.clientName) && OM.map("locale", IRA.locale) &&221 OM.map("linesStartAt1", IRA.linesStartAt1) &&222 OM.map("columnsStartAt1", IRA.columnsStartAt1) &&223 OM.mapOptional("pathFormat", IRA.pathFormat) &&224 OM.map("$__lldb_sourceInitFile", IRA.lldbExtSourceInitFile);225}226 227bool fromJSON(const json::Value &Params, Configuration &C, json::Path P) {228 json::ObjectMapper O(Params, P);229 return O.mapOptional("debuggerRoot", C.debuggerRoot) &&230 O.mapOptional("enableAutoVariableSummaries",231 C.enableAutoVariableSummaries) &&232 O.mapOptional("enableSyntheticChildDebugging",233 C.enableSyntheticChildDebugging) &&234 O.mapOptional("displayExtendedBacktrace",235 C.displayExtendedBacktrace) &&236 O.mapOptional("stopOnEntry", C.stopOnEntry) &&237 O.mapOptional("commandEscapePrefix", C.commandEscapePrefix) &&238 O.mapOptional("customFrameFormat", C.customFrameFormat) &&239 O.mapOptional("customThreadFormat", C.customThreadFormat) &&240 O.mapOptional("sourcePath", C.sourcePath) &&241 O.mapOptional("initCommands", C.initCommands) &&242 O.mapOptional("preRunCommands", C.preRunCommands) &&243 O.mapOptional("postRunCommands", C.postRunCommands) &&244 O.mapOptional("stopCommands", C.stopCommands) &&245 O.mapOptional("exitCommands", C.exitCommands) &&246 O.mapOptional("terminateCommands", C.terminateCommands) &&247 O.mapOptional("program", C.program) &&248 O.mapOptional("targetTriple", C.targetTriple) &&249 O.mapOptional("platformName", C.platformName) &&250 parseSourceMap(Params, C.sourceMap, P) &&251 parseTimeout(Params, C.timeout, P);252}253 254bool fromJSON(const json::Value &Params, BreakpointLocationsArguments &BLA,255 json::Path P) {256 json::ObjectMapper O(Params, P);257 return O && O.map("source", BLA.source) && O.map("line", BLA.line) &&258 O.mapOptional("column", BLA.column) &&259 O.mapOptional("endLine", BLA.endLine) &&260 O.mapOptional("endColumn", BLA.endColumn);261}262 263json::Value toJSON(const BreakpointLocationsResponseBody &BLRB) {264 return json::Object{{"breakpoints", BLRB.breakpoints}};265}266 267bool fromJSON(const json::Value &Params, Console &C, json::Path P) {268 auto oldFormatConsole = Params.getAsBoolean();269 if (oldFormatConsole) {270 C = *oldFormatConsole ? eConsoleIntegratedTerminal : eConsoleInternal;271 return true;272 }273 auto newFormatConsole = Params.getAsString();274 if (!newFormatConsole) {275 P.report("expected a string");276 return false;277 }278 279 std::optional<Console> console =280 StringSwitch<std::optional<Console>>(*newFormatConsole)281 .Case("internalConsole", eConsoleInternal)282 .Case("integratedTerminal", eConsoleIntegratedTerminal)283 .Case("externalTerminal", eConsoleExternalTerminal)284 .Default(std::nullopt);285 if (!console) {286 P.report("unexpected value, expected 'internalConsole', "287 "'integratedTerminal' or 'externalTerminal'");288 return false;289 }290 291 C = *console;292 return true;293}294 295bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,296 json::Path P) {297 json::ObjectMapper O(Params, P);298 return O && fromJSON(Params, LRA.configuration, P) &&299 O.mapOptional("noDebug", LRA.noDebug) &&300 O.mapOptional("launchCommands", LRA.launchCommands) &&301 O.mapOptional("cwd", LRA.cwd) && O.mapOptional("args", LRA.args) &&302 O.mapOptional("detachOnError", LRA.detachOnError) &&303 O.mapOptional("disableASLR", LRA.disableASLR) &&304 O.mapOptional("disableSTDIO", LRA.disableSTDIO) &&305 O.mapOptional("shellExpandArguments", LRA.shellExpandArguments) &&306 O.mapOptional("runInTerminal", LRA.console) &&307 O.mapOptional("console", LRA.console) &&308 O.mapOptional("stdio", LRA.stdio) && parseEnv(Params, LRA.env, P);309}310 311bool fromJSON(const json::Value &Params, AttachRequestArguments &ARA,312 json::Path P) {313 json::ObjectMapper O(Params, P);314 return O && fromJSON(Params, ARA.configuration, P) &&315 O.mapOptional("attachCommands", ARA.attachCommands) &&316 O.mapOptional("pid", ARA.pid) &&317 O.mapOptional("waitFor", ARA.waitFor) &&318 O.mapOptional("gdb-remote-port", ARA.gdbRemotePort) &&319 O.mapOptional("gdb-remote-hostname", ARA.gdbRemoteHostname) &&320 O.mapOptional("coreFile", ARA.coreFile) &&321 O.mapOptional("targetId", ARA.targetId) &&322 O.mapOptional("debuggerId", ARA.debuggerId);323}324 325bool fromJSON(const json::Value &Params, ContinueArguments &CA, json::Path P) {326 json::ObjectMapper O(Params, P);327 return O && O.map("threadId", CA.threadId) &&328 O.mapOptional("singleThread", CA.singleThread);329}330 331json::Value toJSON(const ContinueResponseBody &CRB) {332 json::Object Body{{"allThreadsContinued", CRB.allThreadsContinued}};333 return std::move(Body);334}335 336bool fromJSON(const json::Value &Params, CompletionsArguments &CA,337 json::Path P) {338 json::ObjectMapper O(Params, P);339 return O && O.map("text", CA.text) && O.map("column", CA.column) &&340 O.mapOptional("frameId", CA.frameId) && O.mapOptional("line", CA.line);341}342 343json::Value toJSON(const CompletionsResponseBody &CRB) {344 return json::Object{{"targets", CRB.targets}};345}346 347bool fromJSON(const json::Value &Params, SetVariableArguments &SVA,348 json::Path P) {349 json::ObjectMapper O(Params, P);350 return O && O.map("variablesReference", SVA.variablesReference) &&351 O.map("name", SVA.name) && O.map("value", SVA.value) &&352 O.mapOptional("format", SVA.format);353}354 355json::Value toJSON(const SetVariableResponseBody &SVR) {356 json::Object Body{{"value", SVR.value}};357 358 if (!SVR.type.empty())359 Body.insert({"type", SVR.type});360 if (SVR.variablesReference)361 Body.insert({"variablesReference", SVR.variablesReference});362 if (SVR.namedVariables)363 Body.insert({"namedVariables", SVR.namedVariables});364 if (SVR.indexedVariables)365 Body.insert({"indexedVariables", SVR.indexedVariables});366 if (SVR.memoryReference != LLDB_INVALID_ADDRESS)367 Body.insert(368 {"memoryReference", EncodeMemoryReference(SVR.memoryReference)});369 if (SVR.valueLocationReference)370 Body.insert({"valueLocationReference", SVR.valueLocationReference});371 372 return json::Value(std::move(Body));373}374 375bool fromJSON(const json::Value &Params, ScopesArguments &SCA, json::Path P) {376 json::ObjectMapper O(Params, P);377 return O && O.map("frameId", SCA.frameId);378}379 380json::Value toJSON(const ScopesResponseBody &SCR) {381 return json::Object{{"scopes", SCR.scopes}};382}383 384bool fromJSON(const json::Value &Params, SourceArguments &SA, json::Path P) {385 json::ObjectMapper O(Params, P);386 return O && O.map("source", SA.source) &&387 O.map("sourceReference", SA.sourceReference);388}389 390json::Value toJSON(const SourceResponseBody &SA) {391 json::Object Result{{"content", SA.content}};392 393 if (SA.mimeType)394 Result.insert({"mimeType", SA.mimeType});395 396 return std::move(Result);397}398 399bool fromJSON(const json::Value &Params, NextArguments &NA, json::Path P) {400 json::ObjectMapper OM(Params, P);401 return OM && OM.map("threadId", NA.threadId) &&402 OM.mapOptional("singleThread", NA.singleThread) &&403 OM.mapOptional("granularity", NA.granularity);404}405 406bool fromJSON(const json::Value &Params, StepInArguments &SIA, json::Path P) {407 json::ObjectMapper OM(Params, P);408 return OM && OM.map("threadId", SIA.threadId) &&409 OM.map("targetId", SIA.targetId) &&410 OM.mapOptional("singleThread", SIA.singleThread) &&411 OM.mapOptional("granularity", SIA.granularity);412}413 414bool fromJSON(const llvm::json::Value &Params, StepInTargetsArguments &SITA,415 llvm::json::Path P) {416 json::ObjectMapper OM(Params, P);417 return OM && OM.map("frameId", SITA.frameId);418}419 420llvm::json::Value toJSON(const StepInTargetsResponseBody &SITR) {421 return llvm::json::Object{{"targets", SITR.targets}};422}423 424bool fromJSON(const json::Value &Params, StepOutArguments &SOA, json::Path P) {425 json::ObjectMapper OM(Params, P);426 return OM && OM.map("threadId", SOA.threadId) &&427 OM.mapOptional("singleThread", SOA.singleThread) &&428 OM.mapOptional("granularity", SOA.granularity);429}430 431bool fromJSON(const json::Value &Params, SetBreakpointsArguments &SBA,432 json::Path P) {433 json::ObjectMapper O(Params, P);434 return O && O.map("source", SBA.source) &&435 O.map("breakpoints", SBA.breakpoints) && O.map("lines", SBA.lines) &&436 O.map("sourceModified", SBA.sourceModified);437}438 439json::Value toJSON(const SetBreakpointsResponseBody &SBR) {440 return json::Object{{"breakpoints", SBR.breakpoints}};441}442 443bool fromJSON(const json::Value &Params, SetFunctionBreakpointsArguments &SFBA,444 json::Path P) {445 json::ObjectMapper O(Params, P);446 return O && O.map("breakpoints", SFBA.breakpoints);447}448 449json::Value toJSON(const SetFunctionBreakpointsResponseBody &SFBR) {450 return json::Object{{"breakpoints", SFBR.breakpoints}};451}452 453bool fromJSON(const json::Value &Params,454 SetInstructionBreakpointsArguments &SIBA, json::Path P) {455 json::ObjectMapper O(Params, P);456 return O && O.map("breakpoints", SIBA.breakpoints);457}458 459json::Value toJSON(const SetInstructionBreakpointsResponseBody &SIBR) {460 return json::Object{{"breakpoints", SIBR.breakpoints}};461}462 463bool fromJSON(const json::Value &Params, DataBreakpointInfoArguments &DBIA,464 json::Path P) {465 json::ObjectMapper O(Params, P);466 return O && O.map("variablesReference", DBIA.variablesReference) &&467 O.map("name", DBIA.name) && O.mapOptional("frameId", DBIA.frameId) &&468 O.map("bytes", DBIA.bytes) && O.map("asAddress", DBIA.asAddress) &&469 O.map("mode", DBIA.mode);470}471 472json::Value toJSON(const DataBreakpointInfoResponseBody &DBIRB) {473 json::Object result{{"dataId", DBIRB.dataId},474 {"description", DBIRB.description}};475 476 if (DBIRB.accessTypes)477 result["accessTypes"] = *DBIRB.accessTypes;478 if (DBIRB.canPersist)479 result["canPersist"] = *DBIRB.canPersist;480 481 return result;482}483 484bool fromJSON(const json::Value &Params, SetDataBreakpointsArguments &SDBA,485 json::Path P) {486 json::ObjectMapper O(Params, P);487 return O && O.map("breakpoints", SDBA.breakpoints);488}489 490json::Value toJSON(const SetDataBreakpointsResponseBody &SDBR) {491 return json::Object{{"breakpoints", SDBR.breakpoints}};492}493 494bool fromJSON(const json::Value &Params, SetExceptionBreakpointsArguments &Args,495 json::Path P) {496 json::ObjectMapper O(Params, P);497 return O && O.map("filters", Args.filters) &&498 O.mapOptional("filterOptions", Args.filterOptions);499}500 501json::Value toJSON(const SetExceptionBreakpointsResponseBody &B) {502 json::Object result;503 if (!B.breakpoints.empty())504 result.insert({"breakpoints", B.breakpoints});505 return result;506}507 508json::Value toJSON(const ThreadsResponseBody &TR) {509 return json::Object{{"threads", TR.threads}};510}511 512bool fromJSON(const llvm::json::Value &Params, DisassembleArguments &DA,513 llvm::json::Path P) {514 json::ObjectMapper O(Params, P);515 return O &&516 DecodeMemoryReference(Params, "memoryReference", DA.memoryReference, P,517 /*required=*/true) &&518 O.mapOptional("offset", DA.offset) &&519 O.mapOptional("instructionOffset", DA.instructionOffset) &&520 O.map("instructionCount", DA.instructionCount) &&521 O.mapOptional("resolveSymbols", DA.resolveSymbols);522}523 524json::Value toJSON(const DisassembleResponseBody &DRB) {525 return json::Object{{"instructions", DRB.instructions}};526}527 528bool fromJSON(const json::Value &Params, ReadMemoryArguments &RMA,529 json::Path P) {530 json::ObjectMapper O(Params, P);531 return O &&532 DecodeMemoryReference(Params, "memoryReference", RMA.memoryReference,533 P, /*required=*/true) &&534 O.map("count", RMA.count) && O.mapOptional("offset", RMA.offset);535}536 537json::Value toJSON(const ReadMemoryResponseBody &RMR) {538 json::Object result{{"address", EncodeMemoryReference(RMR.address)}};539 540 if (RMR.unreadableBytes != 0)541 result.insert({"unreadableBytes", RMR.unreadableBytes});542 if (!RMR.data.empty())543 result.insert({"data", llvm::encodeBase64(RMR.data)});544 545 return result;546}547 548bool fromJSON(const json::Value &Params, ModulesArguments &MA, json::Path P) {549 json::ObjectMapper O(Params, P);550 return O && O.mapOptional("startModule", MA.startModule) &&551 O.mapOptional("moduleCount", MA.moduleCount);552}553 554json::Value toJSON(const ModulesResponseBody &MR) {555 json::Object result{{"modules", MR.modules}};556 if (MR.totalModules != 0)557 result.insert({"totalModules", MR.totalModules});558 559 return result;560}561 562bool fromJSON(const json::Value &Param, VariablesArguments::VariablesFilter &VA,563 json::Path Path) {564 auto rawFilter = Param.getAsString();565 if (!rawFilter) {566 Path.report("expected a string");567 return false;568 }569 std::optional<VariablesArguments::VariablesFilter> filter =570 StringSwitch<std::optional<VariablesArguments::VariablesFilter>>(571 *rawFilter)572 .Case("indexed", VariablesArguments::eVariablesFilterIndexed)573 .Case("named", VariablesArguments::eVariablesFilterNamed)574 .Default(std::nullopt);575 if (!filter) {576 Path.report("unexpected value, expected 'named' or 'indexed'");577 return false;578 }579 580 VA = *filter;581 return true;582}583 584bool fromJSON(const json::Value &Param, VariablesArguments &VA,585 json::Path Path) {586 json::ObjectMapper O(Param, Path);587 return O && O.map("variablesReference", VA.variablesReference) &&588 O.mapOptional("filter", VA.filter) &&589 O.mapOptional("start", VA.start) && O.mapOptional("count", VA.count) &&590 O.mapOptional("format", VA.format);591}592 593json::Value toJSON(const VariablesResponseBody &VRB) {594 return json::Object{{"variables", VRB.variables}};595}596 597bool fromJSON(const json::Value &Params, WriteMemoryArguments &WMA,598 json::Path P) {599 json::ObjectMapper O(Params, P);600 601 return O &&602 DecodeMemoryReference(Params, "memoryReference", WMA.memoryReference,603 P, /*required=*/true) &&604 O.mapOptional("allowPartial", WMA.allowPartial) &&605 O.mapOptional("offset", WMA.offset) && O.map("data", WMA.data);606}607 608json::Value toJSON(const WriteMemoryResponseBody &WMR) {609 json::Object result;610 611 if (WMR.bytesWritten != 0)612 result.insert({"bytesWritten", WMR.bytesWritten});613 return result;614}615 616bool fromJSON(const llvm::json::Value &Params, ModuleSymbolsArguments &Args,617 llvm::json::Path P) {618 json::ObjectMapper O(Params, P);619 return O && O.map("moduleId", Args.moduleId) &&620 O.map("moduleName", Args.moduleName) &&621 O.mapOptional("startIndex", Args.startIndex) &&622 O.mapOptional("count", Args.count);623}624 625llvm::json::Value toJSON(const ModuleSymbolsResponseBody &DGMSR) {626 json::Object result;627 result.insert({"symbols", DGMSR.symbols});628 return result;629}630 631bool fromJSON(const json::Value &Params, ExceptionInfoArguments &Args,632 json::Path Path) {633 json::ObjectMapper O(Params, Path);634 return O && O.map("threadId", Args.threadId);635}636 637json::Value toJSON(const ExceptionInfoResponseBody &ERB) {638 json::Object result{{"exceptionId", ERB.exceptionId},639 {"breakMode", ERB.breakMode}};640 641 if (!ERB.description.empty())642 result.insert({"description", ERB.description});643 if (ERB.details.has_value())644 result.insert({"details", *ERB.details});645 return result;646}647 648static bool fromJSON(const llvm::json::Value &Params, EvaluateContext &C,649 llvm::json::Path P) {650 auto rawContext = Params.getAsString();651 if (!rawContext) {652 P.report("expected a string");653 return false;654 }655 C = StringSwitch<EvaluateContext>(*rawContext)656 .Case("watch", EvaluateContext::eEvaluateContextWatch)657 .Case("repl", EvaluateContext::eEvaluateContextRepl)658 .Case("hover", EvaluateContext::eEvaluateContextHover)659 .Case("clipboard", EvaluateContext::eEvaluateContextClipboard)660 .Case("variables", EvaluateContext::eEvaluateContextVariables)661 .Default(eEvaluateContextUnknown);662 return true;663}664 665bool fromJSON(const llvm::json::Value &Params, EvaluateArguments &Args,666 llvm::json::Path P) {667 json::ObjectMapper O(Params, P);668 return O && O.map("expression", Args.expression) &&669 O.mapOptional("frameId", Args.frameId) &&670 O.mapOptional("line", Args.line) &&671 O.mapOptional("column", Args.column) &&672 O.mapOptional("source", Args.source) &&673 O.mapOptional("context", Args.context) &&674 O.mapOptional("format", Args.format);675}676 677llvm::json::Value toJSON(const EvaluateResponseBody &Body) {678 json::Object result{{"result", Body.result},679 {"variablesReference", Body.variablesReference}};680 681 if (!Body.type.empty())682 result.insert({"type", Body.type});683 if (Body.presentationHint)684 result.insert({"presentationHint", Body.presentationHint});685 if (Body.namedVariables)686 result.insert({"namedVariables", Body.namedVariables});687 if (Body.indexedVariables)688 result.insert({"indexedVariables", Body.indexedVariables});689 if (!Body.memoryReference.empty())690 result.insert({"memoryReference", Body.memoryReference});691 if (Body.valueLocationReference != LLDB_DAP_INVALID_VALUE_LOC)692 result.insert({"valueLocationReference", Body.valueLocationReference});693 694 return result;695}696 697} // namespace lldb_dap::protocol698