diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index 46cbca570..ca044f7b1 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -1092,14 +1092,6 @@ module Fieldname = struct module Set = Caml.Set.Make (T) module Map = Caml.Map.Make (T) - module Clang = struct - let from_class_name class_name field_name = Clang {class_name; field_name} - end - - module Java = struct - let from_string n = Java n - end - (** Convert a fieldname to a string. *) let to_string = function | Hidden @@ -1181,6 +1173,21 @@ module Fieldname = struct (** hidded fieldname constant *) let is_hidden fn = equal fn hidden + + module Clang = struct + let from_class_name class_name field_name = Clang {class_name; field_name} + end + + module Java = struct + let from_string n = Java n + + let is_captured_parameter field_name = + match field_name with + | Java _ + -> String.is_prefix ~prefix:"val$" (to_flat_string field_name) + | Hidden | Clang _ + -> false + end end module Struct = struct diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index 66c8f47a4..b2d05c537 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -509,6 +509,9 @@ module Fieldname : sig module Java : sig val from_string : string -> t (** Create a java field name from string *) + + val is_captured_parameter : t -> bool + (** Check if field is a captured parameter *) end val to_string : t -> string diff --git a/infer/src/checkers/NullabilitySuggest.ml b/infer/src/checkers/NullabilitySuggest.ml index f9d7d8b30..68bd05c1d 100644 --- a/infer/src/checkers/NullabilitySuggest.ml +++ b/infer/src/checkers/NullabilitySuggest.ml @@ -148,6 +148,9 @@ let checker {Callbacks.summary; proc_desc; tenv} = let report_access_path ap udchain = let issue_kind = Localise.to_issue_id Localise.field_should_be_nullable in match AccessPath.Raw.get_field_and_annotation ap proc_data.tenv with + | Some (field_name, _) when Typ.Fieldname.Java.is_captured_parameter field_name + -> (* Skip reporting when field comes from generated code *) + () | Some (field_name, _) -> ( let message = diff --git a/infer/tests/codetoanalyze/java/checkers/NullableSuggest.java b/infer/tests/codetoanalyze/java/checkers/NullableSuggest.java index 3aa117eec..74bc7b21d 100644 --- a/infer/tests/codetoanalyze/java/checkers/NullableSuggest.java +++ b/infer/tests/codetoanalyze/java/checkers/NullableSuggest.java @@ -105,4 +105,25 @@ public class NullableSuggest { // Pretend that we did something here... } } + + void methodWithCapturedNullableParameterOk(@Nullable Object parameter) { + Object object = new Object() { + void foo() { + if (parameter != null) { + parameter.toString(); + } + } + }; + } + + void methodWithCapturednonNullableParameterBad_FN(Object parameter) { + Object object = new Object() { + void foo() { + if (parameter != null) { + parameter.toString(); + } + } + }; + } + } diff --git a/infer/tests/codetoanalyze/java/eradicate/FieldNotNullable.java b/infer/tests/codetoanalyze/java/eradicate/FieldNotNullable.java index 08b6d8f1c..68135d2c3 100644 --- a/infer/tests/codetoanalyze/java/eradicate/FieldNotNullable.java +++ b/infer/tests/codetoanalyze/java/eradicate/FieldNotNullable.java @@ -350,4 +350,12 @@ class NestedFieldAccess { } } + void methodWithNullableCapturedParameterBad_FN(@Nullable Object parameter) { + Object object = new Object() { + void foo() { + parameter.toString(); + } + }; + } + }