Path: blob/main/src/vs/editor/test/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.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*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { WordCharacterClassifier } from '../../../../common/core/wordCharacterClassifier.js';7import { Position } from '../../../../common/core/position.js';8import { Range } from '../../../../common/core/range.js';9import { DefaultEndOfLine, ITextSnapshot, SearchData } from '../../../../common/model.js';10import { PieceTreeBase } from '../../../../common/model/pieceTreeTextBuffer/pieceTreeBase.js';11import { PieceTreeTextBuffer } from '../../../../common/model/pieceTreeTextBuffer/pieceTreeTextBuffer.js';12import { PieceTreeTextBufferBuilder } from '../../../../common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder.js';13import { NodeColor, SENTINEL, TreeNode } from '../../../../common/model/pieceTreeTextBuffer/rbTreeBase.js';14import { createTextModel } from '../../testTextModel.js';15import { splitLines } from '../../../../../base/common/strings.js';16import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';1718const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n';1920function randomChar() {21return alphabet[randomInt(alphabet.length)];22}2324function randomInt(bound: number) {25return Math.floor(Math.random() * bound);26}2728function randomStr(len: number) {29if (len === null) {30len = 10;31}32return (function () {33let j, ref;34const results = [];35for (36j = 1, ref = len;371 <= ref ? j < ref : j > ref;381 <= ref ? j++ : j--39) {40results.push(randomChar());41}42return results;43})().join('');44}4546function trimLineFeed(text: string): string {47if (text.length === 0) {48return text;49}5051if (text.length === 1) {52if (53text.charCodeAt(text.length - 1) === 10 ||54text.charCodeAt(text.length - 1) === 1355) {56return '';57}58return text;59}6061if (text.charCodeAt(text.length - 1) === 10) {62if (text.charCodeAt(text.length - 2) === 13) {63return text.slice(0, -2);64}65return text.slice(0, -1);66}6768if (text.charCodeAt(text.length - 1) === 13) {69return text.slice(0, -1);70}7172return text;73}7475//#region Assertion7677function testLinesContent(str: string, pieceTable: PieceTreeBase) {78const lines = splitLines(str);79assert.strictEqual(pieceTable.getLineCount(), lines.length);80assert.strictEqual(pieceTable.getLinesRawContent(), str);81for (let i = 0; i < lines.length; i++) {82assert.strictEqual(pieceTable.getLineContent(i + 1), lines[i]);83assert.strictEqual(84trimLineFeed(85pieceTable.getValueInRange(86new Range(87i + 1,881,89i + 1,90lines[i].length + (i === lines.length - 1 ? 1 : 2)91)92)93),94lines[i]95);96}97}9899function testLineStarts(str: string, pieceTable: PieceTreeBase) {100const lineStarts = [0];101102// Reset regex to search from the beginning103const _regex = new RegExp(/\r\n|\r|\n/g);104_regex.lastIndex = 0;105let prevMatchStartIndex = -1;106let prevMatchLength = 0;107108let m: RegExpExecArray | null;109do {110if (prevMatchStartIndex + prevMatchLength === str.length) {111// Reached the end of the line112break;113}114115m = _regex.exec(str);116if (!m) {117break;118}119120const matchStartIndex = m.index;121const matchLength = m[0].length;122123if (124matchStartIndex === prevMatchStartIndex &&125matchLength === prevMatchLength126) {127// Exit early if the regex matches the same range twice128break;129}130131prevMatchStartIndex = matchStartIndex;132prevMatchLength = matchLength;133134lineStarts.push(matchStartIndex + matchLength);135} while (m);136137for (let i = 0; i < lineStarts.length; i++) {138assert.deepStrictEqual(139pieceTable.getPositionAt(lineStarts[i]),140new Position(i + 1, 1)141);142assert.strictEqual(pieceTable.getOffsetAt(i + 1, 1), lineStarts[i]);143}144145for (let i = 1; i < lineStarts.length; i++) {146const pos = pieceTable.getPositionAt(lineStarts[i] - 1);147assert.strictEqual(148pieceTable.getOffsetAt(pos.lineNumber, pos.column),149lineStarts[i] - 1150);151}152}153154function createTextBuffer(val: string[], normalizeEOL: boolean = true): PieceTreeTextBuffer {155const bufferBuilder = new PieceTreeTextBufferBuilder();156for (const chunk of val) {157bufferBuilder.acceptChunk(chunk);158}159const factory = bufferBuilder.finish(normalizeEOL);160return (<PieceTreeTextBuffer>factory.create(DefaultEndOfLine.LF).textBuffer);161}162163function assertTreeInvariants(T: PieceTreeBase): void {164assert(SENTINEL.color === NodeColor.Black);165assert(SENTINEL.parent === SENTINEL);166assert(SENTINEL.left === SENTINEL);167assert(SENTINEL.right === SENTINEL);168assert(SENTINEL.size_left === 0);169assert(SENTINEL.lf_left === 0);170assertValidTree(T);171}172173function depth(n: TreeNode): number {174if (n === SENTINEL) {175// The leafs are black176return 1;177}178assert(depth(n.left) === depth(n.right));179return (n.color === NodeColor.Black ? 1 : 0) + depth(n.left);180}181182function assertValidNode(n: TreeNode): { size: number; lf_cnt: number } {183if (n === SENTINEL) {184return { size: 0, lf_cnt: 0 };185}186187const l = n.left;188const r = n.right;189190if (n.color === NodeColor.Red) {191assert(l.color === NodeColor.Black);192assert(r.color === NodeColor.Black);193}194195const actualLeft = assertValidNode(l);196assert(actualLeft.lf_cnt === n.lf_left);197assert(actualLeft.size === n.size_left);198const actualRight = assertValidNode(r);199200return { size: n.size_left + n.piece.length + actualRight.size, lf_cnt: n.lf_left + n.piece.lineFeedCnt + actualRight.lf_cnt };201}202203function assertValidTree(T: PieceTreeBase): void {204if (T.root === SENTINEL) {205return;206}207assert(T.root.color === NodeColor.Black);208assert(depth(T.root.left) === depth(T.root.right));209assertValidNode(T.root);210}211212//#endregion213214suite('inserts and deletes', () => {215const ds = ensureNoDisposablesAreLeakedInTestSuite();216217test('basic insert/delete', () => {218const pieceTree = createTextBuffer([219'This is a document with some text.'220]);221ds.add(pieceTree);222const pieceTable = pieceTree.getPieceTree();223224pieceTable.insert(34, 'This is some more text to insert at offset 34.');225assert.strictEqual(226pieceTable.getLinesRawContent(),227'This is a document with some text.This is some more text to insert at offset 34.'228);229pieceTable.delete(42, 5);230assert.strictEqual(231pieceTable.getLinesRawContent(),232'This is a document with some text.This is more text to insert at offset 34.'233);234assertTreeInvariants(pieceTable);235});236237test('more inserts', () => {238const pieceTree = createTextBuffer(['']);239ds.add(pieceTree);240const pt = pieceTree.getPieceTree();241pt.insert(0, 'AAA');242assert.strictEqual(pt.getLinesRawContent(), 'AAA');243pt.insert(0, 'BBB');244assert.strictEqual(pt.getLinesRawContent(), 'BBBAAA');245pt.insert(6, 'CCC');246assert.strictEqual(pt.getLinesRawContent(), 'BBBAAACCC');247pt.insert(5, 'DDD');248assert.strictEqual(pt.getLinesRawContent(), 'BBBAADDDACCC');249assertTreeInvariants(pt);250});251252test('more deletes', () => {253const pieceTree = createTextBuffer(['012345678']);254ds.add(pieceTree);255const pt = pieceTree.getPieceTree();256257pt.delete(8, 1);258assert.strictEqual(pt.getLinesRawContent(), '01234567');259pt.delete(0, 1);260assert.strictEqual(pt.getLinesRawContent(), '1234567');261pt.delete(5, 1);262assert.strictEqual(pt.getLinesRawContent(), '123457');263pt.delete(5, 1);264assert.strictEqual(pt.getLinesRawContent(), '12345');265pt.delete(0, 5);266assert.strictEqual(pt.getLinesRawContent(), '');267assertTreeInvariants(pt);268});269270test('random test 1', () => {271let str = '';272const pieceTree = createTextBuffer(['']);273ds.add(pieceTree);274const pieceTable = pieceTree.getPieceTree();275276pieceTable.insert(0, 'ceLPHmFzvCtFeHkCBej ');277str = str.substring(0, 0) + 'ceLPHmFzvCtFeHkCBej ' + str.substring(0);278assert.strictEqual(pieceTable.getLinesRawContent(), str);279pieceTable.insert(8, 'gDCEfNYiBUNkSwtvB K ');280str = str.substring(0, 8) + 'gDCEfNYiBUNkSwtvB K ' + str.substring(8);281assert.strictEqual(pieceTable.getLinesRawContent(), str);282pieceTable.insert(38, 'cyNcHxjNPPoehBJldLS ');283str = str.substring(0, 38) + 'cyNcHxjNPPoehBJldLS ' + str.substring(38);284assert.strictEqual(pieceTable.getLinesRawContent(), str);285pieceTable.insert(59, 'ejMx\nOTgWlbpeDExjOk ');286str = str.substring(0, 59) + 'ejMx\nOTgWlbpeDExjOk ' + str.substring(59);287288assert.strictEqual(pieceTable.getLinesRawContent(), str);289assertTreeInvariants(pieceTable);290});291292test('random test 2', () => {293let str = '';294const pieceTree = createTextBuffer(['']);295ds.add(pieceTree);296const pieceTable = pieceTree.getPieceTree();297pieceTable.insert(0, 'VgPG ');298str = str.substring(0, 0) + 'VgPG ' + str.substring(0);299pieceTable.insert(2, 'DdWF ');300str = str.substring(0, 2) + 'DdWF ' + str.substring(2);301pieceTable.insert(0, 'hUJc ');302str = str.substring(0, 0) + 'hUJc ' + str.substring(0);303pieceTable.insert(8, 'lQEq ');304str = str.substring(0, 8) + 'lQEq ' + str.substring(8);305pieceTable.insert(10, 'Gbtp ');306str = str.substring(0, 10) + 'Gbtp ' + str.substring(10);307308assert.strictEqual(pieceTable.getLinesRawContent(), str);309assertTreeInvariants(pieceTable);310});311312test('random test 3', () => {313let str = '';314const pieceTree = createTextBuffer(['']);315ds.add(pieceTree);316const pieceTable = pieceTree.getPieceTree();317pieceTable.insert(0, 'gYSz');318str = str.substring(0, 0) + 'gYSz' + str.substring(0);319pieceTable.insert(1, 'mDQe');320str = str.substring(0, 1) + 'mDQe' + str.substring(1);321pieceTable.insert(1, 'DTMQ');322str = str.substring(0, 1) + 'DTMQ' + str.substring(1);323pieceTable.insert(2, 'GGZB');324str = str.substring(0, 2) + 'GGZB' + str.substring(2);325pieceTable.insert(12, 'wXpq');326str = str.substring(0, 12) + 'wXpq' + str.substring(12);327assert.strictEqual(pieceTable.getLinesRawContent(), str);328});329330test('random delete 1', () => {331let str = '';332const pieceTree = createTextBuffer(['']);333ds.add(pieceTree);334const pieceTable = pieceTree.getPieceTree();335336pieceTable.insert(0, 'vfb');337str = str.substring(0, 0) + 'vfb' + str.substring(0);338assert.strictEqual(pieceTable.getLinesRawContent(), str);339pieceTable.insert(0, 'zRq');340str = str.substring(0, 0) + 'zRq' + str.substring(0);341assert.strictEqual(pieceTable.getLinesRawContent(), str);342343pieceTable.delete(5, 1);344str = str.substring(0, 5) + str.substring(5 + 1);345assert.strictEqual(pieceTable.getLinesRawContent(), str);346347pieceTable.insert(1, 'UNw');348str = str.substring(0, 1) + 'UNw' + str.substring(1);349assert.strictEqual(pieceTable.getLinesRawContent(), str);350351pieceTable.delete(4, 3);352str = str.substring(0, 4) + str.substring(4 + 3);353assert.strictEqual(pieceTable.getLinesRawContent(), str);354355pieceTable.delete(1, 4);356str = str.substring(0, 1) + str.substring(1 + 4);357assert.strictEqual(pieceTable.getLinesRawContent(), str);358359pieceTable.delete(0, 1);360str = str.substring(0, 0) + str.substring(0 + 1);361assert.strictEqual(pieceTable.getLinesRawContent(), str);362assertTreeInvariants(pieceTable);363});364365test('random delete 2', () => {366let str = '';367const pieceTree = createTextBuffer(['']);368ds.add(pieceTree);369const pieceTable = pieceTree.getPieceTree();370371pieceTable.insert(0, 'IDT');372str = str.substring(0, 0) + 'IDT' + str.substring(0);373pieceTable.insert(3, 'wwA');374str = str.substring(0, 3) + 'wwA' + str.substring(3);375pieceTable.insert(3, 'Gnr');376str = str.substring(0, 3) + 'Gnr' + str.substring(3);377pieceTable.delete(6, 3);378str = str.substring(0, 6) + str.substring(6 + 3);379pieceTable.insert(4, 'eHp');380str = str.substring(0, 4) + 'eHp' + str.substring(4);381pieceTable.insert(1, 'UAi');382str = str.substring(0, 1) + 'UAi' + str.substring(1);383pieceTable.insert(2, 'FrR');384str = str.substring(0, 2) + 'FrR' + str.substring(2);385pieceTable.delete(6, 7);386str = str.substring(0, 6) + str.substring(6 + 7);387pieceTable.delete(3, 5);388str = str.substring(0, 3) + str.substring(3 + 5);389assert.strictEqual(pieceTable.getLinesRawContent(), str);390assertTreeInvariants(pieceTable);391});392393test('random delete 3', () => {394let str = '';395const pieceTree = createTextBuffer(['']);396ds.add(pieceTree);397const pieceTable = pieceTree.getPieceTree();398pieceTable.insert(0, 'PqM');399str = str.substring(0, 0) + 'PqM' + str.substring(0);400pieceTable.delete(1, 2);401str = str.substring(0, 1) + str.substring(1 + 2);402pieceTable.insert(1, 'zLc');403str = str.substring(0, 1) + 'zLc' + str.substring(1);404pieceTable.insert(0, 'MEX');405str = str.substring(0, 0) + 'MEX' + str.substring(0);406pieceTable.insert(0, 'jZh');407str = str.substring(0, 0) + 'jZh' + str.substring(0);408pieceTable.insert(8, 'GwQ');409str = str.substring(0, 8) + 'GwQ' + str.substring(8);410pieceTable.delete(5, 6);411str = str.substring(0, 5) + str.substring(5 + 6);412pieceTable.insert(4, 'ktw');413str = str.substring(0, 4) + 'ktw' + str.substring(4);414pieceTable.insert(5, 'GVu');415str = str.substring(0, 5) + 'GVu' + str.substring(5);416pieceTable.insert(9, 'jdm');417str = str.substring(0, 9) + 'jdm' + str.substring(9);418pieceTable.insert(15, 'na\n');419str = str.substring(0, 15) + 'na\n' + str.substring(15);420pieceTable.delete(5, 8);421str = str.substring(0, 5) + str.substring(5 + 8);422pieceTable.delete(3, 4);423str = str.substring(0, 3) + str.substring(3 + 4);424assert.strictEqual(pieceTable.getLinesRawContent(), str);425assertTreeInvariants(pieceTable);426});427428test('random insert/delete \\r bug 1', () => {429let str = 'a';430const pieceTree = createTextBuffer(['a']);431ds.add(pieceTree);432const pieceTable = pieceTree.getPieceTree();433pieceTable.delete(0, 1);434str = str.substring(0, 0) + str.substring(0 + 1);435pieceTable.insert(0, '\r\r\n\n');436str = str.substring(0, 0) + '\r\r\n\n' + str.substring(0);437pieceTable.delete(3, 1);438str = str.substring(0, 3) + str.substring(3 + 1);439pieceTable.insert(2, '\n\n\ra');440str = str.substring(0, 2) + '\n\n\ra' + str.substring(2);441pieceTable.delete(4, 3);442str = str.substring(0, 4) + str.substring(4 + 3);443pieceTable.insert(2, '\na\r\r');444str = str.substring(0, 2) + '\na\r\r' + str.substring(2);445pieceTable.insert(6, '\ra\n\n');446str = str.substring(0, 6) + '\ra\n\n' + str.substring(6);447pieceTable.insert(0, 'aa\n\n');448str = str.substring(0, 0) + 'aa\n\n' + str.substring(0);449pieceTable.insert(5, '\n\na\r');450str = str.substring(0, 5) + '\n\na\r' + str.substring(5);451452assert.strictEqual(pieceTable.getLinesRawContent(), str);453assertTreeInvariants(pieceTable);454});455456test('random insert/delete \\r bug 2', () => {457let str = 'a';458const pieceTree = createTextBuffer(['a']);459ds.add(pieceTree);460const pieceTable = pieceTree.getPieceTree();461pieceTable.insert(1, '\naa\r');462str = str.substring(0, 1) + '\naa\r' + str.substring(1);463pieceTable.delete(0, 4);464str = str.substring(0, 0) + str.substring(0 + 4);465pieceTable.insert(1, '\r\r\na');466str = str.substring(0, 1) + '\r\r\na' + str.substring(1);467pieceTable.insert(2, '\n\r\ra');468str = str.substring(0, 2) + '\n\r\ra' + str.substring(2);469pieceTable.delete(4, 1);470str = str.substring(0, 4) + str.substring(4 + 1);471pieceTable.insert(8, '\r\n\r\r');472str = str.substring(0, 8) + '\r\n\r\r' + str.substring(8);473pieceTable.insert(7, '\n\n\na');474str = str.substring(0, 7) + '\n\n\na' + str.substring(7);475pieceTable.insert(13, 'a\n\na');476str = str.substring(0, 13) + 'a\n\na' + str.substring(13);477pieceTable.delete(17, 3);478str = str.substring(0, 17) + str.substring(17 + 3);479pieceTable.insert(2, 'a\ra\n');480str = str.substring(0, 2) + 'a\ra\n' + str.substring(2);481482assert.strictEqual(pieceTable.getLinesRawContent(), str);483assertTreeInvariants(pieceTable);484});485486test('random insert/delete \\r bug 3', () => {487let str = 'a';488const pieceTree = createTextBuffer(['a']);489ds.add(pieceTree);490const pieceTable = pieceTree.getPieceTree();491pieceTable.insert(0, '\r\na\r');492str = str.substring(0, 0) + '\r\na\r' + str.substring(0);493pieceTable.delete(2, 3);494str = str.substring(0, 2) + str.substring(2 + 3);495pieceTable.insert(2, 'a\r\n\r');496str = str.substring(0, 2) + 'a\r\n\r' + str.substring(2);497pieceTable.delete(4, 2);498str = str.substring(0, 4) + str.substring(4 + 2);499pieceTable.insert(4, 'a\n\r\n');500str = str.substring(0, 4) + 'a\n\r\n' + str.substring(4);501pieceTable.insert(1, 'aa\n\r');502str = str.substring(0, 1) + 'aa\n\r' + str.substring(1);503pieceTable.insert(7, '\na\r\n');504str = str.substring(0, 7) + '\na\r\n' + str.substring(7);505pieceTable.insert(5, '\n\na\r');506str = str.substring(0, 5) + '\n\na\r' + str.substring(5);507pieceTable.insert(10, '\r\r\n\r');508str = str.substring(0, 10) + '\r\r\n\r' + str.substring(10);509assert.strictEqual(pieceTable.getLinesRawContent(), str);510pieceTable.delete(21, 3);511str = str.substring(0, 21) + str.substring(21 + 3);512513assert.strictEqual(pieceTable.getLinesRawContent(), str);514assertTreeInvariants(pieceTable);515});516517test('random insert/delete \\r bug 4s', () => {518let str = 'a';519const pieceTree = createTextBuffer(['a']);520ds.add(pieceTree);521const pieceTable = pieceTree.getPieceTree();522pieceTable.delete(0, 1);523str = str.substring(0, 0) + str.substring(0 + 1);524pieceTable.insert(0, '\naaa');525str = str.substring(0, 0) + '\naaa' + str.substring(0);526pieceTable.insert(2, '\n\naa');527str = str.substring(0, 2) + '\n\naa' + str.substring(2);528pieceTable.delete(1, 4);529str = str.substring(0, 1) + str.substring(1 + 4);530pieceTable.delete(3, 1);531str = str.substring(0, 3) + str.substring(3 + 1);532pieceTable.delete(1, 2);533str = str.substring(0, 1) + str.substring(1 + 2);534pieceTable.delete(0, 1);535str = str.substring(0, 0) + str.substring(0 + 1);536pieceTable.insert(0, 'a\n\n\r');537str = str.substring(0, 0) + 'a\n\n\r' + str.substring(0);538pieceTable.insert(2, 'aa\r\n');539str = str.substring(0, 2) + 'aa\r\n' + str.substring(2);540pieceTable.insert(3, 'a\naa');541str = str.substring(0, 3) + 'a\naa' + str.substring(3);542543assert.strictEqual(pieceTable.getLinesRawContent(), str);544assertTreeInvariants(pieceTable);545});546test('random insert/delete \\r bug 5', () => {547let str = '';548const pieceTree = createTextBuffer(['']);549ds.add(pieceTree);550const pieceTable = pieceTree.getPieceTree();551pieceTable.insert(0, '\n\n\n\r');552str = str.substring(0, 0) + '\n\n\n\r' + str.substring(0);553pieceTable.insert(1, '\n\n\n\r');554str = str.substring(0, 1) + '\n\n\n\r' + str.substring(1);555pieceTable.insert(2, '\n\r\r\r');556str = str.substring(0, 2) + '\n\r\r\r' + str.substring(2);557pieceTable.insert(8, '\n\r\n\r');558str = str.substring(0, 8) + '\n\r\n\r' + str.substring(8);559pieceTable.delete(5, 2);560str = str.substring(0, 5) + str.substring(5 + 2);561pieceTable.insert(4, '\n\r\r\r');562str = str.substring(0, 4) + '\n\r\r\r' + str.substring(4);563pieceTable.insert(8, '\n\n\n\r');564str = str.substring(0, 8) + '\n\n\n\r' + str.substring(8);565pieceTable.delete(0, 7);566str = str.substring(0, 0) + str.substring(0 + 7);567pieceTable.insert(1, '\r\n\r\r');568str = str.substring(0, 1) + '\r\n\r\r' + str.substring(1);569pieceTable.insert(15, '\n\r\r\r');570str = str.substring(0, 15) + '\n\r\r\r' + str.substring(15);571572assert.strictEqual(pieceTable.getLinesRawContent(), str);573assertTreeInvariants(pieceTable);574});575});576577suite('prefix sum for line feed', () => {578const ds = ensureNoDisposablesAreLeakedInTestSuite();579580test('basic', () => {581const pieceTree = createTextBuffer(['1\n2\n3\n4']);582ds.add(pieceTree);583const pieceTable = pieceTree.getPieceTree();584585assert.strictEqual(pieceTable.getLineCount(), 4);586assert.deepStrictEqual(pieceTable.getPositionAt(0), new Position(1, 1));587assert.deepStrictEqual(pieceTable.getPositionAt(1), new Position(1, 2));588assert.deepStrictEqual(pieceTable.getPositionAt(2), new Position(2, 1));589assert.deepStrictEqual(pieceTable.getPositionAt(3), new Position(2, 2));590assert.deepStrictEqual(pieceTable.getPositionAt(4), new Position(3, 1));591assert.deepStrictEqual(pieceTable.getPositionAt(5), new Position(3, 2));592assert.deepStrictEqual(pieceTable.getPositionAt(6), new Position(4, 1));593594assert.strictEqual(pieceTable.getOffsetAt(1, 1), 0);595assert.strictEqual(pieceTable.getOffsetAt(1, 2), 1);596assert.strictEqual(pieceTable.getOffsetAt(2, 1), 2);597assert.strictEqual(pieceTable.getOffsetAt(2, 2), 3);598assert.strictEqual(pieceTable.getOffsetAt(3, 1), 4);599assert.strictEqual(pieceTable.getOffsetAt(3, 2), 5);600assert.strictEqual(pieceTable.getOffsetAt(4, 1), 6);601assertTreeInvariants(pieceTable);602});603604test('append', () => {605const pieceTree = createTextBuffer(['a\nb\nc\nde']);606ds.add(pieceTree);607const pieceTable = pieceTree.getPieceTree();608pieceTable.insert(8, 'fh\ni\njk');609610assert.strictEqual(pieceTable.getLineCount(), 6);611assert.deepStrictEqual(pieceTable.getPositionAt(9), new Position(4, 4));612assert.strictEqual(pieceTable.getOffsetAt(1, 1), 0);613assertTreeInvariants(pieceTable);614});615616test('insert', () => {617const pieceTree = createTextBuffer(['a\nb\nc\nde']);618ds.add(pieceTree);619const pieceTable = pieceTree.getPieceTree();620pieceTable.insert(7, 'fh\ni\njk');621622assert.strictEqual(pieceTable.getLineCount(), 6);623assert.deepStrictEqual(pieceTable.getPositionAt(6), new Position(4, 1));624assert.deepStrictEqual(pieceTable.getPositionAt(7), new Position(4, 2));625assert.deepStrictEqual(pieceTable.getPositionAt(8), new Position(4, 3));626assert.deepStrictEqual(pieceTable.getPositionAt(9), new Position(4, 4));627assert.deepStrictEqual(pieceTable.getPositionAt(12), new Position(6, 1));628assert.deepStrictEqual(pieceTable.getPositionAt(13), new Position(6, 2));629assert.deepStrictEqual(pieceTable.getPositionAt(14), new Position(6, 3));630631assert.strictEqual(pieceTable.getOffsetAt(4, 1), 6);632assert.strictEqual(pieceTable.getOffsetAt(4, 2), 7);633assert.strictEqual(pieceTable.getOffsetAt(4, 3), 8);634assert.strictEqual(pieceTable.getOffsetAt(4, 4), 9);635assert.strictEqual(pieceTable.getOffsetAt(6, 1), 12);636assert.strictEqual(pieceTable.getOffsetAt(6, 2), 13);637assert.strictEqual(pieceTable.getOffsetAt(6, 3), 14);638assertTreeInvariants(pieceTable);639});640641test('delete', () => {642const pieceTree = createTextBuffer(['a\nb\nc\ndefh\ni\njk']);643ds.add(pieceTree);644const pieceTable = pieceTree.getPieceTree();645646pieceTable.delete(7, 2);647648assert.strictEqual(pieceTable.getLinesRawContent(), 'a\nb\nc\ndh\ni\njk');649assert.strictEqual(pieceTable.getLineCount(), 6);650assert.deepStrictEqual(pieceTable.getPositionAt(6), new Position(4, 1));651assert.deepStrictEqual(pieceTable.getPositionAt(7), new Position(4, 2));652assert.deepStrictEqual(pieceTable.getPositionAt(8), new Position(4, 3));653assert.deepStrictEqual(pieceTable.getPositionAt(9), new Position(5, 1));654assert.deepStrictEqual(pieceTable.getPositionAt(11), new Position(6, 1));655assert.deepStrictEqual(pieceTable.getPositionAt(12), new Position(6, 2));656assert.deepStrictEqual(pieceTable.getPositionAt(13), new Position(6, 3));657658assert.strictEqual(pieceTable.getOffsetAt(4, 1), 6);659assert.strictEqual(pieceTable.getOffsetAt(4, 2), 7);660assert.strictEqual(pieceTable.getOffsetAt(4, 3), 8);661assert.strictEqual(pieceTable.getOffsetAt(5, 1), 9);662assert.strictEqual(pieceTable.getOffsetAt(6, 1), 11);663assert.strictEqual(pieceTable.getOffsetAt(6, 2), 12);664assert.strictEqual(pieceTable.getOffsetAt(6, 3), 13);665assertTreeInvariants(pieceTable);666});667668test('add+delete 1', () => {669const pieceTree = createTextBuffer(['a\nb\nc\nde']);670ds.add(pieceTree);671const pieceTable = pieceTree.getPieceTree();672pieceTable.insert(8, 'fh\ni\njk');673pieceTable.delete(7, 2);674675assert.strictEqual(pieceTable.getLinesRawContent(), 'a\nb\nc\ndh\ni\njk');676assert.strictEqual(pieceTable.getLineCount(), 6);677assert.deepStrictEqual(pieceTable.getPositionAt(6), new Position(4, 1));678assert.deepStrictEqual(pieceTable.getPositionAt(7), new Position(4, 2));679assert.deepStrictEqual(pieceTable.getPositionAt(8), new Position(4, 3));680assert.deepStrictEqual(pieceTable.getPositionAt(9), new Position(5, 1));681assert.deepStrictEqual(pieceTable.getPositionAt(11), new Position(6, 1));682assert.deepStrictEqual(pieceTable.getPositionAt(12), new Position(6, 2));683assert.deepStrictEqual(pieceTable.getPositionAt(13), new Position(6, 3));684685assert.strictEqual(pieceTable.getOffsetAt(4, 1), 6);686assert.strictEqual(pieceTable.getOffsetAt(4, 2), 7);687assert.strictEqual(pieceTable.getOffsetAt(4, 3), 8);688assert.strictEqual(pieceTable.getOffsetAt(5, 1), 9);689assert.strictEqual(pieceTable.getOffsetAt(6, 1), 11);690assert.strictEqual(pieceTable.getOffsetAt(6, 2), 12);691assert.strictEqual(pieceTable.getOffsetAt(6, 3), 13);692assertTreeInvariants(pieceTable);693});694695test('insert random bug 1: prefixSumComputer.removeValues(start, cnt) cnt is 1 based.', () => {696let str = '';697const pieceTree = createTextBuffer(['']);698ds.add(pieceTree);699const pieceTable = pieceTree.getPieceTree();700pieceTable.insert(0, ' ZX \n Z\nZ\n YZ\nY\nZXX ');701str =702str.substring(0, 0) +703' ZX \n Z\nZ\n YZ\nY\nZXX ' +704str.substring(0);705pieceTable.insert(14, 'X ZZ\nYZZYZXXY Y XY\n ');706str =707str.substring(0, 14) + 'X ZZ\nYZZYZXXY Y XY\n ' + str.substring(14);708709assert.strictEqual(pieceTable.getLinesRawContent(), str);710testLineStarts(str, pieceTable);711assertTreeInvariants(pieceTable);712});713714test('insert random bug 2: prefixSumComputer initialize does not do deep copy of UInt32Array.', () => {715let str = '';716const pieceTree = createTextBuffer(['']);717ds.add(pieceTree);718const pieceTable = pieceTree.getPieceTree();719pieceTable.insert(0, 'ZYZ\nYY XY\nX \nZ Y \nZ ');720str =721str.substring(0, 0) + 'ZYZ\nYY XY\nX \nZ Y \nZ ' + str.substring(0);722pieceTable.insert(3, 'XXY \n\nY Y YYY ZYXY ');723str = str.substring(0, 3) + 'XXY \n\nY Y YYY ZYXY ' + str.substring(3);724725assert.strictEqual(pieceTable.getLinesRawContent(), str);726testLineStarts(str, pieceTable);727assertTreeInvariants(pieceTable);728});729730test('delete random bug 1: I forgot to update the lineFeedCnt when deletion is on one single piece.', () => {731const pieceTree = createTextBuffer(['']);732ds.add(pieceTree);733const pieceTable = pieceTree.getPieceTree();734pieceTable.insert(0, 'ba\na\nca\nba\ncbab\ncaa ');735pieceTable.insert(13, 'cca\naabb\ncac\nccc\nab ');736pieceTable.delete(5, 8);737pieceTable.delete(30, 2);738pieceTable.insert(24, 'cbbacccbac\nbaaab\n\nc ');739pieceTable.delete(29, 3);740pieceTable.delete(23, 9);741pieceTable.delete(21, 5);742pieceTable.delete(30, 3);743pieceTable.insert(3, 'cb\nac\nc\n\nacc\nbb\nb\nc ');744pieceTable.delete(19, 5);745pieceTable.insert(18, '\nbb\n\nacbc\ncbb\nc\nbb\n ');746pieceTable.insert(65, 'cbccbac\nbc\n\nccabba\n ');747pieceTable.insert(77, 'a\ncacb\n\nac\n\n\n\n\nabab ');748pieceTable.delete(30, 9);749pieceTable.insert(45, 'b\n\nc\nba\n\nbbbba\n\naa\n ');750pieceTable.insert(82, 'ab\nbb\ncabacab\ncbc\na ');751pieceTable.delete(123, 9);752pieceTable.delete(71, 2);753pieceTable.insert(33, 'acaa\nacb\n\naa\n\nc\n\n\n\n ');754755const str = pieceTable.getLinesRawContent();756testLineStarts(str, pieceTable);757assertTreeInvariants(pieceTable);758});759760test('delete random bug rb tree 1', () => {761let str = '';762const pieceTree = createTextBuffer([str]);763ds.add(pieceTree);764const pieceTable = pieceTree.getPieceTree();765pieceTable.insert(0, 'YXXZ\n\nYY\n');766str = str.substring(0, 0) + 'YXXZ\n\nYY\n' + str.substring(0);767pieceTable.delete(0, 5);768str = str.substring(0, 0) + str.substring(0 + 5);769pieceTable.insert(0, 'ZXYY\nX\nZ\n');770str = str.substring(0, 0) + 'ZXYY\nX\nZ\n' + str.substring(0);771pieceTable.insert(10, '\nXY\nYXYXY');772str = str.substring(0, 10) + '\nXY\nYXYXY' + str.substring(10);773testLineStarts(str, pieceTable);774assertTreeInvariants(pieceTable);775});776777test('delete random bug rb tree 2', () => {778let str = '';779const pieceTree = createTextBuffer([str]);780ds.add(pieceTree);781const pieceTable = pieceTree.getPieceTree();782pieceTable.insert(0, 'YXXZ\n\nYY\n');783str = str.substring(0, 0) + 'YXXZ\n\nYY\n' + str.substring(0);784pieceTable.insert(0, 'ZXYY\nX\nZ\n');785str = str.substring(0, 0) + 'ZXYY\nX\nZ\n' + str.substring(0);786pieceTable.insert(10, '\nXY\nYXYXY');787str = str.substring(0, 10) + '\nXY\nYXYXY' + str.substring(10);788pieceTable.insert(8, 'YZXY\nZ\nYX');789str = str.substring(0, 8) + 'YZXY\nZ\nYX' + str.substring(8);790pieceTable.insert(12, 'XX\nXXYXYZ');791str = str.substring(0, 12) + 'XX\nXXYXYZ' + str.substring(12);792pieceTable.delete(0, 4);793str = str.substring(0, 0) + str.substring(0 + 4);794795testLineStarts(str, pieceTable);796assertTreeInvariants(pieceTable);797});798799test('delete random bug rb tree 3', () => {800let str = '';801const pieceTree = createTextBuffer([str]);802ds.add(pieceTree);803const pieceTable = pieceTree.getPieceTree();804pieceTable.insert(0, 'YXXZ\n\nYY\n');805str = str.substring(0, 0) + 'YXXZ\n\nYY\n' + str.substring(0);806pieceTable.delete(7, 2);807str = str.substring(0, 7) + str.substring(7 + 2);808pieceTable.delete(6, 1);809str = str.substring(0, 6) + str.substring(6 + 1);810pieceTable.delete(0, 5);811str = str.substring(0, 0) + str.substring(0 + 5);812pieceTable.insert(0, 'ZXYY\nX\nZ\n');813str = str.substring(0, 0) + 'ZXYY\nX\nZ\n' + str.substring(0);814pieceTable.insert(10, '\nXY\nYXYXY');815str = str.substring(0, 10) + '\nXY\nYXYXY' + str.substring(10);816pieceTable.insert(8, 'YZXY\nZ\nYX');817str = str.substring(0, 8) + 'YZXY\nZ\nYX' + str.substring(8);818pieceTable.insert(12, 'XX\nXXYXYZ');819str = str.substring(0, 12) + 'XX\nXXYXYZ' + str.substring(12);820pieceTable.delete(0, 4);821str = str.substring(0, 0) + str.substring(0 + 4);822pieceTable.delete(30, 3);823str = str.substring(0, 30) + str.substring(30 + 3);824825testLineStarts(str, pieceTable);826assertTreeInvariants(pieceTable);827});828});829830suite('offset 2 position', () => {831const ds = ensureNoDisposablesAreLeakedInTestSuite();832833test('random tests bug 1', () => {834let str = '';835const pieceTree = createTextBuffer(['']);836ds.add(pieceTree);837const pieceTable = pieceTree.getPieceTree();838pieceTable.insert(0, 'huuyYzUfKOENwGgZLqn ');839str = str.substring(0, 0) + 'huuyYzUfKOENwGgZLqn ' + str.substring(0);840pieceTable.delete(18, 2);841str = str.substring(0, 18) + str.substring(18 + 2);842pieceTable.delete(3, 1);843str = str.substring(0, 3) + str.substring(3 + 1);844pieceTable.delete(12, 4);845str = str.substring(0, 12) + str.substring(12 + 4);846pieceTable.insert(3, 'hMbnVEdTSdhLlPevXKF ');847str = str.substring(0, 3) + 'hMbnVEdTSdhLlPevXKF ' + str.substring(3);848pieceTable.delete(22, 8);849str = str.substring(0, 22) + str.substring(22 + 8);850pieceTable.insert(4, 'S umSnYrqOmOAV\nEbZJ ');851str = str.substring(0, 4) + 'S umSnYrqOmOAV\nEbZJ ' + str.substring(4);852853testLineStarts(str, pieceTable);854assertTreeInvariants(pieceTable);855});856});857858suite('get text in range', () => {859const ds = ensureNoDisposablesAreLeakedInTestSuite();860861test('getContentInRange', () => {862const pieceTree = createTextBuffer(['a\nb\nc\nde']);863ds.add(pieceTree);864const pieceTable = pieceTree.getPieceTree();865pieceTable.insert(8, 'fh\ni\njk');866pieceTable.delete(7, 2);867// 'a\nb\nc\ndh\ni\njk'868869assert.strictEqual(pieceTable.getValueInRange(new Range(1, 1, 1, 3)), 'a\n');870assert.strictEqual(pieceTable.getValueInRange(new Range(2, 1, 2, 3)), 'b\n');871assert.strictEqual(pieceTable.getValueInRange(new Range(3, 1, 3, 3)), 'c\n');872assert.strictEqual(pieceTable.getValueInRange(new Range(4, 1, 4, 4)), 'dh\n');873assert.strictEqual(pieceTable.getValueInRange(new Range(5, 1, 5, 3)), 'i\n');874assert.strictEqual(pieceTable.getValueInRange(new Range(6, 1, 6, 3)), 'jk');875assertTreeInvariants(pieceTable);876});877878test('random test value in range', () => {879let str = '';880const pieceTree = createTextBuffer([str]);881ds.add(pieceTree);882const pieceTable = pieceTree.getPieceTree();883884pieceTable.insert(0, 'ZXXY');885str = str.substring(0, 0) + 'ZXXY' + str.substring(0);886pieceTable.insert(1, 'XZZY');887str = str.substring(0, 1) + 'XZZY' + str.substring(1);888pieceTable.insert(5, '\nX\n\n');889str = str.substring(0, 5) + '\nX\n\n' + str.substring(5);890pieceTable.insert(3, '\nXX\n');891str = str.substring(0, 3) + '\nXX\n' + str.substring(3);892pieceTable.insert(12, 'YYYX');893str = str.substring(0, 12) + 'YYYX' + str.substring(12);894895testLinesContent(str, pieceTable);896assertTreeInvariants(pieceTable);897});898test('random test value in range exception', () => {899let str = '';900const pieceTree = createTextBuffer([str]);901ds.add(pieceTree);902const pieceTable = pieceTree.getPieceTree();903904pieceTable.insert(0, 'XZ\nZ');905str = str.substring(0, 0) + 'XZ\nZ' + str.substring(0);906pieceTable.delete(0, 3);907str = str.substring(0, 0) + str.substring(0 + 3);908pieceTable.delete(0, 1);909str = str.substring(0, 0) + str.substring(0 + 1);910pieceTable.insert(0, 'ZYX\n');911str = str.substring(0, 0) + 'ZYX\n' + str.substring(0);912pieceTable.delete(0, 4);913str = str.substring(0, 0) + str.substring(0 + 4);914915pieceTable.getValueInRange(new Range(1, 1, 1, 1));916assertTreeInvariants(pieceTable);917});918919test('random tests bug 1', () => {920let str = '';921const pieceTree = createTextBuffer(['']);922ds.add(pieceTree);923const pieceTable = pieceTree.getPieceTree();924pieceTable.insert(0, 'huuyYzUfKOENwGgZLqn ');925str = str.substring(0, 0) + 'huuyYzUfKOENwGgZLqn ' + str.substring(0);926pieceTable.delete(18, 2);927str = str.substring(0, 18) + str.substring(18 + 2);928pieceTable.delete(3, 1);929str = str.substring(0, 3) + str.substring(3 + 1);930pieceTable.delete(12, 4);931str = str.substring(0, 12) + str.substring(12 + 4);932pieceTable.insert(3, 'hMbnVEdTSdhLlPevXKF ');933str = str.substring(0, 3) + 'hMbnVEdTSdhLlPevXKF ' + str.substring(3);934pieceTable.delete(22, 8);935str = str.substring(0, 22) + str.substring(22 + 8);936pieceTable.insert(4, 'S umSnYrqOmOAV\nEbZJ ');937str = str.substring(0, 4) + 'S umSnYrqOmOAV\nEbZJ ' + str.substring(4);938testLinesContent(str, pieceTable);939assertTreeInvariants(pieceTable);940});941942test('random tests bug 2', () => {943let str = '';944const pieceTree = createTextBuffer(['']);945ds.add(pieceTree);946const pieceTable = pieceTree.getPieceTree();947pieceTable.insert(0, 'xfouRDZwdAHjVXJAMV\n ');948str = str.substring(0, 0) + 'xfouRDZwdAHjVXJAMV\n ' + str.substring(0);949pieceTable.insert(16, 'dBGndxpFZBEAIKykYYx ');950str = str.substring(0, 16) + 'dBGndxpFZBEAIKykYYx ' + str.substring(16);951pieceTable.delete(7, 6);952str = str.substring(0, 7) + str.substring(7 + 6);953pieceTable.delete(9, 7);954str = str.substring(0, 9) + str.substring(9 + 7);955pieceTable.delete(17, 6);956str = str.substring(0, 17) + str.substring(17 + 6);957pieceTable.delete(0, 4);958str = str.substring(0, 0) + str.substring(0 + 4);959pieceTable.insert(9, 'qvEFXCNvVkWgvykahYt ');960str = str.substring(0, 9) + 'qvEFXCNvVkWgvykahYt ' + str.substring(9);961pieceTable.delete(4, 6);962str = str.substring(0, 4) + str.substring(4 + 6);963pieceTable.insert(11, 'OcSChUYT\nzPEBOpsGmR ');964str =965str.substring(0, 11) + 'OcSChUYT\nzPEBOpsGmR ' + str.substring(11);966pieceTable.insert(15, 'KJCozaXTvkE\nxnqAeTz ');967str =968str.substring(0, 15) + 'KJCozaXTvkE\nxnqAeTz ' + str.substring(15);969970testLinesContent(str, pieceTable);971assertTreeInvariants(pieceTable);972});973974test('get line content', () => {975const pieceTree = createTextBuffer(['1']);976ds.add(pieceTree);977const pieceTable = pieceTree.getPieceTree();978979assert.strictEqual(pieceTable.getLineRawContent(1), '1');980pieceTable.insert(1, '2');981assert.strictEqual(pieceTable.getLineRawContent(1), '12');982assertTreeInvariants(pieceTable);983});984985test('get line content basic', () => {986const pieceTree = createTextBuffer(['1\n2\n3\n4']);987ds.add(pieceTree);988const pieceTable = pieceTree.getPieceTree();989990assert.strictEqual(pieceTable.getLineRawContent(1), '1\n');991assert.strictEqual(pieceTable.getLineRawContent(2), '2\n');992assert.strictEqual(pieceTable.getLineRawContent(3), '3\n');993assert.strictEqual(pieceTable.getLineRawContent(4), '4');994assertTreeInvariants(pieceTable);995});996997test('get line content after inserts/deletes', () => {998const pieceTree = createTextBuffer(['a\nb\nc\nde']);999ds.add(pieceTree);1000const pieceTable = pieceTree.getPieceTree();1001pieceTable.insert(8, 'fh\ni\njk');1002pieceTable.delete(7, 2);1003// 'a\nb\nc\ndh\ni\njk'10041005assert.strictEqual(pieceTable.getLineRawContent(1), 'a\n');1006assert.strictEqual(pieceTable.getLineRawContent(2), 'b\n');1007assert.strictEqual(pieceTable.getLineRawContent(3), 'c\n');1008assert.strictEqual(pieceTable.getLineRawContent(4), 'dh\n');1009assert.strictEqual(pieceTable.getLineRawContent(5), 'i\n');1010assert.strictEqual(pieceTable.getLineRawContent(6), 'jk');1011assertTreeInvariants(pieceTable);1012});10131014test('random 1', () => {1015let str = '';1016const pieceTree = createTextBuffer(['']);1017ds.add(pieceTree);1018const pieceTable = pieceTree.getPieceTree();10191020pieceTable.insert(0, 'J eNnDzQpnlWyjmUu\ny ');1021str = str.substring(0, 0) + 'J eNnDzQpnlWyjmUu\ny ' + str.substring(0);1022pieceTable.insert(0, 'QPEeRAQmRwlJqtZSWhQ ');1023str = str.substring(0, 0) + 'QPEeRAQmRwlJqtZSWhQ ' + str.substring(0);1024pieceTable.delete(5, 1);1025str = str.substring(0, 5) + str.substring(5 + 1);10261027testLinesContent(str, pieceTable);1028assertTreeInvariants(pieceTable);1029});10301031test('random 2', () => {1032let str = '';1033const pieceTree = createTextBuffer(['']);1034ds.add(pieceTree);1035const pieceTable = pieceTree.getPieceTree();1036pieceTable.insert(0, 'DZoQ tglPCRHMltejRI ');1037str = str.substring(0, 0) + 'DZoQ tglPCRHMltejRI ' + str.substring(0);1038pieceTable.insert(10, 'JRXiyYqJ qqdcmbfkKX ');1039str = str.substring(0, 10) + 'JRXiyYqJ qqdcmbfkKX ' + str.substring(10);1040pieceTable.delete(16, 3);1041str = str.substring(0, 16) + str.substring(16 + 3);1042pieceTable.delete(25, 1);1043str = str.substring(0, 25) + str.substring(25 + 1);1044pieceTable.insert(18, 'vH\nNlvfqQJPm\nSFkhMc ');1045str =1046str.substring(0, 18) + 'vH\nNlvfqQJPm\nSFkhMc ' + str.substring(18);10471048testLinesContent(str, pieceTable);1049assertTreeInvariants(pieceTable);1050});1051});10521053suite('CRLF', () => {1054const ds = ensureNoDisposablesAreLeakedInTestSuite();10551056test('delete CR in CRLF 1', () => {1057const pieceTree = createTextBuffer([''], false);1058ds.add(pieceTree);1059const pieceTable = pieceTree.getPieceTree();1060pieceTable.insert(0, 'a\r\nb');1061pieceTable.delete(0, 2);10621063assert.strictEqual(pieceTable.getLineCount(), 2);1064assertTreeInvariants(pieceTable);1065});10661067test('delete CR in CRLF 2', () => {1068const pieceTree = createTextBuffer([''], false);1069ds.add(pieceTree);1070const pieceTable = pieceTree.getPieceTree();1071pieceTable.insert(0, 'a\r\nb');1072pieceTable.delete(2, 2);10731074assert.strictEqual(pieceTable.getLineCount(), 2);1075assertTreeInvariants(pieceTable);1076});10771078test('random bug 1', () => {1079let str = '';1080const pieceTree = createTextBuffer([''], false);1081ds.add(pieceTree);1082const pieceTable = pieceTree.getPieceTree();1083pieceTable.insert(0, '\n\n\r\r');1084str = str.substring(0, 0) + '\n\n\r\r' + str.substring(0);1085pieceTable.insert(1, '\r\n\r\n');1086str = str.substring(0, 1) + '\r\n\r\n' + str.substring(1);1087pieceTable.delete(5, 3);1088str = str.substring(0, 5) + str.substring(5 + 3);1089pieceTable.delete(2, 3);1090str = str.substring(0, 2) + str.substring(2 + 3);10911092const lines = splitLines(str);1093assert.strictEqual(pieceTable.getLineCount(), lines.length);1094assertTreeInvariants(pieceTable);1095});1096test('random bug 2', () => {1097let str = '';1098const pieceTree = createTextBuffer([''], false);1099ds.add(pieceTree);1100const pieceTable = pieceTree.getPieceTree();11011102pieceTable.insert(0, '\n\r\n\r');1103str = str.substring(0, 0) + '\n\r\n\r' + str.substring(0);1104pieceTable.insert(2, '\n\r\r\r');1105str = str.substring(0, 2) + '\n\r\r\r' + str.substring(2);1106pieceTable.delete(4, 1);1107str = str.substring(0, 4) + str.substring(4 + 1);11081109const lines = splitLines(str);1110assert.strictEqual(pieceTable.getLineCount(), lines.length);1111assertTreeInvariants(pieceTable);1112});1113test('random bug 3', () => {1114let str = '';1115const pieceTree = createTextBuffer([''], false);1116ds.add(pieceTree);1117const pieceTable = pieceTree.getPieceTree();11181119pieceTable.insert(0, '\n\n\n\r');1120str = str.substring(0, 0) + '\n\n\n\r' + str.substring(0);1121pieceTable.delete(2, 2);1122str = str.substring(0, 2) + str.substring(2 + 2);1123pieceTable.delete(0, 2);1124str = str.substring(0, 0) + str.substring(0 + 2);1125pieceTable.insert(0, '\r\r\r\r');1126str = str.substring(0, 0) + '\r\r\r\r' + str.substring(0);1127pieceTable.insert(2, '\r\n\r\r');1128str = str.substring(0, 2) + '\r\n\r\r' + str.substring(2);1129pieceTable.insert(3, '\r\r\r\n');1130str = str.substring(0, 3) + '\r\r\r\n' + str.substring(3);11311132const lines = splitLines(str);1133assert.strictEqual(pieceTable.getLineCount(), lines.length);1134assertTreeInvariants(pieceTable);1135});1136test('random bug 4', () => {1137let str = '';1138const pieceTree = createTextBuffer([''], false);1139ds.add(pieceTree);1140const pieceTable = pieceTree.getPieceTree();11411142pieceTable.insert(0, '\n\n\n\n');1143str = str.substring(0, 0) + '\n\n\n\n' + str.substring(0);1144pieceTable.delete(3, 1);1145str = str.substring(0, 3) + str.substring(3 + 1);1146pieceTable.insert(1, '\r\r\r\r');1147str = str.substring(0, 1) + '\r\r\r\r' + str.substring(1);1148pieceTable.insert(6, '\r\n\n\r');1149str = str.substring(0, 6) + '\r\n\n\r' + str.substring(6);1150pieceTable.delete(5, 3);1151str = str.substring(0, 5) + str.substring(5 + 3);11521153testLinesContent(str, pieceTable);1154assertTreeInvariants(pieceTable);1155});1156test('random bug 5', () => {1157let str = '';1158const pieceTree = createTextBuffer([''], false);1159ds.add(pieceTree);1160const pieceTable = pieceTree.getPieceTree();11611162pieceTable.insert(0, '\n\n\n\n');1163str = str.substring(0, 0) + '\n\n\n\n' + str.substring(0);1164pieceTable.delete(3, 1);1165str = str.substring(0, 3) + str.substring(3 + 1);1166pieceTable.insert(0, '\n\r\r\n');1167str = str.substring(0, 0) + '\n\r\r\n' + str.substring(0);1168pieceTable.insert(4, '\n\r\r\n');1169str = str.substring(0, 4) + '\n\r\r\n' + str.substring(4);1170pieceTable.delete(4, 3);1171str = str.substring(0, 4) + str.substring(4 + 3);1172pieceTable.insert(5, '\r\r\n\r');1173str = str.substring(0, 5) + '\r\r\n\r' + str.substring(5);1174pieceTable.insert(12, '\n\n\n\r');1175str = str.substring(0, 12) + '\n\n\n\r' + str.substring(12);1176pieceTable.insert(5, '\r\r\r\n');1177str = str.substring(0, 5) + '\r\r\r\n' + str.substring(5);1178pieceTable.insert(20, '\n\n\r\n');1179str = str.substring(0, 20) + '\n\n\r\n' + str.substring(20);11801181testLinesContent(str, pieceTable);1182assertTreeInvariants(pieceTable);1183});1184test('random bug 6', () => {1185let str = '';1186const pieceTree = createTextBuffer([''], false);1187ds.add(pieceTree);1188const pieceTable = pieceTree.getPieceTree();11891190pieceTable.insert(0, '\n\r\r\n');1191str = str.substring(0, 0) + '\n\r\r\n' + str.substring(0);1192pieceTable.insert(4, '\r\n\n\r');1193str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4);1194pieceTable.insert(3, '\r\n\n\n');1195str = str.substring(0, 3) + '\r\n\n\n' + str.substring(3);1196pieceTable.delete(4, 8);1197str = str.substring(0, 4) + str.substring(4 + 8);1198pieceTable.insert(4, '\r\n\n\r');1199str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4);1200pieceTable.insert(0, '\r\n\n\r');1201str = str.substring(0, 0) + '\r\n\n\r' + str.substring(0);1202pieceTable.delete(4, 0);1203str = str.substring(0, 4) + str.substring(4 + 0);1204pieceTable.delete(8, 4);1205str = str.substring(0, 8) + str.substring(8 + 4);12061207testLinesContent(str, pieceTable);1208assertTreeInvariants(pieceTable);1209});1210test('random bug 8', () => {1211let str = '';1212const pieceTree = createTextBuffer([''], false);1213ds.add(pieceTree);1214const pieceTable = pieceTree.getPieceTree();12151216pieceTable.insert(0, '\r\n\n\r');1217str = str.substring(0, 0) + '\r\n\n\r' + str.substring(0);1218pieceTable.delete(1, 0);1219str = str.substring(0, 1) + str.substring(1 + 0);1220pieceTable.insert(3, '\n\n\n\r');1221str = str.substring(0, 3) + '\n\n\n\r' + str.substring(3);1222pieceTable.insert(7, '\n\n\r\n');1223str = str.substring(0, 7) + '\n\n\r\n' + str.substring(7);12241225testLinesContent(str, pieceTable);1226assertTreeInvariants(pieceTable);1227});1228test('random bug 7', () => {1229let str = '';1230const pieceTree = createTextBuffer([''], false);1231ds.add(pieceTree);1232const pieceTable = pieceTree.getPieceTree();12331234pieceTable.insert(0, '\r\r\n\n');1235str = str.substring(0, 0) + '\r\r\n\n' + str.substring(0);1236pieceTable.insert(4, '\r\n\n\r');1237str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4);1238pieceTable.insert(7, '\n\r\r\r');1239str = str.substring(0, 7) + '\n\r\r\r' + str.substring(7);1240pieceTable.insert(11, '\n\n\r\n');1241str = str.substring(0, 11) + '\n\n\r\n' + str.substring(11);1242testLinesContent(str, pieceTable);1243assertTreeInvariants(pieceTable);1244});12451246test('random bug 10', () => {1247let str = '';1248const pieceTree = createTextBuffer([''], false);1249ds.add(pieceTree);1250const pieceTable = pieceTree.getPieceTree();12511252pieceTable.insert(0, 'qneW');1253str = str.substring(0, 0) + 'qneW' + str.substring(0);1254pieceTable.insert(0, 'YhIl');1255str = str.substring(0, 0) + 'YhIl' + str.substring(0);1256pieceTable.insert(0, 'qdsm');1257str = str.substring(0, 0) + 'qdsm' + str.substring(0);1258pieceTable.delete(7, 0);1259str = str.substring(0, 7) + str.substring(7 + 0);1260pieceTable.insert(12, 'iiPv');1261str = str.substring(0, 12) + 'iiPv' + str.substring(12);1262pieceTable.insert(9, 'V\rSA');1263str = str.substring(0, 9) + 'V\rSA' + str.substring(9);12641265testLinesContent(str, pieceTable);1266assertTreeInvariants(pieceTable);1267});12681269test('random bug 9', () => {1270let str = '';1271const pieceTree = createTextBuffer([''], false);1272ds.add(pieceTree);1273const pieceTable = pieceTree.getPieceTree();12741275pieceTable.insert(0, '\n\n\n\n');1276str = str.substring(0, 0) + '\n\n\n\n' + str.substring(0);1277pieceTable.insert(3, '\n\r\n\r');1278str = str.substring(0, 3) + '\n\r\n\r' + str.substring(3);1279pieceTable.insert(2, '\n\r\n\n');1280str = str.substring(0, 2) + '\n\r\n\n' + str.substring(2);1281pieceTable.insert(0, '\n\n\r\r');1282str = str.substring(0, 0) + '\n\n\r\r' + str.substring(0);1283pieceTable.insert(3, '\r\r\r\r');1284str = str.substring(0, 3) + '\r\r\r\r' + str.substring(3);1285pieceTable.insert(3, '\n\n\r\r');1286str = str.substring(0, 3) + '\n\n\r\r' + str.substring(3);12871288testLinesContent(str, pieceTable);1289assertTreeInvariants(pieceTable);1290});1291});12921293suite('centralized lineStarts with CRLF', () => {1294const ds = ensureNoDisposablesAreLeakedInTestSuite();12951296test('delete CR in CRLF 1', () => {1297const pieceTree = createTextBuffer(['a\r\nb'], false);1298ds.add(pieceTree);1299const pieceTable = pieceTree.getPieceTree();1300pieceTable.delete(2, 2);1301assert.strictEqual(pieceTable.getLineCount(), 2);1302assertTreeInvariants(pieceTable);1303});1304test('delete CR in CRLF 2', () => {1305const pieceTree = createTextBuffer(['a\r\nb']);1306ds.add(pieceTree);1307const pieceTable = pieceTree.getPieceTree();1308pieceTable.delete(0, 2);13091310assert.strictEqual(pieceTable.getLineCount(), 2);1311assertTreeInvariants(pieceTable);1312});13131314test('random bug 1', () => {1315let str = '\n\n\r\r';1316const pieceTree = createTextBuffer(['\n\n\r\r'], false);1317ds.add(pieceTree);1318const pieceTable = pieceTree.getPieceTree();13191320pieceTable.insert(1, '\r\n\r\n');1321str = str.substring(0, 1) + '\r\n\r\n' + str.substring(1);1322pieceTable.delete(5, 3);1323str = str.substring(0, 5) + str.substring(5 + 3);1324pieceTable.delete(2, 3);1325str = str.substring(0, 2) + str.substring(2 + 3);13261327const lines = splitLines(str);1328assert.strictEqual(pieceTable.getLineCount(), lines.length);1329assertTreeInvariants(pieceTable);1330});1331test('random bug 2', () => {1332let str = '\n\r\n\r';1333const pieceTree = createTextBuffer(['\n\r\n\r'], false);1334ds.add(pieceTree);1335const pieceTable = pieceTree.getPieceTree();13361337pieceTable.insert(2, '\n\r\r\r');1338str = str.substring(0, 2) + '\n\r\r\r' + str.substring(2);1339pieceTable.delete(4, 1);1340str = str.substring(0, 4) + str.substring(4 + 1);13411342const lines = splitLines(str);1343assert.strictEqual(pieceTable.getLineCount(), lines.length);1344assertTreeInvariants(pieceTable);1345});13461347test('random bug 3', () => {1348let str = '\n\n\n\r';1349const pieceTree = createTextBuffer(['\n\n\n\r'], false);1350ds.add(pieceTree);1351const pieceTable = pieceTree.getPieceTree();13521353pieceTable.delete(2, 2);1354str = str.substring(0, 2) + str.substring(2 + 2);1355pieceTable.delete(0, 2);1356str = str.substring(0, 0) + str.substring(0 + 2);1357pieceTable.insert(0, '\r\r\r\r');1358str = str.substring(0, 0) + '\r\r\r\r' + str.substring(0);1359pieceTable.insert(2, '\r\n\r\r');1360str = str.substring(0, 2) + '\r\n\r\r' + str.substring(2);1361pieceTable.insert(3, '\r\r\r\n');1362str = str.substring(0, 3) + '\r\r\r\n' + str.substring(3);13631364const lines = splitLines(str);1365assert.strictEqual(pieceTable.getLineCount(), lines.length);1366assertTreeInvariants(pieceTable);1367});13681369test('random bug 4', () => {1370let str = '\n\n\n\n';1371const pieceTree = createTextBuffer(['\n\n\n\n'], false);1372ds.add(pieceTree);1373const pieceTable = pieceTree.getPieceTree();13741375pieceTable.delete(3, 1);1376str = str.substring(0, 3) + str.substring(3 + 1);1377pieceTable.insert(1, '\r\r\r\r');1378str = str.substring(0, 1) + '\r\r\r\r' + str.substring(1);1379pieceTable.insert(6, '\r\n\n\r');1380str = str.substring(0, 6) + '\r\n\n\r' + str.substring(6);1381pieceTable.delete(5, 3);1382str = str.substring(0, 5) + str.substring(5 + 3);13831384testLinesContent(str, pieceTable);1385assertTreeInvariants(pieceTable);1386});13871388test('random bug 5', () => {1389let str = '\n\n\n\n';1390const pieceTree = createTextBuffer(['\n\n\n\n'], false);1391ds.add(pieceTree);1392const pieceTable = pieceTree.getPieceTree();13931394pieceTable.delete(3, 1);1395str = str.substring(0, 3) + str.substring(3 + 1);1396pieceTable.insert(0, '\n\r\r\n');1397str = str.substring(0, 0) + '\n\r\r\n' + str.substring(0);1398pieceTable.insert(4, '\n\r\r\n');1399str = str.substring(0, 4) + '\n\r\r\n' + str.substring(4);1400pieceTable.delete(4, 3);1401str = str.substring(0, 4) + str.substring(4 + 3);1402pieceTable.insert(5, '\r\r\n\r');1403str = str.substring(0, 5) + '\r\r\n\r' + str.substring(5);1404pieceTable.insert(12, '\n\n\n\r');1405str = str.substring(0, 12) + '\n\n\n\r' + str.substring(12);1406pieceTable.insert(5, '\r\r\r\n');1407str = str.substring(0, 5) + '\r\r\r\n' + str.substring(5);1408pieceTable.insert(20, '\n\n\r\n');1409str = str.substring(0, 20) + '\n\n\r\n' + str.substring(20);14101411testLinesContent(str, pieceTable);1412assertTreeInvariants(pieceTable);1413});14141415test('random bug 6', () => {1416let str = '\n\r\r\n';1417const pieceTree = createTextBuffer(['\n\r\r\n'], false);1418ds.add(pieceTree);1419const pieceTable = pieceTree.getPieceTree();14201421pieceTable.insert(4, '\r\n\n\r');1422str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4);1423pieceTable.insert(3, '\r\n\n\n');1424str = str.substring(0, 3) + '\r\n\n\n' + str.substring(3);1425pieceTable.delete(4, 8);1426str = str.substring(0, 4) + str.substring(4 + 8);1427pieceTable.insert(4, '\r\n\n\r');1428str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4);1429pieceTable.insert(0, '\r\n\n\r');1430str = str.substring(0, 0) + '\r\n\n\r' + str.substring(0);1431pieceTable.delete(4, 0);1432str = str.substring(0, 4) + str.substring(4 + 0);1433pieceTable.delete(8, 4);1434str = str.substring(0, 8) + str.substring(8 + 4);14351436testLinesContent(str, pieceTable);1437assertTreeInvariants(pieceTable);1438});14391440test('random bug 7', () => {1441let str = '\r\n\n\r';1442const pieceTree = createTextBuffer(['\r\n\n\r'], false);1443ds.add(pieceTree);1444const pieceTable = pieceTree.getPieceTree();14451446pieceTable.delete(1, 0);1447str = str.substring(0, 1) + str.substring(1 + 0);1448pieceTable.insert(3, '\n\n\n\r');1449str = str.substring(0, 3) + '\n\n\n\r' + str.substring(3);1450pieceTable.insert(7, '\n\n\r\n');1451str = str.substring(0, 7) + '\n\n\r\n' + str.substring(7);14521453testLinesContent(str, pieceTable);1454assertTreeInvariants(pieceTable);1455});14561457test('random bug 8', () => {1458let str = '\r\r\n\n';1459const pieceTree = createTextBuffer(['\r\r\n\n'], false);1460ds.add(pieceTree);1461const pieceTable = pieceTree.getPieceTree();14621463pieceTable.insert(4, '\r\n\n\r');1464str = str.substring(0, 4) + '\r\n\n\r' + str.substring(4);1465pieceTable.insert(7, '\n\r\r\r');1466str = str.substring(0, 7) + '\n\r\r\r' + str.substring(7);1467pieceTable.insert(11, '\n\n\r\n');1468str = str.substring(0, 11) + '\n\n\r\n' + str.substring(11);1469testLinesContent(str, pieceTable);1470assertTreeInvariants(pieceTable);1471});14721473test('random bug 9', () => {1474let str = 'qneW';1475const pieceTree = createTextBuffer(['qneW'], false);1476ds.add(pieceTree);1477const pieceTable = pieceTree.getPieceTree();14781479pieceTable.insert(0, 'YhIl');1480str = str.substring(0, 0) + 'YhIl' + str.substring(0);1481pieceTable.insert(0, 'qdsm');1482str = str.substring(0, 0) + 'qdsm' + str.substring(0);1483pieceTable.delete(7, 0);1484str = str.substring(0, 7) + str.substring(7 + 0);1485pieceTable.insert(12, 'iiPv');1486str = str.substring(0, 12) + 'iiPv' + str.substring(12);1487pieceTable.insert(9, 'V\rSA');1488str = str.substring(0, 9) + 'V\rSA' + str.substring(9);14891490testLinesContent(str, pieceTable);1491assertTreeInvariants(pieceTable);1492});14931494test('random bug 10', () => {1495let str = '\n\n\n\n';1496const pieceTree = createTextBuffer(['\n\n\n\n'], false);1497ds.add(pieceTree);1498const pieceTable = pieceTree.getPieceTree();14991500pieceTable.insert(3, '\n\r\n\r');1501str = str.substring(0, 3) + '\n\r\n\r' + str.substring(3);1502pieceTable.insert(2, '\n\r\n\n');1503str = str.substring(0, 2) + '\n\r\n\n' + str.substring(2);1504pieceTable.insert(0, '\n\n\r\r');1505str = str.substring(0, 0) + '\n\n\r\r' + str.substring(0);1506pieceTable.insert(3, '\r\r\r\r');1507str = str.substring(0, 3) + '\r\r\r\r' + str.substring(3);1508pieceTable.insert(3, '\n\n\r\r');1509str = str.substring(0, 3) + '\n\n\r\r' + str.substring(3);15101511testLinesContent(str, pieceTable);1512assertTreeInvariants(pieceTable);1513});15141515test('random chunk bug 1', () => {1516const pieceTree = createTextBuffer(['\n\r\r\n\n\n\r\n\r'], false);1517ds.add(pieceTree);1518const pieceTable = pieceTree.getPieceTree();15191520let str = '\n\r\r\n\n\n\r\n\r';1521pieceTable.delete(0, 2);1522str = str.substring(0, 0) + str.substring(0 + 2);1523pieceTable.insert(1, '\r\r\n\n');1524str = str.substring(0, 1) + '\r\r\n\n' + str.substring(1);1525pieceTable.insert(7, '\r\r\r\r');1526str = str.substring(0, 7) + '\r\r\r\r' + str.substring(7);15271528assert.strictEqual(pieceTable.getLinesRawContent(), str);1529testLineStarts(str, pieceTable);1530assertTreeInvariants(pieceTable);1531});15321533test('random chunk bug 2', () => {1534const pieceTree = createTextBuffer([1535'\n\r\n\n\n\r\n\r\n\r\r\n\n\n\r\r\n\r\n'1536], false);1537ds.add(pieceTree);1538const pieceTable = pieceTree.getPieceTree();1539let str = '\n\r\n\n\n\r\n\r\n\r\r\n\n\n\r\r\n\r\n';1540pieceTable.insert(16, '\r\n\r\r');1541str = str.substring(0, 16) + '\r\n\r\r' + str.substring(16);1542pieceTable.insert(13, '\n\n\r\r');1543str = str.substring(0, 13) + '\n\n\r\r' + str.substring(13);1544pieceTable.insert(19, '\n\n\r\n');1545str = str.substring(0, 19) + '\n\n\r\n' + str.substring(19);1546pieceTable.delete(5, 0);1547str = str.substring(0, 5) + str.substring(5 + 0);1548pieceTable.delete(11, 2);1549str = str.substring(0, 11) + str.substring(11 + 2);15501551assert.strictEqual(pieceTable.getLinesRawContent(), str);1552testLineStarts(str, pieceTable);1553assertTreeInvariants(pieceTable);1554});15551556test('random chunk bug 3', () => {1557const pieceTree = createTextBuffer(['\r\n\n\n\n\n\n\r\n'], false);1558ds.add(pieceTree);1559const pieceTable = pieceTree.getPieceTree();1560let str = '\r\n\n\n\n\n\n\r\n';1561pieceTable.insert(4, '\n\n\r\n\r\r\n\n\r');1562str = str.substring(0, 4) + '\n\n\r\n\r\r\n\n\r' + str.substring(4);1563pieceTable.delete(4, 4);1564str = str.substring(0, 4) + str.substring(4 + 4);1565pieceTable.insert(11, '\r\n\r\n\n\r\r\n\n');1566str = str.substring(0, 11) + '\r\n\r\n\n\r\r\n\n' + str.substring(11);1567pieceTable.delete(1, 2);1568str = str.substring(0, 1) + str.substring(1 + 2);15691570assert.strictEqual(pieceTable.getLinesRawContent(), str);1571testLineStarts(str, pieceTable);1572assertTreeInvariants(pieceTable);1573});15741575test('random chunk bug 4', () => {1576const pieceTree = createTextBuffer(['\n\r\n\r'], false);1577ds.add(pieceTree);1578const pieceTable = pieceTree.getPieceTree();1579let str = '\n\r\n\r';1580pieceTable.insert(4, '\n\n\r\n');1581str = str.substring(0, 4) + '\n\n\r\n' + str.substring(4);1582pieceTable.insert(3, '\r\n\n\n');1583str = str.substring(0, 3) + '\r\n\n\n' + str.substring(3);15841585assert.strictEqual(pieceTable.getLinesRawContent(), str);1586testLineStarts(str, pieceTable);1587assertTreeInvariants(pieceTable);1588});1589});15901591suite('random is unsupervised', () => {1592const ds = ensureNoDisposablesAreLeakedInTestSuite();15931594test('splitting large change buffer', function () {1595const pieceTree = createTextBuffer([''], false);1596ds.add(pieceTree);1597const pieceTable = pieceTree.getPieceTree();1598let str = '';15991600pieceTable.insert(0, 'WUZ\nXVZY\n');1601str = str.substring(0, 0) + 'WUZ\nXVZY\n' + str.substring(0);1602pieceTable.insert(8, '\r\r\nZXUWVW');1603str = str.substring(0, 8) + '\r\r\nZXUWVW' + str.substring(8);1604pieceTable.delete(10, 7);1605str = str.substring(0, 10) + str.substring(10 + 7);1606pieceTable.delete(10, 1);1607str = str.substring(0, 10) + str.substring(10 + 1);1608pieceTable.insert(4, 'VX\r\r\nWZVZ');1609str = str.substring(0, 4) + 'VX\r\r\nWZVZ' + str.substring(4);1610pieceTable.delete(11, 3);1611str = str.substring(0, 11) + str.substring(11 + 3);1612pieceTable.delete(12, 4);1613str = str.substring(0, 12) + str.substring(12 + 4);1614pieceTable.delete(8, 0);1615str = str.substring(0, 8) + str.substring(8 + 0);1616pieceTable.delete(10, 2);1617str = str.substring(0, 10) + str.substring(10 + 2);1618pieceTable.insert(0, 'VZXXZYZX\r');1619str = str.substring(0, 0) + 'VZXXZYZX\r' + str.substring(0);16201621assert.strictEqual(pieceTable.getLinesRawContent(), str);16221623testLineStarts(str, pieceTable);1624testLinesContent(str, pieceTable);1625assertTreeInvariants(pieceTable);1626});16271628test('random insert delete', function () {1629this.timeout(500000);1630let str = '';1631const pieceTree = createTextBuffer([str], false);1632ds.add(pieceTree);1633const pieceTable = pieceTree.getPieceTree();1634// let output = '';1635for (let i = 0; i < 1000; i++) {1636if (Math.random() < 0.6) {1637// insert1638const text = randomStr(100);1639const pos = randomInt(str.length + 1);1640pieceTable.insert(pos, text);1641str = str.substring(0, pos) + text + str.substring(pos);1642// output += `pieceTable.insert(${pos}, '${text.replace(/\n/g, '\\n').replace(/\r/g, '\\r')}');\n`;1643// output += `str = str.substring(0, ${pos}) + '${text.replace(/\n/g, '\\n').replace(/\r/g, '\\r')}' + str.substring(${pos});\n`;1644} else {1645// delete1646const pos = randomInt(str.length);1647const length = Math.min(1648str.length - pos,1649Math.floor(Math.random() * 10)1650);1651pieceTable.delete(pos, length);1652str = str.substring(0, pos) + str.substring(pos + length);1653// output += `pieceTable.delete(${pos}, ${length});\n`;1654// output += `str = str.substring(0, ${pos}) + str.substring(${pos} + ${length});\n`16551656}1657}1658// console.log(output);16591660assert.strictEqual(pieceTable.getLinesRawContent(), str);16611662testLineStarts(str, pieceTable);1663testLinesContent(str, pieceTable);1664assertTreeInvariants(pieceTable);1665});16661667test('random chunks', function () {1668this.timeout(500000);1669const chunks: string[] = [];1670for (let i = 0; i < 5; i++) {1671chunks.push(randomStr(1000));1672}16731674const pieceTree = createTextBuffer(chunks, false);1675ds.add(pieceTree);1676const pieceTable = pieceTree.getPieceTree();1677let str = chunks.join('');16781679for (let i = 0; i < 1000; i++) {1680if (Math.random() < 0.6) {1681// insert1682const text = randomStr(100);1683const pos = randomInt(str.length + 1);1684pieceTable.insert(pos, text);1685str = str.substring(0, pos) + text + str.substring(pos);1686} else {1687// delete1688const pos = randomInt(str.length);1689const length = Math.min(1690str.length - pos,1691Math.floor(Math.random() * 10)1692);1693pieceTable.delete(pos, length);1694str = str.substring(0, pos) + str.substring(pos + length);1695}1696}16971698assert.strictEqual(pieceTable.getLinesRawContent(), str);1699testLineStarts(str, pieceTable);1700testLinesContent(str, pieceTable);1701assertTreeInvariants(pieceTable);1702});17031704test('random chunks 2', function () {1705this.timeout(500000);1706const chunks: string[] = [];1707chunks.push(randomStr(1000));17081709const pieceTree = createTextBuffer(chunks, false);1710ds.add(pieceTree);1711const pieceTable = pieceTree.getPieceTree();1712let str = chunks.join('');17131714for (let i = 0; i < 50; i++) {1715if (Math.random() < 0.6) {1716// insert1717const text = randomStr(30);1718const pos = randomInt(str.length + 1);1719pieceTable.insert(pos, text);1720str = str.substring(0, pos) + text + str.substring(pos);1721} else {1722// delete1723const pos = randomInt(str.length);1724const length = Math.min(1725str.length - pos,1726Math.floor(Math.random() * 10)1727);1728pieceTable.delete(pos, length);1729str = str.substring(0, pos) + str.substring(pos + length);1730}1731testLinesContent(str, pieceTable);1732}17331734assert.strictEqual(pieceTable.getLinesRawContent(), str);1735testLineStarts(str, pieceTable);1736testLinesContent(str, pieceTable);1737assertTreeInvariants(pieceTable);1738});1739});17401741suite('buffer api', () => {1742const ds = ensureNoDisposablesAreLeakedInTestSuite();17431744test('equal', () => {1745const a = createTextBuffer(['abc']);1746const b = createTextBuffer(['ab', 'c']);1747const c = createTextBuffer(['abd']);1748const d = createTextBuffer(['abcd']);1749ds.add(a);1750ds.add(b);1751ds.add(c);1752ds.add(d);17531754assert(a.getPieceTree().equal(b.getPieceTree()));1755assert(!a.getPieceTree().equal(c.getPieceTree()));1756assert(!a.getPieceTree().equal(d.getPieceTree()));1757});17581759test('equal with more chunks', () => {1760const a = createTextBuffer(['ab', 'cd', 'e']);1761const b = createTextBuffer(['ab', 'c', 'de']);1762ds.add(a);1763ds.add(b);1764assert(a.getPieceTree().equal(b.getPieceTree()));1765});17661767test('equal 2, empty buffer', () => {1768const a = createTextBuffer(['']);1769const b = createTextBuffer(['']);1770ds.add(a);1771ds.add(b);17721773assert(a.getPieceTree().equal(b.getPieceTree()));1774});17751776test('equal 3, empty buffer', () => {1777const a = createTextBuffer(['a']);1778const b = createTextBuffer(['']);1779ds.add(a);1780ds.add(b);17811782assert(!a.getPieceTree().equal(b.getPieceTree()));1783});17841785test('getLineCharCode - issue #45735', () => {1786const pieceTree = createTextBuffer(['LINE1\nline2']);1787ds.add(pieceTree);1788const pieceTable = pieceTree.getPieceTree();1789assert.strictEqual(pieceTable.getLineCharCode(1, 0), 'L'.charCodeAt(0), 'L');1790assert.strictEqual(pieceTable.getLineCharCode(1, 1), 'I'.charCodeAt(0), 'I');1791assert.strictEqual(pieceTable.getLineCharCode(1, 2), 'N'.charCodeAt(0), 'N');1792assert.strictEqual(pieceTable.getLineCharCode(1, 3), 'E'.charCodeAt(0), 'E');1793assert.strictEqual(pieceTable.getLineCharCode(1, 4), '1'.charCodeAt(0), '1');1794assert.strictEqual(pieceTable.getLineCharCode(1, 5), '\n'.charCodeAt(0), '\\n');1795assert.strictEqual(pieceTable.getLineCharCode(2, 0), 'l'.charCodeAt(0), 'l');1796assert.strictEqual(pieceTable.getLineCharCode(2, 1), 'i'.charCodeAt(0), 'i');1797assert.strictEqual(pieceTable.getLineCharCode(2, 2), 'n'.charCodeAt(0), 'n');1798assert.strictEqual(pieceTable.getLineCharCode(2, 3), 'e'.charCodeAt(0), 'e');1799assert.strictEqual(pieceTable.getLineCharCode(2, 4), '2'.charCodeAt(0), '2');1800});180118021803test('getLineCharCode - issue #47733', () => {1804const pieceTree = createTextBuffer(['', 'LINE1\n', 'line2']);1805ds.add(pieceTree);1806const pieceTable = pieceTree.getPieceTree();1807assert.strictEqual(pieceTable.getLineCharCode(1, 0), 'L'.charCodeAt(0), 'L');1808assert.strictEqual(pieceTable.getLineCharCode(1, 1), 'I'.charCodeAt(0), 'I');1809assert.strictEqual(pieceTable.getLineCharCode(1, 2), 'N'.charCodeAt(0), 'N');1810assert.strictEqual(pieceTable.getLineCharCode(1, 3), 'E'.charCodeAt(0), 'E');1811assert.strictEqual(pieceTable.getLineCharCode(1, 4), '1'.charCodeAt(0), '1');1812assert.strictEqual(pieceTable.getLineCharCode(1, 5), '\n'.charCodeAt(0), '\\n');1813assert.strictEqual(pieceTable.getLineCharCode(2, 0), 'l'.charCodeAt(0), 'l');1814assert.strictEqual(pieceTable.getLineCharCode(2, 1), 'i'.charCodeAt(0), 'i');1815assert.strictEqual(pieceTable.getLineCharCode(2, 2), 'n'.charCodeAt(0), 'n');1816assert.strictEqual(pieceTable.getLineCharCode(2, 3), 'e'.charCodeAt(0), 'e');1817assert.strictEqual(pieceTable.getLineCharCode(2, 4), '2'.charCodeAt(0), '2');1818});18191820test('getNearestChunk', () => {1821const pieceTree = createTextBuffer(['012345678']);1822ds.add(pieceTree);1823const pt = pieceTree.getPieceTree();18241825pt.insert(3, 'ABC');1826assert.equal(pt.getLineContent(1), '012ABC345678');1827assert.equal(pt.getNearestChunk(3), 'ABC');1828assert.equal(pt.getNearestChunk(6), '345678');18291830pt.delete(9, 1);1831assert.equal(pt.getLineContent(1), '012ABC34578');1832assert.equal(pt.getNearestChunk(6), '345');1833assert.equal(pt.getNearestChunk(9), '78');1834});1835});18361837suite('search offset cache', () => {1838const ds = ensureNoDisposablesAreLeakedInTestSuite();18391840test('render white space exception', () => {1841const pieceTree = createTextBuffer(['class Name{\n\t\n\t\t\tget() {\n\n\t\t\t}\n\t\t}']);1842ds.add(pieceTree);1843const pieceTable = pieceTree.getPieceTree();1844let str = 'class Name{\n\t\n\t\t\tget() {\n\n\t\t\t}\n\t\t}';18451846pieceTable.insert(12, 's');1847str = str.substring(0, 12) + 's' + str.substring(12);18481849pieceTable.insert(13, 'e');1850str = str.substring(0, 13) + 'e' + str.substring(13);18511852pieceTable.insert(14, 't');1853str = str.substring(0, 14) + 't' + str.substring(14);18541855pieceTable.insert(15, '()');1856str = str.substring(0, 15) + '()' + str.substring(15);18571858pieceTable.delete(16, 1);1859str = str.substring(0, 16) + str.substring(16 + 1);18601861pieceTable.insert(17, '()');1862str = str.substring(0, 17) + '()' + str.substring(17);18631864pieceTable.delete(18, 1);1865str = str.substring(0, 18) + str.substring(18 + 1);18661867pieceTable.insert(18, '}');1868str = str.substring(0, 18) + '}' + str.substring(18);18691870pieceTable.insert(12, '\n');1871str = str.substring(0, 12) + '\n' + str.substring(12);18721873pieceTable.delete(12, 1);1874str = str.substring(0, 12) + str.substring(12 + 1);18751876pieceTable.delete(18, 1);1877str = str.substring(0, 18) + str.substring(18 + 1);18781879pieceTable.insert(18, '}');1880str = str.substring(0, 18) + '}' + str.substring(18);18811882pieceTable.delete(17, 2);1883str = str.substring(0, 17) + str.substring(17 + 2);18841885pieceTable.delete(16, 1);1886str = str.substring(0, 16) + str.substring(16 + 1);18871888pieceTable.insert(16, ')');1889str = str.substring(0, 16) + ')' + str.substring(16);18901891pieceTable.delete(15, 2);1892str = str.substring(0, 15) + str.substring(15 + 2);18931894const content = pieceTable.getLinesRawContent();1895assert(content === str);1896});18971898test('Line breaks replacement is not necessary when EOL is normalized', () => {1899const pieceTree = createTextBuffer(['abc']);1900ds.add(pieceTree);1901const pieceTable = pieceTree.getPieceTree();1902let str = 'abc';19031904pieceTable.insert(3, 'def\nabc');1905str = str + 'def\nabc';19061907testLineStarts(str, pieceTable);1908testLinesContent(str, pieceTable);1909assertTreeInvariants(pieceTable);1910});19111912test('Line breaks replacement is not necessary when EOL is normalized 2', () => {1913const pieceTree = createTextBuffer(['abc\n']);1914ds.add(pieceTree);1915const pieceTable = pieceTree.getPieceTree();1916let str = 'abc\n';19171918pieceTable.insert(4, 'def\nabc');1919str = str + 'def\nabc';19201921testLineStarts(str, pieceTable);1922testLinesContent(str, pieceTable);1923assertTreeInvariants(pieceTable);1924});19251926test('Line breaks replacement is not necessary when EOL is normalized 3', () => {1927const pieceTree = createTextBuffer(['abc\n']);1928ds.add(pieceTree);1929const pieceTable = pieceTree.getPieceTree();1930let str = 'abc\n';19311932pieceTable.insert(2, 'def\nabc');1933str = str.substring(0, 2) + 'def\nabc' + str.substring(2);19341935testLineStarts(str, pieceTable);1936testLinesContent(str, pieceTable);1937assertTreeInvariants(pieceTable);1938});19391940test('Line breaks replacement is not necessary when EOL is normalized 4', () => {1941const pieceTree = createTextBuffer(['abc\n']);1942ds.add(pieceTree);1943const pieceTable = pieceTree.getPieceTree();1944let str = 'abc\n';19451946pieceTable.insert(3, 'def\nabc');1947str = str.substring(0, 3) + 'def\nabc' + str.substring(3);19481949testLineStarts(str, pieceTable);1950testLinesContent(str, pieceTable);1951assertTreeInvariants(pieceTable);1952});19531954});19551956function getValueInSnapshot(snapshot: ITextSnapshot) {1957let ret = '';1958let tmp = snapshot.read();19591960while (tmp !== null) {1961ret += tmp;1962tmp = snapshot.read();1963}19641965return ret;1966}1967suite('snapshot', () => {1968ensureNoDisposablesAreLeakedInTestSuite();19691970test('bug #45564, piece tree pieces should be immutable', () => {1971const model = createTextModel('\n');1972model.applyEdits([1973{1974range: new Range(2, 1, 2, 1),1975text: '!'1976}1977]);1978const snapshot = model.createSnapshot();1979const snapshot1 = model.createSnapshot();1980assert.strictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot));19811982model.applyEdits([1983{1984range: new Range(2, 1, 2, 2),1985text: ''1986}1987]);1988model.applyEdits([1989{1990range: new Range(2, 1, 2, 1),1991text: '!'1992}1993]);19941995assert.strictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot1));19961997model.dispose();1998});19992000test('immutable snapshot 1', () => {2001const model = createTextModel('abc\ndef');2002const snapshot = model.createSnapshot();2003model.applyEdits([2004{2005range: new Range(2, 1, 2, 4),2006text: ''2007}2008]);20092010model.applyEdits([2011{2012range: new Range(1, 1, 2, 1),2013text: 'abc\ndef'2014}2015]);20162017assert.strictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot));20182019model.dispose();2020});20212022test('immutable snapshot 2', () => {2023const model = createTextModel('abc\ndef');2024const snapshot = model.createSnapshot();2025model.applyEdits([2026{2027range: new Range(2, 1, 2, 1),2028text: '!'2029}2030]);20312032model.applyEdits([2033{2034range: new Range(2, 1, 2, 2),2035text: ''2036}2037]);20382039assert.strictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot));20402041model.dispose();2042});20432044test('immutable snapshot 3', () => {2045const model = createTextModel('abc\ndef');2046model.applyEdits([2047{2048range: new Range(2, 4, 2, 4),2049text: '!'2050}2051]);2052const snapshot = model.createSnapshot();2053model.applyEdits([2054{2055range: new Range(2, 5, 2, 5),2056text: '!'2057}2058]);20592060assert.notStrictEqual(model.getLinesContent().join('\n'), getValueInSnapshot(snapshot));20612062model.dispose();2063});2064});20652066suite('chunk based search', () => {2067const ds = ensureNoDisposablesAreLeakedInTestSuite();20682069test('#45892. For some cases, the buffer is empty but we still try to search', () => {2070const pieceTree = createTextBuffer(['']);2071ds.add(pieceTree);2072const pieceTable = pieceTree.getPieceTree();2073pieceTable.delete(0, 1);2074const ret = pieceTree.findMatchesLineByLine(new Range(1, 1, 1, 1), new SearchData(/abc/, new WordCharacterClassifier(',./', []), 'abc'), true, 1000);2075assert.strictEqual(ret.length, 0);2076});20772078test('#45770. FindInNode should not cross node boundary.', () => {2079const pieceTree = createTextBuffer([2080[2081'balabalababalabalababalabalaba',2082'balabalababalabalababalabalaba',2083'',2084'* [ ] task1',2085'* [x] task2 balabalaba',2086'* [ ] task 3'2087].join('\n')2088]);2089ds.add(pieceTree);2090const pieceTable = pieceTree.getPieceTree();20912092pieceTable.delete(0, 62);2093pieceTable.delete(16, 1);20942095pieceTable.insert(16, ' ');2096const ret = pieceTable.findMatchesLineByLine(new Range(1, 1, 4, 13), new SearchData(/\[/gi, new WordCharacterClassifier(',./', []), '['), true, 1000);2097assert.strictEqual(ret.length, 3);20982099assert.deepStrictEqual(ret[0].range, new Range(2, 3, 2, 4));2100assert.deepStrictEqual(ret[1].range, new Range(3, 3, 3, 4));2101assert.deepStrictEqual(ret[2].range, new Range(4, 3, 4, 4));2102});21032104test('search searching from the middle', () => {2105const pieceTree = createTextBuffer([2106[2107'def',2108'dbcabc'2109].join('\n')2110]);2111ds.add(pieceTree);2112const pieceTable = pieceTree.getPieceTree();21132114pieceTable.delete(4, 1);2115let ret = pieceTable.findMatchesLineByLine(new Range(2, 3, 2, 6), new SearchData(/a/gi, null, 'a'), true, 1000);2116assert.strictEqual(ret.length, 1);2117assert.deepStrictEqual(ret[0].range, new Range(2, 3, 2, 4));21182119pieceTable.delete(4, 1);2120ret = pieceTable.findMatchesLineByLine(new Range(2, 2, 2, 5), new SearchData(/a/gi, null, 'a'), true, 1000);2121assert.strictEqual(ret.length, 1);2122assert.deepStrictEqual(ret[0].range, new Range(2, 2, 2, 3));2123});2124});212521262127