mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-12 04:35:41 +03:00
lib.types: Introduce types.optionType
This type correctly merges multiple option types together while also annotating them with file information. In a future commit this will be used for `_module.freeformType`
This commit is contained in:
parent
891e65b0fa
commit
5cbeddfde4
6 changed files with 113 additions and 1 deletions
|
@ -299,6 +299,13 @@ checkConfigOutput "10" config.processedToplevel ./raw.nix
|
||||||
checkConfigError "The option .multiple. is defined multiple times" config.multiple ./raw.nix
|
checkConfigError "The option .multiple. is defined multiple times" config.multiple ./raw.nix
|
||||||
checkConfigOutput "bar" config.priorities ./raw.nix
|
checkConfigOutput "bar" config.priorities ./raw.nix
|
||||||
|
|
||||||
|
# Test that types.optionType merges types correctly
|
||||||
|
checkConfigOutput '^10$' config.theOption.int ./optionTypeMerging.nix
|
||||||
|
checkConfigOutput '^"hello"$' config.theOption.str ./optionTypeMerging.nix
|
||||||
|
|
||||||
|
# Test that types.optionType correctly annotates option locations
|
||||||
|
checkConfigError 'The option .theOption.nested. in .other.nix. is already declared in .optionTypeFile.nix.' config.theOption.nested ./optionTypeFile.nix
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
====== module tests ======
|
====== module tests ======
|
||||||
$pass Pass
|
$pass Pass
|
||||||
|
|
28
lib/tests/modules/optionTypeFile.nix
Normal file
28
lib/tests/modules/optionTypeFile.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{ config, lib, ... }: {
|
||||||
|
|
||||||
|
_file = "optionTypeFile.nix";
|
||||||
|
|
||||||
|
options.theType = lib.mkOption {
|
||||||
|
type = lib.types.optionType;
|
||||||
|
};
|
||||||
|
|
||||||
|
options.theOption = lib.mkOption {
|
||||||
|
type = config.theType;
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
config.theType = lib.mkMerge [
|
||||||
|
(lib.types.submodule {
|
||||||
|
options.nested = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(lib.types.submodule {
|
||||||
|
_file = "other.nix";
|
||||||
|
options.nested = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
27
lib/tests/modules/optionTypeMerging.nix
Normal file
27
lib/tests/modules/optionTypeMerging.nix
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{ config, lib, ... }: {
|
||||||
|
|
||||||
|
options.theType = lib.mkOption {
|
||||||
|
type = lib.types.optionType;
|
||||||
|
};
|
||||||
|
|
||||||
|
options.theOption = lib.mkOption {
|
||||||
|
type = config.theType;
|
||||||
|
};
|
||||||
|
|
||||||
|
config.theType = lib.mkMerge [
|
||||||
|
(lib.types.submodule {
|
||||||
|
options.int = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 10;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
(lib.types.submodule {
|
||||||
|
options.str = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
config.theOption.str = "hello";
|
||||||
|
|
||||||
|
}
|
|
@ -61,7 +61,11 @@ let
|
||||||
boolToString
|
boolToString
|
||||||
;
|
;
|
||||||
|
|
||||||
inherit (lib.modules) mergeDefinitions;
|
inherit (lib.modules)
|
||||||
|
mergeDefinitions
|
||||||
|
fixupOptionType
|
||||||
|
mergeOptionDecls
|
||||||
|
;
|
||||||
outer_types =
|
outer_types =
|
||||||
rec {
|
rec {
|
||||||
isType = type: x: (x._type or "") == type;
|
isType = type: x: (x._type or "") == type;
|
||||||
|
@ -525,6 +529,31 @@ rec {
|
||||||
modules = toList modules;
|
modules = toList modules;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# The type of a type!
|
||||||
|
optionType = mkOptionType {
|
||||||
|
name = "optionType";
|
||||||
|
description = "optionType";
|
||||||
|
check = value: value._type or null == "option-type";
|
||||||
|
merge = loc: defs:
|
||||||
|
let
|
||||||
|
# Prepares the type definitions for mergeOptionDecls, which
|
||||||
|
# annotates submodules types with file locations
|
||||||
|
optionModules = map ({ value, file }:
|
||||||
|
{
|
||||||
|
_file = file;
|
||||||
|
# There's no way to merge types directly from the module system,
|
||||||
|
# but we can cheat a bit by just declaring an option with the type
|
||||||
|
options = lib.mkOption {
|
||||||
|
type = value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) defs;
|
||||||
|
# Merges all the types into a single one, including submodule merging.
|
||||||
|
# This also propagates file information to all submodules
|
||||||
|
mergedOption = fixupOptionType loc (mergeOptionDecls loc optionModules);
|
||||||
|
in mergedOption.type;
|
||||||
|
};
|
||||||
|
|
||||||
submoduleWith =
|
submoduleWith =
|
||||||
{ modules
|
{ modules
|
||||||
, specialArgs ? {}
|
, specialArgs ? {}
|
||||||
|
|
|
@ -74,6 +74,13 @@ merging is handled.
|
||||||
should only be used when checking, merging and nested evaluation are not
|
should only be used when checking, merging and nested evaluation are not
|
||||||
desirable.
|
desirable.
|
||||||
|
|
||||||
|
`types.optionType`
|
||||||
|
|
||||||
|
: The type of an option's type. Its merging operation ensures that nested
|
||||||
|
options have the correct file location annotated, and that if possible,
|
||||||
|
multiple option definitions are correctly merged together. The main use
|
||||||
|
case is as the type of the `_module.freeformType` option.
|
||||||
|
|
||||||
`types.attrs`
|
`types.attrs`
|
||||||
|
|
||||||
: A free-form attribute set.
|
: A free-form attribute set.
|
||||||
|
|
|
@ -111,6 +111,20 @@
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<literal>types.optionType</literal>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The type of an option’s type. Its merging operation ensures
|
||||||
|
that nested options have the correct file location
|
||||||
|
annotated, and that if possible, multiple option definitions
|
||||||
|
are correctly merged together. The main use case is as the
|
||||||
|
type of the <literal>_module.freeformType</literal> option.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
<literal>types.attrs</literal>
|
<literal>types.attrs</literal>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue