about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xlib/tests/modules.sh2
-rw-r--r--lib/tests/modules/functionTo/submodule-options.nix61
-rw-r--r--lib/types.nix4
-rw-r--r--nixos/lib/make-options-doc/options-to-docbook.xsl8
4 files changed, 73 insertions, 2 deletions
diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh
index 82d3dd96e88bb..487fcd93641b8 100755
--- a/lib/tests/modules.sh
+++ b/lib/tests/modules.sh
@@ -290,6 +290,8 @@ checkConfigOutput '^"a b"$' config.result ./functionTo/merging-list.nix
 checkConfigError 'A definition for option .fun.\[function body\]. is not of type .string.. Definition values:\n\s*- In .*wrong-type.nix' config.result ./functionTo/wrong-type.nix
 checkConfigOutput '^"b a"$' config.result ./functionTo/list-order.nix
 checkConfigOutput '^"a c"$' config.result ./functionTo/merging-attrs.nix
+checkConfigOutput '^"a bee"$' config.result ./functionTo/submodule-options.nix
+checkConfigOutput '^"fun.\[function body\].a fun.\[function body\].b"$' config.optionsResult ./functionTo/submodule-options.nix
 
 # moduleType
 checkConfigOutput '^"a b"$' config.resultFoo ./declare-variants.nix ./define-variant.nix
diff --git a/lib/tests/modules/functionTo/submodule-options.nix b/lib/tests/modules/functionTo/submodule-options.nix
new file mode 100644
index 0000000000000..b884892efd6aa
--- /dev/null
+++ b/lib/tests/modules/functionTo/submodule-options.nix
@@ -0,0 +1,61 @@
+{ lib, config, options, ... }:
+let
+  inherit (lib) types;
+in
+{
+  imports = [
+
+    # fun.<function-body>.a
+    ({ ... }: {
+      options = {
+        fun = lib.mkOption {
+          type = types.functionTo (types.submodule {
+            options.a = lib.mkOption { default = "a"; };
+          });
+        };
+      };
+    })
+
+    # fun.<function-body>.b
+    ({ ... }: {
+      options = {
+        fun = lib.mkOption {
+          type = types.functionTo (types.submodule {
+            options.b = lib.mkOption { default = "b"; };
+          });
+        };
+      };
+    })
+  ];
+
+  options = {
+    result = lib.mkOption
+      {
+        type = types.str;
+        default = lib.concatStringsSep " " (lib.attrValues (config.fun (throw "shouldn't use input param")));
+      };
+
+    optionsResult = lib.mkOption
+      {
+        type = types.str;
+        default = lib.concatStringsSep " "
+          (lib.concatLists
+            (lib.mapAttrsToList
+              (k: v:
+                if k == "_module"
+                then [ ]
+                else [ (lib.showOption v.loc) ]
+              )
+              (
+                (options.fun.type.getSubOptions [ "fun" ])
+              )
+            )
+          );
+      };
+  };
+
+  config.fun = lib.mkMerge
+    [
+      (input: { b = "bee"; })
+    ];
+}
diff --git a/lib/types.nix b/lib/types.nix
index e4b3f358d1c9a..2590d3e8710b3 100644
--- a/lib/types.nix
+++ b/lib/types.nix
@@ -526,9 +526,11 @@ rec {
       check = isFunction;
       merge = loc: defs:
         fnArgs: (mergeDefinitions (loc ++ [ "[function body]" ]) elemType (map (fn: { inherit (fn) file; value = fn.value fnArgs; }) defs)).mergedValue;
-      getSubOptions = elemType.getSubOptions;
+      getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "[function body]" ]);
       getSubModules = elemType.getSubModules;
       substSubModules = m: functionTo (elemType.substSubModules m);
+      functor = (defaultFunctor "functionTo") // { wrapped = elemType; };
+      nestedTypes.elemType = elemType;
     };
 
     # A submodule (like typed attribute set). See NixOS manual.
diff --git a/nixos/lib/make-options-doc/options-to-docbook.xsl b/nixos/lib/make-options-doc/options-to-docbook.xsl
index b286f7b5e2c0a..607db4bb21bae 100644
--- a/nixos/lib/make-options-doc/options-to-docbook.xsl
+++ b/nixos/lib/make-options-doc/options-to-docbook.xsl
@@ -20,7 +20,13 @@
       <title>Configuration Options</title>
       <variablelist xml:id="configuration-variable-list">
         <xsl:for-each select="attrs">
-          <xsl:variable name="id" select="concat('opt-', str:replace(str:replace(str:replace(str:replace(attr[@name = 'name']/string/@value, '*', '_'), '&lt;', '_'), '>', '_'), ':', '_'))" />
+          <xsl:variable name="id" select="
+            concat('opt-',
+              translate(
+                attr[@name = 'name']/string/@value,
+                '*&lt; >[]:',
+                '_______'
+            ))" />
           <varlistentry>
             <term xlink:href="#{$id}">
               <xsl:attribute name="xml:id"><xsl:value-of select="$id"/></xsl:attribute>