From 62918a3a2bc72eca8605e2938dfa59d74c11d5ef Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Sat, 16 Mar 2024 00:28:57 +0800 Subject: [PATCH] nixd: use lspserver for RPC client/server --- nixd/nix-node-eval/meson.build | 12 +---- nixd/nix-node-eval/src/EvalProvider.cpp | 47 ++++++------------- nixd/nix-node-eval/src/EvalProvider.h | 14 +++--- nixd/nix-node-eval/src/Main.cpp | 11 ++++- nixd/nix-node-eval/test/EvalProvider.cpp | 44 ------------------ nixd/tools/nixd/src/Controller.h | 2 +- nixd/tools/nixd/src/EvalClient.cpp | 22 +++++---- nixd/tools/nixd/src/EvalClient.h | 57 +++++++++++++++++------- nixd/tools/nixd/src/LifeTime.cpp | 4 +- nixd/tools/nixd/src/Support.cpp | 3 +- 10 files changed, 90 insertions(+), 126 deletions(-) delete mode 100644 nixd/nix-node-eval/test/EvalProvider.cpp diff --git a/nixd/nix-node-eval/meson.build b/nixd/nix-node-eval/meson.build index 19d357fba..94e664e9c 100644 --- a/nixd/nix-node-eval/meson.build +++ b/nixd/nix-node-eval/meson.build @@ -1,4 +1,4 @@ -nixd_nix_node_eval_deps = [ libnixdrpc, nixt, libnixdutil ] +nixd_nix_node_eval_deps = [ libnixdrpc, nixt, libnixdutil, nixd_lsp_server ] nixd_nix_node_eval_lib = library( 'nix-node-eval', @@ -19,13 +19,3 @@ nixd_nix_node_eval = executable('nix-node-eval', install_dir: get_option('libexecdir'), dependencies: nixd_nix_node_eval_lib_dep ) - -test( - 'unit/nixd/nix-node-eval', - executable( - 'unit-nixd-nix-node-eval', - 'test/EvalProvider.cpp', - dependencies: [ nixd_nix_node_eval_lib_dep, gtest_main], - include_directories: include_directories('src') - ) -) diff --git a/nixd/nix-node-eval/src/EvalProvider.cpp b/nixd/nix-node-eval/src/EvalProvider.cpp index b9cd29a11..30746e122 100644 --- a/nixd/nix-node-eval/src/EvalProvider.cpp +++ b/nixd/nix-node-eval/src/EvalProvider.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include #include @@ -22,40 +24,17 @@ namespace nixd { -using bc::readBytecode; -using rpc::readBytecode; - namespace bipc = boost::interprocess; using namespace rpc; -EvalProvider::EvalProvider(int InboundFD, int OutboundFD) - : rpc::Transport(InboundFD, OutboundFD), +EvalProvider::EvalProvider(std::unique_ptr In, + std::unique_ptr Out) + : lspserver::LSPServer(std::move(In), std::move(Out)), State(std::unique_ptr( - new nix::EvalState{{}, nix::openStore("dummy://")})) {} - -void EvalProvider::handleInbound(const std::vector &Buf) { - std::ostringstream OS; - rpc::RPCKind Kind; - std::string_view Data(Buf.data(), Buf.size()); - readBytecode(Data, Kind); - switch (Kind) { - case rpc::RPCKind::RegisterBC: { - rpc::RegisterBCParams Params; - readBytecode(Data, Params); - onRegisterBC(Params); - break; - } - case rpc::RPCKind::UnregisterBC: - case rpc::RPCKind::Log: - case rpc::RPCKind::ExprValue: { - rpc::ExprValueParams Params; - readBytecode(Data, Params); - rpc::ExprValueResponse Response = onExprValue(Params); - sendPacket(Response); - break; - } - } + new nix::EvalState{{}, nix::openStore("dummy://")})) { + Registry.addMethod("exprValue", this, &EvalProvider::onExprValue); + Registry.addNotification("registerBC", this, &EvalProvider::onRegisterBC); } void EvalProvider::onRegisterBC(const rpc::RegisterBCParams &Params) { @@ -84,17 +63,19 @@ void EvalProvider::onRegisterBC(const rpc::RegisterBCParams &Params) { Cache[CachePath] = AST; } -ExprValueResponse EvalProvider::onExprValue(const ExprValueParams &Params) { +void EvalProvider::onExprValue(const ExprValueParams &Params, + lspserver::Callback Reply) { if (VMap.contains(Params.ExprID)) { nix::Value V = VMap[Params.ExprID]; - return { + Reply(ExprValueResponse{ ExprValueResponse::OK, static_cast(V.integer), ExprValueResponse::Int, - }; + }); + return; } - return {ExprValueResponse::NotEvaluated, 0}; + Reply(ExprValueResponse{ExprValueResponse::NotEvaluated, 0}); } } // namespace nixd diff --git a/nixd/nix-node-eval/src/EvalProvider.h b/nixd/nix-node-eval/src/EvalProvider.h index cd35b3d0e..89a8a2bc5 100644 --- a/nixd/nix-node-eval/src/EvalProvider.h +++ b/nixd/nix-node-eval/src/EvalProvider.h @@ -1,7 +1,9 @@ #pragma once #include "nixd/rpc/Protocol.h" -#include "nixd/rpc/Transport.h" + +#include +#include #include #include @@ -10,21 +12,23 @@ namespace nixd { -class EvalProvider : public rpc::Transport { +class EvalProvider : public lspserver::LSPServer { nixt::PtrPool Pool; nixt::ValueMap VMap; nixt::EnvMap EMap; std::unique_ptr State; - void handleInbound(const std::vector &Buf) override; + llvm::unique_function Exit; public: - EvalProvider(int InboundFD, int OutboundFD); + EvalProvider(std::unique_ptr In, + std::unique_ptr Out); void onRegisterBC(const rpc::RegisterBCParams &Params); - rpc::ExprValueResponse onExprValue(const rpc::ExprValueParams &Params); + void onExprValue(const rpc::ExprValueParams &Params, + lspserver::Callback); }; } // namespace nixd diff --git a/nixd/nix-node-eval/src/Main.cpp b/nixd/nix-node-eval/src/Main.cpp index a383f4b99..189a3906e 100644 --- a/nixd/nix-node-eval/src/Main.cpp +++ b/nixd/nix-node-eval/src/Main.cpp @@ -1,12 +1,19 @@ #include "EvalProvider.h" +#include + #include #include int main() { nixt::initEval(); - nixd::EvalProvider Provider(STDIN_FILENO, STDOUT_FILENO); - return Provider.run(); + auto In = std::make_unique( + STDIN_FILENO, lspserver::JSONStreamStyle::Standard); + + auto Out = std::make_unique(false); + nixd::EvalProvider Provider(std::move(In), std::move(Out)); + + Provider.run(); } diff --git a/nixd/nix-node-eval/test/EvalProvider.cpp b/nixd/nix-node-eval/test/EvalProvider.cpp deleted file mode 100644 index 3751655b1..000000000 --- a/nixd/nix-node-eval/test/EvalProvider.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include - -#include "EvalProvider.h" - -#include "nixd/rpc/Protocol.h" -#include "nixd/rpc/Transport.h" - -#include - -#include - -namespace { - -using namespace nixd::rpc; - -#define READ 0 -#define WRITE 1 - -struct TestEvalProvider : testing::Test { - int Pipes[2][2]; - - TestEvalProvider() { nixt::initEval(); } -}; - -TEST_F(TestEvalProvider, ExprValue) { - ASSERT_EQ(pipe(Pipes[READ]), 0); - ASSERT_EQ(pipe(Pipes[WRITE]), 0); - - nixd::EvalProvider Provider(Pipes[READ][READ], Pipes[WRITE][WRITE]); - - sendPacket>(Pipes[READ][WRITE], - {RPCKind::ExprValue, {}}); - - close(Pipes[READ][WRITE]); - - [[maybe_unused]] int Result = Provider.run(); - - auto Packet = recvPacket(Pipes[WRITE][READ]); - - ASSERT_EQ(Packet.ValueID, 0); - ASSERT_EQ(Packet.ValueKind, 0); -} - -} // namespace diff --git a/nixd/tools/nixd/src/Controller.h b/nixd/tools/nixd/src/Controller.h index baf759355..79e4f3e6e 100644 --- a/nixd/tools/nixd/src/Controller.h +++ b/nixd/tools/nixd/src/Controller.h @@ -9,7 +9,7 @@ namespace nixd { class Controller : public lspserver::LSPServer { - std::unique_ptr Eval; + std::unique_ptr Eval; lspserver::DraftStore Store; llvm::unique_function diff --git a/nixd/tools/nixd/src/EvalClient.cpp b/nixd/tools/nixd/src/EvalClient.cpp index 8f1f31b17..fe05404a7 100644 --- a/nixd/tools/nixd/src/EvalClient.cpp +++ b/nixd/tools/nixd/src/EvalClient.cpp @@ -2,12 +2,13 @@ #include "EvalClient.h" -#include "nixd/rpc/Protocol.h" #include "nixd/util/ForkPiped.h" #include #include +#include + #include namespace nixd { @@ -15,9 +16,7 @@ namespace nixd { using namespace rpc; using namespace nixd::util; -template using M = Message; - -std::unique_ptr EvalClient::create(int &Fail) { +std::unique_ptr OwnedEvalClient::create(int &Fail) { int In; int Out; int Err; @@ -35,16 +34,15 @@ std::unique_ptr EvalClient::create(int &Fail) { Fail = 0; // Parent process. auto Proc = std::make_unique(Child, In, Out, Err); - return std::make_unique(Out, In, std::move(Proc)); -} + auto InP = std::make_unique( + Out, lspserver::JSONStreamStyle::Standard); -void EvalClient::registerBC(const RegisterBCParams &Params) { - sendPacket>({RPCKind::RegisterBC, Params}); -} + auto ProcFdStream = std::make_unique(In, false); -ExprValueResponse EvalClient::exprValue(const ExprValueParams &Params) { - sendPacket>({RPCKind::ExprValue, Params}); - return recvPacket(); + auto OutP = std::make_unique(*ProcFdStream, false); + return std::make_unique(std::move(InP), std::move(OutP), + std::move(Proc), + std::move(ProcFdStream)); } } // namespace nixd diff --git a/nixd/tools/nixd/src/EvalClient.h b/nixd/tools/nixd/src/EvalClient.h index 22b5f7903..b74a54d8a 100644 --- a/nixd/tools/nixd/src/EvalClient.h +++ b/nixd/tools/nixd/src/EvalClient.h @@ -1,35 +1,62 @@ #pragma once #include "nixd/rpc/Protocol.h" -#include "nixd/rpc/Transport.h" + #include "nixd/util/PipedProc.h" +#include + #include +#include namespace nixd { -class EvalClient : public rpc::Transport { - // Owned process of the evaluator +class EvalClient : public lspserver::LSPServer { +public: + llvm::unique_function RegisterBC; + llvm::unique_function)> + ExprValue; + + EvalClient(std::unique_ptr In, + std::unique_ptr Out) + : lspserver::LSPServer(std::move(In), std::move(Out)) { + RegisterBC = mkOutNotifiction("registerBC"); + ExprValue = + mkOutMethod("exprValue"); + } + + virtual ~EvalClient() = default; +}; + +class OwnedEvalClient : public EvalClient { std::unique_ptr Proc; - void handleInbound(const std::vector &Buf) override{}; + std::unique_ptr Stream; + + std::thread Input; public: - EvalClient(int InboundFD, int OutboundFD, - std::unique_ptr Proc) - : rpc::Transport(InboundFD, OutboundFD), Proc(std::move(Proc)) {} + OwnedEvalClient(std::unique_ptr In, + std::unique_ptr Out, + std::unique_ptr Proc, + std::unique_ptr Stream) + : EvalClient(std::move(In), std::move(Out)), Proc(std::move(Proc)), + Stream(std::move(Stream)) { - virtual ~EvalClient() = default; + Input = std::thread([this]() { run(); }); + } + + util::PipedProc &proc() { return *Proc; } + + ~OwnedEvalClient() { + closeInbound(); + Input.join(); + } /// Lanch nix-node-eval, with properly handled file descriptors. /// System-wide errno will be written into "Fail" variable and thus cannot be /// discarded. - static std::unique_ptr create(int &Fail); - - void registerBC(const rpc::RegisterBCParams &Params); - - rpc::ExprValueResponse exprValue(const rpc::ExprValueParams &Params); - - util::PipedProc *proc() { return Proc.get(); } + static std::unique_ptr create(int &Fail); }; } // namespace nixd diff --git a/nixd/tools/nixd/src/LifeTime.cpp b/nixd/tools/nixd/src/LifeTime.cpp index 23e20eb17..35dce973c 100644 --- a/nixd/tools/nixd/src/LifeTime.cpp +++ b/nixd/tools/nixd/src/LifeTime.cpp @@ -55,12 +55,12 @@ void Controller:: "textDocument/publishDiagnostics"); int Fail; - Eval = EvalClient::create(Fail); + Eval = OwnedEvalClient::create(Fail); if (Fail != 0) { lspserver::elog("failed to create nix-node-eval worker: {0}", strerror(-Fail)); } else { - lspserver::log("launched nix-node-eval instance: {0}", Eval->proc()->PID); + lspserver::log("launched nix-node-eval instance: {0}", Eval->proc().PID); } } diff --git a/nixd/tools/nixd/src/Support.cpp b/nixd/tools/nixd/src/Support.cpp index 34999fb80..97874d370 100644 --- a/nixd/tools/nixd/src/Support.cpp +++ b/nixd/tools/nixd/src/Support.cpp @@ -1,5 +1,6 @@ #include "Controller.h" +#include "nixd/rpc/Protocol.h" #include "nixd/util/OwnedRegion.h" #include "nixf/Basic/Diagnostic.h" @@ -68,7 +69,7 @@ void Controller::actOnDocumentAdd(PathRef File, util::OwnedRegion{std::move(Shm), std::move(Region)}); if (Eval) { - Eval->registerBC({ShmName, ".", ".", Buf.size()}); + Eval->RegisterBC(rpc::RegisterBCParams{ShmName, ".", ".", Buf.size()}); } }