[nullsafe] Unify issue types

Summary:
1. For each Nullsafe Rule, lets have a dedicated IssueType.
2. Split error reporting to three subfunctions: description, field type,
and infer issue.

This allows to introduce additional capabilities in a consolidated
manner. Example of such capabilities is should we hide or show an error,
what should be error severity depending on strictness mode, and how
exactly the error should be reported depending on how exactly
nullability is violated.

Reviewed By: artempyanykh

Differential Revision: D17977887

fbshipit-source-id: 860d67d2f
master
Mitya Lyubarskiy 5 years ago committed by Facebook Github Bot
parent 46ae3580c2
commit 92f765a948

@ -156,9 +156,9 @@ let check_field_assignment tenv find_canonical_duplicate curr_pdesc node instr_r
&& not (field_is_in_cleanup_context ()) && not (field_is_in_cleanup_context ())
in in
if should_report_nullable then if should_report_nullable then
let origin_descr = InferredNullability.descr_origin inferred_nullability_rhs in let rhs_origin_descr = InferredNullability.descr_origin inferred_nullability_rhs in
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Field_annotation_inconsistent (fname, origin_descr)) (TypeErr.Bad_assignment {rhs_origin_descr; assignment_type= TypeErr.AssigningToAField fname})
(Some instr_ref) loc curr_pdesc (Some instr_ref) loc curr_pdesc
@ -298,7 +298,7 @@ let check_constructor_initialization tenv find_canonical_duplicate curr_construc
~rhs_upper_bound:(field_nullability_upper_bound_over_all_typestates ()) ~rhs_upper_bound:(field_nullability_upper_bound_over_all_typestates ())
then then
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Field_over_annotated (field_name, curr_constructor_pname)) (TypeErr.Over_annotation (TypeErr.FieldOverAnnotedAsNullable field_name))
None loc curr_constructor_pdesc ) None loc curr_constructor_pdesc )
in in
List.iter ~f:do_field fields List.iter ~f:do_field fields
@ -314,9 +314,10 @@ let check_return_not_nullable tenv find_canonical_duplicate loc curr_pname curr_
let lhs = AnnotatedNullability.get_nullability ret_signature.ret_annotated_type.nullability in let lhs = AnnotatedNullability.get_nullability ret_signature.ret_annotated_type.nullability in
let rhs = InferredNullability.get_nullability ret_inferred_nullability in let rhs = InferredNullability.get_nullability ret_inferred_nullability in
if not (NullsafeRules.passes_assignment_rule ~lhs ~rhs) then if not (NullsafeRules.passes_assignment_rule ~lhs ~rhs) then
let rhs_origin_descr = InferredNullability.descr_origin ret_inferred_nullability in
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Return_annotation_inconsistent (TypeErr.Bad_assignment
(curr_pname, InferredNullability.descr_origin ret_inferred_nullability)) {rhs_origin_descr; assignment_type= TypeErr.ReturningFromAFunction curr_pname})
None loc curr_pdesc None loc curr_pdesc
@ -330,7 +331,8 @@ let check_return_overrannotated tenv find_canonical_duplicate loc curr_pname cur
*) *)
let rhs_upper_bound = InferredNullability.get_nullability ret_inferred_nullability in let rhs_upper_bound = InferredNullability.get_nullability ret_inferred_nullability in
if NullsafeRules.is_overannotated ~lhs ~rhs_upper_bound then if NullsafeRules.is_overannotated ~lhs ~rhs_upper_bound then
report_error tenv find_canonical_duplicate (TypeErr.Return_over_annotated curr_pname) None loc report_error tenv find_canonical_duplicate
(TypeErr.Over_annotation (TypeErr.ReturnOverAnnotatedAsNullable curr_pname)) None loc
curr_pdesc curr_pdesc
@ -386,20 +388,22 @@ type resolved_param =
let check_call_parameters tenv find_canonical_duplicate curr_pdesc node callee_attributes let check_call_parameters tenv find_canonical_duplicate curr_pdesc node callee_attributes
resolved_params loc instr_ref : unit = resolved_params loc instr_ref : unit =
let callee_pname = callee_attributes.ProcAttributes.proc_name in let callee_pname = callee_attributes.ProcAttributes.proc_name in
let check {num= param_num; formal; actual= orig_e2, nullability_actual} = let check {num= param_position; formal; actual= orig_e2, nullability_actual} =
let report () = let report () =
let description = let param_description =
match explain_expr tenv node orig_e2 with match explain_expr tenv node orig_e2 with
| Some descr -> | Some descr ->
descr descr
| None -> | None ->
"formal parameter " ^ Mangled.to_string formal.mangled "formal parameter " ^ Mangled.to_string formal.mangled
in in
let origin_descr = InferredNullability.descr_origin nullability_actual in let rhs_origin_descr = InferredNullability.descr_origin nullability_actual in
let callee_loc = callee_attributes.ProcAttributes.loc in
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Parameter_annotation_inconsistent (TypeErr.Bad_assignment
(description, param_num, callee_pname, callee_loc, origin_descr)) { rhs_origin_descr
; assignment_type=
TypeErr.PassingParamToAFunction
{param_description; param_position; function_procname= callee_pname} })
(Some instr_ref) loc curr_pdesc (Some instr_ref) loc curr_pdesc
in in
if PatternMatch.type_is_class formal.param_annotated_type.typ then if PatternMatch.type_is_class formal.param_annotated_type.typ then
@ -432,7 +436,10 @@ let check_inheritance_rule_for_return find_canonical_duplicate tenv loc ~base_pr
~overridden:overridden_nullability) ~overridden:overridden_nullability)
then then
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Inconsistent_subclass_return_annotation (overridden_proc_name, base_proc_name)) (TypeErr.Inconsistent_subclass
{ overridden_proc_name
; base_proc_name
; inconsistent_subclass_type= TypeErr.InconsistentReturn })
None loc overridden_proc_desc None loc overridden_proc_desc
@ -445,11 +452,12 @@ let check_inheritance_rule_for_param find_canonical_duplicate tenv loc ~overridd
~overridden:overridden_nullability) ~overridden:overridden_nullability)
then then
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Inconsistent_subclass_parameter_annotation (TypeErr.Inconsistent_subclass
( Mangled.to_string overridden_param_name { base_proc_name
, param_position ; overridden_proc_name
, overridden_proc_name ; inconsistent_subclass_type=
, base_proc_name )) TypeErr.InconsistentParam
{param_position; param_description= Mangled.to_string overridden_param_name} })
None loc overridden_proc_desc None loc overridden_proc_desc

