typer_info.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 129 行

ERL
129
字号
%% -*- erlang-indent-level: 2 -*-%%--------------------------------------------------------------------%% File        : typer_info.erl%% Author      : Bingwen He <Bingwen.He@gmail.com>%% Description : %%---------------------------------------------------------------------module(typer_info).-export([collect/1]).-record(tmpAcc,{file,		module,		funcAcc=[],		incFuncAcc=[],		dialyzerObj=[]}).-include("typer.hrl").collect(Analysis) ->  try get_dialyzer_plt() of      DialyzerPlt ->      dialyzer_plt:merge_plts([Analysis#analysis.trust_plt, DialyzerPlt])  catch    throw:{dialyzer_error,_Reason} ->      typer:error("No dialyzer_init_plt found under lib/dialyzer/plt/\n"++                  "       Please check your Erlang/OTP installation");    exit:Term ->      io:format("Error: ~p\n", [Term])  end,  lists:foldl(fun collect_one_file_info/2, Analysis, Analysis#analysis.ana_files).collect_one_file_info(File, Analysis) ->  Ds = [{d,Name,Val} || {Name,Val} <- Analysis#analysis.macros],  %% Current directory should also be included in "Includes".  Includes = [filename:dirname(File)|Analysis#analysis.includes],  Is = [{i,Dir} || Dir <- Includes],  Options = ?SRC_COMP_OPTS ++Is ++Ds,  case dialyzer_utils:get_abstract_code_from_src(File, Options) of    {error, Reason} ->      %% io:format("File=~p\n,Options=~p\n,Error=~p\n", [File,Options,Reason]),      typer:compile_error(Reason);    AbstractCode ->      case dialyzer_utils:get_core_from_abstract_code(AbstractCode) of	error -> typer:compile_error("Could not get core erlang for "++File);	Core ->	  case dialyzer_utils:get_record_info(AbstractCode) of	    {error, Reason} -> typer:compile_error(Reason);	    {ok, Records} -> analyze_core_tree(Core, Records, Analysis, File)	  end      end  end.analyze_core_tree(Core, Records, Analysis, File) ->  Module = list_to_atom(filename:basename(File, ".erl")),  TmpTree = cerl:from_records(Core),  CS1 = Analysis#analysis.code_server,  NextLabel = dialyzer_codeserver:next_core_label(CS1),  {Tree,NewLabel} = cerl_trees:label(TmpTree, NextLabel),  CS2 = dialyzer_codeserver:insert([{Module, Tree}], core, CS1),  CS3 = dialyzer_codeserver:update_next_core_label(NewLabel, CS2),  CS4 = dialyzer_codeserver:store_records(Module, Records, CS3),  Ex_Funcs = [{0,F,A} || {_,_,{F,A}} <- cerl:module_exports(Tree)],  TmpCG = Analysis#analysis.callgraph,  CG = dialyzer_callgraph:scan_core_tree(Tree, TmpCG),  Fun = fun analyze_one_function/2,  All_Defs = cerl:module_defs(Tree),  Acc = lists:foldl(Fun, #tmpAcc{file=File,module=Module}, All_Defs),  Exported_FuncMap = typer_map:insert({File, Ex_Funcs},				      Analysis#analysis.ex_func),  %% NOTE: we *MUST* sort here all functions in the file which  %% originate from this file by *numerical order* of lineNo  Sorted_Functions = lists:keysort(1, Acc#tmpAcc.funcAcc),  FuncMap = typer_map:insert({File,Sorted_Functions},			     Analysis#analysis.func),  %% NOTE: However so far we do *NOT* need to sort functions  %% which are imported from included files.  IncFuncMap = typer_map:insert({File, Acc#tmpAcc.incFuncAcc}, 				Analysis#analysis.inc_func),    Final_Files = Analysis#analysis.final_files++[{File, Module}],  RecordMap = typer_map:insert({File,Records}, Analysis#analysis.record),  Analysis#analysis{final_files=Final_Files,		    callgraph=CG,		    code_server=CS4,		    ex_func=Exported_FuncMap,		    inc_func=IncFuncMap,		    record=RecordMap,		    func=FuncMap}.analyze_one_function({Var,FunBody}, Acc) ->  F = cerl:fname_id(Var),  A = cerl:fname_arity(Var),  TmpDialyzerObj = {{Acc#tmpAcc.module,F,A},{Var,FunBody}},  NewDialyzerObj = Acc#tmpAcc.dialyzerObj++[TmpDialyzerObj],    [_,LineNo,{file,FileName}] = cerl:get_ann(FunBody),  %% Note!: If you run TypEr on files that are right at   %%        the current level of directory, you will have   %%        'FileName' like './FileName', so there will be  %%        no match, that is why we have 'AlterName'  case FileName of    "./"++AlterName -> ok;    _ -> AlterName = FileName  end,  FuncInfo = {LineNo,F,A},  OrginalName = Acc#tmpAcc.file,  case (FileName =:= OrginalName) orelse (AlterName =:= OrginalName) of    true -> %% Coming from original file      %% io:format("Added function ~p\n",[{LineNo, F,A}]),      FuncAcc    = Acc#tmpAcc.funcAcc++[FuncInfo],       IncFuncAcc = Acc#tmpAcc.incFuncAcc;    false ->      %% Coming from other sourses, including:      %%     -- .yrl (yecc-generated file)      %%     -- yeccpre.hrl (yecc-generated file)      %%     -- other cases      FuncAcc    = Acc#tmpAcc.funcAcc,      IncFuncAcc = Acc#tmpAcc.incFuncAcc++[{FileName,FuncInfo}]  end,  Acc#tmpAcc{funcAcc=FuncAcc,	     incFuncAcc=IncFuncAcc,	     dialyzerObj=NewDialyzerObj}.get_dialyzer_plt() ->  DialyzerDir = code:lib_dir(dialyzer),  Dialyzer_Init_Plt = filename:join([DialyzerDir,"plt","dialyzer_init_plt"]),  dialyzer_plt:from_file(typer_plt, Dialyzer_Init_Plt).

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?