aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer')
-rw-r--r--lib/dialyzer/src/dialyzer_behaviours.erl5
-rw-r--r--lib/dialyzer/src/dialyzer_plt.erl48
-rw-r--r--lib/dialyzer/src/dialyzer_succ_typings.erl41
3 files changed, 47 insertions, 47 deletions
diff --git a/lib/dialyzer/src/dialyzer_behaviours.erl b/lib/dialyzer/src/dialyzer_behaviours.erl
index 127e906135..f86cc3d3d6 100644
--- a/lib/dialyzer/src/dialyzer_behaviours.erl
+++ b/lib/dialyzer/src/dialyzer_behaviours.erl
@@ -92,8 +92,9 @@ get_warnings(Module, [Behaviour|Rest], State, Acc) ->
check_behaviour(Module, Behaviour, #state{plt = Plt} = State, Acc) ->
case dialyzer_plt:lookup_callbacks(Plt, Behaviour) of
- [] -> [{callback_info_missing, [Behaviour]}|Acc];
- Callbacks -> check_all_callbacks(Module, Behaviour, Callbacks, State, Acc)
+ none -> [{callback_info_missing, [Behaviour]}|Acc];
+ {value, Callbacks} ->
+ check_all_callbacks(Module, Behaviour, Callbacks, State, Acc)
end.
check_all_callbacks(_Module, _Behaviour, [], _State, Acc) ->
diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl
index 0c0773e977..35bee913c2 100644
--- a/lib/dialyzer/src/dialyzer_plt.erl
+++ b/lib/dialyzer/src/dialyzer_plt.erl
@@ -87,7 +87,8 @@
exported_types = sets:new() :: set()}).
-record(mini_plt, {info :: ets:tid(),
- contracts :: ets:tid()
+ contracts :: ets:tid(),
+ callbacks :: ets:tid()
}).
-opaque plt() :: #plt{} | #mini_plt{}.
@@ -140,8 +141,6 @@ delete_list(#plt{info = Info, types = Types,
-spec insert_contract_list(plt(), dialyzer_contracts:plt_contracts()) -> plt().
-insert_contract_list(#plt{contracts = Contracts} = PLT, List) ->
- PLT#plt{contracts = table_insert_list(Contracts, List)};
insert_contract_list(#mini_plt{contracts = Contracts} = PLT, List) ->
true = ets:insert(Contracts, List),
PLT.
@@ -154,9 +153,6 @@ insert_callbacks(#plt{callbacks = Callbacks} = Plt, Codeserver) ->
-spec lookup_contract(plt(), mfa_patt()) -> 'none' | {'value', #contract{}}.
-lookup_contract(#plt{contracts = Contracts},
- {M, F, _} = MFA) when is_atom(M), is_atom(F) ->
- table_lookup(Contracts, MFA);
lookup_contract(#mini_plt{contracts = ETSContracts},
{M, F, _} = MFA) when is_atom(M), is_atom(F) ->
ets_table_lookup(ETSContracts, MFA).
@@ -164,15 +160,13 @@ lookup_contract(#mini_plt{contracts = ETSContracts},
-spec lookup_callbacks(plt(), module()) ->
[{mfa(), {{Filename::string(), Line::pos_integer()}, #contract{}}}].
-lookup_callbacks(#plt{callbacks = Callbacks}, Mod) when is_atom(Mod) ->
- table_filter_module(Callbacks, Mod).
+lookup_callbacks(#mini_plt{callbacks = ETSCallbacks}, Mod) when is_atom(Mod) ->
+ ets_table_lookup(ETSCallbacks, Mod).
-type ret_args_types() :: {erl_types:erl_type(), [erl_types:erl_type()]}.
-spec insert_list(plt(), [{mfa() | integer(), ret_args_types()}]) -> plt().
-insert_list(#plt{info = Info} = PLT, List) ->
- PLT#plt{info = table_insert_list(Info, List)};
insert_list(#mini_plt{info = Info} = PLT, List) ->
true = ets:insert(Info, List),
PLT.
@@ -185,8 +179,6 @@ lookup(Plt, {M, F, _} = MFA) when is_atom(M), is_atom(F) ->
lookup(Plt, Label) when is_integer(Label) ->
lookup_1(Plt, Label).
-lookup_1(#plt{info = Info}, MFAorLabel) ->
- table_lookup(Info, MFAorLabel);
lookup_1(#mini_plt{info = Info}, MFAorLabel) ->
ets_table_lookup(Info, MFAorLabel).
@@ -517,12 +509,20 @@ init_md5_list_1(Md5List, [], Acc) ->
-spec get_mini_plt(plt()) -> plt().
-get_mini_plt(#plt{info = Info, contracts = Contracts}) ->
- ETSInfo = ets:new(plt_info, [public]),
- ETSContracts = ets:new(plt_contracts, [public]),
- true = ets:insert(ETSInfo, dict:to_list(Info)),
- true = ets:insert(ETSContracts, dict:to_list(Contracts)),
- #mini_plt{info = ETSInfo, contracts = ETSContracts}.
+get_mini_plt(#plt{info = Info, contracts = Contracts, callbacks = Callbacks}) ->
+ [ETSInfo, ETSContracts, ETSCallbacks] =
+ [ets:new(Name, [public]) || Name <- [plt_info, plt_contracts, plt_callbacks]],
+ CallbackList = dict:to_list(Callbacks),
+ CallbacksByModule =
+ [{M, [Cb || {{M1,_,_},_} = Cb <- CallbackList, M1 =:= M]} ||
+ M <- lists:usort([M || {{M,_,_},_} <- CallbackList])],
+ [true, true] =
+ [ets:insert(ETS, dict:to_list(Data)) ||
+ {ETS, Data} <- [{ETSInfo, Info}, {ETSContracts, Contracts}]],
+ true = ets:insert(ETSCallbacks, CallbacksByModule),
+ #mini_plt{info = ETSInfo, contracts = ETSContracts, callbacks = ETSCallbacks};
+get_mini_plt(undefined) ->
+ undefined.
-spec restore_full_plt(plt(), plt()) -> plt().
@@ -531,7 +531,9 @@ restore_full_plt(#mini_plt{info = ETSInfo, contracts = ETSContracts}, Plt) ->
Contracts = dict:from_list(ets:tab2list(ETSContracts)),
ets:delete(ETSContracts),
ets:delete(ETSInfo),
- Plt#plt{info = Info, contracts = Contracts}.
+ Plt#plt{info = Info, contracts = Contracts};
+restore_full_plt(undefined, undefined) ->
+ undefined.
%%---------------------------------------------------------------------------
%% Edoc
@@ -645,14 +647,6 @@ table_lookup_module(Plt, Mod) ->
false -> {value, List}
end.
-table_filter_module(Plt, Mod) ->
- FunModFilter =
- fun({M, _F, _A}, _Val) -> M =:= Mod;
- ( _Key, _Val) -> false
- end,
- ModCallbacks = dict:filter(FunModFilter, Plt),
- dict:to_list(ModCallbacks).
-
table_all_modules(Plt) ->
Fold =
fun({M, _F, _A}, _Val, Acc) -> sets:add_element(M, Acc);
diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl
index 38f3d47353..4d813e06bb 100644
--- a/lib/dialyzer/src/dialyzer_succ_typings.erl
+++ b/lib/dialyzer/src/dialyzer_succ_typings.erl
@@ -126,13 +126,16 @@ get_refined_success_typings(SCCs, State) ->
get_warnings(Callgraph, Plt, DocPlt, Codeserver, NoWarnUnused, Parent) ->
InitState =
init_state_and_get_success_typings(Callgraph, Plt, Codeserver, Parent),
- NewState =
- InitState#st{no_warn_unused = NoWarnUnused,
- plt = dialyzer_plt:restore_full_plt(InitState#st.plt, Plt)},
+ NewState = InitState#st{no_warn_unused = NoWarnUnused},
Mods = dialyzer_callgraph:modules(NewState#st.callgraph),
CWarns = dialyzer_contracts:get_invalid_contract_warnings(Mods, Codeserver,
NewState#st.plt),
- get_warnings_from_modules(Mods, NewState, DocPlt, CWarns).
+ MiniDocPlt = dialyzer_plt:get_mini_plt(DocPlt),
+ {Warnings, FinalPlt, FinalDocPlt} =
+ get_warnings_from_modules(Mods, NewState, MiniDocPlt, CWarns),
+ {postprocess_warnings(Warnings, Codeserver),
+ dialyzer_plt:restore_full_plt(FinalPlt, Plt),
+ dialyzer_plt:restore_full_plt(FinalDocPlt, DocPlt)}.
get_warnings_from_modules([M|Ms], State, DocPlt, Acc) when is_atom(M) ->
send_log(State#st.parent, io_lib:format("Getting warnings for ~w\n", [M])),
@@ -145,25 +148,29 @@ get_warnings_from_modules([M|Ms], State, DocPlt, Acc) when is_atom(M) ->
%% Check if there are contracts for functions that do not exist
Warnings1 =
dialyzer_contracts:contracts_without_fun(Contracts, AllFuns, Callgraph),
- {RawWarnings2, FunTypes} =
+ {Warnings2, FunTypes} =
dialyzer_dataflow:get_warnings(ModCode, Plt, Callgraph,
Records, NoWarnUnused),
- {NewAcc, Warnings2} = postprocess_dataflow_warns(RawWarnings2, State, Acc),
Attrs = cerl:module_attrs(ModCode),
Warnings3 = dialyzer_behaviours:check_callbacks(M, Attrs, Plt, Codeserver),
NewDocPlt = insert_into_doc_plt(FunTypes, Callgraph, DocPlt),
get_warnings_from_modules(Ms, State, NewDocPlt,
- [Warnings1, Warnings2, Warnings3|NewAcc]);
+ [Warnings1, Warnings2, Warnings3|Acc]);
get_warnings_from_modules([], #st{plt = Plt}, DocPlt, Acc) ->
{lists:flatten(Acc), Plt, DocPlt}.
-postprocess_dataflow_warns(RawWarnings, State, WarnAcc) ->
- postprocess_dataflow_warns(RawWarnings, State, WarnAcc, []).
+postprocess_warnings(RawWarnings, Codeserver) ->
+ Pred =
+ fun({?WARN_CONTRACT_RANGE, _, _}) -> true;
+ (_) -> false
+ end,
+ {CRWarns, NonCRWarns} = lists:partition(Pred, RawWarnings),
+ postprocess_dataflow_warns(CRWarns, Codeserver, NonCRWarns, []).
-postprocess_dataflow_warns([], _State, WAcc, Acc) ->
- {WAcc, lists:reverse(Acc)};
+postprocess_dataflow_warns([], _Callgraph, WAcc, Acc) ->
+ lists:reverse(Acc, WAcc);
postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {CallF, CallL}, Msg}|Rest],
- #st{codeserver = Codeserver} = State, WAcc, Acc) ->
+ Codeserver, WAcc, Acc) ->
{contract_range, [Contract, M, F, A, ArgStrings, CRet]} = Msg,
case dialyzer_codeserver:lookup_mfa_contract({M,F,A}, Codeserver) of
{ok, {{ContrF, _ContrL} = FileLine, _C}} ->
@@ -176,19 +183,17 @@ postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {CallF, CallL}, Msg}|Rest],
(_) -> true
end,
FilterWAcc = lists:filter(Filter, WAcc),
- postprocess_dataflow_warns(Rest, State, FilterWAcc, [W|Acc]);
+ postprocess_dataflow_warns(Rest, Codeserver, FilterWAcc, [W|Acc]);
false ->
- postprocess_dataflow_warns(Rest, State, WAcc, Acc)
+ postprocess_dataflow_warns(Rest, Codeserver, WAcc, Acc)
end;
error ->
%% The contract is not in a module that is currently under analysis.
%% We display the warning in the file/line of the call.
NewMsg = {contract_range, [Contract, M, F, ArgStrings, CallL, CRet]},
W = {?WARN_CONTRACT_RANGE, {CallF, CallL}, NewMsg},
- postprocess_dataflow_warns(Rest, State, WAcc, [W|Acc])
- end;
-postprocess_dataflow_warns([W|Rest], State, Wacc, Acc) ->
- postprocess_dataflow_warns(Rest, State, Wacc, [W|Acc]).
+ postprocess_dataflow_warns(Rest, Codeserver, WAcc, [W|Acc])
+ end.
refine_succ_typings(ModulePostorder, #st{codeserver = Codeserver,
callgraph = Callgraph,