13 #include "llvm/Support/Errno.h" 18 using namespace clang;
19 using namespace clangd;
23 json::Object encodeError(Error E) {
25 ErrorCode Code = ErrorCode::UnknownErrorCode;
30 return Error::success();
32 Message =
toString(std::move(Unhandled));
35 {
"message", std::move(Message)},
36 {
"code", int64_t(Code)},
40 Error decodeError(
const json::Object &O) {
41 std::string Msg = O.getString(
"message").getValueOr(
"Unspecified error");
42 if (
auto Code = O.getInteger(
"code"))
43 return make_error<LSPError>(std::move(Msg),
ErrorCode(*Code));
44 return make_error<StringError>(std::move(Msg), inconvertibleErrorCode());
49 void connection_handler(xpc_connection_t clientConnection);
56 void notify(StringRef
Method, json::Value Params)
override {
57 sendMessage(json::Object{
60 {
"params", std::move(Params)},
63 void call(StringRef Method, json::Value Params, json::Value ID)
override {
64 sendMessage(json::Object{
66 {
"id", std::move(ID)},
68 {
"params", std::move(Params)},
71 void reply(json::Value ID, Expected<json::Value>
Result)
override {
73 sendMessage(json::Object{
75 {
"id", std::move(ID)},
76 {
"result", std::move(*Result)},
79 sendMessage(json::Object{
81 {
"id", std::move(ID)},
82 {
"error", encodeError(Result.takeError())},
87 Error loop(MessageHandler &Handler)
override;
91 friend void xpcClosure::connection_handler(xpc_connection_t clientConnection);
94 bool handleMessage(json::Value Message, MessageHandler &Handler);
95 void sendMessage(json::Value Message) {
96 xpc_object_t response =
jsonToXpc(Message);
97 xpc_connection_send_message(clientConnection, response);
98 xpc_release(response);
100 void resetClientConnection(xpc_connection_t newClientConnection) {
101 clientConnection = newClientConnection;
103 xpc_connection_t clientConnection;
106 bool XPCTransport::handleMessage(json::Value Message, MessageHandler &Handler) {
108 auto *
Object = Message.getAsObject();
109 if (!
Object ||
Object->getString(
"jsonrpc") != Optional<StringRef>(
"2.0")) {
110 elog(
"Not a JSON-RPC 2.0 message: {0:2}", Message);
114 Optional<json::Value> ID;
115 if (
auto *I =
Object->get(
"id"))
120 elog(
"No method and no response ID: {0:2}", Message);
123 if (
auto *Err =
Object->getObject(
"error"))
124 return Handler.onReply(std::move(*ID), decodeError(*Err));
126 json::Value
Result =
nullptr;
127 if (
auto *R =
Object->get(
"result"))
128 Result = std::move(*R);
129 return Handler.onReply(std::move(*ID), std::move(Result));
132 json::Value Params =
nullptr;
133 if (
auto *P =
Object->get(
"params"))
134 Params = std::move(*P);
137 return Handler.onCall(*
Method, std::move(Params), std::move(*ID));
139 return Handler.onNotify(*
Method, std::move(Params));
145 XPCTransport *TransportObject =
nullptr;
148 void connection_handler(xpc_connection_t clientConnection) {
149 xpc_connection_set_target_queue(clientConnection, dispatch_get_main_queue());
151 xpc_transaction_begin();
153 TransportObject->resetClientConnection(clientConnection);
155 xpc_connection_set_event_handler(clientConnection, ^(xpc_object_t message) {
156 if (message == XPC_ERROR_CONNECTION_INVALID) {
158 log(
"Received XPC_ERROR_CONNECTION_INVALID message - returning from the " 163 if (xpc_get_type(message) != XPC_TYPE_DICTIONARY) {
164 log(
"Received XPC message of unknown type - returning from the " 169 const json::Value Doc =
xpcToJson(message);
170 if (Doc == json::Value(
nullptr)) {
171 log(
"XPC message was converted to Null JSON message - returning from the " 176 vlog(
"<<< {0}\n", Doc);
178 if (!TransportObject->handleMessage(std::move(Doc), *HandlerPtr)) {
179 log(
"Received exit notification - cancelling connection.");
180 xpc_connection_cancel(xpc_dictionary_get_remote_connection(message));
181 xpc_transaction_end();
185 xpc_connection_resume(clientConnection);
189 Error XPCTransport::loop(MessageHandler &Handler) {
190 assert(xpcClosure::TransportObject ==
nullptr &&
191 "TransportObject has already been set.");
196 xpcClosure::TransportObject =
this;
198 assert(xpcClosure::HandlerPtr ==
nullptr &&
199 "HandlerPtr has already been set.");
200 xpcClosure::HandlerPtr = &Handler;
202 xpc_main(xpcClosure::connection_handler);
204 return errorCodeToError(std::make_error_code(std::errc::io_error));
213 return llvm::make_unique<XPCTransport>();
Some operations such as code completion produce a set of candidates.
void log(Logger::Level, const llvm::formatv_object_base &)
std::unique_ptr< Transport > newXPCTransport()
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
static const StringRef Message
void vlog(const char *Fmt, Ts &&... Vals)
void elog(const char *Fmt, Ts &&... Vals)
void handleErrors(llvm::ArrayRef< ClangTidyError > Errors, ClangTidyContext &Context, bool Fix, unsigned &WarningsAsErrorsCount, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS)
Displays the found Errors to the users.
json::Value xpcToJson(const xpc_object_t &XPCObject)
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
xpc_object_t jsonToXpc(const json::Value &JSON)