lib/introspect: recurse for nested attrsOf
This commit is contained in:
@@ -10,6 +10,46 @@ let
|
||||
]
|
||||
);
|
||||
|
||||
pushPositions = map (
|
||||
def:
|
||||
lib.mapAttrs (_n: v: {
|
||||
inherit (def) file;
|
||||
value = v;
|
||||
}) def.value
|
||||
);
|
||||
|
||||
unwrapNullOr =
|
||||
type:
|
||||
let
|
||||
typeName = type.name or null;
|
||||
in
|
||||
if typeName == "nullOr" then type.nestedTypes.name or null else typeName;
|
||||
|
||||
mergeAttrs =
|
||||
{ type, definitionsWithLocations }:
|
||||
let
|
||||
# Vendored merge from lib.types.attrsOf
|
||||
# Because we still cannot access highest prio for the individual attrs yet.
|
||||
elemType = type.nestedTypes.elemType;
|
||||
mergedAttrs = lib.zipAttrsWith (name: defs: lib.modules.mergeDefinitions ([ name ]) elemType defs) (
|
||||
pushPositions definitionsWithLocations
|
||||
);
|
||||
headType = unwrapNullOr elemType;
|
||||
nullable = elemType.name or null == "nullOr";
|
||||
total = elemType.name or null == "submodule";
|
||||
in
|
||||
lib.mapAttrs (_name: merged: {
|
||||
__this = {
|
||||
prio = merged.defsFinal'.highestPrio;
|
||||
files = map (def: def.file) merged.defsFinal'.values;
|
||||
inherit
|
||||
headType
|
||||
nullable
|
||||
total
|
||||
;
|
||||
};
|
||||
}) mergedAttrs;
|
||||
|
||||
/**
|
||||
Takes a set of options as returned by `configuration`
|
||||
|
||||
@@ -45,19 +85,15 @@ let
|
||||
lib.mapAttrs (
|
||||
_: opt:
|
||||
let
|
||||
headType =
|
||||
let
|
||||
typeName = opt.type.name or null;
|
||||
in
|
||||
if typeName == "nullOr" then opt.type.nestedTypes.name or null else typeName;
|
||||
headType = unwrapNullOr opt.type;
|
||||
nullable = opt.type.name or null == "nullOr";
|
||||
total = opt.type.name or null == "submodule";
|
||||
|
||||
definitionInfo = {
|
||||
__this = {
|
||||
prio = opt.highestPrio or null;
|
||||
files = opt.files or [ ];
|
||||
inherit headType nullable;
|
||||
total = opt.type.name or null == "submodule";
|
||||
inherit headType nullable total;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -71,18 +107,34 @@ let
|
||||
/**
|
||||
Maps attrsOf and lazyAttrsOf
|
||||
*/
|
||||
handleAttrsOf = attrs: lib.mapAttrs (_: handleMeta) attrs;
|
||||
handleAttrsOf =
|
||||
type: defs: attrs:
|
||||
lib.mapAttrs (
|
||||
name: meta:
|
||||
(mergeAttrs {
|
||||
inherit type;
|
||||
definitionsWithLocations = defs;
|
||||
}).${name}
|
||||
// handleMeta {
|
||||
inherit meta;
|
||||
definitionsWithLocations =
|
||||
(builtins.zipAttrsWith (_name: values: values) (pushPositions defs)).${name};
|
||||
}
|
||||
) attrs;
|
||||
|
||||
/**
|
||||
Maps attrsOf and lazyAttrsOf
|
||||
*/
|
||||
handleListOf = list: { __list = lib.map handleMeta list; };
|
||||
handleListOf = list: { __list = lib.map handleMeta { meta = list; }; };
|
||||
|
||||
/**
|
||||
Unwraps the valueMeta of an option based on its type
|
||||
*/
|
||||
handleMeta =
|
||||
meta:
|
||||
{
|
||||
meta,
|
||||
definitionsWithLocations ? [ ],
|
||||
}:
|
||||
let
|
||||
hasType = meta ? _internal.type;
|
||||
type = meta._internal.type;
|
||||
@@ -93,7 +145,7 @@ let
|
||||
# TODO: handle types
|
||||
getPrios { options = filterOptions meta.configuration.options; }
|
||||
else if type.name == "attrsOf" || type.name == "lazyAttrsOf" then
|
||||
handleAttrsOf meta.attrs
|
||||
handleAttrsOf meta._internal.type definitionsWithLocations meta.attrs
|
||||
# TODO: Add index support in nixpkgs first
|
||||
# else if type.name == "listOf" then
|
||||
# handleListOf meta.list
|
||||
@@ -103,7 +155,7 @@ let
|
||||
if opt ? type && opt.type.name == "submodule" then
|
||||
(definitionInfo) // submodulePrios
|
||||
else if opt ? type && (opt.type.name == "attrsOf" || opt.type.name == "lazyAttrsOf") then
|
||||
definitionInfo // (handleAttrsOf opt.valueMeta.attrs)
|
||||
definitionInfo // (handleAttrsOf opt.type opt.definitionsWithLocations opt.valueMeta.attrs)
|
||||
# TODO: Add index support in nixpkgs, otherwise we cannot
|
||||
else if opt ? type && (opt.type.name == "listOf") then
|
||||
definitionInfo // (handleListOf opt.valueMeta.list)
|
||||
|
||||
@@ -314,12 +314,17 @@ in
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
{
|
||||
config.foo.nested = lib.mkForce {
|
||||
# <- 50 prio
|
||||
"bar" = 2;
|
||||
};
|
||||
}
|
||||
{
|
||||
config.foo = {
|
||||
"nested" = {
|
||||
"bar" = 2; # <- 100 prio ?
|
||||
};
|
||||
"other" = {
|
||||
"bar" = lib.mkForce 2; # <- 50 prio ?
|
||||
"other" = lib.mkForce {
|
||||
"bar" = 2; # <- 50 prio
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -330,11 +335,19 @@ in
|
||||
expected = {
|
||||
foo = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
files = [
|
||||
"<unknown-file>"
|
||||
"<unknown-file>"
|
||||
];
|
||||
prio = 100;
|
||||
total = false;
|
||||
};
|
||||
nested = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
prio = 50;
|
||||
total = true;
|
||||
};
|
||||
bar = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
@@ -344,10 +357,15 @@ in
|
||||
};
|
||||
};
|
||||
other = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
prio = 50;
|
||||
total = true;
|
||||
};
|
||||
bar = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
prio = 50;
|
||||
prio = 100;
|
||||
total = false;
|
||||
};
|
||||
};
|
||||
@@ -401,7 +419,17 @@ in
|
||||
total = false;
|
||||
};
|
||||
a = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
prio = 100;
|
||||
total = false;
|
||||
};
|
||||
b = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
prio = 100;
|
||||
total = true;
|
||||
};
|
||||
bar = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
@@ -411,6 +439,11 @@ in
|
||||
};
|
||||
};
|
||||
c = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
prio = 100;
|
||||
total = true;
|
||||
};
|
||||
bar = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
@@ -421,7 +454,17 @@ in
|
||||
};
|
||||
};
|
||||
x = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
prio = 100;
|
||||
total = false;
|
||||
};
|
||||
y = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
prio = 100;
|
||||
total = true;
|
||||
};
|
||||
bar = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
@@ -431,6 +474,11 @@ in
|
||||
};
|
||||
};
|
||||
z = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
prio = 100;
|
||||
total = true;
|
||||
};
|
||||
bar = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
@@ -443,7 +491,6 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
test_attrsOf_submodule_default =
|
||||
let
|
||||
evaluated = eval [
|
||||
@@ -496,6 +543,14 @@ in
|
||||
total = false;
|
||||
};
|
||||
jon = {
|
||||
__this = {
|
||||
files = [
|
||||
"<unknown-file>"
|
||||
"inventory.json"
|
||||
];
|
||||
prio = 100;
|
||||
total = true;
|
||||
};
|
||||
fludl = {
|
||||
__this = {
|
||||
files = [ "<unknown-file>" ];
|
||||
|
||||
Reference in New Issue
Block a user