13 #include "llvm/Support/Errno.h"
14 #include "llvm/Support/Error.h"
29 case static_cast<int>(ErrorCode::ContentModified):
30 Code = ErrorCode::ContentModified;
31 Message =
"Request cancelled because the document was modified";
34 Code = ErrorCode::RequestCancelled;
35 Message =
"Request cancelled";
38 return llvm::Error::success();
43 return llvm::Error::success();
47 return llvm::json::Object{
48 {
"message", std::move(
Message)},
49 {
"code", int64_t(
Code)},
53 llvm::Error decodeError(
const llvm::json::Object &O) {
55 std::string(O.getString(
"message").getValueOr(
"Unspecified error"));
56 if (
auto Code = O.getInteger(
"code"))
57 return llvm::make_error<LSPError>(std::move(Msg),
ErrorCode(*
Code));
58 return llvm::make_error<llvm::StringError>(std::move(Msg),
59 llvm::inconvertibleErrorCode());
62 class JSONTransport :
public Transport {
64 JSONTransport(std::FILE *In, llvm::raw_ostream &
Out,
66 : In(In),
Out(
Out), InMirror(InMirror ? *InMirror :
llvm::nulls()),
67 Pretty(Pretty), Style(Style) {}
69 void notify(llvm::StringRef
Method, llvm::json::Value Params)
override {
70 sendMessage(llvm::json::Object{
73 {
"params", std::move(Params)},
76 void call(llvm::StringRef
Method, llvm::json::Value Params,
77 llvm::json::Value ID)
override {
78 sendMessage(llvm::json::Object{
80 {
"id", std::move(ID)},
82 {
"params", std::move(Params)},
85 void reply(llvm::json::Value ID,
86 llvm::Expected<llvm::json::Value> Result)
override {
88 sendMessage(llvm::json::Object{
90 {
"id", std::move(ID)},
91 {
"result", std::move(*Result)},
94 sendMessage(llvm::json::Object{
96 {
"id", std::move(ID)},
97 {
"error", encodeError(Result.takeError())},
102 llvm::Error loop(MessageHandler &Handler)
override {
105 return llvm::createStringError(
106 std::make_error_code(std::errc::operation_canceled),
107 "Got signal, shutting down");
109 return llvm::errorCodeToError(
110 std::error_code(errno, std::system_category()));
111 if (
auto JSON = readRawMessage()) {
112 if (
auto Doc = llvm::json::parse(*JSON)) {
113 vlog(Pretty ?
"<<< {0:2}\n" :
"<<< {0}\n", *Doc);
114 if (!handleMessage(std::move(*Doc), Handler))
115 return llvm::Error::success();
118 vlog(
"<<< {0}\n", *JSON);
123 return llvm::errorCodeToError(std::make_error_code(std::errc::io_error));
128 bool handleMessage(llvm::json::Value
Message, MessageHandler &Handler);
130 void sendMessage(llvm::json::Value
Message) {
132 llvm::raw_string_ostream
OS(S);
133 OS << llvm::formatv(Pretty ?
"{0:2}" :
"{0}",
Message);
135 Out <<
"Content-Length: " << S.size() <<
"\r\n\r\n" << S;
137 vlog(
">>> {0}\n", S);
141 llvm::Optional<std::string> readRawMessage() {
143 : readStandardMessage();
145 llvm::Optional<std::string> readDelimitedMessage();
146 llvm::Optional<std::string> readStandardMessage();
149 llvm::raw_ostream &
Out;
150 llvm::raw_ostream &InMirror;
155 bool JSONTransport::handleMessage(llvm::json::Value
Message,
156 MessageHandler &Handler) {
160 Object->getString(
"jsonrpc") != llvm::Optional<llvm::StringRef>(
"2.0")) {
161 elog(
"Not a JSON-RPC 2.0 message: {0:2}",
Message);
165 llvm::Optional<llvm::json::Value> ID;
166 if (
auto *I =
Object->get(
"id"))
171 elog(
"No method and no response ID: {0:2}",
Message);
174 if (
auto *Err =
Object->getObject(
"error"))
175 return Handler.onReply(std::move(*ID), decodeError(*Err));
177 llvm::json::Value Result =
nullptr;
178 if (
auto *R =
Object->get(
"result"))
179 Result = std::move(*R);
180 return Handler.onReply(std::move(*ID), std::move(Result));
183 llvm::json::Value Params =
nullptr;
184 if (
auto *P =
Object->get(
"params"))
185 Params = std::move(*P);
188 return Handler.onCall(*Method, std::move(Params), std::move(*ID));
190 return Handler.onNotify(*Method, std::move(Params));
195 bool readLine(std::FILE *In, std::string &
Out) {
196 static constexpr
int BufSize = 1024;
200 Out.resize(Size + BufSize);
203 nullptr, [&] {
return std::fgets(&
Out[Size], BufSize, In); }))
208 size_t Read = std::strlen(&
Out[Size]);
209 if (Read > 0 &&
Out[Size + Read - 1] ==
'\n') {
210 Out.resize(Size + Read);
220 llvm::Optional<std::string> JSONTransport::readStandardMessage() {
223 unsigned long long ContentLength = 0;
226 if (feof(In) || ferror(In) || !readLine(In,
Line))
230 llvm::StringRef LineRef(
Line);
235 if (LineRef.startswith(
"#"))
239 if (LineRef.consume_front(
"Content-Length: ")) {
240 if (ContentLength != 0) {
241 elog(
"Warning: Duplicate Content-Length header received. "
242 "The previous value for this message ({0}) was ignored.",
245 llvm::getAsUnsignedInteger(LineRef.trim(), 0, ContentLength);
247 }
else if (!LineRef.trim().empty()) {
258 if (ContentLength > 1 << 30) {
259 elog(
"Refusing to read message with long Content-Length: {0}. "
260 "Expect protocol errors",
264 if (ContentLength == 0) {
265 log(
"Warning: Missing Content-Length header, or zero-length message.");
269 std::string JSON(ContentLength,
'\0');
270 for (
size_t Pos = 0, Read;
Pos < ContentLength;
Pos +=
Read) {
273 return std::fread(&JSON[
Pos], 1, ContentLength -
Pos, In);
276 elog(
"Input was aborted. Read only {0} bytes of expected {1}.",
Pos,
280 InMirror << llvm::StringRef(&JSON[
Pos], Read);
285 return std::move(JSON);
293 llvm::Optional<std::string> JSONTransport::readDelimitedMessage() {
296 while (readLine(In,
Line)) {
298 auto LineRef = llvm::StringRef(
Line).trim();
299 if (LineRef.startswith(
"#"))
303 if (LineRef.rtrim() ==
"---")
312 elog(
"Input error while reading message!");
315 return std::move(JSON);
321 llvm::raw_ostream &
Out,
322 llvm::raw_ostream *InMirror,
325 return std::make_unique<JSONTransport>(In,
Out, InMirror, Pretty, Style);