Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotations rebased #193

Open
wants to merge 91 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
37bb194
Get MFA to Kfun mappings
aggelgian Oct 29, 2021
c702f3b
kmodule api refactor
Dspil Jan 22, 2022
956d5ae
kmodule api updated
Dspil Jan 22, 2022
4c78b6e
kmodule api update
Dspil Jan 22, 2022
18559fa
kmodule api update
Dspil Jan 22, 2022
d676160
utest fixed
Dspil Jan 22, 2022
196c8b2
updated mark unreachable clauses logic
Dspil Jan 26, 2022
b1308b0
bugfix to type_dependent_unreachable annotation stacking
Dspil Jan 26, 2022
d8aadcc
made openset in passing down types fix point computation a queue
Dspil Jan 26, 2022
8ef1360
updated unification algorithm to try to catch unions
Dspil Jan 27, 2022
e3666b1
deconstructed pass_down_types
Dspil Jan 28, 2022
9cc6871
type inference for nested functions
Dspil Jan 29, 2022
11fe091
nested functions supported in maybe_error annotation
Dspil Jan 29, 2022
3b3c608
Tracking master changes
Dspil Feb 10, 2022
1f393b9
added function spec conversion to erl_types
Dspil Feb 10, 2022
691b2b4
refactored cuter_types.erl
Dspil Feb 11, 2022
57b0cb5
name change to parse_specs
Dspil Feb 11, 2022
45e84ae
Remove unnecessary changes
Dspil Feb 11, 2022
364d844
Added unit test file for convert_specs
Dspil Feb 11, 2022
1cb83ef
Verbose printing of the MFA specs
aggelgian Feb 12, 2022
c08e7b0
Add spec assertions
aggelgian Feb 12, 2022
6e6b8ce
Rename conver_specs to specs_as_erl_types
aggelgian Feb 12, 2022
1a41999
Reverse the Line-Type tuples for consistency
aggelgian Feb 12, 2022
1bbf420
Refactor the extraction of type definitions from a kmodule.
aggelgian Feb 12, 2022
deaa7c3
Rename the names for the fix computation
aggelgian Feb 12, 2022
ba8b6c3
Add examples with remote types
aggelgian Feb 12, 2022
f12a2d6
Rename unhandled to openset
aggelgian Feb 12, 2022
1a1cf7d
Remove the Change variable
aggelgian Feb 12, 2022
c49ded6
Refactor specs_as_erl_types_fix
aggelgian Feb 12, 2022
33feb42
Rerun the module again
aggelgian Feb 12, 2022
cedbfee
Remove the inner fixpoint
aggelgian Feb 12, 2022
60e417c
Fix remote types
aggelgian Feb 12, 2022
5e20572
Compute the specs of a module
aggelgian Feb 12, 2022
bdde60c
Refactor the update of RecDict
aggelgian Feb 12, 2022
00fbab6
Add an example with a bounded fun
aggelgian Feb 12, 2022
b1a21f4
Refactor removal of bounded funs
aggelgian Feb 12, 2022
c8cfc8e
Refactor record substitution in specs.
aggelgian Feb 12, 2022
057eb9c
Update comments
aggelgian Feb 12, 2022
60d8d88
Refactor function clause conversion to erl_types
aggelgian Feb 12, 2022
dc2a57a
Filtered variable renamed to ExpTypes
Dspil Feb 14, 2022
6c39131
better use of erl_types api in cuter_types_test
Dspil Feb 14, 2022
82a12c3
Renamed examples_for_type_analysis* to examples_for_spec_conversion*
Dspil Feb 14, 2022
53f7631
added function spec conversion to erl_types
Dspil Feb 10, 2022
188a30b
Remove unnecessary changes
Dspil Feb 11, 2022
111cb5d
Added unit test file for convert_specs
Dspil Feb 11, 2022
f2c64ec
Verbose printing of the MFA specs
aggelgian Feb 12, 2022
daa490c
Add spec assertions
aggelgian Feb 12, 2022
13ae42c
Rename conver_specs to specs_as_erl_types
aggelgian Feb 12, 2022
21a922d
Reverse the Line-Type tuples for consistency
aggelgian Feb 12, 2022
eb8194f
Refactor the extraction of type definitions from a kmodule.
aggelgian Feb 12, 2022
4afdaac
Rename the names for the fix computation
aggelgian Feb 12, 2022
91a2003
Add examples with remote types
aggelgian Feb 12, 2022
613253d
Rename unhandled to openset
aggelgian Feb 12, 2022
5047114
Remove the Change variable
aggelgian Feb 12, 2022
358e075
Refactor specs_as_erl_types_fix
aggelgian Feb 12, 2022
10f76c0
Rerun the module again
aggelgian Feb 12, 2022
a378ab3
Remove the inner fixpoint
aggelgian Feb 12, 2022
55a136b
Fix remote types
aggelgian Feb 12, 2022
3478003
Compute the specs of a module
aggelgian Feb 12, 2022
51b2fbb
Refactor the update of RecDict
aggelgian Feb 12, 2022
728884d
Add an example with a bounded fun
aggelgian Feb 12, 2022
035bc06
Refactor removal of bounded funs
aggelgian Feb 12, 2022
82f8810
Refactor record substitution in specs.
aggelgian Feb 12, 2022
e04b2ed
Update comments
aggelgian Feb 12, 2022
7e39824
Refactor function clause conversion to erl_types
aggelgian Feb 12, 2022
b637f9c
Filtered variable renamed to ExpTypes
Dspil Feb 14, 2022
5baca75
better use of erl_types api in cuter_types_test
Dspil Feb 14, 2022
9818b2e
Renamed examples_for_type_analysis* to examples_for_spec_conversion*
Dspil Feb 14, 2022
d19d0fa
Cleanup tests and simplify assertions
kostis Feb 15, 2022
e4a422a
Resolve conflict
kostis Feb 15, 2022
03cbaf2
Avoid multiple type names for the same type
kostis Feb 15, 2022
6926f9b
Avoid unnecessary type export and simplification
kostis Feb 15, 2022
48c19af
Cleanup and simplify cuter_debug
kostis Feb 15, 2022
1f8b33b
report specs that couldn't be converted to an erl_type
Dspil Feb 15, 2022
35dff54
Merge branch 'erl_types_signatures' of github.com:cuter-testing/cuter…
Dspil Feb 15, 2022
0d4de21
removed unnecessary function mfa_to_string from cuter_types.erl
Dspil Feb 15, 2022
6eff159
moved mfa_to_string/1 from cuter_tests_lib.erl to cuter_types.erl
Dspil Feb 15, 2022
e95f6b1
Code cleanups (and better warning slogan)
kostis Feb 16, 2022
5bd01b8
added temporary call to cuter_types:specs_as_erl_types/1
Dspil Feb 16, 2022
96aa8db
Graceful shutdown during exceptions in initialization
Dspil Feb 16, 2022
0d85883
Print the error message
Dspil Feb 16, 2022
5d7911d
Generalize free variables in bounded funs
Dspil Feb 16, 2022
1532866
Merge branch 'master' into erl_types_signatures
kostis Feb 17, 2022
5be600f
added unit tests for cuter_graphs.erl
Dspil Feb 17, 2022
7116531
Merge branch 'master' into annotations_rebased
Dspil Feb 17, 2022
b7d8038
cuter graphs update
Dspil Mar 17, 2022
3737b74
Merge erl_types_signatures into annotations_rebased
Dspil Apr 7, 2022
15d6a8e
bugfix
Dspil Apr 7, 2022
9e2c56a
changes from eval options pr
Dspil Apr 7, 2022
45b5061
comment and refactor cuter_spec_checker
Dspil May 8, 2022
a0a21bb
more refactoring and comments
Dspil May 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ SRC_MODULES = \
cuter_strategy \
cuter_bfs_strategy \
cuter_metrics \
cuter_config
cuter_config \
cuter_spec_checker \
cuter_graphs \
cuter_maybe_error_annotation \
cuter_type_dependent_functions

