Skip to content

Commit

Permalink
{libnixt,nixd/Eval}: support attrsOf submodule (#465)
Browse files Browse the repository at this point in the history
Currently these options are nested under

`foo.bar.<name>.options`

Fixes: #106
  • Loading branch information
inclyc authored Apr 26, 2024
1 parent f78e80c commit 6eb1a24
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
13 changes: 13 additions & 0 deletions libnixt/include/nixt/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,24 @@ std::vector<nix::Symbol> toSymbols(nix::SymbolTable &STable,
/// \brief Select attribute \p Attr
nix::Value &selectAttr(nix::EvalState &State, nix::Value &V, nix::Symbol Attr);

nix::Value &selectOption(nix::EvalState &State, nix::Value &V,
nix::Symbol Attr);

/// \brief Given an attrpath in nix::Value \p V, select it
nix::Value &selectAttrPath(nix::EvalState &State, nix::Value &V,
std::vector<nix::Symbol>::const_iterator Begin,
std::vector<nix::Symbol>::const_iterator End);

/// \brief Select the option declaration list, \p V, dive into "submodules".
nix::Value &selectOptions(nix::EvalState &State, nix::Value &V,
std::vector<nix::Symbol>::const_iterator Begin,
std::vector<nix::Symbol>::const_iterator End);

inline nix::Value &selectOptions(nix::EvalState &State, nix::Value &V,
const std::vector<nix::Symbol> &AttrPath) {
return selectOptions(State, V, AttrPath.begin(), AttrPath.end());
}

/// \copydoc selectAttrPath
inline nix::Value &selectSymbols(nix::EvalState &State, nix::Value &V,
const std::vector<nix::Symbol> &AttrPath) {
Expand Down
42 changes: 42 additions & 0 deletions libnixt/lib/Value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,45 @@ nix::Value &nixt::selectAttrPath(nix::EvalState &State, nix::Value &V,
nix::Value &Nested = selectAttr(State, V, *Begin);
return selectAttrPath(State, Nested, ++Begin, End);
}

nix::Value &nixt::selectOptions(nix::EvalState &State, nix::Value &V,
std::vector<nix::Symbol>::const_iterator Begin,
std::vector<nix::Symbol>::const_iterator End) {
if (Begin == End)
return V;

if (isOption(State, V)) {
// If currently "V" is an option, it can still be submodules.
//
// e.g. users.users <-- the main option stops at here.
// networking.interfaces
//
// Take care of such case.
nix::Value &Type = selectAttr(State, V, State.sType);
if (checkField(State, Type, "name", "attrsOf")) {
nix::Value NestedTypes =
selectAttr(State, Type, State.symbols.create("nestedTypes"));
nix::Value ElemType =
selectAttr(State, NestedTypes, State.symbols.create("elemType"));

if (checkField(State, ElemType, "name", "submodule")) {
// Current iterator may be ommited, and V becomes "V.getSubOptions []"
nix::Value &GetSubOptions =
selectAttr(State, ElemType, State.symbols.create("getSubOptions"));

nix::Value EmptyList;
EmptyList.mkList(0);

// Invoke "GetSubOptions"
nix::Value Next;
State.callFunction(GetSubOptions, EmptyList, Next, nix::noPos);

return selectOptions(State, Next, ++Begin, End);
}
}
}

// Otherwise, simply select it.
nix::Value &Nested = selectAttr(State, V, *Begin);
return selectOptions(State, Nested, ++Begin, End);
}
6 changes: 4 additions & 2 deletions nixd/lib/Eval/AttrSetProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ void AttrSetProvider::onOptionInfo(
return;
}

nix::Value &Option = nixt::selectStrings(state(), Nixpkgs, AttrPath);
nix::Value &Option = nixt::selectOptions(
state(), Nixpkgs, nixt::toSymbols(state().symbols, AttrPath));

OptionInfoResponse R;

Expand All @@ -253,7 +254,8 @@ void AttrSetProvider::onOptionComplete(
const AttrPathCompleteParams &Params,
lspserver::Callback<OptionCompleteResponse> Reply) {
try {
nix::Value &Scope = nixt::selectStrings(state(), Nixpkgs, Params.Scope);
nix::Value &Scope = nixt::selectOptions(
state(), Nixpkgs, nixt::toSymbols(state().symbols, Params.Scope));

state().forceValue(Scope, nix::noPos);

Expand Down

0 comments on commit 6eb1a24

Please sign in to comment.