Skip to content

Add :default_group_for_doc #1978

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 19 additions & 11 deletions lib/ex_doc/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ defmodule ExDoc.Config do

# Defaults
@default_source_ref "main"
def default_group_for_doc(metadata), do: metadata[:group]
def filter_modules(_module, _metadata), do: true
def before_closing_head_tag(_), do: ""
def before_closing_footer_tag(_), do: ""
Expand All @@ -21,6 +22,7 @@ defmodule ExDoc.Config do
before_closing_head_tag: &__MODULE__.before_closing_head_tag/1,
canonical: nil,
cover: nil,
default_group_for_doc: &__MODULE__.default_group_for_doc/1,
deps: [],
extra_section: nil,
extras: [],
Expand Down Expand Up @@ -63,15 +65,16 @@ defmodule ExDoc.Config do
before_closing_head_tag: (atom() -> String.t()) | mfa() | map(),
canonical: nil | String.t(),
cover: nil | Path.t(),
default_group_for_doc: (keyword() -> String.t() | nil),
deps: [{ebin_path :: String.t(), doc_url :: String.t()}],
extra_section: nil | String.t(),
extras: list(),
filter_modules: (module, map -> boolean),
formatter: nil | String.t(),
formatters: [String.t()],
groups_for_extras: keyword(),
groups_for_docs: keyword((keyword() -> boolean)),
groups_for_modules: keyword(),
groups_for_extras: [{binary(), term()}],
groups_for_docs: [{binary(), (keyword() -> boolean)}],
groups_for_modules: [{binary(), term()}],
homepage_url: nil | String.t(),
language: String.t(),
logo: nil | Path.t(),
Expand All @@ -96,7 +99,6 @@ defmodule ExDoc.Config do
@spec build(String.t(), String.t(), Keyword.t()) :: ExDoc.Config.t()
def build(project, vsn, options) do
{output, options} = Keyword.pop(options, :output, "./doc")
{groups_for_modules, options} = Keyword.pop(options, :groups_for_modules, [])
{nest_modules_by_prefix, options} = Keyword.pop(options, :nest_modules_by_prefix, [])
{proglang, options} = Keyword.pop(options, :proglang, :elixir)
{filter_modules, options} = Keyword.pop(options, :filter_modules, &filter_modules/2)
Expand All @@ -109,6 +111,10 @@ defmodule ExDoc.Config do
options
end

{groups_for_docs, options} = Keyword.pop(options, :groups_for_docs, [])
{groups_for_extras, options} = Keyword.pop(options, :groups_for_extras, [])
{groups_for_modules, options} = Keyword.pop(options, :groups_for_modules, [])

