Unverified Commit c0bf6b83 authored by nixpkgs-ci[bot]'s avatar nixpkgs-ci[bot] Committed by GitHub
Browse files

Merge master into staging-nixos

parents 3fcb49f1 eb3704a2
Loading
Loading
Loading
Loading
+43 −1
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ let
    concatMap
    concatStringsSep
    elem
    elemAt
    filter
    foldl'
    functionArgs
@@ -20,12 +21,14 @@ let
    head
    id
    imap1
    init
    isAttrs
    isBool
    isFunction
    oldestSupportedReleaseIsAtLeast
    isList
    isString
    last
    length
    mapAttrs
    mapAttrsToList
@@ -34,12 +37,16 @@ let
    optional
    optionalAttrs
    optionalString
    pipe
    recursiveUpdate
    remove
    reverseList
    sort
    sortOn
    seq
    setAttrByPath
    substring
    take
    throwIfNot
    trace
    typeOf
@@ -60,6 +67,8 @@ let
    ;
  inherit (lib.strings)
    isConvertibleWithToString
    levenshtein
    levenshteinAtMost
    ;

  showDeclPrefix =
@@ -304,8 +313,41 @@ let
                  addErrorContext
                    "while evaluating the error message for definitions for `${optText}', which is an option that does not exist"
                    (addErrorContext "while evaluating a definition from `${firstDef.file}'" (showDefs [ firstDef ]));

                # absInvalidOptionParent is absolute; other variables are relative to the submodule prefix
                absInvalidOptionParent = init (prefix ++ firstDef.prefix);
                invalidOptionParent = init firstDef.prefix;
                siblingOptionNames = attrNames (attrByPath invalidOptionParent { } options);
                candidateNames =
                  if invalidOptionParent == [ ] then remove "_module" siblingOptionNames else siblingOptionNames;
                invalidOptionName = last firstDef.prefix;
                # For small option sets, check all; for large sets, only check distance ≤ 2
                suggestions =
                  if length candidateNames < 100 then
                    pipe candidateNames [
                      (sortOn (levenshtein invalidOptionName))
                      (take 3)
                    ]
                  else
                    pipe candidateNames [
                      # levenshteinAtMost is only fast for distance ≤ 2
                      (filter (levenshteinAtMost 2 invalidOptionName))
                      (sortOn (levenshtein invalidOptionName))
                      (take 3)
                    ];
                suggestion =
                  if suggestions == [ ] then
                    ""
                  else if length suggestions == 1 then
                    "\n\nDid you mean `${showOption (absInvalidOptionParent ++ [ (head suggestions) ])}'?"
                  else
                    "\n\nDid you mean ${
                      concatStringsSep ", " (
                        map (s: "`${showOption (absInvalidOptionParent ++ [ s ])}'") (init suggestions)
                      )
                    } or `${showOption (absInvalidOptionParent ++ [ (last suggestions) ])}'?";
              in
              "The option `${optText}' does not exist. Definition values:${defText}";
              "The option `${optText}' does not exist. Definition values:${defText}${suggestion}";
          in
          if
            attrNames options == [ "_module" ]
+8 −0
Original line number Diff line number Diff line
@@ -870,6 +870,14 @@ checkConfigError 'A definition for option .* is not of type .*' config.addCheckF
checkConfigOutput '^true$' config.result ./v2-check-coherence.nix


# Option name suggestions
checkConfigError 'Did you mean .set\.enable.\?' config.set ./error-typo-nested.nix
checkConfigError 'Did you mean .set.\?' config ./error-typo-outside-with-nested.nix
checkConfigError 'Did you mean .bar., .baz. or .foo.\?' config ./error-typo-multiple-suggestions.nix
checkConfigError 'Did you mean .enable., .ebe. or .enabled.\?' config ./error-typo-large-attrset.nix
checkConfigError 'Did you mean .services\.myservice\.port. or .services\.myservice\.enable.\?' config.services.myservice ./error-typo-submodule.nix
checkConfigError 'Did you mean .services\.nginx\.virtualHosts\."example\.com"\.ssl\.certificate. or .services\.nginx\.virtualHosts\."example\.com"\.ssl\.certificateKey.\?' config.services.nginx.virtualHosts.\"example.com\" ./error-typo-deeply-nested.nix

cat <<EOF
====== module tests ======
$pass Pass
+42 −0
Original line number Diff line number Diff line
{ lib, ... }:

{
  options.services = {
    nginx = {
      enable = lib.mkOption {
        default = false;
        type = lib.types.bool;
      };
      virtualHosts = lib.mkOption {
        type = lib.types.attrsOf (
          lib.types.submodule {
            options = {
              enableSSL = lib.mkOption {
                default = false;
                type = lib.types.bool;
              };
              ssl = {
                certificate = lib.mkOption {
                  default = "";
                  type = lib.types.str;
                };
                certificateKey = lib.mkOption {
                  default = "";
                  type = lib.types.str;
                };
              };
            };
          }
        );
        default = { };
      };
    };
  };

  config = {
    services.nginx.virtualHosts."example.com" = {
      # Typo: "certficate" instead of "certificate" (nested within submodule)
      ssl.certficate = "/path/to/cert";
    };
  };
}
+56 −0
Original line number Diff line number Diff line
{ lib, ... }:

let
  inherit (lib) mkOption concatMapAttrs;

  ten = {
    a = null;
    b = null;
    c = null;
    d = null;
    e = null;
    f = null;
    g = null;
    h = null;
    i = null;
    j = null;
  };

  # Generate 1000 options (10 * 10 * 10)
  generatedOptions = concatMapAttrs (
    k1: _:
    concatMapAttrs (
      k2: _:
      concatMapAttrs (k3: _: {
        "${k1}${k2}${k3}" = mkOption {
          type = lib.types.bool;
          default = false;
        };
      }) ten
    ) ten
  ) ten;

  # Add some sensible options that are close to our typo
  sensibleOptions = {
    enable = mkOption {
      type = lib.types.bool;
      default = false;
    };
    enabled = mkOption {
      type = lib.types.bool;
      default = false;
    };
    disable = mkOption {
      type = lib.types.bool;
      default = false;
    };
  };
in
{
  options = generatedOptions // sensibleOptions;

  config = {
    # Typo: "enble" is distance 1 from "enable"
    enble = true;
  };
}
+22 −0
Original line number Diff line number Diff line
{ lib, ... }:

{
  options.foo = lib.mkOption {
    default = false;
    type = lib.types.bool;
  };

  options.bar = lib.mkOption {
    default = false;
    type = lib.types.bool;
  };

  options.baz = lib.mkOption {
    default = false;
    type = lib.types.bool;
  };

  config = {
    far = true;
  };
}
Loading