Skip to content

Conversation

@devonestes
Copy link
Contributor

This starts with an initial implementation of the blame/2 callback
for KeyError to add some helpful did_you_mean feedback for
potentially typo'd keys. Right now it's only implemented for maps and
keyword lists, and only for string and atom keys.

Resolves #7779

This starts with an initial implementation of the `blame/2` callback
for `KeyError` to add some helpful `did_you_mean` feedback for
potentially typo'd keys. Right now it's only implemented for maps and
keyword lists, and only for string and atom keys.
def message(%{message: message}), do: message

def message(key, term) do
msg = "key #{inspect(key)} not found"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nitpick: what do you think about using message instead of msg (like the function above) and distance instead of dist in the functions below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, works for me!

end

def blame(exception = %{term: term}, stacktrace) when is_list(term) do
available_keys = Keyword.keys(term)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately I think there is a bug here. Keyword.keys assumes a keyword is given. So if you do Keyword.fetch!([1, foo: :bar], :bar), it will invoke this clause which then fails on Keyword.keys. My suggestion is to unify both clauses above and do something like this:

if (is_map(term) or Keyword.keyword?(term)) and Enum.all?(term, fn {k, _} -> is_atom(k) end) do
  ...
else
  {message, stacktrace}
end

I know we can have mixed keys in maps, but I think we should start with a more conservative approach for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah - I didn't think it was possible for a non-keyword list to be passed as the term to a KeyError. I'll update.

@michalmuskala michalmuskala merged commit e07ccb1 into elixir-lang:master Jun 27, 2018
@michalmuskala
Copy link
Member

Thank you! ❤️

wojtekmach added a commit to wojtekmach/elixir that referenced this pull request Dec 27, 2018
It was introduced in elixir-lang#7803,
looks like it was accidentally made public (no docs, no specs)

It shipped in Elixir v1.7 so technically this would be a breaking
change. I'm happy to deprecate/doc false it instead.
josevalim pushed a commit that referenced this pull request Dec 27, 2018
It was introduced accidentally in #7803 (no docs, no specs)
josevalim pushed a commit that referenced this pull request Dec 29, 2018
It was introduced accidentally in #7803 (no docs, no specs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants