Merge pull request #249243 from lf-/jade/declarationsWithLocations
nixos/modules: Add declarationPositions
This commit is contained in:
@@ -537,7 +537,7 @@ let
|
|||||||
mergeModules' prefix modules
|
mergeModules' prefix modules
|
||||||
(concatMap (m: map (config: { file = m._file; inherit config; }) (pushDownProperties m.config)) modules);
|
(concatMap (m: map (config: { file = m._file; inherit config; }) (pushDownProperties m.config)) modules);
|
||||||
|
|
||||||
mergeModules' = prefix: options: configs:
|
mergeModules' = prefix: modules: configs:
|
||||||
let
|
let
|
||||||
# an attrset 'name' => list of submodules that declare ‘name’.
|
# an attrset 'name' => list of submodules that declare ‘name’.
|
||||||
declsByName =
|
declsByName =
|
||||||
@@ -554,11 +554,11 @@ let
|
|||||||
else
|
else
|
||||||
mapAttrs
|
mapAttrs
|
||||||
(n: option:
|
(n: option:
|
||||||
[{ inherit (module) _file; options = option; }]
|
[{ inherit (module) _file; pos = builtins.unsafeGetAttrPos n subtree; options = option; }]
|
||||||
)
|
)
|
||||||
subtree
|
subtree
|
||||||
)
|
)
|
||||||
options);
|
modules);
|
||||||
|
|
||||||
# The root of any module definition must be an attrset.
|
# The root of any module definition must be an attrset.
|
||||||
checkedConfigs =
|
checkedConfigs =
|
||||||
@@ -762,9 +762,16 @@ let
|
|||||||
else res.options;
|
else res.options;
|
||||||
in opt.options // res //
|
in opt.options // res //
|
||||||
{ declarations = res.declarations ++ [opt._file];
|
{ declarations = res.declarations ++ [opt._file];
|
||||||
|
# In the case of modules that are generated dynamically, we won't
|
||||||
|
# have exact declaration lines; fall back to just the file being
|
||||||
|
# evaluated.
|
||||||
|
declarationPositions = res.declarationPositions
|
||||||
|
++ (if opt.pos != null
|
||||||
|
then [opt.pos]
|
||||||
|
else [{ file = opt._file; line = null; column = null; }]);
|
||||||
options = submodules;
|
options = submodules;
|
||||||
} // typeSet
|
} // typeSet
|
||||||
) { inherit loc; declarations = []; options = []; } opts;
|
) { inherit loc; declarations = []; declarationPositions = []; options = []; } opts;
|
||||||
|
|
||||||
/* Merge all the definitions of an option to produce the final
|
/* Merge all the definitions of an option to produce the final
|
||||||
config value. */
|
config value. */
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ reportFailure() {
|
|||||||
checkConfigOutput() {
|
checkConfigOutput() {
|
||||||
local outputContains=$1
|
local outputContains=$1
|
||||||
shift
|
shift
|
||||||
if evalConfig "$@" 2>/dev/null | grep --silent "$outputContains" ; then
|
if evalConfig "$@" 2>/dev/null | grep -E --silent "$outputContains" ; then
|
||||||
((++pass))
|
((++pass))
|
||||||
else
|
else
|
||||||
echo 2>&1 "error: Expected result matching '$outputContains', while evaluating"
|
echo 2>&1 "error: Expected result matching '$outputContains', while evaluating"
|
||||||
@@ -444,6 +444,24 @@ checkConfigOutput '^"The option `a\.b. defined in `.*/doRename-warnings\.nix. ha
|
|||||||
checkConfigOutput '^"pear"$' config.once.raw ./merge-module-with-key.nix
|
checkConfigOutput '^"pear"$' config.once.raw ./merge-module-with-key.nix
|
||||||
checkConfigOutput '^"pear\\npear"$' config.twice.raw ./merge-module-with-key.nix
|
checkConfigOutput '^"pear\\npear"$' config.twice.raw ./merge-module-with-key.nix
|
||||||
|
|
||||||
|
# Declaration positions
|
||||||
|
# Line should be present for direct options
|
||||||
|
checkConfigOutput '^10$' options.imported.line10.declarationPositions.0.line ./declaration-positions.nix
|
||||||
|
checkConfigOutput '/declaration-positions.nix"$' options.imported.line10.declarationPositions.0.file ./declaration-positions.nix
|
||||||
|
# Generated options may not have line numbers but they will at least get the
|
||||||
|
# right file
|
||||||
|
checkConfigOutput '/declaration-positions.nix"$' options.generated.line18.declarationPositions.0.file ./declaration-positions.nix
|
||||||
|
checkConfigOutput '^null$' options.generated.line18.declarationPositions.0.line ./declaration-positions.nix
|
||||||
|
# Submodules don't break it
|
||||||
|
checkConfigOutput '^39$' config.submoduleLine34.submodDeclLine39.0.line ./declaration-positions.nix
|
||||||
|
checkConfigOutput '/declaration-positions.nix"$' config.submoduleLine34.submodDeclLine39.0.file ./declaration-positions.nix
|
||||||
|
# New options under freeform submodules get collected into the parent submodule
|
||||||
|
# (consistent with .declarations behaviour, but weird; notably appears in system.build)
|
||||||
|
checkConfigOutput '^34|23$' options.submoduleLine34.declarationPositions.0.line ./declaration-positions.nix
|
||||||
|
checkConfigOutput '^34|23$' options.submoduleLine34.declarationPositions.1.line ./declaration-positions.nix
|
||||||
|
# nested options work
|
||||||
|
checkConfigOutput '^30$' options.nested.nestedLine30.declarationPositions.0.line ./declaration-positions.nix
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
====== module tests ======
|
====== module tests ======
|
||||||
$pass Pass
|
$pass Pass
|
||||||
|
|||||||
49
lib/tests/modules/declaration-positions.nix
Normal file
49
lib/tests/modules/declaration-positions.nix
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{ lib, options, ... }:
|
||||||
|
let discardPositions = lib.mapAttrs (k: v: v);
|
||||||
|
in
|
||||||
|
# unsafeGetAttrPos is unspecified best-effort behavior, so we only want to consider this test on an evaluator that satisfies some basic assumptions about this function.
|
||||||
|
assert builtins.unsafeGetAttrPos "a" { a = true; } != null;
|
||||||
|
assert builtins.unsafeGetAttrPos "a" (discardPositions { a = true; }) == null;
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
{
|
||||||
|
options.imported.line10 = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Simulates various patterns of generating modules such as
|
||||||
|
# programs.firefox.nativeMessagingHosts.ff2mpv. We don't expect to get
|
||||||
|
# line numbers for these, but we can fall back on knowing the file.
|
||||||
|
options.generated = discardPositions {
|
||||||
|
line18 = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
options.submoduleLine34.extraOptLine23 = lib.mkOption {
|
||||||
|
default = 1;
|
||||||
|
type = lib.types.int;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
options.nested.nestedLine30 = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
};
|
||||||
|
|
||||||
|
options.submoduleLine34 = lib.mkOption {
|
||||||
|
default = { };
|
||||||
|
type = lib.types.submoduleWith {
|
||||||
|
modules = [
|
||||||
|
({ options, ... }: {
|
||||||
|
options.submodDeclLine39 = lib.mkOption { };
|
||||||
|
})
|
||||||
|
{ freeformType = with lib.types; lazyAttrsOf (uniq unspecified); }
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
submoduleLine34.submodDeclLine39 = (options.submoduleLine34.type.getSubOptions [ ]).submodDeclLine39.declarationPositions;
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user