diff options
Diffstat (limited to 'lib/dialyzer/src/dialyzer_utils.erl')
-rw-r--r-- | lib/dialyzer/src/dialyzer_utils.erl | 76 |
1 files changed, 61 insertions, 15 deletions
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl index 75d6e3bc65..511a6d66bf 100644 --- a/lib/dialyzer/src/dialyzer_utils.erl +++ b/lib/dialyzer/src/dialyzer_utils.erl @@ -39,6 +39,8 @@ sets_filter/2, src_compiler_opts/0, refold_pattern/1, + ets_tab2list/1, + ets_move/2, parallelism/0, family/1 ]). @@ -56,15 +58,15 @@ print_types1([], _) -> ok; print_types1([{type, _Name, _NArgs} = Key|T], RecDict) -> {ok, {{_Mod, _FileLine, _Form, _Args}, Type}} = dict:find(Key, RecDict), - io:format("\n~w: ~w\n", [Key, Type]), + io:format("\n~tw: ~tw\n", [Key, Type]), print_types1(T, RecDict); print_types1([{opaque, _Name, _NArgs} = Key|T], RecDict) -> {ok, {{_Mod, _FileLine, _Form, _Args}, Type}} = dict:find(Key, RecDict), - io:format("\n~w: ~w\n", [Key, Type]), + io:format("\n~tw: ~tw\n", [Key, Type]), print_types1(T, RecDict); print_types1([{record, _Name} = Key|T], RecDict) -> {ok, {_FileLine, [{_Arity, _Fields} = AF]}} = dict:find(Key, RecDict), - io:format("~w: ~w\n\n", [Key, AF]), + io:format("~tw: ~tw\n\n", [Key, AF]), print_types1(T, RecDict). -define(debug(D_), print_types(D_)). -else. @@ -268,7 +270,7 @@ add_new_type(TypeOrOpaque, Name, TypeForm, ArgForms, Module, FN, Arity = length(ArgForms), case erl_types:type_is_defined(TypeOrOpaque, Name, Arity, RecDict) of true -> - Msg = flat_format("Type ~s/~w already defined\n", [Name, Arity]), + Msg = flat_format("Type ~ts/~w already defined\n", [Name, Arity]), throw({error, Msg}); false -> try erl_types:t_var_names(ArgForms) of @@ -278,7 +280,7 @@ add_new_type(TypeOrOpaque, Name, TypeForm, ArgForms, Module, FN, erl_types:t_any()}, RecDict) catch _:_ -> - throw({error, flat_format("Type declaration for ~w does not " + throw({error, flat_format("Type declaration for ~tw does not " "have variables as parameters", [Name])}) end end. @@ -340,7 +342,19 @@ process_record_remote_types(CServer) -> {FieldsList, C3} = lists:mapfoldl(FieldFun, C2, orddict:to_list(Fields)), {{Key, {FileLine, orddict:from_list(FieldsList)}}, C3}; - _Other -> {{Key, Value}, C2} + {type, Name, NArgs} -> + %% Make sure warnings about unknown types are output + %% also for types unused by specs. + Site = {type, {Module, Name, NArgs}}, + L = erl_anno:new(0), + Args = lists:duplicate(NArgs, {var, L, '_'}), + UserType = {user_type, L, Name, Args}, + {_NewType, C3} = + erl_types:t_from_form(UserType, ExpTypes, Site, + RecordTable, VarTable, C2), + {{Key, Value}, C3}; + {opaque, _Name, _NArgs} -> + {{Key, Value}, C2} end end, Cache = erl_types:cache__new(), @@ -378,7 +392,10 @@ process_opaque_types(AllModules, CServer, TempExpTypes) -> erl_types:t_from_form(Form, TempExpTypes, Site, RecordTable, VarTable, C2), {{Key, {F, Type}}, C3}; - _Other -> {{Key, Value}, C2} + {type, _Name, _NArgs} -> + {{Key, Value}, C2}; + {record, _RecName} -> + {{Key, Value}, C2} end end, C0 = erl_types:cache__new(), @@ -433,7 +450,7 @@ msg_with_position(Fun, FileLine) -> throw:{error, Msg} -> {File, Line} = FileLine, BaseName = filename:basename(File), - NewMsg = io_lib:format("~s:~p: ~s", [BaseName, Line, Msg]), + NewMsg = io_lib:format("~ts:~p: ~ts", [BaseName, Line, Msg]), throw({error, NewMsg}) end. @@ -526,13 +543,13 @@ get_spec_info([{Contract, Ln, [{Id, TypeSpec}]}|Left], RecordsMap, ModName, OptCb, File); {ok, {{OtherFile, L}, _D}} -> {Mod, Fun, Arity} = MFA, - Msg = flat_format(" Contract/callback for function ~w:~w/~w " - "already defined in ~s:~w\n", + Msg = flat_format(" Contract/callback for function ~w:~tw/~w " + "already defined in ~ts:~w\n", [Mod, Fun, Arity, OtherFile, L]), throw({error, Msg}) catch throw:{error, Error} -> - {error, flat_format(" Error while parsing contract in line ~w: ~s\n", + {error, flat_format(" Error while parsing contract in line ~w: ~ts\n", [Ln, Error])} end; get_spec_info([{file, _, [{IncludeFile, _}]}|Left], @@ -635,7 +652,7 @@ get_options1([{Args, L, File}|Left], Warnings) -> get_options1(Left, NewWarnings) catch throw:{dialyzer_options_error, Msg} -> - Msg1 = flat_format(" ~s:~w: ~s", [File, L, Msg]), + Msg1 = flat_format(" ~ts:~w: ~ts", [File, L, Msg]), throw({error, Msg1}) end; get_options1([], Warnings) -> @@ -714,7 +731,7 @@ src_compiler_opts() -> format_errors([{Mod, Errors}|Left]) -> FormatedError = - [io_lib:format("~s:~w: ~s\n", [Mod, Line, M:format_error(Desc)]) + [io_lib:format("~ts:~w: ~ts\n", [Mod, Line, M:format_error(Desc)]) || {Line, M, Desc} <- Errors], [lists:flatten(FormatedError) | format_errors(Left)]; format_errors([]) -> @@ -759,14 +776,14 @@ check_fa_list1([{Args, L, File}|Left], Tag, Funcs) -> case lists:dropwhile(fun({_, T}) -> is_fa(T) end, TermsL) of [] -> ok; [{_, Bad}|_] -> - Msg1 = flat_format(" Bad function ~w in line ~s:~w", + Msg1 = flat_format(" Bad function ~tw in line ~ts:~w", [Bad, File, L]), throw({error, Msg1}) end, case lists:dropwhile(fun({_, FA}) -> is_known(FA, Funcs) end, TermsL) of [] -> ok; [{_, {F, A}}|_] -> - Msg2 = flat_format(" Unknown function ~w/~w in line ~s:~w", + Msg2 = flat_format(" Unknown function ~tw/~w in line ~ts:~w", [F, A, File, L]), throw({error, Msg2}) end, @@ -974,6 +991,35 @@ label(Tree) -> %%------------------------------------------------------------------------------ +-spec ets_tab2list(ets:tid()) -> list(). + +%% Deletes the contents of the table. Use: +%% ets_tab2list(T), ets:delete(T) +%% instead of: +%% ets:tab2list(T), ets:delete(T) +%% to save some memory at the expense of somewhat longer execution time. +ets_tab2list(T) -> + F = fun(Vs, A) -> Vs ++ A end, + ets_take(ets:first(T), T, F, []). + +-spec ets_move(From :: ets:tid(), To :: ets:tid()) -> 'ok'. + +ets_move(T1, T2) -> + F = fun(Es, A) -> true = ets:insert(T2, Es), A end, + [] = ets_take(ets:first(T1), T1, F, []), + ok. + +ets_take('$end_of_table', T, F, A) -> + case ets:first(T) of % no safe_fixtable()... + '$end_of_table' -> A; + Key -> ets_take(Key, T, F, A) + end; +ets_take(Key, T, F, A) -> + Vs = ets:lookup(T, Key), + Key1 = ets:next(T, Key), + true = ets:delete(T, Key), + ets_take(Key1, T, F, F(Vs, A)). + -spec parallelism() -> integer(). parallelism() -> |