[nullsafe][easy] use `lazy` instead of `fetcher ()`

Summary: This is more idiomatic in OCaml and hopefully a bit easier to read. Internally `lazy` will do pretty much the same thing but it also ensures the callback is called at most once.

Reviewed By: artempyanykh

Differential Revision: D21722522

fbshipit-source-id: 00897aaf1
master
Jules Villard 5 years ago committed by Facebook GitHub Bot
parent 0c9cc9f791
commit 97ad5b9c96

@ -215,14 +215,13 @@ let get_nonnull_explanation_for_condition_redudant (nonnull_origin : TypeOrigin.
" according to the existing annotations" " according to the existing annotations"
(** If error is reportable to the user, return a callback for getting a description, severity etc. (** If error is reportable to the user, return its information. Otherwise return [None]. *)
Otherwise return None. *) let get_error_info_if_reportable_lazy ~nullsafe_mode err_instance =
let get_error_info_fetcher_if_reportable ~nullsafe_mode err_instance =
let open IOption.Let_syntax in let open IOption.Let_syntax in
match err_instance with match err_instance with
| Condition_redundant {is_always_true; condition_descr; nonnull_origin} -> | Condition_redundant {is_always_true; condition_descr; nonnull_origin} ->
Some Some
(let fetcher () = ( lazy
( P.sprintf "The condition %s might be always %b%s." ( P.sprintf "The condition %s might be always %b%s."
(Option.value condition_descr ~default:"") (Option.value condition_descr ~default:"")
is_always_true is_always_true
@ -234,12 +233,10 @@ let get_error_info_fetcher_if_reportable ~nullsafe_mode err_instance =
Until it is made non-precise, it is recommended to not turn this warning on. Until it is made non-precise, it is recommended to not turn this warning on.
But even when it is on, this should not be more than advice. But even when it is on, this should not be more than advice.
*) *)
Exceptions.Advice ) Exceptions.Advice ) )
in
fetcher )
| Over_annotation {over_annotated_violation; violation_type} -> | Over_annotation {over_annotated_violation; violation_type} ->
Some Some
(let fetcher () = ( lazy
( OverAnnotatedRule.violation_description over_annotated_violation violation_type ( OverAnnotatedRule.violation_description over_annotated_violation violation_type
, ( match violation_type with , ( match violation_type with
| OverAnnotatedRule.FieldOverAnnoted _ -> | OverAnnotatedRule.FieldOverAnnoted _ ->
@ -248,12 +245,10 @@ let get_error_info_fetcher_if_reportable ~nullsafe_mode err_instance =
IssueType.eradicate_return_over_annotated ) IssueType.eradicate_return_over_annotated )
, None , None
, (* Very non-precise issue. Should be actually turned off unless for experimental purposes. *) , (* Very non-precise issue. Should be actually turned off unless for experimental purposes. *)
Exceptions.Advice ) Exceptions.Advice ) )
in
fetcher )
| Field_not_initialized {field_name} -> | Field_not_initialized {field_name} ->
Some Some
(let fetcher () = ( lazy
( Format.asprintf ( Format.asprintf
"Field %a is declared non-nullable, so it should be initialized in the constructor \ "Field %a is declared non-nullable, so it should be initialized in the constructor \
or in an `@Initializer` method" or in an `@Initializer` method"
@ -261,49 +256,43 @@ let get_error_info_fetcher_if_reportable ~nullsafe_mode err_instance =
(Fieldname.get_field_name field_name) (Fieldname.get_field_name field_name)
, IssueType.eradicate_field_not_initialized , IssueType.eradicate_field_not_initialized
, None , None
, NullsafeMode.severity nullsafe_mode ) , NullsafeMode.severity nullsafe_mode ) )
in
fetcher )
| Bad_assignment {rhs_origin; assignment_location; assignment_type; assignment_violation} -> | Bad_assignment {rhs_origin; assignment_location; assignment_type; assignment_violation} ->
(* If violation is reportable, create a fetcher, otherwise None *) (* If violation is reportable, create tuple, otherwise None *)
let+ reportable_violation = let+ reportable_violation =
AssignmentRule.ReportableViolation.from nullsafe_mode assignment_violation AssignmentRule.ReportableViolation.from nullsafe_mode assignment_violation
in in
let fetcher () = lazy
let description, issue_type, error_location = (let description, issue_type, error_location =
AssignmentRule.ReportableViolation.get_description ~assignment_location assignment_type AssignmentRule.ReportableViolation.get_description ~assignment_location assignment_type
~rhs_origin reportable_violation ~rhs_origin reportable_violation
in in
let severity = AssignmentRule.ReportableViolation.get_severity reportable_violation in let severity = AssignmentRule.ReportableViolation.get_severity reportable_violation in
(description, issue_type, Some error_location, severity) (description, issue_type, Some error_location, severity) )
in
fetcher
| Nullable_dereference | Nullable_dereference
{ dereference_violation { dereference_violation
; dereference_location ; dereference_location
; nullable_object_descr ; nullable_object_descr
; dereference_type ; dereference_type
; nullable_object_origin } -> ; nullable_object_origin } ->
(* If violation is reportable, create a fetcher, otherwise None *) (* If violation is reportable, create tuple, otherwise None *)
let+ reportable_violation = let+ reportable_violation =
DereferenceRule.ReportableViolation.from nullsafe_mode dereference_violation DereferenceRule.ReportableViolation.from nullsafe_mode dereference_violation
in in
let fetcher () = lazy
let description, issue_type, error_location = (let description, issue_type, error_location =
DereferenceRule.ReportableViolation.get_description reportable_violation DereferenceRule.ReportableViolation.get_description reportable_violation
~dereference_location dereference_type ~nullable_object_descr ~nullable_object_origin ~dereference_location dereference_type ~nullable_object_descr ~nullable_object_origin
in in
let severity = DereferenceRule.ReportableViolation.get_severity reportable_violation in let severity = DereferenceRule.ReportableViolation.get_severity reportable_violation in
(description, issue_type, Some error_location, severity) (description, issue_type, Some error_location, severity) )
in
fetcher
| Inconsistent_subclass | Inconsistent_subclass
{inheritance_violation; violation_type; base_proc_name; overridden_proc_name} -> {inheritance_violation; violation_type; base_proc_name; overridden_proc_name} ->
(* If violation is reportable, create a fetcher, otherwise None *) (* If violation is reportable, create tuple, otherwise None *)
let+ reportable_violation = let+ reportable_violation =
InheritanceRule.ReportableViolation.from nullsafe_mode inheritance_violation InheritanceRule.ReportableViolation.from nullsafe_mode inheritance_violation
in in
let fetcher () = lazy
( InheritanceRule.ReportableViolation.get_description reportable_violation violation_type ( InheritanceRule.ReportableViolation.get_description reportable_violation violation_type
~base_proc_name ~overridden_proc_name ~base_proc_name ~overridden_proc_name
, ( match violation_type with , ( match violation_type with
@ -313,19 +302,18 @@ let get_error_info_fetcher_if_reportable ~nullsafe_mode err_instance =
IssueType.eradicate_inconsistent_subclass_parameter_annotation ) IssueType.eradicate_inconsistent_subclass_parameter_annotation )
, None , None
, InheritanceRule.ReportableViolation.get_severity reportable_violation ) , InheritanceRule.ReportableViolation.get_severity reportable_violation )
in
fetcher
(** If error is reportable to the user, return description, severity etc. Otherwise return None. *) (** If error is reportable to the user, return description, severity etc. Otherwise return None. *)
let get_error_info_if_reportable ~nullsafe_mode err_instance = let get_error_info_if_reportable ~nullsafe_mode err_instance =
get_error_info_fetcher_if_reportable ~nullsafe_mode err_instance get_error_info_if_reportable_lazy ~nullsafe_mode err_instance |> Option.map ~f:Lazy.force
|> Option.map ~f:(fun fetcher -> fetcher ())
let is_reportable ~nullsafe_mode err_instance = let is_reportable ~nullsafe_mode err_instance =
(* Optimization: we don't fetch the whole info (that might involve string manipulations). *) (* Note: we don't fetch the whole info because the the class-level analysis breaks some
get_error_info_fetcher_if_reportable ~nullsafe_mode err_instance |> Option.is_some assumptions of this function, and also for optimization purposes (saving some string
manipulations). *)
get_error_info_if_reportable_lazy ~nullsafe_mode err_instance |> Option.is_some
let report_now_if_reportable analysis_data err_instance ~nullsafe_mode loc = let report_now_if_reportable analysis_data err_instance ~nullsafe_mode loc =

Loading…
Cancel
Save