From be502ca92ed98936f4d4eade0f4942fffe0883da Mon Sep 17 00:00:00 2001 From: Michal Muskala Date: Mon, 14 Nov 2016 17:32:49 +0100 Subject: [PATCH] In case function has no docs, use the ones from callback --- lib/ex_doc/retriever.ex | 28 ++++++++++++++++++++-------- test/ex_doc/retriever_test.exs | 4 ++++ test/fixtures/behaviour.ex | 2 ++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/ex_doc/retriever.ex b/lib/ex_doc/retriever.ex index 3e2a2bacc..0ffa36d6b 100644 --- a/lib/ex_doc/retriever.ex +++ b/lib/ex_doc/retriever.ex @@ -236,14 +236,7 @@ defmodule ExDoc.Retriever do function = actual_def(name, arity, type) line = find_actual_line(module_info.abst_code, function, :function) || doc_line - behaviour = Map.get(module_info.impls, {name, arity}) - - doc = - if is_nil(doc) && behaviour do - "Callback implementation for `c:#{inspect behaviour}.#{name}/#{arity}`." - else - doc - end + doc = docstring(doc, name, arity, Map.fetch(module_info.impls, {name, arity})) specs = module_info.specs |> Map.get(function, []) @@ -272,6 +265,25 @@ defmodule ExDoc.Retriever do end end + defp docstring(nil, name, arity, {:ok, behaviour}) do + callback_docs = Code.get_docs(behaviour, :callback_docs) || [] + case List.keyfind(callback_docs, {name, arity}, 0) do + {{^name, ^arity}, _, :callback, callback_docs} when is_binary(callback_docs) -> + [header, body] = String.split(callback_docs, "\n", parts: 2) + info = "Documentation for callback `c:#{inspect behaviour}.#{name}/#{arity}`." + "#{header}\n\n#{info}\n\n#{trim_leading_newlines(body)}" + _ -> + "Callback implementation for `c:#{inspect behaviour}.#{name}/#{arity}`." + end + end + + defp docstring(doc, _name, _arity, _behaviour) do + doc + end + + defp trim_leading_newlines("\n" <> rest), do: trim_leading_newlines(rest) + defp trim_leading_newlines(rest), do: rest + defp get_callbacks(%{type: :behaviour, name: name, abst_code: abst_code}, source) do optional_callbacks = get_optional_callbacks(abst_code) (Code.get_docs(name, :callback_docs) || []) diff --git a/test/ex_doc/retriever_test.exs b/test/ex_doc/retriever_test.exs index 1e855904b..77bcac923 100644 --- a/test/ex_doc/retriever_test.exs +++ b/test/ex_doc/retriever_test.exs @@ -196,6 +196,10 @@ defmodule ExDoc.RetrieverTest do "A doc for this so it doesn't use 'Callback implementation for'" assert Enum.at(docs, 1).doc == "Callback implementation for `c:CustomBehaviourOne.greet/1`." + assert Enum.at(docs, 2).doc == + "This is a sample callback.\n\n" <> + "Documentation for callback `c:CustomBehaviourOne.hello/1`.\n\n" <> + "With description\n" end ## PROTOCOLS diff --git a/test/fixtures/behaviour.ex b/test/fixtures/behaviour.ex index 99d5be208..043a36e79 100644 --- a/test/fixtures/behaviour.ex +++ b/test/fixtures/behaviour.ex @@ -4,6 +4,8 @@ defmodule CustomBehaviourOne do @doc """ This is a sample callback. + + With description """ @callback hello(integer) :: integer @callback greet(integer | String.t) :: integer