Skip to content

Commit 805a4dc

Browse files
committed
Add :default_group_for_doc
1 parent 208ecbb commit 805a4dc

File tree

10 files changed

+191
-108
lines changed

10 files changed

+191
-108
lines changed

lib/ex_doc/config.ex

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ defmodule ExDoc.Config do
33

44
# Defaults
55
@default_source_ref "main"
6+
def default_group_for_doc(metadata), do: metadata[:group]
67
def filter_modules(_module, _metadata), do: true
78
def before_closing_head_tag(_), do: ""
89
def before_closing_footer_tag(_), do: ""
@@ -21,6 +22,7 @@ defmodule ExDoc.Config do
2122
before_closing_head_tag: &__MODULE__.before_closing_head_tag/1,
2223
canonical: nil,
2324
cover: nil,
25+
default_group_for_doc: &__MODULE__.default_group_for_doc/1,
2426
deps: [],
2527
extra_section: nil,
2628
extras: [],
@@ -63,15 +65,16 @@ defmodule ExDoc.Config do
6365
before_closing_head_tag: (atom() -> String.t()) | mfa() | map(),
6466
canonical: nil | String.t(),
6567
cover: nil | Path.t(),
68+
default_group_for_doc: (keyword() -> String.t() | nil),
6669
deps: [{ebin_path :: String.t(), doc_url :: String.t()}],
6770
extra_section: nil | String.t(),
6871
extras: list(),
6972
filter_modules: (module, map -> boolean),
7073
formatter: nil | String.t(),
7174
formatters: [String.t()],
72-
groups_for_extras: keyword(),
73-
groups_for_docs: keyword((keyword() -> boolean)),
74-
groups_for_modules: keyword(),
75+
groups_for_extras: [{binary(), term()}],
76+
groups_for_docs: [{binary(), (keyword() -> boolean)}],
77+
groups_for_modules: [{binary(), term()}],
7578
homepage_url: nil | String.t(),
7679
language: String.t(),
7780
logo: nil | Path.t(),
@@ -96,7 +99,6 @@ defmodule ExDoc.Config do
9699
@spec build(String.t(), String.t(), Keyword.t()) :: ExDoc.Config.t()
97100
def build(project, vsn, options) do
98101
{output, options} = Keyword.pop(options, :output, "./doc")
99-
{groups_for_modules, options} = Keyword.pop(options, :groups_for_modules, [])
100102
{nest_modules_by_prefix, options} = Keyword.pop(options, :nest_modules_by_prefix, [])
101103
{proglang, options} = Keyword.pop(options, :proglang, :elixir)
102104
{filter_modules, options} = Keyword.pop(options, :filter_modules, &filter_modules/2)
@@ -109,6 +111,10 @@ defmodule ExDoc.Config do
109111
options
110112
end
111113

