summaryrefslogtreecommitdiff
path: root/src/rebar_dialyzer.erl
diff options
context:
space:
mode:
authorTuncer Ayaz <tuncer.ayaz@gmail.com>2010-10-25 22:07:32 +0200
committerTuncer Ayaz <tuncer.ayaz@gmail.com>2010-10-25 22:37:18 +0200
commit2d2aed627f747533e2a40f44dd813160e582c7e2 (patch)
tree2121aa32c37cd3726f23a4e8f7824c809e848969 /src/rebar_dialyzer.erl
parent7ddd4bdaadcef81410beab0f611c750b87a0445d (diff)
downloadrebar-2d2aed627f747533e2a40f44dd813160e582c7e2.tar.gz
Refactor Dialyzer support to make it more usable
Diffstat (limited to 'src/rebar_dialyzer.erl')
-rw-r--r--src/rebar_dialyzer.erl113
1 files changed, 85 insertions, 28 deletions
diff --git a/src/rebar_dialyzer.erl b/src/rebar_dialyzer.erl
index de78a05..d2b89aa 100644
--- a/src/rebar_dialyzer.erl
+++ b/src/rebar_dialyzer.erl
@@ -27,9 +27,9 @@
%% @author Dave Smith <dizzyd@dizzyd.com>
%% @doc rebar_dialyzer supports the following commands:
%% <ul>
-%% <li>analyze (essentially "dialyzer -r ebin")</li>
-%% <li>build_plt (essentially "dialyzer --build_plt -r &lt;app_dirs&gt;")</li>
-%% <li>check_plt (essentially "dialyzer --check_plt")</li>
+%% <li>dialyze (essentially "dialyzer ebin" or "dialyzer --src src")</li>
+%% <li>build-plt (essentially "dialyzer --build_plt -r &lt;app_dirs&gt;")</li>
+%% <li>check-plt (essentially "dialyzer --check_plt")</li>
%% </ul>
%% A single option <code>plt</code> can be presented in the <code>dialyzer_opts</code>
%% options in <code>rebar.config</code>. If it is present, it is used as the PLT for the
@@ -44,9 +44,9 @@
%% -------------------------------------------------------------------
-module(rebar_dialyzer).
--export([analyze/2,
- build_plt/2,
- check_plt/2]).
+-export([dialyze/2,
+ 'build-plt'/2,
+ 'check-plt'/2]).
-include("rebar.hrl").
@@ -57,21 +57,39 @@
%% ===================================================================
%% @doc Perform static analysis on the contents of the ebin directory.
-%% @spec analyze(Config::#config{}, File::string()) -> ok
--spec(analyze(Config::#config{}, File::string()) -> ok).
-analyze(Config, File) ->
- Plt = plt_path(Config, File),
+%% @spec dialyze(Config::#config{}, File::string()) -> ok
+-spec dialyze(Config::#config{}, File::string()) -> ok.
+dialyze(Config, File) ->
+ Plt = existing_plt_path(Config, File),
case dialyzer:plt_info(Plt) of
{ok, _} ->
- try dialyzer:run([{files_rec, ["ebin"]}, {init_plt, Plt}]) of
+ FromSrc = proplists:get_bool(src, rebar_config:get(Config,
+ dialyzer_opts,
+ [])),
+ DialyzerOpts0 = case FromSrc of
+ true ->
+ [{files_rec, ["src"]}, {init_plt, Plt},
+ {from, src_code}];
+ false ->
+ [{files_rec, ["ebin"]}, {init_plt, Plt}]
+ end,
+ WarnOpts = warnings(Config),
+ DialyzerOpts = case WarnOpts of
+ [] -> DialyzerOpts0;
+ _ -> [{warnings, WarnOpts}|DialyzerOpts0]
+ end,
+ ?DEBUG("DialyzerOpts: ~p~n", [DialyzerOpts]),
+ try dialyzer:run(DialyzerOpts) of
Warnings -> output_warnings(Warnings)
catch
throw:{dialyzer_error, Reason} ->
?ABORT("~s~n", [Reason])
end;
{error, no_such_file} ->
- ?ABORT("The PLT ~s does not exist. Please perform the build_plt command to ~n"
- "produce the initial PLT. Be aware this operation may take several minutes.", [Plt]);
+ ?ABORT("The PLT ~s does not exist. Please perform the build-plt "
+ "command to ~n"
+ "produce the initial PLT. Be aware that this operation may "
+ "take several minutes.~n", [Plt]);
{error, read_error} ->
?ABORT("Unable to read PLT ~n~n", [Plt]);
{error, not_valid} ->
@@ -80,29 +98,30 @@ analyze(Config, File) ->
ok.
%% @doc Build the PLT.
-%% @spec build_plt(Config::#config{}, File::string()) -> ok
--spec(build_plt(Config::#config{}, File::string()) -> ok).
-build_plt(Config, File) ->
- Plt = plt_path(Config, File),
+%% @spec build-plt(Config::#config{}, File::string()) -> ok
+-spec 'build-plt'(Config::#config{}, File::string()) -> ok.
+'build-plt'(Config, File) ->
+ Plt = new_plt_path(Config, File),
Apps = rebar_app_utils:app_applications(File),
+ ?DEBUG("Build PLT ~s including following apps:~n~p~n", [Plt, Apps]),
Warnings = dialyzer:run([{analysis_type, plt_build},
{files_rec, app_dirs(Apps)},
{output_plt, Plt}]),
case Warnings of
[] ->
- ?INFO("The built PLT can be found in ~s", [Plt]);
+ ?INFO("The built PLT can be found in ~s~n", [Plt]);
_ ->
output_warnings(Warnings)
end,
ok.
%% @doc Check whether the PLT is up-to-date (rebuilding it if not).
-%% @spec check_plt(Config::#config{}, File::string()) -> ok
--spec(check_plt(Config::#config{}, File::string()) -> ok).
-check_plt(Config, File) ->
- Plt = plt_path(Config, File),
+%% @spec check-plt(Config::#config{}, File::string()) -> ok
+-spec 'check-plt'(Config::#config{}, File::string()) -> ok.
+'check-plt'(Config, File) ->
+ Plt = existing_plt_path(Config, File),
try dialyzer:run([{analysis_type, plt_check}, {init_plt, Plt}]) of
[] ->
?CONSOLE("The PLT ~s is up-to-date~n", [Plt]);
@@ -121,14 +140,14 @@ check_plt(Config, File) ->
%% @doc Obtain the library paths for the supplied applications.
%% @spec app_dirs(Apps::[atom()]) -> [string()]
--spec(app_dirs(Apps::[atom()]) -> [string()]).
+-spec app_dirs(Apps::[atom()]) -> [string()].
app_dirs(Apps) ->
[filename:join(Path, "ebin") ||
Path <- lists:map(fun(App) -> code:lib_dir(App) end, Apps), erlang:is_list(Path)].
%% @doc Render the warnings on the console.
%% @spec output_warnings(Warnings::[warning()]) -> 'ok'
--spec(output_warnings(Warnings::[warning()]) -> 'ok').
+-spec output_warnings(Warnings::[warning()]) -> 'ok'.
output_warnings(Warnings) ->
lists:foreach(fun(Warning) ->
?CONSOLE("~s", [dialyzer:format_warning(Warning)])
@@ -136,14 +155,52 @@ output_warnings(Warnings) ->
%% @doc If the plt option is present in rebar.config return its value, otherwise
%% return $HOME/.dialyzer_plt.
-%% @spec plt_path(Config::#config{}, File::string()) -> string()
--spec(plt_path(Config::#config{}, File::string()) -> string()).
-plt_path(Config, File) ->
+%% @spec new_plt_path(Config::#config{}, File::string()) -> string()
+-spec new_plt_path(Config::#config{}, File::string()) -> string().
+new_plt_path(Config, File) ->
AppName = rebar_app_utils:app_name(File),
DialyzerOpts = rebar_config:get(Config, dialyzer_opts, []),
case proplists:get_value(plt, DialyzerOpts) of
undefined ->
- filename:join(os:getenv("HOME"), "." ++ atom_to_list(AppName) ++ "_dialyzer_plt");
+ filename:join(os:getenv("HOME"),
+ "." ++ atom_to_list(AppName) ++ "_dialyzer_plt");
Plt ->
Plt
end.
+
+%% @doc If the plt option is present in rebar.config and the file exists
+%% return its value or if ~/.AppName_dialyzer_plt exists return that.
+%% Otherwise return ~/.dialyzer_plt if it exists or abort.
+%% @spec existing_plt_path(Config::#config{}, File::string()) -> string()
+-spec existing_plt_path(Config::#config{}, File::string()) -> string().
+existing_plt_path(Config, File) ->
+ AppName = rebar_app_utils:app_name(File),
+ DialyzerOpts = rebar_config:get(Config, dialyzer_opts, []),
+ Home = os:getenv("HOME"),
+ case proplists:get_value(plt, DialyzerOpts) of
+ undefined ->
+ AppPlt = filename:join(Home, "." ++ atom_to_list(AppName)
+ ++ "_dialyzer_plt"),
+ case filelib:is_regular(AppPlt) of
+ true ->
+ AppPlt;
+ false ->
+ HomePlt = filename:join(Home, ".dialyzer_plt"),
+ case filelib:is_regular(HomePlt) of
+ true ->
+ HomePlt;
+ false ->
+ ?ABORT("No PLT found~n", [])
+ end
+ end;
+ Plt ->
+ Plt
+ end.
+
+%% @doc If the warnings option is present in rebar.config return its value,
+%% otherwise return [].
+%% @spec warnings(Config::#config{}) -> list().
+-spec warnings(Config::#config{}) -> list().
+warnings(Config) ->
+ DialyzerOpts = rebar_config:get(Config, dialyzer_opts, []),
+ proplists:get_value(warnings, DialyzerOpts, []).