Summary: # Current design Infer analysis is currently two staged: 1) proc-level callbacks calculate summary, including writing down the issues if applicable. 2) file-level callbacks (formerly cluster callbacks, see the prev diff) are executed next; they are supposed to emit additional issues that are impossible to emit based on mere proc-context. Currently RacerD and Starvation use file-level callback; in near future we plan to onboard Nullsafe checker as well. # Problem Contract of callback (1) is clear: given a proc and existing summary, the checker updates it and returns a modified summary. This summary later on gets serialized (in-memory + external) and can be consumed by other chechers. Issues written in summary will get reported when analysis is over. In constrast, contract of (2) is wild west: the function returns unit. In practice, what the checkers do is create IssueLog and serialize it to checker-specific directory. Then another part of program (InferPrint.ml) knows about this side effect, reads the error log for checkers and ultimately get it reported together with errors written at stage (1). This is problematic because it is hard to reason about the system and it makes onboarding new checkers to (2) error-prone. # This diff This diff brings (2) on par with (1): now file-level callback has a clear contract: it should be side effect free, and the only responsibility is to fill out and return IssueLog. Additionally, we make the notion of "checker-specific issue directory" an official thing, so the checker only needs to specify the name, everything else will be made automatically by orchestation layer, including cleanup. # Starvation Implementing the new contract is starvation is possible and desirable, but involved: see comment in the code, so we leave it up to the future work to fix that. Reviewed By: ngorogiannis Differential Revision: D20115024 fbshipit-source-id: fb2f9b7e6master
parent
c2a53a1334
commit
73e78d9e20
@ -0,0 +1,15 @@
|
|||||||
|
(*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
let dir_names = ref []
|
||||||
|
|
||||||
|
let get_registered_dir_names () = !dir_names
|
||||||
|
|
||||||
|
let register_dir_name name =
|
||||||
|
if not (List.exists !dir_names ~f:(String.equal name)) then dir_names := name :: !dir_names
|
@ -0,0 +1,16 @@
|
|||||||
|
(*
|
||||||
|
* 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 get_registered_dir_names : unit -> string list
|
||||||
|
(** Directory names responsible for storing checker-specific issues generated at file-level analysis
|
||||||
|
phase. (Those are additional issues on top of ones stored in summary after procedure analysis
|
||||||
|
phase). *)
|
||||||
|
|
||||||
|
val register_dir_name : string -> unit
|
||||||
|
(** Add directory name. No-op if was already added *)
|
Loading…
Reference in new issue