From 99511e32c5d51abecad9b09e3a3566fd6b656c34 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 22 Nov 2016 15:19:57 +0300 Subject: [PATCH] vcs: EA-88856 - assert: Block.createPreviousBlock * reuse existing logic, that allows to update line range on document modification * changed ranges do not intersect, so we can just "apply" changes one-by-one --- .../diff/SelectedBlockHistoryTest.java | 156 +++++++++++++++++- .../vcs-impl/src/com/intellij/diff/Block.java | 35 ++-- 2 files changed, 173 insertions(+), 18 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/diff/SelectedBlockHistoryTest.java b/platform/platform-tests/testSrc/com/intellij/diff/SelectedBlockHistoryTest.java index e70b69e8560a..35f25627c170 100644 --- a/platform/platform-tests/testSrc/com/intellij/diff/SelectedBlockHistoryTest.java +++ b/platform/platform-tests/testSrc/com/intellij/diff/SelectedBlockHistoryTest.java @@ -182,7 +182,17 @@ public class SelectedBlockHistoryTest extends TestCase { ); } - public void test15() throws FilesTooBigForDiffException { + public void testGreediness() throws FilesTooBigForDiffException { + doTest( + new String[]{}, + new String[]{"x", "y", "z"}, + new String[]{}, + + new String[]{"1"}, + new String[]{"2", "3"}, + new String[]{"4"} + ); + doTest( new String[]{"1"}, new String[]{"0"}, @@ -192,6 +202,150 @@ public class SelectedBlockHistoryTest extends TestCase { new String[]{"5", "0"}, new String[]{"3"} ); + + doTest( + new String[]{"1", "2"}, + new String[]{"3", "5", "X", "Z", "7"}, + new String[]{"8", "9"}, + + new String[]{"1", "2"}, + new String[]{"3", "4", "5", "6", "7"}, + new String[]{"8", "9"} + ); + + doTest( + new String[]{"1"}, + new String[]{"5", "X", "Z"}, + new String[]{"9"}, + + new String[]{"1", "2"}, + new String[]{"3", "4", "5", "6", "7"}, + new String[]{"8", "9"} + ); + + doTest( + new String[]{"1"}, + new String[]{"5", "X", "7"}, + new String[]{"Z", "9"}, + + new String[]{"1", "2"}, + new String[]{"3", "4", "5", "6", "7"}, + new String[]{"8", "9"} + ); + } + + public void testEmptyPreviousText() throws FilesTooBigForDiffException { + doTest( + new String[]{}, + new String[]{}, + new String[]{}, + + new String[]{}, + new String[]{}, + new String[]{} + ); + + doTest( + new String[]{}, + new String[]{}, + new String[]{}, + + new String[]{}, + new String[]{}, + new String[]{"x"} + ); + + doTest( + new String[]{}, + new String[]{}, + new String[]{}, + + new String[]{"x"}, + new String[]{}, + new String[]{} + ); + + doTest( + new String[]{}, + new String[]{}, + new String[]{}, + + new String[]{}, + new String[]{"x"}, + new String[]{} + ); + + doTest( + new String[]{}, + new String[]{}, + new String[]{}, + + new String[]{"z"}, + new String[]{"x"}, + new String[]{"y"} + ); + } + + public void testEmptyCurrentRange() throws FilesTooBigForDiffException { + doTest( + new String[]{}, + new String[]{}, + new String[]{"x"}, + + new String[]{}, + new String[]{}, + new String[]{} + ); + + doTest( + new String[]{}, + new String[]{}, + new String[]{"x", "y", "z"}, + + new String[]{}, + new String[]{}, + new String[]{} + ); + + doTest( + new String[]{}, + new String[]{}, + new String[]{"x"}, + + new String[]{}, + new String[]{}, + new String[]{"z"} + ); + + doTest( + new String[]{}, + new String[]{}, + new String[]{"x"}, + + new String[]{}, + new String[]{}, + new String[]{"y", "z"} + ); + + doTest( + new String[]{"x"}, + new String[]{}, + new String[]{}, + + new String[]{"y"}, + new String[]{}, + new String[]{"z"} + ); + + doTest( + new String[]{"y"}, + new String[]{}, + new String[]{"w", "z"}, + + new String[]{"y"}, + new String[]{}, + new String[]{"z"} + ); } public void testContent(){ diff --git a/platform/vcs-impl/src/com/intellij/diff/Block.java b/platform/vcs-impl/src/com/intellij/diff/Block.java index 7b65a317d7a8..588128639d64 100644 --- a/platform/vcs-impl/src/com/intellij/diff/Block.java +++ b/platform/vcs-impl/src/com/intellij/diff/Block.java @@ -19,6 +19,7 @@ import com.intellij.diff.comparison.ByLine; import com.intellij.diff.comparison.ComparisonPolicy; import com.intellij.diff.comparison.DiffTooBigException; import com.intellij.diff.comparison.iterables.FairDiffIterable; +import com.intellij.diff.util.DiffUtil; import com.intellij.diff.util.Range; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.DumbProgressIndicator; @@ -61,29 +62,29 @@ public class Block { @NotNull public Block createPreviousBlock(@NotNull String[] prevContent) { - int start = -1; - int end = -1; - int shift = 0; - try { FairDiffIterable iterable = ByLine.compare(Arrays.asList(prevContent), Arrays.asList(mySource), ComparisonPolicy.IGNORE_WHITESPACES, DumbProgressIndicator.INSTANCE); - for (Range range : iterable.iterateChanges()) { - if (Math.max(myStart, range.start2) < Math.min(myEnd, range.end2)) { - // ranges intersect - if (range.start2 <= myStart) start = range.start1; - if (range.end2 > myEnd) end = range.end1; - } - if (range.start2 > myStart) { - if (start == -1) start = myStart - shift; - if (end == -1 && range.start2 >= myEnd) end = myEnd - shift; - } + // empty range should not be transferred to the non-empty range + boolean greedy = myStart != myEnd; - shift += (range.end2 - range.start2) - (range.end1 - range.start1); + int start = myStart; + int end = myEnd; + int shift = 0; + + for (Range range : iterable.iterateChanges()) { + int changeStart = range.start2 + shift; + int changeEnd = range.end2 + shift; + int changeShift = (range.end1 - range.start1) - (range.end2 - range.start2); + + DiffUtil.UpdatedLineRange updatedRange = + DiffUtil.updateRangeOnModification(start, end, changeStart, changeEnd, changeShift, greedy); + + start = updatedRange.startLine; + end = updatedRange.endLine; + shift += changeShift; } - if (start == -1) start = myStart - shift; - if (end == -1) end = myEnd - shift; if (start < 0 || end > prevContent.length || end < start) { LOG.error("Invalid block range: [" + start + ", " + end + "); length - " + prevContent.length);