aboutsummaryrefslogtreecommitdiffstats
path: root/lib/typer/src/typer.erl
diff options
context:
space:
mode:
authorKostis Sagonas <[email protected]>2011-02-06 16:43:13 +0200
committerKostis Sagonas <[email protected]>2011-02-06 16:43:13 +0200
commit3562e3b44c2ad2df81eb192a2f69d939f73b9232 (patch)
tree86ef94a4fe3856b189f1832909b2d10ca4f94a15 /lib/typer/src/typer.erl
parent1f909eefa0e76bd219dbf933be0785d614057450 (diff)
downloadotp-3562e3b44c2ad2df81eb192a2f69d939f73b9232.tar.gz
otp-3562e3b44c2ad2df81eb192a2f69d939f73b9232.tar.bz2
otp-3562e3b44c2ad2df81eb192a2f69d939f73b9232.zip
Remove typer_preprocess.erl file
Diffstat (limited to 'lib/typer/src/typer.erl')
-rw-r--r--lib/typer/src/typer.erl139
1 files changed, 131 insertions, 8 deletions
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),
@@ -209,6 +211,127 @@ get_external(Exts, Plt) ->
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.
%%--------------------------------------------------------------------