5#include <llvm/ADT/SmallString.h>
6#include <llvm/Support/CommandLine.h>
17#include <system_error>
21llvm::cl::opt<int> ClientProcessID{
24 "Client process ID, if this PID died, the server should exit."),
25 llvm::cl::init(getppid())};
31static llvm::json::Object encodeError(llvm::Error
Error) {
34 auto HandlerFn = [&](
const LSPError &E) -> llvm::Error {
37 return llvm::Error::success();
40 Message = llvm::toString(std::move(
Unhandled));
42 return llvm::json::Object{
43 {
"message", std::move(Message)},
50 llvm::StringRef Message =
51 O.getString(
"message").value_or(
"Unspecified error");
52 if (std::optional<int64_t> Code = O.getInteger(
"code"))
53 return llvm::make_error<LSPError>(Message.str(),
ErrorCode(*Code));
54 return llvm::make_error<llvm::StringError>(llvm::inconvertibleErrorCode(),
62 {
"params", std::move(
Params)},
66 llvm::json::Value ID) {
69 {
"id", std::move(ID)},
71 {
"params", std::move(
Params)},
75 llvm::Expected<llvm::json::Value>
Result) {
79 {
"id", std::move(ID)},
80 {
"result", std::move(*
Result)},
85 {
"id", std::move(ID)},
86 {
"error", encodeError(
Result.takeError())},
93 vlog(
">>> {0}", Message);
94 std::lock_guard<std::mutex>
Guard(Mutex);
96 llvm::raw_svector_ostream
SVecOS(OutputBuffer);
97 SVecOS << (Pretty ? llvm::formatv(
"{0:2}", Message)
98 : llvm::formatv(
"{0}", Message));
99 Outs <<
"Content-Length: " << OutputBuffer.size() <<
"\r\n\r\n"
106 auto *
Object = Message.getAsObject();
108 Object->getString(
"jsonrpc") != std::optional<llvm::StringRef>(
"2.0")) {
109 elog(
"Not a JSON-RPC 2.0 message: {0:2}", Message);
113 std::optional<llvm::json::Value> ID;
114 if (
auto *
I =
Object->get(
"id"))
119 elog(
"No method and no response ID: {0:2}", Message);
122 if (
auto *
Err =
Object->getObject(
"error"))
126 llvm::json::Value
Result =
nullptr;
127 if (
auto *R =
Object->get(
"result"))
132 llvm::json::Value
Params =
nullptr;
133 if (
auto *P =
Object->get(
"params"))
142 llvm::SmallString<128> &Line) {
145 std::vector<pollfd>
FDs;
183 llvm::SmallString<128> Line;
188 llvm::StringRef
LineRef = Line;
191 if (
LineRef.consume_front(
"Content-Length: ")) {
208 elog(
"Input was aborted. Read only {0} bytes of expected {1}.", Pos,
218 llvm::SmallString<128> Line;
221 auto LineRef = Line.str().trim();
228 if (
LineRef.startswith(
"```")) {
235 if (
LineRef.startswith(
"```json"))
251 assert(
false &&
"Invalid stream style");
257 llvm::SmallString<128> Line;
267 elog(
"The received json cannot be parsed, reason: {0}",
Err);
bool dispatch(llvm::json::Value Message, MessageHandler &Handler)
JSONStreamStyle StreamStyle
bool readStandardMessage(std::string &JSONString)
bool readMessage(std::string &JSONString)
bool readDelimitedMessage(std::string &JSONString)
void loop(MessageHandler &Handler)
void sendMessage(llvm::json::Value Message)
void notify(llvm::StringRef Method, llvm::json::Value Params)
void reply(llvm::json::Value ID, llvm::Expected< llvm::json::Value > Result)
void call(llvm::StringRef Method, llvm::json::Value Params, llvm::json::Value ID)
Whether current platform treats paths case insensitively.
bool fromJSON(const llvm::json::Value &, URIForFile &, llvm::json::Path)
llvm::Error decodeError(const llvm::json::Object &O)
Decode the given JSON object into an error.
void elog(const char *Fmt, Ts &&...Vals)
void vlog(const char *Fmt, Ts &&...Vals)
bool readLine(int fd, const std::atomic< bool > &Close, llvm::SmallString< 128 > &Line)