From 3562e3b44c2ad2df81eb192a2f69d939f73b9232 Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Sun, 6 Feb 2011 16:43:13 +0200 Subject: Remove typer_preprocess.erl file --- lib/typer/src/typer.erl | 139 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 131 insertions(+), 8 deletions(-) (limited to 'lib/typer/src/typer.erl') diff --git a/lib/typer/src/typer.erl b/lib/typer/src/typer.erl index c1406cdbbe..3f1302ecc9 100644 --- a/lib/typer/src/typer.erl +++ b/lib/typer/src/typer.erl @@ -45,18 +45,20 @@ %%----------------------------------------------------------------------- +-type files() :: [file:filename()]. + -record(typer_analysis, {mode :: mode(), macros = [] :: [{atom(), term()}], % {macro_name, value} - includes = [] :: [file:filename()], + includes = [] :: files(), %% --- for dialyzer --- code_server = dialyzer_codeserver:new():: dialyzer_codeserver:codeserver(), callgraph = dialyzer_callgraph:new() :: dialyzer_callgraph:callgraph(), - ana_files = [] :: [file:filename()], % absolute filenames + ana_files = [] :: files(), % absolute names plt = none :: 'none' | file:filename(), no_spec = false :: boolean(), %% --- for typer --- - t_files = [] :: [file:filename()], + t_files = [] :: files(), %% For choosing between contracts or comments contracts = true :: boolean(), %% Files in 'final_files' are compilable with option 'to_pp'; we keep @@ -69,9 +71,9 @@ trust_plt = dialyzer_plt:new() :: dialyzer_plt:plt()}). -type analysis() :: #typer_analysis{}. --record(args, {files = [] :: [file:filename()], - files_r = [] :: [file:filename()], - trusted = [] :: [file:filename()]}). +-record(args, {files = [] :: files(), + files_r = [] :: files(), + trusted = [] :: files()}). %%-------------------------------------------------------------------- @@ -81,10 +83,10 @@ start() -> {Args, Analysis} = typer_options:process(), %% io:format("Args: ~p\n", [Args]), %% io:format("Analysis: ~p\n", [Analysis]), - TrustedFiles = typer_preprocess:get_all_files(Args, trust), + TrustedFiles = filter_fd(Args#args.trusted, [], fun is_erl_file/1), Analysis1 = Analysis#typer_analysis{t_files = TrustedFiles}, Analysis2 = extract(Analysis1), - All_Files = typer_preprocess:get_all_files(Args, analysis), + All_Files = get_all_files(Args), %% io:format("All_Files: ~p\n", [All_Files]), Analysis3 = Analysis2#typer_analysis{ana_files = All_Files}, Analysis4 = typer_info:collect(Analysis3), @@ -208,6 +210,127 @@ get_external(Exts, Plt) -> end, lists:foldl(Fun, [], Exts). +%%-------------------------------------------------------------------- +%% File processing. +%%-------------------------------------------------------------------- + +-spec get_all_files(#args{}) -> files(). + +get_all_files(#args{files = Fs,files_r = Ds}) -> + case filter_fd(Fs, Ds, fun test_erl_file_exclude_ann/1) of + [] -> fatal_error("no file(s) to analyze"); + AllFiles -> AllFiles + end. + +-spec test_erl_file_exclude_ann(file:filename()) -> boolean(). + +test_erl_file_exclude_ann(File) -> + case is_erl_file(File) of + true -> %% Exclude files ending with ".ann.erl" + case re:run(File, "[\.]ann[\.]erl$") of + {match, _} -> false; + nomatch -> true + end; + false -> false + end. + +-spec is_erl_file(file:filename()) -> boolean(). + +is_erl_file(File) -> + filename:extension(File) =:= ".erl". + +-type test_file_fun() :: fun((file:filename()) -> boolean()). + +-spec filter_fd(files(), files(), test_file_fun()) -> files(). + +filter_fd(File_Dir, Dir_R, Fun) -> + All_File_1 = process_file_and_dir(File_Dir, Fun), + All_File_2 = process_dir_rec(Dir_R, Fun), + remove_dup(All_File_1 ++ All_File_2). + +-spec process_file_and_dir(files(), test_file_fun()) -> files(). + +process_file_and_dir(File_Dir, TestFun) -> + Fun = + fun (Elem, Acc) -> + case filelib:is_regular(Elem) of + true -> process_file(Elem, TestFun, Acc); + false -> check_dir(Elem, false, Acc, TestFun) + end + end, + lists:foldl(Fun, [], File_Dir). + +-spec process_dir_rec(files(), test_file_fun()) -> files(). + +process_dir_rec(Dirs, TestFun) -> + Fun = fun (Dir, Acc) -> check_dir(Dir, true, Acc, TestFun) end, + lists:foldl(Fun, [], Dirs). + +-spec check_dir(file:filename(), boolean(), files(), test_file_fun()) -> files(). + +check_dir(Dir, Recursive, Acc, Fun) -> + case file:list_dir(Dir) of + {ok, Files} -> + {TmpDirs, TmpFiles} = split_dirs_and_files(Files, Dir), + case Recursive of + false -> + FinalFiles = process_file_and_dir(TmpFiles, Fun), + Acc ++ FinalFiles; + true -> + TmpAcc1 = process_file_and_dir(TmpFiles, Fun), + TmpAcc2 = process_dir_rec(TmpDirs, Fun), + Acc ++ TmpAcc1 ++ TmpAcc2 + end; + {error, eacces} -> + fatal_error("no access permission to dir \""++Dir++"\""); + {error, enoent} -> + fatal_error("cannot access "++Dir++": No such file or directory"); + {error, _Reason} -> + fatal_error("error involving a use of file:list_dir/1") + end. + +%% Same order as the input list +-spec process_file(file:filename(), test_file_fun(), files()) -> files(). + +process_file(File, TestFun, Acc) -> + case TestFun(File) of + true -> Acc ++ [File]; + false -> Acc + end. + +%% Same order as the input list +-spec split_dirs_and_files(files(), file:filename()) -> {files(), files()}. + +split_dirs_and_files(Elems, Dir) -> + Test_Fun = + fun (Elem, {DirAcc, FileAcc}) -> + File = filename:join(Dir, Elem), + case filelib:is_regular(File) of + false -> {[File|DirAcc], FileAcc}; + true -> {DirAcc, [File|FileAcc]} + end + end, + {Dirs, Files} = lists:foldl(Test_Fun, {[], []}, Elems), + {lists:reverse(Dirs), lists:reverse(Files)}. + +%%----------------------------------------------------------------------- +%% Utilities +%%----------------------------------------------------------------------- + +%% Removes duplicate filenames but it keeps the order of the input list + +-spec remove_dup(files()) -> files(). + +remove_dup(Files) -> + Test_Dup = fun (File, Acc) -> + case lists:member(File, Acc) of + true -> Acc; + false -> [File|Acc] + end + end, + Reversed_Elems = lists:foldl(Test_Dup, [], Files), + lists:reverse(Reversed_Elems). + %%-------------------------------------------------------------------- %% Utilities for error reporting. %%-------------------------------------------------------------------- -- cgit v1.2.3