summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rebar.hrl6
-rw-r--r--src/rebar_prv_dialyzer.erl58
2 files changed, 53 insertions, 11 deletions
diff --git a/src/rebar.hrl b/src/rebar.hrl
index 961b8ea..8ad0faa 100644
--- a/src/rebar.hrl
+++ b/src/rebar.hrl
@@ -43,6 +43,12 @@
-type rebar_digraph() :: digraph().
-endif.
+-ifdef(namespaced_types).
+-type rebar_set() :: sets:set().
+-else.
+-type rebar_set() :: set().
+-endif.
+
-define(GRAPH_VSN, 2).
-type v() :: {digraph:vertex(), term()} | 'false'.
-type e() :: {digraph:vertex(), digraph:vertex()}.
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index 7f26487..ef14b81 100644
--- a/src/rebar_prv_dialyzer.erl
+++ b/src/rebar_prv_dialyzer.erl
@@ -44,25 +44,29 @@ desc() ->
"options `dialyzer` in rebar.config:\n"
"`warnings` - a list of dialyzer warnings\n"
"`get_warnings` - display warnings when altering a PLT file (boolean)\n"
- "`plt_extra_apps` - a list of applications to include in the PLT file*\n"
+ "`plt_apps` - the strategy for determining the applications which included "
+ "in the PLT file, `top_level_deps` to include just the direct dependencies "
+ "or `all_deps` to include all nested dependencies*\n"
+ "`plt_extra_apps` - a list of applications to include in the PLT file**\n"
"`plt_location` - the location of the PLT file, `local` to store in the "
"profile's base directory (default) or a custom directory.\n"
- "`plt_prefix` - the prefix to the PLT file, defaults to \"rebar3\"**\n"
+ "`plt_prefix` - the prefix to the PLT file, defaults to \"rebar3\"***\n"
"`base_plt_apps` - a list of applications to include in the base "
- "PLT file***\n"
+ "PLT file****\n"
"`base_plt_location` - the location of base PLT file, `global` to store in "
- "$HOME/.cache/rebar3 (default) or a custom directory***\n"
+ "$HOME/.cache/rebar3 (default) or a custom directory****\n"
"`base_plt_prefix` - the prefix to the base PLT file, defaults to "
- "\"rebar3\"** ***\n"
+ "\"rebar3\"*** ****\n"
"\n"
"For example, to warn on unmatched returns: \n"
"{dialyzer, [{warnings, [unmatched_returns]}]}.\n"
"\n"
- "*The applications in `dialyzer_base_plt_apps` and any `applications` and "
- "`included_applications` listed in their .app files will be added to the "
- "list.\n"
- "**PLT files are named \"<prefix>_<otp_release>_plt\".\n"
- "***The base PLT is a PLT containing the core applications often required "
+ "*The direct dependent applications are listed in `applications` and "
+ "`included_applications` of their .app files.\n"
+ "**The applications in `base_plt_apps` will be added to the "
+ "list. \n"
+ "***PLT files are named \"<prefix>_<otp_release>_plt\".\n"
+ "****The base PLT is a PLT containing the core applications often required "
"for a project's PLT. One base PLT is created per OTP version and "
"stored in `base_plt_location`. A base PLT is used to build project PLTs."
"\n".
@@ -178,7 +182,12 @@ proj_plt_files(State) ->
PltApps = get_config(State, plt_extra_apps, []),
Apps = rebar_state:project_apps(State),
DepApps = lists:flatmap(fun rebar_app_info:applications/1, Apps),
- get_plt_files(BasePltApps ++ PltApps ++ DepApps, Apps).
+ DepApps1 =
+ case get_config(State, plt_apps, top_level_deps) of
+ top_level_deps -> DepApps;
+ all_deps -> collect_nested_dependent_apps(DepApps)
+ end,
+ get_plt_files(BasePltApps ++ PltApps ++ DepApps1, Apps).
default_plt_apps() ->
[erts,
@@ -442,3 +451,30 @@ no_warnings() ->
get_config(State, Key, Default) ->
Config = rebar_state:get(State, dialyzer, []),
proplists:get_value(Key, Config, Default).
+
+-spec collect_nested_dependent_apps([atom()]) -> [atom()].
+collect_nested_dependent_apps(RootApps) ->
+ Deps = lists:foldl(fun collect_nested_dependent_apps/2, sets:new(), RootApps),
+ sets:to_list(Deps).
+
+-spec collect_nested_dependent_apps(atom(), rebar_set()) -> rebar_set().
+collect_nested_dependent_apps(App, Seen) ->
+ case sets:is_element(App, Seen) of
+ true ->
+ Seen;
+ false ->
+ Seen1 = sets:add_element(App, Seen),
+ case code:lib_dir(App) of
+ {error, _} ->
+ throw({unknown_application, App});
+ AppDir ->
+ case rebar_app_discover:find_app(AppDir, all) of
+ false ->
+ throw({unknown_application, App});
+ {true, AppInfo} ->
+ lists:foldl(fun collect_nested_dependent_apps/2,
+ Seen1,
+ rebar_app_info:applications(AppInfo))
+ end
+ end
+ end.