diff --git a/src/vs/editor/common/diff/defaultLinesDiffComputer/heuristicSequenceOptimizations.ts b/src/vs/editor/common/diff/defaultLinesDiffComputer/heuristicSequenceOptimizations.ts index 64b3b75d317..da23e59f332 100644 --- a/src/vs/editor/common/diff/defaultLinesDiffComputer/heuristicSequenceOptimizations.ts +++ b/src/vs/editor/common/diff/defaultLinesDiffComputer/heuristicSequenceOptimizations.ts @@ -12,6 +12,9 @@ import { LinesSliceCharSequence } from 'vs/editor/common/diff/defaultLinesDiffCo export function optimizeSequenceDiffs(sequence1: ISequence, sequence2: ISequence, sequenceDiffs: SequenceDiff[]): SequenceDiff[] { let result = sequenceDiffs; result = joinSequenceDiffsByShifting(sequence1, sequence2, result); + // Sometimes, calling this function twice improves the result. + // Uncomment the second invocation and run the tests to see the difference. + result = joinSequenceDiffsByShifting(sequence1, sequence2, result); result = shiftSequenceDiffs(sequence1, sequence2, result); return result; } diff --git a/src/vs/editor/test/node/diffing/fixtures.test.ts b/src/vs/editor/test/node/diffing/fixtures.test.ts index 01cd621546a..e200d808c22 100644 --- a/src/vs/editor/test/node/diffing/fixtures.test.ts +++ b/src/vs/editor/test/node/diffing/fixtures.test.ts @@ -120,7 +120,7 @@ suite('diffing fixtures', () => { } test(`test`, () => { - runTest('false-positive-move', 'advanced'); + runTest('shifting-twice', 'advanced'); }); for (const folder of folders) { diff --git a/src/vs/editor/test/node/diffing/fixtures/noise-1/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/noise-1/advanced.expected.diff.json index 36bbcbebac9..06849d3af26 100644 --- a/src/vs/editor/test/node/diffing/fixtures/noise-1/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/noise-1/advanced.expected.diff.json @@ -14,11 +14,7 @@ "innerChanges": [ { "originalRange": "[52,7 -> 52,20]", - "modifiedRange": "[52,7 -> 53,2]" - }, - { - "originalRange": "[52,24 -> 52,24]", - "modifiedRange": "[53,6 -> 53,45]" + "modifiedRange": "[52,7 -> 53,41]" }, { "originalRange": "[52,77 -> 56,1 EOL]", diff --git a/src/vs/editor/test/node/diffing/fixtures/noise-2/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/noise-2/advanced.expected.diff.json index a30c65cb9ee..eb4153d4d82 100644 --- a/src/vs/editor/test/node/diffing/fixtures/noise-2/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/noise-2/advanced.expected.diff.json @@ -17,8 +17,8 @@ "modifiedRange": "[50,1 -> 51,1]" }, { - "originalRange": "[50,19 -> 50,27]", - "modifiedRange": "[51,19 -> 68,24]" + "originalRange": "[50,19 -> 50,21]", + "modifiedRange": "[51,19 -> 68,18]" }, { "originalRange": "[51,1 -> 51,1]", diff --git a/src/vs/editor/test/node/diffing/fixtures/noisy-move1/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/noisy-move1/advanced.expected.diff.json index 11efbc5230f..6fd1598ffe3 100644 --- a/src/vs/editor/test/node/diffing/fixtures/noisy-move1/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/noisy-move1/advanced.expected.diff.json @@ -13,8 +13,8 @@ "modifiedRange": "[1,52)", "innerChanges": [ { - "originalRange": "[1,1 -> 2,50]", - "modifiedRange": "[1,1 -> 50,28]" + "originalRange": "[1,1 -> 2,37]", + "modifiedRange": "[1,1 -> 50,15]" }, { "originalRange": "[2,82 -> 2,82]", @@ -59,12 +59,12 @@ ] }, { - "originalRange": "[42,45)", - "modifiedRange": "[91,176)", + "originalRange": "[42,44)", + "modifiedRange": "[91,175)", "innerChanges": [ { - "originalRange": "[42,9 -> 45,1 EOL]", - "modifiedRange": "[91,9 -> 176,1 EOL]" + "originalRange": "[42,9 -> 44,1]", + "modifiedRange": "[91,9 -> 175,1]" } ] }, diff --git a/src/vs/editor/test/node/diffing/fixtures/random-match-2/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/random-match-2/advanced.expected.diff.json index 337c2637132..65ce4a98835 100644 --- a/src/vs/editor/test/node/diffing/fixtures/random-match-2/advanced.expected.diff.json +++ b/src/vs/editor/test/node/diffing/fixtures/random-match-2/advanced.expected.diff.json @@ -13,8 +13,8 @@ "modifiedRange": "[2,4)", "innerChanges": [ { - "originalRange": "[2,8 -> 4,17]", - "modifiedRange": "[2,8 -> 2,16]" + "originalRange": "[2,1 -> 4,2]", + "modifiedRange": "[2,1 -> 2,1]" }, { "originalRange": "[4,46 -> 4,53]", diff --git a/src/vs/editor/test/node/diffing/fixtures/shifting-twice/1.txt b/src/vs/editor/test/node/diffing/fixtures/shifting-twice/1.txt new file mode 100644 index 00000000000..8150851150c --- /dev/null +++ b/src/vs/editor/test/node/diffing/fixtures/shifting-twice/1.txt @@ -0,0 +1,18 @@ + for (extendToBottom = 0; extendToBottom < linesBelow; extendToBottom++) { + const origLine = move.original.endLineNumberExclusive + extendToBottom; + const modLine = move.modified.endLineNumberExclusive + extendToBottom; + if (origLine > originalLines.length || modLine > modifiedLines.length) { + break; + } + if (modifiedSet.contains(modLine) || originalSet.contains(origLine)) { + break; + } + if (!areLinesSimilar(originalLines[origLine - 1], modifiedLines[modLine - 1], timeout)) { + break; + } + } + + if (extendToBottom > 0) { + originalSet.addRange(new LineRange(move.original.endLineNumberExclusive, move.original.endLineNumberExclusive + extendToBottom)); + modifiedSet.addRange(new LineRange(move.modified.endLineNumberExclusive, move.modified.endLineNumberExclusive + extendToBottom)); + } \ No newline at end of file diff --git a/src/vs/editor/test/node/diffing/fixtures/shifting-twice/2.txt b/src/vs/editor/test/node/diffing/fixtures/shifting-twice/2.txt new file mode 100644 index 00000000000..d8220433dfc --- /dev/null +++ b/src/vs/editor/test/node/diffing/fixtures/shifting-twice/2.txt @@ -0,0 +1,21 @@ + for (extendToBottom = 0; extendToBottom < linesBelow; extendToBottom++) { + const origLine = move.original.endLineNumberExclusive + extendToBottom; + const modLine = move.modified.endLineNumberExclusive + extendToBottom; + if (origLine > originalLines.length || modLine > modifiedLines.length) { + break; + } + if (modifiedSet.contains(modLine) || originalSet.contains(origLine)) { + break; + } + if (!areLinesSimilar(originalLines[origLine - 1], modifiedLines[modLine - 1], timeout)) { + break; + } + if (originalLines[origLine - 1].trim().length !== 0) { + extendToBottomWithoutEmptyLines = extendToBottom + 1; + } + } + + if (extendToBottomWithoutEmptyLines > 0) { + originalSet.addRange(new LineRange(move.original.endLineNumberExclusive, move.original.endLineNumberExclusive + extendToBottomWithoutEmptyLines)); + modifiedSet.addRange(new LineRange(move.modified.endLineNumberExclusive, move.modified.endLineNumberExclusive + extendToBottomWithoutEmptyLines)); + } \ No newline at end of file diff --git a/src/vs/editor/test/node/diffing/fixtures/shifting-twice/advanced.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/shifting-twice/advanced.expected.diff.json new file mode 100644 index 00000000000..dbdf35c25c7 --- /dev/null +++ b/src/vs/editor/test/node/diffing/fixtures/shifting-twice/advanced.expected.diff.json @@ -0,0 +1,40 @@ +{ + "original": { + "content": "\t\tfor (extendToBottom = 0; extendToBottom < linesBelow; extendToBottom++) {\n\t\t\tconst origLine = move.original.endLineNumberExclusive + extendToBottom;\n\t\t\tconst modLine = move.modified.endLineNumberExclusive + extendToBottom;\n\t\t\tif (origLine > originalLines.length || modLine > modifiedLines.length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (modifiedSet.contains(modLine) || originalSet.contains(origLine)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!areLinesSimilar(originalLines[origLine - 1], modifiedLines[modLine - 1], timeout)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (extendToBottom > 0) {\n\t\t\toriginalSet.addRange(new LineRange(move.original.endLineNumberExclusive, move.original.endLineNumberExclusive + extendToBottom));\n\t\t\tmodifiedSet.addRange(new LineRange(move.modified.endLineNumberExclusive, move.modified.endLineNumberExclusive + extendToBottom));\n\t\t}", + "fileName": "./1.txt" + }, + "modified": { + "content": "\t\tfor (extendToBottom = 0; extendToBottom < linesBelow; extendToBottom++) {\n\t\t\tconst origLine = move.original.endLineNumberExclusive + extendToBottom;\n\t\t\tconst modLine = move.modified.endLineNumberExclusive + extendToBottom;\n\t\t\tif (origLine > originalLines.length || modLine > modifiedLines.length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (modifiedSet.contains(modLine) || originalSet.contains(origLine)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!areLinesSimilar(originalLines[origLine - 1], modifiedLines[modLine - 1], timeout)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (originalLines[origLine - 1].trim().length !== 0) {\n\t\t\t\textendToBottomWithoutEmptyLines = extendToBottom + 1;\n\t\t\t}\n\t\t}\n\n\t\tif (extendToBottomWithoutEmptyLines > 0) {\n\t\t\toriginalSet.addRange(new LineRange(move.original.endLineNumberExclusive, move.original.endLineNumberExclusive + extendToBottomWithoutEmptyLines));\n\t\t\tmodifiedSet.addRange(new LineRange(move.modified.endLineNumberExclusive, move.modified.endLineNumberExclusive + extendToBottomWithoutEmptyLines));\n\t\t}", + "fileName": "./2.txt" + }, + "diffs": [ + { + "originalRange": "[13,13)", + "modifiedRange": "[13,16)", + "innerChanges": [ + { + "originalRange": "[13,1 -> 13,1]", + "modifiedRange": "[13,1 -> 16,1]" + } + ] + }, + { + "originalRange": "[15,18)", + "modifiedRange": "[18,21)", + "innerChanges": [ + { + "originalRange": "[15,7 -> 15,21]", + "modifiedRange": "[18,7 -> 18,38]" + }, + { + "originalRange": "[16,116 -> 16,130]", + "modifiedRange": "[19,116 -> 19,147]" + }, + { + "originalRange": "[17,116 -> 17,130]", + "modifiedRange": "[20,116 -> 20,147]" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/vs/editor/test/node/diffing/fixtures/shifting-twice/legacy.expected.diff.json b/src/vs/editor/test/node/diffing/fixtures/shifting-twice/legacy.expected.diff.json new file mode 100644 index 00000000000..17d96759241 --- /dev/null +++ b/src/vs/editor/test/node/diffing/fixtures/shifting-twice/legacy.expected.diff.json @@ -0,0 +1,35 @@ +{ + "original": { + "content": "\t\tfor (extendToBottom = 0; extendToBottom < linesBelow; extendToBottom++) {\n\t\t\tconst origLine = move.original.endLineNumberExclusive + extendToBottom;\n\t\t\tconst modLine = move.modified.endLineNumberExclusive + extendToBottom;\n\t\t\tif (origLine > originalLines.length || modLine > modifiedLines.length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (modifiedSet.contains(modLine) || originalSet.contains(origLine)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!areLinesSimilar(originalLines[origLine - 1], modifiedLines[modLine - 1], timeout)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (extendToBottom > 0) {\n\t\t\toriginalSet.addRange(new LineRange(move.original.endLineNumberExclusive, move.original.endLineNumberExclusive + extendToBottom));\n\t\t\tmodifiedSet.addRange(new LineRange(move.modified.endLineNumberExclusive, move.modified.endLineNumberExclusive + extendToBottom));\n\t\t}", + "fileName": "./1.txt" + }, + "modified": { + "content": "\t\tfor (extendToBottom = 0; extendToBottom < linesBelow; extendToBottom++) {\n\t\t\tconst origLine = move.original.endLineNumberExclusive + extendToBottom;\n\t\t\tconst modLine = move.modified.endLineNumberExclusive + extendToBottom;\n\t\t\tif (origLine > originalLines.length || modLine > modifiedLines.length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (modifiedSet.contains(modLine) || originalSet.contains(origLine)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!areLinesSimilar(originalLines[origLine - 1], modifiedLines[modLine - 1], timeout)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (originalLines[origLine - 1].trim().length !== 0) {\n\t\t\t\textendToBottomWithoutEmptyLines = extendToBottom + 1;\n\t\t\t}\n\t\t}\n\n\t\tif (extendToBottomWithoutEmptyLines > 0) {\n\t\t\toriginalSet.addRange(new LineRange(move.original.endLineNumberExclusive, move.original.endLineNumberExclusive + extendToBottomWithoutEmptyLines));\n\t\t\tmodifiedSet.addRange(new LineRange(move.modified.endLineNumberExclusive, move.modified.endLineNumberExclusive + extendToBottomWithoutEmptyLines));\n\t\t}", + "fileName": "./2.txt" + }, + "diffs": [ + { + "originalRange": "[13,13)", + "modifiedRange": "[13,16)", + "innerChanges": null + }, + { + "originalRange": "[15,18)", + "modifiedRange": "[18,21)", + "innerChanges": [ + { + "originalRange": "[15,21 -> 15,21]", + "modifiedRange": "[18,21 -> 18,38]" + }, + { + "originalRange": "[16,130 -> 16,130]", + "modifiedRange": "[19,130 -> 19,147]" + }, + { + "originalRange": "[17,130 -> 17,130]", + "modifiedRange": "[20,130 -> 20,147]" + } + ] + } + ] +} \ No newline at end of file