diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2022-03-11 12:02:26 +0100 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2022-03-11 12:02:26 +0100 |
commit | aee56e0f895e7b9890d1ec948b24c75478f9e88e (patch) | |
tree | b3d1f693cf8d068978c2f0f62abd4d4551d779b2 | |
parent | 31a392dfe2c89a3cb5880eea9e4070ece4e14acb (diff) | |
parent | f6078e474d5fc41c8a7f683865d60490bf0c7040 (diff) |
Merge remote-tracking branch 'origin/eval-suggestions'
-rw-r--r-- | src/libexpr/eval.cc | 45 | ||||
-rw-r--r-- | tests/suggestions.sh | 8 |
2 files changed, 48 insertions, 5 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 0207603c3..c65ef9738 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -729,9 +729,18 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const std::string & s2 throw EvalError(s, s2); } +LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const Suggestions & suggestions, const char * s, const std::string & s2)) +{ + throw EvalError(ErrorInfo { + .msg = hintfmt(s, s2), + .errPos = pos, + .suggestions = suggestions, + }); +} + LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const std::string & s2)) { - throw EvalError({ + throw EvalError(ErrorInfo { .msg = hintfmt(s, s2), .errPos = pos }); @@ -775,6 +784,16 @@ LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const }); } +LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const Suggestions & suggestions, const char * s, const ExprLambda & fun, const Symbol & s2)) +{ + throw TypeError(ErrorInfo { + .msg = hintfmt(s, fun.showNamePos(), s2), + .errPos = pos, + .suggestions = suggestions, + }); +} + + LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v)) { throw TypeError(s, showType(v)); @@ -1247,8 +1266,15 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) } } else { state.forceAttrs(*vAttrs, pos); - if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) - throwEvalError(pos, "attribute '%1%' missing", name); + if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) { + std::set<std::string> allAttrNames; + for (auto & attr : *vAttrs->attrs) + allAttrNames.insert(attr.name); + throwEvalError( + pos, + Suggestions::bestMatches(allAttrNames, name), + "attribute '%1%' missing", name); + } } vAttrs = j->value; pos2 = j->pos; @@ -1364,8 +1390,17 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & /* Nope, so show the first unexpected argument to the user. */ for (auto & i : *args[0]->attrs) - if (!lambda.formals->has(i.name)) - throwTypeError(pos, "%1% called with unexpected argument '%2%'", lambda, i.name); + if (!lambda.formals->has(i.name)) { + std::set<std::string> formalNames; + for (auto & formal : lambda.formals->formals) + formalNames.insert(formal.name); + throwTypeError( + pos, + Suggestions::bestMatches(formalNames, i.name), + "%1% called with unexpected argument '%2%'", + lambda, + i.name); + } abort(); // can't happen } } diff --git a/tests/suggestions.sh b/tests/suggestions.sh index 16a5a7004..f18fefef9 100644 --- a/tests/suggestions.sh +++ b/tests/suggestions.sh @@ -34,3 +34,11 @@ NIX_BUILD_STDERR_WITH_SUGGESTIONS=$(! nix build .\#fob 2>&1 1>/dev/null) NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION=$(! nix build .\#bar 2>&1 1>/dev/null) [[ ! "$NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION" =~ "Did you mean" ]] || \ fail "The nix build stderr shouldn’t suggest anything if there’s nothing relevant to suggest" + +NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '(builtins.getFlake (builtins.toPath ./.)).packages.'$system'.fob' 2>&1 1>/dev/null) +[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean one of fo1, fo2, foo or fooo?" ]] || \ + fail "The evaluator should suggest the three closest possiblities" + +NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '({ foo }: foo) { foo = 1; fob = 2; }' 2>&1 1>/dev/null) +[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean foo?" ]] || \ + fail "The evaluator should suggest the three closest possiblities" |