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

openSUSE Build Service is sponsored by