nixd
Loading...
Searching...
No Matches
Controller/Configuration.cpp
Go to the documentation of this file.
2#include "nixd/Eval/Launch.h"
3
4#include <boost/asio/post.hpp>
5
6using namespace nixd;
7using namespace lspserver;
8using llvm::json::ObjectMapper;
9using llvm::json::Value;
10
12 llvm::json::Path P) {
13 ObjectMapper O(Params, P);
14 return O && O.mapOptional("suppress", R.suppress);
15}
16
18 llvm::json::Path P) {
19 // If it is a single string, treat it as a single vector
20 if (auto Str = Params.getAsString()) {
21 R.command = {Str->str()};
22 return true;
23 }
24 ObjectMapper O(Params, P);
25 return O && O.mapOptional("command", R.command);
26}
27
29 llvm::json::Path P) {
30 ObjectMapper O(Params, P);
31 return O && O.mapOptional("expr", R.expr);
32}
33
35 llvm::json::Path P) {
36 ObjectMapper O(Params, P);
37 return O && O.mapOptional("expr", R.expr);
38}
39
40bool nixd::fromJSON(const Value &Params, Configuration &R, llvm::json::Path P) {
41 ObjectMapper O(Params, P);
42 return O //
43 && O.mapOptional("formatting", R.formatting) //
44 && O.mapOptional("options", R.options) //
45 && O.mapOptional("nixpkgs", R.nixpkgs) //
46 && O.mapOptional("diagnostic", R.diagnostic) //
47 ;
48}
49
50void Controller::onDidChangeConfiguration(
52 // FIXME: incrementally change?
53 fetchConfig();
54}
55
56void Controller::updateConfig(Configuration NewConfig) {
57 std::lock_guard G(ConfigLock);
58 Config = std::move(NewConfig);
59
60 if (!Config.nixpkgs.expr.empty()) {
61 /// Evaluate nixpkgs and options, using user-provided config.
62 if (nixpkgsClient()) {
63 evalExprWithProgress(*nixpkgsClient(), Config.nixpkgs.expr,
64 "nixpkgs entries");
65 }
66 }
67 if (!Config.options.empty()) {
68 std::lock_guard _(OptionsLock);
69 // For each option configuration, update the worker.
70 for (const auto &[Name, Opt] : Config.options) {
71 auto &Client = Options[Name];
72 if (!Client) {
73 // If it does not exist. Launch a new client.
74 startOption(Name, Client);
75 }
76 assert(Client);
77 evalExprWithProgress(*Client->client(), Opt.expr, Name);
78 }
79 }
80
81 // Update the diagnostic part.
82 updateSuppressed(Config.diagnostic.suppress);
83
84 // After all, notify all AST modules the diagnostic set has been updated.
85 std::lock_guard TUsGuard(TUsLock);
86 for (const auto &[File, TU] : TUs) {
87 publishDiagnostics(File, std::nullopt, TU->src(), TU->diagnostics());
88 }
89}
90
91void Controller::fetchConfig() {
92 auto Action = [this](llvm::Expected<llvm::json::Value> Resp) mutable {
93 if (!Resp) {
94 elog("workspace/configuration: {0}", Resp.takeError());
95 return;
96 }
97
98 // LSP response is a json array, just take the first.
99 if (Resp->kind() != llvm::json::Value::Array) {
100 lspserver::elog("workspace/configuration response is not an array: {0}",
101 *Resp);
102 return;
103 }
104 const Value &FirstConfig = Resp->getAsArray()->front();
105
106 // Run this job in the thread pool. Don't block input thread.
107 auto ConfigAction = [this, FirstConfig]() mutable {
108 // Parse the config
110 llvm::json::Path::Root P;
111 if (!fromJSON(FirstConfig, NewConfig, P)) {
112 elog("workspace/configuration: parse error {0}", P.getError());
113 return;
114 }
115
116 // OK, update the config
117 updateConfig(std::move(NewConfig));
118 };
119
120 boost::asio::post(Pool, std::move(ConfigAction));
121 };
122 workspaceConfiguration({.items = {ConfigurationItem{.section = "nixd"}}},
123 std::move(Action));
124}
125
126void Controller::workspaceConfiguration(
129 if (ClientCaps.WorkspaceConfiguration) {
130 WorkspaceConfiguration(Params, std::move(Reply));
131 } else {
132 Reply(lspserver::error("client does not support workspace configuration"));
133 }
134}
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
void elog(const char *Fmt, Ts &&...Vals)
Definition Logger.h:52
bool fromJSON(const llvm::json::Value &Params, Configuration::Diagnostic &R, llvm::json::Path P)
void startOption(const std::string &Name, std::unique_ptr< AttrSetClientProc > &Worker)
Definition Launch.cpp:36
std::string expr
Expression to eval. Treat it as "import <nixpkgs> { }".
std::string expr
Expression to eval. Select this attrset as eval .options.
struct nixd::Configuration::Formatting formatting
std::map< std::string, OptionProvider > options
struct nixd::Configuration::Diagnostic diagnostic
struct nixd::Configuration::NixpkgsProvider nixpkgs