UTEST_MODULES = \
cuter_tests_lib \
Expand All @@ -100,7 +104,11 @@ UTEST_MODULES = \
types_and_specs \
types_and_specs2 \
cuter_metrics_tests \
cuter_config_tests
cuter_config_tests \
cuter_graphs_tests \
callgraph_examples \
examples_for_spec_conversion \
examples_for_spec_conversion_pair

FTEST_MODULES = \
bitstr \
Expand Down
3 changes: 3 additions & 0 deletions cuter
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def main():
parser.add_argument("-m", "--metrics", action='store_true', help="report collected metrics")
parser.add_argument("--debug-keep-traces", action='store_true', help="keep execution traces for debugging")
parser.add_argument("--debug-solver-fsm", action='store_true', help="output debug logs for the solver FSM")
parser.add_argument("-ps", "--prune-safe", action='store_true', help="prune safe paths and stop the execution early")

# Parse the arguments
args = parser.parse_args()
Expand Down Expand Up @@ -109,6 +110,8 @@ def main():
opts.append("debug_keep_traces")
if args.debug_solver_fsm:
opts.append("debug_solver_fsm")
if args.prune_safe:
opts.append("prune_safe")
strOpts = ",".join(opts)

# Run CutEr
Expand Down
10 changes: 10 additions & 0 deletions include/cuter_macros.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@
-define(NUM_SOLVERS, number_of_solvers).
%% Sets the number of concurrent concolic execution processes.
-define(NUM_POLLERS, number_of_pollers).
%% Prune safe paths.
-define(PRUNE_SAFE, prune_safe).

