aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/eval.cc20
-rw-r--r--tests/suggestions.sh4
2 files changed, 22 insertions, 2 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 5bf161cc0..1d88e8709 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -727,6 +727,15 @@ 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({
+ .msg = hintfmt(s, s2),
+ .errPos = pos,
+ .suggestions = suggestions,
+ });
+}
+
LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s, const std::string & s2))
{
throw EvalError({
@@ -1281,8 +1290,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;
diff --git a/tests/suggestions.sh b/tests/suggestions.sh
index 16a5a7004..29d5b364b 100644
--- a/tests/suggestions.sh
+++ b/tests/suggestions.sh
@@ -34,3 +34,7 @@ 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"