summaryrefslogtreecommitdiff
path: root/src/rebar_prv_dialyzer.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/rebar_prv_dialyzer.erl')
-rw-r--r--src/rebar_prv_dialyzer.erl76
1 files changed, 51 insertions, 25 deletions
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index 7f26487..7cf7e28 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,
@@ -395,19 +404,12 @@ run_dialyzer(State, Opts, Output) ->
format_warnings(Output, Warnings) ->
Warnings1 = format_warnings(Warnings),
console_warnings(Warnings1),
- file_warnings(Output, Warnings1),
+ file_warnings(Output, Warnings),
length(Warnings1).
format_warnings(Warnings) ->
- [format_warning(Warning) || Warning <- Warnings].
-
-format_warning(Warning) ->
- case strip(dialyzer:format_warning(Warning, fullpath)) of
- ":0: " ++ Unknown ->
- Unknown;
- Warning1 ->
- Warning1
- end.
+ [rebar_dialyzer_format:format(Warning) || Warning <- Warnings].
+
console_warnings(Warnings) ->
_ = [?CONSOLE("~s", [Warning]) || Warning <- Warnings],
@@ -416,7 +418,7 @@ console_warnings(Warnings) ->
file_warnings(_, []) ->
ok;
file_warnings(Output, Warnings) ->
- Warnings1 = [[Warning, $\n] || Warning <- Warnings],
+ Warnings1 = [[dialyzer:format_warning(Warning, fullpath), $\n] || Warning <- Warnings],
case file:write_file(Output, Warnings1, [append]) of
ok ->
ok;
@@ -424,9 +426,6 @@ file_warnings(Output, Warnings) ->
throw({output_file_error, Output, Reason})
end.
-strip(Warning) ->
- string:strip(Warning, right, $\n).
-
no_warnings() ->
[no_return,
no_unused,
@@ -442,3 +441,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.