Skip to content

Commit

Permalink
nixd/Server: split worker in a dedicated class
Browse files Browse the repository at this point in the history
TODO: sync the draft store
  • Loading branch information
inclyc committed Jul 25, 2023
1 parent b835f4e commit 5916789
Show file tree
Hide file tree
Showing 15 changed files with 481 additions and 376 deletions.
22 changes: 22 additions & 0 deletions nixd/include/nixd/Nix/Eval.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <nix/eval-inline.hh>
#include <nix/shared.hh>

namespace nix {

// Copy-paste from nix source code, do not know why it is inlined.

inline void EvalState::evalAttrs(Env &env, Expr *e, Value &v, const PosIdx pos,
std::string_view errorCtx) {
try {
e->eval(*this, env, v);
if (v.type() != nAttrs)
error("value is %1% while a set was expected", showType(v))
.withFrame(env, *e)
.debugThrow<TypeError>();
} catch (Error &e) {
e.addTrace(positions[pos], errorCtx);
throw;
}
}

} // namespace nix
16 changes: 16 additions & 0 deletions nixd/include/nixd/Nix/Init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include <nix/eval.hh>
#include <nix/globals.hh>
#include <nix/shared.hh>

namespace nixd {

inline void initEval() {
nix::initNix();
nix::initLibStore();
nix::initPlugins();
nix::initGC();
}

} // namespace nixd
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,8 @@

