Skip to content

Commit

Permalink
Propagate :since metadata from modules (#1680)
Browse files Browse the repository at this point in the history
  • Loading branch information
whatyouhide committed Mar 14, 2023
1 parent a55ffa2 commit e63e957
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ ExDoc supports metadata keys in your documentation.

In Elixir, you can add metadata to modules and functions.

For a module, use `@moduledoc`:
For a module, use `@moduledoc`, which is equivalent to adding the annotation to everything inside the module (functions, macros, callbacks, types):

```elixir
@moduledoc since: "1.10.0"
Expand Down
4 changes: 0 additions & 4 deletions assets/css/content/general.css
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,6 @@
font-weight: normal;
}

.content-inner h1 .note {
float: right;
}

.content-inner blockquote {
border-left: 3px solid var(--blockquoteBorder);
position: relative;
Expand Down
30 changes: 13 additions & 17 deletions lib/ex_doc/retriever.ex
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,13 @@ defmodule ExDoc.Retriever do
groups_for_docs,
annotations_for_docs
) do
{:docs_v1, _, _, content_type, _, _, _} = module_data.docs
{:docs_v1, _, _, content_type, _, module_metadata, _} = module_data.docs
{{type, name, arity}, anno, signature, doc_content, metadata} = doc_element
doc_line = anno_line(anno)

annotations =
annotations_for_docs.(metadata) ++
annotations_from_metadata(metadata) ++ function_data.extra_annotations
annotations_from_metadata(metadata, module_metadata) ++ function_data.extra_annotations

line = function_data.line || doc_line
defaults = get_defaults(name, arity, Map.get(metadata, :defaults, 0))
Expand Down Expand Up @@ -270,7 +270,7 @@ defmodule ExDoc.Retriever do
defp get_callback(callback, source, groups_for_docs, module_data, annotations_for_docs) do
callback_data = module_data.language.callback_data(callback, module_data)

{:docs_v1, _, _, content_type, _, _, _} = module_data.docs
{:docs_v1, _, _, content_type, _, module_metadata, _} = module_data.docs
{{kind, name, arity}, anno, _signature, doc, metadata} = callback
doc_line = anno_line(anno)

Expand All @@ -279,7 +279,7 @@ defmodule ExDoc.Retriever do

annotations =
annotations_for_docs.(metadata) ++
callback_data.extra_annotations ++ annotations_from_metadata(metadata)
callback_data.extra_annotations ++ annotations_from_metadata(metadata, module_metadata)

doc_ast = doc_ast(content_type, doc, file: source.path, line: doc_line + 1)

Expand Down Expand Up @@ -314,10 +314,10 @@ defmodule ExDoc.Retriever do
end

defp get_type(type_entry, source, module_data) do
{:docs_v1, _, _, content_type, _, _, _} = module_data.docs
{:docs_v1, _, _, content_type, _, module_metadata, _} = module_data.docs
{{_, name, arity}, anno, _signature, doc, metadata} = type_entry
doc_line = anno_line(anno)
annotations = annotations_from_metadata(metadata)
annotations = annotations_from_metadata(metadata, module_metadata)

type_data = module_data.language.type_data(type_entry, module_data)
signature = signature(type_data.signature)
Expand All @@ -344,17 +344,13 @@ defmodule ExDoc.Retriever do

defp signature(list) when is_list(list), do: Enum.join(list, " ")

defp annotations_from_metadata(metadata) do
annotations = []

annotations =
if since = metadata[:since] do
["since #{since}" | annotations]
else
annotations
end

annotations
defp annotations_from_metadata(metadata, module_metadata) do
# Give precedence to the function/callback/type metadata over the module metadata.
cond do
since = metadata[:since] -> ["since #{since}"]
since = module_metadata[:since] -> ["since #{since}"]
true -> []
end
end

defp anno_line(line) when is_integer(line), do: abs(line)
Expand Down
29 changes: 29 additions & 0 deletions test/ex_doc/retriever/elixir_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -391,5 +391,34 @@ defmodule ExDoc.Retriever.ElixirTest do
assert in_the_middle_2.defaults == []
assert in_the_middle_3.defaults == []
end

test "if @moduledoc has the :since attribute, it's applied to everything in the module", c do
elixirc(c, ~S"""
defmodule Mod do
@moduledoc since: "1.0.0"
@type t() :: :ok
def function(), do: :ok
defmacro macro(), do: :ok
@callback cb() :: :ok
end
""")

assert [%ExDoc.ModuleNode{} = mod] = Retriever.docs_from_modules([Mod], %ExDoc.Config{})

assert [%ExDoc.TypeNode{id: "t:t/0", annotations: ["since 1.0.0"]}] = mod.typespecs

assert %ExDoc.FunctionNode{annotations: ["since 1.0.0"]} =
Enum.find(mod.docs, &(&1.id == "c:cb/0"))

assert %ExDoc.FunctionNode{annotations: ["since 1.0.0"]} =
Enum.find(mod.docs, &(&1.id == "function/0"))

assert %ExDoc.FunctionNode{annotations: ["since 1.0.0", "macro"]} =
Enum.find(mod.docs, &(&1.id == "macro/0"))
end
end
end

0 comments on commit e63e957

Please sign in to comment.