You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
3.7 KiB
101 lines
3.7 KiB
(*
|
|
* Copyright (c) 2009-2013, Monoidics ltd.
|
|
* Copyright (c) 2013-present, Facebook, Inc.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*)
|
|
|
|
(** Main module for the analysis after the capture phase *)
|
|
open! IStd
|
|
module L = Logging
|
|
|
|
let clear_caches () =
|
|
Ondemand.clear_cache () ;
|
|
Summary.clear_cache () ;
|
|
Typ.Procname.SQLite.clear_cache ()
|
|
|
|
|
|
(** Create tasks to analyze an execution environment *)
|
|
let analyze_source_file : SourceFile.t Tasks.doer =
|
|
fun source_file ->
|
|
DB.Results_dir.init source_file ;
|
|
let exe_env = Exe_env.mk () in
|
|
L.(debug Analysis Medium) "@\nProcessing '%a'@." SourceFile.pp source_file ;
|
|
(* clear cache for each source file to avoid it growing unboundedly *)
|
|
clear_caches () ;
|
|
Callbacks.analyze_file exe_env source_file ;
|
|
if Config.write_html then Printer.write_all_html_files source_file
|
|
|
|
|
|
let output_json_makefile_stats clusters =
|
|
let num_files = List.length clusters in
|
|
let num_procs = 0 in
|
|
(* can't compute it at this stage *)
|
|
let num_lines = 0 in
|
|
let file_stats =
|
|
`Assoc [("files", `Int num_files); ("procedures", `Int num_procs); ("lines", `Int num_lines)]
|
|
in
|
|
(* write stats file to disk, intentionally overwriting old file if it already exists *)
|
|
let f = Out_channel.create (Filename.concat Config.results_dir Config.proc_stats_filename) in
|
|
Yojson.Basic.pretty_to_channel f file_stats
|
|
|
|
|
|
let source_file_should_be_analyzed ~changed_files source_file =
|
|
(* whether [fname] is one of the [changed_files] *)
|
|
let is_changed_file = Option.map changed_files ~f:(SourceFile.Set.mem source_file) in
|
|
let check_modified () =
|
|
let modified = SourceFiles.is_freshly_captured source_file in
|
|
if modified then L.debug Analysis Medium "Modified: %a@\n" SourceFile.pp source_file ;
|
|
modified
|
|
in
|
|
match is_changed_file with
|
|
| Some b ->
|
|
b
|
|
| None when Config.reactive_mode ->
|
|
check_modified ()
|
|
| None ->
|
|
true
|
|
|
|
|
|
let register_active_checkers () =
|
|
match Config.analyzer with
|
|
| Checkers | Crashcontext ->
|
|
RegisterCheckers.get_active_checkers () |> RegisterCheckers.register
|
|
| CaptureOnly | CompileOnly | Linters ->
|
|
()
|
|
|
|
|
|
let main ~changed_files =
|
|
( match Config.modified_targets with
|
|
| Some file ->
|
|
MergeCapture.record_modified_targets_from_file file
|
|
| None ->
|
|
() ) ;
|
|
register_active_checkers () ;
|
|
(* delete all specs when doing a full analysis so that we do not report on procedures that do
|
|
not exist anymore *)
|
|
if not Config.reactive_mode then DB.Results_dir.clean_specs_dir () ;
|
|
let all_source_files = SourceFiles.get_all () in
|
|
let source_files_to_analyze =
|
|
List.filter ~f:(source_file_should_be_analyzed ~changed_files) all_source_files
|
|
in
|
|
let n_source_files = List.length source_files_to_analyze in
|
|
L.progress "Found %d%s source file%s to analyze in %s@." n_source_files
|
|
( if Config.reactive_mode || Option.is_some changed_files then
|
|
" (out of " ^ string_of_int (List.length all_source_files) ^ ")"
|
|
else "" )
|
|
(if Int.equal n_source_files 1 then "" else "s")
|
|
Config.results_dir ;
|
|
(* empty all caches to minimize the process heap to have less work to do when forking *)
|
|
clear_caches () ;
|
|
if Int.equal Config.jobs 1 then (
|
|
Tasks.run_sequentially ~f:analyze_source_file source_files_to_analyze ;
|
|
L.progress "@\nAnalysis finished in %as@." Pp.elapsed_time () )
|
|
else (
|
|
L.environment_info "Parallel jobs: %d@." Config.jobs ;
|
|
(* Prepare tasks one cluster at a time while executing in parallel *)
|
|
let runner = Tasks.Runner.create ~jobs:Config.jobs ~f:analyze_source_file in
|
|
Tasks.Runner.run runner ~tasks:source_files_to_analyze ) ;
|
|
output_json_makefile_stats source_files_to_analyze
|