summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/tests/misc.nix36
-rw-r--r--lib/types.nix31
2 files changed, 65 insertions, 2 deletions
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index f5f1fb5e7c2d..d17231061d69 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -2830,6 +2830,42 @@ runTests {
expected = "unknown";
};
+ # https://github.com/NixOS/nixpkgs/issues/396849
+ "test: submodule definitions aren't unchecked when evaluating submodule documentation" = {
+ expr =
+ let
+ module =
+ { lib, ... }:
+ {
+ options.foo = lib.mkOption { type = lib.types.submodule submodule; };
+ };
+
+ submodule = {
+ options.bar = lib.mkOption { type = lib.types.int; };
+ config.submoduleWrong = throw "yikes";
+ };
+
+ options = (evalModules { modules = [ module ]; }).options;
+
+ renderableOpts = filter (o: !o.internal) (optionAttrSetToDocList options);
+ # Evaluate the whole docs
+ in
+ builtins.deepSeq renderableOpts
+ # Return the locations
+ (map (o: o.loc) renderableOpts);
+ expected = [
+ [
+ "_module"
+ "args"
+ ]
+ [ "foo" ]
+ [
+ "foo"
+ "bar"
+ ]
+ ];
+ };
+
testFreeformOptions = {
expr =
let
diff --git a/lib/types.nix b/lib/types.nix
index 11b1b5463bc7..92cdb1491c7c 100644
--- a/lib/types.nix
+++ b/lib/types.nix
@@ -290,6 +290,15 @@ let
unparenthesize: t:
if unparenthesize (t.descriptionClass or null) then t.description else "(${t.description})";
+ noCheckForDocsModule = {
+ # When generating documentation, our goal isn't to check anything.
+ # Quite the opposite in fact. Generating docs is somewhat of a
+ # challenge, evaluating modules in a *lacking* context. Anything
+ # that makes the docs avoid an error is a win.
+ config._module.check = lib.mkForce false;
+ _file = "<built-in module that disables checks for the purpose of documentation generation>";
+ };
+
# When adding new types don't forget to document them in
# nixos/doc/manual/development/option-types.section.md!
types = rec {
@@ -1209,7 +1218,14 @@ let
in
mkOptionType {
inherit name;
- description = if description != null then description else freeformType.description or name;
+ description =
+ if description != null then
+ description
+ else
+ let
+ docsEval = base.extendModules { modules = [ noCheckForDocsModule ]; };
+ in
+ docsEval._module.freeformType.description or name;
check = x: isAttrs x || isFunction x || path.check x;
merge =
loc: defs:
@@ -1222,7 +1238,18 @@ let
};
getSubOptions =
prefix:
- (base.extendModules { inherit prefix; }).options
+ let
+ docsEval = (
+ base.extendModules {
+ inherit prefix;
+ modules = [ noCheckForDocsModule ];
+ }
+ );
+ # Intentionally shadow the freeformType from the possibly *checked*
+ # configuration. See `noCheckForDocsModule` comment.
+ inherit (docsEval._module) freeformType;
+ in
+ docsEval.options
// optionalAttrs (freeformType != null) {
# Expose the sub options of the freeform type. Note that the option
# discovery doesn't care about the attribute name used here, so this