@Override
  public synchronized void blameResult(InputFile file, List<BlameLine> lines) {
    checkNotNull(file);
    checkNotNull(lines);
    checkArgument(allFilesToBlame.contains(file), "It was not expected to blame file %s", file);

    if (lines.size() != file.lines()) {
      LOG.debug("Ignoring blame result since provider returned {} blame lines but file {} has {} lines", lines.size(), file, file.lines());
      return;
    }

    Builder scmBuilder = ScannerReport.Changesets.newBuilder();
    DefaultInputFile inputFile = (DefaultInputFile) file;
    scmBuilder.setComponentRef(inputFile.scannerId());
    Map<String, Integer> changesetsIdByRevision = new HashMap<>();

    int lineId = 1;
    for (BlameLine line : lines) {
      validateLine(line, lineId, file);
      Integer changesetId = changesetsIdByRevision.get(line.revision());
      if (changesetId == null) {
        addChangeset(scmBuilder, line);
        changesetId = scmBuilder.getChangesetCount() - 1;
        changesetsIdByRevision.put(line.revision(), changesetId);
      }
      scmBuilder.addChangesetIndexByLine(changesetId);
      lineId++;
    }
    writer.writeComponentChangesets(scmBuilder.build());
    allFilesToBlame.remove(file);
    count++;
    progressReport.message(count + "/" + total + " " + pluralize(count) + " have been analyzed");
  }
@Test
  public void shouldFailIfNullDate() {
    InputFile file = new TestInputFileBuilder("foo", "src/main/java/Foo.java").setLines(1).build();
    var blameOutput = new DefaultBlameOutput(null, analysisWarnings, singletonList(file), mock(DocumentationLinkGenerator.class));
    var lines = singletonList(new BlameLine().revision("1").author("guy"));

    assertThatThrownBy(() -> blameOutput.blameResult(file, lines))
      .isInstanceOf(IllegalArgumentException.class)
      .hasMessage("Blame date is null for file " + file + " at line 1");
  }