[nullsafe][refactor][messaging] Refactor code + more consistent messaging

Summary:
In the previos diff we restructured error rendering utils for
TypeOrigin.MethodCall.

In this diff we do the same with TypeOrigin field: lets make the code
consistent.

We also clearly distinct third party from all other possible cases in
this branch.

This changes messaging and reported errors for strict modes (see test cases), and I believe this is a net improvement.

Reviewed By: artempyanykh

Differential Revision: D20139741

fbshipit-source-id: 84f502553
master
Mitya Lyubarskiy 5 years ago committed by Facebook Github Bot
parent 2aea7d1304
commit f136bf21b5

@ -84,19 +84,17 @@ let get_field_class_name field_name =
|> Option.value_map ~f:(fun (classname, _) -> classname) ~default:"the field class" |> Option.value_map ~f:(fun (classname, _) -> classname) ~default:"the field class"
let mk_coming_from nullsafe_mode nullability = let mk_coming_from_unchecked_or_locally_checked_case_only nullsafe_mode nullability =
match (nullsafe_mode, nullability) with match (nullsafe_mode, nullability) with
| NullsafeMode.Strict, Nullability.ThirdPartyNonnull
| NullsafeMode.Strict, Nullability.UncheckedNonnull -> | NullsafeMode.Strict, Nullability.UncheckedNonnull ->
Some "non-strict classes" "non-strict classes"
| NullsafeMode.Strict, Nullability.LocallyCheckedNonnull -> | NullsafeMode.Strict, Nullability.LocallyCheckedNonnull ->
Some "nullsafe-local classes" "nullsafe-local classes"
| NullsafeMode.Local _, Nullability.ThirdPartyNonnull ->
Some "third-party classes"
| NullsafeMode.Local _, Nullability.UncheckedNonnull -> | NullsafeMode.Local _, Nullability.UncheckedNonnull ->
Some "non-nullsafe classes" "non-nullsafe classes"
| _ -> | _ ->
None Logging.die Logging.InternalError
"Should be called only for locally checked or unchecked nonnull cases"
let mk_recommendation nullsafe_mode nullability what = let mk_recommendation nullsafe_mode nullability what =
@ -110,14 +108,15 @@ let mk_recommendation nullsafe_mode nullability what =
None None
let mk_recommendation_for_third_party_field nullsafe_mode nullability field = let mk_recommendation_for_third_party_field nullsafe_mode field =
match (nullsafe_mode, nullability) with match nullsafe_mode with
| NullsafeMode.Strict, Nullability.ThirdPartyNonnull -> | NullsafeMode.Strict ->
Some (F.sprintf "access %s via a nullsafe strict getter" field) F.sprintf "access %s via a nullsafe strict getter" field
| NullsafeMode.Local _, Nullability.ThirdPartyNonnull -> | NullsafeMode.Local _ ->
Some (F.sprintf "access %s via a nullsafe getter" field) F.sprintf "access %s via a nullsafe getter" field
| _ -> | NullsafeMode.Default ->
None Logging.die Logging.InternalError
"Should not happen: we should tolerate third party in default mode"
let get_info object_origin nullsafe_mode bad_nullability = let get_info object_origin nullsafe_mode bad_nullability =
@ -136,7 +135,6 @@ let get_info object_origin nullsafe_mode bad_nullability =
(* This method makes sense only for non-nullable violations *) (* This method makes sense only for non-nullable violations *)
None None
| Nullability.StrictNonnull -> | Nullability.StrictNonnull ->
(* This method makes sense only for non-nullable violations *)
Logging.die InternalError "There should not be type violations involving StrictNonnull" Logging.die InternalError "There should not be type violations involving StrictNonnull"
| Nullability.ThirdPartyNonnull -> | Nullability.ThirdPartyNonnull ->
let suggested_third_party_sig_file = let suggested_third_party_sig_file =
@ -157,7 +155,9 @@ let get_info object_origin nullsafe_mode bad_nullability =
, F.sprintf "add the correct signature to %s" where_to_add_signature , F.sprintf "add the correct signature to %s" where_to_add_signature
, IssueType.eradicate_unvetted_third_party_in_nullsafe ) , IssueType.eradicate_unvetted_third_party_in_nullsafe )
| Nullability.UncheckedNonnull | Nullability.LocallyCheckedNonnull -> | Nullability.UncheckedNonnull | Nullability.LocallyCheckedNonnull ->
let* from = mk_coming_from nullsafe_mode bad_nullability in let from =
mk_coming_from_unchecked_or_locally_checked_case_only nullsafe_mode bad_nullability
in
let+ recommendation = let+ recommendation =
let what_to_strictify = let what_to_strictify =
Option.value (get_method_class_name pname) ~default:offending_object Option.value (get_method_class_name pname) ~default:offending_object
@ -184,13 +184,27 @@ let get_info object_origin nullsafe_mode bad_nullability =
(* TODO: currently we do not support third-party annotations for fields. Because of this, (* TODO: currently we do not support third-party annotations for fields. Because of this,
render error like it is a non-stict class. *) render error like it is a non-stict class. *)
let what_is_used = "This field" in let what_is_used = "This field" in
let* coming_from_explanation = mk_coming_from nullsafe_mode bad_nullability in let+ coming_from_explanation, recommendation, issue_type =
let+ recommendation = match bad_nullability with
Option.first_some | Nullability.Null | Nullability.Nullable ->
(mk_recommendation_for_third_party_field nullsafe_mode bad_nullability unqualified_name) (* This method makes sense only for non-nullable violations *)
(mk_recommendation nullsafe_mode bad_nullability (get_field_class_name field_name)) None
| Nullability.StrictNonnull ->
Logging.die InternalError "There should not be type violations involving StrictNonnull"
| Nullability.ThirdPartyNonnull ->
return
( "third-party classes"
, mk_recommendation_for_third_party_field nullsafe_mode unqualified_name
, IssueType.eradicate_unvetted_third_party_in_nullsafe )
| Nullability.UncheckedNonnull | Nullability.LocallyCheckedNonnull ->
let from =
mk_coming_from_unchecked_or_locally_checked_case_only nullsafe_mode bad_nullability
in
let+ recommendation =
mk_recommendation nullsafe_mode bad_nullability (get_field_class_name field_name)
in
(from, recommendation, IssueType.eradicate_unchecked_usage_in_nullsafe)
in in
let issue_type = IssueType.eradicate_unchecked_usage_in_nullsafe in
{ offending_object= qualified_name { offending_object= qualified_name
; object_loc ; object_loc
; coming_from_explanation ; coming_from_explanation

@ -156,7 +156,7 @@ codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsa
codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$StrictNullsafe.BAD_returnFromNonNullsafe():java.lang.String, 0, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NullsafeMode$NonNullsafe.returnVal()`: `@NullsafeStrict` mode prohibits using values coming from non-strict classes without a check. Result of this call is used at line 198. Either add a local check for null or assertion, or make NullsafeMode$NonNullsafe nullsafe strict.] codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$StrictNullsafe.BAD_returnFromNonNullsafe():java.lang.String, 0, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NullsafeMode$NonNullsafe.returnVal()`: `@NullsafeStrict` mode prohibits using values coming from non-strict classes without a check. Result of this call is used at line 198. Either add a local check for null or assertion, or make NullsafeMode$NonNullsafe nullsafe strict.]
codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_passThirdPartyToUnchecked():codetoanalyze.java.nullsafe_default.NullsafeMode$UncheckedParams, 0, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.getUncheckedLong(...)`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 113. Either add a local check for null or assertion, or add the correct signature to nullsafe-default/third-party-signatures/some.test.pckg.sig.] codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_passThirdPartyToUnchecked():codetoanalyze.java.nullsafe_default.NullsafeMode$UncheckedParams, 0, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.getUncheckedLong(...)`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 113. Either add a local check for null or assertion, or add the correct signature to nullsafe-default/third-party-signatures/some.test.pckg.sig.]
codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_returnFromUnvettedThirdParty():java.lang.String, 0, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 93. Either add a local check for null or assertion, or add the correct signature to nullsafe-default/third-party-signatures/some.test.pckg.sig.] codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_returnFromUnvettedThirdParty():java.lang.String, 0, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 93. Either add a local check for null or assertion, or add the correct signature to nullsafe-default/third-party-signatures/some.test.pckg.sig.]
codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_returnNonNullableFieldFromThirdParty():java.lang.String, 0, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.nonNullableField`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from third-party classes without a check. This field is used at line 101. Either add a local check for null or assertion, or access `nonNullableField` via a nullsafe getter.] codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_returnNonNullableFieldFromThirdParty():java.lang.String, 0, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.nonNullableField`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from third-party classes without a check. This field is used at line 101. Either add a local check for null or assertion, or access `nonNullableField` via a nullsafe getter.]
codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_returnNullFromNonNulsafe():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`BAD_returnNullFromNonNulsafe()`: return type is declared non-nullable but the method returns a nullable value: call to returnNull() at line 89.] codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_returnNullFromNonNulsafe():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`BAD_returnNullFromNonNulsafe()`: return type is declared non-nullable but the method returns a nullable value: call to returnNull() at line 89.]
codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_returnNullableFieldFromThirdParty():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`BAD_returnNullableFieldFromThirdParty()`: return type is declared non-nullable but the method returns a nullable value: field nullableField at line 97.] codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustAllNullsafe.BAD_returnNullableFieldFromThirdParty():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`BAD_returnNullableFieldFromThirdParty()`: return type is declared non-nullable but the method returns a nullable value: field nullableField at line 97.]
codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustNoneNullsafe.BAD_returnFromNonNullsafe():java.lang.String, 0, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NullsafeMode$NonNullsafe.returnVal()`: `@NullsafeLocal(trust=none)` mode prohibits using values coming from non-nullsafe classes without a check. Result of this call is used at line 155. Either add a local check for null or assertion, or make NullsafeMode$NonNullsafe nullsafe.] codetoanalyze/java/nullsafe-default/NullsafeMode.java, codetoanalyze.java.nullsafe_default.NullsafeMode$TrustNoneNullsafe.BAD_returnFromNonNullsafe():java.lang.String, 0, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NullsafeMode$NonNullsafe.returnVal()`: `@NullsafeLocal(trust=none)` mode prohibits using values coming from non-nullsafe classes without a check. Result of this call is used at line 155. Either add a local check for null or assertion, or make NullsafeMode$NonNullsafe nullsafe.]
@ -253,7 +253,7 @@ codetoanalyze/java/nullsafe-default/StrictMode.java, codetoanalyze.java.nullsafe
codetoanalyze/java/nullsafe-default/StrictMode.java, codetoanalyze.java.nullsafe_default.Strict.strictClass_dereferenceNullableFieldIsBad():void, 0, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`__new(...).nullable` is nullable and is not locally checked for null when calling `toString()`.] codetoanalyze/java/nullsafe-default/StrictMode.java, codetoanalyze.java.nullsafe_default.Strict.strictClass_dereferenceNullableFieldIsBad():void, 0, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`__new(...).nullable` is nullable and is not locally checked for null when calling `toString()`.]
codetoanalyze/java/nullsafe-default/StrictMode.java, codetoanalyze.java.nullsafe_default.Strict.strictClass_dereferenceNullableMethodIsBad():void, 0, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`__new(...).getNullable()` is nullable and is not locally checked for null when calling `toString()`.] codetoanalyze/java/nullsafe-default/StrictMode.java, codetoanalyze.java.nullsafe_default.Strict.strictClass_dereferenceNullableMethodIsBad():void, 0, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`__new(...).getNullable()` is nullable and is not locally checked for null when calling `toString()`.]
codetoanalyze/java/nullsafe-default/StrictMode.java, codetoanalyze.java.nullsafe_default.Strict.strictClass_dereferenceNullableStaticMethodIsBad():void, 0, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`staticNullable()` is nullable and is not locally checked for null when calling `toString()`.] codetoanalyze/java/nullsafe-default/StrictMode.java, codetoanalyze.java.nullsafe_default.Strict.strictClass_dereferenceNullableStaticMethodIsBad():void, 0, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`staticNullable()` is nullable and is not locally checked for null when calling `toString()`.]
codetoanalyze/java/nullsafe-default/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe_default.StrictModeForThirdParty.dereferenceFieldIsBAD():void, 0, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.nonNullableField`: `@NullsafeStrict` mode prohibits using values coming from non-strict classes without a check. This field is used at line 49. Either add a local check for null or assertion, or access `nonNullableField` via a nullsafe strict getter.] codetoanalyze/java/nullsafe-default/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe_default.StrictModeForThirdParty.dereferenceFieldIsBAD():void, 0, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.nonNullableField`: `@NullsafeStrict` mode prohibits using values coming from third-party classes without a check. This field is used at line 49. Either add a local check for null or assertion, or access `nonNullableField` via a nullsafe strict getter.]
codetoanalyze/java/nullsafe-default/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe_default.StrictModeForThirdParty.dereferenceSpecifiedAsNullableIsBAD():void, 0, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`StrictModeForThirdParty.obj.returnSpecifiedAsNullable()` is nullable and is not locally checked for null when calling `toString()`: call to ThirdPartyTestClass.returnSpecifiedAsNullable() at line 45 (declared nullable in nullsafe-default/third-party-signatures/some.test.pckg.sig at line 2).] codetoanalyze/java/nullsafe-default/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe_default.StrictModeForThirdParty.dereferenceSpecifiedAsNullableIsBAD():void, 0, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`StrictModeForThirdParty.obj.returnSpecifiedAsNullable()` is nullable and is not locally checked for null when calling `toString()`: call to ThirdPartyTestClass.returnSpecifiedAsNullable() at line 45 (declared nullable in nullsafe-default/third-party-signatures/some.test.pckg.sig at line 2).]
codetoanalyze/java/nullsafe-default/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe_default.StrictModeForThirdParty.dereferenceUnspecifiedIsBAD():void, 0, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 41. Either add a local check for null or assertion, or add the correct signature to nullsafe-default/third-party-signatures/some.test.pckg.sig.] codetoanalyze/java/nullsafe-default/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe_default.StrictModeForThirdParty.dereferenceUnspecifiedIsBAD():void, 0, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 41. Either add a local check for null or assertion, or add the correct signature to nullsafe-default/third-party-signatures/some.test.pckg.sig.]
codetoanalyze/java/nullsafe-default/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe_default.StrictModeForThirdParty.passingNullableParamToUnspecifiedIsBAD():void, 0, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, ERROR, [Third-party `ThirdPartyTestClass.paramUnspecified(...)` is missing a signature that would allow passing a nullable to param #1(`param`). Actual argument `getNullable()` is nullable. Consider adding the correct signature of `ThirdPartyTestClass.paramUnspecified(...)` to nullsafe-default/third-party-signatures/some.test.pckg.sig.] codetoanalyze/java/nullsafe-default/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe_default.StrictModeForThirdParty.passingNullableParamToUnspecifiedIsBAD():void, 0, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, ERROR, [Third-party `ThirdPartyTestClass.paramUnspecified(...)` is missing a signature that would allow passing a nullable to param #1(`param`). Actual argument `getNullable()` is nullable. Consider adding the correct signature of `ThirdPartyTestClass.paramUnspecified(...)` to nullsafe-default/third-party-signatures/some.test.pckg.sig.]

Loading…
Cancel
Save