diff options
author | Thomas Strobel <ts468@cam.ac.uk> | 2016-02-20 01:47:01 +0100 |
---|---|---|
committer | Thomas Strobel <ts468@cam.ac.uk> | 2016-02-29 01:09:00 +0100 |
commit | cad8957eabcbf73062226d28366fd446c15c8737 (patch) | |
tree | 0299e96391c14f612e7bd1cf3b2274198425fd61 /nixos/lib | |
parent | c483224c82c8e94324c03576e64c5dfbf16bd2f8 (diff) |
Add the tool "nixos-typecheck" that can check an option declaration to:
- Enforce that an option declaration has a "defaultText" if and only if the
type of the option derives from "package", "packageSet" or "nixpkgsConfig"
and if a "default" attribute is defined.
- Enforce that the value of the "example" attribute is wrapped with "literalExample"
if the type of the option derives from "package", "packageSet" or "nixpkgsConfig".
- Warn if a "defaultText" is defined in an option declaration if the type of
the option does not derive from "package", "packageSet" or "nixpkgsConfig".
- Warn if no "type" is defined in an option declaration.
Diffstat (limited to 'nixos/lib')
-rw-r--r-- | nixos/lib/eval-config.nix | 15 | ||||
-rw-r--r-- | nixos/lib/typechecker.nix | 91 |
2 files changed, 103 insertions, 3 deletions
diff --git a/nixos/lib/eval-config.nix b/nixos/lib/eval-config.nix index a87b285c5b7b..79890e0add7d 100644 --- a/nixos/lib/eval-config.nix +++ b/nixos/lib/eval-config.nix @@ -20,8 +20,13 @@ , # !!! See comment about args in lib/modules.nix specialArgs ? {} , modules +, # Pass through a configuration of the internal modules declared + # in lib/modules.nix. + _module ? {} +, # !!! See comment about typeInference in lib/modules.nix + typeInference ? null , # !!! See comment about check in lib/modules.nix - check ? true + check ? null , prefix ? [] , lib ? import ../../lib }: @@ -41,13 +46,17 @@ let }; }; + internalModule = { _module = (_module + // (if isNull check then {} else { inherit check; }) + // (if isNull typeInference then {} else { inherit typeInference; })); }; + in rec { # Merge the option definitions in all modules, forming the full # system configuration. inherit (lib.evalModules { - inherit prefix check; - modules = modules ++ extraModules ++ baseModules ++ [ pkgsModule ]; + inherit prefix; + modules = modules ++ extraModules ++ baseModules ++ [ pkgsModule ] ++ [ internalModule ]; args = extraArgs; specialArgs = { modulesPath = ../modules; } // specialArgs; }) config options; diff --git a/nixos/lib/typechecker.nix b/nixos/lib/typechecker.nix new file mode 100644 index 000000000000..b4d8277f8fe9 --- /dev/null +++ b/nixos/lib/typechecker.nix @@ -0,0 +1,91 @@ +{ config, lib, pkgs, baseModules, ... }: + +with pkgs; +with pkgs.lib; + +let + + optionsSpecs = inferenceMode: + let + versionModule = + { system.nixosVersionSuffix = config.system.nixosVersionSuffix; + system.nixosRevision = config.system.nixosRevision; + nixpkgs.system = config.nixpkgs.system; + }; + + internalModule = { _module = config._module; } // (if isNull inferenceMode then {} else { _module.typeInference = mkForce inferenceMode; }); + + eval = evalModules { + modules = [ versionModule ] ++ baseModules ++ [ internalModule ]; + args = (config._module.args) // { modules = [ ]; }; + }; + + # Remove invisible and internal options. + optionsSpecs' = filter (opt: opt.visible && !opt.internal) (optionAttrSetToParseableSpecifications config._module eval.options); + + # INFO: Please add 'defaultText' or 'literalExample' to the option + # definition to avoid this exception! + substFunction = key: decls: x: + if builtins.isAttrs x then mapAttrs (name: substFunction key decls) x + else if builtins.isList x then map (substFunction key decls) x + else if builtins.isFunction x then throw "Found an unexpected <function> in ${key} declared in ${concatStringsSep " and " decls}." + else x; + + prefix = toString ../..; + + stripPrefix = fn: + if substring 0 (stringLength prefix) fn == prefix then + substring (stringLength prefix + 1) 1000 fn + else + fn; + + # Clean up declaration sites to not refer to the NixOS source tree. + cleanupOptions = x: flip map x (opt: + let substFunction' = y: substFunction opt.name opt.declarations y; + in opt + // { declarations = map (fn: stripPrefix fn) opt.declarations; } + // optionalAttrs (opt ? example) { example = substFunction' opt.example; } + // optionalAttrs (opt ? default) { default = substFunction' opt.default; } + // optionalAttrs (opt ? type) { type = substFunction' opt.type; }); + + in + cleanupOptions optionsSpecs'; + +in + +{ + + system.build.typechecker = { + + # The NixOS options as machine readable specifications in JSON format. + specifications = stdenv.mkDerivation { + name = "options-specs-json"; + + buildCommand = '' + # Export list of options in different format. + dst=$out/share/doc/nixos + mkdir -p $dst + + cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON + (listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) (optionsSpecs null))))) + } $dst/options-specs.json + + mkdir -p $out/nix-support + echo "file json $dst/options-specs.json" >> $out/nix-support/hydra-build-products + ''; # */ + + meta.description = "List of NixOS options specifications in JSON format"; + }; + + silent = listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) (optionsSpecs "silent")); + printAll = listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) (optionsSpecs "printAll")); + printUnspecified = listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) (optionsSpecs "printUnspecified")); + + }; + +} + + + + + |