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.

115 lines
3.6 KiB

(*
* Copyright (c) 2018-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.
*)
open! IStd
module F = Format
type breadcrumb =
| VariableDeclaration of Location.t
| Assignment of {lhs: HilExp.AccessExpression.t; location: Location.t}
| Capture of
{ captured_as: AccessPath.base
; captured: HilExp.AccessExpression.t
; location: Location.t }
| Call of
{ f: [`HilCall of HilInstr.call | `Model of string]
; actuals: HilExp.t list
; location: Location.t }
[@@deriving compare]
let pp_breadcrumb_no_location fmt = function
| VariableDeclaration _ ->
F.fprintf fmt "variable declared"
| Capture {captured_as; captured; location= _} ->
F.fprintf fmt "`%a` captured as `%a`" HilExp.AccessExpression.pp captured AccessPath.pp_base
captured_as
| Assignment {lhs; location= _} ->
F.fprintf fmt "assigned to `%a`" HilExp.AccessExpression.pp lhs
| Call {f; actuals; location= _} ->
let pp_f fmt = function
| `HilCall call ->
F.fprintf fmt "%a" HilInstr.pp_call call
| `Model model ->
F.pp_print_string fmt model
in
F.fprintf fmt "returned from call to `%a(%a)`" pp_f f (Pp.seq ~sep:"," HilExp.pp) actuals
let location_of_breadcrumb = function
| VariableDeclaration location | Assignment {location} | Capture {location} | Call {location} ->
location
let pp_breadcrumb fmt crumb =
F.fprintf fmt "%a at %a" pp_breadcrumb_no_location crumb Location.pp_line
(location_of_breadcrumb crumb)
let errlog_trace_elem_of_breadcrumb ~nesting crumb =
let location = location_of_breadcrumb crumb in
let description = F.asprintf "%a" pp_breadcrumb_no_location crumb in
let tags = [] in
Errlog.make_trace_element nesting location description tags
type t = breadcrumb list [@@deriving compare]
let pp f trace = Pp.seq ~print_env:Pp.text_break pp_breadcrumb f trace
let add_errlog_of_trace ~nesting trace errlog =
List.rev_map_append ~f:(errlog_trace_elem_of_breadcrumb ~nesting) trace errlog
let get_start_location = function [] -> None | crumb :: _ -> Some (location_of_breadcrumb crumb)
type 'a action =
| Immediate of {imm: 'a; location: Location.t}
| ViaCall of {action: 'a action; proc_name: Typ.Procname.t; location: Location.t}
[@@deriving compare]
let pp_action pp_immediate fmt = function
| Immediate {imm; _} ->
pp_immediate fmt imm
| ViaCall {proc_name; _} ->
F.fprintf fmt "call to `%a`" Typ.Procname.describe proc_name
let location_of_action_start = function
| Immediate {location; _} | ViaCall {location; _} ->
location
let rec immediate_of_action = function
| Immediate {imm; _} ->
imm
| ViaCall {action; _} ->
immediate_of_action action
let add_errlog_of_action ~nesting ~action_name pp_immediate action errlog =
let rec aux ~nesting rev_errlog action =
match action with
| Immediate {imm; location} ->
let rev_errlog =
Errlog.make_trace_element nesting location
(F.asprintf "%s %a here" action_name pp_immediate imm)
[]
:: rev_errlog
in
List.rev_append rev_errlog errlog
| ViaCall {action; proc_name; location} ->
aux ~nesting:(nesting + 1)
( Errlog.make_trace_element nesting location
(F.asprintf "%s during call to `%a` here" action_name Typ.Procname.describe proc_name)
[]
:: rev_errlog )
action
in
aux ~nesting [] action
let outer_location_of_action = function Immediate {location} | ViaCall {location} -> location