aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/src/dialyzer_plt.erl
diff options
context:
space:
mode:
authorHenrik Nord <[email protected]>2011-11-18 17:33:22 +0100
committerHenrik Nord <[email protected]>2011-11-18 17:33:42 +0100
commitb130455e73b0bcacee2bfd3dfe6bafa9dd497886 (patch)
tree2f97ac74f573b2f0c5a4f846e4505dec871e05f5 /lib/dialyzer/src/dialyzer_plt.erl
parent01bf07008b38839f4e1dff3293f921c2e35a44c4 (diff)
parent8167578ca6b23f3043ae2e21ded4b13b8db74e20 (diff)
downloadotp-b130455e73b0bcacee2bfd3dfe6bafa9dd497886.tar.gz
otp-b130455e73b0bcacee2bfd3dfe6bafa9dd497886.tar.bz2
otp-b130455e73b0bcacee2bfd3dfe6bafa9dd497886.zip
Merge branch 'sa/dialyzer-behaviours'
* sa/dialyzer-behaviours: Wrap up behaviours patch for Dialyzer Detection of callback-spec discrepancies Allow none() as return value in callbacks Behaviour callback discrepancy detection for Dialyzer Add lookup function for callbacks Store callbacks in codeserver and PLT Collect callback definitions during compilation Update inets results OTP-9731
Diffstat (limited to 'lib/dialyzer/src/dialyzer_plt.erl')
-rw-r--r--lib/dialyzer/src/dialyzer_plt.erl74
1 files changed, 60 insertions, 14 deletions
diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl
index 6033d7f17c..206c43e4e2 100644
--- a/lib/dialyzer/src/dialyzer_plt.erl
+++ b/lib/dialyzer/src/dialyzer_plt.erl
@@ -43,10 +43,12 @@
%% insert/3,
insert_list/2,
insert_contract_list/2,
+ insert_callbacks/2,
insert_types/2,
insert_exported_types/2,
lookup/2,
lookup_contract/2,
+ lookup_callbacks/2,
lookup_module/2,
merge_plts/1,
merge_plts_or_report_conflicts/2,
@@ -79,6 +81,7 @@
-record(plt, {info = table_new() :: dict(),
types = table_new() :: dict(),
contracts = table_new() :: dict(),
+ callbacks = table_new() :: dict(),
exported_types = sets:new() :: set()}).
-opaque plt() :: #plt{}.
@@ -91,6 +94,7 @@
file_md5_list = [] :: [file_md5()],
info = dict:new() :: dict(),
contracts = dict:new() :: dict(),
+ callbacks = dict:new() :: dict(),
types = dict:new() :: dict(),
exported_types = sets:new() :: set(),
mod_deps :: mod_deps(),
@@ -105,20 +109,26 @@ new() ->
-spec delete_module(plt(), atom()) -> plt().
-delete_module(#plt{info = Info, types = Types, contracts = Contracts,
+delete_module(#plt{info = Info, types = Types,
+ contracts = Contracts,
+ callbacks = Callbacks,
exported_types = ExpTypes}, Mod) ->
#plt{info = table_delete_module(Info, Mod),
types = table_delete_module2(Types, Mod),
contracts = table_delete_module(Contracts, Mod),
+ callbacks = table_delete_module(Callbacks, Mod),
exported_types = table_delete_module1(ExpTypes, Mod)}.
-spec delete_list(plt(), [mfa() | integer()]) -> plt().
-delete_list(#plt{info = Info, types = Types, contracts = Contracts,
+delete_list(#plt{info = Info, types = Types,
+ contracts = Contracts,
+ callbacks = Callbacks,
exported_types = ExpTypes}, List) ->
#plt{info = table_delete_list(Info, List),
types = Types,
contracts = table_delete_list(Contracts, List),
+ callbacks = table_delete_list(Callbacks, List),
exported_types = ExpTypes}.
-spec insert_contract_list(plt(), dialyzer_contracts:plt_contracts()) -> plt().
@@ -126,16 +136,42 @@ delete_list(#plt{info = Info, types = Types, contracts = Contracts,
insert_contract_list(#plt{contracts = Contracts} = PLT, List) ->
PLT#plt{contracts = table_insert_list(Contracts, List)}.
+-spec insert_callbacks(plt(), dialyzer_codeserver:codeserver()) -> plt().
+
+insert_callbacks(#plt{callbacks = Callbacks} = Plt, Codeserver) ->
+ FunPreferNew = fun(_Key, _Val1, Val2) -> Val2 end,
+ FunDictMerger =
+ fun(_Key, Value, AccIn) -> dict:merge(FunPreferNew, Value, AccIn) end,
+ MergedCallbacks = dict:fold(FunDictMerger, dict:new(),
+ dialyzer_codeserver:get_callbacks(Codeserver)),
+ List = dict:to_list(MergedCallbacks),
+ Plt#plt{callbacks = table_insert_list(Callbacks, List)}.
+
-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).
+-spec lookup_callbacks(plt(), module()) -> [{mfa(),
+ {{Filename::string(),
+ Line::pos_integer()},
+ #contract{}}}].
+
+lookup_callbacks(#plt{callbacks = Callbacks}, Mod) when is_atom(Mod) ->
+ FunModFilter =
+ fun({M, _F, _A}, _Val) -> M =:= Mod;
+ ( _Key, _Val) -> false
+ end,
+ ModCallbacks = dict:filter(FunModFilter, Callbacks),
+ dict:to_list(ModCallbacks).
+
-spec delete_contract_list(plt(), [mfa()]) -> plt().
-delete_contract_list(#plt{contracts = Contracts} = PLT, List) ->
- PLT#plt{contracts = table_delete_list(Contracts, List)}.
+delete_contract_list(#plt{contracts = Contracts,
+ callbacks = Callbacks} = PLT, List) ->
+ PLT#plt{contracts = table_delete_list(Contracts, List),
+ callbacks = table_delete_list(Callbacks, List)}.
%% -spec insert(plt(), mfa() | integer(), {_, _}) -> plt().
%%
@@ -230,6 +266,7 @@ from_file(FileName, ReturnInfo) ->
Plt = #plt{info = Rec#file_plt.info,
types = Rec#file_plt.types,
contracts = Rec#file_plt.contracts,
+ callbacks = Rec#file_plt.callbacks,
exported_types = Rec#file_plt.exported_types},
case ReturnInfo of
false -> Plt;
@@ -284,26 +321,34 @@ get_record_from_file(FileName) ->
-spec merge_plts([plt()]) -> plt().
merge_plts(List) ->
- InfoList = [Info || #plt{info = Info} <- List],
- TypesList = [Types || #plt{types = Types} <- List],
- ExpTypesList = [ExpTypes || #plt{exported_types = ExpTypes} <- List],
- ContractsList = [Contracts || #plt{contracts = Contracts} <- List],
+ {InfoList, TypesList, ExpTypesList, ContractsList, CallbacksList} =
+ group_fields(List),
#plt{info = table_merge(InfoList),
types = table_merge(TypesList),
exported_types = sets_merge(ExpTypesList),
- contracts = table_merge(ContractsList)}.
+ contracts = table_merge(ContractsList),
+ callbacks = table_merge(CallbacksList)
+ }.
-spec merge_disj_plts([plt()]) -> plt().
merge_disj_plts(List) ->
+ {InfoList, TypesList, ExpTypesList, ContractsList, CallbacksList} =
+ group_fields(List),
+ #plt{info = table_disj_merge(InfoList),
+ types = table_disj_merge(TypesList),
+ exported_types = sets_disj_merge(ExpTypesList),
+ contracts = table_disj_merge(ContractsList),
+ callbacks = table_disj_merge(CallbacksList)
+ }.
+
+group_fields(List) ->
InfoList = [Info || #plt{info = Info} <- List],
TypesList = [Types || #plt{types = Types} <- List],
ExpTypesList = [ExpTypes || #plt{exported_types = ExpTypes} <- List],
ContractsList = [Contracts || #plt{contracts = Contracts} <- List],
- #plt{info = table_disj_merge(InfoList),
- types = table_disj_merge(TypesList),
- exported_types = sets_disj_merge(ExpTypesList),
- contracts = table_disj_merge(ContractsList)}.
+ CallbacksList = [Callbacks || #plt{callbacks = Callbacks} <- List],
+ {InfoList, TypesList, ExpTypesList, ContractsList, CallbacksList}.
-spec merge_plts_or_report_conflicts([file:filename()], [plt()]) -> plt().
@@ -329,7 +374,7 @@ find_duplicates(List) ->
to_file(FileName,
#plt{info = Info, types = Types, contracts = Contracts,
- exported_types = ExpTypes},
+ callbacks = Callbacks, exported_types = ExpTypes},
ModDeps, {MD5, OldModDeps}) ->
NewModDeps = dict:merge(fun(_Key, OldVal, NewVal) ->
ordsets:union(OldVal, NewVal)
@@ -340,6 +385,7 @@ to_file(FileName,
file_md5_list = MD5,
info = Info,
contracts = Contracts,
+ callbacks = Callbacks,
types = Types,
exported_types = ExpTypes,
mod_deps = NewModDeps,