12 #include "llvm/Support/Errno.h" 17 using namespace clang;
18 using namespace clangd;
22 json::Object encodeError(Error E) {
24 ErrorCode Code = ErrorCode::UnknownErrorCode;
29 return Error::success();
31 Message =
toString(std::move(Unhandled));
34 {
"message", std::move(Message)},
35 {
"code", int64_t(Code)},
39 Error decodeError(
const json::Object &O) {
40 std::string Msg = O.getString(
"message").getValueOr(
"Unspecified error");
41 if (
auto Code = O.getInteger(
"code"))
42 return make_error<LSPError>(std::move(Msg),
ErrorCode(*Code));
43 return make_error<StringError>(std::move(Msg), inconvertibleErrorCode());
48 void connection_handler(xpc_connection_t clientConnection);
55 void notify(StringRef
Method, json::Value Params)
override {
56 sendMessage(json::Object{
59 {
"params", std::move(Params)},
62 void call(StringRef Method, json::Value Params, json::Value ID)
override {
63 sendMessage(json::Object{
65 {
"id", std::move(ID)},
67 {
"params", std::move(Params)},
70 void reply(json::Value ID, Expected<json::Value>
Result)
override {
72 sendMessage(json::Object{
74 {
"id", std::move(ID)},
75 {
"result", std::move(*Result)},
78 sendMessage(json::Object{
80 {
"id", std::move(ID)},
81 {
"error", encodeError(Result.takeError())},
86 Error loop(MessageHandler &Handler)
override;
90 friend void xpcClosure::connection_handler(xpc_connection_t clientConnection);
93 bool handleMessage(json::Value Message, MessageHandler &Handler);
94 void sendMessage(json::Value Message) {
95 xpc_object_t response =
jsonToXpc(Message);
96 xpc_connection_send_message(clientConnection, response);
97 xpc_release(response);
99 void resetClientConnection(xpc_connection_t newClientConnection) {
100 clientConnection = newClientConnection;
102 xpc_connection_t clientConnection;
105 bool XPCTransport::handleMessage(json::Value Message, MessageHandler &Handler) {
107 auto *
Object = Message.getAsObject();
108 if (!
Object ||
Object->getString(
"jsonrpc") != Optional<StringRef>(
"2.0")) {
109 elog(
"Not a JSON-RPC 2.0 message: {0:2}", Message);
113 Optional<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"))
123 return Handler.onReply(std::move(*ID), decodeError(*Err));
125 json::Value
Result =
nullptr;
126 if (
auto *R =
Object->get(
"result"))
127 Result = std::move(*R);
128 return Handler.onReply(std::move(*ID), std::move(Result));
131 json::Value Params =
nullptr;
132 if (
auto *P =
Object->get(
"params"))
133 Params = std::move(*P);
136 return Handler.onCall(*
Method, std::move(Params), std::move(*ID));
138 return Handler.onNotify(*
Method, std::move(Params));
144 XPCTransport *TransportObject =
nullptr;
147 void connection_handler(xpc_connection_t clientConnection) {
148 xpc_connection_set_target_queue(clientConnection, dispatch_get_main_queue());
150 xpc_transaction_begin();
152 TransportObject->resetClientConnection(clientConnection);
154 xpc_connection_set_event_handler(clientConnection, ^(xpc_object_t message) {
155 if (message == XPC_ERROR_CONNECTION_INVALID) {
157 log(
"Received XPC_ERROR_CONNECTION_INVALID message - returning from the " 162 if (xpc_get_type(message) != XPC_TYPE_DICTIONARY) {
163 log(
"Received XPC message of unknown type - returning from the " 168 const json::Value Doc =
xpcToJson(message);
169 if (Doc == json::Value(
nullptr)) {
170 log(
"XPC message was converted to Null JSON message - returning from the " 175 vlog(
"<<< {0}\n", Doc);
177 if (!TransportObject->handleMessage(std::move(Doc), *HandlerPtr)) {
178 log(
"Received exit notification - cancelling connection.");
179 xpc_connection_cancel(xpc_dictionary_get_remote_connection(message));
180 xpc_transaction_end();
184 xpc_connection_resume(clientConnection);
188 Error XPCTransport::loop(MessageHandler &Handler) {
189 assert(xpcClosure::TransportObject ==
nullptr &&
190 "TransportObject has already been set.");
195 xpcClosure::TransportObject =
this;
197 assert(xpcClosure::HandlerPtr ==
nullptr &&
198 "HandlerPtr has already been set.");
199 xpcClosure::HandlerPtr = &Handler;
201 xpc_main(xpcClosure::connection_handler);
203 return errorCodeToError(std::make_error_code(std::errc::io_error));
212 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()
constexpr llvm::StringLiteral Message
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
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)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
xpc_object_t jsonToXpc(const json::Value &JSON)