Skip to content

Commit

Permalink
nixd/Server: move rename to controller
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc committed Jul 2, 2023
1 parent e881da7 commit 871d500
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 55 deletions.
12 changes: 12 additions & 0 deletions nixd/include/nixd/AST/ParseAST.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,18 @@ class ParseAST {
return rename(def(Var), NewName);
};

[[nodiscard]] std::optional<TextEdits>
rename(lspserver::Position Pos, const std::string &NewName) const {
if (const auto *EVar =
dynamic_cast<const nix::ExprVar *>(lookupContainMin(Pos))) {
return rename(EVar, NewName);
}
if (auto Def = lookupDef(Pos)) {
return rename(*Def, NewName);
}
return std::nullopt;
};

// Document Symbol
[[nodiscard]] Symbols documentSymbol(const nix::SymbolTable &STable) const;

Expand Down
54 changes: 51 additions & 3 deletions nixd/include/nixd/Server/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,57 @@ class Server : public lspserver::LSPServer {
~ReplyRAII() { R(std::move(Response)); };
};

template <class ReplyTy>
void withParseData(ReplyRAII<ReplyTy> &&RR, const std::string &Path,
llvm::unique_function<void(ReplyRAII<ReplyTy> &&RR,
std::unique_ptr<ParseData> Data,
const std::string &Version)>
Action) noexcept {
using namespace lspserver;
auto ActionWrapped =
[&, Action = std::move(Action)](
const EvalDraftStore::Draft &Draft) mutable noexcept {
try {
Action(std::move(RR), parse(*Draft.Contents, Path), Draft.Version);
} catch (std::exception &E) {
RR.Response =
error("something uncaught in the AST action, reason {0}",
stripANSI(E.what()));
} catch (...) {
RR.Response = error("something uncaught in the AST action");
}
};

try {
auto Draft = DraftMgr.getDraft(Path);
if (!Draft)
throw std::logic_error("no draft stored for requested file");
ActionWrapped(*Draft);
} catch (std::exception &E) {
RR.Response = error(stripANSI(E.what()));
} catch (...) {
RR.Response = error("encountered unknown exception");
}
}

template <class ReplyTy>
void withParseAST(
ReplyRAII<ReplyTy> &&RR, const std::string &Path,
llvm::unique_function<void(ReplyRAII<ReplyTy> &&RR, ParseAST &&AST,
const std::string &Version)>
Action) noexcept {
withParseData<ReplyTy>(
std::move(RR), Path,
[Action = std::move(Action)](ReplyRAII<ReplyTy> &&RR,
std::unique_ptr<ParseData> Data,
const std::string &Version) mutable {
auto AST = ParseAST(std::move(Data));
AST.bindVars();
AST.staticAnalysis();
Action(std::move(RR), std::move(AST), Version);
});
}

private:
bool WaitWorker = false;

Expand Down Expand Up @@ -333,9 +384,6 @@ class Server : public lspserver::LSPServer {
const lspserver::TextDocumentIdentifier &,
lspserver::Callback<std::vector<lspserver::DocumentSymbol>>);

void onStaticRename(const lspserver::RenameParams &,
lspserver::Callback<std::vector<lspserver::TextEdit>>);

// Worker::Nix::Eval

void switchToEvaluator();
Expand Down
64 changes: 37 additions & 27 deletions nixd/lib/Server/Controller.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "nixd-config.h"

