Skip to content

Commit f16fb5a

Browse files
committed
Keep line information in defstruct
1 parent 08d844a commit f16fb5a

File tree

3 files changed

+18
-26
lines changed

3 files changed

+18
-26
lines changed

lib/elixir/lib/kernel.ex

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5468,33 +5468,21 @@ defmodule Kernel do
54685468
use `@type`.
54695469
"""
54705470
defmacro defstruct(fields) do
5471-
header =
5472-
quote bind_quoted: [fields: fields, bootstrapped?: bootstrapped?(Enum)] do
5473-
{struct, derive, escaped_struct, kv, body} =
5474-
Kernel.Utils.defstruct(__MODULE__, fields, bootstrapped?, __ENV__)
5475-
5476-
case derive do
5477-
[] -> :ok
5478-
_ -> Protocol.__derive__(derive, __MODULE__, __ENV__)
5479-
end
5480-
end
5471+
quote bind_quoted: [fields: fields, bootstrapped?: bootstrapped?(Enum)] do
5472+
{struct, derive, escaped_struct, kv, body} =
5473+
Kernel.Utils.defstruct(__MODULE__, fields, bootstrapped?, __ENV__)
54815474

5482-
# We attach the line: 0 to struct functions because we don't want
5483-
# the generated callbacks to count towards code coverage and metrics,
5484-
# especially since they are often expanded at compile-time.
5485-
functions =
5486-
quote line: 0, unquote: false do
5487-
def __struct__(), do: unquote(escaped_struct)
5488-
def __struct__(unquote(kv)), do: unquote(body)
5475+
case derive do
5476+
[] -> :ok
5477+
_ -> Protocol.__derive__(derive, __MODULE__, __ENV__)
54895478
end
54905479

5491-
footer =
5492-
quote do
5493-
Kernel.Utils.announce_struct(__MODULE__)
5494-
struct
5495-
end
5480+
def __struct__(), do: unquote(escaped_struct)
5481+
def __struct__(unquote(kv)), do: unquote(body)
54965482

5497-
{:__block__, [], [header, functions, footer]}
5483+
Kernel.Utils.announce_struct(__MODULE__)
5484+
struct
5485+
end
54985486
end
54995487

55005488
@doc ~S"""

lib/elixir/lib/kernel/utils.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,14 +174,14 @@ defmodule Kernel.Utils do
174174
true ->
175175
case enforce_keys do
176176
[] ->
177-
quote do
177+
quote line: 0, generated: true do
178178
Enum.reduce(kv, unquote(escaped_struct), fn {key, val}, map ->
179179
%{map | key => val}
180180
end)
181181
end
182182

183183
_ ->
184-
quote do
184+
quote line: 0, generated: true do
185185
{map, keys} =
186186
Enum.reduce(kv, {unquote(escaped_struct), unquote(enforce_keys)}, fn
187187
{key, val}, {map, keys} ->
@@ -201,7 +201,7 @@ defmodule Kernel.Utils do
201201
end
202202

203203
false ->
204-
quote do
204+
quote line: 0, generated: true do
205205
:lists.foldl(
206206
fn {key, val}, acc -> %{acc | key => val} end,
207207
unquote(escaped_struct),

lib/elixir/test/elixir/kernel_test.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ defmodule KernelTest do
205205

206206
defmodule User do
207207
assert is_map(defstruct name: "john")
208+
# Ensure we keep the line information around.
209+
# It is important for debugging tools, ExDoc, etc.
210+
{:v1, :def, anno, _clauses} = Module.get_definition(__MODULE__, {:__struct__, 1})
211+
anno[:line] == __ENV__.line - 4
208212
end
209213

210214
test "struct/1 and struct/2" do

0 commit comments

Comments
 (0)