move Printer.LineReader to its own file in base/

Summary: So it can be used by dune libraries without depending on backend/.

Reviewed By: dulmarod

Differential Revision: D21351908

fbshipit-source-id: d288f9179
master
Jules Villard 5 years ago committed by Facebook GitHub Bot
parent c0440f29ae
commit 3e3b5b1f1d

@ -14,56 +14,6 @@ module Hashtbl = Caml.Hashtbl
module L = Logging
module F = Format
(** Module to read specific lines from files. The data from any file will stay in memory until the
handle is collected by the gc. *)
module LineReader = struct
(** Map a file name to an array of string, one for each line in the file. *)
type t = (SourceFile.t, string array) Hashtbl.t
let create () = Hashtbl.create 1
let read_file fname =
let cin = In_channel.create fname in
let lines = ref [] in
try
while true do
let line_raw = In_channel.input_line_exn cin in
let line =
let len = String.length line_raw in
if len > 0 && Char.equal line_raw.[len - 1] '\r' then
String.sub line_raw ~pos:0 ~len:(len - 1)
else line_raw
in
lines := line :: !lines
done ;
assert false (* execution never reaches here *)
with End_of_file -> In_channel.close cin ; Array.of_list_rev !lines
let file_data (hash : t) fname =
try Some (Hashtbl.find hash fname)
with Caml.Not_found -> (
try
let lines_arr = read_file (SourceFile.to_abs_path fname) in
Hashtbl.add hash fname lines_arr ; Some lines_arr
with exn when SymOp.exn_not_failure exn -> None )
let from_file_linenum hash fname linenum =
match file_data hash fname with
| Some lines_arr when linenum > 0 && linenum <= Array.length lines_arr ->
Some lines_arr.(linenum - 1)
| _ ->
None
let from_loc hash loc = from_file_linenum hash loc.Location.file loc.Location.line
let iter hash fname ~f =
file_data hash fname
|> Option.iter ~f:(Array.iteri ~f:(fun linenum line -> f (linenum + 1) line))
end
(** Current formatter for the html output *)
let curr_html_formatter = ref F.std_formatter
@ -273,7 +223,7 @@ end = struct
() ) ;
F.fprintf fmt "</td></tr>@\n"
in
LineReader.iter linereader filename ~f:print_one_line ;
LineReader.iteri linereader filename ~f:print_one_line ;
F.fprintf fmt "</table>@\n" ;
Errlog.pp_html filename [fname_encoding] fmt global_err_log ;
Io_infer.Html.close (fd, fmt)

@ -10,18 +10,6 @@ open! IStd
(** Printers for the analysis results *)
(** Module to read specific lines from files. The data from any file will stay in memory until the
handle is collected by the gc *)
module LineReader : sig
type t
val create : unit -> t
(** create a line reader *)
val from_loc : t -> Location.t -> string option
(** get the line from a location looking for the copy of the file in the results dir *)
end
val curr_html_formatter : Format.formatter ref
(** Current html formatter *)

@ -0,0 +1,55 @@
(*
* Copyright (c) 2009-2013, Monoidics ltd.
* 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 Hashtbl = Caml.Hashtbl
(** Map a file name to an array of string, one for each line in the file. *)
type t = (SourceFile.t, string array) Hashtbl.t
let create () = Hashtbl.create 1
let read_file fname =
let cin = In_channel.create fname in
let lines = ref [] in
try
while true do
let line_raw = In_channel.input_line_exn cin in
let line =
let len = String.length line_raw in
if len > 0 && Char.equal line_raw.[len - 1] '\r' then
String.sub line_raw ~pos:0 ~len:(len - 1)
else line_raw
in
lines := line :: !lines
done ;
assert false (* execution never reaches here *)
with End_of_file -> In_channel.close cin ; Array.of_list_rev !lines
let file_data (hash : t) fname =
try Some (Hashtbl.find hash fname)
with Caml.Not_found -> (
try
let lines_arr = read_file (SourceFile.to_abs_path fname) in
Hashtbl.add hash fname lines_arr ; Some lines_arr
with exn when SymOp.exn_not_failure exn -> None )
let from_file_linenum hash fname linenum =
match file_data hash fname with
| Some lines_arr when linenum > 0 && linenum <= Array.length lines_arr ->
Some lines_arr.(linenum - 1)
| _ ->
None
let from_loc hash loc = from_file_linenum hash loc.Location.file loc.Location.line
let iteri hash fname ~f =
file_data hash fname |> Option.iter ~f:(Array.iteri ~f:(fun linenum line -> f (linenum + 1) line))

@ -0,0 +1,22 @@
(*
* Copyright (c) 2009-2013, Monoidics ltd.
* 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 to read specific lines from files. The data from any file will stay in memory until the
handle is collected by the gc *)
type t
val create : unit -> t
val from_loc : t -> Location.t -> string option
(** get the line from a location looking for the copy of the file in the results dir *)
val iteri : t -> SourceFile.t -> f:(int -> string -> unit) -> unit
(** iterate on the lines of the file, with line numbers *)

@ -307,7 +307,7 @@ let process_summary ~costs_outf summary issues_acc =
let process_all_summaries_and_issues ~issues_outf ~costs_outf =
let linereader = Printer.LineReader.create () in
let linereader = LineReader.create () in
let filters = Inferconfig.create_filters () in
let all_issues = ref [] in
SpecsFiles.iter_from_config ~f:(fun summary ->

@ -39,11 +39,11 @@ let get_start_location_heuristics =
match line.[next_char_idx] with ' ' | '<' | '(' -> true | _ -> false
else false )
in
let line_reader = lazy (Printer.LineReader.create ()) in
let line_reader = lazy (LineReader.create ()) in
let rec find_proc_loc_backward name ~lines_to_find loc =
if lines_to_find <= 0 || loc.Location.line <= 0 then None
else
match Printer.LineReader.from_loc (Lazy.force_val line_reader) loc with
match LineReader.from_loc (Lazy.force_val line_reader) loc with
| None ->
None
| Some line when is_proc_line line ~name ->

@ -210,7 +210,7 @@ let analyze checks ({IntraproceduralAnalysis.proc_desc; tenv; _} as analysis_dat
L.debug Analysis Medium "Signature: %a@\n" (AnnotatedSignature.pp proc_name)
annotated_signature ;
let loc = Procdesc.get_loc proc_desc in
let linereader = Printer.LineReader.create () in
let linereader = LineReader.create () in
(* Initializing TypeErr signleton. *)
TypeErr.reset () ;
(* The main method - during this the actual analysis will happen and TypeErr will be populated with

@ -79,7 +79,7 @@ let check_condition_for_redundancy
in
let from_try_with_resources () : bool =
(* heuristic to check if the condition is the translation of try-with-resources *)
match Printer.LineReader.from_loc linereader loc with
match LineReader.from_loc linereader loc with
| Some line ->
(not (String.is_substring ~substring:"==" line || String.is_substring ~substring:"!=" line))
&& String.is_substring ~substring:"}" line

@ -34,6 +34,6 @@ val typecheck_node :
-> AnnotatedSignature.t
-> TypeState.t
-> Procdesc.Node.t
-> Printer.LineReader.t
-> LineReader.t
-> typecheck_result
(** Main entry point. Typecheck the CFG node given input typestate, and report issues, if found *)

Loading…
Cancel
Save