#include "nixd/Expr/Expr.h"
#include "nixd/Parser/Parser.h"
#include "nixd/Parser/Require.h"
#include "nixd/Server/EvalDraftStore.h"
#include "nixd/Server/Server.h"
#include "nixd/Support/Diagnostic.h"
Expand Down Expand Up @@ -518,16 +520,23 @@ void Server::onCompletion(
void Server::onRename(const lspserver::RenameParams &Params,
lspserver::Callback<lspserver::WorkspaceEdit> Reply) {

auto Task = [=, Reply = std::move(Reply), this]() mutable {
auto Responses = askWC<std::vector<lspserver::TextEdit>>(
"nixd/ipc/textDocument/rename", Params,
{StaticWorkers, StaticWorkerLock, 1e5});
auto Edits = latestMatchOr<std::vector<lspserver::TextEdit>>(
Responses,
[](const std::vector<lspserver::TextEdit> &) -> bool { return true; });
std::map<std::string, std::vector<lspserver::TextEdit>> Changes;
Changes[Params.textDocument.uri.uri()] = std::move(Edits);
Reply(lspserver::WorkspaceEdit{.changes = std::move(Changes)});
auto Task = [Params, Reply = std::move(Reply), this]() mutable {
auto URI = Params.textDocument.uri;
auto Path = URI.file().str();
auto Action = [&URI, &Params](ReplyRAII<lspserver::WorkspaceEdit> &&RR,
ParseAST &&AST, const std::string &Version) {
std::map<std::string, std::vector<lspserver::TextEdit>> Changes;
if (auto Edits = AST.rename(Params.position, Params.newName)) {
Changes[URI.uri()] = std::move(*Edits);
RR.Response = lspserver::WorkspaceEdit{.changes = Changes};
return;
}
RR.Response = lspserver::error("no rename edits available");
return;
};
withParseAST<lspserver::WorkspaceEdit>(
ReplyRAII<lspserver::WorkspaceEdit>(std::move(Reply)), Path,
std::move(Action));
};

boost::asio::post(Pool, std::move(Task));
Expand All @@ -536,24 +545,25 @@ void Server::onRename(const lspserver::RenameParams &Params,
void Server::onPrepareRename(
const lspserver::TextDocumentPositionParams &Params,
lspserver::Callback<llvm::json::Value> Reply) {
auto Task = [=, Reply = std::move(Reply), this]() mutable {
auto Responses = askWC<std::vector<lspserver::TextEdit>>(
"nixd/ipc/textDocument/rename",
lspserver::RenameParams{
.textDocument = Params.textDocument,
.position = Params.position,
},
{StaticWorkers, StaticWorkerLock, 1e5});
auto Edits = latestMatchOr<std::vector<lspserver::TextEdit>>(
Responses,
[](const std::vector<lspserver::TextEdit> &) -> bool { return true; });
for (const auto &Edit : Edits) {
if (Edit.range.contains(Params.position)) {
Reply(Edit.range);
return;
auto Task = [Params, Reply = std::move(Reply), this]() mutable {
auto Path = Params.textDocument.uri.file().str();
auto Action = [&Params](ReplyRAII<llvm::json::Value> &&RR, ParseAST &&AST,
const std::string &Version) {
auto Pos = Params.position;
if (auto Edits = AST.rename(Pos, "")) {
for (const auto &Edit : *Edits) {
if (Edit.range.contains(Pos)) {
RR.Response = Edit.range;
return;
}
}
}
}
Reply(lspserver::error("no rename edits available"));
RR.Response = lspserver::error("no rename edits available");
return;
};
withParseAST<llvm::json::Value>(
ReplyRAII<llvm::json::Value>(std::move(Reply)), Path,
std::move(Action));
};

boost::asio::post(Pool, std::move(Task));
Expand Down
25 changes: 0 additions & 25 deletions nixd/lib/Server/Static.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ void Server::switchToStatic() {
Registry.addMethod("nixd/ipc/textDocument/definition", this,
&Server::onStaticDefinition);

Registry.addMethod("nixd/ipc/textDocument/rename", this,
&Server::onStaticRename);

evalInstallable(Config.getEvalDepth());
mkOutNotifiction<ipc::WorkerMessage>("nixd/ipc/finished")(
ipc::WorkerMessage{WorkspaceVersion});
Expand Down Expand Up @@ -52,28 +49,6 @@ void Server::onStaticDocumentLink(
});
}

void Server::onStaticRename(
const lspserver::RenameParams &Params,
lspserver::Callback<std::vector<lspserver::TextEdit>> Reply) {
using namespace lspserver;
using TextEdits = std::vector<lspserver::TextEdit>;
auto Action = [&Params](const nix::ref<EvalAST> &AST,
ReplyRAII<TextEdits> &&RR) {
RR.Response = error("no suitable renaming action available");
if (const auto *EVar = dynamic_cast<const nix::ExprVar *>(
AST->lookupContainMin(Params.position))) {
RR.Response = AST->rename(EVar, Params.newName);
return;
}
if (auto Def = AST->lookupDef(Params.position)) {
RR.Response = AST->rename(*Def, Params.newName);
return;
}
};
withAST<TextEdits>(Params.textDocument.uri.file().str(),
ReplyRAII<TextEdits>(std::move(Reply)), std::move(Action));
}

void Server::onStaticCompletion(const lspserver::CompletionParams &Params,
lspserver::Callback<llvm::json::Value> Reply) {
using namespace lspserver;
Expand Down

0 comments on commit 871d500

Please sign in to comment.