Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 29 additions & 19 deletions lib/ex_doc/language/erlang.ex
Original file line number Diff line number Diff line change
Expand Up @@ -546,9 +546,14 @@ defmodule ExDoc.Language.Erlang do
{op, _, [int]}, acc when is_integer(int) and op in [:+, :-] ->
{nil, acc}

# fun() (spec_to_quoted expands it to (... -> any())
{:->, _, [[{name, _, _}], {:any, _, _}]}, acc when name == :... ->
{nil, acc}
# fun() (spec_to_quoted expands it to (... -> any() in Elixir v1.17 and earlier)
# TODO: Remove me when we require Elixir v1.18+
{:->, _, [[{name, _, _}], {:any, _, _}]} = node, acc when name == :... ->
if Version.match?(System.version(), ">= 1.18.0-rc") do
{node, acc}
else
{nil, acc}
end

# record{type :: remote:type/arity}
{:field_type, _, [name, {{:., _, [r_mod, r_type]}, _, args}]}, acc ->
Expand Down Expand Up @@ -588,7 +593,7 @@ defmodule ExDoc.Language.Erlang do
end
|> Enum.concat()

put(acc)
put_stack(acc)

# Drop and re-add type name (it, the first element in acc, is dropped there too)
#
Expand All @@ -614,16 +619,21 @@ defmodule ExDoc.Language.Erlang do
defp replace(formatted, acc, config) do
String.replace(formatted, Enum.map(acc, &"#{elem(&1, 0)}("), fn string ->
string = String.trim_trailing(string, "(")
{other, ref} = pop()

if string != other do
Autolink.maybe_warn(
config,
"internal inconsistency, please submit bug: #{inspect(string)} != #{inspect(other)}",
nil,
nil
)
end

ref =
case get_stack() do
[{^string, ref} | tail] ->
put_stack(tail)
ref

_ ->
Autolink.maybe_warn(
config,
"internal inconsistency when processing #{inspect(formatted)}",
nil,
nil
)
end

what =
case config.current_kfa do
Expand Down Expand Up @@ -691,16 +701,16 @@ defmodule ExDoc.Language.Erlang do
end)
end

defp put(items) do
defp put_stack(items) do
Process.put({__MODULE__, :stack}, items)
end

defp pop() do
[head | tail] = Process.get({__MODULE__, :stack})
put(tail)
head
defp get_stack() do
Process.get({__MODULE__, :stack})
end

defp pp(:fun), do: "fun"

defp pp(name) when is_atom(name) do
:io_lib.format("~p", [name]) |> IO.iodata_to_binary()
end
Expand Down
6 changes: 6 additions & 0 deletions test/ex_doc/language/erlang_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,12 @@ defmodule ExDoc.Language.ErlangTest do
test "function - any arity", c do
assert autolink_spec(~s"-spec foo() -> fun((...) -> t()) | erlang_bar:t().", c) ==
~s[foo() -> fun((...) -> <a href="#t:t/0">t</a>()) | <a href="erlang_bar.html#t:t/0">erlang_bar:t</a>().]

if Version.match?(System.version(), ">= 1.18.0-rc") do
assert autolink_spec(~s"-type foo() :: fun((...) -> any()) | [any()].", c) ==
"foo() :: fun((...) -> <a href=\"https://www.erlang.org/doc/apps/erts/erlang.html#t:any/0\">any</a>()) | " <>
"[<a href=\"https://www.erlang.org/doc/apps/erts/erlang.html#t:any/0\">any</a>()]."
end
end

test "local type", c do
Expand Down