Index: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp =================================================================== --- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp +++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp @@ -69,7 +69,7 @@ Outs << "Content-Length: " << S.size() << "\r\n\r\n" << S; Outs.flush(); } - vlog("--> {0}\n", S); + vlog(">>> {0}\n", S); } void JSONOutput::log(Logger::Level Level, @@ -99,6 +99,7 @@ return; } RequestSpan::attach([&](json::Object &Args) { Args["Reply"] = Result; }); + log("--> reply({0})", *ID); Context::current() .getExisting(RequestOut) ->writeMessage(json::Object{ @@ -116,6 +117,7 @@ }); if (auto ID = Context::current().get(RequestID)) { + log("--> reply({0}) error: {1}", *ID, Message); Context::current() .getExisting(RequestOut) ->writeMessage(json::Object{ @@ -128,16 +130,18 @@ } void clangd::call(StringRef Method, json::Value &&Params) { - // FIXME: Generate/Increment IDs for every request so that we can get proper - // replies once we need to. RequestSpan::attach([&](json::Object &Args) { Args["Call"] = json::Object{{"method", Method.str()}, {"params", Params}}; }); + // FIXME: Generate/Increment IDs for every request so that we can get proper + // replies once we need to. + auto ID = 1; + log("--> {0}({1})", Method, ID); Context::current() .getExisting(RequestOut) ->writeMessage(json::Object{ {"jsonrpc", "2.0"}, - {"id", 1}, + {"id", ID}, {"method", Method}, {"params", std::move(Params)}, }); @@ -148,6 +152,23 @@ Handlers[Method] = std::move(H); } +static void logIncomingMessage(const llvm::Optional &ID, + llvm::Optional Method, + const json::Object *Error) { + if (Method) { // incoming request + if (ID) // call + log("<-- {0}({1})", *Method, *ID); + else // notification + log("<-- {0}", *Method); + } else if (ID) { // response, ID must be provided + if (Error) + log("<-- reply({0}) error: {1}", *ID, + Error->getString("message").getValueOr("")); + else + log("<-- reply({0})", *ID); + } +} + bool JSONRPCDispatcher::call(const json::Value &Message, JSONOutput &Out) const { // Message must be an object with "jsonrpc":"2.0". @@ -158,9 +179,9 @@ llvm::Optional ID; if (auto *I = Object->get("id")) ID = std::move(*I); - // Method must be given. auto Method = Object->getString("method"); - if (!Method) + logIncomingMessage(ID, Method, Object->getObject("error")); + if (!Method) // We only handle incoming requests, and ignore responses. return false; // Params should be given, use null if not. json::Value Params = nullptr; @@ -333,13 +354,13 @@ if (auto JSON = ReadMessage(In, Out)) { if (auto Doc = json::parse(*JSON)) { // Log the formatted message. - vlog(Out.Pretty ? "<-- {0:2}\n" : "<-- {0}\n", *Doc); + vlog(Out.Pretty ? "<<< {0:2}\n" : "<<< {0}\n", *Doc); // Finally, execute the action for this JSON message. if (!Dispatcher.call(*Doc, Out)) elog("JSON dispatch failed!"); } else { // Parse error. Log the raw message. - vlog("<-- {0}\n", *JSON); + vlog("<<< {0}\n", *JSON); elog("JSON parse error: {0}", llvm::toString(Doc.takeError())); } }