Skip to content
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

Various edoc fixes and improvements #8063

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
3 changes: 2 additions & 1 deletion lib/edoc/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ SOURCES= \
edoc.erl edoc_cli.erl edoc_data.erl edoc_doclet.erl edoc_doclet_chunks.erl \
edoc_extract.erl edoc_layout.erl edoc_layout_chunks.erl \
edoc_lib.erl edoc_macros.erl edoc_parser.erl edoc_refs.erl edoc_report.erl \
edoc_run.erl edoc_scanner.erl edoc_specs.erl edoc_tags.erl edoc_types.erl edoc_wiki.erl
edoc_run.erl edoc_scanner.erl edoc_specs.erl edoc_tags.erl edoc_types.erl edoc_wiki.erl \
edoc_html_to_markdown.erl

OBJECTS=$(SOURCES:%.erl=$(EBIN)/%.$(EMULATOR)) $(APP_TARGET) $(APPUP_TARGET)

Expand Down
5 changes: 3 additions & 2 deletions lib/edoc/src/edoc.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
edoc_doclet,
edoc_doclet_chunks,
edoc_extract,
edoc_html_to_markdown,
edoc_layout,
edoc_layout_chunks,
edoc_lib,
Expand All @@ -26,6 +27,6 @@
{registered,[]},
{applications, [compiler, kernel, stdlib, syntax_tools]},
{env, []},
{runtime_dependencies, ["xmerl-1.3.7", "syntax_tools-2.0", "stdlib-3.15",
"kernel-3.0", "inets-5.10", "erts-6.0"]}
{runtime_dependencies, ["xmerl-1.3.7", "syntax_tools-2.0", "stdlib-4.0",
"kernel-7.0", "inets-5.10", "erts-11.0"]}
]}.
1,225 changes: 1,225 additions & 0 deletions lib/edoc/src/edoc_html_to_markdown.erl

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions lib/edoc/src/edoc_layout.erl
Original file line number Diff line number Diff line change
Expand Up @@ -660,10 +660,13 @@ href(E) ->
case get_attrval(href, E) of
"" -> [];
URI ->
T = case get_attrval(target, E) of
"" -> [];
S -> [{target, S}]
end,
T = lists:flatmap(
fun(K) ->
case get_attrval(K, E) of
"" -> [];
S -> [{K, S}]
end
end, [target, 'docgen-rel', 'docgen-href']),
[{href, URI} | T]
end.