namespace nixd {

struct CompletionHelper {
using Items = std::vector<lspserver::CompletionItem>;
static void fromEnv(nix::EvalState &State, nix::Env &NixEnv, Items &Items);
static void fromStaticEnv(const nix::SymbolTable &STable,
const nix::StaticEnv &SEnv, Items &Items);
};

/// The server instance, nix-related language features goes here
class Server : public lspserver::LSPServer {
class Controller : public lspserver::LSPServer {
public:
using WorkspaceVersionTy = ipc::WorkspaceVersionTy;

Expand Down Expand Up @@ -191,17 +184,11 @@ class Server : public lspserver::LSPServer {
nix::Value *OptionAttrSet;
std::unique_ptr<IValueEvalSession> OptionIES;

// Worker::Eval

llvm::unique_function<void(const ipc::Diagnostics &)> EvalDiagnostic;

std::unique_ptr<IValueEvalResult> IER;

public:
Server(std::unique_ptr<lspserver::InboundPort> In,
std::unique_ptr<lspserver::OutboundPort> Out, int WaitWorker = 0);
Controller(std::unique_ptr<lspserver::InboundPort> In,
std::unique_ptr<lspserver::OutboundPort> Out, int WaitWorker = 0);

~Server() override {
~Controller() override {
if (WaitWorker) {
Pool.join();
std::lock_guard Guard(EvalWorkerLock);
Expand Down Expand Up @@ -325,10 +312,6 @@ class Server : public lspserver::LSPServer {
return Vec;
}

// Worker

void initWorker();

// Worker::Nix::Option

void forkOptionWorker();
Expand All @@ -340,31 +323,11 @@ class Server : public lspserver::LSPServer {

void onOptionCompletion(const ipc::AttrPathParams &,
lspserver::Callback<llvm::json::Value>);

// Worker::Nix::Eval

void switchToEvaluator();

template <class ReplyTy>
void withAST(
const std::string &, ReplyRAII<ReplyTy>,
llvm::unique_function<void(nix::ref<EvalAST>, ReplyRAII<ReplyTy> &&)>);

void evalInstallable();

void onEvalDefinition(const lspserver::TextDocumentPositionParams &,
lspserver::Callback<lspserver::Location>);

void onEvalHover(const lspserver::TextDocumentPositionParams &,
lspserver::Callback<llvm::json::Value>);

void onEvalCompletion(const lspserver::CompletionParams &,
lspserver::Callback<llvm::json::Value>);
};

template <class Resp, class Arg>
auto Server::askWorkers(
const std::deque<std::unique_ptr<Server::Proc>> &Workers,
auto Controller::askWorkers(
const std::deque<std::unique_ptr<Controller::Proc>> &Workers,
std::shared_mutex &WorkerLock, llvm::StringRef IPCMethod, const Arg &Params,
unsigned Timeout) {
// For all active workers, send the completion request
Expand Down Expand Up @@ -418,24 +381,4 @@ auto Server::askWorkers(
return AnsweredResp;
}

template <class ReplyTy>
void Server::withAST(
const std::string &RequestedFile, ReplyRAII<ReplyTy> RR,
llvm::unique_function<void(nix::ref<EvalAST>, ReplyRAII<ReplyTy> &&)>
Action) {
try {
auto AST = IER->Forest.at(RequestedFile);
try {
Action(AST, std::move(RR));
} catch (std::exception &E) {
RR.Response =
lspserver::error("something uncaught in the AST action, reason {0}",
stripANSI(E.what()));
}
} catch (std::out_of_range &E) {
RR.Response = lspserver::error("no AST available on requested file {0}",
RequestedFile);
}
}

}; // namespace nixd
56 changes: 56 additions & 0 deletions nixd/include/nixd/Server/EvalWorker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once

#include "nixd/Server/EvalDraftStore.h"
#include "nixd/Support/Diagnostic.h"
#include "nixd/Support/JSONSerialization.h"
#include "nixd/Support/ReplyRAII.h"

#include "lspserver/LSPServer.h"

namespace nixd {

class EvalWorker : public lspserver::LSPServer {
llvm::unique_function<void(const ipc::Diagnostics &)> EvalDiagnostic;

std::unique_ptr<IValueEvalResult> IER;

template <class ReplyTy>
void withAST(
const std::string &, ReplyRAII<ReplyTy>,
llvm::unique_function<void(nix::ref<EvalAST>, ReplyRAII<ReplyTy> &&)>);

public:
EvalWorker(std::unique_ptr<lspserver::InboundPort> In,
std::unique_ptr<lspserver::OutboundPort> Out);

void onEvalDefinition(const lspserver::TextDocumentPositionParams &,
lspserver::Callback<lspserver::Location>);

void onEvalHover(const lspserver::TextDocumentPositionParams &,
lspserver::Callback<llvm::json::Value>);

void onEvalCompletion(const lspserver::CompletionParams &,
lspserver::Callback<llvm::json::Value>);
};

template <class ReplyTy>
void EvalWorker::withAST(
const std::string &RequestedFile, ReplyRAII<ReplyTy> RR,
llvm::unique_function<void(nix::ref<EvalAST>, ReplyRAII<ReplyTy> &&)>
Action) {
try {
auto AST = IER->Forest.at(RequestedFile);
try {
Action(AST, std::move(RR));
} catch (std::exception &E) {
RR.Response =
lspserver::error("something uncaught in the AST action, reason {0}",
stripANSI(E.what()));
}
} catch (std::out_of_range &E) {
RR.Response = lspserver::error("no AST available on requested file {0}",
RequestedFile);
}
}

} // namespace nixd
18 changes: 18 additions & 0 deletions nixd/include/nixd/Support/CompletionHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "lspserver/Protocol.h"

#include <nix/eval.hh>

#include <vector>

namespace nixd {

struct CompletionHelper {
using Items = std::vector<lspserver::CompletionItem>;
static void fromEnv(nix::EvalState &State, nix::Env &NixEnv, Items &Items);
static void fromStaticEnv(const nix::SymbolTable &STable,
const nix::StaticEnv &SEnv, Items &Items);
};

} // namespace nixd
2 changes: 2 additions & 0 deletions nixd/include/nixd/Support/JSONSerialization.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#pragma once

#include "lspserver/Protocol.h"

#include <llvm/Support/JSON.h>
Expand Down
22 changes: 22 additions & 0 deletions nixd/include/nixd/Support/ReplyRAII.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "lspserver/Function.h"
#include "lspserver/Logger.h"

namespace nixd {

template <class ReplyTy> struct ReplyRAII {
lspserver::Callback<ReplyTy> R;
llvm::Expected<ReplyTy> Response = lspserver::error("no response available");
ReplyRAII(decltype(R) R) : R(std::move(R)) {}
~ReplyRAII() {
if (R)
R(std::move(Response));
};
ReplyRAII(ReplyRAII &&Old) noexcept {
R = std::move(Old.R);
Response = std::move(Old.Response);
}
};

} // namespace nixd
Loading

0 comments on commit 5916789

Please sign in to comment.