/* * Copyright (c) 2016 - present Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package codetoanalyze.java.checkers; import com.facebook.infer.annotation.ThreadSafe; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; public class Builders { static class Obj { final String f; String g; public Obj(String f, String g) { this.f = f; this.g = g; } public static class Builder { String f; String g; public Builder setFromObj(Obj input) { this.f = input.f; this.g = input.g; return this; } public Obj build() { return new Obj(f, g); } public Builder setF(String f) { this.f = f; return this; } public Builder setG(String g) { this.g = g; return this; } } } @ThreadSafe public void guavaBuilderOk() { ImmutableList.Builder builder = new ImmutableList.Builder(); builder.add("foo"); builder.build(); } @ThreadSafe public Obj customBuilderOk1() { Obj.Builder builder = new Obj.Builder(); builder.setF("f"); builder.setG("g"); return builder.build(); } @ThreadSafe public Obj customBuilderOk2() { Obj.Builder builder = new Obj.Builder(); return builder.setF("f").setG("g").build(); } @ThreadSafe public Obj customBuilderOk3() { Obj obj = new Obj("a", "b"); Obj.Builder builder = new Obj.Builder(); return builder.setFromObj(obj).build(); } @ThreadSafe public Obj mutateBad(Obj o) { o.g = ""; return o; } @ThreadSafe public Obj buildThenMutateBad(Obj input) { Obj.Builder builder = new Obj.Builder(); Obj output = builder.setFromObj(input).build(); input.g = ""; return output; } } @ThreadSafe class TopLevelBuilder { public String g; public void setG(String g) { this.g = g; // still want to warn if the builder is annotated ThreadSafe } } class MyBuilder { Obj mObj; public static MyBuilder create() { return new MyBuilder(); } public MyBuilder setNestedPath(int i) { this.mObj.f = i; return this; } @ThreadSafe static void setNestedPathOk(int i) { MyBuilder.create().setNestedPath(1); } }