Skip to content

Commit e63e957

Browse files
authored
Propagate :since metadata from modules (#1680)
1 parent a55ffa2 commit e63e957

File tree

4 files changed

+43
-22
lines changed

4 files changed

+43
-22
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ ExDoc supports metadata keys in your documentation.
144144

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

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

149149
```elixir
150150
@moduledoc since: "1.10.0"

assets/css/content/general.css

-4
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,6 @@
9393
font-weight: normal;
9494
}
9595

96-
.content-inner h1 .note {
97-
float: right;
98-
}
99-
10096
.content-inner blockquote {
10197
border-left: 3px solid var(--blockquoteBorder);
10298
position: relative;

lib/ex_doc/retriever.ex

+13-17
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,13 @@ defmodule ExDoc.Retriever do
197197
groups_for_docs,
198198
annotations_for_docs
199199
) do
200-
{:docs_v1, _, _, content_type, _, _, _} = module_data.docs
200+
{:docs_v1, _, _, content_type, _, module_metadata, _} = module_data.docs
201201
{{type, name, arity}, anno, signature, doc_content, metadata} = doc_element
202202
doc_line = anno_line(anno)
203203

204204
annotations =
205205
annotations_for_docs.(metadata) ++
206-
annotations_from_metadata(metadata) ++ function_data.extra_annotations
206+
annotations_from_metadata(metadata, module_metadata) ++ function_data.extra_annotations
207207

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

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

@@ -279,7 +279,7 @@ defmodule ExDoc.Retriever do
279279

280280
annotations =
281281
annotations_for_docs.(metadata) ++
282-
callback_data.extra_annotations ++ annotations_from_metadata(metadata)
282+
callback_data.extra_annotations ++ annotations_from_metadata(metadata, module_metadata)
283283

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

@@ -314,10 +314,10 @@ defmodule ExDoc.Retriever do
314314
end
315315

316316
defp get_type(type_entry, source, module_data) do
317-
{:docs_v1, _, _, content_type, _, _, _} = module_data.docs
317+
{:docs_v1, _, _, content_type, _, module_metadata, _} = module_data.docs
318318
{{_, name, arity}, anno, _signature, doc, metadata} = type_entry
319319
doc_line = anno_line(anno)
320-
annotations = annotations_from_metadata(metadata)
320+
annotations = annotations_from_metadata(metadata, module_metadata)
321321

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

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

347-
defp annotations_from_metadata(metadata) do
348-
annotations = []
349-
350-
annotations =
351-
if since = metadata[:since] do
352-
["since #{since}" | annotations]
353-
else
354-
annotations
355-
end
356-
357-
annotations
347+
defp annotations_from_metadata(metadata, module_metadata) do
348+
# Give precedence to the function/callback/type metadata over the module metadata.
349+
cond do
350+
since = metadata[:since] -> ["since #{since}"]
351+
since = module_metadata[:since] -> ["since #{since}"]
352+
true -> []
353+
end
358354
end
359355

360356
defp anno_line(line) when is_integer(line), do: abs(line)

test/ex_doc/retriever/elixir_test.exs

+29
Original file line numberDiff line numberDiff line change
@@ -391,5 +391,34 @@ defmodule ExDoc.Retriever.ElixirTest do
391391
assert in_the_middle_2.defaults == []
392392
assert in_the_middle_3.defaults == []
393393
end
394+
395+
test "if @moduledoc has the :since attribute, it's applied to everything in the module", c do
396+
elixirc(c, ~S"""
397+
defmodule Mod do
398+
@moduledoc since: "1.0.0"
399+
400+
@type t() :: :ok
401+
402+
def function(), do: :ok
403+
404+
defmacro macro(), do: :ok
405+
406+
@callback cb() :: :ok
407+
end
408+
""")
409+
410+
assert [%ExDoc.ModuleNode{} = mod] = Retriever.docs_from_modules([Mod], %ExDoc.Config{})
411+
412+
assert [%ExDoc.TypeNode{id: "t:t/0", annotations: ["since 1.0.0"]}] = mod.typespecs
413+
414+
assert %ExDoc.FunctionNode{annotations: ["since 1.0.0"]} =
415+
Enum.find(mod.docs, &(&1.id == "c:cb/0"))
416+
417+
assert %ExDoc.FunctionNode{annotations: ["since 1.0.0"]} =
418+
Enum.find(mod.docs, &(&1.id == "function/0"))
419+
420+
assert %ExDoc.FunctionNode{annotations: ["since 1.0.0", "macro"]} =
421+
Enum.find(mod.docs, &(&1.id == "macro/0"))
422+
end
394423
end
395424
end

0 commit comments

Comments
 (0)