diff options
Diffstat (limited to 'lib/dialyzer/src/dialyzer_utils.erl')
-rw-r--r-- | lib/dialyzer/src/dialyzer_utils.erl | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl index 6ea243c26f..a9da229061 100644 --- a/lib/dialyzer/src/dialyzer_utils.erl +++ b/lib/dialyzer/src/dialyzer_utils.erl @@ -21,7 +21,7 @@ %%%------------------------------------------------------------------- %%% File : dialyzer_utils.erl %%% Author : Tobias Lindahl <[email protected]> -%%% Description : +%%% Description : %%% %%% Created : 5 Dec 2006 by Tobias Lindahl <[email protected]> %%%------------------------------------------------------------------- @@ -42,6 +42,7 @@ merge_records/2, pp_hook/0, process_record_remote_types/1, + sets_filter/2, src_compiler_opts/0 ]). @@ -73,12 +74,11 @@ print_types1([{record, _Name} = Key|T], RecDict) -> -define(debug(D_), ok). -endif. -%% -%% Types that need to be imported from somewhere else -%% +%% ---------------------------------------------------------------------------- --type abstract_code() :: [tuple()]. %% XXX: refine --type comp_options() :: [atom()]. %% XXX: only a resticted set of options used +-type abstract_code() :: [tuple()]. %% XXX: import from somewhere +-type comp_options() :: [compile:option()]. +-type mod_or_fname() :: atom() | file:filename(). %% ============================================================================ %% @@ -86,13 +86,13 @@ print_types1([{record, _Name} = Key|T], RecDict) -> %% %% ============================================================================ --spec get_abstract_code_from_src(atom() | file:filename()) -> +-spec get_abstract_code_from_src(mod_or_fname()) -> {'ok', abstract_code()} | {'error', [string()]}. get_abstract_code_from_src(File) -> get_abstract_code_from_src(File, src_compiler_opts()). --spec get_abstract_code_from_src(atom() | file:filename(), comp_options()) -> +-spec get_abstract_code_from_src(mod_or_fname(), comp_options()) -> {'ok', abstract_code()} | {'error', [string()]}. get_abstract_code_from_src(File, Opts) -> @@ -169,13 +169,13 @@ get_record_and_type_info(AbstractCode) -> Module = get_module(AbstractCode), get_record_and_type_info(AbstractCode, Module, dict:new()). --spec get_record_and_type_info(abstract_code(), atom(), dict()) -> +-spec get_record_and_type_info(abstract_code(), module(), dict()) -> {'ok', dict()} | {'error', string()}. get_record_and_type_info(AbstractCode, Module, RecDict) -> get_record_and_type_info(AbstractCode, Module, [], RecDict). -get_record_and_type_info([{attribute, _, record, {Name, Fields0}}|Left], +get_record_and_type_info([{attribute, _, record, {Name, Fields0}}|Left], Module, Records, RecDict) -> {ok, Fields} = get_record_fields(Fields0, RecDict), Arity = length(Fields), @@ -188,7 +188,7 @@ get_record_and_type_info([{attribute, _, type, {{record, Name}, Fields0, []}} Arity = length(Fields), NewRecDict = dict:store({record, Name}, [{Arity, Fields}], RecDict), get_record_and_type_info(Left, Module, Records, NewRecDict); -get_record_and_type_info([{attribute, _, Attr, {Name, TypeForm}}|Left], +get_record_and_type_info([{attribute, _, Attr, {Name, TypeForm}}|Left], Module, Records, RecDict) when Attr =:= 'type'; Attr =:= 'opaque' -> try @@ -197,7 +197,7 @@ get_record_and_type_info([{attribute, _, Attr, {Name, TypeForm}}|Left], catch throw:{error, _} = Error -> Error end; -get_record_and_type_info([{attribute, _, Attr, {Name, TypeForm, Args}}|Left], +get_record_and_type_info([{attribute, _, Attr, {Name, TypeForm, Args}}|Left], Module, Records, RecDict) when Attr =:= 'type'; Attr =:= 'opaque' -> try @@ -219,7 +219,7 @@ get_record_and_type_info([], _Module, Records, RecDict) -> end. add_new_type(TypeOrOpaque, Name, TypeForm, ArgForms, Module, RecDict) -> - case erl_types:type_is_defined(TypeOrOpaque, Name, RecDict) of + case erl_types:type_is_defined(TypeOrOpaque, Name, RecDict) of true -> throw({error, io_lib:format("Type already defined: ~w\n", [Name])}); false -> @@ -237,7 +237,7 @@ add_new_type(TypeOrOpaque, Name, TypeForm, ArgForms, Module, RecDict) -> get_record_fields(Fields, RecDict) -> get_record_fields(Fields, RecDict, []). -get_record_fields([{typed_record_field, OrdRecField, TypeForm}|Left], +get_record_fields([{typed_record_field, OrdRecField, TypeForm}|Left], RecDict, Acc) -> Name = case OrdRecField of @@ -278,13 +278,16 @@ type_record_fields([RecKey|Recs], RecDict) -> process_record_remote_types(CServer) -> TempRecords = dialyzer_codeserver:get_temp_records(CServer), + TempExpTypes = dialyzer_codeserver:get_temp_exported_types(CServer), RecordFun = fun(Key, Value) -> case Key of {record, _Name} -> FieldFun = fun(_Arity, Fields) -> - [{Name, erl_types:t_solve_remote(Field, TempRecords)} || {Name, Field} <- Fields] + [{Name, erl_types:t_solve_remote(Field, TempExpTypes, + TempRecords)} + || {Name, Field} <- Fields] end, orddict:map(FieldFun, Value); _Other -> Value @@ -295,7 +298,8 @@ process_record_remote_types(CServer) -> dict:map(RecordFun, Record) end, NewRecords = dict:map(ModuleFun, TempRecords), - dialyzer_codeserver:finalize_records(NewRecords, CServer). + CServer1 = dialyzer_codeserver:finalize_records(NewRecords, CServer), + dialyzer_codeserver:finalize_exported_types(TempExpTypes, CServer1). -spec merge_records(dict(), dict()) -> dict(). @@ -308,19 +312,19 @@ merge_records(NewRecords, OldRecords) -> %% %% ============================================================================ --spec get_spec_info(module(), abstract_code(), dict()) -> +-spec get_spec_info(atom(), abstract_code(), dict()) -> {'ok', dict()} | {'error', string()}. get_spec_info(ModName, AbstractCode, RecordsDict) -> get_spec_info(AbstractCode, dict:new(), RecordsDict, ModName, "nofile"). -%% TypeSpec is a list of conditional contracts for a function. +%% TypeSpec is a list of conditional contracts for a function. %% Each contract is of the form {[Argument], Range, [Constraint]} where %% - Argument and Range are in erl_types:erl_type() format and %% - Constraint is of the form {subtype, T1, T2} where T1 and T2 %% are erl_types:erl_type() -get_spec_info([{attribute, Ln, spec, {Id, TypeSpec}}|Left], +get_spec_info([{attribute, Ln, spec, {Id, TypeSpec}}|Left], SpecDict, RecordsDict, ModName, File) when is_list(TypeSpec) -> MFA = case Id of {_, _, _} = T -> T; @@ -335,7 +339,7 @@ get_spec_info([{attribute, Ln, spec, {Id, TypeSpec}}|Left], {ok, {{OtherFile, L},_C}} -> {Mod, Fun, Arity} = MFA, Msg = io_lib:format(" Contract for function ~w:~w/~w " - "already defined in ~s:~w\n", + "already defined in ~s:~w\n", [Mod, Fun, Arity, OtherFile, L]), throw({error, Msg}) catch @@ -353,15 +357,30 @@ get_spec_info([], SpecDict, _RecordsDict, _ModName, _File) -> %% ============================================================================ %% +%% Exported types +%% +%% ============================================================================ + +-spec sets_filter([module()], set()) -> set(). + +sets_filter([], ExpTypes) -> + ExpTypes; +sets_filter([Mod|Mods], ExpTypes) -> + NewExpTypes = sets:filter(fun({M, _F, _A}) -> M =/= Mod end, ExpTypes), + sets_filter(Mods, NewExpTypes). + +%% ============================================================================ +%% %% Util utils %% %% ============================================================================ --spec src_compiler_opts() -> comp_options(). +-spec src_compiler_opts() -> [compile:option(),...]. src_compiler_opts() -> [no_copt, to_core, binary, return_errors, - no_inline, strict_record_tests, strict_record_updates]. + no_inline, strict_record_tests, strict_record_updates, + no_is_record_optimization]. -spec get_module(abstract_code()) -> module(). @@ -381,7 +400,7 @@ cleanup_parse_transforms([]) -> -spec format_errors([{module(), string()}]) -> [string()]. format_errors([{Mod, Errors}|Left]) -> - FormatedError = + FormatedError = [io_lib:format("~s:~w: ~s\n", [Mod, Line, M:format_error(Desc)]) || {Line, M, Desc} <- Errors], [lists:flatten(FormatedError) | format_errors(Left)]; @@ -456,7 +475,7 @@ pp_size(Size, Ctxt, Cont) -> end. pp_opts(Type, Flags) -> - FinalFlags = + FinalFlags = case cerl:atom_val(Type) of binary -> []; float -> keep_endian(cerl:concrete(Flags)); |