From 805e3f17fc159f62eb738dcdfb191a0f10f05559 Mon Sep 17 00:00:00 2001 From: Sungkeun Cho Date: Wed, 18 Dec 2019 08:30:46 -0800 Subject: [PATCH] [litho] Do not remove non-build-called part at build calls Summary: In the previous code, it removed non-build-called method calls. For example, it was like ``` {non-build-called: {prop1, prop3}} {build-called: {}} b.build(); {non-build-called: {}} {build-called: {prop1, prop3}} ``` However, this behavior introduced a false positive when there is multiple builders that point to the same abstract object and `build` is called one by one. This diff changes the semantics to keep the method calls of non-build-called at `build` calls. Reviewed By: ezgicicek Differential Revision: D19144525 fbshipit-source-id: e2ace127f --- infer/src/checkers/LithoDomain.ml | 2 +- .../litho-required-props/RequiredProps.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/infer/src/checkers/LithoDomain.ml b/infer/src/checkers/LithoDomain.ml index f6301b5f4..b14f4c50a 100644 --- a/infer/src/checkers/LithoDomain.ml +++ b/infer/src/checkers/LithoDomain.ml @@ -216,7 +216,7 @@ module MethodCalled = struct | Some method_calls_no_build_called, Some method_calls_build_called -> MethodCalls.join method_calls_no_build_called method_calls_build_called in - remove k_no_build_called x |> add k_build_called method_calls + add k_build_called method_calls x let build_method_called created_locations x = diff --git a/infer/tests/codetoanalyze/java/litho-required-props/RequiredProps.java b/infer/tests/codetoanalyze/java/litho-required-props/RequiredProps.java index a3d448d1f..2e19cce9c 100644 --- a/infer/tests/codetoanalyze/java/litho-required-props/RequiredProps.java +++ b/infer/tests/codetoanalyze/java/litho-required-props/RequiredProps.java @@ -488,4 +488,22 @@ public class RequiredProps { MyComponent.Builder builder2 = mMyComponent.create().prop1(new Object()); setProp3AndBuild(builder1); } + + public MyComponent.Builder createWrapper() { + return mMyComponent.create(); + } + + public void twoBuildersOk() { + MyComponent.Builder builder1 = createWrapper(); + MyComponent.Builder builder2 = createWrapper().prop1(new Object()); + builder1.prop1(new Object()).prop3(new Object()).build(); + builder2.prop3(new Object()).build(); + } + + public void twoBuildersBad_FN() { + MyComponent.Builder builder1 = createWrapper(); + MyComponent.Builder builder2 = createWrapper(); + builder1.prop1(new Object()).prop3(new Object()).build(); + builder2.prop3(new Object()).build(); + } }