diff --git a/infer/src/absint/InterproceduralAnalysis.ml b/infer/src/absint/InterproceduralAnalysis.ml index d86743f67..ac74293f2 100644 --- a/infer/src/absint/InterproceduralAnalysis.ml +++ b/infer/src/absint/InterproceduralAnalysis.ml @@ -15,3 +15,9 @@ type 'payload t = ; analyze_dependency: Procname.t -> (Procdesc.t * 'payload) option ; analyze_pdesc_dependency: Procdesc.t -> 'payload option ; update_stats: ?add_symops:int -> ?failure_kind:SymOp.failure_kind -> unit -> unit } + +type 'payload file_t = + { source_file: SourceFile.t + ; procedures: Procname.t list + ; file_exe_env: Exe_env.t + ; analyze_file_dependency: Procname.t -> (Procdesc.t * 'payload) option } diff --git a/infer/src/absint/InterproceduralAnalysis.mli b/infer/src/absint/InterproceduralAnalysis.mli index 0a885f7af..a0355a19a 100644 --- a/infer/src/absint/InterproceduralAnalysis.mli +++ b/infer/src/absint/InterproceduralAnalysis.mli @@ -24,3 +24,12 @@ type 'payload t = (** same as above when we already know the {!Procdesc.t} *) ; update_stats: ?add_symops:int -> ?failure_kind:SymOp.failure_kind -> unit -> unit (** update the [Summary.Stats.t] of the summary of the current procedure *) } + +(** Analysis data for the analysis of a source file. *) +type 'payload file_t = + { source_file: SourceFile.t (** the source file under analysis *) + ; procedures: Procname.t list (** list of procedures declared in the source file *) + ; file_exe_env: Exe_env.t (** {!Exe_env.t} for the current analysis *) + ; analyze_file_dependency: Procname.t -> (Procdesc.t * 'payload) option + (** On-demand analysis of dependencies needed for the file analysis, e.g. the proc names in + [procedures] *) } diff --git a/infer/src/checkers/registerCheckers.ml b/infer/src/checkers/registerCheckers.ml index e89b2b522..37354a052 100644 --- a/infer/src/checkers/registerCheckers.ml +++ b/infer/src/checkers/registerCheckers.ml @@ -62,6 +62,21 @@ let dynamic_dispatch payload_field checker = DynamicDispatch (proc_callback_of_interprocedural payload_field checker) +let file_callback_of_interprocedural_file payload_field checker + {Callbacks.procedures; exe_env; source_file} = + let analyze_file_dependency proc_name = + let summary = Ondemand.analyze_proc_name_no_caller proc_name in + Option.bind summary ~f:(fun {Summary.payloads; proc_desc; _} -> + Field.get payload_field payloads |> Option.map ~f:(fun payload -> (proc_desc, payload)) ) + in + checker + {InterproceduralAnalysis.procedures; source_file; file_exe_env= exe_env; analyze_file_dependency} + + +let file issue_dir payload_field checker = + File {callback= file_callback_of_interprocedural_file payload_field checker; issue_dir} + + let proc_callback_of_intraprocedural ?payload_field checker {Callbacks.summary; exe_env} = let result = checker @@ -180,8 +195,8 @@ let all_checkers = ; callbacks= [ ( intraprocedural_with_payload Payloads.Fields.nullsafe Eradicate.analyze_procedure , Language.Java ) - ; (File {callback= Eradicate.file_callback; issue_dir= NullsafeFileIssues}, Language.Java) - ] } + ; ( file NullsafeFileIssues Payloads.Fields.nullsafe FileLevelAnalysis.analyze_file + , Language.Java ) ] } ; { name= "buffer overrun checker" ; active= Config.(is_checker_enabled BufferOverrun) ; callbacks= diff --git a/infer/src/nullsafe/FileLevelAnalysis.ml b/infer/src/nullsafe/FileLevelAnalysis.ml index efc397393..517a96939 100644 --- a/infer/src/nullsafe/FileLevelAnalysis.ml +++ b/infer/src/nullsafe/FileLevelAnalysis.ml @@ -38,8 +38,8 @@ let analyze_class tenv source_file issue_log (class_name, class_info) = else ClassLevelAnalysis.analyze_class tenv source_file class_name class_info issue_log -let analyze_file ({exe_env; procedures; source_file} : Callbacks.file_callback_args) = +let analyze_file {InterproceduralAnalysis.procedures; file_exe_env; source_file} = let class_map = aggregate_by_class procedures in - let tenv = Exe_env.load_java_global_tenv exe_env in + let tenv = Exe_env.load_java_global_tenv file_exe_env in let user_class_info = AggregatedSummaries.group_by_user_class class_map in List.fold user_class_info ~init:IssueLog.empty ~f:(analyze_class tenv source_file) diff --git a/infer/src/nullsafe/FileLevelAnalysis.mli b/infer/src/nullsafe/FileLevelAnalysis.mli index ab234a63a..840f1e10d 100644 --- a/infer/src/nullsafe/FileLevelAnalysis.mli +++ b/infer/src/nullsafe/FileLevelAnalysis.mli @@ -7,6 +7,6 @@ open! IStd -val analyze_file : Callbacks.file_callback_t +val analyze_file : NullsafeSummary.t InterproceduralAnalysis.file_t -> IssueLog.t (** File-level callback for nullsafe. Is called after all proc-level callbacks are called and calculated their summaries. At this stage, additional issues can be emitted. *) diff --git a/infer/src/nullsafe/eradicate.ml b/infer/src/nullsafe/eradicate.ml index 376506720..b988e43b5 100644 --- a/infer/src/nullsafe/eradicate.ml +++ b/infer/src/nullsafe/eradicate.ml @@ -226,8 +226,6 @@ let analyze_procedure analysis_data = analyze checks analysis_data -let file_callback = FileLevelAnalysis.analyze_file - let analyze_for_immutable_cast_checker check_return_type analysis_data = let checks = {TypeCheck.eradicate= false; check_ret_type= [check_return_type]} in analyze checks analysis_data diff --git a/infer/src/nullsafe/eradicate.mli b/infer/src/nullsafe/eradicate.mli index c1229a83b..c14765d0d 100644 --- a/infer/src/nullsafe/eradicate.mli +++ b/infer/src/nullsafe/eradicate.mli @@ -12,10 +12,6 @@ open! IStd val analyze_procedure : IntraproceduralAnalysis.t -> NullsafeSummary.t option (** Proc-level callback for nullsafe. *) -val file_callback : Callbacks.file_callback_t -(** File-level callback for nullsafe. Is called after all proc-level callbacks are called and - calculated their summaries *) - val analyze_for_immutable_cast_checker : TypeCheck.check_return_type -> IntraproceduralAnalysis.t -> NullsafeSummary.t option (** For checkers that explore eradicate/nullsafe infra, but not part of nullsafe.Annot Call the