diff --git a/lib/trivial.nix b/lib/trivial.nix index 5d4fad8266bc9..46cd35f883f30 100644 --- a/lib/trivial.nix +++ b/lib/trivial.nix @@ -442,6 +442,67 @@ rec { then f.__functionArgs or (lib.functionArgs (f.__functor f)) else builtins.functionArgs f; + getFunction = f: + if builtins.isFunction f then f + else if f ? __functor + then getFunction (f.__functor f) + else throw "getFunction: Not a function"; + + /* + functionInfo builtins.add -> + { + type = "builtin"; + } + + functionInfo (arg: arg + 1) -> + { + type = "argument"; + argumentName = "arg"; + } + + functionInfo (arg@{ a }: a + 1) -> + { + type = "attributes"; + argumentName = "arg"; + attributes = { a = false; }; + ellipsis = false; + } + functionInfo ({ a ? 0, ...}: a + 1) -> + { + type = "attributes"; + argumentName = null; + attributes = { a = true; }; + ellipsis = true; + } + */ + functionInfo = f: + let + function = getFunction f; + xmlString = builtins.toXML function; + builtinString = "\n\n \n\n"; + argumentRegex = "<\\?xml version='1.0' encoding='utf-8'\\?>\n\n \n \n \n\n"; + argumentMatch = builtins.match argumentRegex xmlString; + attributesRegex = "<\\?xml version='1.0' encoding='utf-8'\\?>\n\n \n .*\n \n \n\n"; + attributesMatch = builtins.match attributesRegex xmlString; + in + if builtinString == xmlString then { + type = "builtin"; + } + else if argumentMatch != null then { + type = "argument"; + argumentName = builtins.elemAt argumentMatch 0; + } + else if attributesMatch != null then { + type = "attributes"; + argumentName = + if builtins.elemAt attributesMatch 1 != null + then builtins.elemAt attributesMatch 2 + else null; + ellipsis = builtins.elemAt attributesMatch 0 != null; + attributes = builtins.functionArgs function; + } + else throw "functionInfo: Cannot parse builtins.toXML output (this is a bug): ${xmlString}"; + /* Check whether something is a function or something annotated with function args. */