diff --git a/src/vs/editor/browser/view/domLineBreaksComputer.ts b/src/vs/editor/browser/view/domLineBreaksComputer.ts index 46d5cbd206d..360a051d067 100644 --- a/src/vs/editor/browser/view/domLineBreaksComputer.ts +++ b/src/vs/editor/browser/view/domLineBreaksComputer.ts @@ -10,7 +10,7 @@ import { createStringBuilder, IStringBuilder } from 'vs/editor/common/core/strin import { CharCode } from 'vs/base/common/charCode'; import * as strings from 'vs/base/common/strings'; import { Configuration } from 'vs/editor/browser/config/configuration'; -import { ILineBreaksComputer, LineBreakData } from 'vs/editor/common/viewModel/viewModel'; +import { ILineBreaksComputer, LineBreakData, LineInjectedText } from 'vs/editor/common/viewModel/viewModel'; const ttPolicy = window.trustedTypes?.createPolicy('domLineBreaksComputer', { createHTML: value => value }); @@ -29,7 +29,8 @@ export class DOMLineBreaksComputerFactory implements ILineBreaksComputerFactory let requests: string[] = []; return { - addRequest: (lineText: string, previousLineBreakData: LineBreakData | null) => { + addRequest: (lineText: string, injectedText: LineInjectedText[] | null, previousLineBreakData: LineBreakData | null) => { + // TODO: handle injectedText requests.push(lineText); }, finalize: () => { diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index c4a791e9ab3..3977fe6f80e 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -2297,7 +2297,7 @@ class InlineViewZonesComputer extends ViewZonesComputer { }; for (let lineNumber = lineChange.originalStartLineNumber; lineNumber <= lineChange.originalEndLineNumber; lineNumber++) { - this._lineBreaksComputer.addRequest(this._originalModel.getLineContent(lineNumber), null); + this._lineBreaksComputer.addRequest(this._originalModel.getLineContent(lineNumber), null, null); } this._pendingLineChange.push(lineChange); diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index a10d22ba630..153aa2c4590 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -156,6 +156,10 @@ export interface IModelDecorationOptions { * If set, the decoration will be rendered after the text with this CSS class name. */ afterContentClassName?: string | null; + /** + * If set, the content will be injected in the text after the range. + */ + afterContent?: string | null; } /** @@ -1068,6 +1072,12 @@ export interface ITextModel { */ getOverviewRulerDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; + /** + * Gets all the decorations that contain injected text. + * @param ownerId If set, it will ignore decorations belonging to other owners. + */ + getInjectedTextDecorations(ownerId?: number): IModelDecoration[]; + /** * @internal */ diff --git a/src/vs/editor/common/model/intervalTree.ts b/src/vs/editor/common/model/intervalTree.ts index d400024e7c5..6ac684722b4 100644 --- a/src/vs/editor/common/model/intervalTree.ts +++ b/src/vs/editor/common/model/intervalTree.ts @@ -39,17 +39,13 @@ const enum Constants { IsForValidationMaskInverse = 0b11111011, IsForValidationOffset = 2, - IsInOverviewRulerMask = 0b00001000, - IsInOverviewRulerMaskInverse = 0b11110111, - IsInOverviewRulerOffset = 3, + StickinessMask = 0b00011000, + StickinessMaskInverse = 0b11100111, + StickinessOffset = 3, - StickinessMask = 0b00110000, - StickinessMaskInverse = 0b11001111, - StickinessOffset = 4, - - CollapseOnReplaceEditMask = 0b01000000, - CollapseOnReplaceEditMaskInverse = 0b10111111, - CollapseOnReplaceEditOffset = 6, + CollapseOnReplaceEditMask = 0b00100000, + CollapseOnReplaceEditMaskInverse = 0b11011111, + CollapseOnReplaceEditOffset = 5, /** * Due to how deletion works (in order to avoid always walking the right subtree of the deleted node), @@ -98,14 +94,6 @@ function setNodeIsForValidation(node: IntervalNode, value: boolean): void { (node.metadata & Constants.IsForValidationMaskInverse) | ((value ? 1 : 0) << Constants.IsForValidationOffset) ); } -export function getNodeIsInOverviewRuler(node: IntervalNode): boolean { - return ((node.metadata & Constants.IsInOverviewRulerMask) >>> Constants.IsInOverviewRulerOffset) === 1; -} -function setNodeIsInOverviewRuler(node: IntervalNode, value: boolean): void { - node.metadata = ( - (node.metadata & Constants.IsInOverviewRulerMaskInverse) | ((value ? 1 : 0) << Constants.IsInOverviewRulerOffset) - ); -} function getNodeStickiness(node: IntervalNode): TrackedRangeStickiness { return ((node.metadata & Constants.StickinessMask) >>> Constants.StickinessOffset); } @@ -170,7 +158,6 @@ export class IntervalNode implements IModelDecoration { this.options = null!; setNodeIsForValidation(this, false); _setNodeStickiness(this, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges); - setNodeIsInOverviewRuler(this, false); setCollapseOnReplaceEdit(this, false); this.cachedVersionId = 0; @@ -200,7 +187,6 @@ export class IntervalNode implements IModelDecoration { || className === ClassName.EditorInfoDecoration )); _setNodeStickiness(this, this.options.stickiness); - setNodeIsInOverviewRuler(this, (this.options.overviewRuler && this.options.overviewRuler.color) ? true : false); setCollapseOnReplaceEdit(this, this.options.collapseOnReplaceEdit); } diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index d4b41529591..d43c25bcfd2 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -18,7 +18,7 @@ import { Selection } from 'vs/editor/common/core/selection'; import * as model from 'vs/editor/common/model'; import { EditStack } from 'vs/editor/common/model/editStack'; import { guessIndentation } from 'vs/editor/common/model/indentationGuesser'; -import { IntervalNode, IntervalTree, getNodeIsInOverviewRuler, recomputeMaxEnd } from 'vs/editor/common/model/intervalTree'; +import { IntervalNode, IntervalTree, recomputeMaxEnd } from 'vs/editor/common/model/intervalTree'; import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelTokensChangedEvent, InternalModelContentChangeEvent, ModelRawChange, ModelRawContentChangedEvent, ModelRawEOLChanged, ModelRawFlush, ModelRawLineChanged, ModelRawLinesDeleted, ModelRawLinesInserted } from 'vs/editor/common/model/textModelEvents'; import { SearchData, SearchParams, TextModelSearch } from 'vs/editor/common/model/textModelSearch'; @@ -510,7 +510,7 @@ export class TextModel extends Disposable implements model.ITextModel { private _onBeforeEOLChange(): void { // Ensure all decorations get their `range` set. const versionId = this.getVersionId(); - const allDecorations = this._decorationsTree.search(0, false, false, versionId); + const allDecorations = this._decorationsTree.search(0, false, false, false, versionId); this._ensureNodesHaveRanges(allDecorations); } @@ -1676,13 +1676,19 @@ export class TextModel extends Disposable implements model.ITextModel { public getOverviewRulerDecorations(ownerId: number = 0, filterOutValidation: boolean = false): model.IModelDecoration[] { const versionId = this.getVersionId(); - const result = this._decorationsTree.search(ownerId, filterOutValidation, true, versionId); + const result = this._decorationsTree.search(ownerId, filterOutValidation, true, false, versionId); + return this._ensureNodesHaveRanges(result); + } + + public getInjectedTextDecorations(ownerId: number = 0): model.IModelDecoration[] { + const versionId = this.getVersionId(); + const result = this._decorationsTree.search(ownerId, false, false, true, versionId); return this._ensureNodesHaveRanges(result); } public getAllDecorations(ownerId: number = 0, filterOutValidation: boolean = false): model.IModelDecoration[] { const versionId = this.getVersionId(); - const result = this._decorationsTree.search(ownerId, filterOutValidation, false, versionId); + const result = this._decorationsTree.search(ownerId, filterOutValidation, false, false, versionId); return this._ensureNodesHaveRanges(result); } @@ -3056,6 +3062,15 @@ function indentOfLine(line: string): number { //#region Decorations +function isNodeInOverviewRuler(node: IntervalNode): boolean { + return (node.options.overviewRuler && node.options.overviewRuler.color ? true : false); +} + +function isNodeInjectedText(node: IntervalNode): boolean { + // TODO: handle beforeContent + return (node.options.afterContent ? true : false); +} + class DecorationsTrees { /** @@ -3068,41 +3083,55 @@ class DecorationsTrees { */ private readonly _decorationsTree1: IntervalTree; + /** + * This tree holds decorations that contain injected text. + */ + private readonly _injectedTextDecorationsTree: IntervalTree; + constructor() { this._decorationsTree0 = new IntervalTree(); this._decorationsTree1 = new IntervalTree(); + this._injectedTextDecorationsTree = new IntervalTree(); } public intervalSearch(start: number, end: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { const r0 = this._decorationsTree0.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId); const r1 = this._decorationsTree1.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId); - return r0.concat(r1); + const r2 = this._injectedTextDecorationsTree.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId); + return r0.concat(r1).concat(r2); } - public search(filterOwnerId: number, filterOutValidation: boolean, overviewRulerOnly: boolean, cachedVersionId: number): IntervalNode[] { - if (overviewRulerOnly) { + public search(filterOwnerId: number, filterOutValidation: boolean, overviewRulerOnly: boolean, injectedTextOnly: boolean, cachedVersionId: number): IntervalNode[] { + if (injectedTextOnly) { + return this._injectedTextDecorationsTree.search(filterOwnerId, filterOutValidation, cachedVersionId); + } else if (overviewRulerOnly) { return this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId); } else { const r0 = this._decorationsTree0.search(filterOwnerId, filterOutValidation, cachedVersionId); const r1 = this._decorationsTree1.search(filterOwnerId, filterOutValidation, cachedVersionId); - return r0.concat(r1); + const r2 = this._injectedTextDecorationsTree.search(filterOwnerId, filterOutValidation, cachedVersionId); + return r0.concat(r1).concat(r2); } } public collectNodesFromOwner(ownerId: number): IntervalNode[] { const r0 = this._decorationsTree0.collectNodesFromOwner(ownerId); const r1 = this._decorationsTree1.collectNodesFromOwner(ownerId); - return r0.concat(r1); + const r2 = this._injectedTextDecorationsTree.collectNodesFromOwner(ownerId); + return r0.concat(r1).concat(r2); } public collectNodesPostOrder(): IntervalNode[] { const r0 = this._decorationsTree0.collectNodesPostOrder(); const r1 = this._decorationsTree1.collectNodesPostOrder(); - return r0.concat(r1); + const r2 = this._injectedTextDecorationsTree.collectNodesPostOrder(); + return r0.concat(r1).concat(r2); } public insert(node: IntervalNode): void { - if (getNodeIsInOverviewRuler(node)) { + if (isNodeInjectedText(node)) { + this._injectedTextDecorationsTree.insert(node); + } else if (isNodeInOverviewRuler(node)) { this._decorationsTree1.insert(node); } else { this._decorationsTree0.insert(node); @@ -3110,7 +3139,9 @@ class DecorationsTrees { } public delete(node: IntervalNode): void { - if (getNodeIsInOverviewRuler(node)) { + if (isNodeInjectedText(node)) { + this._injectedTextDecorationsTree.delete(node); + } else if (isNodeInOverviewRuler(node)) { this._decorationsTree1.delete(node); } else { this._decorationsTree0.delete(node); @@ -3118,7 +3149,9 @@ class DecorationsTrees { } public resolveNode(node: IntervalNode, cachedVersionId: number): void { - if (getNodeIsInOverviewRuler(node)) { + if (isNodeInjectedText(node)) { + this._injectedTextDecorationsTree.resolveNode(node, cachedVersionId); + } else if (isNodeInOverviewRuler(node)) { this._decorationsTree1.resolveNode(node, cachedVersionId); } else { this._decorationsTree0.resolveNode(node, cachedVersionId); @@ -3128,6 +3161,7 @@ class DecorationsTrees { public acceptReplace(offset: number, length: number, textLength: number, forceMoveMarkers: boolean): void { this._decorationsTree0.acceptReplace(offset, length, textLength, forceMoveMarkers); this._decorationsTree1.acceptReplace(offset, length, textLength, forceMoveMarkers); + this._injectedTextDecorationsTree.acceptReplace(offset, length, textLength, forceMoveMarkers); } } @@ -3248,6 +3282,7 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions { readonly inlineClassNameAffectsLetterSpacing: boolean; readonly beforeContentClassName: string | null; readonly afterContentClassName: string | null; + readonly afterContent: string | null; private constructor(options: model.IModelDecorationOptions) { this.description = options.description; @@ -3269,6 +3304,7 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions { this.inlineClassNameAffectsLetterSpacing = options.inlineClassNameAffectsLetterSpacing || false; this.beforeContentClassName = options.beforeContentClassName ? cleanClassName(options.beforeContentClassName) : null; this.afterContentClassName = options.afterContentClassName ? cleanClassName(options.afterContentClassName) : null; + this.afterContent = options.afterContent || null; } } ModelDecorationOptions.EMPTY = ModelDecorationOptions.register({ description: 'empty' }); diff --git a/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts b/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts index 57370e069f7..043b8d5643f 100644 --- a/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts +++ b/src/vs/editor/common/viewModel/monospaceLineBreaksComputer.ts @@ -9,7 +9,7 @@ import { WrappingIndent, IComputedEditorOptions, EditorOption } from 'vs/editor/ import { CharacterClassifier } from 'vs/editor/common/core/characterClassifier'; import { ILineBreaksComputerFactory } from 'vs/editor/common/viewModel/splitLinesCollection'; import { FontInfo } from 'vs/editor/common/config/fontInfo'; -import { ILineBreaksComputer, LineBreakData } from 'vs/editor/common/viewModel/viewModel'; +import { ILineBreaksComputer, LineBreakData, LineInjectedText } from 'vs/editor/common/viewModel/viewModel'; const enum CharacterClass { NONE = 0, @@ -75,22 +75,25 @@ export class MonospaceLineBreaksComputerFactory implements ILineBreaksComputerFa tabSize = tabSize | 0; //@perf wrappingColumn = +wrappingColumn; //@perf - let requests: string[] = []; - let previousBreakingData: (LineBreakData | null)[] = []; + const requests: string[] = []; + const injectedTexts: (LineInjectedText[] | null)[] = []; + const previousBreakingData: (LineBreakData | null)[] = []; return { - addRequest: (lineText: string, previousLineBreakData: LineBreakData | null) => { + addRequest: (lineText: string, injectedText: LineInjectedText[] | null, previousLineBreakData: LineBreakData | null) => { requests.push(lineText); + injectedTexts.push(injectedText); previousBreakingData.push(previousLineBreakData); }, finalize: () => { const columnsForFullWidthChar = fontInfo.typicalFullwidthCharacterWidth / fontInfo.typicalHalfwidthCharacterWidth; //@perf let result: (LineBreakData | null)[] = []; for (let i = 0, len = requests.length; i < len; i++) { + const injectedText = injectedTexts[i]; const previousLineBreakData = previousBreakingData[i]; - if (previousLineBreakData) { + if (previousLineBreakData && !injectedText) { result[i] = createLineBreaksFromPreviousLineBreaks(this.classifier, previousLineBreakData, requests[i], tabSize, wrappingColumn, columnsForFullWidthChar, wrappingIndent); } else { - result[i] = createLineBreaks(this.classifier, requests[i], tabSize, wrappingColumn, columnsForFullWidthChar, wrappingIndent); + result[i] = createLineBreaks(this.classifier, requests[i], injectedText, tabSize, wrappingColumn, columnsForFullWidthChar, wrappingIndent); } } arrPool1.length = 0; @@ -353,7 +356,10 @@ function createLineBreaksFromPreviousLineBreaks(classifier: WrappingCharacterCla return previousBreakingData; } -function createLineBreaks(classifier: WrappingCharacterClassifier, lineText: string, tabSize: number, firstLineBreakColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent): LineBreakData | null { +function createLineBreaks(classifier: WrappingCharacterClassifier, lineText: string, injectedText: LineInjectedText[] | null, tabSize: number, firstLineBreakColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent): LineBreakData | null { + if (injectedText) { + console.log(`TODO: `, injectedText); + } if (firstLineBreakColumn === -1) { return null; } diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index a3e15958d32..808fac953e1 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -12,7 +12,7 @@ import { EndOfLinePreference, IActiveIndentGuideInfo, IModelDecoration, IModelDe import { ModelDecorationOptions, ModelDecorationOverviewRulerOptions } from 'vs/editor/common/model/textModel'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { PrefixSumIndexOfResult } from 'vs/editor/common/viewModel/prefixSumComputer'; -import { ICoordinatesConverter, ILineBreaksComputer, IOverviewRulerDecorations, LineBreakData, ViewLineData } from 'vs/editor/common/viewModel/viewModel'; +import { ICoordinatesConverter, ILineBreaksComputer, IOverviewRulerDecorations, LineBreakData, LineInjectedText, ViewLineData } from 'vs/editor/common/viewModel/viewModel'; import { IDisposable } from 'vs/base/common/lifecycle'; import { FontInfo } from 'vs/editor/common/config/fontInfo'; import { EditorTheme } from 'vs/editor/common/view/viewContext'; @@ -276,11 +276,48 @@ export class SplitLinesCollection implements IViewModelLinesCollection { this.hiddenAreasIds = []; } - let linesContent = this.model.getLinesContent(); + const linesContent = this.model.getLinesContent(); + const injectedTextDecorations = this.model.getInjectedTextDecorations(); + const injectedText: LineInjectedText[] = []; + for (const injectedTextDecoration of injectedTextDecorations) { + // TODO: user order 0 for before + if (injectedTextDecoration.options.afterContent) { + injectedText.push(new LineInjectedText( + injectedTextDecoration.range.endLineNumber, + injectedTextDecoration.range.endColumn, + 1, + injectedTextDecoration.options.afterContent + )); + } + } + injectedText.sort((a, b) => { + if (a.lineNumber === b.lineNumber) { + if (a.column === b.column) { + return a.order - b.order; + } + return a.column - b.column; + } + return a.lineNumber - b.lineNumber; + }); + const lineCount = linesContent.length; const lineBreaksComputer = this.createLineBreaksComputer(); + const injectedTextLength = injectedText.length; + let injectedTextIndex = 0; + let nextLineNumberWithInjectedText = (injectedTextIndex < injectedTextLength ? injectedText[injectedTextIndex].lineNumber : lineCount + 1); for (let i = 0; i < lineCount; i++) { - lineBreaksComputer.addRequest(linesContent[i], previousLineBreaks ? previousLineBreaks[i] : null); + let lineInjectedText: LineInjectedText[] | null = null; + if (i + 1 === nextLineNumberWithInjectedText) { + // There is some injected text on this line + lineInjectedText = []; + while (i + 1 === nextLineNumberWithInjectedText && injectedTextIndex < injectedTextLength) { + lineInjectedText.push(injectedText[injectedTextIndex]); + injectedTextIndex++; + nextLineNumberWithInjectedText = (injectedTextIndex < injectedTextLength ? injectedText[injectedTextIndex].lineNumber : lineCount + 1); + } + } + + lineBreaksComputer.addRequest(linesContent[i], lineInjectedText, previousLineBreaks ? previousLineBreaks[i] : null); } const linesBreaks = lineBreaksComputer.finalize(); @@ -1477,7 +1514,7 @@ export class IdentityLinesCollection implements IViewModelLinesCollection { public createLineBreaksComputer(): ILineBreaksComputer { let result: null[] = []; return { - addRequest: (lineText: string, previousLineBreakData: LineBreakData | null) => { + addRequest: (lineText: string, injectedText: LineInjectedText[] | null, previousLineBreakData: LineBreakData | null) => { result.push(null); }, finalize: () => { diff --git a/src/vs/editor/common/viewModel/viewModel.ts b/src/vs/editor/common/viewModel/viewModel.ts index 92966555364..0e3330611c4 100644 --- a/src/vs/editor/common/viewModel/viewModel.ts +++ b/src/vs/editor/common/viewModel/viewModel.ts @@ -97,6 +97,18 @@ export class OutputPosition { } } +/** + * Represents text injected on a line + */ +export class LineInjectedText { + constructor( + public readonly lineNumber: number, + public readonly column: number, + public readonly order: number, + public readonly text: string + ) { } +} + export class LineBreakData { constructor( public breakOffsets: number[], @@ -141,7 +153,7 @@ export interface ILineBreaksComputer { /** * Pass in `previousLineBreakData` if the only difference is in breaking columns!!! */ - addRequest(lineText: string, previousLineBreakData: LineBreakData | null): void; + addRequest(lineText: string, injectedText: LineInjectedText[] | null, previousLineBreakData: LineBreakData | null): void; finalize(): (LineBreakData | null)[]; } diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index fd971ba5bf0..7e1826032ab 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -251,6 +251,7 @@ export class ViewModel extends Disposable implements IViewModel { private _registerModelEvents(): void { this._register(this.model.onDidChangeRawContentFast((e) => { + // TODO: Add an event for injected text try { const eventsCollector = this._eventDispatcher.beginEmitViewEvents(); @@ -265,13 +266,15 @@ export class ViewModel extends Disposable implements IViewModel { for (const change of changes) { switch (change.changeType) { case textModelEvents.RawContentChangedType.LinesInserted: { + // TODO: enrich this event with injected text decorations for (const line of change.detail) { - lineBreaksComputer.addRequest(line, null); + lineBreaksComputer.addRequest(line, null, null); } break; } case textModelEvents.RawContentChangedType.LineChanged: { - lineBreaksComputer.addRequest(change.detail, null); + // TODO: enrich this event with injected text decorations + lineBreaksComputer.addRequest(change.detail, null, null); break; } } diff --git a/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts b/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts index eec0e2b2717..b98a4a1f7c8 100644 --- a/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts +++ b/src/vs/editor/test/common/viewModel/monospaceLineBreaksComputer.test.ts @@ -65,7 +65,7 @@ function getLineBreakData(factory: ILineBreaksComputerFactory, tabSize: number, }, false); const lineBreaksComputer = factory.createLineBreaksComputer(fontInfo, tabSize, breakAfter, wrappingIndent); const previousLineBreakDataClone = previousLineBreakData ? new LineBreakData(previousLineBreakData.breakOffsets.slice(0), previousLineBreakData.breakOffsetsVisibleColumn.slice(0), previousLineBreakData.wrappedTextIndentLength) : null; - lineBreaksComputer.addRequest(text, previousLineBreakDataClone); + lineBreaksComputer.addRequest(text, null, previousLineBreakDataClone); return lineBreaksComputer.finalize()[0]; } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 2b8c3885dfa..d503b99bcde 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -1443,6 +1443,10 @@ declare namespace monaco.editor { * If set, the decoration will be rendered after the text with this CSS class name. */ afterContentClassName?: string | null; + /** + * If set, the content will be injected in the text after the range. + */ + afterContent?: string | null; } /** @@ -1908,6 +1912,11 @@ declare namespace monaco.editor { * @param filterOutValidation If set, it will ignore decorations specific to validation (i.e. warnings, errors). */ getOverviewRulerDecorations(ownerId?: number, filterOutValidation?: boolean): IModelDecoration[]; + /** + * Gets all the decorations that contain injected text. + * @param ownerId If set, it will ignore decorations belonging to other owners. + */ + getInjectedTextDecorations(ownerId?: number): IModelDecoration[]; /** * Normalize a string containing whitespace according to indentation rules (converts to spaces or to tabs). */