MergeInnerDifferences (@NotNull List<? extends CharSequence> chunks, @NotNull ComparisonPolicy comparisonPolicy, @NotNull ProgressIndicator indicator) { if (chunks.get(0) == null && chunks.get(1) == null && chunks.get(2) == null) return null; // --- if (comparisonPolicy == ComparisonPolicy.IGNORE_WHITESPACES) { if (isChunksEquals(chunks.get(0), chunks.get(1), comparisonPolicy) && isChunksEquals(chunks.get(0), chunks.get(2), comparisonPolicy)) { // whitespace-only changes, ex: empty lines added/removed return new MergeInnerDifferences(Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); } } if (chunks.get(0) == null && chunks.get(1) == null || chunks.get(0) == null && chunks.get(2) == null || chunks.get(1) == null && chunks.get(2) == null) { // =--, -=-, --= return null; } if (chunks.get(0) != null && chunks.get(1) != null && chunks.get(2) != null) { // === List<DiffFragment> fragments1 = ByWord.compare(chunks.get(1), chunks.get(0), comparisonPolicy, indicator); List<DiffFragment> fragments2 = ByWord.compare(chunks.get(1), chunks.get(2), comparisonPolicy, indicator); List<TextRange> left = new ArrayList<>(); List<TextRange> base = new ArrayList<>(); List<TextRange> right = new ArrayList<>(); for (DiffFragment wordFragment : fragments1) { base.add(new TextRange(wordFragment.getStartOffset1(), wordFragment.getEndOffset1())); left.add(new TextRange(wordFragment.getStartOffset2(), wordFragment.getEndOffset2())); } for (DiffFragment wordFragment : fragments2) { base.add(new TextRange(wordFragment.getStartOffset1(), wordFragment.getEndOffset1())); right.add(new TextRange(wordFragment.getStartOffset2(), wordFragment.getEndOffset2())); } return new MergeInnerDifferences(left, base, right); } // ==-, =-=, -== final ThreeSide side1 = chunks.get(0) != null ? ThreeSide.LEFT : ThreeSide.BASE; final ThreeSide side2 = chunks.get(2) != null ? ThreeSide.RIGHT : ThreeSide.BASE; CharSequence chunk1 = side1.select(chunks); CharSequence chunk2 = side2.select(chunks); List<DiffFragment> wordConflicts = ByWord.compare(chunk1, chunk2, comparisonPolicy, indicator); List<List<TextRange>> textRanges = ThreeSide.map(side -> { if (side == side1) { return ContainerUtil.map(wordConflicts, fragment -> new TextRange(fragment.getStartOffset1(), fragment.getEndOffset1())); } if (side == side2) { return ContainerUtil.map(wordConflicts, fragment -> new TextRange(fragment.getStartOffset2(), fragment.getEndOffset2())); } return null; }); return new MergeInnerDifferences(textRanges.get(0), textRanges.get(1), textRanges.get(2)); }