1
%% -*- erlang-indent-level: 2 -*-
5
%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
7
%% The contents of this file are subject to the Erlang Public License,
8
%% Version 1.1, (the "License"); you may not use this file except in
9
%% compliance with the License. You should have received a copy of the
10
%% Erlang Public License along with this software. If not, it can be
11
%% retrieved online at http://www.erlang.org/.
13
%% Software distributed under the License is distributed on an "AS IS"
14
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
15
%% the License for the specific language governing rights and limitations
21
-module(typer_preprocess).
23
-export([get_all_files/2]).
25
-include("typer.hrl").
27
%%----------------------------------------------------------------------------
29
-spec get_all_files(#args{}, 'analysis' | 'trust') -> [string()].
31
get_all_files(Args, analysis) ->
32
case internal_get_all_files(Args#args.analyze,
33
Args#args.analyzed_dir_r,
34
fun test_erl_file_exclude_ann/1) of
35
[] -> typer:error("no file(s) to analyze");
38
get_all_files(Args, trust) ->
39
internal_get_all_files(Args#args.trust, [], fun test_erl_file/1).
41
-spec test_erl_file_exclude_ann(string()) -> boolean().
43
test_erl_file_exclude_ann(File) ->
44
case filename:extension(File) of
45
".erl" -> %% Exclude files ending with ".ann.erl"
46
case re:run(File, "[\.]ann[\.]erl$") of
53
-spec test_erl_file(string()) -> boolean().
55
test_erl_file(File) ->
56
filename:extension(File) =:= ".erl".
58
-spec internal_get_all_files([string()], [string()],
59
fun((string()) -> boolean())) -> [string()].
61
internal_get_all_files(File_Dir, Dir_R, Fun) ->
62
All_File_1 = process_file_and_dir(File_Dir, Fun),
63
All_File_2 = process_dir_recursively(Dir_R, Fun),
64
remove_dup(All_File_1 ++ All_File_2).
66
-spec process_file_and_dir([string()],
67
fun((string()) -> boolean())) -> [string()].
69
process_file_and_dir(File_Dir, TestFun) ->
72
case filelib:is_regular(Elem) of
73
true -> process_file(Elem, TestFun, Acc);
74
false -> check_dir(Elem, non_recursive, Acc, TestFun)
77
lists:foldl(Fun, [], File_Dir).
79
-spec process_dir_recursively([string()],
80
fun((string()) -> boolean())) -> [string()].
82
process_dir_recursively(Dirs, TestFun) ->
83
Fun = fun (Dir, Acc) ->
84
check_dir(Dir, recursive, Acc, TestFun)
86
lists:foldl(Fun, [], Dirs).
88
-spec check_dir(string(),
89
'non_recursive' | 'recursive',
91
fun((string()) -> boolean())) -> [string()].
93
check_dir(Dir, Mode, Acc, Fun) ->
94
case file:list_dir(Dir) of
96
{TmpDirs, TmpFiles} = split_dirs_and_files(Files, Dir),
99
FinalFiles = process_file_and_dir(TmpFiles, Fun),
102
TmpAcc1 = process_file_and_dir(TmpFiles, Fun),
103
TmpAcc2 = process_dir_recursively(TmpDirs, Fun),
104
Acc ++ TmpAcc1 ++ TmpAcc2
107
typer:error("no access permission to dir \""++Dir++"\"");
109
typer:error("cannot access "++Dir++": No such file or directory");
111
typer:error("error involving a use of file:list_dir/1")
114
%% Same order as the input list
115
-spec process_file(string(), fun((string()) -> boolean()), string()) -> [string()].
117
process_file(File, TestFun, Acc) ->
118
case TestFun(File) of
119
true -> Acc ++ [File];
123
%% Same order as the input list
124
-spec split_dirs_and_files([string()], string()) -> {[string()], [string()]}.
126
split_dirs_and_files(Elems, Dir) ->
128
fun (Elem, {DirAcc, FileAcc}) ->
129
File = filename:join(Dir, Elem),
130
case filelib:is_regular(File) of
131
false -> {[File|DirAcc], FileAcc};
132
true -> {DirAcc, [File|FileAcc]}
135
{Dirs, Files} = lists:foldl(Test_Fun, {[], []}, Elems),
136
{lists:reverse(Dirs), lists:reverse(Files)}.
138
%%-----------------------------------------------------------------------
140
%%-----------------------------------------------------------------------
142
%% Removes duplicate filenames but it keeps the order of the input list
144
-spec remove_dup([string()]) -> [string()].
147
Test_Dup = fun (File, Acc) ->
148
case lists:member(File, Acc) of
153
Reversed_Elems = lists:foldl(Test_Dup, [], Files),
154
lists:reverse(Reversed_Elems).