forked from facebookarchive/pfff
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main_scheck_heavy.ml
211 lines (165 loc) · 6.28 KB
/
main_scheck_heavy.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
(*
* The author disclaims copyright to this source code. In place of
* a legal notice, here is a blessing:
*
* May you do good and not evil.
* May you find forgiveness for yourself and forgive others.
* May you share freely, never taking more than you give.
*)
open Common
open Ast_php
module Ast = Ast_php
module V = Visitor_php
module S = Scope_code
(*****************************************************************************)
(* Purpose *)
(*****************************************************************************)
(* A lint-like checker for PHP using (expensive) global analysis.
* See also main_scheck.ml
*)
(*****************************************************************************)
(* Flags *)
(*****************************************************************************)
let verbose = ref false
(* action mode *)
let action = ref ""
(* no -heavy or -depth_limit or -php_stdlib or -cache_parse here *)
let metapath = ref "/tmp/pfff_db"
let strict_scope = ref false
let rank = ref true
let layer_file = ref (None: filename option)
(*****************************************************************************)
(* Helpers *)
(*****************************************************************************)
(*****************************************************************************)
(* Wrappers *)
(*****************************************************************************)
let pr2_dbg s =
if !verbose then Common.pr2 s
(*****************************************************************************)
(* Main action *)
(*****************************************************************************)
(* mostly a copy paste of main_scheck.ml but now use metapath *)
let main_action xs =
let files = Lib_parsing_php.find_php_files_of_dir_or_files xs in
let errors = ref [] in
Flag_parsing_php.show_parsing_error := false;
Flag_parsing_php.verbose_lexing := false;
Database_php.with_db ~metapath:!metapath (fun db ->
let find_entity = Some (Database_php_build.build_entity_finder db) in
files +> Common.index_list_and_total +> List.iter (fun (file, i, total) ->
try
pr2_dbg (spf "processing: %s (%d/%d)" file i total);
Check_all_php.check_file ~find_entity file;
with
| (Timeout | UnixExit _) as exn -> raise exn
| exn ->
Common.push2 (spf "PB with %s, exn = %s" file
(Common.string_of_exn exn)) errors;
);
let errs = !Error_php._errors +> List.rev in
let errs =
if !rank
then Error_php.rank_errors errs +> Common.take_safe 20
else errs
in
errs +> List.iter (fun err -> pr (Error_php.string_of_error err));
Error_php.show_10_most_recurring_unused_variable_names ();
pr2 (spf "total errors = %d" (List.length !Error_php._errors));
pr2 "";
!errors +> List.iter pr2;
pr2 "";
!layer_file +> Common.do_option (fun file ->
(* a layer needs readable paths, hence the root *)
let root = Common.common_prefix_of_files_or_dirs xs in
Layer_checker_php.gen_layer ~root ~output:file !Error_php._errors
);
)
(*****************************************************************************)
(* Extra actions *)
(*****************************************************************************)
(*---------------------------------------------------------------------------*)
(* the command line flags *)
(*---------------------------------------------------------------------------*)
let scheck_extra_actions () = [
]
(*****************************************************************************)
(* The options *)
(*****************************************************************************)
let all_actions () =
scheck_extra_actions()++
[]
let options () =
[
"-metapath", Arg.Set_string metapath,
"<dir> (default=" ^ !metapath ^ ")";
"-strict", Arg.Set strict_scope,
" emulate block scope instead of function scope";
"-no_scrict_scope", Arg.Clear strict_scope,
" use function scope (default)";
"-no_rank", Arg.Clear rank,
" ";
"-gen_layer", Arg.String (fun s -> layer_file := Some s),
" <file> save result in pfff layer file";
"-verbose", Arg.Set verbose,
" ";
] ++
Flag_analyze_php.cmdline_flags_verbose () ++
Common.options_of_actions action (all_actions()) ++
Common.cmdline_flags_devel () ++
Common.cmdline_flags_verbose () ++
Common.cmdline_flags_other () ++
[
"-version", Arg.Unit (fun () ->
pr2 (spf "scheck version: %s" Config.version);
exit 0;
),
" guess what";
(* this can not be factorized in Common *)
"-date", Arg.Unit (fun () ->
pr2 "version: $Date: 2010/04/25 00:44:57 $";
raise (Common.UnixExit 0)
),
" guess what";
] ++
[]
(*****************************************************************************)
(* Main entry point *)
(*****************************************************************************)
let main () =
Common_extra.set_link();
Database_php_storage.set_link();
let usage_msg =
"Usage: " ^ Common.basename Sys.argv.(0) ^
" [options] <file or dir> " ^ "\n" ^ "Options are:"
in
(* does side effect on many global flags *)
let args = Common.parse_options (options()) usage_msg Sys.argv in
(* must be done after Arg.parse, because Common.profile is set by it *)
Common.profile_code "Main total" (fun () ->
(match args with
(* --------------------------------------------------------- *)
(* actions, useful to debug subpart *)
(* --------------------------------------------------------- *)
| xs when List.mem !action (Common.action_list (all_actions())) ->
Common.do_action !action xs (all_actions())
| _ when not (Common.null_string !action) ->
failwith ("unrecognized action or wrong params: " ^ !action)
(* --------------------------------------------------------- *)
(* main entry *)
(* --------------------------------------------------------- *)
| x::xs ->
main_action (x::xs)
(* --------------------------------------------------------- *)
(* empty entry *)
(* --------------------------------------------------------- *)
| [] ->
Common.usage usage_msg (options());
failwith "too few arguments"
)
)
(*****************************************************************************)
let _ =
Common.main_boilerplate (fun () ->
main ();
)