From ae7f63f007e2f631d0c8e12376f3d11971a1f78b Mon Sep 17 00:00:00 2001 From: Jonathan Watson <23344719+jonathanjameswatson@users.noreply.github.com> Date: Tue, 19 Sep 2023 00:15:03 +0100 Subject: [PATCH 1/9] nixd/Server/configuration: use `nixd.json` for `workspace/configuration` defaults Add jjw-log for options.enable Actually use BaseConstructor Fix some bugs Fix move bug Remove jjw-log Format changed files --- lspserver/include/lspserver/LSPBinder.h | 4 ++-- lspserver/include/lspserver/LSPServer.h | 7 ++++--- nixd/include/nixd/Server/Controller.h | 1 + nixd/lib/Server/Controller.cpp | 19 +++++++++++-------- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/lspserver/include/lspserver/LSPBinder.h b/lspserver/include/lspserver/LSPBinder.h index 7320319f5..4ae455f20 100644 --- a/lspserver/include/lspserver/LSPBinder.h +++ b/lspserver/include/lspserver/LSPBinder.h @@ -12,8 +12,8 @@ namespace lspserver { template llvm::Expected parseParam(const llvm::json::Value &Raw, llvm::StringRef PayloadName, - llvm::StringRef PayloadKind) { - T Result; + llvm::StringRef PayloadKind, T Base = T()) { + T Result = Base; llvm::json::Path::Root Root; if (!fromJSON(Raw, Result, Root)) { elog("Failed to decode {0} {1}: {2}", PayloadName, PayloadKind, diff --git a/lspserver/include/lspserver/LSPServer.h b/lspserver/include/lspserver/LSPServer.h index 4ea65c635..31627f3ab 100644 --- a/lspserver/include/lspserver/LSPServer.h +++ b/lspserver/include/lspserver/LSPServer.h @@ -66,7 +66,8 @@ class LSPServer : public MessageHandler { template llvm::unique_function)> - mkOutMethod(llvm::StringRef Method, OutboundPort *O = nullptr) { + mkOutMethod(llvm::StringRef Method, OutboundPort *O = nullptr, + ResponseTy Base = ResponseTy()) { if (!O) O = Out.get(); return [=, this](const ParamTy &Params, Callback Reply) { @@ -76,8 +77,8 @@ class LSPServer : public MessageHandler { llvm::Expected Response) mutable { if (!Response) return Reply(Response.takeError()); - Reply( - parseParam(std::move(*Response), Method, "reply")); + Reply(parseParam(std::move(*Response), Method, "reply", + Base)); }, O); }; diff --git a/nixd/include/nixd/Server/Controller.h b/nixd/include/nixd/Server/Controller.h index e7355fee0..77b9a7628 100644 --- a/nixd/include/nixd/Server/Controller.h +++ b/nixd/include/nixd/Server/Controller.h @@ -122,6 +122,7 @@ class Controller : public lspserver::LSPServer { std::mutex ConfigLock; + configuration::TopLevel JSONConfig; configuration::TopLevel Config; // GUARDED_BY(ConfigLock) std::shared_ptr getDraft(lspserver::PathRef File) const; diff --git a/nixd/lib/Server/Controller.cpp b/nixd/lib/Server/Controller.cpp index 675f2009d..fa3420f9b 100644 --- a/nixd/lib/Server/Controller.cpp +++ b/nixd/lib/Server/Controller.cpp @@ -233,9 +233,9 @@ void Controller::readJSONConfig(lspserver::PathRef File) noexcept { std::ifstream In(File.str(), std::ios::in); SS << In.rdbuf(); - if (auto NewConfig = parseConfig(SS.str())) - updateConfig(std::move(NewConfig.get())); - else { + if (auto NewConfig = parseConfig(SS.str())) { + JSONConfig = std::move(NewConfig.get()); + } else { throw nix::Error("configuration cannot be parsed"); } } catch (std::exception &E) { @@ -257,6 +257,14 @@ Controller::Controller(std::unique_ptr In, : LSPServer(std::move(In), std::move(Out)), WaitWorker(WaitWorker), ASTMgr(Pool) { + // JSON Config, run before initialize + readJSONConfig(); + configuration::TopLevel JSONConfigCopy = JSONConfig; + updateConfig(std::move(JSONConfigCopy)); + WorkspaceConfiguration = + mkOutMethod( + "workspace/configuration", nullptr, JSONConfig); + // Life Cycle Registry.addMethod("initialize", this, &Controller::onInitialize); Registry.addNotification("initialized", this, &Controller::onInitialized); @@ -293,17 +301,12 @@ Controller::Controller(std::unique_ptr In, // Workspace Registry.addNotification("workspace/didChangeConfiguration", this, &Controller::onWorkspaceDidChangeConfiguration); - WorkspaceConfiguration = - mkOutMethod( - "workspace/configuration"); /// IPC Registry.addNotification("nixd/ipc/diagnostic", this, &Controller::onEvalDiagnostic); Registry.addNotification("nixd/ipc/finished", this, &Controller::onFinished); - - readJSONConfig(); } //-----------------------------------------------------------------------------/ From 8183ba4b95a6fd589110a4d4d3c52d6dc5d8d3ce Mon Sep 17 00:00:00 2001 From: Jonathan Watson <23344719+jonathanjameswatson@users.noreply.github.com> Date: Fri, 6 Oct 2023 20:40:01 +0100 Subject: [PATCH 2/9] lsp: Restore previous `parseParam` behaviour --- lspserver/include/lspserver/LSPBinder.h | 30 +++++++++++++++++++++---- lspserver/include/lspserver/LSPServer.h | 4 ++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/lspserver/include/lspserver/LSPBinder.h b/lspserver/include/lspserver/LSPBinder.h index 4ae455f20..6d54fe55a 100644 --- a/lspserver/include/lspserver/LSPBinder.h +++ b/lspserver/include/lspserver/LSPBinder.h @@ -9,11 +9,15 @@ namespace lspserver { +namespace detail { template -llvm::Expected parseParam(const llvm::json::Value &Raw, - llvm::StringRef PayloadName, - llvm::StringRef PayloadKind, T Base = T()) { - T Result = Base; +llvm::Expected parseParamWithOptionalDefault( + const llvm::json::Value &Raw, llvm::StringRef PayloadName, + llvm::StringRef PayloadKind, std::optional OptionalDefault = {}) { + T Result; + if (OptionalDefault) { + Result = std::move(OptionalDefault.value()); + } llvm::json::Path::Root Root; if (!fromJSON(Raw, Result, Root)) { elog("Failed to decode {0} {1}: {2}", PayloadName, PayloadKind, @@ -31,6 +35,24 @@ llvm::Expected parseParam(const llvm::json::Value &Raw, } return Result; } +} // namespace detail + +template +llvm::Expected parseParam(const llvm::json::Value &Raw, + llvm::StringRef PayloadName, + llvm::StringRef PayloadKind) { + return detail::parseParamWithOptionalDefault(Raw, PayloadName, + PayloadKind); +} + +template +llvm::Expected +parseParamWithDefault(const llvm::json::Value &Raw, llvm::StringRef PayloadName, + llvm::StringRef PayloadKind, T Default) { + return detail::parseParamWithOptionalDefault(Raw, PayloadName, PayloadKind, + Default); +} + struct HandlerRegistry { using JSON = llvm::json::Value; template diff --git a/lspserver/include/lspserver/LSPServer.h b/lspserver/include/lspserver/LSPServer.h index 31627f3ab..0411cf26e 100644 --- a/lspserver/include/lspserver/LSPServer.h +++ b/lspserver/include/lspserver/LSPServer.h @@ -77,8 +77,8 @@ class LSPServer : public MessageHandler { llvm::Expected Response) mutable { if (!Response) return Reply(Response.takeError()); - Reply(parseParam(std::move(*Response), Method, "reply", - Base)); + Reply(parseParamWithDefault(std::move(*Response), + Method, "reply", Base)); }, O); }; From 500b0b43cd5bef60abfbb7c3c2766b20891ebd34 Mon Sep 17 00:00:00 2001 From: Jonathan Watson <23344719+jonathanjameswatson@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:26:18 +0100 Subject: [PATCH 3/9] lsp: Fix `parseParamWithOptionalDefault` when no default exists --- lspserver/include/lspserver/LSPBinder.h | 27 ++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lspserver/include/lspserver/LSPBinder.h b/lspserver/include/lspserver/LSPBinder.h index 6d54fe55a..b71542796 100644 --- a/lspserver/include/lspserver/LSPBinder.h +++ b/lspserver/include/lspserver/LSPBinder.h @@ -6,18 +6,29 @@ #include #include #include +#include namespace lspserver { namespace detail { + +template +typename std::enable_if, T>::type +valueOrDefault(const std::optional &OptionalDefault) { + return OptionalDefault ? OptionalDefault.value() : T(); +} + +template +typename std::enable_if, T>::type +valueOrDefault(const std::optional &OptionalDefault) { + return OptionalDefault.value(); +} + template llvm::Expected parseParamWithOptionalDefault( const llvm::json::Value &Raw, llvm::StringRef PayloadName, llvm::StringRef PayloadKind, std::optional OptionalDefault = {}) { - T Result; - if (OptionalDefault) { - Result = std::move(OptionalDefault.value()); - } + T Result = valueOrDefault(OptionalDefault); llvm::json::Path::Root Root; if (!fromJSON(Raw, Result, Root)) { elog("Failed to decode {0} {1}: {2}", PayloadName, PayloadKind, @@ -35,12 +46,14 @@ llvm::Expected parseParamWithOptionalDefault( } return Result; } + } // namespace detail template -llvm::Expected parseParam(const llvm::json::Value &Raw, - llvm::StringRef PayloadName, - llvm::StringRef PayloadKind) { +typename std::enable_if, + llvm::Expected>::type +parseParam(const llvm::json::Value &Raw, llvm::StringRef PayloadName, + llvm::StringRef PayloadKind) { return detail::parseParamWithOptionalDefault(Raw, PayloadName, PayloadKind); } From 92a24650ed9b81fb09c693180c89cf23a3192229 Mon Sep 17 00:00:00 2001 From: Jonathan Watson <23344719+jonathanjameswatson@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:28:34 +0100 Subject: [PATCH 4/9] nixd/Server/configuration: Remove `Base` from `mkOutMethod` --- lspserver/include/lspserver/LSPServer.h | 7 +++---- lspserver/include/lspserver/Protocol.h | 3 +++ lspserver/src/Protocol.cpp | 6 ++++++ nixd/include/nixd/Server/Controller.h | 2 +- nixd/lib/Server/Controller.cpp | 15 +++++++++++---- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lspserver/include/lspserver/LSPServer.h b/lspserver/include/lspserver/LSPServer.h index 0411cf26e..4ea65c635 100644 --- a/lspserver/include/lspserver/LSPServer.h +++ b/lspserver/include/lspserver/LSPServer.h @@ -66,8 +66,7 @@ class LSPServer : public MessageHandler { template llvm::unique_function)> - mkOutMethod(llvm::StringRef Method, OutboundPort *O = nullptr, - ResponseTy Base = ResponseTy()) { + mkOutMethod(llvm::StringRef Method, OutboundPort *O = nullptr) { if (!O) O = Out.get(); return [=, this](const ParamTy &Params, Callback Reply) { @@ -77,8 +76,8 @@ class LSPServer : public MessageHandler { llvm::Expected Response) mutable { if (!Response) return Reply(Response.takeError()); - Reply(parseParamWithDefault(std::move(*Response), - Method, "reply", Base)); + Reply( + parseParam(std::move(*Response), Method, "reply")); }, O); }; diff --git a/lspserver/include/lspserver/Protocol.h b/lspserver/include/lspserver/Protocol.h index f5bb8f9be..91b37f505 100644 --- a/lspserver/include/lspserver/Protocol.h +++ b/lspserver/include/lspserver/Protocol.h @@ -1903,6 +1903,9 @@ struct ConfigurationParams { llvm::json::Value toJSON(const ConfigurationParams &); +bool fromJSON(const llvm::json::Value &E, llvm::json::Value &R, + llvm::json::Path P); + } // namespace lspserver namespace llvm { template <> struct format_provider { diff --git a/lspserver/src/Protocol.cpp b/lspserver/src/Protocol.cpp index ec00b2564..4d5f0aa76 100644 --- a/lspserver/src/Protocol.cpp +++ b/lspserver/src/Protocol.cpp @@ -1498,4 +1498,10 @@ llvm::json::Value toJSON(const ConfigurationParams &N) { return llvm::json::Object{{"items", N.items}}; } +bool fromJSON(const llvm::json::Value &E, llvm::json::Value &R, + llvm::json::Path P) { + R = E; + return true; +} + } // namespace lspserver diff --git a/nixd/include/nixd/Server/Controller.h b/nixd/include/nixd/Server/Controller.h index 77b9a7628..5c87afff0 100644 --- a/nixd/include/nixd/Server/Controller.h +++ b/nixd/include/nixd/Server/Controller.h @@ -136,7 +136,7 @@ class Controller : public lspserver::LSPServer { PublishDiagnostic; llvm::unique_function)> + lspserver::Callback)> WorkspaceConfiguration; std::mutex DiagStatusLock; diff --git a/nixd/lib/Server/Controller.cpp b/nixd/lib/Server/Controller.cpp index fa3420f9b..7db2505b2 100644 --- a/nixd/lib/Server/Controller.cpp +++ b/nixd/lib/Server/Controller.cpp @@ -1,3 +1,4 @@ +#include "lspserver/LSPBinder.h" #include "nixd-config.h" #include "nixd/AST/AttrLocator.h" @@ -204,9 +205,15 @@ void Controller::fetchConfig() { lspserver::ConfigurationParams{ std::vector{ lspserver::ConfigurationItem{.section = "nixd"}}}, - [this](llvm::Expected Response) { + [this](llvm::Expected Response) { if (Response) { - updateConfig(std::move(Response.get())); + llvm::Expected ResponseConfig = + lspserver::parseParamWithDefault( + Response.get(), "workspace/configuration", "reply", + JSONConfig); + if (ResponseConfig) { + updateConfig(std::move(ResponseConfig.get())); + } } }); } @@ -262,8 +269,8 @@ Controller::Controller(std::unique_ptr In, configuration::TopLevel JSONConfigCopy = JSONConfig; updateConfig(std::move(JSONConfigCopy)); WorkspaceConfiguration = - mkOutMethod( - "workspace/configuration", nullptr, JSONConfig); + mkOutMethod( + "workspace/configuration", nullptr); // Life Cycle Registry.addMethod("initialize", this, &Controller::onInitialize); From 2597d4db72fc4d3bb5d0fc7b958b4b4a22512b95 Mon Sep 17 00:00:00 2001 From: Jonathan Watson <23344719+jonathanjameswatson@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:55:52 +0100 Subject: [PATCH 5/9] lsp: Fix default constructor being used instead of uninitializing --- lspserver/include/lspserver/LSPBinder.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lspserver/include/lspserver/LSPBinder.h b/lspserver/include/lspserver/LSPBinder.h index b71542796..9e9656d6c 100644 --- a/lspserver/include/lspserver/LSPBinder.h +++ b/lspserver/include/lspserver/LSPBinder.h @@ -14,13 +14,17 @@ namespace detail { template typename std::enable_if, T>::type -valueOrDefault(const std::optional &OptionalDefault) { - return OptionalDefault ? OptionalDefault.value() : T(); +valueOrUninitialized(const std::optional &OptionalDefault) { + T Result; + if (OptionalDefault) { + Result = OptionalDefault.value(); + } + return Result; } template typename std::enable_if, T>::type -valueOrDefault(const std::optional &OptionalDefault) { +valueOrUninitialized(const std::optional &OptionalDefault) { return OptionalDefault.value(); } @@ -28,7 +32,7 @@ template llvm::Expected parseParamWithOptionalDefault( const llvm::json::Value &Raw, llvm::StringRef PayloadName, llvm::StringRef PayloadKind, std::optional OptionalDefault = {}) { - T Result = valueOrDefault(OptionalDefault); + T Result = valueOrUninitialized(OptionalDefault); llvm::json::Path::Root Root; if (!fromJSON(Raw, Result, Root)) { elog("Failed to decode {0} {1}: {2}", PayloadName, PayloadKind, From 80a87169db668c7eb635691809f12f38a8913e33 Mon Sep 17 00:00:00 2001 From: Jonathan Watson <23344719+jonathanjameswatson@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:42:03 +0100 Subject: [PATCH 6/9] nixd/Server/configuration: Add wrapper type for JSON value defaulting --- lspserver/include/lspserver/Protocol.h | 3 --- lspserver/src/Protocol.cpp | 6 ------ nixd/include/nixd/Server/Controller.h | 8 +++++++- nixd/lib/Server/Controller.cpp | 15 +++++++++++---- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lspserver/include/lspserver/Protocol.h b/lspserver/include/lspserver/Protocol.h index 91b37f505..f5bb8f9be 100644 --- a/lspserver/include/lspserver/Protocol.h +++ b/lspserver/include/lspserver/Protocol.h @@ -1903,9 +1903,6 @@ struct ConfigurationParams { llvm::json::Value toJSON(const ConfigurationParams &); -bool fromJSON(const llvm::json::Value &E, llvm::json::Value &R, - llvm::json::Path P); - } // namespace lspserver namespace llvm { template <> struct format_provider { diff --git a/lspserver/src/Protocol.cpp b/lspserver/src/Protocol.cpp index 4d5f0aa76..ec00b2564 100644 --- a/lspserver/src/Protocol.cpp +++ b/lspserver/src/Protocol.cpp @@ -1498,10 +1498,4 @@ llvm::json::Value toJSON(const ConfigurationParams &N) { return llvm::json::Object{{"items", N.items}}; } -bool fromJSON(const llvm::json::Value &E, llvm::json::Value &R, - llvm::json::Path P) { - R = E; - return true; -} - } // namespace lspserver diff --git a/nixd/include/nixd/Server/Controller.h b/nixd/include/nixd/Server/Controller.h index 5c87afff0..06cd5ebc7 100644 --- a/nixd/include/nixd/Server/Controller.h +++ b/nixd/include/nixd/Server/Controller.h @@ -41,6 +41,12 @@ namespace nixd { +struct OptionalValue { + std::optional Value; +}; + +bool fromJSON(const llvm::json::Value &E, OptionalValue &R, llvm::json::Path P); + /// The server instance, nix-related language features goes here class Controller : public lspserver::LSPServer { public: @@ -136,7 +142,7 @@ class Controller : public lspserver::LSPServer { PublishDiagnostic; llvm::unique_function)> + lspserver::Callback)> WorkspaceConfiguration; std::mutex DiagStatusLock; diff --git a/nixd/lib/Server/Controller.cpp b/nixd/lib/Server/Controller.cpp index 7db2505b2..9ba6b219a 100644 --- a/nixd/lib/Server/Controller.cpp +++ b/nixd/lib/Server/Controller.cpp @@ -205,12 +205,12 @@ void Controller::fetchConfig() { lspserver::ConfigurationParams{ std::vector{ lspserver::ConfigurationItem{.section = "nixd"}}}, - [this](llvm::Expected Response) { + [this](llvm::Expected Response) { if (Response) { llvm::Expected ResponseConfig = lspserver::parseParamWithDefault( - Response.get(), "workspace/configuration", "reply", - JSONConfig); + Response.get().Value.value(), "workspace/configuration", + "reply", JSONConfig); if (ResponseConfig) { updateConfig(std::move(ResponseConfig.get())); } @@ -269,7 +269,7 @@ Controller::Controller(std::unique_ptr In, configuration::TopLevel JSONConfigCopy = JSONConfig; updateConfig(std::move(JSONConfigCopy)); WorkspaceConfiguration = - mkOutMethod( + mkOutMethod( "workspace/configuration", nullptr); // Life Cycle @@ -800,4 +800,11 @@ void Controller::onFormat( }; boost::asio::post(Pool, std::move(Task)); } + +bool fromJSON(const llvm::json::Value &E, OptionalValue &R, + llvm::json::Path P) { + R.Value = E; + return true; +} + } // namespace nixd From ed79ff5fe0a4005ccdb3742e0b84a7a9abe0596e Mon Sep 17 00:00:00 2001 From: Jonathan Watson <23344719+jonathanjameswatson@users.noreply.github.com> Date: Sat, 7 Oct 2023 12:43:10 +0100 Subject: [PATCH 7/9] lsp: Separate includes and use enable_if_t --- lspserver/include/lspserver/LSPBinder.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lspserver/include/lspserver/LSPBinder.h b/lspserver/include/lspserver/LSPBinder.h index 9e9656d6c..36f71ac3f 100644 --- a/lspserver/include/lspserver/LSPBinder.h +++ b/lspserver/include/lspserver/LSPBinder.h @@ -6,6 +6,7 @@ #include #include #include + #include namespace lspserver { @@ -13,7 +14,7 @@ namespace lspserver { namespace detail { template -typename std::enable_if, T>::type +typename std::enable_if_t, T> valueOrUninitialized(const std::optional &OptionalDefault) { T Result; if (OptionalDefault) { @@ -23,7 +24,7 @@ valueOrUninitialized(const std::optional &OptionalDefault) { } template -typename std::enable_if, T>::type +typename std::enable_if_t, T> valueOrUninitialized(const std::optional &OptionalDefault) { return OptionalDefault.value(); } @@ -54,8 +55,7 @@ llvm::Expected parseParamWithOptionalDefault( } // namespace detail template -typename std::enable_if, - llvm::Expected>::type +typename std::enable_if_t, llvm::Expected> parseParam(const llvm::json::Value &Raw, llvm::StringRef PayloadName, llvm::StringRef PayloadKind) { return detail::parseParamWithOptionalDefault(Raw, PayloadName, From d56b61b1cfe6cdb0aab8a29ed1ddc72e3ca00cb6 Mon Sep 17 00:00:00 2001 From: Jonathan Watson <23344719+jonathanjameswatson@users.noreply.github.com> Date: Sat, 7 Oct 2023 12:55:08 +0100 Subject: [PATCH 8/9] nixd/Server/configuration: Organise import of `LSPBinder` --- nixd/lib/Server/Controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixd/lib/Server/Controller.cpp b/nixd/lib/Server/Controller.cpp index 9ba6b219a..5cd5b61c6 100644 --- a/nixd/lib/Server/Controller.cpp +++ b/nixd/lib/Server/Controller.cpp @@ -1,4 +1,3 @@ -#include "lspserver/LSPBinder.h" #include "nixd-config.h" #include "nixd/AST/AttrLocator.h" @@ -16,6 +15,7 @@ #include "lspserver/Connection.h" #include "lspserver/DraftStore.h" +#include "lspserver/LSPBinder.h" #include "lspserver/Logger.h" #include "lspserver/Path.h" #include "lspserver/Protocol.h" From 122d2c2c302bac0bad5ce5367a5730bfee57604d Mon Sep 17 00:00:00 2001 From: Jonathan Watson <23344719+jonathanjameswatson@users.noreply.github.com> Date: Sat, 7 Oct 2023 15:03:10 +0100 Subject: [PATCH 9/9] nixd/Server/configuration: Improve the naming of default config symbols --- nixd/include/nixd/Server/Controller.h | 12 ++++++++---- nixd/lib/Server/Controller.cpp | 21 +++++++++++++-------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/nixd/include/nixd/Server/Controller.h b/nixd/include/nixd/Server/Controller.h index 06cd5ebc7..0af96afdc 100644 --- a/nixd/include/nixd/Server/Controller.h +++ b/nixd/include/nixd/Server/Controller.h @@ -128,7 +128,10 @@ class Controller : public lspserver::LSPServer { std::mutex ConfigLock; - configuration::TopLevel JSONConfig; + // When the server starts, DefaultConfig is set to the + // parsed contents of .nixd.json if it exists. This is used + // as the default when parsing workspace/configuration. + configuration::TopLevel DefaultConfig; configuration::TopLevel Config; // GUARDED_BY(ConfigLock) std::shared_ptr getDraft(lspserver::PathRef File) const; @@ -262,9 +265,10 @@ class Controller : public lspserver::LSPServer { static llvm::Expected parseConfig(llvm::StringRef JSON); - /// Try to update the server config from json encoded file \p File - /// Won't touch config field if exceptions encountered - void readJSONConfig(lspserver::PathRef File = ".nixd.json") noexcept; + /// Try to update the default config from json encoded file \p File + /// Won't touch default config field if exceptions encountered + /// Returns true if the default config is set and false otherwise. + bool readJSONConfigToDefault(lspserver::PathRef File = ".nixd.json") noexcept; void onWorkspaceDidChangeConfiguration( const lspserver::DidChangeConfigurationParams &) { diff --git a/nixd/lib/Server/Controller.cpp b/nixd/lib/Server/Controller.cpp index 5cd5b61c6..47d017b52 100644 --- a/nixd/lib/Server/Controller.cpp +++ b/nixd/lib/Server/Controller.cpp @@ -210,7 +210,7 @@ void Controller::fetchConfig() { llvm::Expected ResponseConfig = lspserver::parseParamWithDefault( Response.get().Value.value(), "workspace/configuration", - "reply", JSONConfig); + "reply", DefaultConfig); if (ResponseConfig) { updateConfig(std::move(ResponseConfig.get())); } @@ -233,7 +233,7 @@ Controller::parseConfig(llvm::StringRef JSON) { return lspserver::error("value cannot be converted to internal config type"); } -void Controller::readJSONConfig(lspserver::PathRef File) noexcept { +bool Controller::readJSONConfigToDefault(lspserver::PathRef File) noexcept { try { std::string ConfigStr; std::ostringstream SS; @@ -241,12 +241,15 @@ void Controller::readJSONConfig(lspserver::PathRef File) noexcept { SS << In.rdbuf(); if (auto NewConfig = parseConfig(SS.str())) { - JSONConfig = std::move(NewConfig.get()); - } else { - throw nix::Error("configuration cannot be parsed"); + DefaultConfig = std::move(NewConfig.get()); + return true; } + + throw nix::Error(".nixd.json configuration cannot be parsed"); } catch (std::exception &E) { + return false; } catch (...) { + return false; } } @@ -265,9 +268,11 @@ Controller::Controller(std::unique_ptr In, ASTMgr(Pool) { // JSON Config, run before initialize - readJSONConfig(); - configuration::TopLevel JSONConfigCopy = JSONConfig; - updateConfig(std::move(JSONConfigCopy)); + if (readJSONConfigToDefault()) { + configuration::TopLevel JSONConfigCopy = DefaultConfig; + updateConfig(std::move(JSONConfigCopy)); + }; + WorkspaceConfiguration = mkOutMethod( "workspace/configuration", nullptr);