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
27 "nixpkgs-expr",
28 desc("Default expression intrepreted as `import <nixpkgs> { }`"),
29 cat(NixdCategory), init("import <nixpkgs> { }")};
30
32 "nixos-options-expr",
33 desc("Default expression interpreted as option declarations"),
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(true), 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 }
56}
57
58} // namespace
59
60void Controller::evalExprWithProgress(AttrSetClient &Client,
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)
90
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", Array{CodeAction::QUICKFIX_KIND}},
102 {"resolveProvider", false},
103 },
104 },
105 {"definitionProvider", true},
106 {"documentLinkProvider", Object{}},
107 {"documentSymbolProvider", true},
108 {"inlayHintProvider", true},
109 {"completionProvider",
110 Object{
111 {"resolveProvider", true},
112 {"triggerCharacters", {"."}},
113 }},
114 {"referencesProvider", true},
115 {"documentHighlightProvider", true},
116 {"hoverProvider", true},
117 {"documentFormattingProvider", true},
118 {"renameProvider",
119 Object{
120 {"prepareProvider", true},
121 }}},
122 };
123
125 ServerCaps["semanticTokensProvider"] = Object{
126 {
127 "legend",
128 Object{
129 {"tokenTypes",
130 Array{
131 "function", // function
132 "string", // string
133 "number", // number
134 "type", // select
135 "keyword", // builtin
136 "variable", // constant
137 "interface", // fromWith
138 "variable", // variable
139 "regexp", // null
140 "macro", // bool
141 "method", // attrname
142 "regexp", // lambdaArg
143 "regexp", // lambdaFormal
144 }},
145 {"tokenModifiers",
146 Array{
147 "static", // builtin
148 "abstract", // deprecated
149 "async", // dynamic
150 }},
151 },
152 },
153 {"range", false},
154 {"full", true},
155 };
156 }
157
158 Object Result{{
159 {"serverInfo",
160 Object{
161 {"name", "nixd"},
162 {"version", NIXD_VERSION},
163 }},
164 {"capabilities", std::move(ServerCaps)},
165 }};
166
167 Reply(std::move(Result));
168
169 ClientCaps = Params.capabilities;
170
171 // Start default workers.
172 startNixpkgs(NixpkgsEval);
173
174 if (nixpkgsClient()) {
175 evalExprWithProgress(*nixpkgsClient(), getDefaultNixpkgsExpr(),
176 "nixpkgs entries");
177 }
178
179 // Launch nixos worker also.
180 {
181 std::lock_guard _(OptionsLock);
182 startOption("nixos", Options["nixos"]);
183
184 if (AttrSetClient *Client = Options["nixos"]->client())
185 evalExprWithProgress(*Client, getDefaultNixOSOptionsExpr(),
186 "nixos options");
187 }
188 try {
189 Config = parseCLIConfig();
190 } catch (LLVMErrorException &Err) {
191 lspserver::elog("parse CLI config error: {0}, {1}", Err.what(),
192 Err.takeError());
193 std::exit(-1);
194 }
195 fetchConfig();
196}
197
198void Controller::onInitialized(const lspserver::InitializedParams &Params) {}
199
200void Controller::onShutdown(const lspserver::NoParams &,
202 ReceivedShutdown = true;
203 Reply(nullptr);
204}
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.
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:38
bool fromJSON(const llvm::json::Value &Params, Configuration::Diagnostic &R, llvm::json::Path P)
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 QUICKFIX_KIND
Signals the end of progress reporting.