From 34f7741ad922da26038e6d31a79af78f113d0e2f Mon Sep 17 00:00:00 2001 From: Nikos Gorogiannis Date: Wed, 8 Jul 2020 05:56:34 -0700 Subject: [PATCH] [java][2/n] refactor classpath Summary: Make the module interface safe wrt closing the classpath channel when done, plus reducing the exposed API. Reviewed By: skcho Differential Revision: D22411685 fbshipit-source-id: 11316c577 --- infer/src/java/jClasspath.ml | 29 ++++++++++++++++++++++++++--- infer/src/java/jClasspath.mli | 16 +++++++++++----- infer/src/java/jMain.ml | 21 +++++---------------- infer/src/java/jProgramDesc.ml | 6 ++---- infer/src/java/jProgramDesc.mli | 4 +--- 5 files changed, 45 insertions(+), 31 deletions(-) diff --git a/infer/src/java/jClasspath.ml b/infer/src/java/jClasspath.ml index f5064816a..6aee8c551 100644 --- a/infer/src/java/jClasspath.ml +++ b/infer/src/java/jClasspath.ml @@ -28,7 +28,10 @@ let classpath_of_paths paths = type file_entry = Singleton of SourceFile.t | Duplicate of (string * SourceFile.t) list -type t = {classpath: string; sources: file_entry String.Map.t; classes: JBasics.ClassSet.t} +type t = + { classpath_channel: Javalib.class_path + ; sources: file_entry String.Map.t + ; classes: JBasics.ClassSet.t } (* Open the source file and search for the package declaration. Only the case where the package is declared in a single line is supported *) @@ -103,7 +106,7 @@ let load_from_verbose_output = match In_channel.input_line file_in with | None -> let classpath = classpath_of_paths (String.Set.elements roots @ paths) in - {classpath; sources; classes} + {classpath_channel= Javalib.class_path classpath; sources; classes} | Some line when Str.string_match class_filename_re line 0 -> ( let path = try Str.matched_group 5 line @@ -189,4 +192,24 @@ let load_from_arguments classes_out_path = split Config.bootclasspath @ split Config.classpath @ String.Set.elements roots |> classpath_of_paths in - {classpath; sources= search_sources (); classes} + {classpath_channel= Javalib.class_path classpath; sources= search_sources (); classes} + + +type source = FromVerboseOut of {verbose_out_file: string} | FromArguments of {path: string} + +let with_classpath ~f source = + let classpath = + match source with + | FromVerboseOut {verbose_out_file} -> + load_from_verbose_output verbose_out_file + | FromArguments {path} -> + load_from_arguments path + in + if String.Map.is_empty classpath.sources then + L.(die InternalError) "Failed to load any Java source code" ; + L.(debug Capture Quiet) + "Translating %d source files (%d classes)@." + (String.Map.length classpath.sources) + (JBasics.ClassSet.cardinal classpath.classes) ; + f classpath ; + Javalib.close_class_path classpath.classpath_channel diff --git a/infer/src/java/jClasspath.mli b/infer/src/java/jClasspath.mli index c7645be5c..adc82dc0c 100644 --- a/infer/src/java/jClasspath.mli +++ b/infer/src/java/jClasspath.mli @@ -12,10 +12,16 @@ open Javalib_pack (** map entry for source files with potential basename collision within the same compiler call *) type file_entry = Singleton of SourceFile.t | Duplicate of (string * SourceFile.t) list -type t = {classpath: string; sources: file_entry String.Map.t; classes: JBasics.ClassSet.t} +type t = + { classpath_channel: Javalib.class_path + ; sources: file_entry String.Map.t + ; classes: JBasics.ClassSet.t } -val load_from_verbose_output : string -> t -(** load the list of source files and the list of classes from the javac verbose file *) +type source = + | FromVerboseOut of {verbose_out_file: string} + (** load the list of source files and the list of classes from the javac verbose file *) + | FromArguments of {path: string} + (** load the list of source files and the list of classes from [Config.generated_classes] *) -val load_from_arguments : string -> t -(** load the list of source files and the list of classes from Config.generated_classes *) +val with_classpath : f:(t -> unit) -> source -> unit +(** load a class path, pass it to [f] and cleanup after [f] is done *) diff --git a/infer/src/java/jMain.ml b/infer/src/java/jMain.ml index 5da5bf471..1ef2fc958 100644 --- a/infer/src/java/jMain.ml +++ b/infer/src/java/jMain.ml @@ -106,7 +106,6 @@ let do_all_files sources program = if Config.dependency_mode then capture_libs program tenv ; store_callee_attributes tenv program ; save_tenv tenv ; - JProgramDesc.cleanup program ; L.(debug Capture Quiet) "done capturing all files@." @@ -122,21 +121,11 @@ let main load_sources_and_classes = | false, true -> JModels.load_models ~jar_filename:Config.biabduction_models_jar ) ; JBasics.set_permissive true ; - let JClasspath.{classpath; sources; classes} = - match load_sources_and_classes with - | `FromVerboseOut verbose_out_file -> - JClasspath.load_from_verbose_output verbose_out_file - | `FromArguments path -> - JClasspath.load_from_arguments path - in - if String.Map.is_empty sources then L.(die InternalError) "Failed to load any Java source code" ; - L.(debug Capture Quiet) - "Translating %d source files (%d classes)@." (String.Map.length sources) - (JBasics.ClassSet.cardinal classes) ; - let program = JProgramDesc.load_program ~classpath classes in - do_all_files sources program + JClasspath.with_classpath load_sources_and_classes ~f:(fun classpath -> + let program = JProgramDesc.load classpath in + do_all_files classpath.sources program ) -let from_arguments path = main (`FromArguments path) +let from_arguments path = main (JClasspath.FromArguments {path}) -let from_verbose_out verbose_out_file = main (`FromVerboseOut verbose_out_file) +let from_verbose_out verbose_out_file = main (JClasspath.FromVerboseOut {verbose_out_file}) diff --git a/infer/src/java/jProgramDesc.ml b/infer/src/java/jProgramDesc.ml index 536ae46ba..050530833 100644 --- a/infer/src/java/jProgramDesc.ml +++ b/infer/src/java/jProgramDesc.ml @@ -67,8 +67,6 @@ let iter_missing_callees program ~f = Procname.Hash.iter select program.callees -let cleanup program = Javalib.close_class_path program.classpath_channel - let lookup_node cn program = try Some (JBasics.ClassMap.find cn (get_classmap program)) with Caml.Not_found -> ( @@ -84,10 +82,10 @@ let lookup_node cn program = None ) -let load_program ~classpath classes = +let load JClasspath.{classpath_channel; classes} = L.(debug Capture Medium) "loading program ... %!" ; let program = - { classpath_channel= Javalib.class_path classpath + { classpath_channel ; classmap= JBasics.ClassMap.empty ; java_location_map= JBasics.ClassMap.empty ; callees= Procname.Hash.create 128 } diff --git a/infer/src/java/jProgramDesc.mli b/infer/src/java/jProgramDesc.mli index f85937fe3..1674a3410 100644 --- a/infer/src/java/jProgramDesc.mli +++ b/infer/src/java/jProgramDesc.mli @@ -21,9 +21,7 @@ val get_java_location : t -> JBasics.class_name -> Location.t option val mem_classmap : JBasics.class_name -> t -> bool -val cleanup : t -> unit - -val load_program : classpath:string -> JBasics.ClassSet.t -> t +val load : JClasspath.t -> t (** load a java program *) val lookup_node : JBasics.class_name -> t -> JCode.jcode Javalib.interface_or_class option