Expand Down
9 changes: 5 additions & 4 deletions lib/edoc/src/edoc_layout_chunks.erl
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ edoc_to_chunk(Doc, Opts) ->
Opts :: proplists:proplist().
doc_contents(XPath, Doc, Opts) ->
case doc_visibility(XPath, Doc, Opts) of
none -> none;
hidden -> hidden;
show -> doc_contents_(XPath, Doc, Opts)
end.
Expand All @@ -152,9 +151,9 @@ doc_visibility(_XPath, Doc, Opts) ->
%% EDoc `@private' maps to EEP-48 `hidden'
{<<"yes">>, _, _} ->
hidden;
%% EDoc `@hidden' is EEP-48 `none'
%% EDoc `@hidden' is EEP-48 `hidden'
{_, _, <<"yes">>} ->
none;
hidden;
_ ->
show
end.
Expand Down Expand Up @@ -480,7 +479,9 @@ xpath_to_text(XPath, Doc, Opts) ->
[] -> <<>>;
[#xmlAttribute{} = Attr] ->
{_ , Value} = format_attribute(Attr),
hd(shell_docs:normalize([Value]));
case shell_docs:normalize([Value]) of
[{p,[],[Normal]}] -> Normal
end;
[#xmlElement{}] = Elements ->
xmerl_to_binary(Elements, Opts);
[_|_] ->
Expand Down
6 changes: 3 additions & 3 deletions lib/edoc/src/edoc_refs.erl
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ docgen_uri({module, M}) ->
docgen_uri({module, M, Ref}) ->
[atom_to_list(M), docgen_uri(Ref)];
docgen_uri({function, F, A}) ->
["#", atom_to_list(F), "/", integer_to_list(A)];
["#", escape_uri(atom_to_list(F)), "/", integer_to_list(A)];
docgen_uri({type, T}) ->
["#", atom_to_list(T), "/0"];
["#", escape_uri(atom_to_list(T)), "/0"];
docgen_uri({type, T, A}) ->
%% This case is not used yet, but since types also have arity it should be in the future.
["#", atom_to_list(T), "/", integer_to_list(A)].
["#", escape_uri(atom_to_list(T)), "/", integer_to_list(A)].

get_uri({app, App}, Env) ->
join_uri(app_ref(App, Env), ?INDEX_FILE);
Expand Down
14 changes: 12 additions & 2 deletions lib/edoc/src/edoc_types.erl
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ get_uri(Name, Env) ->
NewName = infer_module_app(Name),
edoc_refs:get_uri(to_ref(NewName), Env).

get_docgen_uri(Name, _Env) ->
NewName = infer_module_app(Name),
edoc_refs:get_docgen_link(to_ref(NewName)).

infer_module_app(#t_name{app = [], module = M} = TName) when is_atom(M) ->
case edoc_lib:infer_module_app(M) of
no_app ->
Expand Down Expand Up @@ -194,9 +198,15 @@ to_xml(#t_type{name = N, args = As}, Env, Opts) ->
HRef = case {Predef, proplists:get_value(link_predefined_types, Opts, false)} of
{true, false} -> [];
{true, true} ->
[{href, get_uri(N#t_name{ module = erlang }, Env)}];
{DocgenRel, DocgenURI} = get_docgen_uri(N#t_name{ module = erlang }, Env),
[{'docgen-rel',DocgenRel},
{'docgen-href',DocgenURI},
{href, get_uri(N#t_name{ module = erlang }, Env)}];
{false, _} ->
[{href, get_uri(N, Env)}]
{DocgenRel, DocgenURI} = get_docgen_uri(N, Env),
[{'docgen-rel',DocgenRel},
{'docgen-href',DocgenURI},
{href, get_uri(N, Env)}]
end,
{abstype, HRef, [to_xml(N, Env, Opts) | map(fun wrap_utype/3, As, Env, Opts)]};
to_xml(#t_fun{args = As, range = T}, Env, Opts) ->
Expand Down
21 changes: 17 additions & 4 deletions lib/edoc/test/eep48_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ links(Config) ->
get_doc_link({function, local_function_link, 0}, Docs)),
?assertEqual({<<"seetype">>, <<"#t/0">>},
get_doc_link({function, local_type_link, 0}, Docs)),
?assertEqual({<<"seetype">>, <<"#t/0">>},
get_doc_link({function, local_type_link_macro, 0}, Docs)),
?assertEqual({<<"seetype">>, <<"eep48_links#t/0">>},
get_doc_link({function, external_type_link, 0}, Docs)).

Expand Down Expand Up @@ -514,10 +516,21 @@ lookup_entry(Kind, Function, Arity, Docs) ->
get_metadata({_, _, _, _, Metadata}) -> Metadata.

get_doc_link(KNA, Docs) ->
[Link] = [ Node || {a, _, _} = Node <- get_doc(KNA, Docs) ],
{a, Attrs, _} = Link,
<<"https://erlang.org/doc/link/", ShortRel/bytes>> = fetch(rel, Attrs),
{ShortRel, fetch(href, Attrs)}.
D = get_doc(KNA, Docs),
case lists:foldl(fun F({a, _, _} = E, Acc) ->
[E | Acc];
F({_E, _, Es}, Acc) when is_list(Es) ->
lists:foldl(F, Acc, Es);
F(_, Acc) ->
Acc
end, [], D) of
[{a, Attrs, _}] ->
<<"https://erlang.org/doc/link/", ShortRel/bytes>> = fetch(rel, Attrs),
{ShortRel, fetch(href, Attrs)};
_Else ->
ct:log("Could not find link in ~p",[D]),
ct:fail("Did not find link in docs")
end.

get_anno(Kind, Name, Arity, Docs) ->
{_, Anno, _, _, _} = lookup_entry(Kind, Name, Arity, Docs),
Expand Down
5 changes: 5 additions & 0 deletions lib/edoc/test/eep48_SUITE_data/eep48_links.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
external_function_link/0,
local_function_link/0,
local_type_link/0,
local_type_link_macro/0,
external_type_link/0]).

-export([see_module/0,
Expand Down Expand Up @@ -57,6 +58,10 @@ local_function_link() -> ok.
%% Should map to `seetype'.
local_type_link() -> ok.

%% @doc Local type link {@type {type, t()@}}.
%% Should map to `seetype'.
local_type_link_macro() -> ok.

%% @doc External type link {@link eep48_links:t()}.
%% Should map to `seetype'.
external_type_link() -> ok.
Expand Down
23 changes: 22 additions & 1 deletion lib/stdlib/src/shell_docs.erl
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ validate_docs([],_) ->
NormalizedDocs :: chunk_elements().
normalize(Docs) ->
Trimmed = normalize_trim(Docs,true),
normalize_space(Trimmed).
Space = normalize_space(Trimmed),
normalize_paragraph(Space).

normalize_trim(Bin,true) when is_binary(Bin) ->
%% Remove any whitespace (except \n) before or after a newline
Expand Down Expand Up @@ -341,6 +342,26 @@ trim_last([{Elem,Attr,Content} = Tag|T],What) ->
trim_last([],_What) ->
{[],false}.

%% Any non-block elements at top level are wrapped in a p so that tools
%% don't have to deal with that.
normalize_paragraph([{Tag,_,_} = Block | T]) when ?IS_BLOCK(Tag) ->
[Block | normalize_paragraph(T)];
normalize_paragraph([{_,_,[]} = NoContent | T]) ->
%% If an inline tag has no content we don't wrap it in a <p>. This is
%% aimed at fixing <a id=""/> tags at top-level.
[NoContent | normalize_paragraph(T)];
normalize_paragraph([]) ->
[];
normalize_paragraph(Elems) ->
case lists:splitwith(
fun(E) ->
is_binary(E) orelse
(?IS_INLINE(element(1, E)) andalso element(3, E) =/= [])
end, Elems) of
{NotP, P} ->
[{p,[],NotP} | normalize_paragraph(P)]
end.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% API function for dealing with the function documentation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Expand Down
Loading