Path: blob/main/src/vs/editor/test/common/diff/diffComputer.test.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/4import assert from 'assert';5import { Constants } from '../../../../base/common/uint.js';6import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';7import { Range } from '../../../common/core/range.js';8import { DiffComputer, ICharChange, ILineChange } from '../../../common/diff/legacyLinesDiffComputer.js';9import { IIdentifiedSingleEditOperation, ITextModel } from '../../../common/model.js';10import { createTextModel } from '../testTextModel.js';1112function assertDiff(originalLines: string[], modifiedLines: string[], expectedChanges: ILineChange[], shouldComputeCharChanges: boolean = true, shouldPostProcessCharChanges: boolean = false, shouldIgnoreTrimWhitespace: boolean = false) {13const diffComputer = new DiffComputer(originalLines, modifiedLines, {14shouldComputeCharChanges,15shouldPostProcessCharChanges,16shouldIgnoreTrimWhitespace,17shouldMakePrettyDiff: true,18maxComputationTime: 019});20const changes = diffComputer.computeDiff().changes;2122const mapCharChange = (charChange: ICharChange) => {23return {24originalStartLineNumber: charChange.originalStartLineNumber,25originalStartColumn: charChange.originalStartColumn,26originalEndLineNumber: charChange.originalEndLineNumber,27originalEndColumn: charChange.originalEndColumn,28modifiedStartLineNumber: charChange.modifiedStartLineNumber,29modifiedStartColumn: charChange.modifiedStartColumn,30modifiedEndLineNumber: charChange.modifiedEndLineNumber,31modifiedEndColumn: charChange.modifiedEndColumn,32};33};3435const actual = changes.map((lineChange) => {36return {37originalStartLineNumber: lineChange.originalStartLineNumber,38originalEndLineNumber: lineChange.originalEndLineNumber,39modifiedStartLineNumber: lineChange.modifiedStartLineNumber,40modifiedEndLineNumber: lineChange.modifiedEndLineNumber,41charChanges: (lineChange.charChanges ? lineChange.charChanges.map(mapCharChange) : undefined)42};43});4445assert.deepStrictEqual(actual, expectedChanges);4647if (!shouldIgnoreTrimWhitespace) {48// The diffs should describe how to apply edits to the original text model to get to the modified text model.4950const modifiedTextModel = createTextModel(modifiedLines.join('\n'));51const expectedValue = modifiedTextModel.getValue();5253{54// Line changes:55const originalTextModel = createTextModel(originalLines.join('\n'));56originalTextModel.applyEdits(changes.map(c => getLineEdit(c, modifiedTextModel)));57assert.deepStrictEqual(originalTextModel.getValue(), expectedValue);58originalTextModel.dispose();59}6061if (shouldComputeCharChanges) {62// Char changes:63const originalTextModel = createTextModel(originalLines.join('\n'));64originalTextModel.applyEdits(changes.flatMap(c => getCharEdits(c, modifiedTextModel)));65assert.deepStrictEqual(originalTextModel.getValue(), expectedValue);66originalTextModel.dispose();67}6869modifiedTextModel.dispose();70}71}7273function getCharEdits(lineChange: ILineChange, modifiedTextModel: ITextModel): IIdentifiedSingleEditOperation[] {74if (!lineChange.charChanges) {75return [getLineEdit(lineChange, modifiedTextModel)];76}77return lineChange.charChanges.map(c => {78const originalRange = new Range(c.originalStartLineNumber, c.originalStartColumn, c.originalEndLineNumber, c.originalEndColumn);79const modifiedRange = new Range(c.modifiedStartLineNumber, c.modifiedStartColumn, c.modifiedEndLineNumber, c.modifiedEndColumn);80return {81range: originalRange,82text: modifiedTextModel.getValueInRange(modifiedRange)83};84});85}8687function getLineEdit(lineChange: ILineChange, modifiedTextModel: ITextModel): IIdentifiedSingleEditOperation {88let originalRange: LineRange;89if (lineChange.originalEndLineNumber === 0) {90// Insertion91originalRange = new LineRange(lineChange.originalStartLineNumber + 1, 0);92} else {93originalRange = new LineRange(lineChange.originalStartLineNumber, lineChange.originalEndLineNumber - lineChange.originalStartLineNumber + 1);94}9596let modifiedRange: LineRange;97if (lineChange.modifiedEndLineNumber === 0) {98// Deletion99modifiedRange = new LineRange(lineChange.modifiedStartLineNumber + 1, 0);100} else {101modifiedRange = new LineRange(lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber - lineChange.modifiedStartLineNumber + 1);102}103104const [r1, r2] = diffFromLineRanges(originalRange, modifiedRange);105return {106range: r1,107text: modifiedTextModel.getValueInRange(r2),108};109}110111function diffFromLineRanges(originalRange: LineRange, modifiedRange: LineRange): [Range, Range] {112if (originalRange.startLineNumber === 1 || modifiedRange.startLineNumber === 1) {113if (!originalRange.isEmpty && !modifiedRange.isEmpty) {114return [115new Range(116originalRange.startLineNumber,1171,118originalRange.endLineNumberExclusive - 1,119Constants.MAX_SAFE_SMALL_INTEGER,120),121new Range(122modifiedRange.startLineNumber,1231,124modifiedRange.endLineNumberExclusive - 1,125Constants.MAX_SAFE_SMALL_INTEGER,126)127];128}129130// When one of them is one and one of them is empty, the other cannot be the last line of the document131return [132new Range(133originalRange.startLineNumber,1341,135originalRange.endLineNumberExclusive,1361,137),138new Range(139modifiedRange.startLineNumber,1401,141modifiedRange.endLineNumberExclusive,1421,143)144];145}146147return [148new Range(149originalRange.startLineNumber - 1,150Constants.MAX_SAFE_SMALL_INTEGER,151originalRange.endLineNumberExclusive - 1,152Constants.MAX_SAFE_SMALL_INTEGER,153),154new Range(155modifiedRange.startLineNumber - 1,156Constants.MAX_SAFE_SMALL_INTEGER,157modifiedRange.endLineNumberExclusive - 1,158Constants.MAX_SAFE_SMALL_INTEGER,159)160];161}162163class LineRange {164public constructor(165public readonly startLineNumber: number,166public readonly lineCount: number167) { }168169public get isEmpty(): boolean {170return this.lineCount === 0;171}172173public get endLineNumberExclusive(): number {174return this.startLineNumber + this.lineCount;175}176}177178function createLineDeletion(startLineNumber: number, endLineNumber: number, modifiedLineNumber: number): ILineChange {179return {180originalStartLineNumber: startLineNumber,181originalEndLineNumber: endLineNumber,182modifiedStartLineNumber: modifiedLineNumber,183modifiedEndLineNumber: 0,184charChanges: undefined185};186}187188function createLineInsertion(startLineNumber: number, endLineNumber: number, originalLineNumber: number): ILineChange {189return {190originalStartLineNumber: originalLineNumber,191originalEndLineNumber: 0,192modifiedStartLineNumber: startLineNumber,193modifiedEndLineNumber: endLineNumber,194charChanges: undefined195};196}197198function createLineChange(originalStartLineNumber: number, originalEndLineNumber: number, modifiedStartLineNumber: number, modifiedEndLineNumber: number, charChanges?: ICharChange[]): ILineChange {199return {200originalStartLineNumber: originalStartLineNumber,201originalEndLineNumber: originalEndLineNumber,202modifiedStartLineNumber: modifiedStartLineNumber,203modifiedEndLineNumber: modifiedEndLineNumber,204charChanges: charChanges205};206}207208function createCharChange(209originalStartLineNumber: number, originalStartColumn: number, originalEndLineNumber: number, originalEndColumn: number,210modifiedStartLineNumber: number, modifiedStartColumn: number, modifiedEndLineNumber: number, modifiedEndColumn: number211) {212return {213originalStartLineNumber: originalStartLineNumber,214originalStartColumn: originalStartColumn,215originalEndLineNumber: originalEndLineNumber,216originalEndColumn: originalEndColumn,217modifiedStartLineNumber: modifiedStartLineNumber,218modifiedStartColumn: modifiedStartColumn,219modifiedEndLineNumber: modifiedEndLineNumber,220modifiedEndColumn: modifiedEndColumn221};222}223224suite('Editor Diff - DiffComputer', () => {225226ensureNoDisposablesAreLeakedInTestSuite();227228// ---- insertions229230test('one inserted line below', () => {231const original = ['line'];232const modified = ['line', 'new line'];233const expected = [createLineInsertion(2, 2, 1)];234assertDiff(original, modified, expected);235});236237test('two inserted lines below', () => {238const original = ['line'];239const modified = ['line', 'new line', 'another new line'];240const expected = [createLineInsertion(2, 3, 1)];241assertDiff(original, modified, expected);242});243244test('one inserted line above', () => {245const original = ['line'];246const modified = ['new line', 'line'];247const expected = [createLineInsertion(1, 1, 0)];248assertDiff(original, modified, expected);249});250251test('two inserted lines above', () => {252const original = ['line'];253const modified = ['new line', 'another new line', 'line'];254const expected = [createLineInsertion(1, 2, 0)];255assertDiff(original, modified, expected);256});257258test('one inserted line in middle', () => {259const original = ['line1', 'line2', 'line3', 'line4'];260const modified = ['line1', 'line2', 'new line', 'line3', 'line4'];261const expected = [createLineInsertion(3, 3, 2)];262assertDiff(original, modified, expected);263});264265test('two inserted lines in middle', () => {266const original = ['line1', 'line2', 'line3', 'line4'];267const modified = ['line1', 'line2', 'new line', 'another new line', 'line3', 'line4'];268const expected = [createLineInsertion(3, 4, 2)];269assertDiff(original, modified, expected);270});271272test('two inserted lines in middle interrupted', () => {273const original = ['line1', 'line2', 'line3', 'line4'];274const modified = ['line1', 'line2', 'new line', 'line3', 'another new line', 'line4'];275const expected = [createLineInsertion(3, 3, 2), createLineInsertion(5, 5, 3)];276assertDiff(original, modified, expected);277});278279// ---- deletions280281test('one deleted line below', () => {282const original = ['line', 'new line'];283const modified = ['line'];284const expected = [createLineDeletion(2, 2, 1)];285assertDiff(original, modified, expected);286});287288test('two deleted lines below', () => {289const original = ['line', 'new line', 'another new line'];290const modified = ['line'];291const expected = [createLineDeletion(2, 3, 1)];292assertDiff(original, modified, expected);293});294295test('one deleted lines above', () => {296const original = ['new line', 'line'];297const modified = ['line'];298const expected = [createLineDeletion(1, 1, 0)];299assertDiff(original, modified, expected);300});301302test('two deleted lines above', () => {303const original = ['new line', 'another new line', 'line'];304const modified = ['line'];305const expected = [createLineDeletion(1, 2, 0)];306assertDiff(original, modified, expected);307});308309test('one deleted line in middle', () => {310const original = ['line1', 'line2', 'new line', 'line3', 'line4'];311const modified = ['line1', 'line2', 'line3', 'line4'];312const expected = [createLineDeletion(3, 3, 2)];313assertDiff(original, modified, expected);314});315316test('two deleted lines in middle', () => {317const original = ['line1', 'line2', 'new line', 'another new line', 'line3', 'line4'];318const modified = ['line1', 'line2', 'line3', 'line4'];319const expected = [createLineDeletion(3, 4, 2)];320assertDiff(original, modified, expected);321});322323test('two deleted lines in middle interrupted', () => {324const original = ['line1', 'line2', 'new line', 'line3', 'another new line', 'line4'];325const modified = ['line1', 'line2', 'line3', 'line4'];326const expected = [createLineDeletion(3, 3, 2), createLineDeletion(5, 5, 3)];327assertDiff(original, modified, expected);328});329330// ---- changes331332test('one line changed: chars inserted at the end', () => {333const original = ['line'];334const modified = ['line changed'];335const expected = [336createLineChange(1, 1, 1, 1, [337createCharChange(1, 5, 1, 5, 1, 5, 1, 13)338])339];340assertDiff(original, modified, expected);341});342343test('one line changed: chars inserted at the beginning', () => {344const original = ['line'];345const modified = ['my line'];346const expected = [347createLineChange(1, 1, 1, 1, [348createCharChange(1, 1, 1, 1, 1, 1, 1, 4)349])350];351assertDiff(original, modified, expected);352});353354test('one line changed: chars inserted in the middle', () => {355const original = ['abba'];356const modified = ['abzzba'];357const expected = [358createLineChange(1, 1, 1, 1, [359createCharChange(1, 3, 1, 3, 1, 3, 1, 5)360])361];362assertDiff(original, modified, expected);363});364365test('one line changed: chars inserted in the middle (two spots)', () => {366const original = ['abba'];367const modified = ['abzzbzza'];368const expected = [369createLineChange(1, 1, 1, 1, [370createCharChange(1, 3, 1, 3, 1, 3, 1, 5),371createCharChange(1, 4, 1, 4, 1, 6, 1, 8)372])373];374assertDiff(original, modified, expected);375});376377test('one line changed: chars deleted 1', () => {378const original = ['abcdefg'];379const modified = ['abcfg'];380const expected = [381createLineChange(1, 1, 1, 1, [382createCharChange(1, 4, 1, 6, 1, 4, 1, 4)383])384];385assertDiff(original, modified, expected);386});387388test('one line changed: chars deleted 2', () => {389const original = ['abcdefg'];390const modified = ['acfg'];391const expected = [392createLineChange(1, 1, 1, 1, [393createCharChange(1, 2, 1, 3, 1, 2, 1, 2),394createCharChange(1, 4, 1, 6, 1, 3, 1, 3)395])396];397assertDiff(original, modified, expected);398});399400test('two lines changed 1', () => {401const original = ['abcd', 'efgh'];402const modified = ['abcz'];403const expected = [404createLineChange(1, 2, 1, 1, [405createCharChange(1, 4, 2, 5, 1, 4, 1, 5)406])407];408assertDiff(original, modified, expected);409});410411test('two lines changed 2', () => {412const original = ['foo', 'abcd', 'efgh', 'BAR'];413const modified = ['foo', 'abcz', 'BAR'];414const expected = [415createLineChange(2, 3, 2, 2, [416createCharChange(2, 4, 3, 5, 2, 4, 2, 5)417])418];419assertDiff(original, modified, expected);420});421422test('two lines changed 3', () => {423const original = ['foo', 'abcd', 'efgh', 'BAR'];424const modified = ['foo', 'abcz', 'zzzzefgh', 'BAR'];425const expected = [426createLineChange(2, 3, 2, 3, [427createCharChange(2, 4, 2, 5, 2, 4, 2, 5),428createCharChange(3, 1, 3, 1, 3, 1, 3, 5)429])430];431assertDiff(original, modified, expected);432});433434test('two lines changed 4', () => {435const original = ['abc'];436const modified = ['', '', 'axc', ''];437const expected = [438createLineChange(1, 1, 1, 4, [439createCharChange(1, 1, 1, 1, 1, 1, 3, 1),440createCharChange(1, 2, 1, 3, 3, 2, 3, 3),441createCharChange(1, 4, 1, 4, 3, 4, 4, 1)442])443];444assertDiff(original, modified, expected);445});446447test('empty original sequence in char diff', () => {448const original = ['abc', '', 'xyz'];449const modified = ['abc', 'qwe', 'rty', 'xyz'];450const expected = [451createLineChange(2, 2, 2, 3)452];453assertDiff(original, modified, expected);454});455456test('three lines changed', () => {457const original = ['foo', 'abcd', 'efgh', 'BAR'];458const modified = ['foo', 'zzzefgh', 'xxx', 'BAR'];459const expected = [460createLineChange(2, 3, 2, 3, [461createCharChange(2, 1, 3, 1, 2, 1, 2, 4),462createCharChange(3, 5, 3, 5, 2, 8, 3, 4),463])464];465assertDiff(original, modified, expected);466});467468test('big change part 1', () => {469const original = ['foo', 'abcd', 'efgh', 'BAR'];470const modified = ['hello', 'foo', 'zzzefgh', 'xxx', 'BAR'];471const expected = [472createLineInsertion(1, 1, 0),473createLineChange(2, 3, 3, 4, [474createCharChange(2, 1, 3, 1, 3, 1, 3, 4),475createCharChange(3, 5, 3, 5, 3, 8, 4, 4)476])477];478assertDiff(original, modified, expected);479});480481test('big change part 2', () => {482const original = ['foo', 'abcd', 'efgh', 'BAR', 'RAB'];483const modified = ['hello', 'foo', 'zzzefgh', 'xxx', 'BAR'];484const expected = [485createLineInsertion(1, 1, 0),486createLineChange(2, 3, 3, 4, [487createCharChange(2, 1, 3, 1, 3, 1, 3, 4),488createCharChange(3, 5, 3, 5, 3, 8, 4, 4)489]),490createLineDeletion(5, 5, 5)491];492assertDiff(original, modified, expected);493});494495test('char change postprocessing merges', () => {496const original = ['abba'];497const modified = ['azzzbzzzbzzza'];498const expected = [499createLineChange(1, 1, 1, 1, [500createCharChange(1, 2, 1, 4, 1, 2, 1, 13)501])502];503assertDiff(original, modified, expected, true, true);504});505506test('ignore trim whitespace', () => {507const original = ['\t\t foo ', 'abcd', 'efgh', '\t\t BAR\t\t'];508const modified = [' hello\t', '\t foo \t', 'zzzefgh', 'xxx', ' BAR \t'];509const expected = [510createLineInsertion(1, 1, 0),511createLineChange(2, 3, 3, 4, [512createCharChange(2, 1, 2, 5, 3, 1, 3, 4),513createCharChange(3, 5, 3, 5, 4, 1, 4, 4)514])515];516assertDiff(original, modified, expected, true, false, true);517});518519test('issue #12122 r.hasOwnProperty is not a function', () => {520const original = ['hasOwnProperty'];521const modified = ['hasOwnProperty', 'and another line'];522const expected = [523createLineInsertion(2, 2, 1)524];525assertDiff(original, modified, expected);526});527528test('empty diff 1', () => {529const original = [''];530const modified = ['something'];531const expected = [532createLineChange(1, 1, 1, 1, undefined)533];534assertDiff(original, modified, expected, true, false, true);535});536537test('empty diff 2', () => {538const original = [''];539const modified = ['something', 'something else'];540const expected = [541createLineChange(1, 1, 1, 2, undefined)542];543assertDiff(original, modified, expected, true, false, true);544});545546test('empty diff 3', () => {547const original = ['something', 'something else'];548const modified = [''];549const expected = [550createLineChange(1, 2, 1, 1, undefined)551];552assertDiff(original, modified, expected, true, false, true);553});554555test('empty diff 4', () => {556const original = ['something'];557const modified = [''];558const expected = [559createLineChange(1, 1, 1, 1, undefined)560];561assertDiff(original, modified, expected, true, false, true);562});563564test('empty diff 5', () => {565const original = [''];566const modified = [''];567const expected: ILineChange[] = [];568assertDiff(original, modified, expected, true, false, true);569});570571test('pretty diff 1', () => {572const original = [573'suite(function () {',574' test1() {',575' assert.ok(true);',576' }',577'',578' test2() {',579' assert.ok(true);',580' }',581'});',582'',583];584const modified = [585'// An insertion',586'suite(function () {',587' test1() {',588' assert.ok(true);',589' }',590'',591' test2() {',592' assert.ok(true);',593' }',594'',595' test3() {',596' assert.ok(true);',597' }',598'});',599'',600];601const expected = [602createLineInsertion(1, 1, 0),603createLineInsertion(10, 13, 8)604];605assertDiff(original, modified, expected, true, false, true);606});607608test('pretty diff 2', () => {609const original = [610'// Just a comment',611'',612'function compute(a, b, c, d) {',613' if (a) {',614' if (b) {',615' if (c) {',616' return 5;',617' }',618' }',619' // These next lines will be deleted',620' if (d) {',621' return -1;',622' }',623' return 0;',624' }',625'}',626];627const modified = [628'// Here is an inserted line',629'// and another inserted line',630'// and another one',631'// Just a comment',632'',633'function compute(a, b, c, d) {',634' if (a) {',635' if (b) {',636' if (c) {',637' return 5;',638' }',639' }',640' return 0;',641' }',642'}',643];644const expected = [645createLineInsertion(1, 3, 0),646createLineDeletion(10, 13, 12),647];648assertDiff(original, modified, expected, true, false, true);649});650651test('pretty diff 3', () => {652const original = [653'class A {',654' /**',655' * m1',656' */',657' method1() {}',658'',659' /**',660' * m3',661' */',662' method3() {}',663'}',664];665const modified = [666'class A {',667' /**',668' * m1',669' */',670' method1() {}',671'',672' /**',673' * m2',674' */',675' method2() {}',676'',677' /**',678' * m3',679' */',680' method3() {}',681'}',682];683const expected = [684createLineInsertion(7, 11, 6)685];686assertDiff(original, modified, expected, true, false, true);687});688689test('issue #23636', () => {690const original = [691'if(!TextDrawLoad[playerid])',692'{',693'',694' TextDrawHideForPlayer(playerid,TD_AppleJob[3]);',695' TextDrawHideForPlayer(playerid,TD_AppleJob[4]);',696' if(!AppleJobTreesType[AppleJobTreesPlayerNum[playerid]])',697' {',698' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[5+i]);',699' }',700' else',701' {',702' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[15+i]);',703' }',704'}',705'else',706'{',707' TextDrawHideForPlayer(playerid,TD_AppleJob[3]);',708' TextDrawHideForPlayer(playerid,TD_AppleJob[27]);',709' if(!AppleJobTreesType[AppleJobTreesPlayerNum[playerid]])',710' {',711' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[28+i]);',712' }',713' else',714' {',715' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[38+i]);',716' }',717'}',718];719const modified = [720' if(!TextDrawLoad[playerid])',721' {',722' ',723' TextDrawHideForPlayer(playerid,TD_AppleJob[3]);',724' TextDrawHideForPlayer(playerid,TD_AppleJob[4]);',725' if(!AppleJobTreesType[AppleJobTreesPlayerNum[playerid]])',726' {',727' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[5+i]);',728' }',729' else',730' {',731' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[15+i]);',732' }',733' }',734' else',735' {',736' TextDrawHideForPlayer(playerid,TD_AppleJob[3]);',737' TextDrawHideForPlayer(playerid,TD_AppleJob[27]);',738' if(!AppleJobTreesType[AppleJobTreesPlayerNum[playerid]])',739' {',740' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[28+i]);',741' }',742' else',743' {',744' for(new i=0;i<10;i++) if(StatusTD_AppleJobApples[playerid][i]) TextDrawHideForPlayer(playerid,TD_AppleJob[38+i]);',745' }',746' }',747];748const expected = [749createLineChange(7501, 27, 1, 27,751[752createCharChange(1, 1, 1, 1, 1, 1, 1, 2),753createCharChange(2, 1, 2, 1, 2, 1, 2, 2),754createCharChange(3, 1, 3, 1, 3, 1, 3, 2),755createCharChange(4, 1, 4, 1, 4, 1, 4, 2),756createCharChange(5, 1, 5, 1, 5, 1, 5, 2),757createCharChange(6, 1, 6, 1, 6, 1, 6, 2),758createCharChange(7, 1, 7, 1, 7, 1, 7, 2),759createCharChange(8, 1, 8, 1, 8, 1, 8, 2),760createCharChange(9, 1, 9, 1, 9, 1, 9, 2),761createCharChange(10, 1, 10, 1, 10, 1, 10, 2),762createCharChange(11, 1, 11, 1, 11, 1, 11, 2),763createCharChange(12, 1, 12, 1, 12, 1, 12, 2),764createCharChange(13, 1, 13, 1, 13, 1, 13, 2),765createCharChange(14, 1, 14, 1, 14, 1, 14, 2),766createCharChange(15, 1, 15, 1, 15, 1, 15, 2),767createCharChange(16, 1, 16, 1, 16, 1, 16, 2),768createCharChange(17, 1, 17, 1, 17, 1, 17, 2),769createCharChange(18, 1, 18, 1, 18, 1, 18, 2),770createCharChange(19, 1, 19, 1, 19, 1, 19, 2),771createCharChange(20, 1, 20, 1, 20, 1, 20, 2),772createCharChange(21, 1, 21, 1, 21, 1, 21, 2),773createCharChange(22, 1, 22, 1, 22, 1, 22, 2),774createCharChange(23, 1, 23, 1, 23, 1, 23, 2),775createCharChange(24, 1, 24, 1, 24, 1, 24, 2),776createCharChange(25, 1, 25, 1, 25, 1, 25, 2),777createCharChange(26, 1, 26, 1, 26, 1, 26, 2),778createCharChange(27, 1, 27, 1, 27, 1, 27, 2),779]780)781// createLineInsertion(7, 11, 6)782];783assertDiff(original, modified, expected, true, true, false);784});785786test('issue #43922', () => {787const original = [788' * `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`.',789];790const modified = [791' * `yarn` -- Install project NPM dependencies. You should only need to run this if you add dependencies in `package.json`.',792];793const expected = [794createLineChange(7951, 1, 1, 1,796[797createCharChange(1, 9, 1, 19, 1, 9, 1, 9),798createCharChange(1, 58, 1, 120, 1, 48, 1, 48),799]800)801];802assertDiff(original, modified, expected, true, true, false);803});804805test('issue #42751', () => {806const original = [807' 1',808' 2',809];810const modified = [811' 1',812' 3',813];814const expected = [815createLineChange(8162, 2, 2, 2,817[818createCharChange(2, 3, 2, 4, 2, 3, 2, 5)819]820)821];822assertDiff(original, modified, expected, true, true, false);823});824825test('does not give character changes', () => {826const original = [827' 1',828' 2',829'A',830];831const modified = [832' 1',833' 3',834' A',835];836const expected = [837createLineChange(8382, 3, 2, 3839)840];841assertDiff(original, modified, expected, false, false, false);842});843844test('issue #44422: Less than ideal diff results', () => {845const original = [846'export class C {',847'',848' public m1(): void {',849' {',850' //2',851' //3',852' //4',853' //5',854' //6',855' //7',856' //8',857' //9',858' //10',859' //11',860' //12',861' //13',862' //14',863' //15',864' //16',865' //17',866' //18',867' }',868' }',869'',870' public m2(): void {',871' if (a) {',872' if (b) {',873' //A1',874' //A2',875' //A3',876' //A4',877' //A5',878' //A6',879' //A7',880' //A8',881' }',882' }',883'',884' //A9',885' //A10',886' //A11',887' //A12',888' //A13',889' //A14',890' //A15',891' }',892'',893' public m3(): void {',894' if (a) {',895' //B1',896' }',897' //B2',898' //B3',899' }',900'',901' public m4(): boolean {',902' //1',903' //2',904' //3',905' //4',906' }',907'',908'}',909];910const modified = [911'export class C {',912'',913' constructor() {',914'',915'',916'',917'',918' }',919'',920' public m1(): void {',921' {',922' //2',923' //3',924' //4',925' //5',926' //6',927' //7',928' //8',929' //9',930' //10',931' //11',932' //12',933' //13',934' //14',935' //15',936' //16',937' //17',938' //18',939' }',940' }',941'',942' public m4(): boolean {',943' //1',944' //2',945' //3',946' //4',947' }',948'',949'}',950];951const expected = [952createLineChange(9532, 0, 3, 9954),955createLineChange(95625, 55, 31, 0957)958];959assertDiff(original, modified, expected, false, false, false);960});961962test('gives preference to matching longer lines', () => {963const original = [964'A',965'A',966'BB',967'C',968];969const modified = [970'A',971'BB',972'A',973'D',974'E',975'A',976'C',977];978const expected = [979createLineChange(9802, 2, 1, 0981),982createLineChange(9833, 0, 3, 6984)985];986assertDiff(original, modified, expected, false, false, false);987});988989test('issue #119051: gives preference to fewer diff hunks', () => {990const original = [991'1',992'',993'',994'2',995'',996];997const modified = [998'1',999'',1000'1.5',1001'',1002'',1003'2',1004'',1005'3',1006'',1007];1008const expected = [1009createLineChange(10102, 0, 3, 41011),1012createLineChange(10135, 0, 8, 91014)1015];1016assertDiff(original, modified, expected, false, false, false);1017});10181019test('issue #121436: Diff chunk contains an unchanged line part 1', () => {1020const original = [1021'if (cond) {',1022' cmd',1023'}',1024];1025const modified = [1026'if (cond) {',1027' if (other_cond) {',1028' cmd',1029' }',1030'}',1031];1032const expected = [1033createLineChange(10341, 0, 2, 21035),1036createLineChange(10372, 0, 4, 41038)1039];1040assertDiff(original, modified, expected, false, false, true);1041});10421043test('issue #121436: Diff chunk contains an unchanged line part 2', () => {1044const original = [1045'if (cond) {',1046' cmd',1047'}',1048];1049const modified = [1050'if (cond) {',1051' if (other_cond) {',1052' cmd',1053' }',1054'}',1055];1056const expected = [1057createLineChange(10581, 0, 2, 21059),1060createLineChange(10612, 2, 3, 31062),1063createLineChange(10642, 0, 4, 41065)1066];1067assertDiff(original, modified, expected, false, false, false);1068});10691070test('issue #169552: Assertion error when having both leading and trailing whitespace diffs', () => {1071const original = [1072'if True:',1073' print(2)',1074];1075const modified = [1076'if True:',1077'\tprint(2) ',1078];1079const expected = [1080createLineChange(10812, 2, 2, 2,1082[1083createCharChange(2, 1, 2, 5, 2, 1, 2, 2),1084createCharChange(2, 13, 2, 13, 2, 10, 2, 11),1085]1086),1087];1088assertDiff(original, modified, expected, true, false, false);1089});1090});109110921093