@Test
  public void fieldsWithIsDepEqualsFalseHintAreNotTreatedAsDeps()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      @Hint(isDep = false)
      public Optional<Set<BuildTarget>> deps;
    }

    final String dep = "//should/be:ignored";

    Dto dto = new Dto();
    Map<String, Object> args = Maps.newHashMap();
    args.put("deps", ImmutableList.of(dep));

    ImmutableSet.Builder<BuildTarget> declaredDeps = ImmutableSet.builder();

    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        declaredDeps,
        ImmutableSet.<BuildTargetPattern>builder(),
        args);

    assertEquals(ImmutableSet.of(), declaredDeps.build());
  }
  @Test
  public void shouldPopulateSourcePaths()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public SourcePath filePath;
      public SourcePath targetPath;
    }

    ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
    BuildTarget target = BuildTargetFactory.newInstance("//example/path:peas");
    FakeBuildRule rule = new FakeBuildRule(target, new SourcePathResolver(new BuildRuleResolver()));
    ruleResolver.addToIndex(rule);
    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of(
            "filePath", "cheese.txt",
            "targetPath", ":peas"));

    assertEquals(
        new PathSourcePath(projectFilesystem, Paths.get("example/path/cheese.txt")), dto.filePath);
    assertEquals(new BuildTargetSourcePath(rule.getBuildTarget()), dto.targetPath);
  }
  public void shouldSetBuildTargetParameters()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public BuildTarget single;
      public BuildTarget sameBuildFileTarget;
      public List<BuildTarget> targets;
    }
    Dto dto = new Dto();

    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of(
            "single", "//com/example:cheese",
            "sameBuildFileTarget", ":cake",
            "targets", ImmutableList.of(":cake", "//com/example:cheese")));

    BuildTarget cheese = BuildTargetFactory.newInstance("//com/example:cheese");
    BuildTarget cake = BuildTargetFactory.newInstance("//example/path:cake");

    assertEquals(cheese, dto.single);
    assertEquals(cake, dto.sameBuildFileTarget);
    assertEquals(ImmutableList.of(cake, cheese), dto.targets);
  }
  @Test
  public void upperBoundGenericTypesCauseValuesToBeSetToTheUpperBound()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      public List<? extends SourcePath> yup;
    }

    ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
    SourcePathResolver pathResolver = new SourcePathResolver(new BuildRuleResolver());
    BuildRule rule =
        new FakeBuildRule(BuildTargetFactory.newInstance("//will:happen"), pathResolver);
    ruleResolver.addToIndex(rule);
    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of(
            "yup", ImmutableList.of(rule.getBuildTarget().getFullyQualifiedName())));

    BuildTargetSourcePath path = new BuildTargetSourcePath(rule.getBuildTarget());
    assertEquals(ImmutableList.of(path), dto.yup);
  }
  @Test
  public void onlyFieldNamedDepsAreConsideredDeclaredDeps()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      public Optional<Set<BuildTarget>> deps;
      public Optional<Set<BuildTarget>> notdeps;
    }

    final String dep = "//is/a/declared:dep";
    final String notDep = "//is/not/a/declared:dep";

    BuildTarget declaredDep = BuildTargetFactory.newInstance(dep);

    Dto dto = new Dto();
    Map<String, Object> args = Maps.newHashMap();
    args.put("deps", ImmutableList.of(dep));
    args.put("notdeps", ImmutableList.of(notDep));

    ImmutableSet.Builder<BuildTarget> declaredDeps = ImmutableSet.builder();

    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        declaredDeps,
        ImmutableSet.<BuildTargetPattern>builder(),
        args);

    assertEquals(ImmutableSet.of(declaredDep), declaredDeps.build());
  }
 @Test
 public void testImplicitDepsAreAddedCorrectly() throws NoSuchBuildTargetException {
   Description<GenruleDescription.Arg> genruleDescription = new GenruleDescription();
   Map<String, Object> instance =
       ImmutableMap.<String, Object>of(
           "srcs", ImmutableList.of(":baz", "//biz:baz"),
           "out", "AndroidManifest.xml",
           "cmd", "$(exe //bin:executable) $(location :arg)");
   ProjectFilesystem projectFilesystem = new AllExistingProjectFilesystem();
   BuildRuleFactoryParams params =
       new BuildRuleFactoryParams(projectFilesystem, BuildTargetFactory.newInstance("//foo:bar"));
   ConstructorArgMarshaller marshaller =
       new ConstructorArgMarshaller(
           new DefaultTypeCoercerFactory(ObjectMappers.newDefaultInstance()));
   ImmutableSet.Builder<BuildTarget> declaredDeps = ImmutableSet.builder();
   ImmutableSet.Builder<VisibilityPattern> visibilityPatterns = ImmutableSet.builder();
   GenruleDescription.Arg constructorArg = genruleDescription.createUnpopulatedConstructorArg();
   try {
     marshaller.populate(
         createCellRoots(projectFilesystem),
         projectFilesystem,
         params,
         constructorArg,
         declaredDeps,
         visibilityPatterns,
         instance);
   } catch (ConstructorArgMarshalException e) {
     fail("Expected constructorArg to be correctly populated.");
   }
   TargetNode<GenruleDescription.Arg> targetNode =
       new TargetNodeFactory(new DefaultTypeCoercerFactory(ObjectMappers.newDefaultInstance()))
           .create(
               Hashing.sha1().hashString(params.target.getFullyQualifiedName(), UTF_8),
               genruleDescription,
               constructorArg,
               params,
               declaredDeps.build(),
               visibilityPatterns.build(),
               createCellRoots(projectFilesystem));
   assertEquals(
       "SourcePaths and targets from cmd string should be extracted as extra deps.",
       ImmutableSet.of("//foo:baz", "//biz:baz", "//bin:executable", "//foo:arg"),
       FluentIterable.from(targetNode.getExtraDeps())
           .transform(Functions.toStringFunction())
           .toSet());
 }
 @Test
 public void testImplicitDepsAreAddedCorrectly()
     throws NoSuchBuildTargetException, TargetNode.InvalidSourcePathInputException {
   Description<GenruleDescription.Arg> genruleDescription = new GenruleDescription();
   Map<String, Object> instance =
       ImmutableMap.<String, Object>of(
           "srcs", ImmutableList.of(":baz", "//biz:baz"),
           "out", "AndroidManifest.xml",
           "cmd", "$(exe //bin:executable) $(location :arg)");
   ProjectFilesystem projectFilesystem = new AllExistingProjectFilesystem();
   BuildRuleFactoryParams params =
       new BuildRuleFactoryParams(
           projectFilesystem,
           BuildTargetFactory.newInstance("//foo:bar"),
           new InMemoryBuildFileTree(ImmutableList.<BuildTarget>of()),
           /* enforeBuckBoundaryCheck */ true);
   ConstructorArgMarshaller marshaller = new ConstructorArgMarshaller();
   ImmutableSet.Builder<BuildTarget> declaredDeps = ImmutableSet.builder();
   ImmutableSet.Builder<BuildTargetPattern> visibilityPatterns = ImmutableSet.builder();
   GenruleDescription.Arg constructorArg = genruleDescription.createUnpopulatedConstructorArg();
   try {
     marshaller.populate(
         projectFilesystem, params, constructorArg, declaredDeps, visibilityPatterns, instance);
   } catch (ConstructorArgMarshalException e) {
     fail("Expected constructorArg to be correctly populated.");
   }
   TargetNode<GenruleDescription.Arg> targetNode =
       new TargetNode<>(
           genruleDescription,
           constructorArg,
           params,
           declaredDeps.build(),
           visibilityPatterns.build());
   assertEquals(
       "SourcePaths and targets from cmd string should be extracted as extra deps.",
       ImmutableSet.of("//foo:baz", "//biz:baz", "//bin:executable", "//foo:arg"),
       FluentIterable.from(targetNode.getExtraDeps())
           .transform(Functions.toStringFunction())
           .toSet());
 }
  @Test(expected = RuntimeException.class)
  public void lowerBoundGenericTypesCauseAnException()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      public List<? super BuildTarget> nope;
    }

    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        new Dto(),
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("nope", ImmutableList.of("//will/not:happen")));
  }
  @Test(expected = ConstructorArgMarshalException.class)
  public void shouldBeAnErrorToAttemptToSetACollectionToASingleValue()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      public Set<String> strings;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("strings", "isn't going to happen"));
  }
  @Test(expected = ConstructorArgMarshalException.class)
  public void shouldBeAnErrorToSetTheWrongTypeOfValueInACollection()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      public Set<String> strings;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("strings", ImmutableSet.of(true, false)));
  }
  @Test
  public void shouldNotPopulateAnEmptyArg() throws NoSuchBuildTargetException {
    class Dto {}

    Dto dto = new Dto();
    try {
      marshaller.populate(
          createCellRoots(filesystem),
          filesystem,
          buildRuleFactoryParams(),
          dto,
          ImmutableSet.<BuildTarget>builder(),
          ImmutableSet.<BuildTargetPattern>builder(),
          ImmutableMap.<String, Object>of());
    } catch (RuntimeException | ConstructorArgMarshalException e) {
      fail("Did not expect an exception to be thrown:\n" + Throwables.getStackTraceAsString(e));
    }
  }
  @Test
  public void shouldPopulateAStringValue()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public String name;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("name", "cheese"));

    assertEquals("cheese", dto.name);
  }
  @Test
  public void shouldPopulateLists()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public List<String> list;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("list", ImmutableList.of("alpha", "beta")));

    assertEquals(ImmutableList.of("alpha", "beta"), dto.list);
  }
  @Test
  public void shouldPopulateABooleanValue()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public boolean value;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("value", true));

    assertTrue(dto.value);
  }
  @Test
  public void shouldPopulateANumericValue()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public long number;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("number", 42L));

    assertEquals(42, dto.number);
  }
  @Test
  /**
   * Since we populated the params from the python script, and the python script inserts default
   * values instead of nulls it's never possible for someone to see "Optional.absent()", but that's
   * what we want as authors of buildables. Handle that case.
   */
  public void shouldPopulateDefaultValuesAsBeingAbsent()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public Optional<String> noString;
      public Optional<String> defaultString;

      public Optional<SourcePath> noSourcePath;
      public Optional<SourcePath> defaultSourcePath;

      public int primitiveNum;
      public Integer wrapperObjectNum;
      public boolean primitiveBoolean;
      public Boolean wrapperObjectBoolean;
    }

    // This is not an ImmutableMap so we can test null values.
    Map<String, Object> args = Maps.newHashMap();
    args.put("defaultString", null);
    args.put("defaultSourcePath", null);
    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        args);

    assertEquals(Optional.<String>absent(), dto.noString);
    assertEquals(Optional.<String>absent(), dto.defaultString);
    assertEquals(Optional.<SourcePath>absent(), dto.noSourcePath);
    assertEquals(Optional.<SourcePath>absent(), dto.defaultSourcePath);
    assertEquals(0, dto.primitiveNum);
    assertEquals(Integer.valueOf(0), dto.wrapperObjectNum);
  }
  @Test
  public void specifyingZeroIsNotConsideredOptional()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public Optional<Integer> number;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("number", 0));

    assertTrue(dto.number.isPresent());
    assertEquals(Optional.of(0), dto.number);
  }
  @Test
  public void shouldPopulateAPathValue()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      @Hint(name = "some_path")
      public Path somePath;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("somePath", "Fish.java"));

    assertEquals(Paths.get("example/path", "Fish.java"), dto.somePath);
  }
  @Test
  public void shouldNormalizePaths()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      public Path path;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("path", "./bar/././fish.txt"));

    assertEquals(basePath.resolve("bar/fish.txt").normalize(), dto.path);
  }
  @Test
  public void shouldPopulateSets()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public Set<Path> paths;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("paths", ImmutableList.of("one", "two")));

    assertEquals(
        ImmutableSet.of(Paths.get("example/path/one"), Paths.get("example/path/two")), dto.paths);
  }
  @Test
  public void shouldResolveCollectionOfSourcePaths()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public ImmutableSortedSet<SourcePath> srcs;
    }

    BuildRuleResolver resolver = new BuildRuleResolver();
    BuildTarget target = BuildTargetFactory.newInstance("//example/path:manifest");
    BuildRule rule = new FakeBuildRule(target, new SourcePathResolver(resolver));
    resolver.addToIndex(rule);

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of(
            "srcs", ImmutableList.of("main.py", "lib/__init__.py", "lib/manifest.py")));

    ImmutableSet<String> observedValues =
        FluentIterable.from(dto.srcs)
            .transform(
                new Function<SourcePath, String>() {
                  @Nullable
                  @Override
                  public String apply(SourcePath input) {
                    return ((PathSourcePath) input).getRelativePath().toString();
                  }
                })
            .toSet();
    assertEquals(
        ImmutableSet.of(
            Paths.get("example/path/main.py").toString(),
            Paths.get("example/path/lib/__init__.py").toString(),
            Paths.get("example/path/lib/manifest.py").toString()),
        observedValues);
  }
  @Test
  public void shouldPopulateAnImmutableSortedSet()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public ImmutableSortedSet<BuildTarget> deps;
    }

    BuildTarget t1 = BuildTargetFactory.newInstance("//please/go:here");
    BuildTarget t2 = BuildTargetFactory.newInstance("//example/path:there");

    Dto dto = new Dto();
    // Note: the ordering is reversed from the natural ordering
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of("deps", ImmutableList.of("//please/go:here", ":there")));

    assertEquals(ImmutableSortedSet.of(t2, t1), dto.deps);
  }
  @Test
  public void optionalCollectionsWithoutAValueWillBeSetToAnEmptyOptionalCollection()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      public Optional<Set<String>> strings;
    }

    Dto dto = new Dto();
    Map<String, Object> args = Maps.newHashMap();
    // Deliberately not populating args

    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        args);

    assertEquals(Optional.of((Set<String>) Sets.<String>newHashSet()), dto.strings);
  }
  @Test
  public void collectionsCanBeOptionalAndWillBeSetToAnOptionalEmptyCollectionIfMissing()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      public Optional<Set<BuildTarget>> targets;
    }

    Dto dto = new Dto();
    Map<String, Object> args = Maps.newHashMap();
    args.put("targets", Lists.newArrayList());

    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        args);

    assertEquals(Optional.of((Set<BuildTarget>) Sets.<BuildTarget>newHashSet()), dto.targets);
  }
  @Test
  public void shouldPopulateBuildTargetValues()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {
    class Dto {
      public BuildTarget target;
      public BuildTarget local;
    }

    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        ImmutableMap.<String, Object>of(
            "target", "//cake:walk",
            "local", ":fish"));

    assertEquals(BuildTargetFactory.newInstance(filesystem, "//cake:walk"), dto.target);
    assertEquals(BuildTargetFactory.newInstance(filesystem, "//example/path:fish"), dto.local);
  }
  @SuppressWarnings({"rawtypes", "unchecked"})
  private TargetNode<?> createTargetNode(
      BuckEventBus eventBus,
      Cell cell,
      Path buildFile,
      BuildTarget target,
      Map<String, Object> rawNode,
      TargetNodeListener nodeListener) {
    BuildRuleType buildRuleType = parseBuildRuleTypeFromRawRule(cell, rawNode);

    // Because of the way that the parser works, we know this can never return null.
    Description<?> description = cell.getDescription(buildRuleType);

    if (target.isFlavored()) {
      if (description instanceof Flavored) {
        if (!((Flavored) description).hasFlavors(ImmutableSet.copyOf(target.getFlavors()))) {
          throw new HumanReadableException(
              "Unrecognized flavor in target %s while parsing %s%s.",
              target,
              UnflavoredBuildTarget.BUILD_TARGET_PREFIX,
              MorePaths.pathWithUnixSeparators(
                  target.getBasePath().resolve(cell.getBuildFileName())));
        }
      } else {
        LOG.warn(
            "Target %s (type %s) must implement the Flavored interface "
                + "before we can check if it supports flavors: %s",
            target.getUnflavoredBuildTarget(), buildRuleType, target.getFlavors());
        throw new HumanReadableException(
            "Target %s (type %s) does not currently support flavors (tried %s)",
            target.getUnflavoredBuildTarget(), buildRuleType, target.getFlavors());
      }
    }

    Cell targetCell = cell.getCell(target);
    BuildRuleFactoryParams factoryParams =
        new BuildRuleFactoryParams(
            targetCell.getFilesystem(),
            target.withoutCell(),
            new FilesystemBackedBuildFileTree(cell.getFilesystem(), cell.getBuildFileName()),
            targetCell.isEnforcingBuckPackageBoundaries());
    Object constructorArg = description.createUnpopulatedConstructorArg();
    try {
      ImmutableSet.Builder<BuildTarget> declaredDeps = ImmutableSet.builder();
      ImmutableSet.Builder<BuildTargetPattern> visibilityPatterns = ImmutableSet.builder();
      try (SimplePerfEvent.Scope scope =
          SimplePerfEvent.scope(
              eventBus, PerfEventId.of("MarshalledConstructorArg"), "target", target)) {
        marshaller.populate(
            targetCell.getCellRoots(),
            targetCell.getFilesystem(),
            factoryParams,
            constructorArg,
            declaredDeps,
            visibilityPatterns,
            rawNode);
      }
      try (SimplePerfEvent.Scope scope =
          SimplePerfEvent.scope(eventBus, PerfEventId.of("CreatedTargetNode"), "target", target)) {
        Hasher hasher = Hashing.sha1().newHasher();
        hasher.putString(BuckVersion.getVersion(), UTF_8);
        JsonObjectHashing.hashJsonObject(hasher, rawNode);
        synchronized (this) {
          targetsCornucopia.put(target.getUnflavoredBuildTarget(), target);
        }
        TargetNode<?> node =
            new TargetNode(
                hasher.hash(),
                description,
                constructorArg,
                typeCoercerFactory,
                factoryParams,
                declaredDeps.build(),
                visibilityPatterns.build(),
                targetCell.getCellRoots());
        nodeListener.onCreate(buildFile, node);
        return node;
      }
    } catch (NoSuchBuildTargetException | TargetNode.InvalidSourcePathInputException e) {
      throw new HumanReadableException(e);
    } catch (ConstructorArgMarshalException e) {
      throw new HumanReadableException("%s: %s", target, e.getMessage());
    } catch (IOException e) {
      throw new HumanReadableException(e.getMessage(), e);
    }
  }
  @Test
  public void canPopulateSimpleConstructorArgFromBuildFactoryParams()
      throws ConstructorArgMarshalException, NoSuchBuildTargetException {

    class Dto {
      public String required;
      public Optional<String> notRequired;

      public int num;
      // Turns out there no optional number params
      // public Optional<Long> optionalLong;

      public boolean needed;
      public Optional<Boolean> notNeeded;

      public SourcePath aSrcPath;
      public Optional<SourcePath> notASrcPath;

      public Path aPath;
      public Optional<Path> notAPath;
    }

    ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
    FakeBuildRule expectedRule =
        new FakeBuildRule(
            BuildTargetFactory.newInstance("//example/path:path"),
            new SourcePathResolver(new BuildRuleResolver()));
    ruleResolver.addToIndex(expectedRule);

    ImmutableMap<String, Object> args =
        ImmutableMap.<String, Object>builder()
            .put("required", "cheese")
            .put("notRequired", "cake")
            // Long because that's what comes from python.
            .put("num", 42L)
            // Skipping optional Long.
            .put("needed", true)
            // Skipping optional boolean.
            .put("aSrcPath", ":path")
            .put("aPath", "./File.java")
            .put("notAPath", "./NotFile.java")
            .build();
    Dto dto = new Dto();
    marshaller.populate(
        createCellRoots(filesystem),
        filesystem,
        buildRuleFactoryParams(),
        dto,
        ImmutableSet.<BuildTarget>builder(),
        ImmutableSet.<BuildTargetPattern>builder(),
        args);

    assertEquals("cheese", dto.required);
    assertEquals("cake", dto.notRequired.get());
    assertEquals(42, dto.num);
    assertTrue(dto.needed);
    assertEquals(Optional.<Boolean>absent(), dto.notNeeded);
    BuildTargetSourcePath expected = new BuildTargetSourcePath(expectedRule.getBuildTarget());
    assertEquals(expected, dto.aSrcPath);
    assertEquals(Paths.get("example/path/NotFile.java"), dto.notAPath.get());
  }