Skip to content

Commit 845706c

Browse files
committed
Fixes bug in diffing algorithm & improves fixture testing method.
1 parent c5057ee commit 845706c

File tree

64 files changed

+213
-202
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+213
-202
lines changed

src/vs/editor/common/diff/algorithms/joinSequenceDiffs.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ export function shiftSequenceDiffs(sequence1: ISequence, sequence2: ISequence, s
8585
const diff = sequenceDiffs[i];
8686
if (diff.seq1Range.isEmpty) {
8787
const seq2PrevEndExclusive = (i > 0 ? sequenceDiffs[i - 1].seq2Range.endExclusive : -1);
88-
const seq2NextStart = (i + 1 < sequenceDiffs.length ? sequenceDiffs[i + 1].seq2Range.start : sequence2.length + 1);
88+
const seq2NextStart = (i + 1 < sequenceDiffs.length ? sequenceDiffs[i + 1].seq2Range.start : sequence2.length);
8989
sequenceDiffs[i] = shiftDiffToBetterPosition(diff, sequence1, sequence2, seq2NextStart, seq2PrevEndExclusive);
9090
} else if (diff.seq2Range.isEmpty) {
9191
const seq1PrevEndExclusive = (i > 0 ? sequenceDiffs[i - 1].seq1Range.endExclusive : -1);
92-
const seq1NextStart = (i + 1 < sequenceDiffs.length ? sequenceDiffs[i + 1].seq1Range.start : sequence1.length + 1);
92+
const seq1NextStart = (i + 1 < sequenceDiffs.length ? sequenceDiffs[i + 1].seq1Range.start : sequence1.length);
9393
sequenceDiffs[i] = shiftDiffToBetterPosition(diff.reverse(), sequence2, sequence1, seq1NextStart, seq1PrevEndExclusive).reverse();
9494
}
9595
}
@@ -102,15 +102,15 @@ function shiftDiffToBetterPosition(diff: SequenceDiff, sequence1: ISequence, seq
102102

103103
// don't touch previous or next!
104104
let deltaBefore = 1;
105-
while (diff.seq1Range.start - deltaBefore > seq2PrevEndExclusive &&
105+
while (diff.seq2Range.start - deltaBefore > seq2PrevEndExclusive &&
106106
sequence2.getElement(diff.seq2Range.start - deltaBefore) ===
107107
sequence2.getElement(diff.seq2Range.endExclusive - deltaBefore) && deltaBefore < maxShiftLimit) {
108108
deltaBefore++;
109109
}
110110
deltaBefore--;
111111

112112
let deltaAfter = 1;
113-
while (diff.seq1Range.start + deltaAfter < seq2NextStart &&
113+
while (diff.seq2Range.start + deltaAfter < seq2NextStart &&
114114
sequence2.getElement(diff.seq2Range.start + deltaAfter) ===
115115
sequence2.getElement(diff.seq2Range.endExclusive + deltaAfter) && deltaAfter < maxShiftLimit) {
116116
deltaAfter++;

src/vs/editor/test/node/diffing/diffing.test.ts

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,22 @@
55

66
import assert = require('assert');
77
import { readdirSync, readFileSync, existsSync, writeFileSync } from 'fs';
8-
import { join } from 'path';
8+
import { join, resolve } from 'path';
99
import { FileAccess } from 'vs/base/common/network';
1010
import { SmartLinesDiffComputer } from 'vs/editor/common/diff/smartLinesDiffComputer';
1111
import { StandardLinesDiffComputer } from 'vs/editor/common/diff/standardLinesDiffComputer';
1212

1313
suite('diff fixtures', () => {
14-
const fixturesDir = FileAccess.asFileUri('vs/editor/test/node/diffing/fixtures').fsPath;
15-
const folders = readdirSync(fixturesDir);
14+
const fixturesOutDir = FileAccess.asFileUri('vs/editor/test/node/diffing/fixtures').fsPath;
15+
// We want the dir in src, so we can directly update the source files if they disagree and create invalid files to capture the previous state.
16+
// This makes it very easy to update the fixtures.
17+
const fixturesSrcDir = resolve(fixturesOutDir).replaceAll('\\', '/').replace('/out/vs/editor/', '/src/vs/editor/');
18+
const folders = readdirSync(fixturesSrcDir);
1619

1720
for (const folder of folders) {
1821
for (const diffingAlgoName of ['smart', 'experimental']) {
19-
2022
test(`${folder}-${diffingAlgoName}`, () => {
21-
const folderPath = join(fixturesDir, folder);
23+
const folderPath = join(fixturesSrcDir, folder);
2224
const files = readdirSync(folderPath);
2325

2426
const firstFileName = files.find(f => f.startsWith('1.'))!;
@@ -31,7 +33,7 @@ suite('diff fixtures', () => {
3133

3234
const diff = diffingAlgo.computeDiff(firstContentLines, secondContentLines, { ignoreTrimWhitespace: false, maxComputationTime: Number.MAX_SAFE_INTEGER });
3335

34-
const diffingResult: DiffingResult = {
36+
const actualDiffingResult: DiffingResult = {
3537
originalFileName: `./${firstFileName}`,
3638
modifiedFileName: `./${secondFileName}`,
3739
diffs: diff.changes.map<IDetailedDiff>(c => ({
@@ -44,29 +46,34 @@ suite('diff fixtures', () => {
4446
}))
4547
};
4648

47-
const actualFilePath = join(folderPath, `${diffingAlgoName}.actual.diff.json`);
4849
const expectedFilePath = join(folderPath, `${diffingAlgoName}.expected.diff.json`);
50+
const invalidFilePath = join(folderPath, `${diffingAlgoName}.invalid.diff.json`);
51+
52+
const expectedFileContentFromActual = JSON.stringify(actualDiffingResult, null, '\t');
4953

50-
const expectedFileContent = JSON.stringify(diffingResult, null, '\t');
54+
const invalidExists = existsSync(invalidFilePath);
5155

52-
if (!existsSync(actualFilePath)) {
53-
writeFileSync(actualFilePath, expectedFileContent);
54-
writeFileSync(expectedFilePath, expectedFileContent);
55-
throw new Error('No actual file! Actual and expected files were written.');
56+
if (!existsSync(expectedFilePath)) {
57+
writeFileSync(expectedFilePath, expectedFileContentFromActual);
58+
writeFileSync(invalidFilePath, '');
59+
throw new Error('No expected file! Expected and invalid files were written. Delete the invalid file to make the test pass.');
5660
} else {
57-
const actualFileContent = readFileSync(actualFilePath, 'utf8');
58-
const actualFileDiffResult: DiffingResult = JSON.parse(actualFileContent);
61+
const expectedFileContent = readFileSync(invalidExists ? invalidFilePath : expectedFilePath, 'utf8');
62+
const expectedFileDiffResult: DiffingResult = JSON.parse(expectedFileContent);
5963

6064
try {
61-
assert.deepStrictEqual(actualFileDiffResult, diffingResult);
65+
assert.deepStrictEqual(actualDiffingResult, expectedFileDiffResult);
6266
} catch (e) {
63-
writeFileSync(expectedFilePath, expectedFileContent);
67+
if (!invalidExists) {
68+
writeFileSync(invalidFilePath, expectedFileContent);
69+
}
70+
writeFileSync(expectedFilePath, expectedFileContentFromActual);
6471
throw e;
6572
}
6673
}
6774

68-
if (existsSync(expectedFilePath)) {
69-
throw new Error('Expected file exists! Please delete it.');
75+
if (invalidExists) {
76+
throw new Error('Invalid file exists and agrees with expected file! Delete the invalid file to make the test pass.');
7077
}
7178
});
7279
}

src/vs/editor/test/node/diffing/fixtures/bracket-aligning/experimental.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/bracket-aligning/experimental.expected.diff.json

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@
6161
]
6262
},
6363
{
64-
"originalRange": "[86,95)",
65-
"modifiedRange": "[88,98)",
64+
"originalRange": "[86,98)",
65+
"modifiedRange": "[88,101)",
6666
"innerChanges": [
6767
{
6868
"originalRange": "[86,1 -> 86,1]",
@@ -102,9 +102,21 @@
102102
},
103103
{
104104
"originalRange": "[95,1 -> 95,1]",
105-
"modifiedRange": "[97,1 -> 98,1]"
105+
"modifiedRange": "[97,1 -> 97,2]"
106+
},
107+
{
108+
"originalRange": "[96,1 -> 96,1]",
109+
"modifiedRange": "[98,1 -> 98,2]"
110+
},
111+
{
112+
"originalRange": "[97,1 -> 97,1]",
113+
"modifiedRange": "[99,1 -> 99,2]"
114+
},
115+
{
116+
"originalRange": "[98,1 -> 98,1]",
117+
"modifiedRange": "[100,1 -> 101,1]"
106118
}
107119
]
108120
}
109121
]
110-
}
122+
}

src/vs/editor/test/node/diffing/fixtures/bracket-aligning/smart.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/bracket-aligning/smart.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
"innerChanges": null
1414
}
1515
]
16-
}
16+
}

src/vs/editor/test/node/diffing/fixtures/indentation/experimental.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/indentation/experimental.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,4 @@
7575
]
7676
}
7777
]
78-
}
78+
}

