summaryrefslogtreecommitdiff
path: root/lib/dialyzer/src/dialyzer_cl.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer/src/dialyzer_cl.erl')
-rw-r--r--lib/dialyzer/src/dialyzer_cl.erl225
1 files changed, 126 insertions, 99 deletions
diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl
index 25fdef948e..732873056e 100644
--- a/lib/dialyzer/src/dialyzer_cl.erl
+++ b/lib/dialyzer/src/dialyzer_cl.erl
@@ -23,7 +23,9 @@
-module(dialyzer_cl).
--export([start/1]).
+-export([start/1,
+ start_report_modules_analyzed/1,
+ start_report_modules_changed_and_analyzed/1]).
-include("dialyzer.hrl").
-include_lib("kernel/include/file.hrl"). % needed for #file_info{}
@@ -33,12 +35,8 @@
code_server = none :: 'none'
| dialyzer_codeserver:codeserver(),
erlang_mode = false :: boolean(),
- external_calls = [] :: [{mfa(),
- {file:filename(),
- erl_anno:location()}}],
- external_types = [] :: [{mfa(),
- {file:filename(),
- erl_anno:location()}}],
+ external_calls = [] :: [{mfa(), warning_info()}],
+ external_types = [] :: [{mfa(), warning_info()}],
legal_warnings = ordsets:new() :: [dial_warn_tag()],
mod_deps = dict:new() :: dialyzer_callgraph:mod_deps(),
output = standard_io :: io:device(),
@@ -57,14 +55,26 @@
-spec start(#options{}) -> {dial_ret(), [dial_warning()]}.
-start(#options{analysis_type = AnalysisType} = Options) ->
+start(Opts) ->
+ {{Ret,Warns}, _ModulesAnalyzed} = start_report_modules_analyzed(Opts),
+ {Ret,Warns}.
+
+-spec start_report_modules_analyzed(#options{}) -> {{dial_ret(), [dial_warning()]}, [module()]}.
+
+start_report_modules_analyzed(Opts) ->
+ {{Ret,Warns}, _ModulesChanged, ModulesAnalyzed} = start_report_modules_changed_and_analyzed(Opts),
+ {{Ret,Warns}, ModulesAnalyzed}.
+
+-spec start_report_modules_changed_and_analyzed(#options{}) -> {{dial_ret(), [dial_warning()]}, undefined | [module()], [module()]}.
+
+start_report_modules_changed_and_analyzed(#options{analysis_type = AnalysisType} = Options) ->
process_flag(trap_exit, true),
case AnalysisType of
plt_check -> check_plt(Options);
plt_build -> build_plt(Options);
plt_add -> add_to_plt(Options);
plt_remove -> remove_from_plt(Options);
- succ_typings -> do_analysis(Options)
+ succ_typings -> enrich_with_modules_changed(do_analysis(Options), undefined)
end.
%%--------------------------------------------------------------------
@@ -72,9 +82,9 @@ start(#options{analysis_type = AnalysisType} = Options) ->
build_plt(Opts) ->
Opts1 = init_opts_for_build(Opts),
Files = get_files_from_opts(Opts1),
- Md5 = dialyzer_plt:compute_md5_from_files(Files),
- PltInfo = #plt_info{files = Md5, mod_deps = dict:new()},
- do_analysis(Files, Opts1, dialyzer_plt:new(), PltInfo).
+ Md5 = dialyzer_cplt:compute_md5_from_files(Files),
+ PltInfo = #plt_info{files = Md5},
+ enrich_with_modules_changed(do_analysis(Files, Opts1, dialyzer_plt:new(), PltInfo), undefined).
init_opts_for_build(Opts) ->
case Opts#options.output_plt =:= none of
@@ -95,7 +105,16 @@ init_opts_for_build(Opts) ->
add_to_plt(Opts) ->
Opts1 = init_opts_for_add(Opts),
AddFiles = get_files_from_opts(Opts1),
- plt_common(Opts1, [], AddFiles).
+ case Opts1#options.init_plts of
+ [] -> plt_common(Opts1, [], AddFiles);
+ [_] -> plt_common(Opts1, [], AddFiles);
+ PltFiles ->
+ Plts = [dialyzer_cplt:from_file(F) || F <- PltFiles],
+ % Check merge safety
+ _ = dialyzer_cplt:merge_plts_or_report_conflicts(PltFiles, Plts),
+ _ = [plt_common(Opts#options{init_plts=[Plt]}, [], AddFiles) || Plt <- PltFiles],
+ {{?RET_NOTHING_SUSPICIOUS, []}, [], []}
+ end.
init_opts_for_add(Opts) ->
case Opts#options.output_plt =:= none of
@@ -116,8 +135,6 @@ init_opts_for_add(Opts) ->
end
end.
-%%--------------------------------------------------------------------
-
check_plt(#options{init_plts = []} = Opts) ->
Opts1 = init_opts_for_check(Opts),
report_check(Opts1),
@@ -132,10 +149,12 @@ check_plt_aux([_] = Plt, Opts) ->
plt_common(Opts2, [], []);
check_plt_aux([Plt|Plts], Opts) ->
case check_plt_aux([Plt], Opts) of
- {?RET_NOTHING_SUSPICIOUS, []} -> check_plt_aux(Plts, Opts);
- {?RET_DISCREPANCIES, Warns} ->
- {_RET, MoreWarns} = check_plt_aux(Plts, Opts),
- {?RET_DISCREPANCIES, Warns ++ MoreWarns}
+ {{?RET_NOTHING_SUSPICIOUS, []}, ModulesChanged, ModulesAnalyzed} ->
+ {{Ret, Warns}, MoreModulesChanged, MoreModulesAnalyzed} = check_plt_aux(Plts, Opts),
+ {{Ret, Warns}, ordsets:union(ModulesChanged, MoreModulesChanged), ordsets:union(ModulesAnalyzed, MoreModulesAnalyzed)};
+ {{?RET_DISCREPANCIES, Warns}, ModulesChanged, ModulesAnalyzed} ->
+ {{_RET, MoreWarns}, MoreModulesChanged, MoreModulesAnalyzed} = check_plt_aux(Plts, Opts),
+ {{?RET_DISCREPANCIES, Warns ++ MoreWarns}, ordsets:union(ModulesChanged, MoreModulesChanged), ordsets:union(ModulesAnalyzed, MoreModulesAnalyzed)}
end.
init_opts_for_check(Opts) ->
@@ -145,6 +164,7 @@ init_opts_for_check(Opts) ->
Plt -> Plt
end,
[OutputPlt] = InitPlt,
+
Opts#options{files = [],
files_rec = [],
analysis_type = plt_check,
@@ -198,43 +218,49 @@ plt_common(#options{init_plts = [InitPlt]} = Opts, RemoveFiles, AddFiles) ->
quiet -> ok;
_ -> io:put_chars(" yes\n")
end,
- {?RET_NOTHING_SUSPICIOUS, []};
+ {{?RET_NOTHING_SUSPICIOUS, []}, [], []};
{old_version, Md5} ->
- PltInfo = #plt_info{files = Md5, mod_deps = dict:new()},
+ PltInfo = #plt_info{files = Md5},
Files = [F || {F, _} <- Md5],
- do_analysis(Files, Opts, dialyzer_plt:new(), PltInfo);
+ enrich_with_modules_changed(do_analysis(Files, Opts, dialyzer_plt:new(), PltInfo), undefined);
{differ, Md5, DiffMd5, ModDeps} ->
report_failed_plt_check(Opts, DiffMd5),
- {AnalFiles, RemovedMods, ModDeps1} =
+ {AnalFiles, RemovedMods, ModDeps1} =
expand_dependent_modules(Md5, DiffMd5, ModDeps),
Plt = clean_plt(InitPlt, RemovedMods),
+ ChangedOrRemovedMods = [ChangedOrRemovedMod || {_, ChangedOrRemovedMod} <- DiffMd5],
case AnalFiles =:= [] of
true ->
%% Only removed stuff. Just write the PLT.
- dialyzer_plt:to_file(Opts#options.output_plt, Plt, ModDeps,
- #plt_info{files = Md5, mod_deps = ModDeps}),
- {?RET_NOTHING_SUSPICIOUS, []};
+ dialyzer_cplt:to_file(Opts#options.output_plt, Plt, ModDeps1, #plt_info{files=Md5, mod_deps=ModDeps1}),
+ {{?RET_NOTHING_SUSPICIOUS, []}, ChangedOrRemovedMods, []};
false ->
- do_analysis(AnalFiles, Opts, Plt, #plt_info{files = Md5, mod_deps = ModDeps1})
+ enrich_with_modules_changed(do_analysis(AnalFiles, Opts, Plt, #plt_info{files=Md5, mod_deps=ModDeps1}), ChangedOrRemovedMods)
end;
{error, no_such_file} ->
- Msg = io_lib:format("Could not find the PLT: ~ts\n~s",
+ Msg = io_lib:format("Could not find the PLT: ~ts~n~s",
[InitPlt, default_plt_error_msg()]),
cl_error(Msg);
{error, not_valid} ->
- Msg = io_lib:format("The file: ~ts is not a valid PLT file\n~s",
+ Msg = io_lib:format("The file: ~ts is not a valid PLT file~n~s",
[InitPlt, default_plt_error_msg()]),
cl_error(Msg);
{error, read_error} ->
- Msg = io_lib:format("Could not read the PLT: ~ts\n~s",
+ Msg = io_lib:format("Could not read the PLT: ~ts~n~s",
[InitPlt, default_plt_error_msg()]),
cl_error(Msg);
{error, {no_file_to_remove, F}} ->
- Msg = io_lib:format("Could not remove the file ~ts from the PLT: ~ts\n",
+ Msg = io_lib:format("Could not remove the file ~ts from the PLT: ~ts~n",
[F, InitPlt]),
cl_error(Msg)
end.
+-spec enrich_with_modules_changed({{Ret :: dial_ret(), Warns :: [dial_warning()]}, Analyzed :: [module()]}, Changed :: undefined | [module()]) ->
+ {{dial_ret(), [dial_warning()]}, Changed :: undefined | [module()], Analyzed :: [module()]}.
+
+enrich_with_modules_changed({{Ret,Warns}, Analyzed}, Changed) ->
+ {{Ret,Warns}, Changed, Analyzed}.
+
default_plt_error_msg() ->
"Use the options:\n"
" --build_plt to build a new PLT; or\n"
@@ -252,7 +278,7 @@ default_plt_error_msg() ->
%%--------------------------------------------------------------------
check_plt(#options{init_plts = [Plt]} = Opts, RemoveFiles, AddFiles) ->
- case dialyzer_plt:check_plt(Plt, RemoveFiles, AddFiles) of
+ case dialyzer_cplt:check_plt(Plt, RemoveFiles, AddFiles) of
{old_version, _MD5} = OldVersion ->
report_old_version(Opts),
OldVersion;
@@ -282,7 +308,7 @@ report_old_version(#options{report_mode = ReportMode, init_plts = [InitPlt]}) ->
[InitPlt])
end.
-report_failed_plt_check(#options{analysis_type = AnalType,
+report_failed_plt_check(#options{analysis_type = AnalType,
report_mode = ReportMode}, DiffMd5) ->
case AnalType =:= plt_check of
true ->
@@ -349,10 +375,10 @@ report_md5_diff(List) ->
%%--------------------------------------------------------------------
get_default_init_plt() ->
- [dialyzer_plt:get_default_plt()].
+ [dialyzer_cplt:get_default_cplt_filename()].
get_default_output_plt() ->
- dialyzer_plt:get_default_plt().
+ dialyzer_cplt:get_default_cplt_filename().
%%--------------------------------------------------------------------
@@ -367,11 +393,11 @@ do_analysis(Options) ->
case Options#options.init_plts of
[] -> do_analysis(Files, Options, dialyzer_plt:new(), none);
PltFiles ->
- Plts = [dialyzer_plt:from_file(F) || F <- PltFiles],
- Plt = dialyzer_plt:merge_plts_or_report_conflicts(PltFiles, Plts),
+ Plts = [dialyzer_cplt:from_file(F) || F <- PltFiles],
+ Plt = dialyzer_cplt:merge_plts_or_report_conflicts(PltFiles, Plts),
do_analysis(Files, Options, Plt, none)
end.
-
+
do_analysis(Files, Options, Plt, PltInfo) ->
assert_writable(Options#options.output_plt),
report_analysis_start(Options),
@@ -381,7 +407,8 @@ do_analysis(Files, Options, Plt, PltInfo) ->
output_plt = Options#options.output_plt,
plt_info = PltInfo,
erlang_mode = Options#options.erlang_mode,
- report_mode = Options#options.report_mode},
+ report_mode = Options#options.report_mode
+ },
AnalysisType = convert_analysis_type(Options#options.analysis_type,
Options#options.get_warnings),
InitAnalysis = #analysis{type = AnalysisType,
@@ -393,23 +420,19 @@ do_analysis(Files, Options, Plt, PltInfo) ->
plt = Plt,
use_contracts = Options#options.use_contracts,
callgraph_file = Options#options.callgraph_file,
+ mod_deps_file = Options#options.mod_deps_file,
solvers = Options#options.solvers},
State3 = start_analysis(State2, InitAnalysis),
{T1, _} = statistics(wall_clock),
- Return = cl_loop(State3),
+ RetAndWarns = cl_loop(State3),
{T2, _} = statistics(wall_clock),
report_elapsed_time(T1, T2, Options),
- Return.
-
-convert_analysis_type(plt_check, true) -> succ_typings;
-convert_analysis_type(plt_check, false) -> plt_build;
-convert_analysis_type(plt_add, true) -> succ_typings;
-convert_analysis_type(plt_add, false) -> plt_build;
-convert_analysis_type(plt_build, true) -> succ_typings;
-convert_analysis_type(plt_build, false) -> plt_build;
-convert_analysis_type(plt_remove, true) -> succ_typings;
-convert_analysis_type(plt_remove, false) -> plt_build;
-convert_analysis_type(succ_typings, _) -> succ_typings.
+ {RetAndWarns, lists:usort([path_to_mod(F) || F <- Files])}.
+
+-spec convert_analysis_type(anal_type1(), boolean()) -> succ_typings | plt_build.
+convert_analysis_type(succ_typings, _) -> succ_typings;
+convert_analysis_type(_, true) -> succ_typings;
+convert_analysis_type(_, false) -> plt_build.
%%--------------------------------------------------------------------
@@ -428,14 +451,13 @@ check_if_writable(PltFile) ->
true -> is_writable_file_or_dir(PltFile);
false ->
case filelib:is_dir(PltFile) of
- true -> false;
- false ->
- DirName = filename:dirname(PltFile),
- case filelib:is_dir(DirName) of
+ true -> false;
+ false ->
+ DirName = filename:dirname(PltFile),
+ case filelib:is_dir(DirName) of
false ->
case filelib:ensure_dir(PltFile) of
ok ->
- io:format(" Creating ~ts as it did not exist...~n", [DirName]),
true;
{error, _} ->
false
@@ -458,7 +480,7 @@ is_writable_file_or_dir(PltFile) ->
clean_plt(PltFile, RemovedMods) ->
%% Clean the plt from the removed modules.
- Plt = dialyzer_plt:from_file(PltFile),
+ Plt = dialyzer_cplt:from_file(PltFile),
sets:fold(fun(M, AccPlt) -> dialyzer_plt:delete_module(AccPlt, M) end,
Plt, RemovedMods).
@@ -469,9 +491,9 @@ expand_dependent_modules(Md5, DiffMd5, ModDeps) ->
BigList = sets:to_list(BigSet),
ExpandedSet = expand_dependent_modules_1(BigList, BigSet, ModDeps),
NewModDeps = dialyzer_callgraph:strip_module_deps(ModDeps, BigSet),
- AnalyzeMods = sets:subtract(ExpandedSet, RemovedMods),
+ AnalyzeMods = sets:subtract(ExpandedSet, RemovedMods),
FilterFun = fun(File) ->
- Mod = list_to_atom(filename:basename(File, ".beam")),
+ Mod = path_to_mod(File),
sets:is_element(Mod, AnalyzeMods)
end,
{[F || {F, _} <- Md5, FilterFun(F)], BigSet, NewModDeps}.
@@ -479,12 +501,12 @@ expand_dependent_modules(Md5, DiffMd5, ModDeps) ->
expand_dependent_modules_1([Mod|Mods], Included, ModDeps) ->
case dict:find(Mod, ModDeps) of
{ok, Deps} ->
- NewDeps = sets:subtract(sets:from_list(Deps), Included),
+ NewDeps = sets:subtract(sets:from_list(Deps), Included),
case sets:size(NewDeps) =:= 0 of
true -> expand_dependent_modules_1(Mods, Included, ModDeps);
- false ->
+ false ->
NewIncluded = sets:union(Included, NewDeps),
- expand_dependent_modules_1(sets:to_list(NewDeps) ++ Mods,
+ expand_dependent_modules_1(sets:to_list(NewDeps) ++ Mods,
NewIncluded, ModDeps)
end;
error ->
@@ -493,6 +515,9 @@ expand_dependent_modules_1([Mod|Mods], Included, ModDeps) ->
expand_dependent_modules_1([], Included, _ModDeps) ->
Included.
+path_to_mod(File) ->
+ list_to_atom(filename:basename(File, ".beam")).
+
new_state() ->
#cl_state{}.
@@ -536,7 +561,7 @@ maybe_close_output_file(State) ->
-define(LOG_CACHE_SIZE, 10).
-%%-spec cl_loop(#cl_state{}) ->
+%%-spec cl_loop(#cl_state{}) ->
cl_loop(State) ->
cl_loop(State, []).
@@ -609,14 +634,15 @@ cl_error(State, Msg) ->
maybe_close_output_file(State),
throw({dialyzer_error, lists:flatten(Msg)}).
-return_value(State = #cl_state{code_server = CodeServer,
- erlang_mode = ErlangMode,
- mod_deps = ModDeps,
- output_plt = OutputPlt,
- plt_info = PltInfo,
- error_location = EOpt,
- stored_warnings = StoredWarnings},
- Plt) ->
+return_value(#cl_state{code_server = CodeServer,
+ erlang_mode = ErlangMode,
+ mod_deps = ModDeps,
+ output_plt = OutputPlt,
+ plt_info = PltInfo,
+ error_location = EOpt,
+ stored_warnings = StoredWarnings}=State,
+ Plt) ->
+ UnknownWarnings = unknown_warnings(State),
%% Just for now:
case CodeServer =:= none of
true ->
@@ -628,9 +654,8 @@ return_value(State = #cl_state{code_server = CodeServer,
true ->
dialyzer_plt:delete(Plt);
false ->
- dialyzer_plt:to_file(OutputPlt, Plt, ModDeps, PltInfo)
+ dialyzer_cplt:to_file(OutputPlt, Plt, ModDeps, PltInfo)
end,
- UnknownWarnings = unknown_warnings(State),
RetValue =
case StoredWarnings =:= [] andalso UnknownWarnings =:= [] of
true -> ?RET_NOTHING_SUSPICIOUS;
@@ -638,18 +663,19 @@ return_value(State = #cl_state{code_server = CodeServer,
end,
case ErlangMode of
false ->
- print_warnings(State),
- print_ext_calls(State),
- print_ext_types(State),
- maybe_close_output_file(State),
+ Fns = [ fun print_warnings/1, fun print_ext_calls/1
+ , fun print_ext_types/1, fun maybe_close_output_file/1],
+ lists:foreach(fun (F) -> F(State) end, Fns),
{RetValue, []};
- true ->
- AllWarnings =
- UnknownWarnings ++ process_warnings(StoredWarnings),
- {RetValue, set_warning_id(AllWarnings, EOpt)}
+ true ->
+ ResultingWarnings = process_warnings(StoredWarnings ++ UnknownWarnings),
+ {RetValue, set_warning_id(ResultingWarnings, EOpt)}
end.
-unknown_warnings(State = #cl_state{legal_warnings = LegalWarnings}) ->
+unknown_warnings(State) ->
+ [Warning || {_M, Warning} <- unknown_warnings_by_module(State)].
+
+unknown_warnings_by_module(#cl_state{legal_warnings = LegalWarnings} = State) ->
case ordsets:is_element(?WARN_UNKNOWN, LegalWarnings) of
true ->
lists:sort(unknown_functions(State)) ++
@@ -657,9 +683,14 @@ unknown_warnings(State = #cl_state{legal_warnings = LegalWarnings}) ->
false -> []
end.
-unknown_functions(#cl_state{external_calls = Calls}) ->
- [{?WARN_UNKNOWN, {File, Location, ''},{unknown_function, MFA}} ||
- {MFA, {File, Location}} <- Calls].
+unknown_functions(#cl_state{ external_calls = Calls
+ , code_server = CodeServer}) ->
+ [{Mod, {?WARN_UNKNOWN, WarningInfo, {unknown_function, MFA}}} || { MFA, WarningInfo = {_, _, {Mod, _, _}=WarnMFA}} <- Calls
+ , not dialyzer_codeserver:is_member_meta_info(WarnMFA, CodeServer)].
+
+unknown_types(#cl_state{external_types = Types}) ->
+ [{Mod, {?WARN_UNKNOWN, WarningInfo, {unknown_type, MFA}}} ||
+ {MFA, WarningInfo = {_, _, {Mod, _, _}}} <- Types].
set_warning_id(Warnings, EOpt) ->
lists:map(fun({Tag, {File, Location, _MorMFA}, Msg}) ->
@@ -695,17 +726,13 @@ print_ext_calls(#cl_state{output = Output,
end
end.
-do_print_ext_calls(Output, [{{M,F,A},{File,Location}}|T], Before) ->
+do_print_ext_calls(Output, [{{M,F,A},{File,Location,_FromMFA}}|T], Before) ->
io:format(Output, "~s~tp:~tp/~p (~ts)\n",
[Before,M,F,A,file_pos(File, Location)]),
do_print_ext_calls(Output, T, Before);
do_print_ext_calls(_, [], _) ->
ok.
-unknown_types(#cl_state{external_types = Types}) ->
- [{?WARN_UNKNOWN, {File, Location, ''},{unknown_type, MFA}} ||
- {MFA, {File, Location}} <- Types].
-
print_ext_types(#cl_state{report_mode = quiet}) ->
ok;
print_ext_types(#cl_state{output = Output,
@@ -731,7 +758,7 @@ print_ext_types(#cl_state{output = Output,
end
end.
-do_print_ext_types(Output, [{{M,F,A},{File,Location}}|T], Before) ->
+do_print_ext_types(Output, [{{M,F,A},{File,Location,_}}|T], Before) ->
io:format(Output, "~s~tp:~tp/~p (~ts)\n",
[Before,M,F,A,file_pos(File, Location)]),
do_print_ext_types(Output, T, Before);
@@ -752,8 +779,8 @@ pos(Line) ->
%% Keep one warning per MFA and File. Often too many warnings otherwise.
%%
limit_unknown(Unknowns) ->
- L = [{{MFA, File}, Line} || {MFA, {File, Line}} <- Unknowns],
- [{MFA, {File, Line}} || {{MFA, File}, [Line|_]} <-
+ L = [{{MFA, File}, {FromMFA, Line}} || {MFA, {File, Line, FromMFA}} <- Unknowns],
+ [{MFA, {File, Line, FromMFA}} || {{MFA, File}, [{FromMFA, Line}|_]} <-
dialyzer_utils:family(L)].
%% Keep one warning per MFA. This is how it used to be before Erlang/OTP 24.
%% limit_unknown(Unknowns) ->
@@ -787,10 +814,11 @@ print_warnings(#cl_state{output = Output,
end.
-spec process_warnings([raw_warning()]) -> [raw_warning()].
-
+
process_warnings(Warnings) ->
- Warnings1 = lists:keysort(2, Warnings), %% Sort on file/location (and m/mfa..)
- remove_duplicate_warnings(Warnings1, []).
+ Warnings1 = lists:keysort(3, Warnings), %% First sort on Warning
+ Warnings2 = lists:keysort(2, Warnings1), %% Sort on file/location (and m/mfa..)
+ remove_duplicate_warnings(Warnings2, []).
remove_duplicate_warnings([Duplicate, Duplicate|Left], Acc) ->
remove_duplicate_warnings([Duplicate|Left], Acc);
@@ -813,7 +841,7 @@ add_files(Files, From) ->
add_files(Files, From, Rec) ->
Files1 = [filename:absname(F) || F <- Files],
- Files2 = ordsets:from_list(Files1),
+ Files2 = ordsets:from_list(Files1),
Dirs = ordsets:filter(fun(X) -> filelib:is_dir(X) end, Files2),
Files3 = ordsets:subtract(Files2, Dirs),
Extension = case From of
@@ -840,9 +868,8 @@ add_file_fun(Extension) ->
start_analysis(State, Analysis) ->
Self = self(),
LegalWarnings = State#cl_state.legal_warnings,
- Fun = fun() ->
+ Fun = fun() ->
dialyzer_analysis_callgraph:start(Self, LegalWarnings, Analysis)
end,
BackendPid = spawn_link(Fun),
State#cl_state{backend_pid = BackendPid}.
-