15 #ifndef MLIR_TOOLS_LSPSERVERSUPPORT_TRANSPORT_H
16 #define MLIR_TOOLS_LSPSERVERSUPPORT_TRANSPORT_H
22 #include "llvm/ADT/FunctionExtras.h"
23 #include "llvm/ADT/StringMap.h"
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/Support/FormatAdapters.h"
26 #include "llvm/Support/JSON.h"
27 #include "llvm/Support/raw_ostream.h"
52 bool prettyOutput =
false)
53 : in(in), out(out), style(style), prettyOutput(prettyOutput) {}
56 void notify(StringRef method, llvm::json::Value params);
57 void call(StringRef method, llvm::json::Value params, llvm::json::Value
id);
65 bool handleMessage(llvm::json::Value msg,
MessageHandler &handler);
67 void sendMessage(llvm::json::Value msg);
70 LogicalResult readMessage(std::string &json) {
72 : readStandardMessage(json);
74 LogicalResult readDelimitedMessage(std::string &json);
75 LogicalResult readStandardMessage(std::string &json);
100 template <
typename T>
105 template <
typename T>
107 llvm::unique_function<void(
const T &, llvm::json::Value
id)>;
112 template <
typename T>
122 bool onCall(StringRef
method, llvm::json::Value params, llvm::json::Value
id);
125 template <
typename T>
127 StringRef payloadName, StringRef payloadKind) {
129 llvm::json::Path::Root root;
131 return std::move(result);
135 llvm::raw_string_ostream os(context);
136 root.printErrorContext(raw, os);
139 return llvm::make_error<LSPError>(
140 llvm::formatv(
"failed to decode {0} {1}: {2}", payloadName, payloadKind,
141 fmt_consume(root.getError())),
145 template <
typename Param,
typename Result,
typename ThisT>
149 thisPtr](llvm::json::Value rawParams,
153 return reply(param.takeError());
154 (thisPtr->*handler)(*param, std::move(reply));
158 template <
typename Param,
typename ThisT>
160 void (ThisT::*handler)(
const Param &)) {
162 thisPtr](llvm::json::Value rawParams) {
164 parse<Param>(rawParams,
method,
"notification");
166 return llvm::consumeError(
167 llvm::handleErrors(param.takeError(), [](
const LSPError &lspError) {
168 Logger::error(
"JSON parsing error: {0}",
169 lspError.message.c_str());
172 (thisPtr->*handler)(*param);
177 template <
typename T>
179 return [&,
method](
const T ¶ms) {
180 std::lock_guard<std::mutex> transportLock(transportOutputMutex);
190 template <
typename Param,
typename Result>
194 return [&,
method, callback](
const Param ¶m, llvm::json::Value id) {
195 auto callbackWrapper = [
method, callback = std::move(callback)](
196 llvm::json::Value id,
199 return callback(std::move(
id), value.takeError());
201 std::string responseName = llvm::formatv(
"reply:{0}({1})",
method,
id);
203 parse<Result>(*value, responseName,
"response");
205 return callback(std::move(
id), result.takeError());
207 return callback(std::move(
id), *result);
211 std::lock_guard<std::mutex> lock(responseHandlersMutex);
212 responseHandlers.insert(
216 std::lock_guard<std::mutex> transportLock(transportOutputMutex);
218 transport.
call(
method, llvm::json::Value(param),
id);
223 template <
typename HandlerT>
224 using HandlerMap = llvm::StringMap<llvm::unique_function<HandlerT>>;
226 HandlerMap<void(llvm::json::Value)> notificationHandlers;
232 using ResponseHandlerTy =
233 std::pair<std::string, OutgoingRequestCallback<llvm::json::Value>>;
235 llvm::StringMap<ResponseHandlerTy> responseHandlers;
237 std::mutex responseHandlersMutex;
242 std::mutex transportOutputMutex;
A transport class that performs the JSON-RPC communication with the LSP client.
void notify(StringRef method, llvm::json::Value params)
The following methods are used to send a message to the LSP client.
JSONTransport(std::FILE *in, raw_ostream &out, JSONStreamStyle style=JSONStreamStyle::Standard, bool prettyOutput=false)
void call(StringRef method, llvm::json::Value params, llvm::json::Value id)
llvm::Error run(MessageHandler &handler)
Start executing the JSON-RPC transport.
void reply(llvm::json::Value id, llvm::Expected< llvm::json::Value > result)
This class models an LSP error as an llvm::Error.
static void info(const char *fmt, Ts &&...vals)
A handler used to process the incoming transport messages.
void notification(llvm::StringLiteral method, ThisT *thisPtr, void(ThisT::*handler)(const Param &))
bool onCall(StringRef method, llvm::json::Value params, llvm::json::Value id)
void method(llvm::StringLiteral method, ThisT *thisPtr, void(ThisT::*handler)(const Param &, Callback< Result >))
bool onReply(llvm::json::Value id, llvm::Expected< llvm::json::Value > result)
OutgoingNotification< T > outgoingNotification(llvm::StringLiteral method)
Create an OutgoingNotification object used for the given method.
static llvm::Expected< T > parse(const llvm::json::Value &raw, StringRef payloadName, StringRef payloadKind)
MessageHandler(JSONTransport &transport)
OutgoingRequest< Param > outgoingRequest(llvm::StringLiteral method, OutgoingRequestCallback< Result > callback)
Create an OutgoingRequest function that, when called, sends a request with the given method via the t...
bool onNotify(StringRef method, llvm::json::Value value)
llvm::unique_function< void(const T &)> OutgoingNotification
An OutgoingNotification<T> is a function used for outgoing notifications send to the client.
llvm::unique_function< void(const T &, llvm::json::Value id)> OutgoingRequest
An OutgoingRequest<T> is a function used for outgoing requests to send to the client.
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
std::function< void(llvm::json::Value, llvm::Expected< T >)> OutgoingRequestCallback
An OutgoingRequestCallback is invoked when an outgoing request to the client receives a response in t...
JSONStreamStyle
The encoding style of the JSON-RPC messages (both input and output).
@ Delimited
Messages are delimited by a '// --—' line. Comment lines start with //.
@ Standard
Encoding per the LSP specification, with mandatory Content-Length header.
bool fromJSON(const llvm::json::Value &value, URIForFile &result, llvm::json::Path path)
Include the generated interface declarations.
static std::string debugString(T &&op)