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"
76 bool hasError() const final {
return ferror(in); }
91 bool prettyOutput =
false)
92 : in(std::move(in)), out(out), prettyOutput(prettyOutput) {}
96 bool prettyOutput =
false)
98 prettyOutput(prettyOutput) {}
101 void notify(StringRef method, llvm::json::Value params);
102 void call(StringRef method, llvm::json::Value params, llvm::json::Value
id);
110 bool handleMessage(llvm::json::Value msg,
MessageHandler &handler);
112 void sendMessage(llvm::json::Value msg);
116 std::unique_ptr<JSONTransportInput> in;
130 template <
typename T>
135 template <
typename T>
140 template <
typename T>
142 llvm::unique_function<void(
const T &, llvm::json::Value
id)>;
147 template <
typename T>
157 bool onCall(StringRef
method, llvm::json::Value params, llvm::json::Value
id);
160 template <
typename T>
162 StringRef payloadName, StringRef payloadKind) {
164 llvm::json::Path::Root root;
166 return std::move(result);
170 llvm::raw_string_ostream os(context);
171 root.printErrorContext(raw, os);
174 return llvm::make_error<LSPError>(
175 llvm::formatv(
"failed to decode {0} {1}: {2}", payloadName, payloadKind,
176 fmt_consume(root.getError())),
180 template <
typename Param,
typename Result,
typename ThisT>
184 thisPtr](llvm::json::Value rawParams,
188 return reply(param.takeError());
189 (thisPtr->*handler)(*param, std::move(reply));
193 template <
typename Param,
typename ThisT>
195 void (ThisT::*handler)(
const Param &)) {
197 thisPtr](llvm::json::Value rawParams) {
199 parse<Param>(rawParams,
method,
"notification");
201 return llvm::consumeError(
202 llvm::handleErrors(param.takeError(), [](
const LSPError &lspError) {
203 Logger::error(
"JSON parsing error: {0}",
204 lspError.message.c_str());
207 (thisPtr->*handler)(*param);
212 template <
typename T>
214 return [&,
method](
const T ¶ms) {
215 std::lock_guard<std::mutex> transportLock(transportOutputMutex);
225 template <
typename Param,
typename Result>
229 return [&,
method, callback](
const Param ¶m, llvm::json::Value id) {
230 auto callbackWrapper = [
method, callback = std::move(callback)](
231 llvm::json::Value id,
234 return callback(std::move(
id), value.takeError());
236 std::string responseName = llvm::formatv(
"reply:{0}({1})",
method,
id);
238 parse<Result>(*value, responseName,
"response");
240 return callback(std::move(
id), result.takeError());
242 return callback(std::move(
id), *result);
246 std::lock_guard<std::mutex> lock(responseHandlersMutex);
247 responseHandlers.insert(
251 std::lock_guard<std::mutex> transportLock(transportOutputMutex);
253 transport.
call(
method, llvm::json::Value(param),
id);
258 template <
typename HandlerT>
259 using HandlerMap = llvm::StringMap<llvm::unique_function<HandlerT>>;
261 HandlerMap<void(llvm::json::Value)> notificationHandlers;
267 using ResponseHandlerTy =
268 std::pair<std::string, OutgoingRequestCallback<llvm::json::Value>>;
270 llvm::StringMap<ResponseHandlerTy> responseHandlers;
272 std::mutex responseHandlersMutex;
277 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::unique_ptr< JSONTransportInput > in, raw_ostream &out, bool prettyOutput=false)
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)