[nullsafe] Model Field nullability for Boolean.TRUE and Boolean.FALSE

Summary:
This diff:
1. Adds general capability to model any field as nullable /
non-nullable.
2. Uses it for Boolean.TRUE and Boolean.FALSE

Reviewed By: artempyanykh

Differential Revision: D22794226

fbshipit-source-id: 95f586592
master
Mitya Lyubarskiy 5 years ago committed by Facebook GitHub Bot
parent 5a71583c72
commit 4d09c54e29

@ -76,6 +76,8 @@ let get tenv field_name class_typ =
(* This field is artifact of codegen and is not visible to the user.
Surfacing it as non-strict is non-actionable for the user *)
AnnotatedNullability.StrictNonnull SyntheticField
else if Models.is_field_nonnullable field_name then
AnnotatedNullability.StrictNonnull ModelledNonnull
else nullability
else nullability
in

@ -712,3 +712,11 @@ let nonnull_alternatives_table =
~f:(fun (_, method_descr, alternative) -> (alternative, method_descr))
in
mk_table method_descr_to_alternative
let field_nullability = [("java.lang.Boolean.TRUE", o); ("java.lang.Boolean.FALSE", o)]
let field_nullability_table =
let table = Hashtbl.create 1 in
List.iter field_nullability ~f:(fun (name, nullability) -> Hashtbl.add table name nullability) ;
table

@ -43,3 +43,7 @@ val nonnull_alternatives_table : (string, nonnull_alternative_method) Caml.Hasht
(** The key is a string representation of a [@Nullable] method. The value is the description of
non-nullable alternative: a method does the same, but never returns null (does a null check
inside). *)
val field_nullability_table : (string, bool) Caml.Hashtbl.t
(** Table of known fields whos nullability is explicitly modelled. Keys are field full names; value
[true] means nullable *)

@ -154,3 +154,9 @@ let find_nonnullable_alternative proc_name =
It is a good idea to support this feature in a user-facing third party repository. *)
let proc_id = Procname.to_unique_id proc_name in
Hashtbl.find_opt nonnull_alternatives_table proc_id
(* Check if a given field is known to be a non-nullable *)
let is_field_nonnullable field_name =
Hashtbl.find_opt field_nullability_table (Fieldname.to_full_string field_name)
|> Option.value_map ~f:(fun is_nullable -> not is_nullable) ~default:false

@ -168,6 +168,14 @@ class Strict {
return SomeEnum.valueOf("this will throw but won't return null");
}
private Boolean booleanFALSE_NonNullableOK() {
return Boolean.FALSE;
}
private Boolean booleanTRUE_NonNullableOK() {
return Boolean.TRUE;
}
private String nonStrictClass_convertingNonnullToNonnullIsBad() {
// even that it is declared as nonnull, can not convert it to nonnull it without checking before
return (new NonStrict()).getNonnull();

@ -315,11 +315,11 @@ codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe.
codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe.ReturnNotNullable.return_null_in_catch_after_throw():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [`return_null_in_catch_after_throw()`: return type is declared non-nullable but the method returns `null`: null constant at line 172.]
codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe.ReturnNotNullable.tryWithResourcesReturnNullable(java.lang.String):java.lang.Object, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [`tryWithResourcesReturnNullable(...)`: return type is declared non-nullable but the method returns a nullable value: call to nullToNullableIsOK() at line 142.]
codetoanalyze/java/nullsafe/StrictMode.java, Linters_dummy_method, 15, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], Strict, codetoanalyze.java.nullsafe, issues: 17, curr_mode: "Strict"
codetoanalyze/java/nullsafe/StrictMode.java, Linters_dummy_method, 231, ERADICATE_META_CLASS_IS_NULLSAFE, no_bucket, INFO, [], OtherStrict, codetoanalyze.java.nullsafe, issues: 0, curr_mode: "Strict"
codetoanalyze/java/nullsafe/StrictMode.java, Linters_dummy_method, 252, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `NonStrict` is free of nullability issues. Mark it `@Nullsafe(Nullsafe.Mode.LOCAL)` to prevent regressions.], NonStrict, codetoanalyze.java.nullsafe, issues: 0, curr_mode: "Default", promote_mode: "LocalTrustAll"
codetoanalyze/java/nullsafe/StrictMode.java, Linters_dummy_method, 277, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], SomeEnum, codetoanalyze.java.nullsafe, issues: 0, curr_mode: "Default"
codetoanalyze/java/nullsafe/StrictMode.java, Linters_dummy_method, 239, ERADICATE_META_CLASS_IS_NULLSAFE, no_bucket, INFO, [], OtherStrict, codetoanalyze.java.nullsafe, issues: 0, curr_mode: "Strict"
codetoanalyze/java/nullsafe/StrictMode.java, Linters_dummy_method, 260, ERADICATE_META_CLASS_CAN_BE_NULLSAFE, no_bucket, ADVICE, [Congrats! `NonStrict` is free of nullability issues. Mark it `@Nullsafe(Nullsafe.Mode.LOCAL)` to prevent regressions.], NonStrict, codetoanalyze.java.nullsafe, issues: 0, curr_mode: "Default", promote_mode: "LocalTrustAll"
codetoanalyze/java/nullsafe/StrictMode.java, Linters_dummy_method, 285, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], SomeEnum, codetoanalyze.java.nullsafe, issues: 0, curr_mode: "Default"
codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict.<init>(), 0, ERADICATE_FIELD_NOT_INITIALIZED, no_bucket, ERROR, [Field `notInitializedIsBAD` is declared non-nullable, so it should be initialized in the constructor or in an `@Initializer` method]
codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict.nonStrictClass_convertingNonnullToNonnullIsBad():java.lang.String, 2, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NonStrict.getNonnull()`: `@NullsafeStrict` mode prohibits using values coming from non-strict classes without a check. Result of this call is used at line 171. Either add a local check for null or assertion, or make `NonStrict` nullsafe strict.]
codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict.nonStrictClass_convertingNonnullToNonnullIsBad():java.lang.String, 2, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NonStrict.getNonnull()`: `@NullsafeStrict` mode prohibits using values coming from non-strict classes without a check. Result of this call is used at line 179. Either add a local check for null or assertion, or make `NonStrict` nullsafe strict.]
codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict.nonStrictClass_convertingNonnullToNullableIsOK():java.lang.String, 0, ERADICATE_RETURN_OVER_ANNOTATED, no_bucket, ADVICE, [Method `nonStrictClass_convertingNonnullToNullableIsOK()` is annotated with `@Nullable` but never returns null.]
codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict.nonStrictClass_convertingNullableToNonnullIsBad():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`nonStrictClass_convertingNullableToNonnullIsBad()`: return type is declared non-nullable but the method returns a nullable value: call to getNullable() at line 137.]
codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict.nonStrictClass_dereferenceNonnullFieldAfterCheckIsOK():void, 2, ERADICATE_CONDITION_REDUNDANT, no_bucket, ADVICE, [The condition NonStrict.nonnull might be always true according to the existing annotations.]

Loading…
Cancel
Save