diff --git a/infer/src/checkers/LithoFramework.ml b/infer/src/checkers/LithoFramework.ml index 69f463fa7..4ecd9a0e1 100644 --- a/infer/src/checkers/LithoFramework.ml +++ b/infer/src/checkers/LithoFramework.ml @@ -104,29 +104,32 @@ struct type extras = ProcData.no_extras - let apply_callee_summary summary_opt caller_pname ret_id_typ actuals astate = - match summary_opt with - | Some summary -> - (* TODO: append paths if the footprint access path is an actual path instead of a var *) - let f_sub {Domain.LocalAccessPath.access_path= (var, _), _} = - match Var.get_footprint_index var with - | Some footprint_index -> ( - match List.nth actuals footprint_index with - | Some (HilExp.AccessExpression actual_access_expr) -> - Some - (Domain.LocalAccessPath.make - (HilExp.AccessExpression.to_access_path actual_access_expr) - caller_pname) - | _ -> - None ) - | None -> - if Var.is_return var then - Some (Domain.LocalAccessPath.make (ret_id_typ, []) caller_pname) - else None - in - Domain.substitute ~f_sub summary |> Domain.join astate - | None -> - astate + let apply_callee_summary summary_opt caller_pname ret_id_typ actuals ((_, new_domain) as astate) = + let old_domain', _ = + match summary_opt with + | Some summary -> + (* TODO: append paths if the footprint access path is an actual path instead of a var *) + let f_sub {Domain.LocalAccessPath.access_path= (var, _), _} = + match Var.get_footprint_index var with + | Some footprint_index -> ( + match List.nth actuals footprint_index with + | Some (HilExp.AccessExpression actual_access_expr) -> + Some + (Domain.LocalAccessPath.make + (HilExp.AccessExpression.to_access_path actual_access_expr) + caller_pname) + | _ -> + None ) + | None -> + if Var.is_return var then + Some (Domain.LocalAccessPath.make (ret_id_typ, []) caller_pname) + else None + in + Domain.substitute ~f_sub summary |> Domain.join astate + | None -> + astate + in + (old_domain', new_domain) let exec_instr astate ProcData.{summary; tenv} _ (instr : HilInstr.t) : Domain.t = diff --git a/infer/tests/codetoanalyze/java/litho/RequiredProps.java b/infer/tests/codetoanalyze/java/litho/RequiredProps.java index 588db60dc..e59ce2b07 100644 --- a/infer/tests/codetoanalyze/java/litho/RequiredProps.java +++ b/infer/tests/codetoanalyze/java/litho/RequiredProps.java @@ -182,6 +182,18 @@ public class RequiredProps { builder.build(); } + public boolean isEmptyOrNull(String str) { + return str == null || str.isEmpty(); + } + + public void buildInterProcUnrelatedBad(boolean b, String s) { + MyComponent.Builder builder = mMyComponent.create().prop1(new Object()); + if (!isEmptyOrNull(s)) { + builder.prop3(new Object()); + } + builder.build(); + } + // don't want to report here; want to report at clients that don't pass prop1 private MyComponent buildSuffix(MyComponent.Builder builder) { return builder.prop2(new Object()).prop3(new Object()).build(); diff --git a/infer/tests/codetoanalyze/java/litho/issues.exp b/infer/tests/codetoanalyze/java/litho/issues.exp index 752a3e9eb..6d6afa906 100644 --- a/infer/tests/codetoanalyze/java/litho/issues.exp +++ b/infer/tests/codetoanalyze/java/litho/issues.exp @@ -1,3 +1,4 @@ +codetoanalyze/java/litho/RequiredProps.java, codetoanalyze.java.litho.RequiredProps.buildInterProcUnrelatedBad(boolean,java.lang.String):void, 0, MISSING_REQUIRED_PROP, no_bucket, ERROR, [@Prop prop3 is required for component codetoanalyze.java.litho.MyComponent, but is not set before the call to build(),calls MyComponent$Builder MyComponent.create(),calls MyComponent$Builder MyComponent$Builder.prop1(Object),calls MyComponent MyComponent$Builder.build()] codetoanalyze/java/litho/RequiredProps.java, codetoanalyze.java.litho.RequiredProps.buildPropInConditionalOk_FP(boolean):void, 0, MISSING_REQUIRED_PROP, no_bucket, ERROR, [@Prop prop3 is required for component codetoanalyze.java.litho.MyComponent, but is not set before the call to build(),calls MyComponent$Builder MyComponent.create(),calls MyComponent MyComponent$Builder.build()] codetoanalyze/java/litho/RequiredProps.java, codetoanalyze.java.litho.RequiredProps.buildPropInConditionalOk_FP(boolean):void, 0, MISSING_REQUIRED_PROP, no_bucket, ERROR, [@Prop prop1 is required for component codetoanalyze.java.litho.MyComponent, but is not set before the call to build(),calls MyComponent$Builder MyComponent.create(),calls MyComponent MyComponent$Builder.build()] codetoanalyze/java/litho/RequiredProps.java, codetoanalyze.java.litho.RequiredProps.buildPropLithoMissingBothBad():com.facebook.litho.Component, 0, MISSING_REQUIRED_PROP, no_bucket, ERROR, [@Prop prop2 is required for component com.facebook.litho.MyLithoComponent, but is not set before the call to build(),calls MyLithoComponent$Builder MyLithoComponent.create(),calls MyLithoComponent MyLithoComponent$Builder.build()]