Show error locations in submodules

This commit is contained in:
Eelco Dolstra 2013-10-28 15:13:51 +01:00
parent a40583e7e4
commit c263b5b284
2 changed files with 15 additions and 12 deletions

View File

@ -119,7 +119,7 @@ rec {
if opt.options ? default && res ? default || if opt.options ? default && res ? default ||
opt.options ? example && res ? example || opt.options ? example && res ? example ||
opt.options ? description && res ? description || opt.options ? description && res ? description ||
opt.options ? merge && res ? merge || opt.options ? merge && res ? merge || # FIXME: remove merge
opt.options ? apply && res ? apply || opt.options ? apply && res ? apply ||
opt.options ? type && res ? type opt.options ? type && res ? type
then then
@ -148,13 +148,13 @@ rec {
fold (def: res: fold (def: res:
if opt.type.check def.value then res if opt.type.check def.value then res
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${opt.type.name}.") else throw "The option value `${showOption loc}' in `${def.file}' is not a ${opt.type.name}.")
(opt.type.merge (map (m: m.value) defsFinal)) defsFinal; (opt.type.merge' { prefix = loc; } (map (m: m.value) defsFinal)) defsFinal;
# Finally, apply the apply function to the merged # Finally, apply the apply function to the merged
# value. This allows options to yield a value computed # value. This allows options to yield a value computed
# from the definitions. # from the definitions.
value = (opt.apply or id) merged; value = (opt.apply or id) merged;
in opt // in opt //
{ inherit value; { value = addErrorContext "while evaluating the option `${showOption loc}':" value;
definitions = defsFinal; definitions = defsFinal;
isDefined = defsFinal != []; isDefined = defsFinal != [];
}; };

View File

@ -37,6 +37,9 @@ rec {
}; };
addToPrefix = args: name: args // { prefix = args.prefix ++ [name]; };
types = rec { types = rec {
unspecified = mkOptionType { unspecified = mkOptionType {
@ -98,14 +101,15 @@ rec {
listOf = elemType: mkOptionType { listOf = elemType: mkOptionType {
name = "list of ${elemType.name}s"; name = "list of ${elemType.name}s";
check = value: isList value && all elemType.check value; check = value: isList value && all elemType.check value;
merge = defs: map (def: elemType.merge [def]) (concatLists defs); merge' = args: defs: imap (n: def: elemType.merge' (addToPrefix args (toString n)) [def]) (concatLists defs);
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]);
}; };
attrsOf = elemType: mkOptionType { attrsOf = elemType: mkOptionType {
name = "attribute set of ${elemType.name}s"; name = "attribute set of ${elemType.name}s";
check = x: isAttrs x && all elemType.check (lib.attrValues x); check = x: isAttrs x && all elemType.check (lib.attrValues x);
merge = lib.zipAttrsWith (name: elemType.merge' { inherit name; }); merge' = args: lib.zipAttrsWith (name:
elemType.merge' (addToPrefix (args // { inherit name; }) name));
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
}; };
@ -128,7 +132,7 @@ rec {
if isList x then listOnly.check x if isList x then listOnly.check x
else if isAttrs x then attrOnly.check x else if isAttrs x then attrOnly.check x
else false; else false;
merge = defs: attrOnly.merge (imap convertIfList defs); merge' = args: defs: attrOnly.merge' args (imap convertIfList defs);
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
}; };
@ -152,19 +156,19 @@ rec {
nullOr = elemType: mkOptionType { nullOr = elemType: mkOptionType {
name = "null or ${elemType.name}"; name = "null or ${elemType.name}";
check = x: builtins.isNull x || elemType.check x; check = x: builtins.isNull x || elemType.check x;
merge = defs: merge' = args: defs:
if all isNull defs then null if all isNull defs then null
else if any isNull defs then else if any isNull defs then
throw "Some but not all values are null." throw "Some but not all values are null."
else elemType.merge defs; else elemType.merge' args defs;
getSubOptions = elemType.getSubOptions; getSubOptions = elemType.getSubOptions;
}; };
functionTo = elemType: mkOptionType { functionTo = elemType: mkOptionType {
name = "function that evaluates to a(n) ${elemType.name}"; name = "function that evaluates to a(n) ${elemType.name}";
check = builtins.isFunction; check = builtins.isFunction;
merge = fns: merge' = args: fns:
args: elemType.merge (map (fn: fn args) fns); fnArgs: elemType.merge' args (map (fn: fn fnArgs) fns);
getSubOptions = elemType.getSubOptions; getSubOptions = elemType.getSubOptions;
}; };
@ -173,13 +177,12 @@ rec {
mkOptionType rec { mkOptionType rec {
name = "submodule"; name = "submodule";
check = x: isAttrs x || builtins.isFunction x; check = x: isAttrs x || builtins.isFunction x;
# FIXME: make error messages include the parent attrpath.
merge = merge' {}; merge = merge' {};
merge' = args: defs: merge' = args: defs:
let let
coerce = def: if builtins.isFunction def then def else { config = def; }; coerce = def: if builtins.isFunction def then def else { config = def; };
modules = opts' ++ map coerce defs; modules = opts' ++ map coerce defs;
in (evalModules modules args).config; in (evalModules' args.prefix modules args).config;
getSubOptions = prefix: (evalModules' prefix opts' getSubOptions = prefix: (evalModules' prefix opts'
# FIXME: hack to get shit to evaluate. # FIXME: hack to get shit to evaluate.
{ name = ""; } { name = ""; }