about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2024-01-29 07:10:14 +0100
committerRobert Hensing <robert@roberthensing.nl>2024-04-04 11:54:41 +0200
commit5b49672af44875df0449f7ff1b55965eedeec1da (patch)
tree95bc925c9eb0f64dec8734242dfb46811d8f99c0 /lib
parent6949bc21ce1de068bc1b21e273d15620c0e5770e (diff)
lib.types.attrTag: Support module docs
Diffstat (limited to 'lib')
-rw-r--r--lib/tests/modules/docs.nix41
-rw-r--r--lib/tests/modules/types-attrTag.nix19
-rw-r--r--lib/types.nix6
3 files changed, 65 insertions, 1 deletions
diff --git a/lib/tests/modules/docs.nix b/lib/tests/modules/docs.nix
new file mode 100644
index 0000000000000..225aa7eac1de8
--- /dev/null
+++ b/lib/tests/modules/docs.nix
@@ -0,0 +1,41 @@
+/*
+  A basic documentation generating module.
+  Declares and defines a `docs` option, suitable for making assertions about
+  the extraction "phase" of documentation generation.
+ */
+{ lib, options, ... }:
+
+let
+  inherit (lib)
+    head
+    length
+    mkOption
+    types
+  ;
+
+  traceListSeq = l: v: lib.foldl' (a: b: lib.traceSeq b a) v l;
+
+in
+
+{
+  options.docs = mkOption {
+    type = types.lazyAttrsOf types.raw;
+    description = ''
+      All options to be rendered, without any visibility filtering applied.
+    '';
+  };
+  config.docs =
+    lib.zipAttrsWith
+      (name: values:
+        if length values > 1 then
+          traceListSeq values
+          abort "Multiple options with the same name: ${name}"
+        else
+          assert length values == 1;
+          head values
+      )
+      (map
+        (opt: { ${opt.name} = opt; })
+        (lib.optionAttrSetToDocList options)
+      );
+}
diff --git a/lib/tests/modules/types-attrTag.nix b/lib/tests/modules/types-attrTag.nix
index 08854ca73f566..1a0a0f7ba01e4 100644
--- a/lib/tests/modules/types-attrTag.nix
+++ b/lib/tests/modules/types-attrTag.nix
@@ -28,9 +28,24 @@ in
         }
       );
     };
+    submodules = mkOption {
+      type = types.attrsOf (
+        types.attrTag {
+          foo = types.submodule {
+            options = {
+              bar = mkOption {
+                type = types.int;
+              };
+            };
+          };
+          qux = types.str;
+        }
+      );
+    };
     okChecks = mkOption {};
   };
   imports = [
+    ./docs.nix
     {
       options.merged = mkOption {
         type = types.attrsOf (
@@ -59,6 +74,10 @@ in
       assert config.intStrings.numberOne.left == 1;
       assert config.merged.negative.nay == false;
       assert config.merged.positive.yay == 100;
+      # assert lib.foldl' (a: b: builtins.trace b a) true (lib.attrNames config.docs);
+      assert config.docs."submodules.<name>.foo.bar".type == "signed integer";
+      # It's not an option, so we can't render it as such. Something would be nice though.
+      assert ! (config.docs?"submodules.<name>.qux");
       true;
   };
 }
diff --git a/lib/types.nix b/lib/types.nix
index 59577856f4e1f..5286ce76862e2 100644
--- a/lib/types.nix
+++ b/lib/types.nix
@@ -623,7 +623,11 @@ rec {
       mkOptionType {
         name = "attrTag";
         description = "attribute-tagged union of ${choicesStr}";
-        getSubModules = null;
+        getSubOptions = prefix:
+          mapAttrs
+            (tagName: tagType:
+              tagType.getSubOptions (prefix ++ [ tagName ]))
+            tags;
         substSubModules = m: attrTagWith { tags = mapAttrs (n: v: v.substSubModules m) tags; };
         check = v: isAttrs v && length (attrNames v) == 1 && tags?${head (attrNames v)};
         merge = loc: defs: