File 0643-edoc-Restore-default-options-for-chunks.patch of Package erlang
From 8d83a276b3353ce7f417cce40fa207c551627f71 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lukas=20Backstr=C3=B6m?= <lukas@erlang.org>
Date: Wed, 25 Feb 2026 13:57:59 +0100
Subject: [PATCH 1/2] edoc: Restore default options for chunks
The default for edoc is to not include private/hidden functions and types
so we do that in order to make the behaviour of chunks (and in extension ExDoc)
more similar to how edoc does things.
closes #10377
---
lib/edoc/src/edoc_doclet_chunks.erl | 3 +-
lib/edoc/test/eep48_SUITE.erl | 73 ++++++++++++++++---
.../test/eep48_SUITE_data/eep48_links.erl | 5 +-
.../test/eep48_SUITE_data/eep48_redundant.erl | 5 ++
.../test/eep48_SUITE_data/eep48_specs.erl | 16 +++-
.../eep48_SUITE_data/eep48_visibility.erl | 31 ++++++++
6 files changed, 117 insertions(+), 16 deletions(-)
create mode 100644 lib/edoc/test/eep48_SUITE_data/eep48_visibility.erl
diff --git a/lib/edoc/src/edoc_doclet_chunks.erl b/lib/edoc/src/edoc_doclet_chunks.erl
index d553b03fbe..74a66427ed 100644
--- a/lib/edoc/src/edoc_doclet_chunks.erl
+++ b/lib/edoc/src/edoc_doclet_chunks.erl
@@ -116,8 +116,7 @@ source({_M, Name, Path}, Dir, Suffix, Env, OkSet, ErrorFlag, Options0) ->
try
%% Without these opts the entries returned by EDoc core (`edoc_extract:source1/5') won't have
%% all the necessary data to generate chunks.
- RequiredChunkOpts = [return_entries, private, hidden],
- %% But we also want to have the real user-defined `private' accessible.
+ RequiredChunkOpts = [return_entries],
Options = ([{show_private, proplists:get_bool(private, Options0)}]
++ RequiredChunkOpts
++ Options0),
diff --git a/lib/edoc/test/eep48_SUITE.erl b/lib/edoc/test/eep48_SUITE.erl
index a9ae2b8402..32f1237ba3 100644
--- a/lib/edoc/test/eep48_SUITE.erl
+++ b/lib/edoc/test/eep48_SUITE.erl
@@ -53,7 +53,8 @@
f_prefixed_spec/1,
t_only_attr/1,
t_only_tag/1,
- t_redundant/1]).
+ t_redundant/1,
+ t_visibility/1]).
-define(a2b(A), atom_to_binary(A, utf8)).
-define(io2b(IO), iolist_to_binary(IO)).
@@ -106,7 +107,8 @@ all() -> [edoc_app_should_pass_shell_docs_validation,
f_prefixed_spec,
t_only_attr,
t_only_tag,
- t_redundant].
+ t_redundant,
+ t_visibility].
%% TODO: remove these cases once EDoc supports extracting the relevant tags
not_supported() -> [type_since_tag,
@@ -468,18 +470,62 @@ t_redundant(Config) ->
?assertEqual( <<"Type t_redundant defined with an attribute, redundant with a tag.">>,
get_flat_doc({type, ?FUNCTION_NAME, 0}, Docs) ).
+t_visibility(Config) ->
+ Docs = get_docs(Config, eep48_visibility),
+ %?debugVal(Docs, 1000),
+ ?assertMatch([<<"public_function()">>], get_sig({function, public_function, 0}, Docs)),
+ ?assertException(error, {not_found, {function, hidden_function, 0}}, get_sig({function, hidden_function, 0}, Docs)),
+ ?assertException(error, {not_found, {function, private_function, 0}}, get_sig({function, private_function, 0}, Docs)),
+ ?assertException(error, {not_found, {function, non_exported_function, 0}}, get_sig({function, non_exported_function, 0}, Docs)),
+ ?assertMatch([<<"public_type/0">>], get_sig({type, public_type, 0}, Docs)),
+ ?assertException(error, {not_found, {type, non_exported_type, 0}}, get_sig({type, non_exported_type, 0}, Docs)),
+
+ PrivateDocs = get_docs(Config, eep48_visibility, [{private, true}]),
+ %?debugVal(Docs, 1000),
+ ?assertMatch([<<"public_function()">>], get_sig({function, public_function, 0}, PrivateDocs)),
+ ?assertException(error, {not_found, {function, hidden_function, 0}}, get_sig({function, hidden_function, 0}, PrivateDocs)),
+ ?assertMatch([<<"private_function()">>], get_sig({function, private_function, 0}, PrivateDocs)),
+ ?assertMatch([<<"non_exported_function()">>], get_sig({function, non_exported_function, 0}, PrivateDocs)),
+ ?assertMatch([<<"public_type/0">>], get_sig({type, public_type, 0}, PrivateDocs)),
+ ?assertMatch([<<"non_exported_type/0">>], get_sig({type, non_exported_type, 0}, PrivateDocs)),
+
+ HiddenDocs = get_docs(Config, eep48_visibility, [{hidden, true}]),
+ %?debugVal(Docs, 1000),
+ ?assertMatch([<<"public_function()">>], get_sig({function, public_function, 0}, HiddenDocs)),
+ ?assertMatch([<<"hidden_function()">>], get_sig({function, hidden_function, 0}, HiddenDocs)),
+ ?assertException(error, {not_found, {function, private_function, 0}}, get_sig({function, private_function, 0}, HiddenDocs)),
+ ?assertException(error, {not_found, {function, non_exported_function, 0}}, get_sig({function, non_exported_function, 0}, HiddenDocs)),
+ ?assertMatch([<<"public_type/0">>], get_sig({type, public_type, 0}, HiddenDocs)),
+ ?assertException(error, {not_found, {type, non_exported_type, 0}}, get_sig({type, non_exported_type, 0}, HiddenDocs)),
+
+ PrivateHiddenDocs = get_docs(Config, eep48_visibility, [{private, true}, {hidden, true}]),
+ %?debugVal(Docs, 1000),
+ ?assertMatch([<<"public_function()">>], get_sig({function, public_function, 0}, PrivateHiddenDocs)),
+ ?assertMatch([<<"hidden_function()">>], get_sig({function, hidden_function, 0}, PrivateHiddenDocs)),
+ ?assertMatch([<<"private_function()">>], get_sig({function, private_function, 0}, PrivateHiddenDocs)),
+ ?assertMatch([<<"non_exported_function()">>], get_sig({function, non_exported_function, 0}, PrivateHiddenDocs)),
+ ?assertMatch([<<"public_type/0">>], get_sig({type, public_type, 0}, PrivateHiddenDocs)),
+ ?assertMatch([<<"non_exported_type/0">>], get_sig({type, non_exported_type, 0}, PrivateHiddenDocs)),
+
+ ok.
+
%%
%% Helpers
%%
get_chunk(Config, M) ->
+ get_chunk(Config, M, []).
+
+get_chunk(Config, M, Options) ->
DataDir = ?config(data_dir, Config),
PrivDir = ?config(priv_dir, Config),
- {ok, Chunk} = get_doc_chunk(DataDir, PrivDir, M),
+ {ok, Chunk} = get_doc_chunk(DataDir, PrivDir, M, Options),
Chunk.
get_docs(Config, M) ->
- Chunk = get_chunk(Config, M),
+ get_docs(Config, M, []).
+get_docs(Config, M, Options) ->
+ Chunk = get_chunk(Config, M, Options),
Chunk#docs_v1.docs.
get_function_meta_field(Field, F, A, Docs) ->
@@ -495,25 +541,28 @@ get_meta_field(Field, Kind, Name, Arity, Docs) ->
Meta = get_metadata(lookup_entry(Kind, Name, Arity, Docs)),
maps:get(Field, Meta).
-get_doc_chunk(DataDir, PrivDir, Mod) ->
+get_doc_chunk(DataDir, PrivDir, Mod, Options) ->
TagsErl = filename:join([DataDir, atom_to_list(Mod) ++ ".erl"]),
edoc:files([TagsErl], [{doclet, edoc_doclet_chunks},
{layout, edoc_layout_chunks},
- {dir, PrivDir}]),
+ {dir, PrivDir}|Options]),
TagsChunk = filename:join([PrivDir, "chunks", atom_to_list(Mod) ++ ".chunk"]),
{ok, BChunk} = file:read_file(TagsChunk),
Chunk = binary_to_term(BChunk),
{ok, Chunk}.
lookup_entry(Kind, Function, Arity, Docs) ->
- [Entry] = lists:filter(fun({{K, F, A},_Anno,_Sig,_Doc,_Meta})
+ case lists:filter(fun({{K, F, A},_Anno,_Sig,_Doc,_Meta})
when K =:= Kind andalso F =:= Function, A =:= Arity ->
true;
(_) ->
false
- end, Docs),
- Entry.
-
+ end, Docs) of
+ [Entry] ->
+ Entry;
+ [] ->
+ error({not_found, {Kind, Function, Arity}})
+ end.
get_metadata({_, _, _, _, Metadata}) -> Metadata.
get_doc_link(KNA, Docs) ->
@@ -582,9 +631,9 @@ copy_application(App, TargetDir) ->
{ok, #{ebin => EbinDir, doc => DocDir, src => SrcDir}}.
copy_app_dir(App, Dir, TargetDir) ->
- {ok, Files} = file:list_dir(code:lib_dir(App, Dir)),
+ {ok, Files} = file:list_dir(filename:join(code:lib_dir(App), Dir)),
lists:foreach(fun (F) ->
- file:copy(filename:join(code:lib_dir(App, Dir), F),
+ file:copy(filename:join([code:lib_dir(App), Dir, F]),
filename:join(TargetDir, F))
end, Files).
diff --git a/lib/edoc/test/eep48_SUITE_data/eep48_links.erl b/lib/edoc/test/eep48_SUITE_data/eep48_links.erl
index 2345495aed..6669671f77 100644
--- a/lib/edoc/test/eep48_SUITE_data/eep48_links.erl
+++ b/lib/edoc/test/eep48_SUITE_data/eep48_links.erl
@@ -12,7 +12,10 @@
local_function_link/0,
local_type_link/0,
local_type_link_macro/0,
- external_type_link/0]).
+ external_type_link/0,
+ fun_with_equiv_tag/0,
+ fun_with_non_call_equiv_tag/0,
+ fun_with_equiv_doc_and_see/0]).
-export([see_module/0,
see_app/0,
diff --git a/lib/edoc/test/eep48_SUITE_data/eep48_redundant.erl b/lib/edoc/test/eep48_SUITE_data/eep48_redundant.erl
index f8bed5780f..88ae231e43 100644
--- a/lib/edoc/test/eep48_SUITE_data/eep48_redundant.erl
+++ b/lib/edoc/test/eep48_SUITE_data/eep48_redundant.erl
@@ -1,5 +1,10 @@
-module(eep48_redundant).
+-export([f_redundant_spec/0,
+ f_only_attr/0,
+ f_only_tag/0,
+ f_prefixed_spec/0]).
+
-export_type([t_only_attr/0,
t_only_tag/0,
t_redundant/0]).
diff --git a/lib/edoc/test/eep48_SUITE_data/eep48_specs.erl b/lib/edoc/test/eep48_SUITE_data/eep48_specs.erl
index 7da149f591..19319b44a2 100644
--- a/lib/edoc/test/eep48_SUITE_data/eep48_specs.erl
+++ b/lib/edoc/test/eep48_SUITE_data/eep48_specs.erl
@@ -1,7 +1,21 @@
%% @doc Fixtures for chunk specs.
-module(eep48_specs).
--export([]).
+-export([f_spec_type_without_name/1,
+ f_spec_type_with_name/1,
+ f_spec_types_mixed/2,
+ f_spec_with_multiple_clauses/2,
+ f_spec_with_multiple_clauses_one_fun_clause/2,
+ f_spec_lhs_match_expr/1,
+ f_spec_rhs_match_expr/1,
+ f_spec_unnamed_pattern/1,
+ f_spec_bounded_single_clause_fun/4,
+ f_spec_bounded_multiple_clause_fun/4,
+ f_spec_bounded_singleton_atom/2,
+ f_spec_bounded_singleton_int/2,
+ f_spec_rettype_constraint/0,
+ f_spec_indirect_constraint/2,
+ f_spec_arg_type_in_retval/2]).
-export_type([opaque_type/0]).
diff --git a/lib/edoc/test/eep48_SUITE_data/eep48_visibility.erl b/lib/edoc/test/eep48_SUITE_data/eep48_visibility.erl
new file mode 100644
index 0000000000..7e08b3325d
--- /dev/null
+++ b/lib/edoc/test/eep48_SUITE_data/eep48_visibility.erl
@@ -0,0 +1,31 @@
+%% @doc Test visibility of various kinds of items in the generated docs.
+-module(eep48_visibility).
+
+-export([public_function/0, hidden_function/0, private_function/0]).
+
+-export_type([public_type/0]).
+
+%% Note: There is no such thing as a hidden or private type.
+
+-type public_type() :: {}.
+%% This type should be visible in the generated docs.
+-type non_exported_type() :: ok.
+%% This type should not be visible in the generated docs.
+
+%% @doc This function should be visible in the generated docs.
+-spec public_function() -> ok.
+public_function() -> ok.
+
+%% @doc This function should not be visible in the generated docs.
+%% @hidden
+-spec hidden_function() -> ok.
+hidden_function() -> ok.
+
+%% @doc This function should not be visible in the generated docs.
+%% @private
+-spec private_function() -> non_exported_type().
+private_function() -> non_exported_function().
+
+%% @doc This type should not be visible in the generated docs.
+-spec non_exported_function() -> non_exported_type().
+non_exported_function() -> ok.
\ No newline at end of file
--
2.51.0