[nullsafe] Cleanup nullsafe top level execution

Summary:
This is not a full cleanup, but it is better than nothing.
At least `callback2` won't trigger me each time I see it anymore.

Reviewed By: jvillard

Differential Revision: D20364812

fbshipit-source-id: 8f25c24ad
master
Mitya Lyubarskiy 5 years ago committed by Facebook GitHub Bot
parent d48c3f644a
commit 82fb4e67b9

@ -6,16 +6,10 @@
*) *)
open! IStd open! IStd
(** Eradicate NPEs. *)
module L = Logging module L = Logging
module F = Format module F = Format
open Dataflow open Dataflow
(* ERADICATE CHECKER. TODOS:*)
(* 1) add support for constructors for anonymous inner classes (currently not checked) *)
(** Type for a module that provides a main callback function *) (** Type for a module that provides a main callback function *)
module type CallBackT = sig module type CallBackT = sig
val callback : TypeCheck.checks -> Callbacks.proc_callback_t val callback : TypeCheck.checks -> Callbacks.proc_callback_t
@ -120,16 +114,15 @@ module MkCallback (Extension : ExtensionT) : CallBackT = struct
(!calls_this, None) (!calls_this, None)
let callback2 tenv curr_pname calls_this checks {Callbacks.summary; get_procs_in_file} let analyze_procedure tenv proc_name proc_desc calls_this checks Callbacks.{get_procs_in_file}
annotated_signature linereader proc_loc : unit = annotated_signature linereader proc_loc : unit =
let curr_pdesc = Summary.get_proc_desc summary in let idenv = Idenv.create proc_desc in
let idenv = Idenv.create curr_pdesc in let find_duplicate_nodes = State.mk_find_duplicate_nodes proc_desc in
let find_duplicate_nodes = State.mk_find_duplicate_nodes curr_pdesc in
let find_canonical_duplicate node = let find_canonical_duplicate node =
let duplicate_nodes = find_duplicate_nodes node in let duplicate_nodes = find_duplicate_nodes node in
try Procdesc.NodeSet.min_elt duplicate_nodes with Caml.Not_found -> node try Procdesc.NodeSet.min_elt duplicate_nodes with Caml.Not_found -> node
in in
let caller_nullsafe_mode = NullsafeMode.of_procname tenv curr_pname in let caller_nullsafe_mode = NullsafeMode.of_procname tenv proc_name in
let typecheck_proc do_checks pname pdesc proc_details_opt = let typecheck_proc do_checks pname pdesc proc_details_opt =
let ann_sig, loc, idenv_pn = let ann_sig, loc, idenv_pn =
match proc_details_opt with match proc_details_opt with
@ -158,23 +151,22 @@ module MkCallback (Extension : ExtensionT) : CallBackT = struct
in in
let do_final_typestate typestate_opt calls_this = let do_final_typestate typestate_opt calls_this =
let do_typestate typestate = let do_typestate typestate =
let start_node = Procdesc.get_start_node curr_pdesc in let start_node = Procdesc.get_start_node proc_desc in
if if
(not calls_this) (not calls_this)
(* if 'this(...)' is called, no need to check initialization *) (* if 'this(...)' is called, no need to check initialization *)
&& checks.TypeCheck.eradicate && checks.TypeCheck.eradicate
then ( then (
let typestates_for_curr_constructor_and_all_initializer_methods = let typestates_for_curr_constructor_and_all_initializer_methods =
Initializers.final_initializer_typestates_lazy tenv curr_pname curr_pdesc Initializers.final_initializer_typestates_lazy tenv proc_name proc_desc
get_procs_in_file typecheck_proc get_procs_in_file typecheck_proc
in in
let typestates_for_all_constructors_incl_current = let typestates_for_all_constructors_incl_current =
Initializers.final_constructor_typestates_lazy tenv curr_pname get_procs_in_file Initializers.final_constructor_typestates_lazy tenv proc_name get_procs_in_file
typecheck_proc typecheck_proc
in in
EradicateChecks.check_constructor_initialization tenv find_canonical_duplicate curr_pname EradicateChecks.check_constructor_initialization tenv find_canonical_duplicate proc_name
curr_pdesc start_node proc_desc start_node ~nullsafe_mode:annotated_signature.AnnotatedSignature.nullsafe_mode
~nullsafe_mode:annotated_signature.AnnotatedSignature.nullsafe_mode
~typestates_for_curr_constructor_and_all_initializer_methods ~typestates_for_curr_constructor_and_all_initializer_methods
~typestates_for_all_constructors_incl_current proc_loc ; ~typestates_for_all_constructors_incl_current proc_loc ;
if Config.eradicate_verbose then L.result "Final Typestate@\n%a@." TypeState.pp typestate if Config.eradicate_verbose then L.result "Final Typestate@\n%a@." TypeState.pp typestate
@ -182,53 +174,55 @@ module MkCallback (Extension : ExtensionT) : CallBackT = struct
in in
match typestate_opt with None -> () | Some typestate -> do_typestate typestate match typestate_opt with None -> () | Some typestate -> do_typestate typestate
in in
TypeErr.reset () ;
let calls_this, final_typestate_opt = let calls_this, final_typestate_opt =
typecheck_proc true curr_pname curr_pdesc (Some (annotated_signature, proc_loc, idenv)) typecheck_proc true proc_name proc_desc (Some (annotated_signature, proc_loc, idenv))
in in
do_final_typestate final_typestate_opt calls_this ; do_final_typestate final_typestate_opt calls_this ;
if checks.TypeCheck.eradicate then if checks.TypeCheck.eradicate then
EradicateChecks.check_overridden_annotations find_canonical_duplicate tenv curr_pname EradicateChecks.check_overridden_annotations find_canonical_duplicate tenv proc_name proc_desc
curr_pdesc annotated_signature ; annotated_signature ;
TypeErr.report_forall_checks_and_reset (EradicateCheckers.report_error tenv) curr_pdesc ;
() ()
(** Entry point for the eradicate-based checker infrastructure. *) (* If we need to skip analysis, returns a string reason for debug, otherwise None *)
let find_reason_to_skip_analysis proc_name proc_desc =
match proc_name with
| Procname.Java java_pname ->
if Procname.Java.is_access_method java_pname then Some "access method"
else if Procname.Java.is_external java_pname then Some "third party method"
else if (Procdesc.get_attributes proc_desc).ProcAttributes.is_bridge_method then
Some "bridge method"
else None
| _ ->
Some "not a Java method"
(** Entry point for the nullsafe procedure-level analysis. *)
let callback checks ({Callbacks.summary} as callback_args) : Summary.t = let callback checks ({Callbacks.summary} as callback_args) : Summary.t =
let proc_desc = Summary.get_proc_desc summary in let proc_desc = Summary.get_proc_desc summary in
let proc_name = Procdesc.get_proc_name proc_desc in let proc_name = Procdesc.get_proc_name proc_desc in
let calls_this = ref false in L.debug Analysis Medium "Analysis of %a@\n" Procname.pp proc_name ;
let curr_pname = Summary.get_proc_name summary in match find_reason_to_skip_analysis proc_name proc_desc with
let tenv = Exe_env.get_tenv callback_args.exe_env curr_pname in | Some reason ->
let filter_special_cases () = L.debug Analysis Medium "Skipping analysis: %s@\n" reason ;
if summary
( match proc_name with | None ->
| Procname.Java java_pname -> (* start the analysis! *)
Procname.Java.is_access_method java_pname || Procname.Java.is_external java_pname let calls_this = ref false in
| _ -> let tenv = Exe_env.get_tenv callback_args.exe_env proc_name in
false )
|| (Procdesc.get_attributes proc_desc).ProcAttributes.is_bridge_method
then None
else
let annotated_signature = let annotated_signature =
(* TODO(T62825735): fully support trusted callees; this could benefit from refactoring *)
Models.get_modelled_annotated_signature ~is_trusted_callee:false tenv Models.get_modelled_annotated_signature ~is_trusted_callee:false tenv
(Procdesc.get_attributes proc_desc) (Procdesc.get_attributes proc_desc)
in in
Some annotated_signature L.debug Analysis Medium "Signature: %a@\n" (AnnotatedSignature.pp proc_name)
in annotated_signature ;
( match filter_special_cases () with
| None ->
()
| Some annotated_signature ->
let loc = Procdesc.get_loc proc_desc in let loc = Procdesc.get_loc proc_desc in
let linereader = Printer.LineReader.create () in let linereader = Printer.LineReader.create () in
if Config.eradicate_verbose then TypeErr.reset () ;
L.result "%a@." (AnnotatedSignature.pp proc_name) annotated_signature ; analyze_procedure tenv proc_name proc_desc calls_this checks callback_args
callback2 tenv curr_pname calls_this checks callback_args annotated_signature linereader loc annotated_signature linereader loc ;
) ; TypeErr.report_forall_checks_and_reset (EradicateCheckers.report_error tenv) proc_desc ;
summary summary
end end
(* MkCallback *) (* MkCallback *)

@ -7,7 +7,7 @@
open! IStd open! IStd
(** Eradicate NPEs. *) (** The main entry point for Nullsafe typechecker. *)
val callback_eradicate : Callbacks.proc_callback_t val callback_eradicate : Callbacks.proc_callback_t

Loading…
Cancel
Save