nixd
Loading...
Searching...
No Matches
LifeTime.cpp
Go to the documentation of this file.
1/// \file
2/// \brief Implementation of [Server Lifecycle].
3/// [Server Lifecycle]:
4/// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#lifeCycleMessages
5
6#include "nixd-config.h"
7
11#include "nixd/Eval/Launch.h"
13
14#include "lspserver/Protocol.h"
15
16#include <llvm/Support/CommandLine.h>
17
18using namespace nixd;
19using namespace util;
20using namespace llvm::json;
21using namespace llvm::cl;
22using namespace lspserver;
23
24namespace {
25
26opt<std::string> DefaultNixpkgsExpr{
27 "nixpkgs-expr",
28 desc("Default expression intrepreted as `import <nixpkgs> { }`"),
29 cat(NixdCategory), init("import <nixpkgs> { }")};
30
31opt<std::string> DefaultNixOSOptionsExpr{
32 "nixos-options-expr",
33 desc("Default expression interpreted as option declarations"),
34 cat(NixdCategory),
35 init("(let pkgs = import <nixpkgs> { }; in (pkgs.lib.evalModules { modules "
36 "= (import <nixpkgs/nixos/modules/module-list.nix>) ++ [ ({...}: { "
37 "nixpkgs.hostPlatform = builtins.currentSystem;} ) ] ; })).options")};
38
39opt<bool> EnableSemanticTokens{"semantic-tokens",
40 desc("Enable/Disable semantic tokens"),
41 init(false), cat(NixdCategory)};
42
43// Here we try to wrap nixpkgs, nixos options in a single emtpy attrset in test.
44std::string getDefaultNixpkgsExpr() {
45 if (LitTest && !DefaultNixpkgsExpr.getNumOccurrences()) {
46 return "{ }";
47 }
48 return DefaultNixpkgsExpr;
49}
50
51std::string getDefaultNixOSOptionsExpr() {
52 if (LitTest && !DefaultNixOSOptionsExpr.getNumOccurrences()) {
53 return "{ }";
54 }
55 return DefaultNixOSOptionsExpr;
56}
57
58} // namespace
59
60void Controller::evalExprWithProgress(AttrSetClient &Client,
61 const EvalExprParams &Params,
62 std::string_view Description) {
63 auto Token = rand();
64 auto Action = [Token, Description = std::string(Description),
65 this](llvm::Expected<EvalExprResponse> Resp) {
66 endWorkDoneProgress({
67 .token = Token,
68 .value = WorkDoneProgressEnd{.message = "evaluated " +
69 std::string(Description)},
70 });
71 if (!Resp) {
72 lspserver::elog("{0} eval expr: {1}", Description, Resp.takeError());
73 return;
74 }
75 };
76 createWorkDoneProgress({Token});
77 beginWorkDoneProgress({.token = Token,
78 .value = WorkDoneProgressBegin{
79 .title = "evaluating " + std::string(Description),
80 .cancellable = false,
81 .percentage = false,
82 }});
83 Client.evalExpr(Params, std::move(Action));
84}
85
86void Controller::
87 onInitialize( // NOLINT(readability-convert-member-functions-to-static)
88 [[maybe_unused]] const InitializeParams &Params,
89 Callback<Value> Reply) {
90
91 Object ServerCaps{
92 {{"textDocumentSync",
93 llvm::json::Object{
94 {"openClose", true},
95 {"change", (int)TextDocumentSyncKind::Incremental},
96 {"save", true},
97 }},
98 {
99 "codeActionProvider",
100 Object{
101 {"codeActionKinds",
104 {"resolveProvider", true},
105 },
106 },
107 {"definitionProvider", true},
108 {"documentLinkProvider", Object{}},
109 {"documentSymbolProvider", true},
110 {"foldingRangeProvider", true},
111 {"inlayHintProvider", true},
112 {"completionProvider",
113 Object{
114 {"resolveProvider", true},
115 {"triggerCharacters", {"."}},
116 }},
117 {"referencesProvider", true},
118 {"documentHighlightProvider", true},
119 {"hoverProvider", true},
120 {"documentFormattingProvider", true},
121 {"renameProvider",
122 Object{
123 {"prepareProvider", true},
124 }}},
125 };
126
127 if (EnableSemanticTokens) {
128 ServerCaps["semanticTokensProvider"] = Object{
129 {
130 "legend",
131 Object{
132 {"tokenTypes",
133 Array{
134 "function", // function
135 "string", // string
136 "number", // number
137 "type", // select
138 "keyword", // builtin
139 "variable", // constant
140 "interface", // fromWith
141 "variable", // variable
142 "regexp", // null
143 "macro", // bool
144 "method", // attrname
145 "regexp", // lambdaArg
146 "regexp", // lambdaFormal
147 }},
148 {"tokenModifiers",
149 Array{
150 "static", // builtin
151 "abstract", // deprecated
152 "async", // dynamic
153 }},
154 },
155 },
156 {"range", false},
157 {"full", true},
158 };
159 }
160
161 Object Result{{
162 {"serverInfo",
163 Object{
164 {"name", "nixd"},
165 {"version", NIXD_VERSION},
166 }},
167 {"capabilities", std::move(ServerCaps)},
168 }};
169
170 Reply(std::move(Result));
171
172 ClientCaps = Params.capabilities;
173
174 // Start default workers.
175 startNixpkgs(NixpkgsEval);
176
177 if (nixpkgsClient()) {
178 evalExprWithProgress(*nixpkgsClient(), getDefaultNixpkgsExpr(),
179 "nixpkgs entries");
180 }
181
182 // Launch nixos worker also.
183 {
184 std::lock_guard _(OptionsLock);
185 startOption("nixos", Options["nixos"]);
186
187 if (AttrSetClient *Client = Options["nixos"]->client())
188 evalExprWithProgress(*Client, getDefaultNixOSOptionsExpr(),
189 "nixos options");
190 }
191 try {
192 Config = parseCLIConfig();
193 } catch (LLVMErrorException &Err) {
194 lspserver::elog("parse CLI config error: {0}, {1}", Err.what(),
195 Err.takeError());
196 std::exit(-1);
197 }
198 fetchConfig();
199}
200
201void Controller::onInitialized(const lspserver::InitializedParams &Params) {}
202
203void Controller::onShutdown(const lspserver::NoParams &,
205 ReceivedShutdown = true;
206 Reply(nullptr);
207}
Allow default configuration being passed via CLI.
void evalExpr(const EvalExprParams &Params, lspserver::Callback< EvalExprResponse > Reply)
Request eval some expression. The expression should be evaluted to attrset.
llvm::Error takeError()
Definition Exception.h:15
Whether current platform treats paths case insensitively.
Definition Connection.h:11
llvm::unique_function< void(llvm::Expected< T >)> Callback
Definition Function.h:14
void elog(const char *Fmt, Ts &&...Vals)
Definition Logger.h:52
std::string EvalExprParams
Definition AttrSet.h:39
llvm::cl::OptionCategory NixdCategory
void startOption(const std::string &Name, std::unique_ptr< AttrSetClientProc > &Worker)
Definition Launch.cpp:36
nixd::Configuration parseCLIConfig()
Parse the CLI flag and initialize the config nixd::DefaultConfig.
void startNixpkgs(std::unique_ptr< AttrSetClientProc > &NixpkgsEval)
Definition Launch.cpp:32
llvm::cl::opt< bool > LitTest
Indicating that we are in lit-test mode.
Definition Options.cpp:8
static const llvm::StringLiteral REFACTOR_KIND
static const llvm::StringLiteral REFACTOR_REWRITE_KIND
static const llvm::StringLiteral QUICKFIX_KIND