Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

120 rindas
5.0 KiB

pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
  1. -module(rebar_prv_edoc).
  2. -behaviour(provider).
  3. -export([init/1,
  4. do/1,
  5. format_error/1]).
  6. -include("rebar.hrl").
  7. -include_lib("providers/include/providers.hrl").
  8. -define(PROVIDER, edoc).
  9. -define(DEPS, [compile]).
  10. %% ===================================================================
  11. %% Public API
  12. %% ===================================================================
  13. -spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
  14. init(State) ->
  15. State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER},
  16. {module, ?MODULE},
  17. {bare, true},
  18. {deps, ?DEPS},
  19. {example, "rebar3 edoc"},
  20. {short_desc, "Generate documentation using edoc."},
  21. {desc, "Generate documentation using edoc."},
  22. {opts, []},
  23. {profiles, [docs]}])),
  24. {ok, State1}.
  25. -spec do(rebar_state:t()) ->
  26. {ok, rebar_state:t()} | {error, string()} | {error, {module(), any()}}.
  27. do(State) ->
  28. rebar_paths:set_paths([deps, plugins], State),
  29. ProjectApps = rebar_state:project_apps(State),
  30. Providers = rebar_state:providers(State),
  31. EdocOpts = rebar_state:get(State, edoc_opts, []),
  32. ShouldAccPaths = not has_configured_paths(EdocOpts),
  33. Cwd = rebar_state:dir(State),
  34. rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State),
  35. Res = try
  36. lists:foldl(fun(AppInfo, EdocOptsAcc) ->
  37. rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, AppInfo, State),
  38. AppName = rebar_utils:to_list(rebar_app_info:name(AppInfo)),
  39. ?INFO("Running edoc for ~ts", [AppName]),
  40. AppDir = rebar_app_info:dir(AppInfo),
  41. AppOpts = rebar_app_info:opts(AppInfo),
  42. %% order of the merge is important to allow app opts overrides
  43. AppEdocOpts = merge_opts(rebar_opts:get(AppOpts, edoc_opts, []), EdocOptsAcc),
  44. ?DEBUG("{edoc_opts, ~p}.", [AppEdocOpts]),
  45. AppRes = (catch edoc:application(list_to_atom(AppName), AppDir, AppEdocOpts)),
  46. rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, AppInfo, State),
  47. case {AppRes, ShouldAccPaths} of
  48. {ok, true} ->
  49. %% edoc wants / on all OSes
  50. add_to_paths(EdocOptsAcc, AppDir++"/doc");
  51. {ok, false} ->
  52. EdocOptsAcc;
  53. {{'EXIT', error}, _} ->
  54. %% EDoc is not very descriptive
  55. %% in terms of failures
  56. throw({app_failed, AppName})
  57. end
  58. end, EdocOpts, ProjectApps)
  59. catch
  60. {app_failed, AppName} ->
  61. {app_failed, AppName}
  62. end,
  63. rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State),
  64. rebar_paths:set_paths([plugins, deps], State),
  65. case Res of
  66. {app_failed, App} ->
  67. ?PRV_ERROR({app_failed, App});
  68. _ ->
  69. {ok, State}
  70. end.
  71. -spec format_error(any()) -> iolist().
  72. format_error({app_failed, AppName}) ->
  73. io_lib:format("Failed to generate documentation for app '~ts'", [AppName]);
  74. format_error(Reason) ->
  75. io_lib:format("~p", [Reason]).
  76. %% ===================================================================
  77. %% Internal functions
  78. %% ===================================================================
  79. has_configured_paths(EdocOpts) ->
  80. proplists:get_value(dir, EdocOpts) =/= undefined.
  81. add_to_paths([], Path) ->
  82. [{doc_path, [Path]}];
  83. add_to_paths([{doc_path, Paths}|T], Path) ->
  84. [{doc_path, [Path | Paths]} | T];
  85. add_to_paths([H|T], Path) ->
  86. [H | add_to_paths(T, Path)].
  87. merge_opts(AppOpts, BaseOpts) ->
  88. merge_epp_macros(rebar_utils:tup_umerge(AppOpts, BaseOpts)).
  89. %% @private the `{macros, ...}' definitions for epp can't be
  90. %% containing duplicate definitions even if multiple macro lists
  91. %% are supported, so we need to manually remove duplicates
  92. %% and merge the many lists into a single one.
  93. merge_epp_macros([]) ->
  94. [];
  95. merge_epp_macros([{macros, M1}, {macros, M2} | Rest]) ->
  96. NewMacros = dedupe_macros(lists:usort(M1), lists:usort(M2)),
  97. merge_epp_macros( [{macros, NewMacros} | Rest]);
  98. merge_epp_macros([H | T]) ->
  99. [H | merge_epp_macros(T)].
  100. dedupe_macros([], Bs) -> Bs;
  101. dedupe_macros(As, []) -> As;
  102. dedupe_macros([{K, V1} | As], [{K, _} | Bs]) ->
  103. [{K, V1} | dedupe_macros(As, Bs)];
  104. dedupe_macros([{KA, VA} | As], [{KB, VB} | Bs]) ->
  105. if KA < KB -> [{KA, VA} | dedupe_macros(As, [{KB, VB} | Bs])];
  106. KA > KB -> [{KB, VB} | dedupe_macros([{KA, VA} | As], Bs)]
  107. end.