src/vs/editor/test/node/diffing/fixtures/indentation/smart.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/indentation/smart.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
"innerChanges": null
1414
}
1515
]
16-
}
16+
}

src/vs/editor/test/node/diffing/fixtures/json-brackets/experimental.actual.diff.json

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"originalFileName": "./1.json",
3+
"modifiedFileName": "./2.json",
4+
"diffs": [
5+
{
6+
"originalRange": "[301,301)",
7+
"modifiedRange": "[301,305)",
8+
"innerChanges": [
9+
{
10+
"originalRange": "[301,1 -> 301,1]",
11+
"modifiedRange": "[301,1 -> 305,1]"
12+
}
13+
]
14+
}
15+
]
16+
}

src/vs/editor/test/node/diffing/fixtures/method-splitting/experimental.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/method-splitting/experimental.expected.diff.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@
215215
"modifiedRange": "[7,130 -> 7,130]"
216216
},
217217
{
218-
"originalRange": "[8,5 -> 8,10]",
219-
"modifiedRange": "[7,130 -> 7,130]"
218+
"originalRange": "[8,6 -> 8,11]",
219+
"modifiedRange": "[7,131 -> 7,131]"
220220
},
221221
{
222222
"originalRange": "[8,15 -> 8,21]",
@@ -251,8 +251,8 @@
251251
"modifiedRange": "[7,181 -> 7,182]"
252252
},
253253
{
254-
"originalRange": "[9,1 -> 10,1]",
255-
"modifiedRange": "[8,1 -> 8,1]"
254+
"originalRange": "[8,66 -> 9,3]",
255+
"modifiedRange": "[7,183 -> 7,183]"
256256
}
257257
]
258258
},
@@ -275,4 +275,4 @@
275275
]
276276
}
277277
]
278-
}
278+
}

