[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
//===-- JSONTransportTests.cpp -------------------------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Protocol.h"
|
|
|
|
#include "Transport.h"
|
[clangd] Move non-clang base pieces into separate support/ lib. NFCI
Summary:
This enforces layering, reduces a sprawling clangd/ directory, and makes life
easier for embedders.
Reviewers: kbobyrev
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79014
2020-04-28 23:49:17 +08:00
|
|
|
#include "support/Cancellation.h"
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "gtest/gtest.h"
|
2019-01-08 00:55:59 +08:00
|
|
|
#include <cstdio>
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
|
|
|
|
2018-10-20 10:11:45 +08:00
|
|
|
// No fmemopen on windows or on versions of MacOS X earlier than 10.13, so we
|
|
|
|
// can't easily run this test.
|
2019-04-02 05:16:17 +08:00
|
|
|
#if !(defined(_WIN32) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
|
|
|
__MAC_OS_X_VERSION_MIN_REQUIRED < 101300))
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
|
|
|
|
// Fixture takes care of managing the input/output buffers for the transport.
|
|
|
|
class JSONTransportTest : public ::testing::Test {
|
|
|
|
std::string InBuf, OutBuf, MirrorBuf;
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::raw_string_ostream Out, Mirror;
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
std::unique_ptr<FILE, int (*)(FILE *)> In;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
JSONTransportTest() : Out(OutBuf), Mirror(MirrorBuf), In(nullptr, nullptr) {}
|
|
|
|
|
|
|
|
template <typename... Args>
|
|
|
|
std::unique_ptr<Transport> transport(std::string InData, bool Pretty,
|
|
|
|
JSONStreamStyle Style) {
|
|
|
|
InBuf = std::move(InData);
|
|
|
|
In = {fmemopen(&InBuf[0], InBuf.size(), "r"), &fclose};
|
|
|
|
return newJSONTransport(In.get(), Out, &Mirror, Pretty, Style);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string input() const { return InBuf; }
|
|
|
|
std::string output() { return Out.str(); }
|
|
|
|
std::string input_mirror() { return Mirror.str(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
// Echo is a simple server running on a transport:
|
|
|
|
// - logs each message it gets.
|
|
|
|
// - when it gets a call, replies to it
|
|
|
|
// - when it gets a notification for method "call", makes a call on Target
|
|
|
|
// Hangs up when it gets an exit notification.
|
|
|
|
class Echo : public Transport::MessageHandler {
|
|
|
|
Transport &Target;
|
|
|
|
std::string LogBuf;
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::raw_string_ostream Log;
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
Echo(Transport &Target) : Target(Target), Log(LogBuf) {}
|
|
|
|
|
|
|
|
std::string log() { return Log.str(); }
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
bool onNotify(llvm::StringRef Method, llvm::json::Value Params) override {
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
Log << "Notification " << Method << ": " << Params << "\n";
|
|
|
|
if (Method == "call")
|
|
|
|
Target.call("echo call", std::move(Params), 42);
|
|
|
|
return Method != "exit";
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
bool onCall(llvm::StringRef Method, llvm::json::Value Params,
|
|
|
|
llvm::json::Value ID) override {
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
Log << "Call " << Method << "(" << ID << "): " << Params << "\n";
|
|
|
|
if (Method == "err")
|
2019-01-07 23:45:19 +08:00
|
|
|
Target.reply(
|
|
|
|
ID, llvm::make_error<LSPError>("trouble at mill", ErrorCode(88)));
|
2020-04-12 00:19:50 +08:00
|
|
|
else if (Method == "invalidated") // gone out skew on treadle
|
|
|
|
Target.reply(ID, llvm::make_error<CancelledError>(
|
|
|
|
static_cast<int>(ErrorCode::ContentModified)));
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
else
|
|
|
|
Target.reply(ID, std::move(Params));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
bool onReply(llvm::json::Value ID,
|
|
|
|
llvm::Expected<llvm::json::Value> Params) override {
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
if (Params)
|
|
|
|
Log << "Reply(" << ID << "): " << *Params << "\n";
|
|
|
|
else
|
2019-01-07 23:45:19 +08:00
|
|
|
Log << "Reply(" << ID
|
|
|
|
<< "): error = " << llvm::toString(Params.takeError()) << "\n";
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
std::string trim(llvm::StringRef S) { return S.trim().str(); }
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
|
|
|
|
// Runs an Echo session using the standard JSON-RPC format we use in production.
|
|
|
|
TEST_F(JSONTransportTest, StandardDense) {
|
|
|
|
auto T = transport(
|
|
|
|
"Content-Length: 52\r\n\r\n"
|
|
|
|
R"({"jsonrpc": "2.0", "method": "call", "params": 1234})"
|
|
|
|
"Content-Length: 46\r\n\r\n"
|
|
|
|
R"({"jsonrpc": "2.0", "id": 1234, "result": 5678})"
|
|
|
|
"Content-Length: 67\r\n\r\n"
|
|
|
|
R"({"jsonrpc": "2.0", "method": "foo", "id": "abcd", "params": "efgh"})"
|
|
|
|
"Content-Length: 73\r\n\r\n"
|
|
|
|
R"({"jsonrpc": "2.0", "id": "xyz", "error": {"code": 99, "message": "bad!"}})"
|
|
|
|
"Content-Length: 68\r\n\r\n"
|
|
|
|
R"({"jsonrpc": "2.0", "method": "err", "id": "wxyz", "params": "boom!"})"
|
|
|
|
"Content-Length: 36\r\n\r\n"
|
|
|
|
R"({"jsonrpc": "2.0", "method": "exit"})",
|
|
|
|
/*Pretty=*/false, JSONStreamStyle::Standard);
|
|
|
|
Echo E(*T);
|
|
|
|
auto Err = T->loop(E);
|
2018-10-20 23:30:37 +08:00
|
|
|
EXPECT_FALSE(bool(Err)) << toString(std::move(Err));
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
|
|
|
|
const char *WantLog = R"(
|
|
|
|
Notification call: 1234
|
|
|
|
Reply(1234): 5678
|
|
|
|
Call foo("abcd"): "efgh"
|
|
|
|
Reply("xyz"): error = 99: bad!
|
|
|
|
Call err("wxyz"): "boom!"
|
|
|
|
Notification exit: null
|
|
|
|
)";
|
|
|
|
EXPECT_EQ(trim(E.log()), trim(WantLog));
|
|
|
|
const char *WantOutput =
|
|
|
|
"Content-Length: 60\r\n\r\n"
|
|
|
|
R"({"id":42,"jsonrpc":"2.0","method":"echo call","params":1234})"
|
|
|
|
"Content-Length: 45\r\n\r\n"
|
|
|
|
R"({"id":"abcd","jsonrpc":"2.0","result":"efgh"})"
|
|
|
|
"Content-Length: 77\r\n\r\n"
|
|
|
|
R"({"error":{"code":88,"message":"trouble at mill"},"id":"wxyz","jsonrpc":"2.0"})";
|
|
|
|
EXPECT_EQ(output(), WantOutput);
|
|
|
|
EXPECT_EQ(trim(input_mirror()), trim(input()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Runs an Echo session using the "delimited" input and pretty-printed output
|
|
|
|
// that we use in lit tests.
|
|
|
|
TEST_F(JSONTransportTest, DelimitedPretty) {
|
|
|
|
auto T = transport(R"jsonrpc(
|
|
|
|
{"jsonrpc": "2.0", "method": "call", "params": 1234}
|
|
|
|
---
|
|
|
|
{"jsonrpc": "2.0", "id": 1234, "result": 5678}
|
|
|
|
---
|
|
|
|
{"jsonrpc": "2.0", "method": "foo", "id": "abcd", "params": "efgh"}
|
|
|
|
---
|
|
|
|
{"jsonrpc": "2.0", "id": "xyz", "error": {"code": 99, "message": "bad!"}}
|
|
|
|
---
|
2020-04-12 00:19:50 +08:00
|
|
|
{"jsonrpc": "2.0", "method": "invalidated", "id": "wxyz", "params": "boom!"}
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
---
|
|
|
|
{"jsonrpc": "2.0", "method": "exit"}
|
|
|
|
)jsonrpc",
|
|
|
|
/*Pretty=*/true, JSONStreamStyle::Delimited);
|
|
|
|
Echo E(*T);
|
|
|
|
auto Err = T->loop(E);
|
2018-10-20 23:30:37 +08:00
|
|
|
EXPECT_FALSE(bool(Err)) << toString(std::move(Err));
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
|
|
|
|
const char *WantLog = R"(
|
|
|
|
Notification call: 1234
|
|
|
|
Reply(1234): 5678
|
|
|
|
Call foo("abcd"): "efgh"
|
|
|
|
Reply("xyz"): error = 99: bad!
|
2020-04-12 00:19:50 +08:00
|
|
|
Call invalidated("wxyz"): "boom!"
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
Notification exit: null
|
|
|
|
)";
|
|
|
|
EXPECT_EQ(trim(E.log()), trim(WantLog));
|
|
|
|
const char *WantOutput = "Content-Length: 77\r\n\r\n"
|
|
|
|
R"({
|
|
|
|
"id": 42,
|
|
|
|
"jsonrpc": "2.0",
|
|
|
|
"method": "echo call",
|
|
|
|
"params": 1234
|
|
|
|
})"
|
|
|
|
"Content-Length: 58\r\n\r\n"
|
|
|
|
R"({
|
|
|
|
"id": "abcd",
|
|
|
|
"jsonrpc": "2.0",
|
|
|
|
"result": "efgh"
|
|
|
|
})"
|
2020-04-12 00:19:50 +08:00
|
|
|
"Content-Length: 145\r\n\r\n"
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
R"({
|
|
|
|
"error": {
|
2020-04-12 00:19:50 +08:00
|
|
|
"code": -32801,
|
|
|
|
"message": "Request cancelled because the document was modified"
|
[clangd] Refactor JSON-over-stdin/stdout code into Transport abstraction. (re-land r344620)
Summary:
This paves the way for alternative transports (mac XPC, maybe messagepack?),
and also generally improves layering: testing ClangdLSPServer becomes less of
a pipe dream, we split up the JSONOutput monolith, etc.
This isn't a final state, much of what remains in JSONRPCDispatcher can go away,
handlers can call reply() on the transport directly, JSONOutput can be renamed
to StreamLogger and removed, etc. But this patch is sprawling already.
The main observable change (see tests) is that hitting EOF on input is now an
error: the client should send the 'exit' notification.
This is defensible: the protocol doesn't spell this case out. Reproducing the
current behavior for all combinations of shutdown/exit/EOF clutters interfaces.
We can iterate on this if desired.
Reviewers: jkorous, ioeric, hokein
Subscribers: mgorny, ilya-biryukov, MaskRay, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53286
llvm-svn: 344672
2018-10-17 15:32:05 +08:00
|
|
|
},
|
|
|
|
"id": "wxyz",
|
|
|
|
"jsonrpc": "2.0"
|
|
|
|
})";
|
|
|
|
EXPECT_EQ(output(), WantOutput);
|
|
|
|
EXPECT_EQ(trim(input_mirror()), trim(input()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// IO errors such as EOF ane reported.
|
|
|
|
// The only successful return from loop() is if a handler returned false.
|
|
|
|
TEST_F(JSONTransportTest, EndOfFile) {
|
|
|
|
auto T = transport("Content-Length: 52\r\n\r\n"
|
|
|
|
R"({"jsonrpc": "2.0", "method": "call", "params": 1234})",
|
|
|
|
/*Pretty=*/false, JSONStreamStyle::Standard);
|
|
|
|
Echo E(*T);
|
|
|
|
auto Err = T->loop(E);
|
|
|
|
EXPECT_EQ(trim(E.log()), "Notification call: 1234");
|
|
|
|
EXPECT_TRUE(bool(Err)); // Ran into EOF with no handler signalling done.
|
|
|
|
consumeError(std::move(Err));
|
|
|
|
EXPECT_EQ(trim(input_mirror()), trim(input()));
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|