@ -14,6 +14,7 @@
- define ( PROVIDER , dialyzer ) .
- define ( DEPS , [ compile ] ) .
- define ( PLT_PREFIX , " rebar3 " ) .
% % == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == =
% % Public API
@ -39,24 +40,32 @@ desc() ->
" This command will build, and keep up-to-date, a suitable PLT and will use "
" it to carry out success typing analysis on the current project. \n "
" \n "
" The following (optional) configurations can be added to a rebar.config: \n "
" `dialyzer_warnings` - a list of dialyzer warnings \n "
" `dialyzer_plt` - the PLT file to use \n "
" `dialyzer_plt_apps` - a list of applications to include in the PLT file* \n "
" `dialyzer_plt_warnings` - display warnings when updating a PLT file "
" (boolean) \n "
" `dialyzer_base_plt` - the base PLT file to use** \n "
" `dialyzer_base_plt_dir` - the base PLT directory** \n "
" `dialyzer_base_plt_apps` - a list of applications to include in the base "
" PLT file** \n "
" The following (optional) configurations can be added to a `proplist` of "
" 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_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 "
" `base_plt_apps` - a list of applications to include in the base "
" 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 "
" `base_plt_prefix` - the prefix to the base PLT file, defaults to "
" \" 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 "
" **The base PLT is a PLT containing the core OTP applications often "
" required for a project's PLT. One base PLT is created per OTP version and "
" stored in `dialyzer_base_plt_dir` (defaults to $HOME/.rebar3/). A base "
" PLT is used to create a project's initial PLT. " .
" **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 " .
short_desc ( ) - >
" Run the Dialyzer analyzer on the project. " .
@ -65,7 +74,7 @@ short_desc() ->
do ( State ) - >
? INFO ( " Dialyzer starting, this may take a while... " , [ ] ) ,
code : add_pathsa ( rebar_state : code_paths ( State , all_deps ) ) ,
Plt = get_plt_location ( State ) ,
Plt = get_plt ( State ) ,
try
do ( State , Plt )
@ -97,13 +106,19 @@ format_error(Reason) ->
% % Internal functions
get_plt_location ( State ) - >
BaseDir = rebar_dir : base_dir ( State ) ,
DefaultPlt = filename : join ( BaseDir , default_plt ( ) ) ,
rebar_state : get ( State , dialyzer_plt , DefaultPlt ) .
get_plt ( State ) - >
Prefix = get_config ( State , plt_prefix , ? PLT_PREFIX ) ,
Name = plt_name ( Prefix ) ,
case get_config ( State , plt_location , local ) of
local - >
BaseDir = rebar_dir : base_dir ( State ) ,
filename : join ( BaseDir , Name ) ;
Dir - >
filename : join ( Dir , Name )
end .
default_plt ( ) - >
rebar_utils : otp_release ( ) ++ " .plt " .
plt_name ( Prefix ) - >
Prefix ++ " _ " ++ rebar_utils : otp_release ( ) ++ " _ plt" .
do ( State , Plt ) - >
Output = get_output_file ( State ) ,
@ -151,9 +166,8 @@ do_update_proj_plt(State, Plt, Output) ->
end .
proj_plt_files ( State ) - >
BasePltApps = rebar_state : get ( State , dialyzer_base_plt_apps ,
default_plt_apps ( ) ) ,
PltApps = rebar_state : get ( State , dialyzer_plt_apps , [ ] ) ,
BasePltApps = get_config ( State , base_plt_apps , default_plt_apps ( ) ) ,
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 ) .
@ -259,16 +273,17 @@ add_plt(State, Plt, Output, Files) ->
run_plt ( State , Plt , Output , plt_add , Files ) .
run_plt ( State , Plt , Output , Analysis , Files ) - >
GetWarnings = rebar_state : get ( State , dialyzer_pl t_warnings, false ) ,
GetWarnings = get_config ( State , ge t_warnings, false ) ,
Opts = [ { analysis_type , Analysis } ,
{ get_warnings , GetWarnings } ,
{ init_plt , Plt } ,
{ output_plt , Plt } ,
{ from , byte_code } ,
{ files , Files } ] ,
run_dialyzer ( State , Opts , Output ) .
build_proj_plt ( State , Plt , Output , Files ) - >
BasePlt = get_base_plt_location ( State ) ,
BasePlt = get_base_plt ( State ) ,
? INFO ( " Updating base plt... " , [ ] ) ,
BaseFiles = base_plt_files ( State ) ,
{ BaseWarnings , State1 } = update_base_plt ( State , BasePlt , Output , BaseFiles ) ,
@ -285,15 +300,19 @@ build_proj_plt(State, Plt, Output, Files) ->
throw ( { dialyzer_error , Error } )
end .
get_base_plt_location ( State ) - >
GlobalCacheDir = rebar_dir : global_cache_dir ( State ) ,
BaseDir = rebar_state : get ( State , dialyzer_base_plt_dir , GlobalCacheDir ) ,
BasePlt = rebar_state : get ( State , dialyzer_base_plt , default_plt ( ) ) ,
filename : join ( BaseDir , BasePlt ) .
get_base_plt ( State ) - >
Prefix = get_config ( State , base_plt_prefix , ? PLT_PREFIX ) ,
Name = plt_name ( Prefix ) ,
case get_config ( State , base_plt_location , global ) of
global - >
GlobalCacheDir = rebar_dir : global_cache_dir ( State ) ,
filename : join ( GlobalCacheDir , Name ) ;
Dir - >
filename : join ( Dir , Name )
end .
base_plt_files ( State ) - >
BasePltApps = rebar_state : get ( State , dialyzer_base_plt_apps ,
default_plt_apps ( ) ) ,
BasePltApps = get_config ( State , base_plt_apps , default_plt_apps ( ) ) ,
Apps = rebar_state : project_apps ( State ) ,
get_plt_files ( BasePltApps , Apps ) .
@ -308,7 +327,7 @@ update_base_plt(State, BasePlt, Output, BaseFiles) ->
build_plt ( State , Plt , Output , Files ) - >
? INFO ( " Adding ~b files to ~p ... " , [ length ( Files ) , Plt ] ) ,
GetWarnings = rebar_state : get ( State , dialyzer_pl t_warnings, false ) ,
GetWarnings = get_config ( State , ge t_warnings, false ) ,
Opts = [ { analysis_type , plt_build } ,
{ get_warnings , GetWarnings } ,
{ output_plt , Plt } ,
@ -349,7 +368,7 @@ run_dialyzer(State, Opts, Output) ->
% % dialyzer may return callgraph warnings when get_warnings is false
case proplists : get_bool ( get_warnings , Opts ) of
true - >
WarningsList = rebar_state : get ( State , dialyzer_ warnings, [ ] ) ,
WarningsList = get_config ( State , warnings , [ ] ) ,
Opts2 = [ { warnings , WarningsList } ,
{ check_plt , false } |
Opts ] ,
@ -411,3 +430,7 @@ no_warnings() ->
no_contracts ,
no_behaviours ,
no_undefined_callbacks ] .
get_config ( State , Key , Default ) - >
Config = rebar_state : get ( State , dialyzer , [ ] ) ,
proplists : get_value ( Key , Config , Default ) .