summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Fish <james@fishcakez.com>2014-11-20 15:46:54 +0000
committerJames Fish <james@fishcakez.com>2014-11-20 16:05:03 +0000
commita96fddfcde4ab3a71aea01914bd3e7a836db46c0 (patch)
tree06710c4cdd49fbf55f4239e300b73cd824378866
parent16b2dae066484f44e28f707cb58326da0d217bb5 (diff)
Improve default dialyzer PLT by trying to guess dependencies
Try to automatically detect all application dependencies when `plt_apps` is not included in `rebar.config`. Note that this will not follow `runtime_dependencies` in OTP applications. This can be resolved by adding any missing `runtime_dependencies` to `applications` in the .app.src file or including `plt_apps` in `rebar.config`.
-rw-r--r--src/rebar_prv_dialyzer.erl62
1 files changed, 51 insertions, 11 deletions
diff --git a/src/rebar_prv_dialyzer.erl b/src/rebar_prv_dialyzer.erl
index f5d840d..7c13417 100644
--- a/src/rebar_prv_dialyzer.erl
+++ b/src/rebar_prv_dialyzer.erl
@@ -72,11 +72,42 @@ update_plt(State, Apps, Deps) ->
get_plt_files(State, Apps, Deps) ->
case rebar_state:get(State, plt_apps) of
undefined ->
- apps_to_files(Deps);
+ default_plt_files(Apps, Deps);
PltApps ->
app_names_to_files(PltApps, Apps ++ Deps)
end.
+default_plt_files(Apps, Deps) ->
+ DepApps = lists:flatmap(fun rebar_app_info:applications/1, Apps),
+ default_plt_files(default_plt_apps() ++ DepApps, Apps, Deps, [], []).
+
+default_plt_apps() ->
+ [erts,
+ kernel,
+ stdlib].
+
+default_plt_files([], _, _, _, Files) ->
+ Files;
+default_plt_files([AppName | DepApps], Apps, Deps, PltApps, Files) ->
+ case lists:member(AppName, PltApps) of
+ true ->
+ default_plt_files(DepApps, Apps, Deps, PltApps, Files);
+ false ->
+ {DepApps2, Files2} = app_name_to_info(AppName, Apps, Deps),
+ DepApps3 = DepApps2 ++ DepApps,
+ Files3 = Files2 ++ Files,
+ default_plt_files(DepApps3, Apps, Deps, [AppName | PltApps], Files3)
+ end.
+
+app_name_to_info(AppName, Apps, Deps) ->
+ case rebar_app_utils:find(ec_cnv:to_binary(AppName), Apps) of
+ {ok, App} ->
+ % Don't include project app files in plt
+ {rebar_app_info:applications(App), []};
+ error ->
+ app_name_to_info(AppName, Deps)
+ end.
+
apps_to_files(Apps) ->
lists:flatmap(fun app_to_files/1, Apps).
@@ -102,33 +133,42 @@ module_to_file(Module, EbinDir, Ext) ->
end.
app_names_to_files(AppNames, Apps) ->
- lists:flatmap(fun(AppName) -> app_name_to_files(AppName, Apps) end,
- AppNames).
+ ToFiles = fun(AppName) ->
+ {_, Files} = app_name_to_info(AppName, Apps),
+ Files
+ end,
+ lists:flatmap(ToFiles, AppNames).
-app_name_to_files(AppName, Apps) ->
+app_name_to_info(AppName, Apps) ->
case rebar_app_utils:find(ec_cnv:to_binary(AppName), Apps) of
{ok, App} ->
- app_to_files(App);
+ DepApps = rebar_app_info:applications(App),
+ Files = app_to_files(App),
+ {DepApps, Files};
error ->
- app_name_to_files(AppName)
+ app_name_to_info(AppName)
end.
-app_name_to_files(AppName) ->
+app_name_to_info(AppName) ->
case code:lib_dir(AppName) of
{error, _} ->
?CONSOLE("Unknown application ~s", [AppName]),
- [];
+ {[], []};
AppDir ->
- app_dir_to_files(AppDir, AppName)
+ app_dir_to_info(AppDir, AppName)
end.
-app_dir_to_files(AppDir, AppName) ->
+app_dir_to_info(AppDir, AppName) ->
EbinDir = filename:join(AppDir, "ebin"),
AppFile = filename:join(EbinDir, atom_to_list(AppName) ++ ".app"),
case file:consult(AppFile) of
{ok, [{application, AppName, AppDetails}]} ->
+ DepApps = proplists:get_value(applications, AppDetails, []),
+ IncApps = proplists:get_value(included_applications, AppDetails,
+ []),
Modules = proplists:get_value(modules, AppDetails, []),
- modules_to_files(Modules, EbinDir);
+ Files = modules_to_files(Modules, EbinDir),
+ {IncApps ++ DepApps, Files};
_ ->
Error = io_lib:format("Could not parse ~p", [AppFile]),
throw({dialyzer_error, Error})