@NotNull
  static List<MergeRange> doCompare(@NotNull List<? extends Line> lines1,
                                    @NotNull List<? extends Line> lines2,
                                    @NotNull List<? extends Line> lines3,
                                    @NotNull ComparisonPolicy policy,
                                    @NotNull CancellationChecker indicator,
                                    boolean keepIgnoredChanges) {
    indicator.checkCanceled();

    List<Line> iwLines1 = convertMode(lines1, IGNORE_WHITESPACES);
    List<Line> iwLines2 = convertMode(lines2, IGNORE_WHITESPACES);
    List<Line> iwLines3 = convertMode(lines3, IGNORE_WHITESPACES);

    FairDiffIterable iwChanges1 = compareSmart(iwLines2, iwLines1, indicator);
    iwChanges1 = optimizeLineChunks(lines2, lines1, iwChanges1, indicator);
    FairDiffIterable iterable1 = correctChangesSecondStep(lines2, lines1, iwChanges1);

    FairDiffIterable iwChanges2 = compareSmart(iwLines2, iwLines3, indicator);
    iwChanges2 = optimizeLineChunks(lines2, lines3, iwChanges2, indicator);
    FairDiffIterable iterable2 = correctChangesSecondStep(lines2, lines3, iwChanges2);

    if (keepIgnoredChanges && policy != DEFAULT) {
      return ComparisonMergeUtil.buildMerge(iterable1, iterable2,
                                            (index1, index2, index3) -> equalsDefaultPolicy(lines1, lines2, lines3, index1, index2, index3),
                                            indicator);
    }
    else {
      return ComparisonMergeUtil.buildSimple(iterable1, iterable2, indicator);
    }
  }
@NotNull
  static List<MergeRange> doCompare(@NotNull List<? extends Line> lines1,
                                    @NotNull List<? extends Line> lines2,
                                    @NotNull List<? extends Line> lines3,
                                    @NotNull ComparisonPolicy policy,
                                    @NotNull CancellationChecker indicator,
                                    boolean keepIgnoredChanges)