[java] ability to call directly into the Java source parser for debug

Summary:
This is to be able to run the Java source file parser (that detects the position of class definitions and other things) on individual .java files for debugging.
Use with `infer --java-debug-source-file-info SomeFile.java`.

Reviewed By: ngorogiannis

Differential Revision: D21594327

fbshipit-source-id: 2f6d747b7
master
Jules Villard 5 years ago committed by Facebook GitHub Bot
parent bf97abfbd3
commit 8a0d584121

@ -1431,6 +1431,13 @@ INTERNAL OPTIONS
expressed as a multiple of symbolic operations and a multiple of
seconds of elapsed time
--java-debug-source-file-info path
For debugging only: Call the Java declarations source file parser
on the given file and do not run anything else.
--java-debug-source-file-info-reset
Cancel the effect of --java-debug-source-file-info.
--java-jar-compiler-reset
Cancel the effect of --java-jar-compiler.

@ -1396,6 +1396,12 @@ and iterations =
symbolic operations and a multiple of seconds of elapsed time"
and java_debug_source_file_info =
CLOpt.mk_path_opt ~long:"java-debug-source-file-info" ~meta:"path"
"For debugging only: Call the Java declarations source file parser on the given file and do \
not run anything else."
and java_jar_compiler =
CLOpt.mk_path_opt ~long:"java-jar-compiler"
~in_help:InferCommand.[(Capture, manual_java)]
@ -2737,6 +2743,8 @@ and issues_tests_fields = !issues_tests_fields
and iterations = !iterations
and java_debug_source_file_info = !java_debug_source_file_info
and java_jar_compiler = !java_jar_compiler
and java_version = !java_version

@ -344,6 +344,8 @@ val issues_tests_fields : IssuesTestField.t list
val iterations : int
val java_debug_source_file_info : string option
val java_jar_compiler : string option
val java_version : int option

@ -63,12 +63,13 @@ let infer_exe_stanza =
(name infer)
(modes byte_complete exe)
(modules Infer)
(flags (:standard -open Core -open IStdlib -open IStd -open IBase -open IR -open Backend -open Integration -open Biabduction -open TestDeterminators -open ClangFrontend -open ASTLanguage %s))
(flags (:standard -open Core -open IStdlib -open IStd -open IBase -open IR -open Backend -open Integration -open Biabduction -open TestDeterminators -open ClangFrontend -open ASTLanguage %s -open JavaFrontend %s))
(libraries %s core IStdlib IBase IR Backend Integration Biabduction TestDeterminators ClangFrontend ASTLanguage)
(preprocess (pps ppx_compare))
(promote (until-clean) (into ../bin))
)|}
(if clang then "" else "-open ClangFrontendStubs")
(if java then "" else "-open JavaFrontendStubs")
extlib_if_java

