Current section
Files
Jump to
Current section
Files
src/doctest_parse.erl
%%%---------------------------------------------------------------------
%%% Copyright 2024 William Fank Thomé
%%%
%%% Licensed under the Apache License, Version 2.0 (the "License");
%%% you may not use this file except in compliance with the License.
%%% You may obtain a copy of the License at
%%%
%%% http://www.apache.org/licenses/LICENSE-2.0
%%%
%%% Unless required by applicable law or agreed to in writing, software
%%% distributed under the License is distributed on an "AS IS" BASIS,
%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%% See the License for the specific language governing permissions and
%%% limitations under the License.
%%%---------------------------------------------------------------------
-module(doctest_parse).
-moduledoc false.
% API functions
-export([module_tests/3]).
% Contains the docs_v1 record.
-include_lib("kernel/include/eep48.hrl").
%%%=====================================================================
%%% API functions
%%%=====================================================================
module_tests(Mod, ShouldTestModDoc, FunsOpts) ->
case code:get_doc(Mod) of
{ok, #docs_v1{anno = Anno, module_doc = Lang, docs = Docs}} ->
Desc = iolist_to_binary(io_lib:format("module '~w'", [Mod])),
case ShouldTestModDoc of
true ->
{ok, {Desc, lists:flatten([
moduledoc_attr_tests(Mod, Anno, Lang),
doc_attr_tests(Mod, Docs, FunsOpts)
])}};
false ->
{ok, {Desc, doc_attr_tests(Mod, Docs, FunsOpts)}}
end;
{error, Reason} ->
{error, Reason}
end.
%%%=====================================================================
%%% Internal functions
%%%=====================================================================
unwrap(#{<<"en">> := Markdown}) ->
{ok, Markdown};
unwrap(none) ->
none.
moduledoc_attr_tests(Mod, Anno, Lang) ->
case unwrap(Lang) of
{ok, Markdown} ->
case doctest_md:code_blocks(Markdown) of
{ok, CodeBlocks} ->
Ln = erl_anno:line(Anno),
doctest_eunit:moduledoc_tests(Mod, Ln, CodeBlocks);
none ->
[]
end;
none ->
[]
end.
doc_attr_tests(Mod, Docs, FunsOpts) ->
lists:filtermap(fun
({{function, Fun, Arity}, Anno, _Sign, Lang, _Meta}) ->
case keep_fun({Fun, Arity}, FunsOpts) of
true ->
case unwrap(Lang) of
{ok, Markdown} ->
case doctest_md:code_blocks(Markdown) of
{ok, CodeBlocks} ->
MFA = {Mod, Fun, Arity},
Ln = erl_anno:line(Anno),
{true, doctest_eunit:doc_tests(MFA, Ln, CodeBlocks)};
none ->
false
end;
none ->
false
end;
false ->
false
end;
(_) ->
false
end, Docs).
keep_fun(_Fun, true) ->
true;
keep_fun(_Fun, false) ->
false;
keep_fun(Fun, Funs) when is_list(Funs) ->
lists:member(Fun, Funs).