forked from lix-project/lix
addErrorTrace
This commit is contained in:
parent
4d1a4f0217
commit
54e8f550c9
|
@ -592,19 +592,19 @@ LocalNoInlineNoReturn(void throwUndefinedVarError(const Pos & pos, const char *
|
|||
});
|
||||
}
|
||||
|
||||
LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2))
|
||||
LocalNoInline(void addErrorTrace(Error & e, const char * s, const string & s2))
|
||||
{
|
||||
e.addPrefix(format(s) % s2);
|
||||
e.addTrace(std::nullopt, hintfmt(s) % s2);
|
||||
}
|
||||
|
||||
LocalNoInline(void addErrorPrefix(Error & e, const char * s, const ExprLambda & fun, const Pos & pos))
|
||||
LocalNoInline(void addErrorTrace(Error & e, const Pos & pos, const char * s, const ExprLambda & fun))
|
||||
{
|
||||
e.addPrefix(format(s) % fun.showNamePos() % pos);
|
||||
e.addTrace(pos, hintfmt(s) % fun.showNamePos());
|
||||
}
|
||||
|
||||
LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2, const Pos & pos))
|
||||
LocalNoInline(void addErrorTrace(Error & e, const Pos & pos, const char * s, const string & s2))
|
||||
{
|
||||
e.addPrefix(format(s) % s2 % pos);
|
||||
e.addTrace(pos, hintfmt(s) % s2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -818,7 +818,7 @@ void EvalState::evalFile(const Path & path_, Value & v)
|
|||
try {
|
||||
eval(e, v);
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the file '%1%':\n", path2);
|
||||
addErrorTrace(e, "while evaluating the file '%1%':", path2);
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -1068,8 +1068,8 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
|||
|
||||
} catch (Error & e) {
|
||||
if (pos2 && pos2->file != state.sDerivationNix)
|
||||
addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n",
|
||||
showAttrPath(state, env, attrPath), *pos2);
|
||||
addErrorTrace(e, *pos2, "while evaluating the attribute '%1%'",
|
||||
showAttrPath(state, env, attrPath));
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -1241,7 +1241,9 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
|||
try {
|
||||
lambda.body->eval(*this, env2, v);
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating %1%, called from %2%:\n", lambda, pos);
|
||||
// TODO something different for 'called from' than usual addTrace?
|
||||
// addErrorTrace(e, pos, "while evaluating %1%, called from %2%:", lambda);
|
||||
addErrorTrace(e, pos, "while evaluating %1%:", lambda);
|
||||
throw;
|
||||
}
|
||||
else
|
||||
|
@ -1516,7 +1518,7 @@ void EvalState::forceValueDeep(Value & v)
|
|||
try {
|
||||
recurse(*i.value);
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the attribute '%1%' at %2%:\n", i.name, *i.pos);
|
||||
addErrorTrace(e, *i.pos, "while evaluating the attribute '%1%'", i.name);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -471,7 +471,8 @@ static void prim_addErrorContext(EvalState & state, const Pos & pos, Value * * a
|
|||
v = *args[1];
|
||||
} catch (Error & e) {
|
||||
PathSet context;
|
||||
e.addPrefix(format("%1%\n") % state.coerceToString(pos, *args[0], context));
|
||||
// TODO: is this right, include this pos?? Test it. esp with LOC.
|
||||
e.addTrace(pos, hintfmt("%1%") % state.coerceToString(pos, *args[0], context));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -563,7 +564,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
try {
|
||||
drvName = state.forceStringNoCtx(*attr->value, pos);
|
||||
} catch (Error & e) {
|
||||
e.addPrefix(fmt("while evaluating the derivation attribute 'name' at %1%:\n", posDrvName));
|
||||
e.addTrace(posDrvName, hintfmt("while evaluating the derivation attribute 'name'"));
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -696,8 +697,9 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
}
|
||||
|
||||
} catch (Error & e) {
|
||||
e.addPrefix(format("while evaluating the attribute '%1%' of the derivation '%2%' at %3%:\n")
|
||||
% key % drvName % posDrvName);
|
||||
e.addTrace(posDrvName,
|
||||
hintfmt("while evaluating the attribute '%1%' of the derivation '%2%'",
|
||||
key, drvName));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -323,11 +323,13 @@ int handleExceptions(const string & programName, std::function<void()> fun)
|
|||
printError("Try '%1% --help' for more information.", programName);
|
||||
return 1;
|
||||
} catch (BaseError & e) {
|
||||
if (settings.showTrace && e.prefix() != "")
|
||||
printError(e.prefix());
|
||||
// TODO showTrace as argument, or have calcWhat check settings?
|
||||
// if (settings.showTrace && e.prefix() != "")
|
||||
// printError(e.prefix());
|
||||
logError(e.info());
|
||||
if (e.prefix() != "" && !settings.showTrace)
|
||||
printError("(use '--show-trace' to show detailed location information)");
|
||||
// TODO fix to detect non-empty trace here.
|
||||
// if (e.prefix() != "" && !settings.showTrace)
|
||||
// printError("(use '--show-trace' to show detailed location information)");
|
||||
return e.status;
|
||||
} catch (std::bad_alloc & e) {
|
||||
printError(error + "out of memory");
|
||||
|
|
|
@ -12,20 +12,43 @@ const std::string nativeSystem = SYSTEM;
|
|||
|
||||
// addPrefix is used for show-trace. Strings added with addPrefix
|
||||
// will print ahead of the error itself.
|
||||
BaseError & BaseError::addPrefix(const FormatOrString & fs)
|
||||
{
|
||||
prefix_ = fs.s + prefix_;
|
||||
return *this;
|
||||
}
|
||||
// BaseError & BaseError::addPrefix(const FormatOrString & fs)
|
||||
// {
|
||||
// prefix_ = fs.s + prefix_;
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
// const string & prefix() const
|
||||
// {
|
||||
// // build prefix string on demand??
|
||||
|
||||
// }
|
||||
// ; // { return prefix_; }
|
||||
|
||||
|
||||
// addPrefix is used for show-trace. Strings added with addPrefix
|
||||
// will print ahead of the error itself.
|
||||
BaseError & BaseError::addTrace(hintformat hint, ErrPos e)
|
||||
BaseError & BaseError::addTrace(std::optional<ErrPos> e, hintformat hint)
|
||||
{
|
||||
err.traces.push_front(Trace { .pos = e, .hint = hint});
|
||||
return *this;
|
||||
}
|
||||
|
||||
// const string& BaseError::calcTrace() const
|
||||
// {
|
||||
// if (trace_.has_value())
|
||||
// return *trace_;
|
||||
// else {
|
||||
// err.name = sname();
|
||||
|
||||
// std::ostringstream oss;
|
||||
// oss << err;
|
||||
// trace_ = oss.str();
|
||||
|
||||
// return *trace_;
|
||||
// }
|
||||
// }
|
||||
|
||||
// c++ std::exception descendants must have a 'const char* what()' function.
|
||||
// This stringifies the error and caches it for use by what(), or similarly by msg().
|
||||
const string& BaseError::calcWhat() const
|
||||
|
@ -284,6 +307,22 @@ std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo)
|
|||
nl = true;
|
||||
}
|
||||
|
||||
// traces
|
||||
for (auto iter = einfo.traces.begin(); iter != einfo.traces.end(); ++iter)
|
||||
{
|
||||
|
||||
try {
|
||||
auto pos = *iter->pos;
|
||||
out << iter->hint.str() << showErrPos(pos) << std::endl;
|
||||
NixCode nc { .errPos = pos };
|
||||
getCodeLines(nc);
|
||||
printCodeLines(out, prefix, nc);
|
||||
} catch(const std::bad_optional_access& e) {
|
||||
out << iter->hint.str() << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// description
|
||||
if (einfo.description != "") {
|
||||
if (nl)
|
||||
|
|
|
@ -94,7 +94,7 @@ struct NixCode {
|
|||
};
|
||||
|
||||
struct Trace {
|
||||
ErrPos pos;
|
||||
std::optional<ErrPos> pos;
|
||||
hintformat hint;
|
||||
};
|
||||
|
||||
|
@ -116,9 +116,12 @@ std::ostream& operator<<(std::ostream &out, const ErrorInfo &einfo);
|
|||
class BaseError : public std::exception
|
||||
{
|
||||
protected:
|
||||
string prefix_; // used for location traces etc.
|
||||
// string prefix_; // used for location traces etc.
|
||||
mutable ErrorInfo err;
|
||||
|
||||
// mutable std::optional<string> trace_;
|
||||
// const string& calcTrace() const;
|
||||
|
||||
mutable std::optional<string> what_;
|
||||
const string& calcWhat() const;
|
||||
|
||||
|
@ -164,9 +167,9 @@ public:
|
|||
#endif
|
||||
|
||||
const string & msg() const { return calcWhat(); }
|
||||
const string & prefix() const { return prefix_; }
|
||||
BaseError & addPrefix(const FormatOrString & fs);
|
||||
BaseError & addTrace(ErrPos e, hintformat hint);
|
||||
// const string & trace() const { return calcTrace(); }
|
||||
// BaseError & addPrefix(const FormatOrString & fs);
|
||||
BaseError & addTrace(std::optional<ErrPos> e, hintformat hint);
|
||||
|
||||
const ErrorInfo & info() { calcWhat(); return err; }
|
||||
};
|
||||
|
|
|
@ -593,7 +593,7 @@ static void upgradeDerivations(Globals & globals,
|
|||
} else newElems.push_back(i);
|
||||
|
||||
} catch (Error & e) {
|
||||
e.addPrefix(fmt("while trying to find an upgrade for '%s':\n", i.queryName()));
|
||||
e.addTrace(std::nullopt, hintfmt("while trying to find an upgrade for '%s'", i.queryName()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -1185,7 +1185,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
|||
} catch (AssertionError & e) {
|
||||
printMsg(lvlTalkative, "skipping derivation named '%1%' which gives an assertion failure", i.queryName());
|
||||
} catch (Error & e) {
|
||||
e.addPrefix(fmt("while querying the derivation named '%1%':\n", i.queryName()));
|
||||
e.addTrace(std::nullopt, hintfmt("while querying the derivation named '%1%'", i.queryName()));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,12 +163,12 @@ static int listPossibleCallback(char *s, char ***avp) {
|
|||
}
|
||||
|
||||
namespace {
|
||||
// Used to communicate to NixRepl::getLine whether a signal occurred in ::readline.
|
||||
volatile sig_atomic_t g_signal_received = 0;
|
||||
// Used to communicate to NixRepl::getLine whether a signal occurred in ::readline.
|
||||
volatile sig_atomic_t g_signal_received = 0;
|
||||
|
||||
void sigintHandler(int signo) {
|
||||
void sigintHandler(int signo) {
|
||||
g_signal_received = signo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NixRepl::mainLoop(const std::vector<std::string> & files)
|
||||
|
@ -211,12 +211,14 @@ void NixRepl::mainLoop(const std::vector<std::string> & files)
|
|||
// input without clearing the input so far.
|
||||
continue;
|
||||
} else {
|
||||
printMsg(lvlError, error + "%1%%2%", (settings.showTrace ? e.prefix() : ""), e.msg());
|
||||
printMsg(lvlError, e.msg());
|
||||
}
|
||||
} catch (Error & e) {
|
||||
printMsg(lvlError, error + "%1%%2%", (settings.showTrace ? e.prefix() : ""), e.msg());
|
||||
// printMsg(lvlError, error + "%1%%2%", (settings.showTrace ? e.prefix() : ""), e.msg());
|
||||
printMsg(lvlError, e.msg());
|
||||
} catch (Interrupted & e) {
|
||||
printMsg(lvlError, error + "%1%%2%", (settings.showTrace ? e.prefix() : ""), e.msg());
|
||||
// printMsg(lvlError, error + "%1%%2%", (settings.showTrace ? e.prefix() : ""), e.msg());
|
||||
printMsg(lvlError, e.msg());
|
||||
}
|
||||
|
||||
// We handled the current input fully, so we should clear it
|
||||
|
|
|
@ -216,7 +216,7 @@ struct CmdSearch : SourceExprCommand, MixJSON
|
|||
} catch (AssertionError & e) {
|
||||
} catch (Error & e) {
|
||||
if (!toplevel) {
|
||||
e.addPrefix(fmt("While evaluating the attribute '%s':\n", attrPath));
|
||||
e.addTrace(std::nullopt, hintfmt("While evaluating the attribute '%s'", attrPath));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue