[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 expressed as a multiple of symbolic operations and a multiple of
seconds of elapsed time 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 --java-jar-compiler-reset
Cancel the effect of --java-jar-compiler. Cancel the effect of --java-jar-compiler.

@ -1396,6 +1396,12 @@ and iterations =
symbolic operations and a multiple of seconds of elapsed time" 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 = and java_jar_compiler =
CLOpt.mk_path_opt ~long:"java-jar-compiler" CLOpt.mk_path_opt ~long:"java-jar-compiler"
~in_help:InferCommand.[(Capture, manual_java)] ~in_help:InferCommand.[(Capture, manual_java)]
@ -2737,6 +2743,8 @@ and issues_tests_fields = !issues_tests_fields
and iterations = !iterations and iterations = !iterations
and java_debug_source_file_info = !java_debug_source_file_info
and java_jar_compiler = !java_jar_compiler and java_jar_compiler = !java_jar_compiler
and java_version = !java_version and java_version = !java_version

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

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

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

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

@ -15,8 +15,10 @@ open! IStd
module JMain : sig module JMain : sig
val from_arguments : string -> unit val from_arguments : string -> unit
(** loads the source files from command line arguments and translates them *)
val from_verbose_out : string -> unit 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 end

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

Loading…
Cancel
Save