forked from lix-project/lix
Add builtins.toStringDebug
Added `builtins.toStringDebug`, which formats a value as a string for
debugging purposes. Unlike `builtins.toString`, `builtins.toStringDebug`
will never error and will always produce human-readable, pretty-printed
output (including for expressions that error). This makes it ideal for
interpolation into `builtins.trace` calls and `assert` messages.
(cherry picked from commit 3af61fec55b1bf882d67cc81d874c76c555d058a)
Upstream-PR: https://github.com/NixOS/nix/pull/10206
Change-Id: I2c778d3dea3c797a2eda8a4be5cf0e944ab54225
This commit is contained in:
parent
76b45b4861
commit
ef4f59ea99
11
doc/manual/rl-next/to-string-debug.md
Normal file
11
doc/manual/rl-next/to-string-debug.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
synopsis: Add `builtins.toStringDebug`
|
||||
prs: 10206
|
||||
cls: 967
|
||||
---
|
||||
|
||||
Added `builtins.toStringDebug`, which formats a value as a string for debugging
|
||||
purposes. Unlike `builtins.toString`, `builtins.toStringDebug` will never error
|
||||
and will always produce human-readable, pretty-printed output (including for
|
||||
expressions that error). This makes it ideal for interpolation into
|
||||
`builtins.trace` calls and `assert` messages.
|
|
@ -9,6 +9,7 @@
|
|||
#include "json-to-value.hh"
|
||||
#include "names.hh"
|
||||
#include "path-references.hh"
|
||||
#include "print-options.hh"
|
||||
#include "store-api.hh"
|
||||
#include "util.hh"
|
||||
#include "value-to-json.hh"
|
||||
|
@ -979,7 +980,7 @@ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Valu
|
|||
if (args[0]->type() == nString)
|
||||
printError("trace: %1%", args[0]->string.s);
|
||||
else
|
||||
printError("trace: %1%", ValuePrinter(state, *args[0]));
|
||||
printError("trace: %1%", ValuePrinter(state, *args[0], debugPrintOptions));
|
||||
if (evalSettings.builtinsTraceDebugger && state.debugRepl && !state.debugTraces.empty()) {
|
||||
const DebugTrace & last = state.debugTraces.front();
|
||||
state.runDebugRepl(nullptr, last.env, last.expr);
|
||||
|
|
32
src/libexpr/primops/toStringDebug.cc
Normal file
32
src/libexpr/primops/toStringDebug.cc
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include "primops.hh"
|
||||
#include "print-options.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
static void prim_toStringDebug(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||
{
|
||||
v.mkString(printValue(state, *args[0], debugPrintOptions));
|
||||
}
|
||||
|
||||
static RegisterPrimOp primop_toStringDebug({
|
||||
.name = "toStringDebug",
|
||||
.args = {"value"},
|
||||
.doc = R"(
|
||||
Format a value as a string for debugging purposes.
|
||||
|
||||
Unlike [`toString`](@docroot@/language/builtins.md#builtins-toString),
|
||||
`toStringDebug` will never error and will always produce human-readable
|
||||
output (including for values that throw errors). For this reason,
|
||||
`toStringDebug` is ideal for interpolation into messages in
|
||||
[`trace`](@docroot@/language/builtins.md#builtins-trace)
|
||||
calls and [`assert`](@docroot@/language/constructs.html#assertions)
|
||||
statements.
|
||||
|
||||
Output will be pretty-printed and include ANSI escape sequences.
|
||||
If the value contains too many values (for instance, more than 32
|
||||
attributes or list items), some values will be elided.
|
||||
)",
|
||||
.fun = prim_toStringDebug,
|
||||
});
|
||||
|
||||
}
|
|
@ -117,4 +117,21 @@ static PrintOptions errorPrintOptions = PrintOptions {
|
|||
.maxStringLength = 1024,
|
||||
};
|
||||
|
||||
/**
|
||||
* `PrintOptions` for unknown and therefore potentially large values in
|
||||
* debugging contexts, to avoid printing "too much" output.
|
||||
*
|
||||
* This is like `errorPrintOptions`, but prints more values.
|
||||
*/
|
||||
static PrintOptions debugPrintOptions = PrintOptions {
|
||||
.ansiColors = true,
|
||||
.force = true,
|
||||
.derivationPaths = true,
|
||||
.maxDepth = 15,
|
||||
.maxAttrs = 32,
|
||||
.maxListItems = 32,
|
||||
.maxStringLength = 1024,
|
||||
.prettyIndent = 2
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -554,11 +554,24 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Print the given value to `output`.
|
||||
*/
|
||||
void printValue(EvalState & state, std::ostream & output, Value & v, PrintOptions options)
|
||||
{
|
||||
Printer(output, state, options).print(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the given value to a new string.
|
||||
*/
|
||||
std::string printValue(EvalState & state, Value & v, PrintOptions options)
|
||||
{
|
||||
std::ostringstream output;
|
||||
printValue(state, output, v, options);
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & output, const ValuePrinter & printer)
|
||||
{
|
||||
printValue(printer.state, output, printer.value, printer.options);
|
||||
|
|
|
@ -47,6 +47,8 @@ std::ostream & printIdentifier(std::ostream & o, std::string_view s);
|
|||
|
||||
void printValue(EvalState & state, std::ostream & str, Value & v, PrintOptions options = PrintOptions {});
|
||||
|
||||
std::string printValue(EvalState & state, Value & v, PrintOptions options = PrintOptions {});
|
||||
|
||||
/**
|
||||
* A partially-applied form of `printValue` which can be formatted using `<<`
|
||||
* without allocating an intermediate string.
|
||||
|
|
|
@ -28,10 +28,15 @@ expectStderr 1 nix-instantiate --show-trace --eval -E 'builtins.addErrorContext
|
|||
expectStderr 1 nix-instantiate --show-trace --eval -E 'builtins.addErrorContext "Hello %" (throw "Foo")' | grepQuiet 'Hello %'
|
||||
|
||||
nix-instantiate --eval -E 'let x = builtins.trace { x = x; } true; in x' \
|
||||
2>&1 | grepQuiet -E 'trace: { x = «potential infinite recursion»; }'
|
||||
2>&1 | grepQuiet -F "trace: {
|
||||
x = «potential infinite recursion»;
|
||||
}"
|
||||
|
||||
nix-instantiate --eval -E 'let x = { repeating = x; tracing = builtins.trace x true; }; in x.tracing'\
|
||||
2>&1 | grepQuiet -F 'trace: { repeating = «repeated»; tracing = «potential infinite recursion»; }'
|
||||
2>&1 | grepQuiet -F "trace: {
|
||||
repeating = «repeated»;
|
||||
tracing = «potential infinite recursion»;
|
||||
}"
|
||||
|
||||
set +x
|
||||
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
trace: [ «thunk» ]
|
||||
trace: [
|
||||
2
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue