|
@@ -1213,18 +1213,45 @@ class class_checker cls immediate_execution report =
|
|
Option.may (fun f -> Option.may (fun e -> print_endline (s_expr (fun t -> "") e)) f.cf_expr) cls.cl_constructor; *)
|
|
Option.may (fun f -> Option.may (fun e -> print_endline (s_expr (fun t -> "") e)) f.cf_expr) cls.cl_constructor; *)
|
|
if is_safe_class && (not cls.cl_extern) && (not cls.cl_interface) then
|
|
if is_safe_class && (not cls.cl_extern) && (not cls.cl_interface) then
|
|
self#check_var_fields;
|
|
self#check_var_fields;
|
|
- let check_field f =
|
|
|
|
|
|
+ let check_field is_static f =
|
|
if self#is_in_safety f then begin
|
|
if self#is_in_safety f then begin
|
|
(* if f.cf_name = "return_assignNonNullable_shouldPass" then
|
|
(* if f.cf_name = "return_assignNonNullable_shouldPass" then
|
|
Option.may (fun e -> print_endline (s_expr str_type e)) f.cf_expr; *)
|
|
Option.may (fun e -> print_endline (s_expr str_type e)) f.cf_expr; *)
|
|
- Option.may checker#check_root_expr f.cf_expr
|
|
|
|
|
|
+ Option.may checker#check_root_expr f.cf_expr;
|
|
|
|
+ self#check_accessors is_static f
|
|
end
|
|
end
|
|
in
|
|
in
|
|
if is_safe_class then
|
|
if is_safe_class then
|
|
Option.may checker#check_root_expr cls.cl_init;
|
|
Option.may checker#check_root_expr cls.cl_init;
|
|
- Option.may check_field cls.cl_constructor;
|
|
|
|
- List.iter check_field cls.cl_ordered_fields;
|
|
|
|
- List.iter check_field cls.cl_ordered_statics;
|
|
|
|
|
|
+ Option.may (check_field false) cls.cl_constructor;
|
|
|
|
+ List.iter (check_field false) cls.cl_ordered_fields;
|
|
|
|
+ List.iter (check_field true) cls.cl_ordered_statics;
|
|
|
|
+ (**
|
|
|
|
+ Check if a getter/setter for non-nullable property return safe values.
|
|
|
|
+ E.g.
|
|
|
|
+ ```
|
|
|
|
+ var str(get,never):String;
|
|
|
|
+ function get_str() return (null:Null<String>); //should fail null safety check
|
|
|
|
+ ```
|
|
|
|
+ *)
|
|
|
|
+ method private check_accessors is_static field =
|
|
|
|
+ match field.cf_kind with
|
|
|
|
+ | Var { v_read = read_access; v_write = write_access } when not (is_nullable_type field.cf_type) ->
|
|
|
|
+ let fields = if is_static then cls.cl_statics else cls.cl_fields in
|
|
|
|
+ let check_accessor prefix =
|
|
|
|
+ let accessor =
|
|
|
|
+ try Some (PMap.find (prefix ^ field.cf_name) fields)
|
|
|
|
+ with Not_found -> None
|
|
|
|
+ in
|
|
|
|
+ match accessor with
|
|
|
|
+ | Some { cf_expr = Some ({ eexpr = TFunction fn } as accessor_expr) } ->
|
|
|
|
+ let fn = { fn with tf_type = field.cf_type } in
|
|
|
|
+ checker#check_root_expr { accessor_expr with eexpr = TFunction fn }
|
|
|
|
+ | _ -> ()
|
|
|
|
+ in
|
|
|
|
+ if read_access = AccCall then check_accessor "get_";
|
|
|
|
+ if write_access = AccCall then check_accessor "set_"
|
|
|
|
+ | _ -> ()
|
|
(**
|
|
(**
|
|
Check if field should be checked by null safety
|
|
Check if field should be checked by null safety
|
|
*)
|
|
*)
|