@ -136,87 +136,87 @@ let () =
if Config.debug_mode && CLOpt.is_originator then (
L.progress "Logs in %s@." (ResultsDir.get_path Logs) ;
L.progress "Execution ID %Ld@." Config.execution_id ) ;
( if Config.test_determinator && not Config.process_clang_ast then
TestDeterminator.compute_and_emit_test_to_run ()
else
match Config.command with
| Analyze ->
run Driver.Analyze
| Capture | Compile | Run ->
run (Lazy.force Driver.mode_from_command_line)
| Report -> (
match Config.issues_tests with
| None ->
if not Config.quiet then L.result "%t" SpecsFiles.pp_from_config
| Some out_path ->
IssuesTest.write_from_json ~json_path:Config.from_json_report ~out_path
Config.issues_tests_fields )
| ReportDiff ->
(* at least one report must be passed in input to compute differential *)
( match Config.(report_current, report_previous, costs_current, costs_previous) with
| None, None, None, None ->
L.(die UserError)
"Expected at least one argument among '--report-current', '--report-previous', \
'--costs-current', and '--costs-previous'"
| _ ->
() ) ;
ReportDiff.reportdiff ~current_report:Config.report_current
~previous_report:Config.report_previous ~current_costs:Config.costs_current
~previous_costs:Config.costs_previous
| Explore -> (
match (Config.procedures, Config.source_files) with
| true, false ->
let filter = Lazy.force Filtering.procedures_filter in
if Config.procedures_summary then
let pp_summary fmt proc_name =
match Summary.OnDisk.get proc_name with
| None ->
Format.fprintf fmt "No summary found: %a@\n" Procname.pp proc_name
| Some summary ->
Summary.pp_text fmt summary
in
Option.iter (Procedures.select_proc_names_interactive ~filter) ~f:(fun proc_names ->
L.result "%a" (fun fmt () -> List.iter proc_names ~f:(pp_summary fmt)) () )
else
L.result "%a"
Config.(
Procedures.pp_all ~filter ~proc_name:procedures_name
~attr_kind:procedures_definedness ~source_file:procedures_source_file
~proc_attributes:procedures_attributes)
()
| false, true ->
let filter = Lazy.force Filtering.source_files_filter in
( match Config.command with
| _ when Config.test_determinator && not Config.process_clang_ast ->
TestDeterminator.compute_and_emit_test_to_run ()
| _ when Option.is_some Config.java_debug_source_file_info ->
JSourceFileInfo.debug_on_file (Option.value_exn Config.java_debug_source_file_info)
| Analyze ->
run Driver.Analyze
| Capture | Compile | Run ->
run (Lazy.force Driver.mode_from_command_line)
| Report -> (
match Config.issues_tests with
| None ->
if not Config.quiet then L.result "%t" SpecsFiles.pp_from_config
| Some out_path ->
IssuesTest.write_from_json ~json_path:Config.from_json_report ~out_path
Config.issues_tests_fields )
| ReportDiff ->
(* at least one report must be passed in input to compute differential *)
( match Config.(report_current, report_previous, costs_current, costs_previous) with
| None, None, None, None ->
L.die UserError
"Expected at least one argument among '--report-current', '--report-previous', \
'--costs-current', and '--costs-previous'"
| _ ->
() ) ;
ReportDiff.reportdiff ~current_report:Config.report_current
~previous_report:Config.report_previous ~current_costs:Config.costs_current
~previous_costs:Config.costs_previous
| Explore -> (
match (Config.procedures, Config.source_files) with
| true, false ->
let filter = Lazy.force Filtering.procedures_filter in
if Config.procedures_summary then
let pp_summary fmt proc_name =
match Summary.OnDisk.get proc_name with
| None ->
Format.fprintf fmt "No summary found: %a@\n" Procname.pp proc_name
| Some summary ->
Summary.pp_text fmt summary
in
Option.iter (Procedures.select_proc_names_interactive ~filter) ~f:(fun proc_names ->
L.result "%a" (fun fmt () -> List.iter proc_names ~f:(pp_summary fmt)) () )
else
L.result "%a"
(SourceFiles.pp_all ~filter ~type_environment:Config.source_files_type_environment
~procedure_names:Config.source_files_procedure_names
~freshly_captured:Config.source_files_freshly_captured)
() ;
if Config.source_files_cfg then (
let source_files = SourceFiles.get_all ~filter () in
List.iter source_files ~f:(fun source_file ->
(* create directory in captured/ *)
DB.Results_dir.init ~debug:true source_file ;
(* collect the CFGs for all the procedures in [source_file] *)
let proc_names = SourceFiles.proc_names_of_source source_file in
let cfgs = Procname.Hash.create (List.length proc_names) in
List.iter proc_names ~f:(fun proc_name ->
Procdesc.load proc_name
|> Option.iter ~f:(fun cfg -> Procname.Hash.add cfgs proc_name cfg) ) ;
(* emit the dot file in captured/... *)
DotCfg.emit_frontend_cfg source_file cfgs ) ;
L.result "CFGs written in %s/*/%s@." (ResultsDir.get_path Debug)
Config.dotty_frontend_output )
| false, false ->
(* explore bug traces *)
if Config.html then
TraceBugs.gen_html_report ~report_json:(ResultsDir.get_path ReportJson)
~show_source_context:Config.source_preview ~max_nested_level:Config.max_nesting
~report_html_dir:(ResultsDir.get_path ReportHtml)
else
TraceBugs.explore ~selector_limit:None ~report_json:(ResultsDir.get_path ReportJson)
~report_txt:(ResultsDir.get_path ReportText) ~selected:Config.select
~show_source_context:Config.source_preview ~max_nested_level:Config.max_nesting
| true, true ->
L.user_error "Options --procedures and --source-files cannot be used together.@\n" ) ) ;
Config.(
Procedures.pp_all ~filter ~proc_name:procedures_name ~attr_kind:procedures_definedness
~source_file:procedures_source_file ~proc_attributes:procedures_attributes)
()
| false, true ->
let filter = Lazy.force Filtering.source_files_filter in
L.result "%a"
(SourceFiles.pp_all ~filter ~type_environment:Config.source_files_type_environment
~procedure_names:Config.source_files_procedure_names
~freshly_captured:Config.source_files_freshly_captured)
() ;
if Config.source_files_cfg then (
let source_files = SourceFiles.get_all ~filter () in
List.iter source_files ~f:(fun source_file ->
(* create directory in captured/ *)
DB.Results_dir.init ~debug:true source_file ;
(* collect the CFGs for all the procedures in [source_file] *)
let proc_names = SourceFiles.proc_names_of_source source_file in
let cfgs = Procname.Hash.create (List.length proc_names) in
List.iter proc_names ~f:(fun proc_name ->
Procdesc.load proc_name
|> Option.iter ~f:(fun cfg -> Procname.Hash.add cfgs proc_name cfg) ) ;
(* emit the dot file in captured/... *)
DotCfg.emit_frontend_cfg source_file cfgs ) ;
L.result "CFGs written in %s/*/%s@." (ResultsDir.get_path Debug)
Config.dotty_frontend_output )
| false, false ->
(* explore bug traces *)
if Config.html then
TraceBugs.gen_html_report ~report_json:(ResultsDir.get_path ReportJson)
~show_source_context:Config.source_preview ~max_nested_level:Config.max_nesting
~report_html_dir:(ResultsDir.get_path ReportHtml)
else
TraceBugs.explore ~selector_limit:None ~report_json:(ResultsDir.get_path ReportJson)
~report_txt:(ResultsDir.get_path ReportText) ~selected:Config.select
~show_source_context:Config.source_preview ~max_nested_level:Config.max_nesting
| true, true ->
L.user_error "Options --procedures and --source-files cannot be used together.@\n" ) ) ;
(* to make sure the exitcode=0 case is logged, explicitly invoke exit *)
L.exit 0

@ -12,3 +12,7 @@ module JMain = struct
let from_verbose_out _ = ()
end
module JSourceFileInfo = struct
let debug_on_file _ = ()
end

@ -15,8 +15,10 @@ open! IStd
module JMain : sig
val from_arguments : string -> unit
(** loads the source files from command line arguments and translates them *)
val from_verbose_out : string -> unit
(** loads the source files from javac's verbose output translates them *)
end
module JSourceFileInfo : sig
val debug_on_file : string -> unit
end

@ -401,4 +401,8 @@ and skip_comments action = parse
(SourceFile.to_abs_path file);
In_channel.close cin
)
let debug_on_file _path =
(* TODO: do something here *)
()
}

Loading…
Cancel
Save