12#include "llvm/Support/Errno.h"
19using namespace clangd;
23json::Object encodeError(
Error E) {
30 return Error::success();
35 {
"message", std::move(Message)},
36 {
"code", int64_t(
Code)},
40Error decodeError(
const json::Object &O) {
42 std::string(O.getString(
"message").value_or(
"Unspecified error"));
43 if (
auto Code = O.getInteger(
"code"))
44 return make_error<LSPError>(std::move(Msg),
ErrorCode(*
Code));
45 return error(
"{0}", Msg);
50void connection_handler(xpc_connection_t clientConnection);
57 void notify(StringRef
Method, json::Value Params)
override {
58 sendMessage(json::Object{
61 {
"params", std::move(Params)},
64 void call(StringRef
Method, json::Value Params, json::Value
ID)
override {
65 sendMessage(json::Object{
67 {
"id", std::move(
ID)},
69 {
"params", std::move(Params)},
72 void reply(json::Value
ID, Expected<json::Value> Result)
override {
74 sendMessage(json::Object{
76 {
"id", std::move(
ID)},
77 {
"result", std::move(*Result)},
80 sendMessage(json::Object{
82 {
"id", std::move(
ID)},
83 {
"error", encodeError(Result.takeError())},
88 Error loop(MessageHandler &Handler)
override;
92 friend void xpcClosure::connection_handler(xpc_connection_t clientConnection);
95 bool handleMessage(json::Value Message, MessageHandler &Handler);
96 void sendMessage(json::Value Message) {
97 xpc_object_t response =
jsonToXpc(Message);
98 xpc_connection_send_message(clientConnection, response);
99 xpc_release(response);
101 void resetClientConnection(xpc_connection_t newClientConnection) {
102 clientConnection = newClientConnection;
104 xpc_connection_t clientConnection;
107bool XPCTransport::handleMessage(json::Value Message, MessageHandler &Handler) {
111 Object->getString(
"jsonrpc") != std::optional<StringRef>(
"2.0")) {
112 elog(
"Not a JSON-RPC 2.0 message: {0:2}", Message);
116 std::optional<json::Value>
ID;
117 if (
auto *I =
Object->get(
"id"))
122 elog(
"No method and no response ID: {0:2}", Message);
125 if (
auto *Err =
Object->getObject(
"error"))
126 return Handler.onReply(std::move(*
ID), decodeError(*Err));
128 json::Value Result =
nullptr;
129 if (
auto *R =
Object->get(
"result"))
130 Result = std::move(*R);
131 return Handler.onReply(std::move(*
ID), std::move(Result));
134 json::Value Params =
nullptr;
135 if (
auto *P =
Object->get(
"params"))
136 Params = std::move(*P);
139 return Handler.onCall(*
Method, std::move(Params), std::move(*
ID));
141 return Handler.onNotify(*
Method, std::move(Params));
147XPCTransport *TransportObject =
nullptr;
150void connection_handler(xpc_connection_t clientConnection) {
151 xpc_connection_set_target_queue(clientConnection, dispatch_get_main_queue());
153 xpc_transaction_begin();
155 TransportObject->resetClientConnection(clientConnection);
157 xpc_connection_set_event_handler(clientConnection, ^(xpc_object_t message) {
158 if (message == XPC_ERROR_CONNECTION_INVALID) {
160 log(
"Received XPC_ERROR_CONNECTION_INVALID message - returning from the "
165 if (xpc_get_type(message) != XPC_TYPE_DICTIONARY) {
166 log(
"Received XPC message of unknown type - returning from the "
171 const json::Value Doc =
xpcToJson(message);
172 if (Doc == json::Value(
nullptr)) {
173 log(
"XPC message was converted to Null JSON message - returning from the "
178 vlog(
"<<< {0}\n", Doc);
180 if (!TransportObject->handleMessage(std::move(Doc), *HandlerPtr)) {
181 log(
"Received exit notification - cancelling connection.");
182 xpc_connection_cancel(xpc_dictionary_get_remote_connection(message));
183 xpc_transaction_end();
187 xpc_connection_resume(clientConnection);
191Error XPCTransport::loop(MessageHandler &Handler) {
192 assert(xpcClosure::TransportObject ==
nullptr &&
193 "TransportObject has already been set.");
198 xpcClosure::TransportObject =
this;
200 assert(xpcClosure::HandlerPtr ==
nullptr &&
201 "HandlerPtr has already been set.");
202 xpcClosure::HandlerPtr = &Handler;
204 xpc_main(xpcClosure::connection_handler);
206 return errorCodeToError(std::make_error_code(std::errc::io_error));
215 return std::make_unique<XPCTransport>();
static constexpr llvm::SourceMgr::DiagKind Error
virtual void call(llvm::StringRef Method, llvm::json::Value Params, llvm::json::Value ID)=0
virtual void notify(llvm::StringRef Method, llvm::json::Value Params)=0
virtual void reply(llvm::json::Value ID, llvm::Expected< llvm::json::Value > Result)=0
virtual llvm::Error loop(MessageHandler &)=0
xpc_object_t jsonToXpc(const json::Value &JSON)
void vlog(const char *Fmt, Ts &&... Vals)
static const char * toString(OffsetEncoding OE)
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
std::unique_ptr< Transport > newXPCTransport()
void log(const char *Fmt, Ts &&... Vals)
json::Value xpcToJson(const xpc_object_t &XPCObject)
void elog(const char *Fmt, Ts &&... Vals)
constexpr llvm::StringLiteral Message
void handleErrors(llvm::ArrayRef< ClangTidyError > Errors, ClangTidyContext &Context, FixBehaviour Fix, unsigned &WarningsAsErrorsCount, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > BaseFS)
Displays the found Errors to the users.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Some operations such as code completion produce a set of candidates.