diff --git a/nixd/include/nixd/Eval/AttrSetProvider.h b/nixd/include/nixd/Eval/AttrSetProvider.h index 22ac5104d..bf919e298 100644 --- a/nixd/include/nixd/Eval/AttrSetProvider.h +++ b/nixd/include/nixd/Eval/AttrSetProvider.h @@ -32,7 +32,10 @@ class AttrSetProvider : public lspserver::LSPServer { std::unique_ptr State; - nix::Value Nixpkgs; + nix::Value Val; + + // If this value is valid + bool ValueValid = false; /// Convenient method for get state. Basically assume this->State is not null nix::EvalState &state() { @@ -40,6 +43,17 @@ class AttrSetProvider : public lspserver::LSPServer { return *State; } + /// \brief Check if the value is valid. \throw an exception if it is not. + void checkValueValid() const { + if (!ValueValid) + throw std::runtime_error("value is invalid"); + } + + nix::Value &validValue() { + checkValueValid(); + return Val; + } + public: AttrSetProvider(std::unique_ptr In, std::unique_ptr Out); diff --git a/nixd/lib/Eval/AttrSetProvider.cpp b/nixd/lib/Eval/AttrSetProvider.cpp index 24441f5f3..45d1c5cc2 100644 --- a/nixd/lib/Eval/AttrSetProvider.cpp +++ b/nixd/lib/Eval/AttrSetProvider.cpp @@ -126,9 +126,11 @@ void AttrSetProvider::onEvalExpr( const std::string &Name, lspserver::Callback> Reply) { try { + ValueValid = false; nix::Expr *AST = state().parseExprFromString( Name, state().rootPath(nix::CanonPath::fromCwd())); - state().eval(AST, Nixpkgs); + state().eval(AST, Val); + ValueValid = true; Reply(std::nullopt); return; } catch (const nix::BaseError &Err) { @@ -149,7 +151,7 @@ void AttrSetProvider::onAttrPathInfo( return; } - nix::Value &Package = nixt::selectStrings(state(), Nixpkgs, AttrPath); + nix::Value &Package = nixt::selectStrings(state(), validValue(), AttrPath); AttrPathInfoResponse R; fillPackageDescription(state(), Package, R); @@ -169,7 +171,8 @@ void AttrSetProvider::onAttrPathComplete( const AttrPathCompleteParams &Params, lspserver::Callback Reply) { try { - nix::Value &Scope = nixt::selectStrings(state(), Nixpkgs, Params.Scope); + nix::Value &Scope = + nixt::selectStrings(state(), validValue(), Params.Scope); state().forceValue(Scope, nix::noPos); @@ -217,7 +220,7 @@ void AttrSetProvider::onOptionInfo( return; } - nix::Value &Option = nixt::selectStrings(state(), Nixpkgs, AttrPath); + nix::Value &Option = nixt::selectStrings(state(), validValue(), AttrPath); OptionInfoResponse R; @@ -238,7 +241,8 @@ void AttrSetProvider::onOptionComplete( const AttrPathCompleteParams &Params, lspserver::Callback Reply) { try { - nix::Value &Scope = nixt::selectStrings(state(), Nixpkgs, Params.Scope); + nix::Value &Scope = + nixt::selectStrings(state(), validValue(), Params.Scope); state().forceValue(Scope, nix::noPos); diff --git a/nixd/tools/nixd-attrset-eval/test/invalid-value.md b/nixd/tools/nixd-attrset-eval/test/invalid-value.md new file mode 100644 index 000000000..d1dff3712 --- /dev/null +++ b/nixd/tools/nixd-attrset-eval/test/invalid-value.md @@ -0,0 +1,32 @@ +# RUN: nixd-attrset-eval --lit-test < %s | FileCheck %s + + +```json +{ + "jsonrpc":"2.0", + "id":0, + "method":"attrset/evalExpr", + "params": "fuck $$@" +} +``` + + +```json +{ + "jsonrpc":"2.0", + "id":1, + "method":"attrset/attrpathInfo", + "params": [ "hello" ] +} +``` + +``` + CHECK: "message": "value is invalid" +CHECK-NEXT: }, +CHECK-NEXT: "id": 1, +``` + +```json +{"jsonrpc":"2.0","method":"exit"} +``` +