{skip_undefined_reference_warnings_on, options} =
Keyword.pop(
options,
Expand All @@ -126,7 +132,13 @@ defmodule ExDoc.Config do

preconfig = %__MODULE__{
filter_modules: normalize_filter_modules(filter_modules),
groups_for_modules: normalize_groups_for_modules(groups_for_modules),
groups_for_docs: normalize_groups(groups_for_docs),
groups_for_extras: normalize_groups(groups_for_extras),
groups_for_modules:
normalize_groups(
# TODO: The default module groups must be returned by the language
groups_for_modules ++ [Deprecated: &deprecated?/1, Exceptions: &exception?/1]
),
homepage_url: options[:homepage_url],
main: options[:main],
nest_modules_by_prefix: normalize_nest_modules_by_prefix(nest_modules_by_prefix),
Expand Down Expand Up @@ -159,12 +171,8 @@ defmodule ExDoc.Config do
raise ArgumentError, "#{inspect(proglang)} is not supported"
end

# TODO: The default module groups must be returned by the language
defp normalize_groups_for_modules(groups_for_modules) do
default_groups = [Deprecated: &deprecated?/1, Exceptions: &exception?/1]

groups_for_modules ++
Enum.reject(default_groups, fn {k, _} -> Keyword.has_key?(groups_for_modules, k) end)
defp normalize_groups(groups) do
for {k, v} <- groups, do: {to_string(k), v}
end

defp deprecated?(metadata), do: metadata[:deprecated] != nil
Expand Down
2 changes: 1 addition & 1 deletion lib/ex_doc/formatter/html.ex
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ defmodule ExDoc.Formatter.HTML do
if ids_count[extra.id] > 1, do: {disambiguate_id(extra, idx), idx + 1}, else: {extra, idx}
end)
|> elem(0)
|> Enum.sort_by(fn extra -> GroupMatcher.group_index(groups, extra.group) end)
|> Enum.sort_by(fn extra -> GroupMatcher.index(groups, extra.group) end)
end

def generate_redirects(config, ext) do
Expand Down
13 changes: 6 additions & 7 deletions lib/ex_doc/formatter/html/templates.ex
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,12 @@ defmodule ExDoc.Formatter.HTML.Templates do
end

def module_summary(module_node) do
entries = docs_groups(module_node.docs_groups, module_node.docs ++ module_node.typespecs)

Enum.reject(entries, fn {_type, nodes} -> nodes == [] end)
end

defp docs_groups(groups, docs) do
for group <- groups, do: {group, Enum.filter(docs, &(&1.group == group))}
# TODO: Maybe it should be moved to retriever and it already returned grouped metadata
ExDoc.GroupMatcher.group_by(
module_node.docs_groups,
module_node.docs ++ module_node.typespecs,
& &1.group
)
end

defp logo_path(%{logo: nil}), do: nil
Expand Down
27 changes: 21 additions & 6 deletions lib/ex_doc/group_matcher.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,38 @@ defmodule ExDoc.GroupMatcher do
@doc """
Finds the index of a given group.
"""
def group_index(groups, group) do
def index(groups, group) do
Enum.find_index(groups, fn {k, _v} -> k == group end) || -1
end

@doc """
Group the following entries and while preserving the order in `groups`.
"""
def group_by(groups, entries, by) do
entries = Enum.group_by(entries, by)

{groups, leftovers} =
Enum.flat_map_reduce(groups, entries, fn group, grouped_nodes ->
case Map.pop(grouped_nodes, group, []) do
{[], grouped_nodes} -> {[], grouped_nodes}
{entries, grouped_nodes} -> {[{group, entries}], grouped_nodes}
end
end)

groups ++ Enum.sort(leftovers)
end

@doc """
Finds a matching group for the given function.
"""
@spec match_function(group_patterns, map) :: atom() | nil
def match_function(group_patterns, metadata) do
match_group_patterns(group_patterns, fn pattern -> pattern.(metadata) end)
def match_doc(group_patterns, callback, default, metadata) do
match_group_patterns(group_patterns, fn pattern -> pattern.(metadata) end) ||
callback.(metadata) || default
end

@doc """
Finds a matching group for the given module name, id, and metadata.
"""
@spec match_module(group_patterns, module, binary, map) :: atom() | nil
def match_module(group_patterns, module, id, metadata) do
match_group_patterns(group_patterns, fn pattern ->
case pattern do
Expand All @@ -38,7 +54,6 @@ defmodule ExDoc.GroupMatcher do
@doc """
Finds a matching group for the given extra filename
"""
@spec match_extra(group_patterns, binary) :: atom() | nil
def match_extra(group_patterns, filename) do
match_group_patterns(group_patterns, fn pattern ->
case pattern do
Expand Down
6 changes: 3 additions & 3 deletions lib/ex_doc/language.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ defmodule ExDoc.Language do
@doc """
Returns a map with module information.
"""
@callback module_data(module(), tuple(), ExDoc.Config.t()) :: module_data() | :skip
@callback module_data(module(), tuple(), ExDoc.Config.t()) :: module_data() | false

@doc """
Returns a map with function information or an atom `:skip`.
Returns a map with function information or `false`.

The map has the following keys:

Expand All @@ -78,7 +78,7 @@ defmodule ExDoc.Language do
doc_fallback: (... -> ExDoc.DocAST.t()) | nil,
extra_annotations: [String.t()]
}
| :skip
| false

@doc """
Returns a map with callback information.
Expand Down
8 changes: 4 additions & 4 deletions lib/ex_doc/language/elixir.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule ExDoc.Language.Elixir do

@impl true
@spec module_data(atom, any, any) ::
:skip
false
| %{
callback_types: [:callback, ...],
docs: any,
Expand All @@ -34,7 +34,7 @@ defmodule ExDoc.Language.Elixir do

cond do
skip ->
:skip
false

abst_code = Source.get_abstract_code(module) ->
title = module_title(module, type)
Expand Down Expand Up @@ -73,7 +73,7 @@ defmodule ExDoc.Language.Elixir do
[]
)

:skip
false
end
end

Expand All @@ -84,7 +84,7 @@ defmodule ExDoc.Language.Elixir do
if doc?(entry, module_data.type) do
function_data(kind, name, arity, anno, metadata, module_data)
else
:skip
false
end
end

Expand Down
6 changes: 3 additions & 3 deletions lib/ex_doc/language/erlang.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule ExDoc.Language.Erlang do

@impl true
@spec module_data(atom, any, any) ::
:skip
false
| %{
callback_types: [:callback, ...],
docs: any,
Expand Down Expand Up @@ -54,7 +54,7 @@ defmodule ExDoc.Language.Erlang do
}
else
ExDoc.Utils.warn("skipping docs for module #{inspect(module)}, reason: :no_debug_info", [])
:skip
false
end
end

Expand All @@ -68,7 +68,7 @@ defmodule ExDoc.Language.Erlang do
function_exported?(module_data.module, name, arity) do
function_data(name, arity, doc_content, module_data, metadata)
else
:skip
false
end
end

Expand Down
Loading