16#include <system_error>
33 Reply(
const llvm::json::Value &Id, StringRef Method, JSONTransport &Transport,
34 std::mutex &TransportOutputMutex);
36 Reply &operator=(Reply &&) =
delete;
37 Reply(
const Reply &) =
delete;
38 Reply &operator=(
const Reply &) =
delete;
40 void operator()(llvm::Expected<llvm::json::Value> Reply);
44 std::atomic<bool> Replied = {
false};
46 JSONTransport *Transport;
47 std::mutex &TransportOutputMutex;
54 TransportOutputMutex(TransportOutputMutex) {}
56Reply::Reply(Reply &&
Other)
59 TransportOutputMutex(
Other.TransportOutputMutex) {
60 Other.Transport =
nullptr;
64 if (Replied.exchange(
true)) {
66 assert(
false &&
"must reply to each call only once!");
69 assert(Transport &&
"expected valid transport to reply to");
71 std::lock_guard<std::mutex> TransportLock(TransportOutputMutex);
74 Transport->
reply(std::move(Id), std::move(Reply));
78 Transport->
reply(std::move(Id), std::move(
Error));
88MessageHandler::handleParseError(
const llvm::json::Value &Raw,
89 StringRef PayloadName, StringRef PayloadKind,
90 const llvm::json::Path::Root &Root) {
93 llvm::raw_string_ostream Os(
Context);
98 llvm::formatv(
"failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
100 ErrorCode::InvalidParams);
108 if (
Method ==
"$cancel") {
111 auto It = NotificationHandlers.find(
Method);
112 if (It != NotificationHandlers.end())
113 It->second(std::move(
Value));
122 Reply Reply(Id,
Method, Transport, TransportOutputMutex);
124 auto It = MethodHandlers.find(
Method);
125 if (It != MethodHandlers.end()) {
126 It->second(std::move(Params), std::move(Reply));
138 ResponseHandlerTy ResponseHandler;
140 std::lock_guard<std::mutex> responseHandlersLock(ResponseHandlersMutex);
142 if (It != ResponseHandlers.end()) {
143 ResponseHandler = std::move(It->second);
144 ResponseHandlers.erase(It);
149 if (ResponseHandler.second) {
150 Logger::info(
"--> reply:{0}({1})", ResponseHandler.first, Id);
151 ResponseHandler.second(std::move(Id), std::move(Result));
154 "received a reply with ID {0}, but there was no such outgoing request",
171 Message = LspError.message;
172 Code = LspError.code;
179 {
"message", std::move(Message)},
180 {
"code", int64_t(Code)},
186 StringRef Msg = O.getString(
"message").value_or(
"Unspecified error");
187 if (std::optional<int64_t> Code = O.getInteger(
"code"))
197 {
"params", std::move(Params)},
204 {
"id", std::move(Id)},
206 {
"params", std::move(Params)},
214 {
"id", std::move(Id)},
215 {
"result", std::move(*Result)},
221 {
"id", std::move(Id)},
228 while (!In->isEndOfInput()) {
229 if (In->hasError()) {
231 std::error_code(errno, std::system_category()));
236 if (!handleMessage(std::move(*Doc), Handler))
250 Out <<
"Content-Length: " <<
OutputBuffer.size() <<
"\r\n\r\n"
261 Object->getString(
"jsonrpc") != std::optional<StringRef>(
"2.0"))
265 std::optional<llvm::json::Value> Id;
268 std::optional<StringRef>
Method =
Object->getString(
"method");
274 if (
auto *Err =
Object->getObject(
"error"))
279 Result = std::move(*R);
280 return Handler.
onReply(std::move(*Id), std::move(Result));
286 Params = std::move(*
P);
289 return Handler.
onCall(*
Method, std::move(Params), std::move(*Id));
298 static constexpr int BufSize = 128;
303 if (!std::fgets(&Out[
Size], BufSize, In))
310 size_t Read = std::strlen(&Out[
Size]);
326 unsigned long long ContentLength = 0;
346 if (ContentLength == 0 || ContentLength > 1 << 30)
349 Json.resize(ContentLength);
350 for (
size_t Pos = 0,
Read; Pos < ContentLength; Pos +=
Read) {
351 Read = std::fread(&Json[Pos], 1, ContentLength - Pos, In);
377 if (LineRef ==
"// -----")
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Mark last scratch load
#define LLVM_ATTRIBUTE_NOINLINE
LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, mark a method "not for inl...
This file defines the SmallString class.
static llvm::json::Object encodeError(llvm::Error Error)
Encode the given error as a JSON object.
LogicalResult readLine(std::FILE *In, SmallVectorImpl< char > &Out)
Tries to read a line up to and including .
llvm::Error decodeError(const llvm::json::Object &O)
Decode the given JSON object into an error.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void resize_for_overwrite(size_type N)
Like resize, but T is POD, the new values won't be initialized.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
StringRef trim(char Char) const
Return string with consecutive Char characters starting from the left and right removed.
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
An Object is a JSON object, which maps strings to heterogenous JSON values.
LLVM_ABI void printErrorContext(const Value &, llvm::raw_ostream &) const
Print the root value with the error shown inline as a comment.
LLVM_ABI Error getError() const
Returns the last error reported, or else a generic error.
A Value is an JSON value of unknown type.
A transport class that performs the JSON-RPC communication with the LSP client.
LLVM_ABI void reply(llvm::json::Value Id, llvm::Expected< llvm::json::Value > Result)
LLVM_ABI llvm::Error run(MessageHandler &Handler)
Start executing the JSON-RPC transport.
LLVM_ABI void notify(StringRef Method, llvm::json::Value Params)
The following methods are used to send a message to the LSP client.
LLVM_ABI void call(StringRef Method, llvm::json::Value Params, llvm::json::Value Id)
This class models an LSP error as an llvm::Error.
static void error(const char *Fmt, Ts &&...Vals)
static void debug(const char *Fmt, Ts &&...Vals)
Initiate a log message at various severity levels.
static void info(const char *Fmt, Ts &&...Vals)
A handler used to process the incoming transport messages.
LLVM_ABI bool onNotify(StringRef Method, llvm::json::Value Value)
LLVM_ABI bool onCall(StringRef Method, llvm::json::Value Params, llvm::json::Value Id)
LLVM_ABI bool onReply(llvm::json::Value Id, llvm::Expected< llvm::json::Value > Result)
A raw_ostream that writes to an SmallVector or SmallString.
LLVM_ABI llvm::Expected< Value > parse(llvm::StringRef JSON)
Parses the provided JSON source, or returns a ParseError.
This is an optimization pass for GlobalISel generic memory operations.
support::detail::ErrorAdapter fmt_consume(Error &&Item)
bool succeeded(LogicalResult Result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
bool failed(LogicalResult Result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
LogicalResult failure(bool IsFailure=true)
Utility function to generate a LogicalResult.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
static std::string debugString(T &&Op)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool getAsUnsignedInteger(StringRef Str, unsigned Radix, unsigned long long &Result)
Helper functions for StringRef::getAsInteger.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void consumeError(Error Err)
Consume a Error without doing anything.
Implement std::hash so that hash_code can be used in STL containers.
This class represents an efficient way to signal success or failure.