Write function to load specfiles

Summary:
Write a function to read in the summaries from the `.specs` folder

This is needed so the reverse analysis call graph can be constructed from the summaries

Reviewed By: ngorogiannis

Differential Revision: D16282333

fbshipit-source-id: 101ce2c5b
master
Phoebe Nichols 5 years ago committed by Facebook Github Bot
parent f47d4ed285
commit af8c57e07f

@ -6,30 +6,10 @@
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module CLOpt = CommandLineOption
module Hashtbl = Caml.Hashtbl
module L = Logging
module F = Format
let print_usage_exit err_s =
L.user_error "Load Error: %s@\n@." err_s ;
Config.print_usage_exit ()
(** return the list of the .specs files in the results dir and libs, if they're defined *)
let load_specfiles () =
let specs_files_in_dir dir =
let is_specs_file fname =
Sys.is_directory fname <> `Yes && Filename.check_suffix fname Config.specs_files_suffix
in
let all_filenames = try Array.to_list (Sys.readdir dir) with Sys_error _ -> [] in
let all_filepaths = List.map ~f:(fun fname -> Filename.concat dir fname) all_filenames in
List.filter ~f:is_specs_file all_filepaths
in
let result_specs_dir = DB.filename_to_string DB.Results_dir.specs_dir in
specs_files_in_dir result_specs_dir
let error_desc_to_plain_string error_desc =
let pp fmt = Localise.pp_error_desc fmt error_desc in
let s = F.asprintf "%t" pp in
@ -1089,34 +1069,6 @@ let process_summary filters formats_by_report_kind linereader stats summary issu
issues_acc'
let spec_files_from_cmdline () =
if CLOpt.is_originator then (
(* Find spec files specified by command-line arguments. Not run at init time since the specs
files may be generated between init and report time. *)
List.iter
~f:(fun arg ->
if (not (Filename.check_suffix arg Config.specs_files_suffix)) && arg <> "." then
print_usage_exit ("file " ^ arg ^ ": arguments must be .specs files") )
Config.anon_args ;
if Config.test_filtering then ( Inferconfig.test () ; L.exit 0 ) ;
if List.is_empty Config.anon_args then load_specfiles () else List.rev Config.anon_args )
else load_specfiles ()
(** Create an iterator which loads spec files one at a time *)
let get_summary_iterator () =
let sorted_spec_files = List.sort ~compare:String.compare (spec_files_from_cmdline ()) in
let do_spec f fname =
match Summary.load_from_file (DB.filename_from_string fname) with
| None ->
L.(die UserError) "Error: cannot open file %s@." fname
| Some summary ->
f summary
in
let iterate f = List.iter ~f:(do_spec f) sorted_spec_files in
iterate
(** Although the out_file is an Option type, the None option is strictly meant for the
logs format_kind, and all other formats should contain an outfile value. *)
let mk_format format_kind fname =
@ -1205,9 +1157,8 @@ let pp_summary_and_issues formats_by_report_kind issue_formats =
let stats = Stats.create () in
let linereader = Printer.LineReader.create () in
let filters = Inferconfig.create_filters () in
let iterate_summaries = get_summary_iterator () in
let all_issues = ref [] in
iterate_summaries (fun summary ->
SpecsFiles.iter_from_config ~f:(fun summary ->
all_issues :=
process_summary filters formats_by_report_kind linereader stats summary !all_issues ) ;
all_issues := Issue.sort_filter_issues !all_issues ;

@ -0,0 +1,65 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
module L = Logging
module CLOpt = CommandLineOption
(** return the list of the .specs files in the results dir and libs, if they're defined *)
let load_specfiles () =
let specs_files_in_dir dir =
let is_specs_file fname =
Sys.is_directory fname <> `Yes && Filename.check_suffix fname Config.specs_files_suffix
in
match Sys.readdir dir with
| exception Sys_error _ ->
[]
| files ->
Array.fold files ~init:[] ~f:(fun acc fname ->
let path = Filename.concat dir fname in
if is_specs_file path then path :: acc else acc )
in
let result_specs_dir = DB.filename_to_string DB.Results_dir.specs_dir in
specs_files_in_dir result_specs_dir
let print_usage_exit err_s =
L.user_error "Load Error: %s@\n@." err_s ;
Config.print_usage_exit ()
let spec_files_from_cmdline () =
if CLOpt.is_originator then (
(* Find spec files specified by command-line arguments. Not run at init time since the specs
files may be generated between init and report time. *)
List.iter
~f:(fun arg ->
if (not (Filename.check_suffix arg Config.specs_files_suffix)) && arg <> "." then
print_usage_exit ("file " ^ arg ^ ": arguments must be .specs files") )
Config.anon_args ;
if Config.test_filtering then ( Inferconfig.test () ; L.exit 0 ) ;
if List.is_empty Config.anon_args then load_specfiles () else List.rev Config.anon_args )
else load_specfiles ()
(** Create an iterator which loads spec files one at a time *)
let summary_iterator spec_files =
let sorted_spec_files = List.sort ~compare:String.compare (spec_files ()) in
let do_spec f fname =
match Summary.load_from_file (DB.filename_from_string fname) with
| None ->
L.(die UserError) "Error: cannot open file %s@." fname
| Some summary ->
f summary
in
let iterate f = List.iter ~f:(do_spec f) sorted_spec_files in
iterate
let iter_from_config ~f = summary_iterator spec_files_from_cmdline f
let iter ~f = summary_iterator load_specfiles f

@ -0,0 +1,18 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
(* Suppress unused value warning because this method is intended for incremental analysis, which is
not yet finished *)
val iter : f:(Summary.t -> unit) -> unit
[@@warning "-32"]
(** Iterates over all summaries from the .specs files *)
val iter_from_config : f:(Summary.t -> unit) -> unit
(** Iterates over all sumaries from the .specs files unless a list of specs files has been passed on
the command line *)
Loading…
Cancel
Save