您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

92 行
3.8 KiB

  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. code:add_pathsa(rebar_state:code_paths(State, all_deps)),
  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 = ec_cnv:to_list(rebar_app_info:name(AppInfo)),
  39. ?INFO("Running edoc for ~s", [AppName]),
  40. AppDir = rebar_app_info:dir(AppInfo),
  41. AppRes = (catch edoc:application(list_to_atom(AppName), AppDir, EdocOptsAcc)),
  42. rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, AppInfo, State),
  43. case {AppRes, ShouldAccPaths} of
  44. {ok, true} ->
  45. %% edoc wants / on all OSes
  46. add_to_paths(EdocOptsAcc, AppDir++"/doc");
  47. {ok, false} ->
  48. EdocOptsAcc;
  49. {{'EXIT', error}, _} ->
  50. %% EDoc is not very descriptive
  51. %% in terms of failures
  52. throw({app_failed, AppName})
  53. end
  54. end, EdocOpts, ProjectApps)
  55. catch
  56. {app_failed, AppName} ->
  57. {app_failed, AppName}
  58. end,
  59. rebar_hooks:run_all_hooks(Cwd, post, ?PROVIDER, Providers, State),
  60. rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)),
  61. case Res of
  62. {app_failed, App} ->
  63. ?PRV_ERROR({app_failed, App});
  64. _ ->
  65. {ok, State}
  66. end.
  67. -spec format_error(any()) -> iolist().
  68. format_error({app_failed, AppName}) ->
  69. io_lib:format("Failed to generate documentation for app '~s'", [AppName]);
  70. format_error(Reason) ->
  71. io_lib:format("~p", [Reason]).
  72. %% ===================================================================
  73. %% Internal functions
  74. %% ===================================================================
  75. has_configured_paths(EdocOpts) ->
  76. proplists:get_value(dir, EdocOpts) =/= undefined.
  77. add_to_paths([], Path) ->
  78. [{doc_path, [Path]}];
  79. add_to_paths([{doc_path, Paths}|T], Path) ->
  80. [{doc_path, [Path | Paths]} | T];
  81. add_to_paths([H|T], Path) ->
  82. [H | add_to_paths(T, Path)].