src/vs/editor/test/node/diffing/fixtures/method-splitting/smart.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/method-splitting/smart.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,4 @@
7575
]
7676
}
7777
]
78-
}
78+
}

src/vs/editor/test/node/diffing/fixtures/minimal-diff-character/experimental.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/minimal-diff-character/experimental.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@
2727
]
2828
}
2929
]
30-
}
30+
}

src/vs/editor/test/node/diffing/fixtures/minimal-diff-character/smart.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/minimal-diff-character/smart.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@
2323
]
2424
}
2525
]
26-
}
26+
}

src/vs/editor/test/node/diffing/fixtures/subword/experimental.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/subword/experimental.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@
2323
]
2424
}
2525
]
26-
}
26+
}

src/vs/editor/test/node/diffing/fixtures/subword/smart.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/subword/smart.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@
1818
"innerChanges": null
1919
}
2020
]
21-
}
21+
}

src/vs/editor/test/node/diffing/fixtures/ts-comments/experimental.actual.diff.json

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"originalFileName": "./1.tst",
3+
"modifiedFileName": "./2.tst",
4+
"diffs": [
5+
{
6+
"originalRange": "[7,7)",
7+
"modifiedRange": "[7,12)",
8+
"innerChanges": [
9+
{
10+
"originalRange": "[7,1 -> 7,1]",
11+
"modifiedRange": "[7,1 -> 12,1]"
12+
}
13+
]
14+
}
15+
]
16+
}

