diff options
author | Gabe Jackson <gj@mail.co.de> | 2018-09-28 02:41:23 -0400 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2018-09-28 08:41:23 +0200 |
commit | 97ac0e6a9f1b8dd4fd56fec4427bb8839b396f97 (patch) | |
tree | cd7a9b40d26fd1ac499fe2a58cb9617bab8f81d5 | |
parent | 3fcc9241db7b022a503851056f7bbac4f06c3ab7 (diff) | |
download | elixir-97ac0e6a9f1b8dd4fd56fec4427bb8839b396f97.tar.gz |
Link docs for defdelegate functions (#8228)
Add :delegate_to @doc metadata tag
to enable linking to delegatee's docs from delegator's docs
Associated issue: elixir-lang/ex_doc#902
-rw-r--r-- | lib/elixir/lib/io/ansi/docs.ex | 6 | ||||
-rw-r--r-- | lib/elixir/lib/kernel.ex | 2 | ||||
-rw-r--r-- | lib/elixir/lib/module.ex | 12 | ||||
-rw-r--r-- | lib/elixir/test/elixir/io/ansi/docs_test.exs | 17 | ||||
-rw-r--r-- | lib/iex/test/iex/helpers_test.exs | 28 |
5 files changed, 62 insertions, 3 deletions
diff --git a/lib/elixir/lib/io/ansi/docs.ex b/lib/elixir/lib/io/ansi/docs.ex index 230b86e59..69f287289 100644 --- a/lib/elixir/lib/io/ansi/docs.ex +++ b/lib/elixir/lib/io/ansi/docs.ex @@ -56,7 +56,7 @@ defmodule IO.ANSI.Docs do end @doc """ - Prints documentation metadata (only `since` and `deprecated` for now). + Prints documentation metadata (only `delegate_to`, `deprecated`, `guard`, and `since` for now). See `default_options/0` for docs on the supported options. """ @@ -78,6 +78,10 @@ defmodule IO.ANSI.Docs do {key, value}, _printed when is_boolean(value) and key in @metadata_filter -> IO.puts([metadata_label(key, options), ' ', to_string(value)]) + {:delegate_to, {m, f, a}}, _printed -> + label = metadata_label(:delegate_to, options) + IO.puts([label, ' ', Exception.format_mfa(m, f, a)]) + _metadata, printed -> printed end) diff --git a/lib/elixir/lib/kernel.ex b/lib/elixir/lib/kernel.ex index d3207dd73..e063bda79 100644 --- a/lib/elixir/lib/kernel.ex +++ b/lib/elixir/lib/kernel.ex @@ -5031,6 +5031,8 @@ defmodule Kernel do for fun <- List.wrap(funs) do {name, args, as, as_args} = Kernel.Utils.defdelegate(fun, opts) + @doc delegate_to: {target, as, :erlang.length(as_args)} + def unquote(name)(unquote_splicing(args)) do unquote(target).unquote(as)(unquote_splicing(as_args)) end diff --git a/lib/elixir/lib/module.ex b/lib/elixir/lib/module.ex index b8de65e0f..8c4a7636c 100644 --- a/lib/elixir/lib/module.ex +++ b/lib/elixir/lib/module.ex @@ -1950,6 +1950,18 @@ defmodule Module do "representing the replacement for the deprecated entity, got: #{inspect(value)}" end + defp validate_doc_meta(:delegate_to, value) do + case value do + {m, f, a} when is_atom(m) and is_atom(f) and is_integer(a) and a >= 0 -> + :ok + + _ -> + raise ArgumentError, + ":delegate_to is a built-in documentation metadata key. It should be a three-element " <> + "tuple in the form of {module, function, arity}, got: #{inspect(value)}" + end + end + defp validate_doc_meta(_, _), do: :ok defp get_doc_info(table, env) do diff --git a/lib/elixir/test/elixir/io/ansi/docs_test.exs b/lib/elixir/test/elixir/io/ansi/docs_test.exs index e4bf1a076..642370cf5 100644 --- a/lib/elixir/test/elixir/io/ansi/docs_test.exs +++ b/lib/elixir/test/elixir/io/ansi/docs_test.exs @@ -24,8 +24,21 @@ defmodule IO.ANSI.DocsTest do end test "metadata is formatted" do - result = format_metadata(%{since: "1.2.3", deprecated: "Use that other one", author: "Alice"}) - assert result == "\e[33mdeprecated:\e[0m Use that other one\n\e[33msince:\e[0m 1.2.3\n\n" + result = + format_metadata(%{ + since: "1.2.3", + deprecated: "Use that other one", + author: "Alice", + delegate_to: {Foo, :bar, 3} + }) + + assert result == """ + \e[33mdelegate_to:\e[0m Foo.bar/3 + \e[33mdeprecated:\e[0m Use that other one + \e[33msince:\e[0m 1.2.3 + + """ + assert format_metadata(%{author: "Alice"}) == "" end diff --git a/lib/iex/test/iex/helpers_test.exs b/lib/iex/test/iex/helpers_test.exs index 8c8bcc56f..28844a69b 100644 --- a/lib/iex/test/iex/helpers_test.exs +++ b/lib/iex/test/iex/helpers_test.exs @@ -519,6 +519,34 @@ defmodule IEx.HelpersTest do cleanup_modules([Impl, MyBehaviour]) end + test "prints documentation for delegates" do + filename = "delegate.ex" + + content = """ + defmodule Delegator do + defdelegate func1, to: Delegated + @doc "Delegator func2 doc" + defdelegate func2, to: Delegated + end + defmodule Delegated do + def func1, do: 1 + def func2, do: 2 + end + """ + + with_file(filename, content, fn -> + assert c(filename, ".") |> Enum.sort() == [Delegated, Delegator] + + assert capture_io(fn -> h(Delegator.func1()) end) == + "* def func1()\n\ndelegate_to: Delegated.func1/0\n\n\n" + + assert capture_io(fn -> h(Delegator.func2()) end) == + "* def func2()\n\ndelegate_to: Delegated.func2/0\n\nDelegator func2 doc\n" + end) + after + cleanup_modules([Delegated, Delegator]) + end + test "prints type documentation when function docs are not available" do content = """ defmodule MyTypes do |