Path: blob/main/src/vs/editor/test/browser/viewModel/modelLineProjection.test.ts
5240 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 { IDisposable } from '../../../../base/common/lifecycle.js';7import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';8import { EditorOption } from '../../../common/config/editorOptions.js';9import { Position } from '../../../common/core/position.js';10import { IRange, Range } from '../../../common/core/range.js';11import { MetadataConsts } from '../../../common/encodedTokenAttributes.js';12import * as languages from '../../../common/languages.js';13import { NullState } from '../../../common/languages/nullTokenize.js';14import { EndOfLinePreference } from '../../../common/model.js';15import { TextModel } from '../../../common/model/textModel.js';16import { ModelLineProjectionData } from '../../../common/modelLineProjectionData.js';17import { IViewLineTokens } from '../../../common/tokens/lineTokens.js';18import { ViewLineData } from '../../../common/viewModel.js';19import { IModelLineProjection, ISimpleModel, createModelLineProjection } from '../../../common/viewModel/modelLineProjection.js';20import { MonospaceLineBreaksComputerFactory } from '../../../common/viewModel/monospaceLineBreaksComputer.js';21import { ViewModelLinesFromProjectedModel } from '../../../common/viewModel/viewModelLines.js';22import { TestConfiguration } from '../config/testConfiguration.js';23import { createTextModel } from '../../common/testTextModel.js';2425suite('Editor ViewModel - SplitLinesCollection', () => {2627ensureNoDisposablesAreLeakedInTestSuite();2829test('SplitLine', () => {30let model1 = createModel('My First LineMy Second LineAnd another one');31let line1 = createSplitLine([13, 14, 15], [13, 13 + 14, 13 + 14 + 15], 0);3233assert.strictEqual(line1.getViewLineCount(), 3);34assert.strictEqual(line1.getViewLineContent(model1, 1, 0), 'My First Line');35assert.strictEqual(line1.getViewLineContent(model1, 1, 1), 'My Second Line');36assert.strictEqual(line1.getViewLineContent(model1, 1, 2), 'And another one');37assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 0), 14);38assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 1), 15);39assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 2), 16);40for (let col = 1; col <= 14; col++) {41assert.strictEqual(line1.getModelColumnOfViewPosition(0, col), col, 'getInputColumnOfOutputPosition(0, ' + col + ')');42}43for (let col = 1; col <= 15; col++) {44assert.strictEqual(line1.getModelColumnOfViewPosition(1, col), 13 + col, 'getInputColumnOfOutputPosition(1, ' + col + ')');45}46for (let col = 1; col <= 16; col++) {47assert.strictEqual(line1.getModelColumnOfViewPosition(2, col), 13 + 14 + col, 'getInputColumnOfOutputPosition(2, ' + col + ')');48}49for (let col = 1; col <= 13; col++) {50assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), 'getOutputPositionOfInputPosition(' + col + ')');51}52for (let col = 1 + 13; col <= 14 + 13; col++) {53assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, col - 13), 'getOutputPositionOfInputPosition(' + col + ')');54}55for (let col = 1 + 13 + 14; col <= 15 + 14 + 13; col++) {56assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, col - 13 - 14), 'getOutputPositionOfInputPosition(' + col + ')');57}5859model1 = createModel('My First LineMy Second LineAnd another one');60line1 = createSplitLine([13, 14, 15], [13, 13 + 14, 13 + 14 + 15], 4);6162assert.strictEqual(line1.getViewLineCount(), 3);63assert.strictEqual(line1.getViewLineContent(model1, 1, 0), 'My First Line');64assert.strictEqual(line1.getViewLineContent(model1, 1, 1), ' My Second Line');65assert.strictEqual(line1.getViewLineContent(model1, 1, 2), ' And another one');66assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 0), 14);67assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 1), 19);68assert.strictEqual(line1.getViewLineMaxColumn(model1, 1, 2), 20);6970const actualViewColumnMapping: number[][] = [];71for (let lineIndex = 0; lineIndex < line1.getViewLineCount(); lineIndex++) {72const actualLineViewColumnMapping: number[] = [];73for (let col = 1; col <= line1.getViewLineMaxColumn(model1, 1, lineIndex); col++) {74actualLineViewColumnMapping.push(line1.getModelColumnOfViewPosition(lineIndex, col));75}76actualViewColumnMapping.push(actualLineViewColumnMapping);77}78assert.deepStrictEqual(actualViewColumnMapping, [79[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],80[14, 14, 14, 14, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28],81[28, 28, 28, 28, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43],82]);8384for (let col = 1; col <= 13; col++) {85assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(0, col), '6.getOutputPositionOfInputPosition(' + col + ')');86}87for (let col = 1 + 13; col <= 14 + 13; col++) {88assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(1, 4 + col - 13), '7.getOutputPositionOfInputPosition(' + col + ')');89}90for (let col = 1 + 13 + 14; col <= 15 + 14 + 13; col++) {91assert.deepStrictEqual(line1.getViewPositionOfModelPosition(0, col), pos(2, 4 + col - 13 - 14), '8.getOutputPositionOfInputPosition(' + col + ')');92}93});9495function withSplitLinesCollection(text: string, callback: (model: TextModel, linesCollection: ViewModelLinesFromProjectedModel) => void): void {96const config = new TestConfiguration({});97const wrappingInfo = config.options.get(EditorOption.wrappingInfo);98const fontInfo = config.options.get(EditorOption.fontInfo);99const wordWrapBreakAfterCharacters = config.options.get(EditorOption.wordWrapBreakAfterCharacters);100const wordWrapBreakBeforeCharacters = config.options.get(EditorOption.wordWrapBreakBeforeCharacters);101const wrappingIndent = config.options.get(EditorOption.wrappingIndent);102const wordBreak = config.options.get(EditorOption.wordBreak);103const wrapOnEscapedLineFeeds = config.options.get(EditorOption.wrapOnEscapedLineFeeds);104const lineBreaksComputerFactory = new MonospaceLineBreaksComputerFactory(wordWrapBreakBeforeCharacters, wordWrapBreakAfterCharacters);105106const model = createTextModel(text);107108const linesCollection = new ViewModelLinesFromProjectedModel(1091,110model,111lineBreaksComputerFactory,112lineBreaksComputerFactory,113fontInfo,114model.getOptions().tabSize,115'simple',116wrappingInfo.wrappingColumn,117wrappingIndent,118wordBreak,119wrapOnEscapedLineFeeds120);121122callback(model, linesCollection);123124linesCollection.dispose();125model.dispose();126config.dispose();127}128129test('Invalid line numbers', () => {130131const text = [132'int main() {',133'\tprintf("Hello world!");',134'}',135'int main() {',136'\tprintf("Hello world!");',137'}',138].join('\n');139140withSplitLinesCollection(text, (model, linesCollection) => {141assert.strictEqual(linesCollection.getViewLineCount(), 6);142143// getOutputIndentGuide144assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(-1, -1), [0]);145assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(0, 0), [0]);146assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(1, 1), [0]);147assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(2, 2), [1]);148assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(3, 3), [0]);149assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(4, 4), [0]);150assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(5, 5), [1]);151assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(6, 6), [0]);152assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(7, 7), [0]);153154assert.deepStrictEqual(linesCollection.getViewLinesIndentGuides(0, 7), [0, 1, 0, 0, 1, 0]);155156// getOutputLineContent157assert.strictEqual(linesCollection.getViewLineContent(-1), 'int main() {');158assert.strictEqual(linesCollection.getViewLineContent(0), 'int main() {');159assert.strictEqual(linesCollection.getViewLineContent(1), 'int main() {');160assert.strictEqual(linesCollection.getViewLineContent(2), '\tprintf("Hello world!");');161assert.strictEqual(linesCollection.getViewLineContent(3), '}');162assert.strictEqual(linesCollection.getViewLineContent(4), 'int main() {');163assert.strictEqual(linesCollection.getViewLineContent(5), '\tprintf("Hello world!");');164assert.strictEqual(linesCollection.getViewLineContent(6), '}');165assert.strictEqual(linesCollection.getViewLineContent(7), '}');166167// getOutputLineMinColumn168assert.strictEqual(linesCollection.getViewLineMinColumn(-1), 1);169assert.strictEqual(linesCollection.getViewLineMinColumn(0), 1);170assert.strictEqual(linesCollection.getViewLineMinColumn(1), 1);171assert.strictEqual(linesCollection.getViewLineMinColumn(2), 1);172assert.strictEqual(linesCollection.getViewLineMinColumn(3), 1);173assert.strictEqual(linesCollection.getViewLineMinColumn(4), 1);174assert.strictEqual(linesCollection.getViewLineMinColumn(5), 1);175assert.strictEqual(linesCollection.getViewLineMinColumn(6), 1);176assert.strictEqual(linesCollection.getViewLineMinColumn(7), 1);177178// getOutputLineMaxColumn179assert.strictEqual(linesCollection.getViewLineMaxColumn(-1), 13);180assert.strictEqual(linesCollection.getViewLineMaxColumn(0), 13);181assert.strictEqual(linesCollection.getViewLineMaxColumn(1), 13);182assert.strictEqual(linesCollection.getViewLineMaxColumn(2), 25);183assert.strictEqual(linesCollection.getViewLineMaxColumn(3), 2);184assert.strictEqual(linesCollection.getViewLineMaxColumn(4), 13);185assert.strictEqual(linesCollection.getViewLineMaxColumn(5), 25);186assert.strictEqual(linesCollection.getViewLineMaxColumn(6), 2);187assert.strictEqual(linesCollection.getViewLineMaxColumn(7), 2);188189// convertOutputPositionToInputPosition190assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(-1, 1), new Position(1, 1));191assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(0, 1), new Position(1, 1));192assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(1, 1), new Position(1, 1));193assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(2, 1), new Position(2, 1));194assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(3, 1), new Position(3, 1));195assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(4, 1), new Position(4, 1));196assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(5, 1), new Position(5, 1));197assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(6, 1), new Position(6, 1));198assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(7, 1), new Position(6, 1));199assert.deepStrictEqual(linesCollection.convertViewPositionToModelPosition(8, 1), new Position(6, 1));200});201});202203test('issue #3662', () => {204205const text = [206'int main() {',207'\tprintf("Hello world!");',208'}',209'int main() {',210'\tprintf("Hello world!");',211'}',212].join('\n');213214withSplitLinesCollection(text, (model, linesCollection) => {215linesCollection.setHiddenAreas([216new Range(1, 1, 3, 1),217new Range(5, 1, 6, 1)218]);219220const viewLineCount = linesCollection.getViewLineCount();221assert.strictEqual(viewLineCount, 1, 'getOutputLineCount()');222223const modelLineCount = model.getLineCount();224for (let lineNumber = 0; lineNumber <= modelLineCount + 1; lineNumber++) {225const lineMinColumn = (lineNumber >= 1 && lineNumber <= modelLineCount) ? model.getLineMinColumn(lineNumber) : 1;226const lineMaxColumn = (lineNumber >= 1 && lineNumber <= modelLineCount) ? model.getLineMaxColumn(lineNumber) : 1;227for (let column = lineMinColumn - 1; column <= lineMaxColumn + 1; column++) {228const viewPosition = linesCollection.convertModelPositionToViewPosition(lineNumber, column);229230// validate view position231let viewLineNumber = viewPosition.lineNumber;232let viewColumn = viewPosition.column;233if (viewLineNumber < 1) {234viewLineNumber = 1;235}236const lineCount = linesCollection.getViewLineCount();237if (viewLineNumber > lineCount) {238viewLineNumber = lineCount;239}240const viewMinColumn = linesCollection.getViewLineMinColumn(viewLineNumber);241const viewMaxColumn = linesCollection.getViewLineMaxColumn(viewLineNumber);242if (viewColumn < viewMinColumn) {243viewColumn = viewMinColumn;244}245if (viewColumn > viewMaxColumn) {246viewColumn = viewMaxColumn;247}248const validViewPosition = new Position(viewLineNumber, viewColumn);249assert.strictEqual(viewPosition.toString(), validViewPosition.toString(), 'model->view for ' + lineNumber + ', ' + column);250}251}252253for (let lineNumber = 0; lineNumber <= viewLineCount + 1; lineNumber++) {254const lineMinColumn = linesCollection.getViewLineMinColumn(lineNumber);255const lineMaxColumn = linesCollection.getViewLineMaxColumn(lineNumber);256for (let column = lineMinColumn - 1; column <= lineMaxColumn + 1; column++) {257const modelPosition = linesCollection.convertViewPositionToModelPosition(lineNumber, column);258const validModelPosition = model.validatePosition(modelPosition);259assert.strictEqual(modelPosition.toString(), validModelPosition.toString(), 'view->model for ' + lineNumber + ', ' + column);260}261}262});263});264265});266267suite('SplitLinesCollection', () => {268269const _text = [270'class Nice {',271' function hi() {',272' console.log("Hello world");',273' }',274' function hello() {',275' console.log("Hello world, this is a somewhat longer line");',276' }',277'}',278];279280const _tokens = [281[282{ startIndex: 0, value: 1 },283{ startIndex: 5, value: 2 },284{ startIndex: 6, value: 3 },285{ startIndex: 10, value: 4 },286],287[288{ startIndex: 0, value: 5 },289{ startIndex: 1, value: 6 },290{ startIndex: 9, value: 7 },291{ startIndex: 10, value: 8 },292{ startIndex: 12, value: 9 },293],294[295{ startIndex: 0, value: 10 },296{ startIndex: 2, value: 11 },297{ startIndex: 9, value: 12 },298{ startIndex: 10, value: 13 },299{ startIndex: 13, value: 14 },300{ startIndex: 14, value: 15 },301{ startIndex: 27, value: 16 },302],303[304{ startIndex: 0, value: 17 },305],306[307{ startIndex: 0, value: 18 },308{ startIndex: 1, value: 19 },309{ startIndex: 9, value: 20 },310{ startIndex: 10, value: 21 },311{ startIndex: 15, value: 22 },312],313[314{ startIndex: 0, value: 23 },315{ startIndex: 2, value: 24 },316{ startIndex: 9, value: 25 },317{ startIndex: 10, value: 26 },318{ startIndex: 13, value: 27 },319{ startIndex: 14, value: 28 },320{ startIndex: 59, value: 29 },321],322[323{ startIndex: 0, value: 30 },324],325[326{ startIndex: 0, value: 31 },327]328];329330let model: TextModel;331let languageRegistration: IDisposable;332333setup(() => {334let _lineIndex = 0;335const tokenizationSupport: languages.ITokenizationSupport = {336getInitialState: () => NullState,337tokenize: undefined!,338tokenizeEncoded: (line: string, hasEOL: boolean, state: languages.IState): languages.EncodedTokenizationResult => {339const tokens = _tokens[_lineIndex++];340341const result = new Uint32Array(2 * tokens.length);342for (let i = 0; i < tokens.length; i++) {343result[2 * i] = tokens[i].startIndex;344result[2 * i + 1] = (345tokens[i].value << MetadataConsts.FOREGROUND_OFFSET346);347}348return new languages.EncodedTokenizationResult(result, [], state);349}350};351const LANGUAGE_ID = 'modelModeTest1';352languageRegistration = languages.TokenizationRegistry.register(LANGUAGE_ID, tokenizationSupport);353model = createTextModel(_text.join('\n'), LANGUAGE_ID);354// force tokenization355model.tokenization.forceTokenization(model.getLineCount());356});357358teardown(() => {359model.dispose();360languageRegistration.dispose();361});362363ensureNoDisposablesAreLeakedInTestSuite();364365interface ITestViewLineToken {366endIndex: number;367value: number;368}369370function assertViewLineTokens(_actual: IViewLineTokens, expected: ITestViewLineToken[]): void {371const actual: ITestViewLineToken[] = [];372for (let i = 0, len = _actual.getCount(); i < len; i++) {373actual[i] = {374endIndex: _actual.getEndOffset(i),375value: _actual.getForeground(i)376};377}378assert.deepStrictEqual(actual, expected);379}380381interface ITestMinimapLineRenderingData {382content: string;383minColumn: number;384maxColumn: number;385tokens: ITestViewLineToken[];386}387388function assertMinimapLineRenderingData(actual: ViewLineData, expected: ITestMinimapLineRenderingData | null): void {389if (actual === null && expected === null) {390assert.ok(true);391return;392}393if (expected === null) {394assert.ok(false);395}396assert.strictEqual(actual.content, expected.content);397assert.strictEqual(actual.minColumn, expected.minColumn);398assert.strictEqual(actual.maxColumn, expected.maxColumn);399assertViewLineTokens(actual.tokens, expected.tokens);400}401402function assertMinimapLinesRenderingData(actual: ViewLineData[], expected: Array<ITestMinimapLineRenderingData | null>): void {403assert.strictEqual(actual.length, expected.length);404for (let i = 0; i < expected.length; i++) {405assertMinimapLineRenderingData(actual[i], expected[i]);406}407}408409function assertAllMinimapLinesRenderingData(splitLinesCollection: ViewModelLinesFromProjectedModel, all: ITestMinimapLineRenderingData[]): void {410const lineCount = all.length;411for (let line = 1; line <= lineCount; line++) {412assert.strictEqual(splitLinesCollection.getViewLineData(line).content, splitLinesCollection.getViewLineContent(line));413}414415for (let start = 1; start <= lineCount; start++) {416for (let end = start; end <= lineCount; end++) {417const count = end - start + 1;418for (let desired = Math.pow(2, count) - 1; desired >= 0; desired--) {419const needed: boolean[] = [];420const expected: Array<ITestMinimapLineRenderingData | null> = [];421for (let i = 0; i < count; i++) {422needed[i] = (desired & (1 << i)) ? true : false;423expected[i] = (needed[i] ? all[start - 1 + i] : null);424}425const actual = splitLinesCollection.getViewLinesData(start, end, needed);426427assertMinimapLinesRenderingData(actual, expected);428// Comment out next line to test all possible combinations429break;430}431}432}433}434435test('getViewLinesData - no wrapping', () => {436withSplitLinesCollection(model, 'off', 0, false, (splitLinesCollection) => {437assert.strictEqual(splitLinesCollection.getViewLineCount(), 8);438assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);439assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), true);440assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), true);441assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), true);442assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);443assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);444assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);445assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);446447const _expected: ITestMinimapLineRenderingData[] = [448{449content: 'class Nice {',450minColumn: 1,451maxColumn: 13,452tokens: [453{ endIndex: 5, value: 1 },454{ endIndex: 6, value: 2 },455{ endIndex: 10, value: 3 },456{ endIndex: 12, value: 4 },457]458},459{460content: ' function hi() {',461minColumn: 1,462maxColumn: 17,463tokens: [464{ endIndex: 1, value: 5 },465{ endIndex: 9, value: 6 },466{ endIndex: 10, value: 7 },467{ endIndex: 12, value: 8 },468{ endIndex: 16, value: 9 },469]470},471{472content: ' console.log("Hello world");',473minColumn: 1,474maxColumn: 30,475tokens: [476{ endIndex: 2, value: 10 },477{ endIndex: 9, value: 11 },478{ endIndex: 10, value: 12 },479{ endIndex: 13, value: 13 },480{ endIndex: 14, value: 14 },481{ endIndex: 27, value: 15 },482{ endIndex: 29, value: 16 },483]484},485{486content: ' }',487minColumn: 1,488maxColumn: 3,489tokens: [490{ endIndex: 2, value: 17 },491]492},493{494content: ' function hello() {',495minColumn: 1,496maxColumn: 20,497tokens: [498{ endIndex: 1, value: 18 },499{ endIndex: 9, value: 19 },500{ endIndex: 10, value: 20 },501{ endIndex: 15, value: 21 },502{ endIndex: 19, value: 22 },503]504},505{506content: ' console.log("Hello world, this is a somewhat longer line");',507minColumn: 1,508maxColumn: 62,509tokens: [510{ endIndex: 2, value: 23 },511{ endIndex: 9, value: 24 },512{ endIndex: 10, value: 25 },513{ endIndex: 13, value: 26 },514{ endIndex: 14, value: 27 },515{ endIndex: 59, value: 28 },516{ endIndex: 61, value: 29 },517]518},519{520minColumn: 1,521maxColumn: 3,522content: ' }',523tokens: [524{ endIndex: 2, value: 30 },525]526},527{528minColumn: 1,529maxColumn: 2,530content: '}',531tokens: [532{ endIndex: 1, value: 31 },533]534}535];536537assertAllMinimapLinesRenderingData(splitLinesCollection, [538_expected[0],539_expected[1],540_expected[2],541_expected[3],542_expected[4],543_expected[5],544_expected[6],545_expected[7],546]);547548splitLinesCollection.setHiddenAreas([new Range(2, 1, 4, 1)]);549assert.strictEqual(splitLinesCollection.getViewLineCount(), 5);550assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);551assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), false);552assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), false);553assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), false);554assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);555assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);556assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);557assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);558559assertAllMinimapLinesRenderingData(splitLinesCollection, [560_expected[0],561_expected[4],562_expected[5],563_expected[6],564_expected[7],565]);566});567});568569test('getViewLinesData - with wrapping', () => {570withSplitLinesCollection(model, 'wordWrapColumn', 30, false, (splitLinesCollection) => {571assert.strictEqual(splitLinesCollection.getViewLineCount(), 12);572assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);573assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), true);574assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), true);575assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), true);576assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);577assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);578assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);579assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);580581const _expected: ITestMinimapLineRenderingData[] = [582{583content: 'class Nice {',584minColumn: 1,585maxColumn: 13,586tokens: [587{ endIndex: 5, value: 1 },588{ endIndex: 6, value: 2 },589{ endIndex: 10, value: 3 },590{ endIndex: 12, value: 4 },591]592},593{594content: ' function hi() {',595minColumn: 1,596maxColumn: 17,597tokens: [598{ endIndex: 1, value: 5 },599{ endIndex: 9, value: 6 },600{ endIndex: 10, value: 7 },601{ endIndex: 12, value: 8 },602{ endIndex: 16, value: 9 },603]604},605{606content: ' console.log("Hello ',607minColumn: 1,608maxColumn: 22,609tokens: [610{ endIndex: 2, value: 10 },611{ endIndex: 9, value: 11 },612{ endIndex: 10, value: 12 },613{ endIndex: 13, value: 13 },614{ endIndex: 14, value: 14 },615{ endIndex: 21, value: 15 },616]617},618{619content: ' world");',620minColumn: 13,621maxColumn: 21,622tokens: [623{ endIndex: 18, value: 15 },624{ endIndex: 20, value: 16 },625]626},627{628content: ' }',629minColumn: 1,630maxColumn: 3,631tokens: [632{ endIndex: 2, value: 17 },633]634},635{636content: ' function hello() {',637minColumn: 1,638maxColumn: 20,639tokens: [640{ endIndex: 1, value: 18 },641{ endIndex: 9, value: 19 },642{ endIndex: 10, value: 20 },643{ endIndex: 15, value: 21 },644{ endIndex: 19, value: 22 },645]646},647{648content: ' console.log("Hello ',649minColumn: 1,650maxColumn: 22,651tokens: [652{ endIndex: 2, value: 23 },653{ endIndex: 9, value: 24 },654{ endIndex: 10, value: 25 },655{ endIndex: 13, value: 26 },656{ endIndex: 14, value: 27 },657{ endIndex: 21, value: 28 },658]659},660{661content: ' world, this is a ',662minColumn: 13,663maxColumn: 30,664tokens: [665{ endIndex: 29, value: 28 },666]667},668{669content: ' somewhat longer ',670minColumn: 13,671maxColumn: 29,672tokens: [673{ endIndex: 28, value: 28 },674]675},676{677content: ' line");',678minColumn: 13,679maxColumn: 20,680tokens: [681{ endIndex: 17, value: 28 },682{ endIndex: 19, value: 29 },683]684},685{686content: ' }',687minColumn: 1,688maxColumn: 3,689tokens: [690{ endIndex: 2, value: 30 },691]692},693{694content: '}',695minColumn: 1,696maxColumn: 2,697tokens: [698{ endIndex: 1, value: 31 },699]700}701];702703assertAllMinimapLinesRenderingData(splitLinesCollection, [704_expected[0],705_expected[1],706_expected[2],707_expected[3],708_expected[4],709_expected[5],710_expected[6],711_expected[7],712_expected[8],713_expected[9],714_expected[10],715_expected[11],716]);717718splitLinesCollection.setHiddenAreas([new Range(2, 1, 4, 1)]);719assert.strictEqual(splitLinesCollection.getViewLineCount(), 8);720assert.strictEqual(splitLinesCollection.modelPositionIsVisible(1, 1), true);721assert.strictEqual(splitLinesCollection.modelPositionIsVisible(2, 1), false);722assert.strictEqual(splitLinesCollection.modelPositionIsVisible(3, 1), false);723assert.strictEqual(splitLinesCollection.modelPositionIsVisible(4, 1), false);724assert.strictEqual(splitLinesCollection.modelPositionIsVisible(5, 1), true);725assert.strictEqual(splitLinesCollection.modelPositionIsVisible(6, 1), true);726assert.strictEqual(splitLinesCollection.modelPositionIsVisible(7, 1), true);727assert.strictEqual(splitLinesCollection.modelPositionIsVisible(8, 1), true);728729assertAllMinimapLinesRenderingData(splitLinesCollection, [730_expected[0],731_expected[5],732_expected[6],733_expected[7],734_expected[8],735_expected[9],736_expected[10],737_expected[11],738]);739});740});741742test('getViewLinesData - with wrapping and injected text', () => {743model.deltaDecorations([], [{744range: new Range(1, 9, 1, 9),745options: {746description: 'example',747after: {748content: 'very very long injected text that causes a line break',749inlineClassName: 'myClassName'750},751showIfCollapsed: true,752}753}]);754755withSplitLinesCollection(model, 'wordWrapColumn', 30, false, (splitLinesCollection) => {756assert.strictEqual(splitLinesCollection.getViewLineCount(), 14);757758assert.strictEqual(splitLinesCollection.getViewLineMaxColumn(1), 24);759760const _expected: ITestMinimapLineRenderingData[] = [761{762content: 'class Nivery very long ',763minColumn: 1,764maxColumn: 24,765tokens: [766{ endIndex: 5, value: 1 },767{ endIndex: 6, value: 2 },768{ endIndex: 8, value: 3 },769{ endIndex: 23, value: 1 },770]771},772{773content: ' injected text that causes ',774minColumn: 5,775maxColumn: 31,776tokens: [{ endIndex: 30, value: 1 }]777},778{779content: ' a line breakce {',780minColumn: 5,781maxColumn: 21,782tokens: [783{ endIndex: 16, value: 1 },784{ endIndex: 18, value: 3 },785{ endIndex: 20, value: 4 }786]787},788{789content: ' function hi() {',790minColumn: 1,791maxColumn: 17,792tokens: [793{ endIndex: 1, value: 5 },794{ endIndex: 9, value: 6 },795{ endIndex: 10, value: 7 },796{ endIndex: 12, value: 8 },797{ endIndex: 16, value: 9 },798]799},800{801content: ' console.log("Hello ',802minColumn: 1,803maxColumn: 22,804tokens: [805{ endIndex: 2, value: 10 },806{ endIndex: 9, value: 11 },807{ endIndex: 10, value: 12 },808{ endIndex: 13, value: 13 },809{ endIndex: 14, value: 14 },810{ endIndex: 21, value: 15 },811]812},813{814content: ' world");',815minColumn: 13,816maxColumn: 21,817tokens: [818{ endIndex: 18, value: 15 },819{ endIndex: 20, value: 16 },820]821},822{823content: ' }',824minColumn: 1,825maxColumn: 3,826tokens: [827{ endIndex: 2, value: 17 },828]829},830{831content: ' function hello() {',832minColumn: 1,833maxColumn: 20,834tokens: [835{ endIndex: 1, value: 18 },836{ endIndex: 9, value: 19 },837{ endIndex: 10, value: 20 },838{ endIndex: 15, value: 21 },839{ endIndex: 19, value: 22 },840]841},842{843content: ' console.log("Hello ',844minColumn: 1,845maxColumn: 22,846tokens: [847{ endIndex: 2, value: 23 },848{ endIndex: 9, value: 24 },849{ endIndex: 10, value: 25 },850{ endIndex: 13, value: 26 },851{ endIndex: 14, value: 27 },852{ endIndex: 21, value: 28 },853]854},855{856content: ' world, this is a ',857minColumn: 13,858maxColumn: 30,859tokens: [860{ endIndex: 29, value: 28 },861]862},863{864content: ' somewhat longer ',865minColumn: 13,866maxColumn: 29,867tokens: [868{ endIndex: 28, value: 28 },869]870},871{872content: ' line");',873minColumn: 13,874maxColumn: 20,875tokens: [876{ endIndex: 17, value: 28 },877{ endIndex: 19, value: 29 },878]879},880{881content: ' }',882minColumn: 1,883maxColumn: 3,884tokens: [885{ endIndex: 2, value: 30 },886]887},888{889content: '}',890minColumn: 1,891maxColumn: 2,892tokens: [893{ endIndex: 1, value: 31 },894]895}896];897898assertAllMinimapLinesRenderingData(splitLinesCollection, [899_expected[0],900_expected[1],901_expected[2],902_expected[3],903_expected[4],904_expected[5],905_expected[6],906_expected[7],907_expected[8],908_expected[9],909_expected[10],910_expected[11],911]);912913const data = splitLinesCollection.getViewLinesData(1, 14, new Array(14).fill(true));914assert.deepStrictEqual(915data.map((d) => ({916inlineDecorations: d.inlineDecorations?.map((d) => ({917startOffset: d.startOffset,918endOffset: d.endOffset,919})),920})),921[922{ inlineDecorations: [{ startOffset: 8, endOffset: 23 }] },923{ inlineDecorations: [{ startOffset: 4, endOffset: 30 }] },924{ inlineDecorations: [{ startOffset: 4, endOffset: 16 }] },925{ inlineDecorations: undefined },926{ inlineDecorations: undefined },927{ inlineDecorations: undefined },928{ inlineDecorations: undefined },929{ inlineDecorations: undefined },930{ inlineDecorations: undefined },931{ inlineDecorations: undefined },932{ inlineDecorations: undefined },933{ inlineDecorations: undefined },934{ inlineDecorations: undefined },935{ inlineDecorations: undefined },936]937);938});939});940941function withSplitLinesCollection(model: TextModel, wordWrap: 'on' | 'off' | 'wordWrapColumn' | 'bounded', wordWrapColumn: number, wrapOnEscapedLineFeeds: boolean, callback: (splitLinesCollection: ViewModelLinesFromProjectedModel) => void): void {942const configuration = new TestConfiguration({943wordWrap: wordWrap,944wordWrapColumn: wordWrapColumn,945wrappingIndent: 'indent'946});947const wrappingInfo = configuration.options.get(EditorOption.wrappingInfo);948const fontInfo = configuration.options.get(EditorOption.fontInfo);949const wordWrapBreakAfterCharacters = configuration.options.get(EditorOption.wordWrapBreakAfterCharacters);950const wordWrapBreakBeforeCharacters = configuration.options.get(EditorOption.wordWrapBreakBeforeCharacters);951const wrappingIndent = configuration.options.get(EditorOption.wrappingIndent);952const wordBreak = configuration.options.get(EditorOption.wordBreak);953954const lineBreaksComputerFactory = new MonospaceLineBreaksComputerFactory(wordWrapBreakBeforeCharacters, wordWrapBreakAfterCharacters);955956const linesCollection = new ViewModelLinesFromProjectedModel(9571,958model,959lineBreaksComputerFactory,960lineBreaksComputerFactory,961fontInfo,962model.getOptions().tabSize,963'simple',964wrappingInfo.wrappingColumn,965wrappingIndent,966wordBreak,967wrapOnEscapedLineFeeds968);969970callback(linesCollection);971972configuration.dispose();973}974});975976977function pos(lineNumber: number, column: number): Position {978return new Position(lineNumber, column);979}980981function createSplitLine(splitLengths: number[], breakingOffsetsVisibleColumn: number[], wrappedTextIndentWidth: number, isVisible: boolean = true): IModelLineProjection {982return createModelLineProjection(createLineBreakData(splitLengths, breakingOffsetsVisibleColumn, wrappedTextIndentWidth), isVisible);983}984985function createLineBreakData(breakingLengths: number[], breakingOffsetsVisibleColumn: number[], wrappedTextIndentWidth: number): ModelLineProjectionData {986const sums: number[] = [];987for (let i = 0; i < breakingLengths.length; i++) {988sums[i] = (i > 0 ? sums[i - 1] : 0) + breakingLengths[i];989}990return new ModelLineProjectionData(null, null, sums, breakingOffsetsVisibleColumn, wrappedTextIndentWidth);991}992993function createModel(text: string): ISimpleModel {994return {995tokenization: {996getLineTokens: (lineNumber: number) => {997return null!;998},999},1000getLineContent: (lineNumber: number) => {1001return text;1002},1003getLineLength: (lineNumber: number) => {1004return text.length;1005},1006getLineMinColumn: (lineNumber: number) => {1007return 1;1008},1009getLineMaxColumn: (lineNumber: number) => {1010return text.length + 1;1011},1012getValueInRange: (range: IRange, eol?: EndOfLinePreference) => {1013return text.substring(range.startColumn - 1, range.endColumn - 1);1014}1015};1016}101710181019