src/vs/editor/test/node/diffing/fixtures/ts-comments/smart.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/ts-comments/smart.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
"innerChanges": null
99
}
1010
]
11-
}
11+
}

src/vs/editor/test/node/diffing/fixtures/ts-confusing-2/experimental.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/ts-confusing-2/experimental.expected.diff.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@
177177
"modifiedRange": "[16,81 -> 16,83]"
178178
},
179179
{
180-
"originalRange": "[14,208 -> 14,208]",
181-
"modifiedRange": "[16,84 -> 16,118]"
180+
"originalRange": "[14,209 -> 14,209]",
181+
"modifiedRange": "[16,85 -> 16,119]"
182182
},
183183
{
184184
"originalRange": "[14,210 -> 14,211]",
@@ -251,8 +251,8 @@
251251
"modifiedRange": "[23,25 -> 23,25]"
252252
},
253253
{
254-
"originalRange": "[19,9 -> 19,13]",
255-
"modifiedRange": "[23,27 -> 23,27]"
254+
"originalRange": "[19,10 -> 19,14]",
255+
"modifiedRange": "[23,28 -> 23,28]"
256256
},
257257
{
258258
"originalRange": "[19,14 -> 19,17]",
@@ -303,8 +303,8 @@
303303
"modifiedRange": "[23,79 -> 23,83]"
304304
},
305305
{
306-
"originalRange": "[20,37 -> 20,40]",
307-
"modifiedRange": "[23,85 -> 23,85]"
306+
"originalRange": "[20,36 -> 20,39]",
307+
"modifiedRange": "[23,84 -> 23,84]"
308308
},
309309
{
310310
"originalRange": "[20,41 -> 20,44]",
@@ -391,8 +391,8 @@
391391
"modifiedRange": "[26,38)",
392392
"innerChanges": [
393393
{
394-
"originalRange": "[28,1 -> 28,1]",
395-
"modifiedRange": "[26,1 -> 27,1]"
394+
"originalRange": "[28,4 -> 28,4]",
395+
"modifiedRange": "[26,4 -> 27,4]"
396396
},
397397
{
398398
"originalRange": "[28,15 -> 28,20]",
@@ -505,4 +505,4 @@
505505
]
506506
}
507507
]
508-
}
508+
}

src/vs/editor/test/node/diffing/fixtures/ts-confusing-2/smart.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/ts-confusing-2/smart.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,4 @@
152152
]
153153
}
154154
]
155-
}
155+
}

src/vs/editor/test/node/diffing/fixtures/ts-confusing/experimental.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/ts-confusing/experimental.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,4 @@
109109
]
110110
}
111111
]
112-
}
112+
}

src/vs/editor/test/node/diffing/fixtures/ts-confusing/smart.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/ts-confusing/smart.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@
4545
]
4646
}
4747
]
48-
}
48+
}

src/vs/editor/test/node/diffing/fixtures/ts-diff-word-split/experimental.actual.diff.json renamed to src/vs/editor/test/node/diffing/fixtures/ts-diff-word-split/experimental.expected.diff.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@
4343
]
4444
}
4545
]
46-
}
46+
}

0 commit comments

Comments
 (0)