Merge pull request #99132 from Infinisil/recursive-type-deprecation
Recursive type deprecation
This commit is contained in:
commit
ce93c98ce2
@ -515,11 +515,20 @@ rec {
|
|||||||
# yield a value computed from the definitions
|
# yield a value computed from the definitions
|
||||||
value = if opt ? apply then opt.apply res.mergedValue else res.mergedValue;
|
value = if opt ? apply then opt.apply res.mergedValue else res.mergedValue;
|
||||||
|
|
||||||
warnDeprecation =
|
# Issue deprecation warnings recursively over all nested types of the
|
||||||
warnIf (opt.type.deprecationMessage != null)
|
# given type. But don't recurse if a type with the same name was already
|
||||||
"The type `types.${opt.type.name}' of option `${showOption loc}' defined in ${showFiles opt.declarations} is deprecated. ${opt.type.deprecationMessage}";
|
# visited before in order to prevent infinite recursion. So this only
|
||||||
|
# warns once per type name.
|
||||||
|
# Returns the new set of visited type names
|
||||||
|
recursiveWarn = visited: type:
|
||||||
|
let
|
||||||
|
maybeWarn = warnIf (type.deprecationMessage != null)
|
||||||
|
"The type `types.${type.name}' of option `${showOption loc}' defined in ${showFiles opt.declarations} is deprecated. ${type.deprecationMessage}";
|
||||||
|
in
|
||||||
|
if visited ? ${type.name} then visited
|
||||||
|
else lib.foldl' recursiveWarn (maybeWarn visited // { ${type.name} = null; }) (lib.attrValues type.nestedTypes);
|
||||||
|
|
||||||
in warnDeprecation opt //
|
in builtins.seq (recursiveWarn {} opt.type) opt //
|
||||||
{ value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
|
{ value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
|
||||||
inherit (res.defsFinal') highestPrio;
|
inherit (res.defsFinal') highestPrio;
|
||||||
definitions = map (def: def.value) res.defsFinal;
|
definitions = map (def: def.value) res.defsFinal;
|
||||||
|
@ -175,6 +175,9 @@ checkConfigOutput "true" config.submodule.config ./declare-submoduleWith-noshort
|
|||||||
## submoduleWith should merge all modules in one swoop
|
## submoduleWith should merge all modules in one swoop
|
||||||
checkConfigOutput "true" config.submodule.inner ./declare-submoduleWith-modules.nix
|
checkConfigOutput "true" config.submodule.inner ./declare-submoduleWith-modules.nix
|
||||||
checkConfigOutput "true" config.submodule.outer ./declare-submoduleWith-modules.nix
|
checkConfigOutput "true" config.submodule.outer ./declare-submoduleWith-modules.nix
|
||||||
|
# Should also be able to evaluate the type name (which evaluates freeformType,
|
||||||
|
# which evaluates all the modules defined by the type)
|
||||||
|
checkConfigOutput "submodule" options.submodule.type.description ./declare-submoduleWith-modules.nix
|
||||||
|
|
||||||
## Paths should be allowed as values and work as expected
|
## Paths should be allowed as values and work as expected
|
||||||
checkConfigOutput "true" config.submodule.enable ./declare-submoduleWith-path.nix
|
checkConfigOutput "true" config.submodule.enable ./declare-submoduleWith-path.nix
|
||||||
@ -269,6 +272,12 @@ checkConfigError 'A definition for option .fun.\[function body\]. is not of type
|
|||||||
checkConfigOutput "b a" config.result ./functionTo/list-order.nix
|
checkConfigOutput "b a" config.result ./functionTo/list-order.nix
|
||||||
checkConfigOutput "a c" config.result ./functionTo/merging-attrs.nix
|
checkConfigOutput "a c" config.result ./functionTo/merging-attrs.nix
|
||||||
|
|
||||||
|
## Type deprecation
|
||||||
|
checkConfigError 'The type `types.simple'\'' of option `simple'\'' defined in .* is deprecated. simple shall not be used' config.simple ./type-deprecation.nix
|
||||||
|
checkConfigError 'The type `types.infinite'\'' of option `infinite'\'' defined in .* is deprecated. infinite shall not be used' config.infinite ./type-deprecation.nix
|
||||||
|
checkConfigError 'The type `types.left'\'' of option `nested'\'' defined in .* is deprecated. left shall not be used' config.nested ./type-deprecation.nix
|
||||||
|
checkConfigError 'The type `types.right'\'' of option `nested'\'' defined in .* is deprecated. right shall not be used' config.nested ./type-deprecation.nix
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
====== module tests ======
|
====== module tests ======
|
||||||
$pass Pass
|
$pass Pass
|
||||||
|
@ -8,9 +8,6 @@
|
|||||||
default = false;
|
default = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
{
|
|
||||||
outer = true;
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
default = {};
|
default = {};
|
||||||
@ -25,6 +22,7 @@
|
|||||||
})
|
})
|
||||||
{
|
{
|
||||||
inner = true;
|
inner = true;
|
||||||
|
outer = true;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
39
lib/tests/modules/type-deprecation.nix
Normal file
39
lib/tests/modules/type-deprecation.nix
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
{ lib, ... }: {
|
||||||
|
|
||||||
|
options.simple = lib.mkOption {
|
||||||
|
type = lib.mkOptionType {
|
||||||
|
name = "simple";
|
||||||
|
deprecationMessage = "simple shall not be used";
|
||||||
|
};
|
||||||
|
default = throw "";
|
||||||
|
};
|
||||||
|
|
||||||
|
options.infinite = lib.mkOption {
|
||||||
|
type =
|
||||||
|
let
|
||||||
|
t = lib.mkOptionType {
|
||||||
|
name = "infinite";
|
||||||
|
deprecationMessage = "infinite shall not be used";
|
||||||
|
};
|
||||||
|
r = lib.types.either t (lib.types.attrsOf r);
|
||||||
|
in r;
|
||||||
|
default = throw "";
|
||||||
|
};
|
||||||
|
|
||||||
|
options.nested = lib.mkOption {
|
||||||
|
type =
|
||||||
|
let
|
||||||
|
left = lib.mkOptionType {
|
||||||
|
name = "left";
|
||||||
|
deprecationMessage = "left shall not be used";
|
||||||
|
};
|
||||||
|
right = lib.mkOptionType {
|
||||||
|
name = "right";
|
||||||
|
deprecationMessage = "right shall not be used";
|
||||||
|
};
|
||||||
|
in lib.types.either left right;
|
||||||
|
|
||||||
|
default = throw "";
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -147,9 +147,13 @@ rec {
|
|||||||
, # The deprecation message to display when this type is used by an option
|
, # The deprecation message to display when this type is used by an option
|
||||||
# If null, the type isn't deprecated
|
# If null, the type isn't deprecated
|
||||||
deprecationMessage ? null
|
deprecationMessage ? null
|
||||||
|
, # The types that occur in the definition of this type. This is used to
|
||||||
|
# issue deprecation warnings recursively. Can also be used to reuse
|
||||||
|
# nested types
|
||||||
|
nestedTypes ? {}
|
||||||
}:
|
}:
|
||||||
{ _type = "option-type";
|
{ _type = "option-type";
|
||||||
inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor deprecationMessage;
|
inherit name check merge emptyValue getSubOptions getSubModules substSubModules typeMerge functor deprecationMessage nestedTypes;
|
||||||
description = if description == null then name else description;
|
description = if description == null then name else description;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -365,6 +369,7 @@ rec {
|
|||||||
getSubModules = elemType.getSubModules;
|
getSubModules = elemType.getSubModules;
|
||||||
substSubModules = m: listOf (elemType.substSubModules m);
|
substSubModules = m: listOf (elemType.substSubModules m);
|
||||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||||
|
nestedTypes.elemType = elemType;
|
||||||
};
|
};
|
||||||
|
|
||||||
nonEmptyListOf = elemType:
|
nonEmptyListOf = elemType:
|
||||||
@ -389,6 +394,7 @@ rec {
|
|||||||
getSubModules = elemType.getSubModules;
|
getSubModules = elemType.getSubModules;
|
||||||
substSubModules = m: attrsOf (elemType.substSubModules m);
|
substSubModules = m: attrsOf (elemType.substSubModules m);
|
||||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||||
|
nestedTypes.elemType = elemType;
|
||||||
};
|
};
|
||||||
|
|
||||||
# A version of attrsOf that's lazy in its values at the expense of
|
# A version of attrsOf that's lazy in its values at the expense of
|
||||||
@ -413,6 +419,7 @@ rec {
|
|||||||
getSubModules = elemType.getSubModules;
|
getSubModules = elemType.getSubModules;
|
||||||
substSubModules = m: lazyAttrsOf (elemType.substSubModules m);
|
substSubModules = m: lazyAttrsOf (elemType.substSubModules m);
|
||||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||||
|
nestedTypes.elemType = elemType;
|
||||||
};
|
};
|
||||||
|
|
||||||
# TODO: drop this in the future:
|
# TODO: drop this in the future:
|
||||||
@ -421,6 +428,7 @@ rec {
|
|||||||
deprecationMessage = "Mixing lists with attribute values is no longer"
|
deprecationMessage = "Mixing lists with attribute values is no longer"
|
||||||
+ " possible; please use `types.attrsOf` instead. See"
|
+ " possible; please use `types.attrsOf` instead. See"
|
||||||
+ " https://github.com/NixOS/nixpkgs/issues/1800 for the motivation.";
|
+ " https://github.com/NixOS/nixpkgs/issues/1800 for the motivation.";
|
||||||
|
nestedTypes.elemType = elemType;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Value of given type but with no merging (i.e. `uniq list`s are not concatenated).
|
# Value of given type but with no merging (i.e. `uniq list`s are not concatenated).
|
||||||
@ -433,6 +441,7 @@ rec {
|
|||||||
getSubModules = elemType.getSubModules;
|
getSubModules = elemType.getSubModules;
|
||||||
substSubModules = m: uniq (elemType.substSubModules m);
|
substSubModules = m: uniq (elemType.substSubModules m);
|
||||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||||
|
nestedTypes.elemType = elemType;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Null or value of ...
|
# Null or value of ...
|
||||||
@ -451,6 +460,7 @@ rec {
|
|||||||
getSubModules = elemType.getSubModules;
|
getSubModules = elemType.getSubModules;
|
||||||
substSubModules = m: nullOr (elemType.substSubModules m);
|
substSubModules = m: nullOr (elemType.substSubModules m);
|
||||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||||
|
nestedTypes.elemType = elemType;
|
||||||
};
|
};
|
||||||
|
|
||||||
functionTo = elemType: mkOptionType {
|
functionTo = elemType: mkOptionType {
|
||||||
@ -535,6 +545,9 @@ rec {
|
|||||||
substSubModules = m: submoduleWith (attrs // {
|
substSubModules = m: submoduleWith (attrs // {
|
||||||
modules = m;
|
modules = m;
|
||||||
});
|
});
|
||||||
|
nestedTypes = lib.optionalAttrs (freeformType != null) {
|
||||||
|
freeformType = freeformType;
|
||||||
|
};
|
||||||
functor = defaultFunctor name // {
|
functor = defaultFunctor name // {
|
||||||
type = types.submoduleWith;
|
type = types.submoduleWith;
|
||||||
payload = {
|
payload = {
|
||||||
@ -596,6 +609,8 @@ rec {
|
|||||||
then functor.type mt1 mt2
|
then functor.type mt1 mt2
|
||||||
else null;
|
else null;
|
||||||
functor = (defaultFunctor name) // { wrapped = [ t1 t2 ]; };
|
functor = (defaultFunctor name) // { wrapped = [ t1 t2 ]; };
|
||||||
|
nestedTypes.left = t1;
|
||||||
|
nestedTypes.right = t2;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Any of the types in the given list
|
# Any of the types in the given list
|
||||||
@ -627,6 +642,8 @@ rec {
|
|||||||
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
substSubModules = m: coercedTo coercedType coerceFunc (finalType.substSubModules m);
|
||||||
typeMerge = t1: t2: null;
|
typeMerge = t1: t2: null;
|
||||||
functor = (defaultFunctor name) // { wrapped = finalType; };
|
functor = (defaultFunctor name) // { wrapped = finalType; };
|
||||||
|
nestedTypes.coercedType = coercedType;
|
||||||
|
nestedTypes.finalType = finalType;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Obsolete alternative to configOf. It takes its option
|
# Obsolete alternative to configOf. It takes its option
|
||||||
|
@ -37,7 +37,7 @@ in
|
|||||||
enableProfilePath = mkEnableOption "exposing the Disnix profiles in the system's PATH";
|
enableProfilePath = mkEnableOption "exposing the Disnix profiles in the system's PATH";
|
||||||
|
|
||||||
profiles = mkOption {
|
profiles = mkOption {
|
||||||
type = types.listOf types.string;
|
type = types.listOf types.str;
|
||||||
default = [ "default" ];
|
default = [ "default" ];
|
||||||
example = [ "default" ];
|
example = [ "default" ];
|
||||||
description = "Names of the Disnix profiles to expose in the system's PATH";
|
description = "Names of the Disnix profiles to expose in the system's PATH";
|
||||||
|
@ -112,7 +112,7 @@ let
|
|||||||
http://tools.ietf.org/html/rfc4366#section-3.1
|
http://tools.ietf.org/html/rfc4366#section-3.1
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
name = mkOpt types.string ''
|
name = mkOpt types.str ''
|
||||||
Name of the remote read config, which if specified must be unique among remote read configs.
|
Name of the remote read config, which if specified must be unique among remote read configs.
|
||||||
The name will be used in metrics and logging in place of a generated value to help users distinguish between
|
The name will be used in metrics and logging in place of a generated value to help users distinguish between
|
||||||
remote read configs.
|
remote read configs.
|
||||||
@ -174,7 +174,7 @@ let
|
|||||||
write_relabel_configs = mkOpt (types.listOf promTypes.relabel_config) ''
|
write_relabel_configs = mkOpt (types.listOf promTypes.relabel_config) ''
|
||||||
List of remote write relabel configurations.
|
List of remote write relabel configurations.
|
||||||
'';
|
'';
|
||||||
name = mkOpt types.string ''
|
name = mkOpt types.str ''
|
||||||
Name of the remote write config, which if specified must be unique among remote write configs.
|
Name of the remote write config, which if specified must be unique among remote write configs.
|
||||||
The name will be used in metrics and logging in place of a generated value to help users distinguish between
|
The name will be used in metrics and logging in place of a generated value to help users distinguish between
|
||||||
remote write configs.
|
remote write configs.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user