From 9079b3a6b5af1ff33b149f36ffe1db7ce91844ba Mon Sep 17 00:00:00 2001 From: Wojtek Mach Date: Mon, 27 Nov 2017 00:43:37 +0100 Subject: [PATCH 1/6] Run code formatter on typespecs --- lib/ex_doc/formatter/html/autolink.ex | 92 +++++++++++++++----- test/ex_doc/formatter/html/autolink_test.exs | 21 +++++ 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/lib/ex_doc/formatter/html/autolink.ex b/lib/ex_doc/formatter/html/autolink.ex index 8f6dd972f..71de267a9 100644 --- a/lib/ex_doc/formatter/html/autolink.ex +++ b/lib/ex_doc/formatter/html/autolink.ex @@ -142,32 +142,78 @@ defmodule ExDoc.Formatter.HTML.Autolink do end defp typespec_to_string(ast, typespecs, aliases, lib_dirs) do - Macro.to_string(ast, fn - {name, _, args}, string when is_atom(name) and is_list(args) -> - arity = length(args) - if {name, arity} in typespecs do - n = enc_h("#{name}") - {string_to_link, string_with_parens} = split_string_to_link(string) - ~s[#{h(string_to_link)}#{string_with_parens}] - else - string - end - {{:., _, [alias, name]}, _, args}, string when is_atom(name) and is_list(args) -> - alias = expand_alias(alias) - if source = get_source(alias, aliases, lib_dirs) do - n = enc_h("#{name}") - {string_to_link, string_with_parens} = split_string_to_link(string) - ~s[#{h(string_to_link)}#{string_with_parens}] - else - string - end - _, string -> - string - end) + {ast, placeholders} = + Macro.prewalk(ast, %{}, fn + {name, _, args} = form, placeholders when is_atom(name) and is_list(args) -> + arity = length(args) + + if {name, arity} in typespecs do + string = Macro.to_string(form) + n = enc_h("#{name}") + {string_to_link, _string_with_parens} = split_string_to_link(string) + string = ~s[#{h(string_to_link)}] + + put_placeholder(form, string, placeholders) + else + {form, placeholders} + end + + {{:., _, [alias, name]}, _, args} = form, placeholders when is_atom(name) and is_list(args) -> + alias = expand_alias(alias) + + if source = get_source(alias, aliases, lib_dirs) do + string = Macro.to_string(form) + n = enc_h("#{name}") + {string_to_link, _string_with_parens} = split_string_to_link(string) + string = ~s[#{h(string_to_link)}] + + put_placeholder(form, string, placeholders) + else + {form, placeholders} + end + + form, placeholders -> + {form, placeholders} + end) + + ast + |> format_ast() + |> replace_placeholders(placeholders) + end + + defp put_placeholder(form, string, placeholders) do + id = zero_pad(map_size(placeholders), 3) + placeholder = :"_p#{id}_" + form = put_elem(form, 0, placeholder) + {form, Map.put(placeholders, Atom.to_string(placeholder), string)} + end + + defp zero_pad(val, count) do + num = Integer.to_string(val) + pad_length = max(count - byte_size(num), 0) + :binary.copy("0", pad_length) <> num + end + + defp replace_placeholders(string, placeholders) do + Regex.replace(~r"_p\d{3}_", string, &Map.fetch!(placeholders, &1)) + end + + @line_length 70 + + defp format_ast(ast) do + string = Macro.to_string(ast) + + if function_exported?(Code, :format_string!, 2) do + string + |> Code.format_string!(line_length: @line_length) + |> IO.iodata_to_binary() + else + string + end end defp short_typespec?(ast) do - byte_size(Macro.to_string(ast)) <= 70 + byte_size(Macro.to_string(ast)) <= @line_length end defp split_string_to_link(string) do diff --git a/test/ex_doc/formatter/html/autolink_test.exs b/test/ex_doc/formatter/html/autolink_test.exs index a4bdc2743..34527212b 100644 --- a/test/ex_doc/formatter/html/autolink_test.exs +++ b/test/ex_doc/formatter/html/autolink_test.exs @@ -240,6 +240,27 @@ defmodule ExDoc.Formatter.HTML.AutolinkTest do ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar |\n baz when bat: foo] end + test "complex types" do + ast = quote do + t() :: %{ + foo: term(), + really_long_name_that_will_trigger_multiple_line_breaks: String.t() + } + end + + if function_exported?(Code, :format_string!, 2) do + assert Autolink.typespec(ast, [], []) == String.trim(""" + t() :: %{ + foo: term(), + really_long_name_that_will_trigger_multiple_line_breaks: String.t() + } + """) + else + assert Autolink.typespec(ast, [], []) == + ~s[t() :: %{foo: term(), really_long_name_that_will_trigger_multiple_line_breaks: String.t()}] + end + end + test "autolink Elixir types in typespecs" do assert Autolink.typespec(quote(do: String.t), [], []) == ~s[String.t()] From 8b3cf70aa16e335a89ebc591250d1a4d6b937b61 Mon Sep 17 00:00:00 2001 From: Wojtek Mach Date: Thu, 30 Nov 2017 00:00:42 +0100 Subject: [PATCH 2/6] Make sure we do line breaks and not autolink `foo` in `foo :: term` --- lib/ex_doc/formatter/html/autolink.ex | 48 ++++++++++++++------ test/ex_doc/formatter/html/autolink_test.exs | 23 ++++++++-- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/lib/ex_doc/formatter/html/autolink.ex b/lib/ex_doc/formatter/html/autolink.ex index 71de267a9..4cf27674a 100644 --- a/lib/ex_doc/formatter/html/autolink.ex +++ b/lib/ex_doc/formatter/html/autolink.ex @@ -87,37 +87,49 @@ defmodule ExDoc.Formatter.HTML.Autolink do Converts the given `ast` to string while linking the locals given by `typespecs` as HTML. """ - def typespec(ast, typespecs, aliases, lib_dirs \\ elixir_lib_dirs()) + def typespec(ast, typespecs, aliases, lib_dirs \\ elixir_lib_dirs()) do + if formatter_available?() do + typespec_to_string(ast, typespecs, aliases, lib_dirs) + else + format_typespec(ast, typespecs, aliases, lib_dirs) + end + end - def typespec({:when, _, [{:::, _, [left, {:|, _, _} = center]}, right]} = ast, typespecs, aliases, lib_dirs) do + defp format_typespec({:when, _, [{:::, _, [left, {:|, _, _} = center]}, right]} = ast, typespecs, aliases, lib_dirs) do if short_typespec?(ast) do normalize_left(ast, typespecs, aliases, lib_dirs) else normalize_left(left, typespecs, aliases, lib_dirs) <> - " ::\n " <> typespec_with_new_line(center, typespecs, aliases, lib_dirs) <> + " ::\n " <> format_typespec_with_new_line(center, typespecs, aliases, lib_dirs) <> " when " <> String.slice(typespec_to_string(right, typespecs, aliases, lib_dirs), 1..-2) end end - def typespec({:::, _, [left, {:|, _, _} = center]} = ast, typespecs, aliases, lib_dirs) do + defp format_typespec({:::, _, [left, {:|, _, _} = center]} = ast, typespecs, aliases, lib_dirs) do if short_typespec?(ast) do normalize_left(ast, typespecs, aliases, lib_dirs) else normalize_left(left, typespecs, aliases, lib_dirs) <> - " ::\n " <> typespec_with_new_line(center, typespecs, aliases, lib_dirs) + " ::\n " <> format_typespec_with_new_line(center, typespecs, aliases, lib_dirs) end end - def typespec(other, typespecs, aliases, lib_dirs) do + defp format_typespec(other, typespecs, aliases, lib_dirs) do normalize_left(other, typespecs, aliases, lib_dirs) end - defp typespec_with_new_line({:|, _, [left, right]}, typespecs, aliases, lib_dirs) do + @line_length 70 + + defp short_typespec?(ast) do + byte_size(Macro.to_string(ast)) <= @line_length + end + + defp format_typespec_with_new_line({:|, _, [left, right]}, typespecs, aliases, lib_dirs) do typespec_to_string(left, typespecs, aliases, lib_dirs) <> - " |\n " <> typespec_with_new_line(right, typespecs, aliases, lib_dirs) + " |\n " <> format_typespec_with_new_line(right, typespecs, aliases, lib_dirs) end - defp typespec_with_new_line(other, typespecs, aliases, lib_dirs) do + defp format_typespec_with_new_line(other, typespecs, aliases, lib_dirs) do typespec_to_string(other, typespecs, aliases, lib_dirs) end @@ -142,8 +154,17 @@ defmodule ExDoc.Formatter.HTML.Autolink do end defp typespec_to_string(ast, typespecs, aliases, lib_dirs) do + ref = make_ref() + {ast, placeholders} = Macro.prewalk(ast, %{}, fn + {:::, _, [{name, meta, args}, right]}, placeholders when is_atom(name) and is_list(args) -> + {{:::, [], [{{ref, name}, meta, args}, right]}, placeholders} + + # Consume this form so that we don't autolink `foo` in `foo :: bar` + {{^ref, name}, _, args}, placeholders when is_atom(name) and is_list(args) -> + {{name, [], args}, placeholders} + {name, _, args} = form, placeholders when is_atom(name) and is_list(args) -> arity = length(args) @@ -198,12 +219,10 @@ defmodule ExDoc.Formatter.HTML.Autolink do Regex.replace(~r"_p\d{3}_", string, &Map.fetch!(placeholders, &1)) end - @line_length 70 - defp format_ast(ast) do string = Macro.to_string(ast) - if function_exported?(Code, :format_string!, 2) do + if formatter_available?() do string |> Code.format_string!(line_length: @line_length) |> IO.iodata_to_binary() @@ -212,8 +231,9 @@ defmodule ExDoc.Formatter.HTML.Autolink do end end - defp short_typespec?(ast) do - byte_size(Macro.to_string(ast)) <= @line_length + # TODO: remove when we require Elixir v1.6+ + defp formatter_available? do + function_exported?(Code, :format_string!, 2) end defp split_string_to_link(string) do diff --git a/test/ex_doc/formatter/html/autolink_test.exs b/test/ex_doc/formatter/html/autolink_test.exs index 34527212b..5b9ede9f1 100644 --- a/test/ex_doc/formatter/html/autolink_test.exs +++ b/test/ex_doc/formatter/html/autolink_test.exs @@ -233,11 +233,20 @@ defmodule ExDoc.Formatter.HTML.AutolinkTest do assert Autolink.typespec(quote(do: (foo(1) :: bar | baz when bat: foo)), [], []) == ~s[foo(1) :: bar | baz when bat: foo] - assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz)), [], []) == - ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar |\n baz] + if formatter_available?() do + assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz)), [], []) == + ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz] + + assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz when bat: foo)), [], []) == + ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz\nwhen bat: foo] + else + assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz)), [], []) == + ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar |\n baz] + + assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz when bat: foo)), [], []) == + ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar |\n baz when bat: foo] + end - assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz when bat: foo)), [], []) == - ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar |\n baz when bat: foo] end test "complex types" do @@ -248,7 +257,7 @@ defmodule ExDoc.Formatter.HTML.AutolinkTest do } end - if function_exported?(Code, :format_string!, 2) do + if formatter_available?() do assert Autolink.typespec(ast, [], []) == String.trim(""" t() :: %{ foo: term(), @@ -296,4 +305,8 @@ defmodule ExDoc.Formatter.HTML.AutolinkTest do assert Autolink.typespec(quote(do: parameterized_t(foo())), [foo: 0], []) == ~s[parameterized_t(foo())] end + + defp formatter_available? do + function_exported?(Code, :format_string!, 2) + end end From f749b75446678d27997c1f899606ea2effcddc0b Mon Sep 17 00:00:00 2001 From: Wojtek Mach Date: Thu, 30 Nov 2017 09:36:00 +0100 Subject: [PATCH 3/6] Use tags to control formatter tests --- test/ex_doc/formatter/html/autolink_test.exs | 60 +++++++++++--------- test/test_helper.exs | 4 +- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/test/ex_doc/formatter/html/autolink_test.exs b/test/ex_doc/formatter/html/autolink_test.exs index 5b9ede9f1..4c9a91d84 100644 --- a/test/ex_doc/formatter/html/autolink_test.exs +++ b/test/ex_doc/formatter/html/autolink_test.exs @@ -232,24 +232,28 @@ defmodule ExDoc.Formatter.HTML.AutolinkTest do assert Autolink.typespec(quote(do: (foo(1) :: bar | baz when bat: foo)), [], []) == ~s[foo(1) :: bar | baz when bat: foo] + end - if formatter_available?() do - assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz)), [], []) == - ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz] + @tag :formatter + test "add new lines on | with formatter" do + assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz)), [], []) == + ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz] - assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz when bat: foo)), [], []) == - ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz\nwhen bat: foo] - else - assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz)), [], []) == - ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar |\n baz] + assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz when bat: foo)), [], []) == + ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz\nwhen bat: foo] + end - assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz when bat: foo)), [], []) == - ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar |\n baz when bat: foo] - end + @tag :no_formatter + test "add new lines on | without formatter" do + assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz)), [], []) == + ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar |\n baz] + assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz when bat: foo)), [], []) == + ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar |\n baz when bat: foo] end - test "complex types" do + @tag :formatter + test "complex types with formatter" do ast = quote do t() :: %{ foo: term(), @@ -257,17 +261,25 @@ defmodule ExDoc.Formatter.HTML.AutolinkTest do } end - if formatter_available?() do - assert Autolink.typespec(ast, [], []) == String.trim(""" - t() :: %{ - foo: term(), - really_long_name_that_will_trigger_multiple_line_breaks: String.t() - } - """) - else - assert Autolink.typespec(ast, [], []) == - ~s[t() :: %{foo: term(), really_long_name_that_will_trigger_multiple_line_breaks: String.t()}] + assert Autolink.typespec(ast, [], []) == String.trim(""" + t() :: %{ + foo: term(), + really_long_name_that_will_trigger_multiple_line_breaks: String.t() + } + """) + end + + @tag :no_formatter + test "complex types without formatter" do + ast = quote do + t() :: %{ + foo: term(), + really_long_name_that_will_trigger_multiple_line_breaks: String.t() + } end + + assert Autolink.typespec(ast, [], []) == + ~s[t() :: %{foo: term(), really_long_name_that_will_trigger_multiple_line_breaks: String.t()}] end test "autolink Elixir types in typespecs" do @@ -305,8 +317,4 @@ defmodule ExDoc.Formatter.HTML.AutolinkTest do assert Autolink.typespec(quote(do: parameterized_t(foo())), [foo: 0], []) == ~s[parameterized_t(foo())] end - - defp formatter_available? do - function_exported?(Code, :format_string!, 2) - end end diff --git a/test/test_helper.exs b/test/test_helper.exs index 320a6ec42..6568254b4 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,6 +1,8 @@ exclude = [ cmark: !ExDoc.Markdown.Cmark.available?, - earmark: !ExDoc.Markdown.Earmark.available? + earmark: !ExDoc.Markdown.Earmark.available?, + formatter: !function_exported?(Code, :format_string!, 2), + no_formatter: function_exported?(Code, :format_string!, 2) ] ExUnit.start(exclude: Enum.filter(exclude, &elem(&1, 1))) From 74636e09d6cf9ed774ce40ddf3f2e0ff80154635 Mon Sep 17 00:00:00 2001 From: Wojtek Mach Date: Thu, 30 Nov 2017 14:05:54 +0100 Subject: [PATCH 4/6] Remove zero_pad --- lib/ex_doc/formatter/html/autolink.ex | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/ex_doc/formatter/html/autolink.ex b/lib/ex_doc/formatter/html/autolink.ex index 4cf27674a..d5afec959 100644 --- a/lib/ex_doc/formatter/html/autolink.ex +++ b/lib/ex_doc/formatter/html/autolink.ex @@ -203,20 +203,14 @@ defmodule ExDoc.Formatter.HTML.Autolink do end defp put_placeholder(form, string, placeholders) do - id = zero_pad(map_size(placeholders), 3) + id = map_size(placeholders) placeholder = :"_p#{id}_" form = put_elem(form, 0, placeholder) {form, Map.put(placeholders, Atom.to_string(placeholder), string)} end - defp zero_pad(val, count) do - num = Integer.to_string(val) - pad_length = max(count - byte_size(num), 0) - :binary.copy("0", pad_length) <> num - end - defp replace_placeholders(string, placeholders) do - Regex.replace(~r"_p\d{3}_", string, &Map.fetch!(placeholders, &1)) + Regex.replace(~r"_p\d+_", string, &Map.fetch!(placeholders, &1)) end defp format_ast(ast) do From 1731ddf7d4e9de325d8f02c84b3b7d1bd721f88d Mon Sep 17 00:00:00 2001 From: Wojtek Mach Date: Thu, 30 Nov 2017 14:10:23 +0100 Subject: [PATCH 5/6] Use line_length: 80 on formatter --- lib/ex_doc/formatter/html/autolink.ex | 6 ++---- test/ex_doc/formatter/html/autolink_test.exs | 8 ++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/ex_doc/formatter/html/autolink.ex b/lib/ex_doc/formatter/html/autolink.ex index d5afec959..ddd4f6e40 100644 --- a/lib/ex_doc/formatter/html/autolink.ex +++ b/lib/ex_doc/formatter/html/autolink.ex @@ -118,10 +118,8 @@ defmodule ExDoc.Formatter.HTML.Autolink do normalize_left(other, typespecs, aliases, lib_dirs) end - @line_length 70 - defp short_typespec?(ast) do - byte_size(Macro.to_string(ast)) <= @line_length + byte_size(Macro.to_string(ast)) <= 70 end defp format_typespec_with_new_line({:|, _, [left, right]}, typespecs, aliases, lib_dirs) do @@ -218,7 +216,7 @@ defmodule ExDoc.Formatter.HTML.Autolink do if formatter_available?() do string - |> Code.format_string!(line_length: @line_length) + |> Code.format_string!(line_length: 80) |> IO.iodata_to_binary() else string diff --git a/test/ex_doc/formatter/html/autolink_test.exs b/test/ex_doc/formatter/html/autolink_test.exs index 4c9a91d84..d1b2114ff 100644 --- a/test/ex_doc/formatter/html/autolink_test.exs +++ b/test/ex_doc/formatter/html/autolink_test.exs @@ -236,11 +236,11 @@ defmodule ExDoc.Formatter.HTML.AutolinkTest do @tag :formatter test "add new lines on | with formatter" do - assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz)), [], []) == - ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz] + assert Autolink.typespec(quote(do: (really_really_really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz)), [], []) == + ~s[really_really_really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz] - assert Autolink.typespec(quote(do: (really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz when bat: foo)), [], []) == - ~s[really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz\nwhen bat: foo] + assert Autolink.typespec(quote(do: (really_really_really_long_name_that_will_trigger_multiple_line_breaks(1) :: bar | baz when bat: foo)), [], []) == + ~s[really_really_really_long_name_that_will_trigger_multiple_line_breaks(1) ::\n bar | baz\nwhen bat: foo] end @tag :no_formatter From 381b625874f00e533a2d4f567ca2feb1e7cc170b Mon Sep 17 00:00:00 2001 From: Wojtek Mach Date: Thu, 30 Nov 2017 14:14:28 +0100 Subject: [PATCH 6/6] Swap names between format_typespec and typespec_to_string --- lib/ex_doc/formatter/html/autolink.ex | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/ex_doc/formatter/html/autolink.ex b/lib/ex_doc/formatter/html/autolink.ex index ddd4f6e40..0fc59b5d9 100644 --- a/lib/ex_doc/formatter/html/autolink.ex +++ b/lib/ex_doc/formatter/html/autolink.ex @@ -89,32 +89,32 @@ defmodule ExDoc.Formatter.HTML.Autolink do """ def typespec(ast, typespecs, aliases, lib_dirs \\ elixir_lib_dirs()) do if formatter_available?() do - typespec_to_string(ast, typespecs, aliases, lib_dirs) - else format_typespec(ast, typespecs, aliases, lib_dirs) + else + typespec_to_string(ast, typespecs, aliases, lib_dirs) end end - defp format_typespec({:when, _, [{:::, _, [left, {:|, _, _} = center]}, right]} = ast, typespecs, aliases, lib_dirs) do + defp typespec_to_string({:when, _, [{:::, _, [left, {:|, _, _} = center]}, right]} = ast, typespecs, aliases, lib_dirs) do if short_typespec?(ast) do normalize_left(ast, typespecs, aliases, lib_dirs) else normalize_left(left, typespecs, aliases, lib_dirs) <> - " ::\n " <> format_typespec_with_new_line(center, typespecs, aliases, lib_dirs) <> - " when " <> String.slice(typespec_to_string(right, typespecs, aliases, lib_dirs), 1..-2) + " ::\n " <> typespec_with_new_line(center, typespecs, aliases, lib_dirs) <> + " when " <> String.slice(format_typespec(right, typespecs, aliases, lib_dirs), 1..-2) end end - defp format_typespec({:::, _, [left, {:|, _, _} = center]} = ast, typespecs, aliases, lib_dirs) do + defp typespec_to_string({:::, _, [left, {:|, _, _} = center]} = ast, typespecs, aliases, lib_dirs) do if short_typespec?(ast) do normalize_left(ast, typespecs, aliases, lib_dirs) else normalize_left(left, typespecs, aliases, lib_dirs) <> - " ::\n " <> format_typespec_with_new_line(center, typespecs, aliases, lib_dirs) + " ::\n " <> typespec_with_new_line(center, typespecs, aliases, lib_dirs) end end - defp format_typespec(other, typespecs, aliases, lib_dirs) do + defp typespec_to_string(other, typespecs, aliases, lib_dirs) do normalize_left(other, typespecs, aliases, lib_dirs) end @@ -122,36 +122,36 @@ defmodule ExDoc.Formatter.HTML.Autolink do byte_size(Macro.to_string(ast)) <= 70 end - defp format_typespec_with_new_line({:|, _, [left, right]}, typespecs, aliases, lib_dirs) do - typespec_to_string(left, typespecs, aliases, lib_dirs) <> - " |\n " <> format_typespec_with_new_line(right, typespecs, aliases, lib_dirs) + defp typespec_with_new_line({:|, _, [left, right]}, typespecs, aliases, lib_dirs) do + format_typespec(left, typespecs, aliases, lib_dirs) <> + " |\n " <> typespec_with_new_line(right, typespecs, aliases, lib_dirs) end - defp format_typespec_with_new_line(other, typespecs, aliases, lib_dirs) do - typespec_to_string(other, typespecs, aliases, lib_dirs) + defp typespec_with_new_line(other, typespecs, aliases, lib_dirs) do + format_typespec(other, typespecs, aliases, lib_dirs) end defp normalize_left({:::, _, [{name, meta, args}, right]}, typespecs, aliases, lib_dirs) do new_args = - Enum.map(args, &[self(), typespec_to_string(&1, typespecs, aliases, lib_dirs)]) + Enum.map(args, &[self(), format_typespec(&1, typespecs, aliases, lib_dirs)]) new_left = Macro.to_string {name, meta, new_args}, fn [pid, string], _ when pid == self() -> string _, string -> string end - new_left <> " :: " <> typespec_to_string(right, typespecs, aliases, lib_dirs) + new_left <> " :: " <> format_typespec(right, typespecs, aliases, lib_dirs) end defp normalize_left({:when, _, [{:::, _, _} = left, right]}, typespecs, aliases, lib_dirs) do normalize_left(left, typespecs, aliases, lib_dirs) <> - " when " <> String.slice(typespec_to_string(right, typespecs, aliases, lib_dirs), 1..-2) + " when " <> String.slice(format_typespec(right, typespecs, aliases, lib_dirs), 1..-2) end defp normalize_left(ast, typespecs, aliases, lib_dirs) do - typespec_to_string(ast, typespecs, aliases, lib_dirs) + format_typespec(ast, typespecs, aliases, lib_dirs) end - defp typespec_to_string(ast, typespecs, aliases, lib_dirs) do + defp format_typespec(ast, typespecs, aliases, lib_dirs) do ref = make_ref() {ast, placeholders} =