nixd
Loading...
Searching...
No Matches
Rename.cpp
Go to the documentation of this file.
1/// \file
2/// \brief This implements [Rename].
3/// [Rename]:
4/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rename
5
6#include "CheckReturn.h"
7#include "Convert.h"
8#include "Definition.h"
9
10#include "lspserver/Protocol.h"
12
13#include <boost/asio/post.hpp>
14
15#include <exception>
16
17using namespace lspserver;
18using namespace nixd;
19using namespace llvm;
20using namespace nixf;
21
22namespace {
23
24struct RenameException : std::exception {};
25
26struct RenameWithException : RenameException {
27 [[nodiscard]] const char *what() const noexcept override {
28 return "cannot rename `with` defined variable";
29 }
30};
31
32struct RenameBuiltinException : RenameException {
33 [[nodiscard]] const char *what() const noexcept override {
34 return "cannot rename builtin variable";
35 }
36};
37
38WorkspaceEdit rename(const nixf::Node &Desc, const std::string &NewText,
39 const ParentMapAnalysis &PMA,
40 const VariableLookupAnalysis &VLA, const URIForFile &URI,
41 llvm::StringRef Src) {
43 // Find "definition"
44 auto Def = findDefinition(Desc, PMA, VLA);
45
46 if (Def.source() == Definition::DS_With)
47 throw RenameWithException();
48
49 if (Def.isBuiltin())
50 throw RenameBuiltinException();
51
52 std::vector<TextEdit> Edits;
53
54 for (const auto *Use : Def.uses()) {
55 Edits.emplace_back(TextEdit{
56 .range = toLSPRange(Src, Use->range()),
57 .newText = NewText,
58 });
59 }
60
61 Edits.emplace_back(TextEdit{
62 .range = toLSPRange(Src, Def.syntax()->range()),
63 .newText = NewText,
64 });
66 WE.changes = std::map<std::string, std::vector<TextEdit>>{
67 {URI.uri(), std::move(Edits)}};
68 return WE;
69}
70} // namespace
71
72void Controller::onRename(const RenameParams &Params,
74 using CheckTy = WorkspaceEdit;
75 auto Action = [Reply = std::move(Reply), URI = Params.textDocument.uri,
76 Pos = toNixfPosition(Params.position),
77 NewText = Params.newName, this]() mutable {
78 const auto File = URI.file();
79 return Reply([&]() -> llvm::Expected<WorkspaceEdit> {
80 const auto TU = CheckDefault(getTU(File));
81 const auto AST = CheckDefault(getAST(*TU));
82 const auto &Desc = *CheckReturn(
83 AST->descend({Pos, Pos}),
84 error("cannot find corresponding node on given position"));
85
86 const auto &PM = *TU->parentMap();
87 const auto &VLA = *TU->variableLookup();
88 try {
89 return rename(Desc, NewText, PM, VLA, URI, TU->src());
90 } catch (std::exception &E) {
91 return error(E.what());
92 }
93 }());
94 };
95 boost::asio::post(Pool, std::move(Action));
96}
97
98void Controller::onPrepareRename(
100 Callback<std::optional<lspserver::Range>> Reply) {
101 using CheckTy = std::optional<lspserver::Range>;
102 auto Action = [Reply = std::move(Reply), URI = Params.textDocument.uri,
103 Pos = toNixfPosition(Params.position), this]() mutable {
104 const auto File = URI.file();
105 return Reply([&]() -> llvm::Expected<CheckTy> {
106 const auto TU = CheckDefault(getTU(File));
107 const auto AST = CheckDefault(getAST(*TU));
108
109 const auto &Desc = *CheckDefault(AST->descend({Pos, Pos}));
110
111 const auto &PM = *TU->parentMap();
112 const auto &VLA = *TU->variableLookup();
113 try {
114 WorkspaceEdit WE = rename(Desc, "", PM, VLA, URI, TU->src());
115 return toLSPRange(TU->src(), Desc.range());
116 } catch (std::exception &E) {
117 return error(E.what());
118 }
119 }());
120 };
121 boost::asio::post(Pool, std::move(Action));
122}
#define CheckDefault(x)
Variant of CheckReturn, but returns default constructed CheckTy
Definition CheckReturn.h:16
#define CheckReturn(x, Ret)
Used for simplify early-returns.
Definition CheckReturn.h:6
Convert between LSP and nixf types.
@ DS_With
From with <expr>;.
LexerCursorRange range() const
Definition Basic.h:35
Whether current platform treats paths case insensitively.
Definition Connection.h:11
llvm::unique_function< void(llvm::Expected< T >)> Callback
Definition Function.h:14
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&...Vals)
Definition Logger.h:70
nixf::Position toNixfPosition(const lspserver::Position &P)
Definition Convert.cpp:32
const nixf::Definition & findDefinition(const nixf::Node &N, const nixf::ParentMapAnalysis &PMA, const nixf::VariableLookupAnalysis &VLA)
Heuristically find definition on some node.
lspserver::Range toLSPRange(llvm::StringRef Code, const nixf::LexerCursorRange &R)
Definition Convert.cpp:40
std::string newName
The new name of the symbol.
Position position
The position at which this request was sent.
TextDocumentIdentifier textDocument
The document that was opened.
Position position
The position inside the text document.
TextDocumentIdentifier textDocument
The text document.
std::optional< std::map< std::string, std::vector< TextEdit > > > changes
Holds changes to existing resources.