brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.9 KiB · d53a520 Raw
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