Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/test/common/diff/diffComputer.test.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import assert from 'assert';
6
import { Constants } from '../../../../base/common/uint.js';
7
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';
8
import { Range } from '../../../common/core/range.js';
9
import { DiffComputer, ICharChange, ILineChange } from '../../../common/diff/legacyLinesDiffComputer.js';
10
import { IIdentifiedSingleEditOperation, ITextModel } from '../../../common/model.js';
11
import { createTextModel } from '../testTextModel.js';
12
13
function assertDiff(originalLines: string[], modifiedLines: string[], expectedChanges: ILineChange[], shouldComputeCharChanges: boolean = true, shouldPostProcessCharChanges: boolean = false, shouldIgnoreTrimWhitespace: boolean = false) {
14
const diffComputer = new DiffComputer(originalLines, modifiedLines, {
15
shouldComputeCharChanges,
16
shouldPostProcessCharChanges,
17
shouldIgnoreTrimWhitespace,
18
shouldMakePrettyDiff: true,
19
maxComputationTime: 0
20
});
21
const changes = diffComputer.computeDiff().changes;
22
23
const mapCharChange = (charChange: ICharChange) => {
24
return {
25
originalStartLineNumber: charChange.originalStartLineNumber,
26
originalStartColumn: charChange.originalStartColumn,
27
originalEndLineNumber: charChange.originalEndLineNumber,
28
originalEndColumn: charChange.originalEndColumn,
29
modifiedStartLineNumber: charChange.modifiedStartLineNumber,
30
modifiedStartColumn: charChange.modifiedStartColumn,
31
modifiedEndLineNumber: charChange.modifiedEndLineNumber,
32
modifiedEndColumn: charChange.modifiedEndColumn,
33
};
34
};
35
36
const actual = changes.map((lineChange) => {
37
return {
38
originalStartLineNumber: lineChange.originalStartLineNumber,
39
originalEndLineNumber: lineChange.originalEndLineNumber,
40
modifiedStartLineNumber: lineChange.modifiedStartLineNumber,
41
modifiedEndLineNumber: lineChange.modifiedEndLineNumber,
42
charChanges: (lineChange.charChanges ? lineChange.charChanges.map(mapCharChange) : undefined)
43
};
44
});
45
46
assert.deepStrictEqual(actual, expectedChanges);
47
48
if (!shouldIgnoreTrimWhitespace) {
49
// The diffs should describe how to apply edits to the original text model to get to the modified text model.
50
51
const modifiedTextModel = createTextModel(modifiedLines.join('\n'));
52
const expectedValue = modifiedTextModel.getValue();
53
54
{
55
// Line changes:
56
const originalTextModel = createTextModel(originalLines.join('\n'));
57
originalTextModel.applyEdits(changes.map(c => getLineEdit(c, modifiedTextModel)));
58
assert.deepStrictEqual(originalTextModel.getValue(), expectedValue);
59
originalTextModel.dispose();
60
}
61
62
if (shouldComputeCharChanges) {
63
// Char changes:
64
const originalTextModel = createTextModel(originalLines.join('\n'));
65
originalTextModel.applyEdits(changes.flatMap(c => getCharEdits(c, modifiedTextModel)));
66
assert.deepStrictEqual(originalTextModel.getValue(), expectedValue);
67
originalTextModel.dispose();
68
}
69
70
modifiedTextModel.dispose();
71
}
72
}
73
74
function getCharEdits(lineChange: ILineChange, modifiedTextModel: ITextModel): IIdentifiedSingleEditOperation[] {
75
if (!lineChange.charChanges) {
76
return [getLineEdit(lineChange, modifiedTextModel)];
77
}
78
return lineChange.charChanges.map(c => {
79
const originalRange = new Range(c.originalStartLineNumber, c.originalStartColumn, c.originalEndLineNumber, c.originalEndColumn);
80
const modifiedRange = new Range(c.modifiedStartLineNumber, c.modifiedStartColumn, c.modifiedEndLineNumber, c.modifiedEndColumn);
81
return {
82
range: originalRange,
83
text: modifiedTextModel.getValueInRange(modifiedRange)
84
};
85
});
86
}
87
88
function getLineEdit(lineChange: ILineChange, modifiedTextModel: ITextModel): IIdentifiedSingleEditOperation {
89
let originalRange: LineRange;
90
if (lineChange.originalEndLineNumber === 0) {
91
// Insertion
92
originalRange = new LineRange(lineChange.originalStartLineNumber + 1, 0);
93
} else {
94
originalRange = new LineRange(lineChange.originalStartLineNumber, lineChange.originalEndLineNumber - lineChange.originalStartLineNumber + 1);
95
}
96
97
let modifiedRange: LineRange;
98
if (lineChange.modifiedEndLineNumber === 0) {
99
// Deletion
100
modifiedRange = new LineRange(lineChange.modifiedStartLineNumber + 1, 0);
101
} else {
102
modifiedRange = new LineRange(lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber - lineChange.modifiedStartLineNumber + 1);
103
}
104
105
const [r1, r2] = diffFromLineRanges(originalRange, modifiedRange);
106
return {
107
range: r1,
108
text: modifiedTextModel.getValueInRange(r2),
109
};
110
}
111
112
function diffFromLineRanges(originalRange: LineRange, modifiedRange: LineRange): [Range, Range] {
113
if (originalRange.startLineNumber === 1 || modifiedRange.startLineNumber === 1) {
114
if (!originalRange.isEmpty && !modifiedRange.isEmpty) {
115
return [
116
new Range(
117
originalRange.startLineNumber,
118
1,
119
originalRange.endLineNumberExclusive - 1,
120
Constants.MAX_SAFE_SMALL_INTEGER,
121
),
122
new Range(
123
modifiedRange.startLineNumber,
124
1,
125
modifiedRange.endLineNumberExclusive - 1,
126
Constants.MAX_SAFE_SMALL_INTEGER,
127
)
128
];
129
}
130
131
// When one of them is one and one of them is empty, the other cannot be the last line of the document
132
return [
133
new Range(
134
originalRange.startLineNumber,
135
1,
136
originalRange.endLineNumberExclusive,
137
1,
138
),
139
new Range(
140
modifiedRange.startLineNumber,
141
1,
142
modifiedRange.endLineNumberExclusive,
143
1,
144
)
145
];
146
}
147
148
return [
149
new Range(
150
originalRange.startLineNumber - 1,
151
Constants.MAX_SAFE_SMALL_INTEGER,
152
originalRange.endLineNumberExclusive - 1,
153
Constants.MAX_SAFE_SMALL_INTEGER,
154
),
155
new Range(
156
modifiedRange.startLineNumber - 1,
157
Constants.MAX_SAFE_SMALL_INTEGER,
158
modifiedRange.endLineNumberExclusive - 1,
159
Constants.MAX_SAFE_SMALL_INTEGER,
160
)
161
];
162
}
163
164
class LineRange {
165
public constructor(
166
public readonly startLineNumber: number,
167
public readonly lineCount: number
168
) { }
169
170
public get isEmpty(): boolean {
171
return this.lineCount === 0;
172
}
173
174
public get endLineNumberExclusive(): number {
175
return this.startLineNumber + this.lineCount;
176
}
177
}
178
179
function createLineDeletion(startLineNumber: number, endLineNumber: number, modifiedLineNumber: number): ILineChange {
180
return {
181
originalStartLineNumber: startLineNumber,
182
originalEndLineNumber: endLineNumber,
183
modifiedStartLineNumber: modifiedLineNumber,
184
modifiedEndLineNumber: 0,
185
charChanges: undefined
186
};
187
}
188
189
function createLineInsertion(startLineNumber: number, endLineNumber: number, originalLineNumber: number): ILineChange {
190
return {
191
originalStartLineNumber: originalLineNumber,
192
originalEndLineNumber: 0,
193
modifiedStartLineNumber: startLineNumber,
194
modifiedEndLineNumber: endLineNumber,
195
charChanges: undefined
196
};
197
}
198
199
function createLineChange(originalStartLineNumber: number, originalEndLineNumber: number, modifiedStartLineNumber: number, modifiedEndLineNumber: number, charChanges?: ICharChange[]): ILineChange {
200
return {
201
originalStartLineNumber: originalStartLineNumber,
202
originalEndLineNumber: originalEndLineNumber,
203
modifiedStartLineNumber: modifiedStartLineNumber,
204
modifiedEndLineNumber: modifiedEndLineNumber,
205
charChanges: charChanges
206
};
207
}
208
209
function createCharChange(
210
originalStartLineNumber: number, originalStartColumn: number, originalEndLineNumber: number, originalEndColumn: number,
211
modifiedStartLineNumber: number, modifiedStartColumn: number, modifiedEndLineNumber: number, modifiedEndColumn: number
212
) {
213
return {
214
originalStartLineNumber: originalStartLineNumber,
215
originalStartColumn: originalStartColumn,
216
originalEndLineNumber: originalEndLineNumber,
217
originalEndColumn: originalEndColumn,
218
modifiedStartLineNumber: modifiedStartLineNumber,
219
modifiedStartColumn: modifiedStartColumn,
220
modifiedEndLineNumber: modifiedEndLineNumber,
221
modifiedEndColumn: modifiedEndColumn
222
};
223
}
224
225
suite('Editor Diff - DiffComputer', () => {
226
227
ensureNoDisposablesAreLeakedInTestSuite();
228
229
// ---- insertions
230
231
test('one inserted line below', () => {
232
const original = ['line'];
233
const modified = ['line', 'new line'];
234
const expected = [createLineInsertion(2, 2, 1)];
235
assertDiff(original, modified, expected);
236
});
237
238
test('two inserted lines below', () => {
239
const original = ['line'];
240
const modified = ['line', 'new line', 'another new line'];
241
const expected = [createLineInsertion(2, 3, 1)];
242
assertDiff(original, modified, expected);
243
});
244
245
test('one inserted line above', () => {
246
const original = ['line'];
247
const modified = ['new line', 'line'];
248
const expected = [createLineInsertion(1, 1, 0)];
249
assertDiff(original, modified, expected);
250
});
251
252
test('two inserted lines above', () => {
253
const original = ['line'];
254
const modified = ['new line', 'another new line', 'line'];
255
const expected = [createLineInsertion(1, 2, 0)];
256
assertDiff(original, modified, expected);
257
});
258
259
test('one inserted line in middle', () => {
260
const original = ['line1', 'line2', 'line3', 'line4'];
261
const modified = ['line1', 'line2', 'new line', 'line3', 'line4'];
262
const expected = [createLineInsertion(3, 3, 2)];
263
assertDiff(original, modified, expected);
264
});
265
266
test('two inserted lines in middle', () => {
267
const original = ['line1', 'line2', 'line3', 'line4'];
268
const modified = ['line1', 'line2', 'new line', 'another new line', 'line3', 'line4'];
269
const expected = [createLineInsertion(3, 4, 2)];
270
assertDiff(original, modified, expected);
271
});
272
273
test('two inserted lines in middle interrupted', () => {
274
const original = ['line1', 'line2', 'line3', 'line4'];
275
const modified = ['line1', 'line2', 'new line', 'line3', 'another new line', 'line4'];
276
const expected = [createLineInsertion(3, 3, 2), createLineInsertion(5, 5, 3)];
277
assertDiff(original, modified, expected);
278
});
279
280
// ---- deletions
281
282
test('one deleted line below', () => {
283
const original = ['line', 'new line'];
284
const modified = ['line'];
285
const expected = [createLineDeletion(2, 2, 1)];
286
assertDiff(original, modified, expected);
287
});
288
289
test('two deleted lines below', () => {
290
const original = ['line', 'new line', 'another new line'];
291
const modified = ['line'];
292
const expected = [createLineDeletion(2, 3, 1)];
293
assertDiff(original, modified, expected);
294
});
295
296
test('one deleted lines above', () => {
297
const original = ['new line', 'line'];
298
const modified = ['line'];
299
const expected = [createLineDeletion(1, 1, 0)];
300
assertDiff(original, modified, expected);
301
});
302
303
test('two deleted lines above', () => {
304
const original = ['new line', 'another new line', 'line'];
305
const modified = ['line'];
306
const expected = [createLineDeletion(1, 2, 0)];
307
assertDiff(original, modified, expected);
308
});
309
310
test('one deleted line in middle', () => {
311
const original = ['line1', 'line2', 'new line', 'line3', 'line4'];
312
const modified = ['line1', 'line2', 'line3', 'line4'];
313
const expected = [createLineDeletion(3, 3, 2)];
314
assertDiff(original, modified, expected);
315
});
316
317
test('two deleted lines in middle', () => {
318
const original = ['line1', 'line2', 'new line', 'another new line', 'line3', 'line4'];
319
const modified = ['line1', 'line2', 'line3', 'line4'];
320
const expected = [createLineDeletion(3, 4, 2)];
321
assertDiff(original, modified, expected);
322
});
323
324
test('two deleted lines in middle interrupted', () => {
325
const original = ['line1', 'line2', 'new line', 'line3', 'another new line', 'line4'];
326
const modified = ['line1', 'line2', 'line3', 'line4'];
327
const expected = [createLineDeletion(3, 3, 2), createLineDeletion(5, 5, 3)];
328
assertDiff(original, modified, expected);
329
});
330
331
// ---- changes
332
333
test('one line changed: chars inserted at the end', () => {
334
const original = ['line'];
335
const modified = ['line changed'];
336
const expected = [
337
createLineChange(1, 1, 1, 1, [
338
createCharChange(1, 5, 1, 5, 1, 5, 1, 13)
339
])
340
];
341
assertDiff(original, modified, expected);
342
});
343
344
test('one line changed: chars inserted at the beginning', () => {
345
const original = ['line'];
346
const modified = ['my line'];
347
const expected = [
348
createLineChange(1, 1, 1, 1, [
349
createCharChange(1, 1, 1, 1, 1, 1, 1, 4)
350
])
351
];
352
assertDiff(original, modified, expected);
353
});
354
355
test('one line changed: chars inserted in the middle', () => {
356
const original = ['abba'];
357
const modified = ['abzzba'];
358
const expected = [
359
createLineChange(1, 1, 1, 1, [
360
createCharChange(1, 3, 1, 3, 1, 3, 1, 5)
361
])
362
];
363
assertDiff(original, modified, expected);
364
});
365
366
test('one line changed: chars inserted in the middle (two spots)', () => {
367
const original = ['abba'];
368
const modified = ['abzzbzza'];
369
const expected = [
370
createLineChange(1, 1, 1, 1, [
371
createCharChange(1, 3, 1, 3, 1, 3, 1, 5),
372
createCharChange(1, 4, 1, 4, 1, 6, 1, 8)
373
])
374
];
375
assertDiff(original, modified, expected);
376
});
377
378
test('one line changed: chars deleted 1', () => {
379
const original = ['abcdefg'];
380
const modified = ['abcfg'];
381
const expected = [
382
createLineChange(1, 1, 1, 1, [
383
createCharChange(1, 4, 1, 6, 1, 4, 1, 4)
384
])
385
];
386
assertDiff(original, modified, expected);
387
});
388
389
test('one line changed: chars deleted 2', () => {
390
const original = ['abcdefg'];
391
const modified = ['acfg'];
392
const expected = [
393
createLineChange(1, 1, 1, 1, [
394
createCharChange(1, 2, 1, 3, 1, 2, 1, 2),
395
createCharChange(1, 4, 1, 6, 1, 3, 1, 3)
396
])
397
];
398
assertDiff(original, modified, expected);
399
});
400
401
test('two lines changed 1', () => {
402
const original = ['abcd', 'efgh'];
403
const modified = ['abcz'];
404
const expected = [
405
createLineChange(1, 2, 1, 1, [
406
createCharChange(1, 4, 2, 5, 1, 4, 1, 5)
407
])
408
];
409
assertDiff(original, modified, expected);
410
});
411
412
test('two lines changed 2', () => {
413
const original = ['foo', 'abcd', 'efgh', 'BAR'];
414
const modified = ['foo', 'abcz', 'BAR'];
415
const expected = [
416
createLineChange(2, 3, 2, 2, [
417
createCharChange(2, 4, 3, 5, 2, 4, 2, 5)
418
])
419
];
420
assertDiff(original, modified, expected);
421
});
422
423
test('two lines changed 3', () => {
424
const original = ['foo', 'abcd', 'efgh', 'BAR'];
425
const modified = ['foo', 'abcz', 'zzzzefgh', 'BAR'];
426
const expected = [
427
createLineChange(2, 3, 2, 3, [
428
createCharChange(2, 4, 2, 5, 2, 4, 2, 5),
429
createCharChange(3, 1, 3, 1, 3, 1, 3, 5)
430
])
431
];
432
assertDiff(original, modified, expected);
433
});
434
435
test('two lines changed 4', () => {
436
const original = ['abc'];
437
const modified = ['', '', 'axc', ''];
438
const expected = [
439
createLineChange(1, 1, 1, 4, [
440
createCharChange(1, 1, 1, 1, 1, 1, 3, 1),
441
createCharChange(1, 2, 1, 3, 3, 2, 3, 3),
442
createCharChange(1, 4, 1, 4, 3, 4, 4, 1)
443
])
444
];
445
assertDiff(original, modified, expected);
446
});
447
448
test('empty original sequence in char diff', () => {
449
const original = ['abc', '', 'xyz'];
450
const modified = ['abc', 'qwe', 'rty', 'xyz'];
451
const expected = [
452
createLineChange(2, 2, 2, 3)
453
];
454
assertDiff(original, modified, expected);
455
});
456
457
test('three lines changed', () => {
458
const original = ['foo', 'abcd', 'efgh', 'BAR'];
459
const modified = ['foo', 'zzzefgh', 'xxx', 'BAR'];
460
const expected = [
461
createLineChange(2, 3, 2, 3, [
462
createCharChange(2, 1, 3, 1, 2, 1, 2, 4),
463
createCharChange(3, 5, 3, 5, 2, 8, 3, 4),
464
])
465
];
466
assertDiff(original, modified, expected);
467
});
468
469
test('big change part 1', () => {
470
const original = ['foo', 'abcd', 'efgh', 'BAR'];
471
const modified = ['hello', 'foo', 'zzzefgh', 'xxx', 'BAR'];
472
const expected = [
473
createLineInsertion(1, 1, 0),
474
createLineChange(2, 3, 3, 4, [
475
createCharChange(2, 1, 3, 1, 3, 1, 3, 4),
476
createCharChange(3, 5, 3, 5, 3, 8, 4, 4)
477
])
478
];
479
assertDiff(original, modified, expected);
480
});
481
482
test('big change part 2', () => {
483
const original = ['foo', 'abcd', 'efgh', 'BAR', 'RAB'];
484
const modified = ['hello', 'foo', 'zzzefgh', 'xxx', 'BAR'];
485
const expected = [
486
createLineInsertion(1, 1, 0),
487
createLineChange(2, 3, 3, 4, [
488
createCharChange(2, 1, 3, 1, 3, 1, 3, 4),
489
createCharChange(3, 5, 3, 5, 3, 8, 4, 4)
490
]),
491
createLineDeletion(5, 5, 5)
492
];
493
assertDiff(original, modified, expected);
494
});
495
496
test('char change postprocessing merges', () => {
497
const original = ['abba'];
498
const modified = ['azzzbzzzbzzza'];
499
const expected = [
500
createLineChange(1, 1, 1, 1, [
501
createCharChange(1, 2, 1, 4, 1, 2, 1, 13)
502
])
503
];
504
assertDiff(original, modified, expected, true, true);
505
});
506
507
test('ignore trim whitespace', () => {
508
const original = ['\t\t foo ', 'abcd', 'efgh', '\t\t BAR\t\t'];
509
const modified = [' hello\t', '\t foo \t', 'zzzefgh', 'xxx', ' BAR \t'];
510
const expected = [
511
createLineInsertion(1, 1, 0),
512
createLineChange(2, 3, 3, 4, [
513
createCharChange(2, 1, 2, 5, 3, 1, 3, 4),
514
createCharChange(3, 5, 3, 5, 4, 1, 4, 4)
515
])
516
];
517
assertDiff(original, modified, expected, true, false, true);
518
});
519
520
test('issue #12122 r.hasOwnProperty is not a function', () => {
521
const original = ['hasOwnProperty'];
522
const modified = ['hasOwnProperty', 'and another line'];
523
const expected = [
524
createLineInsertion(2, 2, 1)
525
];
526
assertDiff(original, modified, expected);
527
});
528
529
test('empty diff 1', () => {
530
const original = [''];
531
const modified = ['something'];
532
const expected = [
533
createLineChange(1, 1, 1, 1, undefined)
534
];
535
assertDiff(original, modified, expected, true, false, true);
536
});
537
538
test('empty diff 2', () => {
539
const original = [''];
540
const modified = ['something', 'something else'];
541
const expected = [
542
createLineChange(1, 1, 1, 2, undefined)
543
];
544
assertDiff(original, modified, expected, true, false, true);
545
});
546
547
test('empty diff 3', () => {
548
const original = ['something', 'something else'];
549
const modified = [''];
550
const expected = [
551
createLineChange(1, 2, 1, 1, undefined)
552
];
553
assertDiff(original, modified, expected, true, false, true);
554
});
555
556
test('empty diff 4', () => {
557
const original = ['something'];
558
const modified = [''];
559
const expected = [
560
createLineChange(1, 1, 1, 1, undefined)
561
];
562
assertDiff(original, modified, expected, true, false, true);
563
});
564
565
test('empty diff 5', () => {
566
const original = [''];
567
const modified = [''];
568
const expected: ILineChange[] = [];
569
assertDiff(original, modified, expected, true, false, true);
570
});
571
572
test('pretty diff 1', () => {
573
const original = [
574
'suite(function () {',
575
' test1() {',
576
' assert.ok(true);',
577
' }',
578
'',
579
' test2() {',
580
' assert.ok(true);',
581
' }',
582
'});',
583
'',
584
];
585
const modified = [
586
'// An insertion',
587
'suite(function () {',
588
' test1() {',
589
' assert.ok(true);',
590
' }',
591
'',
592
' test2() {',
593
' assert.ok(true);',
594
' }',
595
'',
596
' test3() {',
597
' assert.ok(true);',
598
' }',
599
'});',
600
'',
601
];
602
const expected = [
603
createLineInsertion(1, 1, 0),
604
createLineInsertion(10, 13, 8)
605
];
606
assertDiff(original, modified, expected, true, false, true);
607
});
608
609
test('pretty diff 2', () => {
610
const original = [
611
'// Just a comment',
612
'',
613
'function compute(a, b, c, d) {',
614
' if (a) {',
615
' if (b) {',
616
' if (c) {',
617
' return 5;',
618
' }',
619
' }',
620
' // These next lines will be deleted',
621
' if (d) {',
622
' return -1;',
623
' }',
624
' return 0;',
625
' }',
626
'}',
627
];
628
const modified = [
629
'// Here is an inserted line',
630
'// and another inserted line',
631
'// and another one',
632
'// Just a comment',
633
'',
634
'function compute(a, b, c, d) {',
635
' if (a) {',
636
' if (b) {',
637
' if (c) {',
638
' return 5;',
639
' }',
640
' }',
641
' return 0;',
642
' }',
643
'}',
644
];
645
const expected = [
646
createLineInsertion(1, 3, 0),
647
createLineDeletion(10, 13, 12),
648
];
649
assertDiff(original, modified, expected, true, false, true);
650
});
651
652
test('pretty diff 3', () => {
653
const original = [
654
'class A {',
655
' /**',
656
' * m1',
657
' */',
658
' method1() {}',
659
'',
660
' /**',
661
' * m3',
662
' */',
663
' method3() {}',
664
'}',
665
];
666
const modified = [
667
'class A {',
668
' /**',
669
' * m1',
670
' */',
671
' method1() {}',
672
'',
673
' /**',
674
' * m2',
675
' */',
676
' method2() {}',
677
'',
678
' /**',
679
' * m3',
680
' */',
681
' method3() {}',
682
'}',
683
];
684
const expected = [
685
createLineInsertion(7, 11, 6)
686
];
687
assertDiff(original, modified, expected, true, false, true);
688
});
689
690
test('issue #23636', () => {
691
const original = [
692
'if(!TextDrawLoad[playerid])',
693
'{',
694
'',
695
' TextDrawHideForPlayer(playerid,TD_AppleJob[3]);',
696
' TextDrawHideForPlayer(playerid,TD_AppleJob[4]);',
697
' if(!AppleJobTreesType[AppleJobTreesPlayerNum[playerid]])',
698
' {',
699
' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[5+i]);',
700
' }',
701
' else',
702
' {',
703
' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[15+i]);',
704
' }',
705
'}',
706
'else',
707
'{',
708
' TextDrawHideForPlayer(playerid,TD_AppleJob[3]);',
709
' TextDrawHideForPlayer(playerid,TD_AppleJob[27]);',
710
' if(!AppleJobTreesType[AppleJobTreesPlayerNum[playerid]])',
711
' {',
712
' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[28+i]);',
713
' }',
714
' else',
715
' {',
716
' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[38+i]);',
717
' }',
718
'}',
719
];
720
const modified = [
721
' if(!TextDrawLoad[playerid])',
722
' {',
723
' ',
724
' TextDrawHideForPlayer(playerid,TD_AppleJob[3]);',
725
' TextDrawHideForPlayer(playerid,TD_AppleJob[4]);',
726
' if(!AppleJobTreesType[AppleJobTreesPlayerNum[playerid]])',
727
' {',
728
' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[5+i]);',
729
' }',
730
' else',
731
' {',
732
' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[15+i]);',
733
' }',
734
' }',
735
' else',
736
' {',
737
' TextDrawHideForPlayer(playerid,TD_AppleJob[3]);',
738
' TextDrawHideForPlayer(playerid,TD_AppleJob[27]);',
739
' if(!AppleJobTreesType[AppleJobTreesPlayerNum[playerid]])',
740
' {',
741
' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[28+i]);',
742
' }',
743
' else',
744
' {',
745
' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[38+i]);',
746
' }',
747
' }',
748
];
749
const expected = [
750
createLineChange(
751
1, 27, 1, 27,
752
[
753
createCharChange(1, 1, 1, 1, 1, 1, 1, 2),
754
createCharChange(2, 1, 2, 1, 2, 1, 2, 2),
755
createCharChange(3, 1, 3, 1, 3, 1, 3, 2),
756
createCharChange(4, 1, 4, 1, 4, 1, 4, 2),
757
createCharChange(5, 1, 5, 1, 5, 1, 5, 2),
758
createCharChange(6, 1, 6, 1, 6, 1, 6, 2),
759
createCharChange(7, 1, 7, 1, 7, 1, 7, 2),
760
createCharChange(8, 1, 8, 1, 8, 1, 8, 2),
761
createCharChange(9, 1, 9, 1, 9, 1, 9, 2),
762
createCharChange(10, 1, 10, 1, 10, 1, 10, 2),
763
createCharChange(11, 1, 11, 1, 11, 1, 11, 2),
764
createCharChange(12, 1, 12, 1, 12, 1, 12, 2),
765
createCharChange(13, 1, 13, 1, 13, 1, 13, 2),
766
createCharChange(14, 1, 14, 1, 14, 1, 14, 2),
767
createCharChange(15, 1, 15, 1, 15, 1, 15, 2),
768
createCharChange(16, 1, 16, 1, 16, 1, 16, 2),
769
createCharChange(17, 1, 17, 1, 17, 1, 17, 2),
770
createCharChange(18, 1, 18, 1, 18, 1, 18, 2),
771
createCharChange(19, 1, 19, 1, 19, 1, 19, 2),
772
createCharChange(20, 1, 20, 1, 20, 1, 20, 2),
773
createCharChange(21, 1, 21, 1, 21, 1, 21, 2),
774
createCharChange(22, 1, 22, 1, 22, 1, 22, 2),
775
createCharChange(23, 1, 23, 1, 23, 1, 23, 2),
776
createCharChange(24, 1, 24, 1, 24, 1, 24, 2),
777
createCharChange(25, 1, 25, 1, 25, 1, 25, 2),
778
createCharChange(26, 1, 26, 1, 26, 1, 26, 2),
779
createCharChange(27, 1, 27, 1, 27, 1, 27, 2),
780
]
781
)
782
// createLineInsertion(7, 11, 6)
783
];
784
assertDiff(original, modified, expected, true, true, false);
785
});
786
787
test('issue #43922', () => {
788
const original = [
789
' * `yarn [install]` -- Install project NPM dependencies. This is automatically done when you first create the project. You should only need to run this if you add dependencies in `package.json`.',
790
];
791
const modified = [
792
' * `yarn` -- Install project NPM dependencies. You should only need to run this if you add dependencies in `package.json`.',
793
];
794
const expected = [
795
createLineChange(
796
1, 1, 1, 1,
797
[
798
createCharChange(1, 9, 1, 19, 1, 9, 1, 9),
799
createCharChange(1, 58, 1, 120, 1, 48, 1, 48),
800
]
801
)
802
];
803
assertDiff(original, modified, expected, true, true, false);
804
});
805
806
test('issue #42751', () => {
807
const original = [
808
' 1',
809
' 2',
810
];
811
const modified = [
812
' 1',
813
' 3',
814
];
815
const expected = [
816
createLineChange(
817
2, 2, 2, 2,
818
[
819
createCharChange(2, 3, 2, 4, 2, 3, 2, 5)
820
]
821
)
822
];
823
assertDiff(original, modified, expected, true, true, false);
824
});
825
826
test('does not give character changes', () => {
827
const original = [
828
' 1',
829
' 2',
830
'A',
831
];
832
const modified = [
833
' 1',
834
' 3',
835
' A',
836
];
837
const expected = [
838
createLineChange(
839
2, 3, 2, 3
840
)
841
];
842
assertDiff(original, modified, expected, false, false, false);
843
});
844
845
test('issue #44422: Less than ideal diff results', () => {
846
const original = [
847
'export class C {',
848
'',
849
' public m1(): void {',
850
' {',
851
' //2',
852
' //3',
853
' //4',
854
' //5',
855
' //6',
856
' //7',
857
' //8',
858
' //9',
859
' //10',
860
' //11',
861
' //12',
862
' //13',
863
' //14',
864
' //15',
865
' //16',
866
' //17',
867
' //18',
868
' }',
869
' }',
870
'',
871
' public m2(): void {',
872
' if (a) {',
873
' if (b) {',
874
' //A1',
875
' //A2',
876
' //A3',
877
' //A4',
878
' //A5',
879
' //A6',
880
' //A7',
881
' //A8',
882
' }',
883
' }',
884
'',
885
' //A9',
886
' //A10',
887
' //A11',
888
' //A12',
889
' //A13',
890
' //A14',
891
' //A15',
892
' }',
893
'',
894
' public m3(): void {',
895
' if (a) {',
896
' //B1',
897
' }',
898
' //B2',
899
' //B3',
900
' }',
901
'',
902
' public m4(): boolean {',
903
' //1',
904
' //2',
905
' //3',
906
' //4',
907
' }',
908
'',
909
'}',
910
];
911
const modified = [
912
'export class C {',
913
'',
914
' constructor() {',
915
'',
916
'',
917
'',
918
'',
919
' }',
920
'',
921
' public m1(): void {',
922
' {',
923
' //2',
924
' //3',
925
' //4',
926
' //5',
927
' //6',
928
' //7',
929
' //8',
930
' //9',
931
' //10',
932
' //11',
933
' //12',
934
' //13',
935
' //14',
936
' //15',
937
' //16',
938
' //17',
939
' //18',
940
' }',
941
' }',
942
'',
943
' public m4(): boolean {',
944
' //1',
945
' //2',
946
' //3',
947
' //4',
948
' }',
949
'',
950
'}',
951
];
952
const expected = [
953
createLineChange(
954
2, 0, 3, 9
955
),
956
createLineChange(
957
25, 55, 31, 0
958
)
959
];
960
assertDiff(original, modified, expected, false, false, false);
961
});
962
963
test('gives preference to matching longer lines', () => {
964
const original = [
965
'A',
966
'A',
967
'BB',
968
'C',
969
];
970
const modified = [
971
'A',
972
'BB',
973
'A',
974
'D',
975
'E',
976
'A',
977
'C',
978
];
979
const expected = [
980
createLineChange(
981
2, 2, 1, 0
982
),
983
createLineChange(
984
3, 0, 3, 6
985
)
986
];
987
assertDiff(original, modified, expected, false, false, false);
988
});
989
990
test('issue #119051: gives preference to fewer diff hunks', () => {
991
const original = [
992
'1',
993
'',
994
'',
995
'2',
996
'',
997
];
998
const modified = [
999
'1',
1000
'',
1001
'1.5',
1002
'',
1003
'',
1004
'2',
1005
'',
1006
'3',
1007
'',
1008
];
1009
const expected = [
1010
createLineChange(
1011
2, 0, 3, 4
1012
),
1013
createLineChange(
1014
5, 0, 8, 9
1015
)
1016
];
1017
assertDiff(original, modified, expected, false, false, false);
1018
});
1019
1020
test('issue #121436: Diff chunk contains an unchanged line part 1', () => {
1021
const original = [
1022
'if (cond) {',
1023
' cmd',
1024
'}',
1025
];
1026
const modified = [
1027
'if (cond) {',
1028
' if (other_cond) {',
1029
' cmd',
1030
' }',
1031
'}',
1032
];
1033
const expected = [
1034
createLineChange(
1035
1, 0, 2, 2
1036
),
1037
createLineChange(
1038
2, 0, 4, 4
1039
)
1040
];
1041
assertDiff(original, modified, expected, false, false, true);
1042
});
1043
1044
test('issue #121436: Diff chunk contains an unchanged line part 2', () => {
1045
const original = [
1046
'if (cond) {',
1047
' cmd',
1048
'}',
1049
];
1050
const modified = [
1051
'if (cond) {',
1052
' if (other_cond) {',
1053
' cmd',
1054
' }',
1055
'}',
1056
];
1057
const expected = [
1058
createLineChange(
1059
1, 0, 2, 2
1060
),
1061
createLineChange(
1062
2, 2, 3, 3
1063
),
1064
createLineChange(
1065
2, 0, 4, 4
1066
)
1067
];
1068
assertDiff(original, modified, expected, false, false, false);
1069
});
1070
1071
test('issue #169552: Assertion error when having both leading and trailing whitespace diffs', () => {
1072
const original = [
1073
'if True:',
1074
' print(2)',
1075
];
1076
const modified = [
1077
'if True:',
1078
'\tprint(2) ',
1079
];
1080
const expected = [
1081
createLineChange(
1082
2, 2, 2, 2,
1083
[
1084
createCharChange(2, 1, 2, 5, 2, 1, 2, 2),
1085
createCharChange(2, 13, 2, 13, 2, 10, 2, 11),
1086
]
1087
),
1088
];
1089
assertDiff(original, modified, expected, true, false, false);
1090
});
1091
});
1092
1093