114+
{groups_for_docs, options} = Keyword.pop(options, :groups_for_docs, [])
115+
{groups_for_extras, options} = Keyword.pop(options, :groups_for_extras, [])
116+
{groups_for_modules, options} = Keyword.pop(options, :groups_for_modules, [])
117+
112118
{skip_undefined_reference_warnings_on, options} =
113119
Keyword.pop(
114120
options,
@@ -126,7 +132,13 @@ defmodule ExDoc.Config do
126132

127133
preconfig = %__MODULE__{
128134
filter_modules: normalize_filter_modules(filter_modules),
129-
groups_for_modules: normalize_groups_for_modules(groups_for_modules),
135+
groups_for_docs: normalize_groups(groups_for_docs),
136+
groups_for_extras: normalize_groups(groups_for_extras),
137+
groups_for_modules:
138+
normalize_groups(
139+
# TODO: The default module groups must be returned by the language
140+
groups_for_modules ++ [Deprecated: &deprecated?/1, Exceptions: &exception?/1]
141+
),
130142
homepage_url: options[:homepage_url],
131143
main: options[:main],
132144
nest_modules_by_prefix: normalize_nest_modules_by_prefix(nest_modules_by_prefix),
@@ -159,12 +171,8 @@ defmodule ExDoc.Config do
159171
raise ArgumentError, "#{inspect(proglang)} is not supported"
160172
end
161173

162-
# TODO: The default module groups must be returned by the language
163-
defp normalize_groups_for_modules(groups_for_modules) do
164-
default_groups = [Deprecated: &deprecated?/1, Exceptions: &exception?/1]
165-
166-
groups_for_modules ++
167-
Enum.reject(default_groups, fn {k, _} -> Keyword.has_key?(groups_for_modules, k) end)
174+
defp normalize_groups(groups) do
175+
for {k, v} <- groups, do: {to_string(k), v}
168176
end
169177

170178
defp deprecated?(metadata), do: metadata[:deprecated] != nil

lib/ex_doc/group_matcher.ex

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,14 @@ defmodule ExDoc.GroupMatcher do
3232
@doc """
3333
Finds a matching group for the given function.
3434
"""
35-
@spec match_doc(group_patterns, map) :: atom() | nil
36-
def match_doc(group_patterns, metadata) do
37-
match_group_patterns(group_patterns, fn pattern -> pattern.(metadata) end)
35+
def match_doc(group_patterns, callback, default, metadata) do
36+
match_group_patterns(group_patterns, fn pattern -> pattern.(metadata) end) ||
37+
callback.(metadata) || default
3838
end
3939

4040
@doc """
4141
Finds a matching group for the given module name, id, and metadata.
4242
"""
43-
@spec match_module(group_patterns, module, binary, map) :: atom() | nil
4443
def match_module(group_patterns, module, id, metadata) do
4544
match_group_patterns(group_patterns, fn pattern ->
4645
case pattern do
@@ -55,7 +54,6 @@ defmodule ExDoc.GroupMatcher do
5554
@doc """
5655
Finds a matching group for the given extra filename
5756
"""
58-
@spec match_extra(group_patterns, binary) :: atom() | nil
5957
def match_extra(group_patterns, filename) do
6058
match_group_patterns(group_patterns, fn pattern ->
6159
case pattern do

lib/ex_doc/language.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ defmodule ExDoc.Language do
4949
@doc """
5050
Returns a map with module information.
5151
"""
52-
@callback module_data(module(), tuple(), ExDoc.Config.t()) :: module_data() | :skip
52+
@callback module_data(module(), tuple(), ExDoc.Config.t()) :: module_data() | false
5353

5454
@doc """
55-
Returns a map with function information or an atom `:skip`.
55+
Returns a map with function information or `false`.
5656
5757
The map has the following keys:
5858
@@ -78,7 +78,7 @@ defmodule ExDoc.Language do
7878
doc_fallback: (... -> ExDoc.DocAST.t()) | nil,
7979
extra_annotations: [String.t()]
8080
}
81-
| :skip
81+
| false
8282

8383
@doc """
8484
Returns a map with callback information.

lib/ex_doc/language/elixir.ex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ defmodule ExDoc.Language.Elixir do
88

99
@impl true
1010
@spec module_data(atom, any, any) ::
11-
:skip
11+
false
1212
| %{
1313
callback_types: [:callback, ...],
1414
docs: any,
@@ -34,7 +34,7 @@ defmodule ExDoc.Language.Elixir do
3434

3535
cond do
3636
skip ->
37-
:skip
37+
false
3838

3939
abst_code = Source.get_abstract_code(module) ->
4040
title = module_title(module, type)
@@ -73,7 +73,7 @@ defmodule ExDoc.Language.Elixir do
7373
[]
7474
)
7575

76-
:skip
76+
false
7777
end
7878
end
7979

@@ -84,7 +84,7 @@ defmodule ExDoc.Language.Elixir do
8484
if doc?(entry, module_data.type) do
8585
function_data(kind, name, arity, anno, metadata, module_data)
8686
else
87-
:skip
87+
false
8888
end
8989
end
9090

@@ -282,7 +282,7 @@ defmodule ExDoc.Language.Elixir do
282282
{:local, :..}
283283

284284
["//", "", ""] ->
285-
{:local, :"..//"}
285+
{:local, :..//}
286286

287287
["", ""] ->
288288
{:local, :.}

lib/ex_doc/language/erlang.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ defmodule ExDoc.Language.Erlang do
88

99
@impl true
1010
@spec module_data(atom, any, any) ::
11-
:skip
11+
false
1212
| %{
1313
callback_types: [:callback, ...],
1414
docs: any,
@@ -54,7 +54,7 @@ defmodule ExDoc.Language.Erlang do
5454
}
5555
else
5656
ExDoc.Utils.warn("skipping docs for module #{inspect(module)}, reason: :no_debug_info", [])
57-
:skip
57+
false
5858
end
5959
end
6060

@@ -68,7 +68,7 @@ defmodule ExDoc.Language.Erlang do
6868
function_exported?(module_data.module, name, arity) do
6969
function_data(name, arity, doc_content, module_data, metadata)
7070
else
71-
:skip
71+
false
7272
end
7373
end
7474

lib/ex_doc/retriever.ex

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,18 @@ defmodule ExDoc.Retriever do
135135
{doc_line, doc_file, format, source_doc, doc, metadata} = get_module_docs(module_data, source)
136136

137137
# TODO: The default function groups must be returned by the language
138+
default_group = config.default_group_for_doc
138139
groups_for_docs = config.groups_for_docs
139140
annotations_for_docs = config.annotations_for_docs
140141

141142
docs_groups =
142-
Enum.uniq(Enum.map(groups_for_docs, &elem(&1, 0)) ++ [:Types, :Callbacks, :Functions])
143+
Enum.uniq(Enum.map(groups_for_docs, &elem(&1, 0)) ++ ~w(Types Callbacks Functions))
143144

144145
docs =
145-
get_docs(module_data, source, groups_for_docs, annotations_for_docs) ++
146-
get_callbacks(module_data, source, groups_for_docs, annotations_for_docs)
146+
get_docs(module_data, source, default_group, groups_for_docs, annotations_for_docs) ++
147+
get_callbacks(module_data, source, default_group, groups_for_docs, annotations_for_docs)
147148

148-
types = get_types(module_data, source, groups_for_docs, annotations_for_docs)
149+
types = get_types(module_data, source, default_group, groups_for_docs, annotations_for_docs)
149150

150151
metadata = Map.put(metadata, :kind, module_data.type)
151152
group = GroupMatcher.match_module(config.groups_for_modules, module, module_data.id, metadata)
@@ -195,42 +196,37 @@ defmodule ExDoc.Retriever do
195196

196197
## Function helpers
197198

198-
defp get_docs(module_data, source, groups_for_docs, annotations_for_docs) do
199-
{:docs_v1, _, _, _, _, _, doc_elements} = module_data.docs
199+
defp get_docs(module_data, source, default_group, groups_for_docs, annotations_for_docs) do
200+
{:docs_v1, _, _, _, _, _, docs} = module_data.docs
200201

201202
nodes =
202-
Enum.flat_map(doc_elements, fn doc_element ->
203-
case module_data.language.function_data(doc_element, module_data) do
204-
:skip ->
205-
[]
206-
207-
function_data ->
208-
[
209-
get_function(
210-
doc_element,
211-
function_data,
212-
source,
213-
module_data,
214-
groups_for_docs,
215-
annotations_for_docs
216-
)
217-
]
218-
end
219-
end)
203+
for doc <- docs,
204+
function_data = module_data.language.function_data(doc, module_data) do
205+
get_function(
206+
doc,
207+
function_data,
208+
module_data,
209+
source,
210+
default_group,
211+
groups_for_docs,
212+
annotations_for_docs
213+
)
214+
end
220215

221216
filter_defaults(nodes)
222217
end
223218

224219
defp get_function(
225-
doc_element,
220+
doc,
226221
function_data,
227-
source,
228222
module_data,
223+
source,
224+
default_group,
229225
groups_for_docs,
230226
annotations_for_docs
231227
) do
232228
{:docs_v1, _, _, content_type, _, module_metadata, _} = module_data.docs
233-
{{type, name, arity}, anno, signature, source_doc, metadata} = doc_element
229+
{{type, name, arity}, anno, signature, source_doc, metadata} = doc
234230
doc_file = anno_file(anno, source)
235231
doc_line = anno_line(anno)
236232

@@ -252,7 +248,7 @@ defmodule ExDoc.Retriever do
252248
(source_doc && doc_ast(content_type, source_doc, file: doc_file, line: doc_line + 1)) ||
253249
function_data.doc_fallback.()
254250

255-
group = GroupMatcher.match_doc(groups_for_docs, metadata) || :Functions
251+
group = GroupMatcher.match_doc(groups_for_docs, default_group, "Functions", metadata)
256252

257253
%ExDoc.FunctionNode{
258254
id: nil_or_name(name, arity),
@@ -296,23 +292,31 @@ defmodule ExDoc.Retriever do
296292
defp get_callbacks(
297293
%{type: :behaviour} = module_data,
298294
source,
295+
default_group,
299296
groups_for_docs,
300297
annotations_for_docs
301298
) do
302299
{:docs_v1, _, _, _, _, _, docs} = module_data.docs
303300

304301
for {{kind, _, _}, _, _, _, _} = doc <- docs, kind in module_data.callback_types do
305-
get_callback(doc, source, groups_for_docs, module_data, annotations_for_docs)
302+
get_callback(doc, module_data, source, default_group, groups_for_docs, annotations_for_docs)
306303
end
307304
end
308305

309-
defp get_callbacks(_, _, _, _), do: []
306+
defp get_callbacks(_, _, _, _, _), do: []
310307

311-
defp get_callback(callback, source, groups_for_docs, module_data, annotations_for_docs) do
312-
callback_data = module_data.language.callback_data(callback, module_data)
308+
defp get_callback(
309+
doc,
310+
module_data,
311+
source,
312+
default_group,
313+
groups_for_docs,
314+
annotations_for_docs
315+
) do
316+
callback_data = module_data.language.callback_data(doc, module_data)
313317

314318
{:docs_v1, _, _, content_type, _, module_metadata, _} = module_data.docs
315-
{{kind, name, arity}, anno, _signature, source_doc, metadata} = callback
319+
{{kind, name, arity}, anno, _signature, source_doc, metadata} = doc
316320
doc_file = anno_file(anno, source)
317321
doc_line = anno_line(anno)
318322

@@ -335,7 +339,7 @@ defmodule ExDoc.Retriever do
335339
doc_ast(content_type, source_doc, file: doc_file, line: doc_line + 1) ||
336340
doc_fallback(callback_data)
337341

338-
group = GroupMatcher.match_doc(groups_for_docs, metadata) || :Callbacks
342+
group = GroupMatcher.match_doc(groups_for_docs, default_group, "Callbacks", metadata)
339343

340344
%ExDoc.FunctionNode{
341345
id: "c:" <> nil_or_name(name, arity),
@@ -357,21 +361,21 @@ defmodule ExDoc.Retriever do
357361

358362
## Typespecs
359363

360-
defp get_types(module_data, source, groups_for_docs, annotations_for_docs) do
364+
defp get_types(module_data, source, default_group, groups_for_docs, annotations_for_docs) do
361365
{:docs_v1, _, _, _, _, _, docs} = module_data.docs
362366

363367
for {{:type, _, _}, _, _, content, _} = doc <- docs, content != :hidden do
364-
get_type(doc, source, groups_for_docs, module_data, annotations_for_docs)
368+
get_type(doc, module_data, source, default_group, groups_for_docs, annotations_for_docs)
365369
end
366370
end
367371

368-
defp get_type(type_entry, source, groups_for_docs, module_data, annotations_for_docs) do
372+
defp get_type(doc, module_data, source, default_group, groups_for_docs, annotations_for_docs) do
369373
{:docs_v1, _, _, content_type, _, module_metadata, _} = module_data.docs
370-
{{kind, name, arity}, anno, _signature, source_doc, metadata} = type_entry
374+
{{kind, name, arity}, anno, _signature, source_doc, metadata} = doc
371375
doc_file = anno_file(anno, source)
372376
doc_line = anno_line(anno)
373377

374-
type_data = module_data.language.type_data(type_entry, module_data)
378+
type_data = module_data.language.type_data(doc, module_data)
375379

376380
metadata =
377381
Map.merge(
@@ -392,7 +396,7 @@ defmodule ExDoc.Retriever do
392396
doc_ast(content_type, source_doc, file: doc_file, line: doc_line + 1) ||
393397
doc_fallback(type_data)
394398

395-
group = GroupMatcher.match_doc(groups_for_docs, metadata) || :Types
399+
group = GroupMatcher.match_doc(groups_for_docs, default_group, "Types", metadata)
396400

397401
%ExDoc.TypeNode{
398402
id: "t:" <> nil_or_name(name, arity),

0 commit comments

Comments
 (0)