195 lines · c
1//===-- ProtocolBase.h ----------------------------------------------------===//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// This file contains POD structs based on the DAP specification at10// https://microsoft.github.io/debug-adapter-protocol/specification11//12// This is not meant to be a complete implementation, new interfaces are added13// when they're needed.14//15// Each struct has a toJSON and fromJSON function, that converts between16// the struct and a JSON representation. (See JSON.h)17//18//===----------------------------------------------------------------------===//19 20#ifndef LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_BASE_H21#define LLDB_TOOLS_LLDB_DAP_PROTOCOL_PROTOCOL_BASE_H22 23#include "llvm/Support/JSON.h"24#include <cstdint>25#include <optional>26#include <string>27#include <variant>28 29namespace lldb_dap::protocol {30 31// MARK: Base Protocol32 33/// Message unique identifier type.34using Id = int64_t;35 36/// A unique identifier that indicates the `seq` field should be calculated by37/// the current session.38static constexpr Id kCalculateSeq = INT64_MAX;39 40/// A client or debug adapter initiated request.41struct Request {42 /// The command to execute.43 std::string command;44 45 /// Object containing arguments for the command.46 ///47 /// Request handlers are expected to validate the arguments, which is handled48 /// by `RequestHandler`.49 std::optional<llvm::json::Value> arguments = std::nullopt;50 51 /// Sequence number of the message (also known as message ID). The `seq` for52 /// the first message sent by a client or debug adapter is 1, and for each53 /// subsequent message is 1 greater than the previous message sent by that54 /// actor. `seq` can be used to order requests, responses, and events, and to55 /// associate requests with their corresponding responses. For protocol56 /// messages of type `request` the sequence number can be used to cancel the57 /// request.58 Id seq = kCalculateSeq;59};60llvm::json::Value toJSON(const Request &);61bool fromJSON(const llvm::json::Value &, Request &, llvm::json::Path);62bool operator==(const Request &, const Request &);63 64/// A debug adapter initiated event.65struct Event {66 /// Type of event.67 std::string event;68 69 /// Event-specific information.70 std::optional<llvm::json::Value> body = std::nullopt;71 72 /// Sequence number of the message (also known as message ID). The `seq` for73 /// the first message sent by a client or debug adapter is 1, and for each74 /// subsequent message is 1 greater than the previous message sent by that75 /// actor. `seq` can be used to order requests, responses, and events, and to76 /// associate requests with their corresponding responses. For protocol77 /// messages of type `request` the sequence number can be used to cancel the78 /// request.79 Id seq = kCalculateSeq;80};81llvm::json::Value toJSON(const Event &);82bool fromJSON(const llvm::json::Value &, Event &, llvm::json::Path);83bool operator==(const Event &, const Event &);84 85enum ResponseMessage : unsigned {86 /// The request was cancelled87 eResponseMessageCancelled,88 /// The request may be retried once the adapter is in a 'stopped' state89 eResponseMessageNotStopped,90};91 92/// Response for a request.93struct Response {94 /// Sequence number of the corresponding request.95 Id request_seq = 0;96 97 /// The command requested.98 std::string command;99 100 /// Outcome of the request. If true, the request was successful and the `body`101 /// attribute may contain the result of the request. If the value is false,102 /// the attribute `message` contains the error in short form and the `body`103 /// may contain additional information (see `ErrorMessage`).104 bool success = false;105 106 // FIXME: Migrate usage of fallback string to ErrorMessage107 108 /// Contains the raw error in short form if `success` is false. This raw error109 /// might be interpreted by the client and is not shown in the UI. Some110 /// predefined values exist.111 std::optional<std::variant<ResponseMessage, std::string>> message =112 std::nullopt;113 114 /// Contains request result if success is true and error details if success is115 /// false.116 ///117 /// Request handlers are expected to build an appropriate body, see118 /// `RequestHandler`.119 std::optional<llvm::json::Value> body = std::nullopt;120 121 /// Sequence number of the message (also known as message ID). The `seq` for122 /// the first message sent by a client or debug adapter is 1, and for each123 /// subsequent message is 1 greater than the previous message sent by that124 /// actor. `seq` can be used to order requests, responses, and events, and to125 /// associate requests with their corresponding responses. For protocol126 /// messages of type `request` the sequence number can be used to cancel the127 /// request.128 Id seq = kCalculateSeq;129};130bool fromJSON(const llvm::json::Value &, Response &, llvm::json::Path);131llvm::json::Value toJSON(const Response &);132bool operator==(const Response &, const Response &);133 134/// A structured message object. Used to return errors from requests.135struct ErrorMessage {136 /// Unique (within a debug adapter implementation) identifier for the message.137 /// The purpose of these error IDs is to help extension authors that have the138 /// requirement that every user visible error message needs a corresponding139 /// error number, so that users or customer support can find information about140 /// the specific error more easily.141 uint64_t id = 0;142 143 /// A format string for the message. Embedded variables have the form144 /// `{name}`. If variable name starts with an underscore character, the145 /// variable does not contain user data (PII) and can be safely used for146 /// telemetry purposes.147 std::string format;148 149 /// An object used as a dictionary for looking up the variables in the format150 /// string.151 std::optional<std::map<std::string, std::string>> variables;152 153 /// If true send to telemetry.154 bool sendTelemetry = false;155 156 /// If true show user.157 bool showUser = false;158 159 /// A url where additional information about this message can be found.160 std::optional<std::string> url;161 162 /// A label that is presented to the user as the UI for opening the url.163 std::optional<std::string> urlLabel;164};165bool fromJSON(const llvm::json::Value &, ErrorMessage &, llvm::json::Path);166llvm::json::Value toJSON(const ErrorMessage &);167 168/// An individual protocol message of requests, responses, and events.169using Message = std::variant<Request, Response, Event>;170bool fromJSON(const llvm::json::Value &, Message &, llvm::json::Path);171llvm::json::Value toJSON(const Message &);172bool operator==(const Message &, const Message &);173 174inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Message &V) {175 OS << toJSON(V);176 return OS;177}178 179/// On error (whenever `success` is false), the body can provide more details.180struct ErrorResponseBody {181 /// A structured error message.182 std::optional<ErrorMessage> error;183};184llvm::json::Value toJSON(const ErrorResponseBody &);185 186/// This is a placehold for requests with an empty, null or undefined arguments.187using EmptyArguments = std::optional<std::monostate>;188 189/// This is just an acknowledgement, so no body field is required.190using VoidResponse = llvm::Error;191 192} // namespace lldb_dap::protocol193 194#endif195