@ -62,34 +62,39 @@ type origin_descr = string * Location.t option * AnnotatedSignature.t option
(* ignore origin descr *) (* ignore origin descr *)
let compare_origin_descr _ _ = 0 let compare_origin_descr _ _ = 0
type parameter_not_nullable =
string
* (* description *)
int
* (* parameter number *)
Typ.Procname.t
* Location.t
* (* callee location *)
origin_descr
[@@deriving compare]
(** Instance of an error *) (** Instance of an error *)
type err_instance = type err_instance =
| Condition_redundant of (bool * string option) | Condition_redundant of (bool * string option)
| Inconsistent_subclass_return_annotation of Typ.Procname.t * Typ.Procname.t | Inconsistent_subclass of
| Inconsistent_subclass_parameter_annotation of string * int * Typ.Procname.t * Typ.Procname.t { base_proc_name: Typ.Procname.t
; overridden_proc_name: Typ.Procname.t
; inconsistent_subclass_type: inconsistent_subclass_type }
| Field_not_initialized of Typ.Fieldname.t * Typ.Procname.t | Field_not_initialized of Typ.Fieldname.t * Typ.Procname.t
| Field_annotation_inconsistent of Typ.Fieldname.t * origin_descr | Over_annotation of over_annotation_type
| Field_over_annotated of Typ.Fieldname.t * Typ.Procname.t
| Nullable_dereference of | Nullable_dereference of
{ nullable_object_descr: string option { nullable_object_descr: string option
; dereference_type: dereference_type ; dereference_type: dereference_type
; origin_descr: origin_descr } ; origin_descr: origin_descr }
| Parameter_annotation_inconsistent of parameter_not_nullable | Bad_assignment of {rhs_origin_descr: origin_descr; assignment_type: assignment_type}
| Return_annotation_inconsistent of Typ.Procname.t * origin_descr
| Return_over_annotated of Typ.Procname.t
[@@deriving compare] [@@deriving compare]
and inconsistent_subclass_type =
| InconsistentParam of {param_description: string; param_position: int}
| InconsistentReturn
and over_annotation_type =
| FieldOverAnnotedAsNullable of Typ.Fieldname.t
| ReturnOverAnnotatedAsNullable of Typ.Procname.t
(** Return value of a method can be made non-nullable *)
and assignment_type =
| PassingParamToAFunction of
{ param_description: string
; param_position: int
; function_procname: Typ.Procname.t }
| AssigningToAField of Typ.Fieldname.t
| ReturningFromAFunction of Typ.Procname.t
and dereference_type = and dereference_type =
| MethodCall of Typ.Procname.t | MethodCall of Typ.Procname.t
| AccessToField of Typ.Fieldname.t | AccessToField of Typ.Fieldname.t
@ -122,22 +127,14 @@ let get_forall = function
true true
| Field_not_initialized _ -> | Field_not_initialized _ ->
false false
| Field_annotation_inconsistent _ -> | Over_annotation _ ->
false
| Field_over_annotated _ ->
false false
| Inconsistent_subclass_return_annotation _ -> | Bad_assignment _ ->
false false
| Inconsistent_subclass_parameter_annotation _ -> | Inconsistent_subclass _ ->
false false
| Nullable_dereference _ -> | Nullable_dereference _ ->
false false
| Parameter_annotation_inconsistent _ ->
false
| Return_annotation_inconsistent _ ->
false
| Return_over_annotated _ ->
false
(** Reset the always field of the forall erros in the node, so if they are not set again (** Reset the always field of the forall erros in the node, so if they are not set again
@ -221,153 +218,163 @@ type st_report_error =
-> string -> string
-> unit -> unit
(** Report an error right now. *) let get_infer_issue_type = function
let report_error_now tenv (st_report_error : st_report_error) err_instance loc pdesc : unit = | Condition_redundant _ ->
let pname = Procdesc.get_proc_name pdesc in IssueType.eradicate_condition_redundant
| Over_annotation (FieldOverAnnotedAsNullable _) ->
IssueType.eradicate_field_over_annotated
| Over_annotation (ReturnOverAnnotatedAsNullable _) ->
IssueType.eradicate_return_over_annotated
| Field_not_initialized _ ->
IssueType.eradicate_field_not_initialized
| Bad_assignment {assignment_type= PassingParamToAFunction _} ->
IssueType.eradicate_parameter_not_nullable
| Bad_assignment {assignment_type= AssigningToAField _} ->
IssueType.eradicate_field_not_nullable
| Bad_assignment {assignment_type= ReturningFromAFunction _} ->
IssueType.eradicate_return_not_nullable
| Nullable_dereference _ ->
IssueType.eradicate_nullable_dereference
| Inconsistent_subclass {inconsistent_subclass_type= InconsistentReturn} ->
IssueType.eradicate_inconsistent_subclass_return_annotation
| Inconsistent_subclass {inconsistent_subclass_type= InconsistentParam _} ->
IssueType.eradicate_inconsistent_subclass_parameter_annotation
(* If an error is related to a particular field, we support suppressing the
error via a supress annotation placed near the field declaration *)
let get_field_name_for_error_suppressing = function
| Over_annotation (FieldOverAnnotedAsNullable field_name) ->
Some field_name
| Field_not_initialized (field_name, _) ->
Some field_name
| Condition_redundant _
| Over_annotation (ReturnOverAnnotatedAsNullable _)
(* In case of assignment to a field, it should be fixed case by case for each assignment *)
| Bad_assignment _
| Nullable_dereference _
| Inconsistent_subclass _ ->
None
let get_error_description err_instance =
let nullable_annotation = "@Nullable" in let nullable_annotation = "@Nullable" in
let kind, description, field_name = match err_instance with
match err_instance with | Condition_redundant (is_always_true, s_opt) ->
| Condition_redundant (is_always_true, s_opt) -> P.sprintf "The condition %s is always %b according to the existing annotations."
( IssueType.eradicate_condition_redundant (Option.value s_opt ~default:"") is_always_true
, P.sprintf "The condition %s is always %b according to the existing annotations." | Over_annotation (FieldOverAnnotedAsNullable field_name) ->
(Option.value s_opt ~default:"") is_always_true Format.asprintf "Field %a is always initialized in the constructor but is declared %a"
, None ) MF.pp_monospaced
| Field_not_initialized (fn, pn) -> (Typ.Fieldname.to_simplified_string field_name)
let constructor_name = MF.pp_monospaced nullable_annotation
if Typ.Procname.is_constructor pn then "the constructor" | Over_annotation (ReturnOverAnnotatedAsNullable proc_name) ->
else Format.asprintf "Method %a is annotated with %a but never returns null." MF.pp_monospaced
match pn with (Typ.Procname.to_simplified_string proc_name)
| Typ.Procname.Java pn_java -> MF.pp_monospaced nullable_annotation
MF.monospaced_to_string (Typ.Procname.Java.get_method pn_java) | Field_not_initialized (field_name, proc_name) ->
| _ -> let constructor_name =
MF.monospaced_to_string (Typ.Procname.to_simplified_string pn) if Typ.Procname.is_constructor proc_name then "the constructor"
in else
( IssueType.eradicate_field_not_initialized match proc_name with
, Format.asprintf "Field %a is not initialized in %s and is not declared %a" | Typ.Procname.Java pn_java ->
MF.pp_monospaced MF.monospaced_to_string (Typ.Procname.Java.get_method pn_java)
(Typ.Fieldname.to_simplified_string fn) | _ ->
constructor_name MF.pp_monospaced nullable_annotation MF.monospaced_to_string (Typ.Procname.to_simplified_string proc_name)
, Some fn ) in
| Field_annotation_inconsistent (fn, (origin_description, _, _)) -> Format.asprintf "Field %a is not initialized in %s and is not declared %a" MF.pp_monospaced
let kind_s, description = (Typ.Fieldname.to_simplified_string field_name)
( IssueType.eradicate_field_not_nullable constructor_name MF.pp_monospaced nullable_annotation
, Format.asprintf "Field %a can be null but is not declared %a. %s" MF.pp_monospaced | Bad_assignment {rhs_origin_descr= origin_descr_string, _, _; assignment_type} -> (
(Typ.Fieldname.to_simplified_string fn) match assignment_type with
MF.pp_monospaced nullable_annotation origin_description ) | PassingParamToAFunction {param_description; param_position; function_procname} ->
in Format.asprintf "%a needs a non-null value in parameter %d but argument %a can be null. %s"
(kind_s, description, None) MF.pp_monospaced
| Field_over_annotated (fn, pn) -> (Typ.Procname.to_simplified_string ~withclass:true function_procname)
let constructor_name = param_position MF.pp_monospaced param_description origin_descr_string
if Typ.Procname.is_constructor pn then "the constructor" | AssigningToAField field_name ->
else Format.asprintf "Field %a can be null but is not declared %a. %s" MF.pp_monospaced
match pn with (Typ.Fieldname.to_simplified_string field_name)
| Typ.Procname.Java pn_java -> MF.pp_monospaced nullable_annotation origin_descr_string
Typ.Procname.Java.get_method pn_java | ReturningFromAFunction function_proc_name ->
| _ -> Format.asprintf "Method %a may return null but it is not annotated with %a. %s"
Typ.Procname.to_simplified_string pn MF.pp_monospaced
in (Typ.Procname.to_simplified_string function_proc_name)
( IssueType.eradicate_field_over_annotated MF.pp_monospaced nullable_annotation origin_descr_string )
, Format.asprintf "Field %a is always initialized in %s but is declared %a" | Nullable_dereference {nullable_object_descr; dereference_type; origin_descr= origin_str, _, _}
MF.pp_monospaced ->
(Typ.Fieldname.to_simplified_string fn) let nullable_object_descr =
constructor_name MF.pp_monospaced nullable_annotation match dereference_type with
, Some fn ) | MethodCall _ | AccessToField _ -> (
| Nullable_dereference {nullable_object_descr; dereference_type; origin_descr= origin_str, _, _} match nullable_object_descr with
-> | None ->
let nullable_object_descr = "Object"
match dereference_type with (* Just describe an object itself *)
| MethodCall _ | AccessToField _ -> ( | Some descr ->
match nullable_object_descr with MF.monospaced_to_string descr )
| None -> | ArrayLengthAccess | AccessByIndex _ -> (
"Object" (* In Java, those operations can be applied only to arrays *)
(* Just describe an object itself *) match nullable_object_descr with
| Some descr -> | None ->
MF.monospaced_to_string descr ) "Array"
| ArrayLengthAccess | AccessByIndex _ -> ( | Some descr ->
(* In Java, those operations can be applied only to arrays *) Format.sprintf "Array %s" (MF.monospaced_to_string descr) )
match nullable_object_descr with in
| None -> let action_descr =
"Array" match dereference_type with
| Some descr -> | MethodCall method_name ->
Format.sprintf "Array %s" (MF.monospaced_to_string descr) ) Format.sprintf "calling %s"
in (MF.monospaced_to_string (Typ.Procname.to_simplified_string method_name))
let action_descr = | AccessToField field_name ->
match dereference_type with Format.sprintf "accessing field %s"
| MethodCall method_name -> (MF.monospaced_to_string (Typ.Fieldname.to_simplified_string field_name))
Format.sprintf "calling %s" | AccessByIndex {index_desc} ->
(MF.monospaced_to_string (Typ.Procname.to_simplified_string method_name)) Format.sprintf "accessing at index %s" (MF.monospaced_to_string index_desc)
| AccessToField field_name -> | ArrayLengthAccess ->
Format.sprintf "accessing field %s" "accessing its length"
(MF.monospaced_to_string (Typ.Fieldname.to_simplified_string field_name)) in
| AccessByIndex {index_desc} -> Format.sprintf "%s is nullable and is not locally checked for null when %s. %s"
Format.sprintf "accessing at index %s" (MF.monospaced_to_string index_desc) nullable_object_descr action_descr origin_str
| ArrayLengthAccess -> | Inconsistent_subclass {base_proc_name; overridden_proc_name; inconsistent_subclass_type} -> (
"accessing its length" let base_method_descr = Typ.Procname.to_simplified_string ~withclass:true base_proc_name in
in let overridden_method_descr =
let description = Typ.Procname.to_simplified_string ~withclass:true overridden_proc_name
Format.sprintf "%s is nullable and is not locally checked for null when %s. %s" in
nullable_object_descr action_descr origin_str match inconsistent_subclass_type with
in | InconsistentReturn ->
(IssueType.eradicate_nullable_dereference, description, None) Format.asprintf "Method %a is annotated with %a but overrides unannotated method %a."
| Parameter_annotation_inconsistent (s, n, pn, _, (origin_desc, _, _)) -> MF.pp_monospaced overridden_method_descr MF.pp_monospaced nullable_annotation
let kind_s, description = MF.pp_monospaced base_method_descr
( IssueType.eradicate_parameter_not_nullable | InconsistentParam {param_description; param_position} ->
, Format.asprintf let translate_position = function
"%a needs a non-null value in parameter %d but argument %a can be null. %s" | 1 ->
MF.pp_monospaced "First"
(Typ.Procname.to_simplified_string ~withclass:true pn) | 2 ->
n MF.pp_monospaced s origin_desc ) "Second"
in | 3 ->
(kind_s, description, None) "Third"
| Return_annotation_inconsistent (pn, (origin_description, _, _)) -> | n ->
let kind_s, description = string_of_int n ^ "th"
( IssueType.eradicate_return_not_nullable in
, Format.asprintf "Method %a may return null but it is not annotated with %a. %s" Format.asprintf
MF.pp_monospaced
(Typ.Procname.to_simplified_string pn)
MF.pp_monospaced nullable_annotation origin_description )
in
(kind_s, description, None)
| Return_over_annotated pn ->
( IssueType.eradicate_return_over_annotated
, Format.asprintf "Method %a is annotated with %a but never returns null." MF.pp_monospaced
(Typ.Procname.to_simplified_string pn)
MF.pp_monospaced nullable_annotation
, None )
| Inconsistent_subclass_return_annotation (pn, opn) ->
( IssueType.eradicate_inconsistent_subclass_return_annotation
, Format.asprintf "Method %a is annotated with %a but overrides unannotated method %a."
MF.pp_monospaced
(Typ.Procname.to_simplified_string ~withclass:true pn)
MF.pp_monospaced nullable_annotation MF.pp_monospaced
(Typ.Procname.to_simplified_string ~withclass:true opn)
, None )
| Inconsistent_subclass_parameter_annotation (param_name, pos, pn, opn) ->
let translate_position = function
| 1 ->
"First"
| 2 ->
"Second"
| 3 ->
"Third"
| n ->
string_of_int n ^ "th"
in
( IssueType.eradicate_inconsistent_subclass_parameter_annotation
, Format.asprintf
"%s parameter %a of method %a is not %a but is declared %ain the parent class method \ "%s parameter %a of method %a is not %a but is declared %ain the parent class method \
%a." %a."
(translate_position pos) MF.pp_monospaced param_name MF.pp_monospaced (translate_position param_position)
(Typ.Procname.to_simplified_string ~withclass:true pn) MF.pp_monospaced param_description MF.pp_monospaced overridden_method_descr
MF.pp_monospaced nullable_annotation MF.pp_monospaced nullable_annotation MF.pp_monospaced nullable_annotation MF.pp_monospaced nullable_annotation
MF.pp_monospaced MF.pp_monospaced base_method_descr )
(Typ.Procname.to_simplified_string ~withclass:true opn)
, None )
in (** Report an error right now. *)
let report_error_now tenv (st_report_error : st_report_error) err_instance loc pdesc : unit =
let pname = Procdesc.get_proc_name pdesc in
let infer_issue_type = get_infer_issue_type err_instance in
let field_name = get_field_name_for_error_suppressing err_instance in
let err_description = get_error_description err_instance in
let severity = Severity.err_instance_get_severity tenv err_instance in let severity = Severity.err_instance_get_severity tenv err_instance in
st_report_error pname pdesc kind loc ~field_name st_report_error pname pdesc infer_issue_type loc ~field_name
~exception_kind:(fun k d -> Exceptions.Eradicate (k, d)) ~exception_kind:(fun k d -> Exceptions.Eradicate (k, d))
?severity description ?severity err_description
(** Report an error unless is has been reported already, or unless it's a forall error (** Report an error unless is has been reported already, or unless it's a forall error

@ -34,33 +34,39 @@ type origin_descr = string * Location.t option * AnnotatedSignature.t option
(* callee signature *) (* callee signature *)
type parameter_not_nullable =
string
* (* description *)
int
* (* parameter number *)
Typ.Procname.t
* Location.t
* (* callee location *)
origin_descr
(** Instance of an error *) (** Instance of an error *)
type err_instance = type err_instance =
| Condition_redundant of (bool * string option) | Condition_redundant of (bool * string option)
| Inconsistent_subclass_return_annotation of Typ.Procname.t * Typ.Procname.t | Inconsistent_subclass of
| Inconsistent_subclass_parameter_annotation of string * int * Typ.Procname.t * Typ.Procname.t { base_proc_name: Typ.Procname.t
; overridden_proc_name: Typ.Procname.t
; inconsistent_subclass_type: inconsistent_subclass_type }
| Field_not_initialized of Typ.Fieldname.t * Typ.Procname.t | Field_not_initialized of Typ.Fieldname.t * Typ.Procname.t
| Field_annotation_inconsistent of Typ.Fieldname.t * origin_descr | Over_annotation of over_annotation_type
| Field_over_annotated of Typ.Fieldname.t * Typ.Procname.t
| Nullable_dereference of | Nullable_dereference of
{ nullable_object_descr: string option { nullable_object_descr: string option
; dereference_type: dereference_type ; dereference_type: dereference_type
; origin_descr: origin_descr } ; origin_descr: origin_descr }
| Parameter_annotation_inconsistent of parameter_not_nullable | Bad_assignment of {rhs_origin_descr: origin_descr; assignment_type: assignment_type}
| Return_annotation_inconsistent of Typ.Procname.t * origin_descr
| Return_over_annotated of Typ.Procname.t
[@@deriving compare] [@@deriving compare]
and inconsistent_subclass_type =
| InconsistentParam of {param_description: string; param_position: int}
| InconsistentReturn
and over_annotation_type =
| FieldOverAnnotedAsNullable of Typ.Fieldname.t
| ReturnOverAnnotatedAsNullable of Typ.Procname.t
(** Return value of a method can be made non-nullable *)
and assignment_type =
| PassingParamToAFunction of
{ param_description: string
; param_position: int
; function_procname: Typ.Procname.t }
| AssigningToAField of Typ.Fieldname.t
| ReturningFromAFunction of Typ.Procname.t
and dereference_type = and dereference_type =
| MethodCall of Typ.Procname.t (** nullable_object.some_method() *) | MethodCall of Typ.Procname.t (** nullable_object.some_method() *)
| AccessToField of Typ.Fieldname.t (** nullable_object.some_field *) | AccessToField of Typ.Fieldname.t (** nullable_object.some_field *)

Loading…
Cancel
Save