[specs] move specs file functionality into summary

Summary: As per title.  Eases next diffs by making Summary the only source of truth for how spec files are accessed/stored.

Reviewed By: ezgicicek

Differential Revision: D22794742

fbshipit-source-id: 0ee20ec1c
master
Nikos Gorogiannis 4 years ago committed by Facebook GitHub Bot
parent 0475e79d0e
commit fe617afa49

@ -201,7 +201,8 @@ let invalidate_changed_procedures changed_files =
let invalidated_nodes =
CallGraph.fold_flagged reverse_callgraph
~f:(fun node acc ->
SpecsFiles.delete node.pname ;
Ondemand.LocalCache.remove node.pname ;
Summary.OnDisk.delete node.pname ;
acc + 1 )
0
in

@ -14,4 +14,4 @@ let register_summary graph summary =
callee_pnames
let build graph = SpecsFiles.iter ~f:(register_summary graph)
let build graph = Summary.OnDisk.iter_specs ~f:(register_summary graph)

@ -1,71 +0,0 @@
(*
* 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 F = Format
module L = Logging
module CLOpt = CommandLineOption
(** return the list of the .specs files in the results dir *)
let load_specfiles () =
let is_specs_file fname = Filename.check_suffix fname Config.specs_files_suffix in
let do_file acc path = 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
Utils.directory_fold do_file [] 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)) && not (String.equal 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.OnDisk.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
let delete pname =
let filename = Summary.OnDisk.specs_filename_of_procname pname |> DB.filename_to_string in
(* Unix_error is raised if the file isn't present so do nothing in this case *)
(try Unix.unlink filename with Unix.Unix_error _ -> ()) ;
Ondemand.LocalCache.remove pname ;
Summary.OnDisk.remove_from_cache pname
let pp_from_config fmt =
iter_from_config ~f:(fun summary ->
F.fprintf fmt "Procedure: %a@\n%a@." Procname.pp (Summary.get_proc_name summary)
Summary.pp_text summary )

@ -1,21 +0,0 @@
(*
* 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
val iter : f:(Summary.t -> unit) -> unit
(** 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 *)
val delete : Procname.t -> unit
(** Delete the .specs file associated with a summary and remove the summary from the caches in
Summary.ml and ondemand.ml *)
val pp_from_config : Format.formatter -> unit

@ -95,7 +95,7 @@ let whole_program_analysis () =
let work_set = WorkHashSet.create 1 in
let exe_env = Exe_env.mk () in
L.progress "Processing on-disk summaries...@." ;
SpecsFiles.iter ~f:(iter_summary exe_env ~f:(WorkHashSet.add_pairs work_set)) ;
Summary.OnDisk.iter_specs ~f:(iter_summary exe_env ~f:(WorkHashSet.add_pairs work_set)) ;
L.progress "Loaded %d pairs@." (WorkHashSet.length work_set) ;
L.progress "Reporting on processed summaries...@." ;
report exe_env work_set

@ -8,6 +8,8 @@
open! IStd
module F = Format
module L = Logging
module CLOpt = CommandLineOption
module Stats = struct
type t =
@ -123,6 +125,8 @@ module OnDisk = struct
let clear_cache () = Procname.Hash.clear cache
(** Remove an element from the cache of summaries. Contrast to reset which re-initializes a
summary keeping the same Procdesc and updates the cache accordingly. *)
let remove_from_cache pname = Procname.Hash.remove cache pname
(** Add the summary to the table for the given function *)
@ -238,4 +242,65 @@ module OnDisk = struct
Serialization.write_to_file summary_serializer filename ~data:blank_summary )
in
Procedures.get_all ~filter () |> List.iter ~f:reset
let delete pname =
let filename = specs_filename_of_procname pname |> DB.filename_to_string in
(* Unix_error is raised if the file isn't present so do nothing in this case *)
(try Unix.unlink filename with Unix.Unix_error _ -> ()) ;
remove_from_cache pname
(** return the list of the .specs files in the results dir *)
let load_specfiles () =
let is_specs_file fname = Filename.check_suffix fname Config.specs_files_suffix in
let do_file acc path = 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
Utils.directory_fold do_file [] 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))
&& not (String.equal 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 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_specs_from_config ~f = summary_iterator spec_files_from_cmdline f
let iter_specs ~f = summary_iterator load_specfiles f
let pp_specs_from_config fmt =
iter_specs_from_config ~f:(fun summary ->
F.fprintf fmt "Procedure: %a@\n%a@." Procname.pp (get_proc_name summary) pp_text summary )
end

@ -65,22 +65,12 @@ module OnDisk : sig
val clear_cache : unit -> unit
(** Remove all the elements from the cache of summaries *)
val remove_from_cache : Procname.t -> unit
(** Remove an element from the cache of summaries. Contrast to reset which re-initializes a
summary keeping the same Procdesc and updates the cache accordingly. *)
val get : Procname.t -> t option
(** Return the summary option for the procedure name *)
val reset : Procdesc.t -> t
(** Reset a summary rebuilding the dependents and preserving the proc attributes if present. *)
val specs_filename_of_procname : Procname.t -> DB.filename
(** Return the path to the .specs file for the given procedure in the current results directory *)
val load_from_file : DB.filename -> t option
(** Load procedure summary from the given file *)
val proc_resolve_attributes : Procname.t -> ProcAttributes.t option
(** Try to find the attributes for a defined proc. First look at specs (to get attributes computed
by analysis) then look at the attributes table. If no attributes can be found, return None. *)
@ -89,4 +79,17 @@ module OnDisk : sig
(** Save summary for the procedure into the spec database *)
val reset_all : filter:Filtering.procedures_filter -> unit -> unit
val delete : Procname.t -> unit
(** Delete the .specs file corresponding to the procname and remove its summary from the Summary
cache *)
val iter_specs : f:(t -> unit) -> unit
(** Iterates over all summaries from the .specs files *)
val iter_specs_from_config : f:(t -> unit) -> unit
(** Iterates over all sumaries from the .specs files unless a list of specs files has been passed
on the command line *)
val pp_specs_from_config : Format.formatter -> unit
end

@ -191,7 +191,7 @@ let () =
in
match (Config.issues_tests, Config.cost_issues_tests) with
| None, None ->
if not Config.quiet then L.result "%t" SpecsFiles.pp_from_config
if not Config.quiet then L.result "%t" Summary.OnDisk.pp_specs_from_config
| Some out_path, Some cost_out_path ->
write_from_json out_path ;
write_from_cost_json cost_out_path

@ -314,7 +314,7 @@ let process_all_summaries_and_issues ~issues_outf ~costs_outf =
let linereader = LineReader.create () in
let filters = Inferconfig.create_filters () in
let all_issues = ref [] in
SpecsFiles.iter_from_config ~f:(fun summary ->
Summary.OnDisk.iter_specs_from_config ~f:(fun summary ->
all_issues := process_summary ~costs_outf summary !all_issues ) ;
all_issues := Issue.sort_filter_issues !all_issues ;
List.iter

Loading…
Cancel
Save