Path: blob/main/src/vs/editor/contrib/folding/test/browser/foldingRanges.test.ts
5260 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 { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';7import { FoldingMarkers } from '../../../../common/languages/languageConfiguration.js';8import { MAX_FOLDING_REGIONS, FoldRange, FoldingRegions, FoldSource } from '../../browser/foldingRanges.js';9import { RangesCollector, computeRanges } from '../../browser/indentRangeProvider.js';10import { createTextModel } from '../../../../test/common/testTextModel.js';1112const markers: FoldingMarkers = {13start: /^#region$/,14end: /^#endregion$/15};1617suite('FoldingRanges', () => {18ensureNoDisposablesAreLeakedInTestSuite();19const foldRange = (from: number, to: number, collapsed: boolean | undefined = undefined, source: FoldSource = FoldSource.provider, type: string | undefined = undefined) =>20<FoldRange>{21startLineNumber: from,22endLineNumber: to,23type: type,24isCollapsed: collapsed || false,25source26};27const assertEqualRanges = (range1: FoldRange, range2: FoldRange, msg: string) => {28assert.strictEqual(range1.startLineNumber, range2.startLineNumber, msg + ' start');29assert.strictEqual(range1.endLineNumber, range2.endLineNumber, msg + ' end');30assert.strictEqual(range1.type, range2.type, msg + ' type');31assert.strictEqual(range1.isCollapsed, range2.isCollapsed, msg + ' collapsed');32assert.strictEqual(range1.source, range2.source, msg + ' source');33};3435test('test max folding regions', () => {36const lines: string[] = [];37const nRegions = MAX_FOLDING_REGIONS;38const collector = new RangesCollector({ limit: MAX_FOLDING_REGIONS, update: () => { } });39for (let i = 0; i < nRegions; i++) {40const startLineNumber = lines.length;41lines.push('#region');42const endLineNumber = lines.length;43lines.push('#endregion');44collector.insertFirst(startLineNumber, endLineNumber, 0);45}46const model = createTextModel(lines.join('\n'));47const actual = collector.toIndentRanges(model);48assert.strictEqual(actual.length, nRegions, 'len');49model.dispose();5051});5253test('findRange', () => {54const lines = [55/* 1*/ '#region',56/* 2*/ '#endregion',57/* 3*/ 'class A {',58/* 4*/ ' void foo() {',59/* 5*/ ' if (true) {',60/* 6*/ ' return;',61/* 7*/ ' }',62/* 8*/ '',63/* 9*/ ' if (true) {',64/* 10*/ ' return;',65/* 11*/ ' }',66/* 12*/ ' }',67/* 13*/ '}'];6869const textModel = createTextModel(lines.join('\n'));70try {71const actual = computeRanges(textModel, false, markers);72// let r0 = r(1, 2);73// let r1 = r(3, 12);74// let r2 = r(4, 11);75// let r3 = r(5, 6);76// let r4 = r(9, 10);7778assert.strictEqual(actual.findRange(1), 0, '1');79assert.strictEqual(actual.findRange(2), 0, '2');80assert.strictEqual(actual.findRange(3), 1, '3');81assert.strictEqual(actual.findRange(4), 2, '4');82assert.strictEqual(actual.findRange(5), 3, '5');83assert.strictEqual(actual.findRange(6), 3, '6');84assert.strictEqual(actual.findRange(7), 2, '7');85assert.strictEqual(actual.findRange(8), 2, '8');86assert.strictEqual(actual.findRange(9), 4, '9');87assert.strictEqual(actual.findRange(10), 4, '10');88assert.strictEqual(actual.findRange(11), 2, '11');89assert.strictEqual(actual.findRange(12), 1, '12');90assert.strictEqual(actual.findRange(13), -1, '13');91} finally {92textModel.dispose();93}949596});9798test('setCollapsed', () => {99const lines: string[] = [];100const nRegions = 500;101for (let i = 0; i < nRegions; i++) {102lines.push('#region');103}104for (let i = 0; i < nRegions; i++) {105lines.push('#endregion');106}107const model = createTextModel(lines.join('\n'));108const actual = computeRanges(model, false, markers);109assert.strictEqual(actual.length, nRegions, 'len');110for (let i = 0; i < nRegions; i++) {111actual.setCollapsed(i, i % 3 === 0);112}113for (let i = 0; i < nRegions; i++) {114assert.strictEqual(actual.isCollapsed(i), i % 3 === 0, 'line' + i);115}116model.dispose();117});118119test('sanitizeAndMerge1', () => {120const regionSet1: FoldRange[] = [121foldRange(0, 100), // invalid, should be removed122foldRange(1, 100, false, FoldSource.provider, 'A'), // valid123foldRange(1, 100, false, FoldSource.provider, 'Z'), // invalid, duplicate start124foldRange(10, 10, false), // invalid, should be removed125foldRange(20, 80, false, FoldSource.provider, 'C1'), // valid inside 'B'126foldRange(22, 80, true, FoldSource.provider, 'D1'), // valid inside 'C1'127foldRange(90, 101), // invalid, should be removed128];129const regionSet2: FoldRange[] = [130foldRange(20, 80, true), // should merge with C1131foldRange(18, 80, true), // invalid, out of order132foldRange(21, 81, true, FoldSource.provider, 'Z'), // invalid, overlapping133foldRange(22, 80, true, FoldSource.provider, 'D2'), // should merge with D1134];135const result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);136assert.strictEqual(result.length, 3, 'result length1');137assertEqualRanges(result[0], foldRange(1, 100, false, FoldSource.provider, 'A'), 'A1');138assertEqualRanges(result[1], foldRange(20, 80, true, FoldSource.provider, 'C1'), 'C1');139assertEqualRanges(result[2], foldRange(22, 80, true, FoldSource.provider, 'D1'), 'D1');140});141142test('sanitizeAndMerge2', () => {143const regionSet1: FoldRange[] = [144foldRange(1, 100, false, FoldSource.provider, 'a1'), // valid145foldRange(2, 100, false, FoldSource.provider, 'a2'), // valid146foldRange(3, 19, false, FoldSource.provider, 'a3'), // valid147foldRange(20, 71, false, FoldSource.provider, 'a4'), // overlaps b3148foldRange(21, 29, false, FoldSource.provider, 'a5'), // valid149foldRange(81, 91, false, FoldSource.provider, 'a6'), // overlaps b4150];151const regionSet2: FoldRange[] = [152foldRange(30, 39, true, FoldSource.provider, 'b1'), // valid, will be recovered153foldRange(40, 49, true, FoldSource.userDefined, 'b2'), // valid154foldRange(50, 100, true, FoldSource.userDefined, 'b3'), // overlaps a4155foldRange(80, 90, true, FoldSource.userDefined, 'b4'), // overlaps a6156foldRange(92, 100, true, FoldSource.userDefined, 'b5'), // valid157];158const result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);159assert.strictEqual(result.length, 9, 'result length1');160assertEqualRanges(result[0], foldRange(1, 100, false, FoldSource.provider, 'a1'), 'P1');161assertEqualRanges(result[1], foldRange(2, 100, false, FoldSource.provider, 'a2'), 'P2');162assertEqualRanges(result[2], foldRange(3, 19, false, FoldSource.provider, 'a3'), 'P3');163assertEqualRanges(result[3], foldRange(21, 29, false, FoldSource.provider, 'a5'), 'P4');164assertEqualRanges(result[4], foldRange(30, 39, true, FoldSource.recovered, 'b1'), 'P5');165assertEqualRanges(result[5], foldRange(40, 49, true, FoldSource.userDefined, 'b2'), 'P6');166assertEqualRanges(result[6], foldRange(50, 100, true, FoldSource.userDefined, 'b3'), 'P7');167assertEqualRanges(result[7], foldRange(80, 90, true, FoldSource.userDefined, 'b4'), 'P8');168assertEqualRanges(result[8], foldRange(92, 100, true, FoldSource.userDefined, 'b5'), 'P9');169});170171test('sanitizeAndMerge3', () => {172const regionSet1: FoldRange[] = [173foldRange(1, 100, false, FoldSource.provider, 'a1'), // valid174foldRange(10, 29, false, FoldSource.provider, 'a2'), // matches manual hidden175foldRange(35, 39, true, FoldSource.recovered, 'a3'), // valid176];177const regionSet2: FoldRange[] = [178foldRange(10, 29, true, FoldSource.recovered, 'b1'), // matches a179foldRange(20, 28, true, FoldSource.provider, 'b2'), // should remain180foldRange(30, 39, true, FoldSource.recovered, 'b3'), // should remain181];182const result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);183assert.strictEqual(result.length, 5, 'result length3');184assertEqualRanges(result[0], foldRange(1, 100, false, FoldSource.provider, 'a1'), 'R1');185assertEqualRanges(result[1], foldRange(10, 29, true, FoldSource.provider, 'a2'), 'R2');186assertEqualRanges(result[2], foldRange(20, 28, true, FoldSource.recovered, 'b2'), 'R3');187assertEqualRanges(result[3], foldRange(30, 39, true, FoldSource.recovered, 'b3'), 'R3');188assertEqualRanges(result[4], foldRange(35, 39, true, FoldSource.recovered, 'a3'), 'R4');189});190191test('sanitizeAndMerge4', () => {192const regionSet1: FoldRange[] = [193foldRange(1, 100, false, FoldSource.provider, 'a1'), // valid194];195const regionSet2: FoldRange[] = [196foldRange(20, 28, true, FoldSource.provider, 'b1'), // hidden197foldRange(30, 38, true, FoldSource.provider, 'b2'), // hidden198];199const result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);200assert.strictEqual(result.length, 3, 'result length4');201assertEqualRanges(result[0], foldRange(1, 100, false, FoldSource.provider, 'a1'), 'R1');202assertEqualRanges(result[1], foldRange(20, 28, true, FoldSource.recovered, 'b1'), 'R2');203assertEqualRanges(result[2], foldRange(30, 38, true, FoldSource.recovered, 'b2'), 'R3');204});205206});207208209