Warn if duplicate key is found in struct (#9452)
Warning is the preferable solution for this, if we raise instead then it is likely that there are some existing libraries that use duplicate struct keys that will break.
This commit is contained in:
committed by
Andrea Leopardi
parent
a570d919da
commit
6a8fa2c7ef
@@ -94,6 +94,9 @@ defmodule Kernel.Utils do
|
||||
fields = :lists.map(mapper, fields)
|
||||
enforce_keys = List.wrap(Module.get_attribute(module, :enforce_keys))
|
||||
|
||||
# TODO: Make it raise on v2.0
|
||||
warn_on_duplicate_struct_key(:lists.keysort(1, fields))
|
||||
|
||||
foreach = fn
|
||||
key when is_atom(key) ->
|
||||
:ok
|
||||
@@ -108,6 +111,19 @@ defmodule Kernel.Utils do
|
||||
{struct, enforce_keys, Module.get_attribute(module, :derive)}
|
||||
end
|
||||
|
||||
defp warn_on_duplicate_struct_key([]) do
|
||||
:ok
|
||||
end
|
||||
|
||||
defp warn_on_duplicate_struct_key([{key, _} | [{key, _} | _] = rest]) do
|
||||
IO.warn("duplicate key #{inspect(key)} found in struct")
|
||||
warn_on_duplicate_struct_key(rest)
|
||||
end
|
||||
|
||||
defp warn_on_duplicate_struct_key([_ | rest]) do
|
||||
warn_on_duplicate_struct_key(rest)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Announcing callback for defstruct.
|
||||
"""
|
||||
|
||||
@@ -1770,6 +1770,18 @@ defmodule Kernel.WarningTest do
|
||||
end
|
||||
end
|
||||
|
||||
test "defstruct warns with duplicate keys" do
|
||||
assert capture_err(fn ->
|
||||
Code.eval_string("""
|
||||
defmodule TestMod do
|
||||
defstruct [:foo, :foo, :bar]
|
||||
end
|
||||
""")
|
||||
end) =~ "duplicate key :foo found in struct"
|
||||
after
|
||||
purge(TestMod)
|
||||
end
|
||||
|
||||
defp purge(list) when is_list(list) do
|
||||
Enum.each(list, &purge/1)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user