Path: blob/main/src/vs/editor/test/common/viewLayout/lineHeights.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 { LineHeightsManager } from '../../../common/viewLayout/lineHeights.js';7import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';89suite('Editor ViewLayout - LineHeightsManager', () => {1011ensureNoDisposablesAreLeakedInTestSuite();1213test('default line height is used when no custom heights exist', () => {14const manager = new LineHeightsManager(10, []);1516// Check individual line heights17assert.strictEqual(manager.heightForLineNumber(1), 10);18assert.strictEqual(manager.heightForLineNumber(5), 10);19assert.strictEqual(manager.heightForLineNumber(100), 10);2021// Check accumulated heights22assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(1), 10);23assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(5), 50);24assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(10), 100);25});2627test('can change default line height', () => {28const manager = new LineHeightsManager(10, []);29manager.defaultLineHeight = 20;3031// Check individual line heights32assert.strictEqual(manager.heightForLineNumber(1), 20);33assert.strictEqual(manager.heightForLineNumber(5), 20);3435// Check accumulated heights36assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(1), 20);37assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(5), 100);38});3940test('can add single custom line height', () => {41const manager = new LineHeightsManager(10, []);42manager.insertOrChangeCustomLineHeight('dec1', 3, 3, 20);43manager.commit();4445// Check individual line heights46assert.strictEqual(manager.heightForLineNumber(1), 10);47assert.strictEqual(manager.heightForLineNumber(2), 10);48assert.strictEqual(manager.heightForLineNumber(3), 20);49assert.strictEqual(manager.heightForLineNumber(4), 10);5051// Check accumulated heights52assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(1), 10);53assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(2), 20);54assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(3), 40);55assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(4), 50);56});5758test('can add multiple custom line heights', () => {59const manager = new LineHeightsManager(10, []);60manager.insertOrChangeCustomLineHeight('dec1', 2, 2, 15);61manager.insertOrChangeCustomLineHeight('dec2', 4, 4, 25);62manager.commit();6364// Check individual line heights65assert.strictEqual(manager.heightForLineNumber(1), 10);66assert.strictEqual(manager.heightForLineNumber(2), 15);67assert.strictEqual(manager.heightForLineNumber(3), 10);68assert.strictEqual(manager.heightForLineNumber(4), 25);69assert.strictEqual(manager.heightForLineNumber(5), 10);7071// Check accumulated heights72assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(1), 10);73assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(2), 25);74assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(3), 35);75assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(4), 60);76assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(5), 70);77});7879test('can add range of custom line heights', () => {80const manager = new LineHeightsManager(10, []);81manager.insertOrChangeCustomLineHeight('dec1', 2, 4, 15);82manager.commit();8384// Check individual line heights85assert.strictEqual(manager.heightForLineNumber(1), 10);86assert.strictEqual(manager.heightForLineNumber(2), 15);87assert.strictEqual(manager.heightForLineNumber(3), 15);88assert.strictEqual(manager.heightForLineNumber(4), 15);89assert.strictEqual(manager.heightForLineNumber(5), 10);9091// Check accumulated heights92assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(1), 10);93assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(2), 25);94assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(3), 40);95assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(4), 55);96assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(5), 65);97});9899test('can change existing custom line height', () => {100const manager = new LineHeightsManager(10, []);101manager.insertOrChangeCustomLineHeight('dec1', 3, 3, 20);102manager.commit();103assert.strictEqual(manager.heightForLineNumber(3), 20);104105manager.insertOrChangeCustomLineHeight('dec1', 3, 3, 30);106manager.commit();107assert.strictEqual(manager.heightForLineNumber(3), 30);108109// Check accumulated heights after change110assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(3), 50);111assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(4), 60);112});113114test('can remove custom line height', () => {115const manager = new LineHeightsManager(10, []);116manager.insertOrChangeCustomLineHeight('dec1', 3, 3, 20);117manager.commit();118assert.strictEqual(manager.heightForLineNumber(3), 20);119120manager.removeCustomLineHeight('dec1');121manager.commit();122assert.strictEqual(manager.heightForLineNumber(3), 10);123124// Check accumulated heights after removal125assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(3), 30);126assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(4), 40);127});128129test('handles overlapping custom line heights (last one wins)', () => {130const manager = new LineHeightsManager(10, []);131manager.insertOrChangeCustomLineHeight('dec1', 3, 5, 20);132manager.insertOrChangeCustomLineHeight('dec2', 4, 6, 30);133manager.commit();134135assert.strictEqual(manager.heightForLineNumber(2), 10);136assert.strictEqual(manager.heightForLineNumber(3), 20);137assert.strictEqual(manager.heightForLineNumber(4), 30);138assert.strictEqual(manager.heightForLineNumber(5), 30);139assert.strictEqual(manager.heightForLineNumber(6), 30);140assert.strictEqual(manager.heightForLineNumber(7), 10);141});142143test('handles deleting lines before custom line heights', () => {144const manager = new LineHeightsManager(10, []);145manager.insertOrChangeCustomLineHeight('dec1', 10, 12, 20);146manager.commit();147148manager.onLinesDeleted(5, 7); // Delete lines 5-7149150assert.strictEqual(manager.heightForLineNumber(7), 20); // Was line 10151assert.strictEqual(manager.heightForLineNumber(8), 20); // Was line 11152assert.strictEqual(manager.heightForLineNumber(9), 20); // Was line 12153assert.strictEqual(manager.heightForLineNumber(10), 10);154});155156test('handles deleting lines overlapping with custom line heights', () => {157const manager = new LineHeightsManager(10, []);158manager.insertOrChangeCustomLineHeight('dec1', 5, 10, 20);159manager.commit();160161manager.onLinesDeleted(7, 12); // Delete lines 7-12, including part of decoration162163assert.strictEqual(manager.heightForLineNumber(5), 20);164assert.strictEqual(manager.heightForLineNumber(6), 20);165assert.strictEqual(manager.heightForLineNumber(7), 10);166});167168test('handles deleting lines containing custom line heights completely', () => {169const manager = new LineHeightsManager(10, []);170manager.insertOrChangeCustomLineHeight('dec1', 5, 7, 20);171manager.commit();172173manager.onLinesDeleted(4, 8); // Delete lines 4-8, completely contains decoration174175// The decoration collapses to a single line which matches the behavior in the text buffer176assert.strictEqual(manager.heightForLineNumber(3), 10);177assert.strictEqual(manager.heightForLineNumber(4), 20);178assert.strictEqual(manager.heightForLineNumber(5), 10);179});180181test('handles deleting lines at the very beginning', () => {182const manager = new LineHeightsManager(10, []);183manager.insertOrChangeCustomLineHeight('decA', 1, 1, 40);184manager.commit();185186manager.onLinesDeleted(2, 4); // Delete lines 2-4 after the variable line height187188// Check individual line heights189assert.strictEqual(manager.heightForLineNumber(1), 40);190});191192test('handles inserting lines before custom line heights', () => {193const manager = new LineHeightsManager(10, []);194manager.insertOrChangeCustomLineHeight('dec1', 5, 7, 20);195manager.commit();196197manager.onLinesInserted(3, 4); // Insert 2 lines at line 3198199assert.strictEqual(manager.heightForLineNumber(5), 10);200assert.strictEqual(manager.heightForLineNumber(6), 10);201assert.strictEqual(manager.heightForLineNumber(7), 20); // Was line 5202assert.strictEqual(manager.heightForLineNumber(8), 20); // Was line 6203assert.strictEqual(manager.heightForLineNumber(9), 20); // Was line 7204});205206test('handles inserting lines inside custom line heights range', () => {207const manager = new LineHeightsManager(10, []);208manager.insertOrChangeCustomLineHeight('dec1', 5, 7, 20);209manager.commit();210211manager.onLinesInserted(6, 7); // Insert 2 lines at line 6212213assert.strictEqual(manager.heightForLineNumber(5), 20);214assert.strictEqual(manager.heightForLineNumber(6), 20);215assert.strictEqual(manager.heightForLineNumber(7), 20);216assert.strictEqual(manager.heightForLineNumber(8), 20);217assert.strictEqual(manager.heightForLineNumber(9), 20);218});219220test('changing decoration id maintains custom line height', () => {221const manager = new LineHeightsManager(10, []);222manager.insertOrChangeCustomLineHeight('dec1', 5, 7, 20);223manager.commit();224225manager.removeCustomLineHeight('dec1');226manager.insertOrChangeCustomLineHeight('dec2', 5, 7, 20);227manager.commit();228229assert.strictEqual(manager.heightForLineNumber(5), 20);230assert.strictEqual(manager.heightForLineNumber(6), 20);231assert.strictEqual(manager.heightForLineNumber(7), 20);232});233234test('accumulates heights correctly with complex setup', () => {235const manager = new LineHeightsManager(10, []);236manager.insertOrChangeCustomLineHeight('dec1', 3, 3, 15);237manager.insertOrChangeCustomLineHeight('dec2', 5, 7, 20);238manager.insertOrChangeCustomLineHeight('dec3', 10, 10, 30);239manager.commit();240241// Check accumulated heights242assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(1), 10);243assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(2), 20);244assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(3), 35);245assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(4), 45);246assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(5), 65);247assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(7), 105);248assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(9), 125);249assert.strictEqual(manager.getAccumulatedLineHeightsIncludingLineNumber(10), 155);250});251252test('partial deletion with multiple lines for the same decoration ID', () => {253const manager = new LineHeightsManager(10, []);254manager.insertOrChangeCustomLineHeight('decSame', 5, 5, 20);255manager.insertOrChangeCustomLineHeight('decSame', 6, 6, 25);256manager.commit();257258// Delete one line that partially intersects the same decoration259manager.onLinesDeleted(6, 6);260261// Check individual line heights262assert.strictEqual(manager.heightForLineNumber(5), 20);263assert.strictEqual(manager.heightForLineNumber(6), 10);264});265266test('overlapping decorations use maximum line height', () => {267const manager = new LineHeightsManager(10, []);268manager.insertOrChangeCustomLineHeight('decA', 3, 5, 40);269manager.insertOrChangeCustomLineHeight('decB', 4, 6, 30);270manager.commit();271272// Check individual line heights273assert.strictEqual(manager.heightForLineNumber(3), 40);274assert.strictEqual(manager.heightForLineNumber(4), 40);275assert.strictEqual(manager.heightForLineNumber(5), 40);276assert.strictEqual(manager.heightForLineNumber(6), 30);277});278});279280281