Merge from vscode 5e80bf449c995aa32a59254c0ff845d37da11b70 (#9317)

This commit is contained in:
Anthony Dresser
2020-02-24 21:15:52 -08:00
committed by GitHub
parent 628fd8d74d
commit 4a9c47d3d6
93 changed files with 3109 additions and 813 deletions

View File

@@ -523,7 +523,7 @@ const editorConfiguration: IConfigurationNode = {
'diffEditor.ignoreTrimWhitespace': {
type: 'boolean',
default: true,
description: nls.localize('ignoreTrimWhitespace', "Controls whether the diff editor shows changes in leading or trailing whitespace as diffs.")
description: nls.localize('ignoreTrimWhitespace', "When enabled, the diff editor ignores changes in leading or trailing whitespace.")
},
'diffEditor.renderIndicators': {
type: 'boolean',

View File

@@ -506,6 +506,11 @@ export interface IEditorOptions {
* Defaults to 'mouseover'.
*/
showFoldingControls?: 'always' | 'mouseover';
/**
* Controls whether clicking on the empty content after a folded line will unfold the line.
* Defaults to false.
*/
unfoldOnClickInEmptyContent?: boolean;
/**
* Enable highlighting of matching brackets.
* Defaults to 'always'.
@@ -3328,6 +3333,7 @@ export const enum EditorOption {
folding,
foldingStrategy,
foldingHighlight,
unfoldOnClickInEmptyContent,
fontFamily,
fontInfo,
fontLigatures,
@@ -3627,6 +3633,10 @@ export const EditorOptions = {
EditorOption.foldingHighlight, 'foldingHighlight', true,
{ description: nls.localize('foldingHighlight', "Controls whether the editor should highlight folded ranges.") }
)),
unfoldOnClickInEmptyContent: register(new EditorBooleanOption(
EditorOption.unfoldOnClickInEmptyContent, 'unfoldOnClickInEmptyContent', false,
{ description: nls.localize('unfoldOnClickInEmptyContent', "Controls whether clicking on the empty content after a folded line will unfold the line.") }
)),
fontFamily: register(new EditorStringOption(
EditorOption.fontFamily, 'fontFamily', EDITOR_FONT_DEFAULTS.fontFamily,
{ description: nls.localize('fontFamily', "Controls the font family.") }

View File

@@ -297,7 +297,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
return this._cursors.getAll();
}
public setStates(source: string, reason: CursorChangeReason, states: PartialCursorState[] | null): void {
public setStates(source: string, reason: CursorChangeReason, states: PartialCursorState[] | null): boolean {
if (states !== null && states.length > Cursor.MAX_CURSOR_COUNT) {
states = states.slice(0, Cursor.MAX_CURSOR_COUNT);
this._onDidReachMaxCursorCount.fire(undefined);
@@ -311,7 +311,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
this._validateAutoClosedActions();
this._emitStateChangedIfNecessary(source, reason, oldState);
return this._emitStateChangedIfNecessary(source, reason, oldState);
}
public setColumnSelectData(columnSelectData: IColumnSelectData): void {
@@ -411,7 +411,9 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
} else {
if (this._hasFocus && e.resultingSelection && e.resultingSelection.length > 0) {
const cursorState = CursorState.fromModelSelections(e.resultingSelection);
this.setStates('modelChange', e.isUndoing ? CursorChangeReason.Undo : e.isRedoing ? CursorChangeReason.Redo : CursorChangeReason.RecoverFromMarkers, cursorState);
if (this.setStates('modelChange', e.isUndoing ? CursorChangeReason.Undo : e.isRedoing ? CursorChangeReason.Redo : CursorChangeReason.RecoverFromMarkers, cursorState)) {
this._revealRange('modelChange', RevealTarget.Primary, viewEvents.VerticalRevealType.Simple, true, editorCommon.ScrollType.Smooth);
}
} else {
const selectionsFromMarkers = this._cursors.readSelectionFromMarkers();
this.setStates('modelChange', CursorChangeReason.RecoverFromMarkers, CursorState.fromModelSelections(selectionsFromMarkers));

View File

@@ -199,85 +199,86 @@ export enum EditorOption {
folding = 31,
foldingStrategy = 32,
foldingHighlight = 33,
fontFamily = 34,
fontInfo = 35,
fontLigatures = 36,
fontSize = 37,
fontWeight = 38,
formatOnPaste = 39,
formatOnType = 40,
glyphMargin = 41,
gotoLocation = 42,
hideCursorInOverviewRuler = 43,
highlightActiveIndentGuide = 44,
hover = 45,
inDiffEditor = 46,
letterSpacing = 47,
lightbulb = 48,
lineDecorationsWidth = 49,
lineHeight = 50,
lineNumbers = 51,
lineNumbersMinChars = 52,
links = 53,
matchBrackets = 54,
minimap = 55,
mouseStyle = 56,
mouseWheelScrollSensitivity = 57,
mouseWheelZoom = 58,
multiCursorMergeOverlapping = 59,
multiCursorModifier = 60,
multiCursorPaste = 61,
occurrencesHighlight = 62,
overviewRulerBorder = 63,
overviewRulerLanes = 64,
padding = 65,
parameterHints = 66,
peekWidgetDefaultFocus = 67,
definitionLinkOpensInPeek = 68,
quickSuggestions = 69,
quickSuggestionsDelay = 70,
readOnly = 71,
renderControlCharacters = 72,
renderIndentGuides = 73,
renderFinalNewline = 74,
renderLineHighlight = 75,
renderValidationDecorations = 76,
renderWhitespace = 77,
revealHorizontalRightPadding = 78,
roundedSelection = 79,
rulers = 80,
scrollbar = 81,
scrollBeyondLastColumn = 82,
scrollBeyondLastLine = 83,
scrollPredominantAxis = 84,
selectionClipboard = 85,
selectionHighlight = 86,
selectOnLineNumbers = 87,
showFoldingControls = 88,
showUnused = 89,
snippetSuggestions = 90,
smoothScrolling = 91,
stopRenderingLineAfter = 92,
suggest = 93,
suggestFontSize = 94,
suggestLineHeight = 95,
suggestOnTriggerCharacters = 96,
suggestSelection = 97,
tabCompletion = 98,
useTabStops = 99,
wordSeparators = 100,
wordWrap = 101,
wordWrapBreakAfterCharacters = 102,
wordWrapBreakBeforeCharacters = 103,
wordWrapColumn = 104,
wordWrapMinified = 105,
wrappingIndent = 106,
wrappingStrategy = 107,
editorClassName = 108,
pixelRatio = 109,
tabFocusMode = 110,
layoutInfo = 111,
wrappingInfo = 112
unfoldOnClickInEmptyContent = 34,
fontFamily = 35,
fontInfo = 36,
fontLigatures = 37,
fontSize = 38,
fontWeight = 39,
formatOnPaste = 40,
formatOnType = 41,
glyphMargin = 42,
gotoLocation = 43,
hideCursorInOverviewRuler = 44,
highlightActiveIndentGuide = 45,
hover = 46,
inDiffEditor = 47,
letterSpacing = 48,
lightbulb = 49,
lineDecorationsWidth = 50,
lineHeight = 51,
lineNumbers = 52,
lineNumbersMinChars = 53,
links = 54,
matchBrackets = 55,
minimap = 56,
mouseStyle = 57,
mouseWheelScrollSensitivity = 58,
mouseWheelZoom = 59,
multiCursorMergeOverlapping = 60,
multiCursorModifier = 61,
multiCursorPaste = 62,
occurrencesHighlight = 63,
overviewRulerBorder = 64,
overviewRulerLanes = 65,
padding = 66,
parameterHints = 67,
peekWidgetDefaultFocus = 68,
definitionLinkOpensInPeek = 69,
quickSuggestions = 70,
quickSuggestionsDelay = 71,
readOnly = 72,
renderControlCharacters = 73,
renderIndentGuides = 74,
renderFinalNewline = 75,
renderLineHighlight = 76,
renderValidationDecorations = 77,
renderWhitespace = 78,
revealHorizontalRightPadding = 79,
roundedSelection = 80,
rulers = 81,
scrollbar = 82,
scrollBeyondLastColumn = 83,
scrollBeyondLastLine = 84,
scrollPredominantAxis = 85,
selectionClipboard = 86,
selectionHighlight = 87,
selectOnLineNumbers = 88,
showFoldingControls = 89,
showUnused = 90,
snippetSuggestions = 91,
smoothScrolling = 92,
stopRenderingLineAfter = 93,
suggest = 94,
suggestFontSize = 95,
suggestLineHeight = 96,
suggestOnTriggerCharacters = 97,
suggestSelection = 98,
tabCompletion = 99,
useTabStops = 100,
wordSeparators = 101,
wordWrap = 102,
wordWrapBreakAfterCharacters = 103,
wordWrapBreakBeforeCharacters = 104,
wordWrapColumn = 105,
wordWrapMinified = 106,
wrappingIndent = 107,
wrappingStrategy = 108,
editorClassName = 109,
pixelRatio = 110,
tabFocusMode = 111,
layoutInfo = 112,
wrappingInfo = 113
}
/**

View File

@@ -6,6 +6,7 @@
import * as strings from 'vs/base/common/strings';
import { Constants } from 'vs/base/common/uint';
import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';
import { LinePartMetadata } from 'vs/editor/common/viewLayout/viewLineRenderer';
export class LineDecoration {
_lineDecorationBrand: void;
@@ -28,8 +29,8 @@ export class LineDecoration {
}
public static equalsArr(a: LineDecoration[], b: LineDecoration[]): boolean {
let aLen = a.length;
let bLen = b.length;
const aLen = a.length;
const bLen = b.length;
if (aLen !== bLen) {
return false;
}
@@ -49,8 +50,8 @@ export class LineDecoration {
let result: LineDecoration[] = [], resultLen = 0;
for (let i = 0, len = lineDecorations.length; i < len; i++) {
let d = lineDecorations[i];
let range = d.range;
const d = lineDecorations[i];
const range = d.range;
if (range.endLineNumber < lineNumber || range.startLineNumber > lineNumber) {
// Ignore decorations that sit outside this line
@@ -62,8 +63,8 @@ export class LineDecoration {
continue;
}
let startColumn = (range.startLineNumber === lineNumber ? range.startColumn : minLineColumn);
let endColumn = (range.endLineNumber === lineNumber ? range.endColumn : maxLineColumn);
const startColumn = (range.startLineNumber === lineNumber ? range.startColumn : minLineColumn);
const endColumn = (range.endLineNumber === lineNumber ? range.endColumn : maxLineColumn);
result[resultLen++] = new LineDecoration(startColumn, endColumn, d.inlineClassName, d.type);
}
@@ -71,16 +72,25 @@ export class LineDecoration {
return result;
}
private static _typeCompare(a: InlineDecorationType, b: InlineDecorationType): number {
const ORDER = [2, 0, 1, 3];
return ORDER[a] - ORDER[b];
}
public static compare(a: LineDecoration, b: LineDecoration): number {
if (a.startColumn === b.startColumn) {
if (a.endColumn === b.endColumn) {
if (a.className < b.className) {
return -1;
const typeCmp = LineDecoration._typeCompare(a.type, b.type);
if (typeCmp === 0) {
if (a.className < b.className) {
return -1;
}
if (a.className > b.className) {
return 1;
}
return 0;
}
if (a.className > b.className) {
return 1;
}
return 0;
return typeCmp;
}
return a.endColumn - b.endColumn;
}
@@ -92,11 +102,13 @@ export class DecorationSegment {
startOffset: number;
endOffset: number;
className: string;
metadata: number;
constructor(startOffset: number, endOffset: number, className: string) {
constructor(startOffset: number, endOffset: number, className: string, metadata: number) {
this.startOffset = startOffset;
this.endOffset = endOffset;
this.className = className;
this.metadata = metadata;
}
}
@@ -104,13 +116,23 @@ class Stack {
public count: number;
private readonly stopOffsets: number[];
private readonly classNames: string[];
private readonly metadata: number[];
constructor() {
this.stopOffsets = [];
this.classNames = [];
this.metadata = [];
this.count = 0;
}
private static _metadata(metadata: number[]): number {
let result = 0;
for (let i = 0, len = metadata.length; i < len; i++) {
result |= metadata[i];
}
return result;
}
public consumeLowerThan(maxStopOffset: number, nextStartOffset: number, result: DecorationSegment[]): number {
while (this.count > 0 && this.stopOffsets[0] < maxStopOffset) {
@@ -122,34 +144,37 @@ class Stack {
}
// Basically we are consuming the first i + 1 elements of the stack
result.push(new DecorationSegment(nextStartOffset, this.stopOffsets[i], this.classNames.join(' ')));
result.push(new DecorationSegment(nextStartOffset, this.stopOffsets[i], this.classNames.join(' '), Stack._metadata(this.metadata)));
nextStartOffset = this.stopOffsets[i] + 1;
// Consume them
this.stopOffsets.splice(0, i + 1);
this.classNames.splice(0, i + 1);
this.metadata.splice(0, i + 1);
this.count -= (i + 1);
}
if (this.count > 0 && nextStartOffset < maxStopOffset) {
result.push(new DecorationSegment(nextStartOffset, maxStopOffset - 1, this.classNames.join(' ')));
result.push(new DecorationSegment(nextStartOffset, maxStopOffset - 1, this.classNames.join(' '), Stack._metadata(this.metadata)));
nextStartOffset = maxStopOffset;
}
return nextStartOffset;
}
public insert(stopOffset: number, className: string): void {
public insert(stopOffset: number, className: string, metadata: number): void {
if (this.count === 0 || this.stopOffsets[this.count - 1] <= stopOffset) {
// Insert at the end
this.stopOffsets.push(stopOffset);
this.classNames.push(className);
this.metadata.push(metadata);
} else {
// Find the insertion position for `stopOffset`
for (let i = 0; i < this.count; i++) {
if (this.stopOffsets[i] >= stopOffset) {
this.stopOffsets.splice(i, 0, stopOffset);
this.classNames.splice(i, 0, className);
this.metadata.splice(i, 0, metadata);
break;
}
}
@@ -170,14 +195,21 @@ export class LineDecorationsNormalizer {
let result: DecorationSegment[] = [];
let stack = new Stack();
const stack = new Stack();
let nextStartOffset = 0;
for (let i = 0, len = lineDecorations.length; i < len; i++) {
let d = lineDecorations[i];
const d = lineDecorations[i];
let startColumn = d.startColumn;
let endColumn = d.endColumn;
let className = d.className;
const className = d.className;
const metadata = (
d.type === InlineDecorationType.Before
? LinePartMetadata.PSEUDO_BEFORE
: d.type === InlineDecorationType.After
? LinePartMetadata.PSEUDO_AFTER
: 0
);
// If the position would end up in the middle of a high-low surrogate pair, we move it to before the pair
if (startColumn > 1) {
@@ -194,15 +226,15 @@ export class LineDecorationsNormalizer {
}
}
let currentStartOffset = startColumn - 1;
let currentEndOffset = endColumn - 2;
const currentStartOffset = startColumn - 1;
const currentEndOffset = endColumn - 2;
nextStartOffset = stack.consumeLowerThan(currentStartOffset, nextStartOffset, result);
if (stack.count === 0) {
nextStartOffset = currentStartOffset;
}
stack.insert(currentEndOffset, className);
stack.insert(currentEndOffset, className, metadata);
}
stack.consumeLowerThan(Constants.MAX_SAFE_SMALL_INTEGER, nextStartOffset, result);

View File

@@ -17,6 +17,16 @@ export const enum RenderWhitespace {
All = 3
}
export const enum LinePartMetadata {
IS_WHITESPACE = 1,
PSEUDO_BEFORE = 2,
PSEUDO_AFTER = 4,
IS_WHITESPACE_MASK = 0b001,
PSEUDO_BEFORE_MASK = 0b010,
PSEUDO_AFTER_MASK = 0b100,
}
class LinePart {
_linePartBrand: void;
@@ -25,10 +35,16 @@ class LinePart {
*/
public readonly endIndex: number;
public readonly type: string;
public readonly metadata: number;
constructor(endIndex: number, type: string) {
constructor(endIndex: number, type: string, metadata: number) {
this.endIndex = endIndex;
this.type = type;
this.metadata = metadata;
}
public isWhitespace(): boolean {
return (this.metadata & LinePartMetadata.IS_WHITESPACE_MASK ? true : false);
}
}
@@ -470,7 +486,7 @@ function transformAndRemoveOverflowing(tokens: IViewLineTokens, fauxIndentLength
// The faux indent part of the line should have no token type
if (fauxIndentLength > 0) {
result[resultLen++] = new LinePart(fauxIndentLength, '');
result[resultLen++] = new LinePart(fauxIndentLength, '', 0);
}
for (let tokenIndex = 0, tokensLen = tokens.getCount(); tokenIndex < tokensLen; tokenIndex++) {
@@ -481,10 +497,10 @@ function transformAndRemoveOverflowing(tokens: IViewLineTokens, fauxIndentLength
}
const type = tokens.getClassName(tokenIndex);
if (endIndex >= len) {
result[resultLen++] = new LinePart(len, type);
result[resultLen++] = new LinePart(len, type, 0);
break;
}
result[resultLen++] = new LinePart(endIndex, type);
result[resultLen++] = new LinePart(endIndex, type, 0);
}
return result;
@@ -513,6 +529,7 @@ function splitLargeTokens(lineContent: string, tokens: LinePart[], onlyAtSpaces:
const tokenEndIndex = token.endIndex;
if (lastTokenEndIndex + Constants.LongToken < tokenEndIndex) {
const tokenType = token.type;
const tokenMetadata = token.metadata;
let lastSpaceOffset = -1;
let currTokenStart = lastTokenEndIndex;
@@ -522,13 +539,13 @@ function splitLargeTokens(lineContent: string, tokens: LinePart[], onlyAtSpaces:
}
if (lastSpaceOffset !== -1 && j - currTokenStart >= Constants.LongToken) {
// Split at `lastSpaceOffset` + 1
result[resultLen++] = new LinePart(lastSpaceOffset + 1, tokenType);
result[resultLen++] = new LinePart(lastSpaceOffset + 1, tokenType, tokenMetadata);
currTokenStart = lastSpaceOffset + 1;
lastSpaceOffset = -1;
}
}
if (currTokenStart !== tokenEndIndex) {
result[resultLen++] = new LinePart(tokenEndIndex, tokenType);
result[resultLen++] = new LinePart(tokenEndIndex, tokenType, tokenMetadata);
}
} else {
result[resultLen++] = token;
@@ -544,12 +561,13 @@ function splitLargeTokens(lineContent: string, tokens: LinePart[], onlyAtSpaces:
let diff = (tokenEndIndex - lastTokenEndIndex);
if (diff > Constants.LongToken) {
const tokenType = token.type;
const tokenMetadata = token.metadata;
const piecesCount = Math.ceil(diff / Constants.LongToken);
for (let j = 1; j < piecesCount; j++) {
let pieceEndIndex = lastTokenEndIndex + (j * Constants.LongToken);
result[resultLen++] = new LinePart(pieceEndIndex, tokenType);
result[resultLen++] = new LinePart(pieceEndIndex, tokenType, tokenMetadata);
}
result[resultLen++] = new LinePart(tokenEndIndex, tokenType);
result[resultLen++] = new LinePart(tokenEndIndex, tokenType, tokenMetadata);
} else {
result[resultLen++] = token;
}
@@ -640,17 +658,17 @@ function _applyRenderWhitespace(input: RenderLineInput, lineContent: string, len
if (generateLinePartForEachWhitespace) {
const lastEndIndex = (resultLen > 0 ? result[resultLen - 1].endIndex : fauxIndentLength);
for (let i = lastEndIndex + 1; i <= charIndex; i++) {
result[resultLen++] = new LinePart(i, 'mtkw');
result[resultLen++] = new LinePart(i, 'mtkw', LinePartMetadata.IS_WHITESPACE);
}
} else {
result[resultLen++] = new LinePart(charIndex, 'mtkw');
result[resultLen++] = new LinePart(charIndex, 'mtkw', LinePartMetadata.IS_WHITESPACE);
}
tmpIndent = tmpIndent % tabSize;
}
} else {
// was in regular token
if (charIndex === tokenEndIndex || (isInWhitespace && charIndex > fauxIndentLength)) {
result[resultLen++] = new LinePart(charIndex, tokenType);
result[resultLen++] = new LinePart(charIndex, tokenType, 0);
tmpIndent = tmpIndent % tabSize;
}
}
@@ -693,13 +711,13 @@ function _applyRenderWhitespace(input: RenderLineInput, lineContent: string, len
if (generateLinePartForEachWhitespace) {
const lastEndIndex = (resultLen > 0 ? result[resultLen - 1].endIndex : fauxIndentLength);
for (let i = lastEndIndex + 1; i <= len; i++) {
result[resultLen++] = new LinePart(i, 'mtkw');
result[resultLen++] = new LinePart(i, 'mtkw', LinePartMetadata.IS_WHITESPACE);
}
} else {
result[resultLen++] = new LinePart(len, 'mtkw');
result[resultLen++] = new LinePart(len, 'mtkw', LinePartMetadata.IS_WHITESPACE);
}
} else {
result[resultLen++] = new LinePart(len, tokenType);
result[resultLen++] = new LinePart(len, tokenType, 0);
}
return result;
@@ -720,42 +738,45 @@ function _applyInlineDecorations(lineContent: string, len: number, tokens: LineP
const token = tokens[tokenIndex];
const tokenEndIndex = token.endIndex;
const tokenType = token.type;
const tokenMetadata = token.metadata;
while (lineDecorationIndex < lineDecorationsLen && lineDecorations[lineDecorationIndex].startOffset < tokenEndIndex) {
const lineDecoration = lineDecorations[lineDecorationIndex];
if (lineDecoration.startOffset > lastResultEndIndex) {
lastResultEndIndex = lineDecoration.startOffset;
result[resultLen++] = new LinePart(lastResultEndIndex, tokenType);
result[resultLen++] = new LinePart(lastResultEndIndex, tokenType, tokenMetadata);
}
if (lineDecoration.endOffset + 1 <= tokenEndIndex) {
// This line decoration ends before this token ends
lastResultEndIndex = lineDecoration.endOffset + 1;
result[resultLen++] = new LinePart(lastResultEndIndex, tokenType + ' ' + lineDecoration.className);
result[resultLen++] = new LinePart(lastResultEndIndex, tokenType + ' ' + lineDecoration.className, tokenMetadata | lineDecoration.metadata);
lineDecorationIndex++;
} else {
// This line decoration continues on to the next token
lastResultEndIndex = tokenEndIndex;
result[resultLen++] = new LinePart(lastResultEndIndex, tokenType + ' ' + lineDecoration.className);
result[resultLen++] = new LinePart(lastResultEndIndex, tokenType + ' ' + lineDecoration.className, tokenMetadata | lineDecoration.metadata);
break;
}
}
if (tokenEndIndex > lastResultEndIndex) {
lastResultEndIndex = tokenEndIndex;
result[resultLen++] = new LinePart(lastResultEndIndex, tokenType);
result[resultLen++] = new LinePart(lastResultEndIndex, tokenType, tokenMetadata);
}
}
const lastTokenEndIndex = tokens[tokens.length - 1].endIndex;
if (lineDecorationIndex < lineDecorationsLen && lineDecorations[lineDecorationIndex].startOffset === lastTokenEndIndex) {
let classNames: string[] = [];
let metadata = 0;
while (lineDecorationIndex < lineDecorationsLen && lineDecorations[lineDecorationIndex].startOffset === lastTokenEndIndex) {
classNames.push(lineDecorations[lineDecorationIndex].className);
metadata |= lineDecorations[lineDecorationIndex].metadata;
lineDecorationIndex++;
}
result[resultLen++] = new LinePart(lastResultEndIndex, classNames.join(' '));
result[resultLen++] = new LinePart(lastResultEndIndex, classNames.join(' '), metadata);
}
return result;
@@ -788,6 +809,7 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
let visibleColumn = startVisibleColumn;
let charOffsetInPart = 0;
let partDisplacement = 0;
let prevPartContentCnt = 0;
let partAbsoluteOffset = 0;
@@ -799,8 +821,9 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
const part = parts[partIndex];
const partEndIndex = part.endIndex;
const partType = part.type;
const partRendersWhitespace = (renderWhitespace !== RenderWhitespace.None && (partType.indexOf('mtkw') >= 0));
const partRendersWhitespace = (renderWhitespace !== RenderWhitespace.None && part.isWhitespace());
const partRendersWhitespaceWithWidth = partRendersWhitespace && !fontIsMonospace && (partType === 'mtkw'/*only whitespace*/ || !containsForeignElements);
const partIsEmptyAndHasPseudoAfter = (charIndex === partEndIndex && part.metadata === LinePartMetadata.PSEUDO_AFTER);
charOffsetInPart = 0;
sb.appendASCIIString('<span class="');
@@ -832,7 +855,8 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
sb.appendASCII(CharCode.GreaterThan);
for (; charIndex < partEndIndex; charIndex++) {
characterMapping.setPartData(charIndex, partIndex, charOffsetInPart, partAbsoluteOffset);
characterMapping.setPartData(charIndex, partIndex - partDisplacement, charOffsetInPart, partAbsoluteOffset);
partDisplacement = 0;
const charCode = lineContent.charCodeAt(charIndex);
let charWidth: number;
@@ -872,7 +896,8 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
sb.appendASCII(CharCode.GreaterThan);
for (; charIndex < partEndIndex; charIndex++) {
characterMapping.setPartData(charIndex, partIndex, charOffsetInPart, partAbsoluteOffset);
characterMapping.setPartData(charIndex, partIndex - partDisplacement, charOffsetInPart, partAbsoluteOffset);
partDisplacement = 0;
const charCode = lineContent.charCodeAt(charIndex);
let producedCharacters = 1;
@@ -933,6 +958,12 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
prevPartContentCnt = partContentCnt;
}
if (partIsEmptyAndHasPseudoAfter) {
partDisplacement++;
} else {
partDisplacement = 0;
}
sb.appendASCIIString('</span>');
}