-type runtime_options() :: {?Z3_TIMEOUT, pos_integer()}
| ?REPORT_METRICS
Expand All @@ -104,6 +106,7 @@
| {?NUM_SOLVERS, pos_integer()}
| {?NUM_POLLERS, pos_integer()}
| {?WORKING_DIR, file:filename()}
| ?PRUNE_SAFE
.

%%====================================================================
Expand Down Expand Up @@ -156,3 +159,10 @@

%% Empty tag ID
-define(EMPTY_TAG_ID, 0).

%%====================================================================
%% Miscellaneous stored values in cuter config
%%====================================================================

%% Entry point for concolic testing
-define(ENTRY_POINT, entry_point).
31 changes: 20 additions & 11 deletions src/cuter.erl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ run(M, F, As, Depth, Options) ->
Seeds = [{M, F, As, Depth}],
run(Seeds, Options).

-spec run([seed()], options()) -> erroneous_inputs().
-spec run([seed(),...], options()) -> erroneous_inputs().
%% Runs CutEr on multiple units.
run(Seeds, Options) ->
State = state_from_options_and_seeds(Options, Seeds),
Expand Down Expand Up @@ -90,7 +90,8 @@ run_from_file(File, Options) ->
%% The tasks to run during the app initialization.
init_tasks() ->
[fun ensure_exported_entry_points/1,
fun compute_callgraph/1].
fun compute_callgraph/1,
fun annotate_for_possible_errors/1].

