Skip to content

Commit 15f2f08

Browse files
authored
Fix typespec with (...) -> any() (#1980)
Closes #1974
1 parent 566e6f4 commit 15f2f08

File tree

2 files changed

+35
-19
lines changed

2 files changed

+35
-19
lines changed

lib/ex_doc/language/erlang.ex

+29-19
Original file line numberDiff line numberDiff line change
@@ -546,9 +546,14 @@ defmodule ExDoc.Language.Erlang do
546546
{op, _, [int]}, acc when is_integer(int) and op in [:+, :-] ->
547547
{nil, acc}
548548

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

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

591-
put(acc)
596+
put_stack(acc)
592597

593598
# Drop and re-add type name (it, the first element in acc, is dropped there too)
594599
#
@@ -614,16 +619,21 @@ defmodule ExDoc.Language.Erlang do
614619
defp replace(formatted, acc, config) do
615620
String.replace(formatted, Enum.map(acc, &"#{elem(&1, 0)}("), fn string ->
616621
string = String.trim_trailing(string, "(")
617-
{other, ref} = pop()
618-
619-
if string != other do
620-
Autolink.maybe_warn(
621-
config,
622-
"internal inconsistency, please submit bug: #{inspect(string)} != #{inspect(other)}",
623-
nil,
624-
nil
625-
)
626-
end
622+
623+
ref =
624+
case get_stack() do
625+
[{^string, ref} | tail] ->
626+
put_stack(tail)
627+
ref
628+
629+
_ ->
630+
Autolink.maybe_warn(
631+
config,
632+
"internal inconsistency when processing #{inspect(formatted)}",
633+
nil,
634+
nil
635+
)
636+
end
627637

628638
what =
629639
case config.current_kfa do
@@ -691,16 +701,16 @@ defmodule ExDoc.Language.Erlang do
691701
end)
692702
end
693703

694-
defp put(items) do
704+
defp put_stack(items) do
695705
Process.put({__MODULE__, :stack}, items)
696706
end
697707

698-
defp pop() do
699-
[head | tail] = Process.get({__MODULE__, :stack})
700-
put(tail)
701-
head
708+
defp get_stack() do
709+
Process.get({__MODULE__, :stack})
702710
end
703711

712+
defp pp(:fun), do: "fun"
713+
704714
defp pp(name) when is_atom(name) do
705715
:io_lib.format("~p", [name]) |> IO.iodata_to_binary()
706716
end

test/ex_doc/language/erlang_test.exs

+6
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,12 @@ defmodule ExDoc.Language.ErlangTest do
806806
test "function - any arity", c do
807807
assert autolink_spec(~s"-spec foo() -> fun((...) -> t()) | erlang_bar:t().", c) ==
808808
~s[foo() -> fun((...) -> <a href="#t:t/0">t</a>()) | <a href="erlang_bar.html#t:t/0">erlang_bar:t</a>().]
809+
810+
if Version.match?(System.version(), ">= 1.18.0-rc") do
811+
assert autolink_spec(~s"-type foo() :: fun((...) -> any()) | [any()].", c) ==
812+
"foo() :: fun((...) -> <a href=\"https://www.erlang.org/doc/apps/erts/erlang.html#t:any/0\">any</a>()) | " <>
813+
"[<a href=\"https://www.erlang.org/doc/apps/erts/erlang.html#t:any/0\">any</a>()]."
814+
end
809815
end
810816

811817
test "local type", c do

0 commit comments

Comments
 (0)