aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/typer/src/typer_annotator.erl157
1 files changed, 78 insertions, 79 deletions
diff --git a/lib/typer/src/typer_annotator.erl b/lib/typer/src/typer_annotator.erl
index 68a8f03a5c..8904867d3e 100644
--- a/lib/typer/src/typer_annotator.erl
+++ b/lib/typer/src/typer_annotator.erl
@@ -2,7 +2,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -34,46 +34,46 @@
-include("typer.hrl").
-%%----------------------------------------------------------------------------
+ %%----------------------------------------------------------------------------
-define(TYPER_ANN_DIR, "typer_ann").
--type func_info() :: {non_neg_integer(), atom(), arity()}.
+-type fun_info() :: {non_neg_integer(), atom(), arity()}.
--record(info, {recMap = typer_map:new() :: dict(),
- funcs = [] :: [func_info()],
- typeMap :: dict(),
- contracts :: boolean()}).
+-record(info, {records = typer_map:new() :: dict(),
+ functions = [] :: [fun_info()],
+ types :: dict(),
+ no_comment_specs = true :: boolean()}).
-record(inc, {map = typer_map:new() :: dict(),
- filter = [] :: [string()]}).
+ filter = [] :: [file:filename()]}).
%%----------------------------------------------------------------------------
-spec annotate(#typer_analysis{}) -> 'ok'.
-annotate(Analysis) ->
- case Analysis#typer_analysis.mode of
+annotate(#typer_analysis{mode = Mode, final_files = Files} = Analysis) ->
+ case Mode of
?SHOW -> show(Analysis);
?SHOW_EXPORTED -> show(Analysis);
?ANNOTATE ->
- Fun = fun({File, Module}) ->
+ Fun = fun ({File, Module}) ->
Info = get_final_info(File, Module, Analysis),
write_typed_file(File, Info)
end,
- lists:foreach(Fun, Analysis#typer_analysis.final_files);
+ lists:foreach(Fun, Files);
?ANNOTATE_INC_FILES ->
IncInfo = write_and_collect_inc_info(Analysis),
write_inc_files(IncInfo)
end.
write_and_collect_inc_info(Analysis) ->
- Fun = fun({File, Module}, Inc) ->
+ Fun = fun ({File, Module}, Inc) ->
Info = get_final_info(File, Module, Analysis),
write_typed_file(File, Info),
IncFuns = get_functions(File, Analysis),
- collect_imported_funcs(IncFuns, Info#info.typeMap, Inc)
+ collect_imported_functions(IncFuns, Info#info.types, Inc)
end,
- NewInc = lists:foldl(Fun,#inc{}, Analysis#typer_analysis.final_files),
+ NewInc = lists:foldl(Fun, #inc{}, Analysis#typer_analysis.final_files),
clean_inc(NewInc).
write_inc_files(Inc) ->
@@ -84,75 +84,75 @@ write_inc_files(Inc) ->
%% in form [{{Line,F,A},Type}]
Functions = [Key || {Key,_} <- Val],
Val1 = [{{F,A},Type} || {{_Line,F,A},Type} <- Val],
- Info = #info{typeMap = typer_map:from_list(Val1),
- recMap = typer_map:new(),
+ Info = #info{types = typer_map:from_list(Val1),
+ records = typer_map:new(),
%% Note we need to sort functions here!
- funcs = lists:keysort(1, Functions)},
- %% io:format("TypeMap ~p\n", [Info#info.typeMap]),
- %% io:format("Funcs ~p\n", [Info#info.funcs]),
- %% io:format("RecMap ~p\n", [Info#info.recMap]),
+ functions = lists:keysort(1, Functions)},
+ %% io:format("Types ~p\n", [Info#info.types]),
+ %% io:format("Functions ~p\n", [Info#info.functions]),
+ %% io:format("Records ~p\n", [Info#info.records]),
write_typed_file(File, Info)
end,
lists:foreach(Fun, dict:fetch_keys(Inc#inc.map)).
show(Analysis) ->
- Fun = fun({File, Module}) ->
+ Fun = fun ({File, Module}) ->
Info = get_final_info(File, Module, Analysis),
- show_type_info_only(File, Info)
+ show_type_info(File, Info)
end,
lists:foreach(Fun, Analysis#typer_analysis.final_files).
get_final_info(File, Module, Analysis) ->
- RecMap = get_recMap(File, Analysis),
- TypeMap = get_typeMap(Module, Analysis,RecMap),
+ Records = get_records(File, Analysis),
+ Types = get_types(Module, Analysis, Records),
Functions = get_functions(File, Analysis),
- Contracts = Analysis#typer_analysis.contracts,
- #info{recMap=RecMap, funcs=Functions, typeMap=TypeMap, contracts=Contracts}.
+ Bool = Analysis#typer_analysis.contracts,
+ #info{records = Records, functions = Functions,
+ types = Types, no_comment_specs = Bool}.
-collect_imported_funcs(Funcs, TypeMap, TmpInc) ->
+collect_imported_functions(Functions, Types, Inc) ->
%% Coming from other sourses, including:
%% FIXME: How to deal with yecc-generated file????
%% --.yrl (yecc-generated file)???
%% -- yeccpre.hrl (yecc-generated file)???
%% -- other cases
- Fun = fun({File,_} = Obj, Inc) ->
- case is_yecc_file(File, Inc) of
- {yecc_generated, NewInc} -> NewInc;
- {not_yecc, NewInc} ->
- check_imported_funcs(Obj, NewInc, TypeMap)
+ Fun = fun ({File, _} = Obj, I) ->
+ case is_yecc_gen(File, I) of
+ {true, NewI} -> NewI;
+ {false, NewI} ->
+ check_imported_functions(Obj, NewI, Types)
end
end,
- lists:foldl(Fun, TmpInc, Funcs).
+ lists:foldl(Fun, Inc, Functions).
--spec is_yecc_file(string(), #inc{}) -> {'not_yecc', #inc{}}
- | {'yecc_generated', #inc{}}.
-is_yecc_file(File, Inc) ->
- case lists:member(File, Inc#inc.filter) of
- true -> {yecc_generated, Inc};
+-spec is_yecc_gen(file:filename(), #inc{}) -> {boolean(), #inc{}}.
+
+is_yecc_gen(File, #inc{filter = Fs} = Inc) ->
+ case lists:member(File, Fs) of
+ true -> {true, Inc};
false ->
case filename:extension(File) of
".yrl" ->
Rootname = filename:rootname(File, ".yrl"),
Obj = Rootname ++ ".erl",
- case lists:member(Obj, Inc#inc.filter) of
- true -> {yecc_generated, Inc};
+ case lists:member(Obj, Fs) of
+ true -> {true, Inc};
false ->
- NewFilter = [Obj|Inc#inc.filter],
- NewInc = Inc#inc{filter = NewFilter},
- {yecc_generated, NewInc}
+ NewInc = Inc#inc{filter = [Obj|Fs]},
+ {true, NewInc}
end;
_ ->
case filename:basename(File) of
- "yeccpre.hrl" -> {yecc_generated, Inc};
- _ -> {not_yecc, Inc}
+ "yeccpre.hrl" -> {true, Inc};
+ _ -> {false, Inc}
end
end
end.
-check_imported_funcs({File, {Line, F, A}}, Inc, TypeMap) ->
+check_imported_functions({File, {Line, F, A}}, Inc, Types) ->
IncMap = Inc#inc.map,
FA = {F, A},
- Type = get_type_info(FA, TypeMap),
+ Type = get_type_info(FA, Types),
case typer_map:lookup(File, IncMap) of
none -> %% File is not added. Add it
Obj = {File,[{FA, {Line, Type}}]},
@@ -190,25 +190,24 @@ clean_inc(Inc) ->
Inc1 = remove_yecc_generated_file(Inc),
normalize_obj(Inc1).
-remove_yecc_generated_file(TmpInc) ->
- Fun = fun(Key, Inc) ->
- NewMap = typer_map:remove(Key, Inc#inc.map),
- Inc#inc{map = NewMap}
+remove_yecc_generated_file(#inc{filter = Filter} = Inc) ->
+ Fun = fun (Key, #inc{map = Map} = I) ->
+ I#inc{map = typer_map:remove(Key, Map)}
end,
- lists:foldl(Fun, TmpInc, TmpInc#inc.filter).
-
+ lists:foldl(Fun, Inc, Filter).
+
normalize_obj(TmpInc) ->
- Fun = fun(Key, Val, Inc) ->
+ Fun = fun (Key, Val, Inc) ->
NewVal = [{{Line,F,A},Type} || {{F,A},{Line,Type}} <- Val],
typer_map:insert({Key,NewVal}, Inc)
end,
NewMap = typer_map:fold(Fun, typer_map:new(), TmpInc#inc.map),
TmpInc#inc{map = NewMap}.
-get_recMap(File, Analysis) ->
+get_records(File, Analysis) ->
typer_map:lookup(File, Analysis#typer_analysis.record).
-get_typeMap(Module, Analysis, RecMap) ->
+get_types(Module, Analysis, Records) ->
TypeInfoPlt = Analysis#typer_analysis.trust_plt,
TypeInfo =
case dialyzer_plt:lookup_module(TypeInfoPlt, Module) of
@@ -216,10 +215,10 @@ get_typeMap(Module, Analysis, RecMap) ->
{value, List} -> List
end,
CodeServer = Analysis#typer_analysis.code_server,
- TypeInfoList = [get_type(I, CodeServer, RecMap) || I <- TypeInfo],
+ TypeInfoList = [get_type(I, CodeServer, Records) || I <- TypeInfo],
typer_map:from_list(TypeInfoList).
-get_type({{M, F, A} = MFA, Range, Arg}, CodeServer, RecMap) ->
+get_type({{M, F, A} = MFA, Range, Arg}, CodeServer, Records) ->
case dialyzer_codeserver:lookup_mfa_contract(MFA, CodeServer) of
error ->
{{F, A}, {Range, Arg}};
@@ -231,7 +230,7 @@ get_type({{M, F, A} = MFA, Range, Arg}, CodeServer, RecMap) ->
{{F, A}, {contract, Contract}};
{error, invalid_contract} ->
CString = dialyzer_contracts:contract_to_string(Contract),
- SigString = dialyzer_utils:format_sig(Sig, RecMap),
+ SigString = dialyzer_utils:format_sig(Sig, Records),
typer:error(
io_lib:format("Error in contract of function ~w:~w/~w\n"
"\t The contract is: " ++ CString ++ "\n" ++
@@ -260,17 +259,17 @@ get_functions(File, Analysis) ->
typer_map:lookup(File, Analysis#typer_analysis.inc_func)
end.
-normalize_incFuncs(Funcs) ->
- [FuncInfo || {_FileName, FuncInfo} <- Funcs].
+normalize_incFuncs(Functions) ->
+ [FunInfo || {_FileName, FunInfo} <- Functions].
--spec remove_module_info([func_info()]) -> [func_info()].
+-spec remove_module_info([fun_info()]) -> [fun_info()].
-remove_module_info(FuncInfoList) ->
+remove_module_info(FunInfoList) ->
F = fun ({_,module_info,0}) -> false;
({_,module_info,1}) -> false;
({Line,F,A}) when is_integer(Line), is_atom(F), is_integer(A) -> true
end,
- lists:filter(F, FuncInfoList).
+ lists:filter(F, FunInfoList).
write_typed_file(File, Info) ->
io:format(" Processing file: ~p\n", [File]),
@@ -278,7 +277,7 @@ write_typed_file(File, Info) ->
RootName = filename:basename(filename:rootname(File)),
Ext = filename:extension(File),
TyperAnnDir = filename:join(Dir, ?TYPER_ANN_DIR),
- TmpNewFilename = lists:concat([RootName,".ann",Ext]),
+ TmpNewFilename = lists:concat([RootName, ".ann", Ext]),
NewFileName = filename:join(TyperAnnDir, TmpNewFilename),
case file:make_dir(TyperAnnDir) of
{error, Reason} ->
@@ -291,7 +290,7 @@ write_typed_file(File, Info) ->
eacces ->
io:format(" No write permission in ~p\n", [Dir]);
_ ->
- io:format("Unknown error when writing ~p\n", [Dir]),
+ io:format("Unhandled error ~s when writing ~p\n", [Reason, Dir]),
halt()
end;
ok -> %% Typer dir does NOT exist
@@ -304,14 +303,14 @@ write_typed_file(File, Info, NewFileName) ->
write_typed_file(Chars, NewFileName, Info, 1, []),
io:format(" Saved as: ~p\n", [NewFileName]).
-write_typed_file(Chars, File, #info{funcs = []}, _LNo, _Acc) ->
+write_typed_file(Chars, File, #info{functions = []}, _LNo, _Acc) ->
ok = file:write_file(File, list_to_binary(Chars), [append]);
write_typed_file([Ch|Chs] = Chars, File, Info, LineNo, Acc) ->
- [{Line,F,A}|RestFuncs] = Info#info.funcs,
+ [{Line,F,A}|RestFuncs] = Info#info.functions,
case Line of
1 -> %% This will happen only for inc files
ok = raw_write(F, A, Info, File, []),
- NewInfo = Info#info{funcs = RestFuncs},
+ NewInfo = Info#info{functions = RestFuncs},
NewAcc = [],
write_typed_file(Chars, File, NewInfo, Line, NewAcc);
_ ->
@@ -322,7 +321,7 @@ write_typed_file([Ch|Chs] = Chars, File, Info, LineNo, Acc) ->
case NewLineNo of
Line ->
ok = raw_write(F, A, Info, File, [Ch|Acc]),
- {Info#info{funcs = RestFuncs}, []};
+ {Info#info{functions = RestFuncs}, []};
_ ->
{Info, [Ch|Acc]}
end,
@@ -339,16 +338,16 @@ raw_write(F, A, Info, File, Content) ->
file:write_file(File, ContentBin, [append]).
get_type_string(F, A, Info, Mode) ->
- Type = get_type_info({F,A}, Info#info.typeMap),
+ Type = get_type_info({F,A}, Info#info.types),
TypeStr =
case Type of
{contract, C} ->
dialyzer_contracts:contract_to_string(C);
{RetType, ArgType} ->
- dialyzer_utils:format_sig(erl_types:t_fun(ArgType, RetType),
- Info#info.recMap)
+ Sig = erl_types:t_fun(ArgType, RetType),
+ dialyzer_utils:format_sig(Sig, Info#info.records)
end,
- case Info#info.contracts of
+ case Info#info.no_comment_specs of
true ->
case {Mode, Type} of
{file, {contract, _}} -> "";
@@ -361,7 +360,7 @@ get_type_string(F, A, Info, Mode) ->
lists:concat([Prefix, TypeStr, "."])
end.
-show_type_info_only(File, Info) ->
+show_type_info(File, Info) ->
io:format("\n%% File: ~p\n%% ", [File]),
OutputString = lists:concat(["~.", length(File)+8, "c~n"]),
io:fwrite(OutputString, [$-]),
@@ -369,10 +368,10 @@ show_type_info_only(File, Info) ->
TypeInfo = get_type_string(F, A, Info, show),
io:format("~s\n", [TypeInfo])
end,
- lists:foreach(Fun, Info#info.funcs).
+ lists:foreach(Fun, Info#info.functions).
-get_type_info(Func, TypeMap) ->
- case typer_map:lookup(Func, TypeMap) of
+get_type_info(Func, Types) ->
+ case typer_map:lookup(Func, Types) of
none ->
%% Note: Typeinfo of any function should exist in
%% the result offered by dialyzer, otherwise there