-spec init(state()) -> ok | error.
init(State) ->
Expand Down Expand Up @@ -131,10 +132,17 @@ compute_callgraph(State) ->
Mfas = mfas_from_state(State),
cuter_codeserver:calculate_callgraph(State#st.codeServer, Mfas).


mfas_from_state(State) ->
[{M, F, length(As)} || {M, F, As, _} <- State#st.seeds].

annotate_for_possible_errors(State) ->
case cuter_config:fetch(?PRUNE_SAFE) of
{ok, true} ->
cuter_codeserver:annotate_for_possible_errors(State#st.codeServer);
_ ->
ok
end.

%% ----------------------------------------------------------------------------
%% Manage the concolic executions
%% ----------------------------------------------------------------------------
Expand All @@ -146,8 +154,7 @@ start(State) ->
-spec start([seed()], state()) -> state().
start([], State) ->
State;
start([{M, F, As, Depth}|Seeds], State) ->
CodeServer = State#st.codeServer,
start([{M, F, As, Depth}|Seeds], State) -> CodeServer = State#st.codeServer,
Scheduler = State#st.scheduler,
Errors = start_one(M, F, As, Depth, CodeServer, Scheduler),
NewErrors = [{{M, F, length(As)}, Errors}|State#st.errors],
Expand Down Expand Up @@ -242,19 +249,19 @@ stop(State) ->
%% Generate the system state
%% ----------------------------------------------------------------------------

-spec state_from_options_and_seeds(options(), [seed()]) -> state().
-spec state_from_options_and_seeds(options(), [seed(),...]) -> state().
state_from_options_and_seeds(Options, Seeds) ->
process_flag(trap_exit, true),
error_logger:tty(false), %% disable error_logger
ok = cuter_config:start(),
ok = cuter_metrics:start(),
ok = define_metrics(),
enable_debug_config(Options),
enable_runtime_config(Options),
enable_runtime_config(Options, Seeds),
ok = cuter_pp:start(),
CodeServer = cuter_codeserver:start(),
SchedPid = cuter_scheduler:start(?DEFAULT_DEPTH, CodeServer),
#st{ codeServer = CodeServer, scheduler = SchedPid, seeds = Seeds }.
#st{codeServer = CodeServer, scheduler = SchedPid, seeds = Seeds}.

define_metrics() ->
define_distribution_metrics().
Expand All @@ -268,8 +275,8 @@ enable_debug_config(Options) ->
cuter_config:store(?DEBUG_SMT, proplists:get_bool(?DEBUG_SMT, Options)),
cuter_config:store(?DEBUG_SOLVER_FSM, proplists:get_bool(?DEBUG_SOLVER_FSM, Options)).

-spec enable_runtime_config(options()) -> ok.
enable_runtime_config(Options) ->
-spec enable_runtime_config(options(), [seed(),...]) -> ok.
enable_runtime_config(Options, [{M, F, I, _D}|_]) ->
{ok, CWD} = file:get_cwd(),
cuter_config:store(?WORKING_DIR,
cuter_lib:get_tmp_dir(proplists:get_value(?WORKING_DIR, Options, CWD))),
Expand All @@ -287,7 +294,9 @@ enable_runtime_config(Options) ->
cuter_config:store(?SORTED_ERRORS, proplists:get_bool(?SORTED_ERRORS, Options)),
cuter_config:store(?WHITELISTED_MFAS, whitelisted_mfas(Options)),
cuter_config:store(?NUM_SOLVERS, proplists:get_value(?NUM_SOLVERS, Options, ?ONE)),
cuter_config:store(?NUM_POLLERS, proplists:get_value(?NUM_POLLERS, Options, ?ONE)).
cuter_config:store(?NUM_POLLERS, proplists:get_value(?NUM_POLLERS, Options, ?ONE)),
cuter_config:store(?PRUNE_SAFE, proplists:get_bool(?PRUNE_SAFE, Options)),
cuter_config:store(?ENTRY_POINT, {M, F, length(I)}).

verbosity_level(Options) ->
Default = cuter_pp:default_reporting_level(),
Expand Down
26 changes: 12 additions & 14 deletions src/cuter_cerl.erl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
node_types_conditions/0, node_types_conditions_nocomp/0,
node_types_paths/0, node_types_paths_nocomp/0]).
%% kfun API.
-export([kfun/2, kfun_code/1, kfun_is_exported/1]).
-export([kfun/2, kfun_code/1, kfun_is_exported/1, kfun_update_code/2]).
%% kmodule API.
-export([kmodule_spec_forms/1, kmodule_record_forms/1, kmodule_type_forms/1, kmodule_exported_types/1, kmodule_name/1, destroy_kmodule/1, kmodule/3, kmodule_kfun/2, kmodule_mfa_spec/2,
kmodule_specs/1, kmodule_types/1, kmodule_update_kfun/3, kmodule_mfas_with_kfuns/1,
Expand All @@ -25,13 +25,12 @@

-include("include/cuter_macros.hrl").

-export_type([compile_error/0, cerl_attr_spec/0, cerl_attr_type/0,
-export_type([compile_error/0, cerl_spec_form/0, cerl_attr_type/0,
cerl_bounded_func/0, cerl_constraint/0, cerl_func/0,
cerl_recdef/0, cerl_record_field/0, cerl_spec/0,
cerl_record_field/0, cerl_spec/0,
cerl_spec_func/0, cerl_type/0, cerl_typedef/0,
cerl_type_record_field/0, node_types/0,
tagID/0, tag/0, tag_generator/0, visited_tags/0,
spec_info/0]).
tagID/0, tag/0, tag_generator/0, visited_tags/0]).

-export_type([extracted_record_form/0, extracted_type_form/0]).

Expand Down Expand Up @@ -70,17 +69,15 @@
-type name() :: atom().
-type fa() :: {name(), arity()}.
-type cerl_attr_type() :: cerl_recdef() | cerl_typedef().
-type cerl_attr_spec() :: cerl_specdef().

-type cerl_recdef() :: {name(), [cerl_record_field()]} % for OTP 19.x
| {{'record', name()}, [cerl_record_field()], []}. % for OTP 18.x or earlier
-type cerl_recdef() :: {name(), [cerl_record_field()]}.
-type cerl_record_field() :: cerl_untyped_record_field() | cerl_typed_record_field().
-type cerl_untyped_record_field() :: {'record_field', lineno(), {'atom', lineno(), name()}}
| {'record_field', lineno(), {'atom', lineno(), name()}, any()}.
-type cerl_typed_record_field() :: {'typed_record_field', cerl_untyped_record_field(), cerl_type()}.
-type cerl_typedef() :: {name(), cerl_type(), [cerl_type_var()]}.

-type cerl_specdef() :: {fa(), cerl_spec()}.
-type cerl_spec_form() :: {fa(), cerl_spec()}.
-type cerl_spec() :: [cerl_spec_func(), ...].
-type cerl_spec_func() :: cerl_func() | cerl_bounded_func().

Expand Down Expand Up @@ -273,7 +270,7 @@ is_mfa({M, F, A}) when is_atom(M), is_atom(F), is_integer(A), A >= 0 -> true;
is_mfa(_Mfa) -> false.

%% Returns the unprocessed specs of a kmodule (as forms).
-spec kmodule_spec_forms(kmodule()) -> [cerl:cerl()].
-spec kmodule_spec_forms(kmodule()) -> [cerl_spec_form()].
kmodule_spec_forms(Kmodule) ->
[{spec_forms, SpecsForms}] = ets:lookup(Kmodule, spec_forms),
SpecsForms.
Expand Down Expand Up @@ -310,6 +307,9 @@ kfun_is_exported(#{is_exported := IsExported}) -> IsExported.
-spec kfun_code(kfun()) -> code().
kfun_code(#{code := Code}) -> Code.

-spec kfun_update_code(kfun(), code()) -> kfun().
kfun_update_code(Fun, Code) -> Fun#{code=>Code}.

%% ===================================================================
%% Internal functions
%% ===================================================================
Expand All @@ -320,8 +320,8 @@ extract_exports(M, AST) ->
[mfa_from_var(M, E) || E <- Exports].

extract_exported_types(Mod, Attrs) ->
Filtered = [T || {#c_literal{val = export_type}, #c_literal{val = T}} <- Attrs],
sets:from_list(lists:append([{Mod, Tname, Tarity} || {Tname, Tarity} <- Filtered])).
ExpTypes = lists:append([Ts || {#c_literal{val = export_type}, #c_literal{val = Ts}} <- Attrs]),
sets:from_list([{Mod, Tname, Tarity} || {Tname, Tarity} <- ExpTypes]).

-spec process_fundef({cerl:c_var(), code()}, [mfa()], module(), tag_generator()) -> {mfa(), kfun()}.
process_fundef({FunVar, Def}, Exports, M, TagGen) ->
Expand Down Expand Up @@ -375,8 +375,6 @@ get_abstract_code(Mod, Beam) ->
_ -> throw(cuter_pp:abstract_code_missing(Mod))
end.

-type spec_info() :: cerl_attr_spec().

%% Extracts the record definitions (as forms) from the annotations of a module.
%% The relevant annotations have the following structure in OTP 19.x and newer:
%% {#c_atom{val=record}, #c_literal{val=[{Name, Fields}]}}
Expand Down
51 changes: 43 additions & 8 deletions src/cuter_codeserver.erl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
visit_tag/2, calculate_callgraph/2,
%% Work with module cache
merge_dumped_cached_modules/2, modules_of_dumped_cache/1,
%% Code annotations
annotate_for_possible_errors/1,
%% Access logs
cachedMods_of_logs/1, visitedTags_of_logs/1, tagsAddedNo_of_logs/1,
unsupportedMfas_of_logs/1, loadedMods_of_logs/1]).
Expand All @@ -19,6 +21,8 @@
%% Counter of branches & Tag generator.
-export([get_branch_counter/0, init_branch_counter/0, generate_tag/0]).

-export([convert_specs/1]).

-include("include/cuter_macros.hrl").

-export_type([cached_modules/0, codeserver/0, counter/0, logs/0]).
Expand All @@ -27,7 +31,7 @@
-define(BRANCH_COUNTER_PREFIX, '__branch_count').

-type counter() :: non_neg_integer().
-type cached_module_data() :: any().
-type cached_module_data() :: any(). % XXX: refine
-type cached_modules() :: dict:dict(module(), cached_module_data()).

-type cache() :: ets:tid().
Expand All @@ -46,20 +50,20 @@
}).
-type logs() :: #logs{}.

%% Internal type declarations
%% Internal type declarations.
-type load_reply() :: {ok, cuter_cerl:kmodule()} | cuter_cerl:compile_error() | {error, (preloaded | cover_compiled | non_existing)}.
-type spec_reply() :: {ok, cuter_types:erl_spec()} | error.
-type from() :: {pid(), reference()}.

%% Finding the remote dependencies of a spec.
%% Remote dependencies of a spec.
-type remote_type() :: {cuter:mod(), atom(), byte()}.
-type module_deps() :: ordsets:ordset(cuter:mod()).
-type visited_remotes() :: ordsets:ordset(remote_type()).

-type codeserver() :: pid().
-type codeserver_args() :: #{}.

%% Server's state
%% Server's state.
-record(st, {
%% Acts as a reference table for looking up the ETS table that holds a module's extracted code.
%% It stores tuples {Module :: module(), ModuleDb :: ets:tid()}.
Expand Down Expand Up @@ -137,11 +141,20 @@ get_whitelist(CodeServer) ->
calculate_callgraph(CodeServer, Mfas) ->
gen_server:call(CodeServer, {calculate_callgraph, Mfas}).

-spec convert_specs(codeserver()) -> ok.
convert_specs(CodeServer) ->
gen_server:call(CodeServer, convert_specs).

%% Gets the feasible tags.
-spec get_feasible_tags(codeserver(), cuter_cerl:node_types()) -> cuter_cerl:visited_tags().
get_feasible_tags(CodeServer, NodeTypes) ->
gen_server:call(CodeServer, {get_feasible_tags, NodeTypes}).

%% Annotates the code for possible errors.
-spec annotate_for_possible_errors(codeserver()) -> ok.
annotate_for_possible_errors(CodeServer) ->
gen_server:call(CodeServer, annotate_for_possible_errors).

%% ----------------------------------------------------------------------------
%% gen_server callbacks (Server Implementation)
%% ----------------------------------------------------------------------------
Expand Down Expand Up @@ -182,6 +195,7 @@ handle_info(_Msg, State) ->
; (get_whitelist, from(), state()) -> {reply, cuter_mock:whitelist(), state()}
; ({get_feasible_tags, cuter_cerl:node_types()}, from(), state()) -> {reply, cuter_cerl:visited_tags(), state()}
; ({calculate_callgraph, [mfa()]}, from(), state()) -> {reply, ok, state()}
; (annotate_for_possible_errors, from(), state()) -> {reply, ok, state()}
.
handle_call({load, M}, _From, State) ->
{reply, try_load(M, State), State};
Expand Down Expand Up @@ -231,7 +245,28 @@ handle_call({calculate_callgraph, Mfas}, _From, State=#st{whitelist = Whitelist}
end,
cuter_callgraph:foreachModule(LoadFn, Callgraph),
{reply, ok, State#st{callgraph = Callgraph}}
end.
end;
handle_call(annotate_for_possible_errors, _From, State=#st{db = Db}) ->
Fn = fun({_M, Kmodule}, KfunAcc) ->
KfunMappings = cuter_cerl:kmodule_mfas_with_kfuns(Kmodule),
TrivialMergeFn = fun(_K, V1, _V2) -> V1 end,
dict:merge(TrivialMergeFn, KfunAcc, KfunMappings)
end,
Fn2 = fun({_M, Kmodule}, Acc) ->
[Kmodule|Acc]
end,
Kmodules = ets:foldl(Fn2, [], Db),
{ok, EntryPoint} = cuter_config:fetch(?ENTRY_POINT),
MfasToKfuns = ets:foldl(Fn, dict:new(), Db),
MfasToSpecs = cuter_types:specs_as_erl_types(Kmodules),
UpdatedKfuns = cuter_maybe_error_annotation:preprocess(EntryPoint, MfasToKfuns, MfasToSpecs),
RFn = fun({M, F, A}, Kfun, _Acc) ->
[{_M, Kmodule}] = ets:lookup(Db, M),
cuter_cerl:kmodule_update_kfun(Kmodule, {M, F, A}, Kfun)
end,
dict:fold(RFn, ok, UpdatedKfuns),
{reply, ok, State}.


%% gen_server callback : handle_cast/2
-spec handle_cast(stop, state()) -> {stop, normal, state()} | {noreply, state()}
Expand All @@ -254,10 +289,10 @@ handle_cast({visit_tag, Tag}, State=#st{tags = Tags}) ->
-spec load_all_deps_of_spec(cuter_types:stored_spec_value(), module(), cuter_cerl:kmodule(), state()) -> [cuter:mod()].
load_all_deps_of_spec(CerlSpec, Module, Kmodule, State) ->
LocalTypesCache = cuter_cerl:kmodule_types(Kmodule),
% Get the remote dependencies of the spec.
%% Get the remote dependencies of the spec.
ToBeVisited = cuter_types:find_remote_deps_of_spec(CerlSpec, LocalTypesCache),
InitDepMods = ordsets:add_element(Module, ordsets:new()),
% Find iteratively the dependencies of the found dependencies.
%% Find iteratively the dependencies of the found dependencies.
case load_all_deps(ToBeVisited, State, ordsets:new(), InitDepMods) of
error -> [];
{ok, DepMods} -> DepMods
Expand Down Expand Up @@ -285,7 +320,7 @@ load_all_deps([Remote={M, TypeName, Arity}|Rest], State, VisitedRemotes, DepMods
Deps = cuter_types:find_remote_deps_of_type(Type, LocalTypesCache),
%% Queue the ones that we haven't encountered yet.
NewRemotes = [R || R <- Deps,
not ordsets:is_element(R, VisitedRemotes1)],
not ordsets:is_element(R, VisitedRemotes1)],
load_all_deps(NewRemotes ++ Rest, State, VisitedRemotes1, DepMods1)
end;
_Msg ->
Expand Down
Loading