/main_scheck_heavy.ml

https://github.com/repos-ocaml/pfff · OCaml · 211 lines · 110 code · 46 blank · 55 comment · 3 complexity · 89f93843f633bc7b52167cdf64160fe3 MD5 · raw file

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