mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 5e80bf449c995aa32a59254c0ff845d37da11b70 (#9317)
This commit is contained in:
@@ -369,7 +369,7 @@ class Widget {
|
||||
|
||||
return {
|
||||
fitsAbove,
|
||||
aboveTop: Math.max(aboveTop, TOP_PADDING),
|
||||
aboveTop: aboveTop,
|
||||
aboveLeft,
|
||||
fitsBelow,
|
||||
belowTop,
|
||||
|
||||
@@ -121,6 +121,13 @@ export class RangeUtil {
|
||||
startChildIndex = Math.min(max, Math.max(min, startChildIndex));
|
||||
endChildIndex = Math.min(max, Math.max(min, endChildIndex));
|
||||
|
||||
if (startChildIndex === endChildIndex && startOffset === endOffset && startOffset === 0) {
|
||||
// We must find the position at the beginning of a <span>
|
||||
// To cover cases of empty <span>s, aboid using a range and use the <span>'s bounding box
|
||||
const clientRects = domNode.children[startChildIndex].getClientRects();
|
||||
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft);
|
||||
}
|
||||
|
||||
// If crossing over to a span only to select offset 0, then use the previous span's maximum offset
|
||||
// Chrome is buggy and doesn't handle 0 offsets well sometimes.
|
||||
if (startChildIndex !== endChildIndex) {
|
||||
|
||||
@@ -195,7 +195,7 @@ export class ViewLine implements IVisibleLine {
|
||||
const endColumn = (selection.endLineNumber === lineNumber ? selection.endColumn : lineData.maxColumn);
|
||||
|
||||
if (startColumn < endColumn) {
|
||||
if (this._options.renderWhitespace !== 'selection') {
|
||||
if (options.themeType === HIGH_CONTRAST || this._options.renderWhitespace !== 'selection') {
|
||||
actualInlineDecorations.push(new LineDecoration(startColumn, endColumn, 'inline-selected-text', InlineDecorationType.Regular));
|
||||
} else {
|
||||
if (!selectionsOnLine) {
|
||||
|
||||
@@ -1149,15 +1149,15 @@ class InnerMinimap extends Disposable {
|
||||
this._gestureInProgress = true;
|
||||
this.scrollDueToTouchEvent(e);
|
||||
}
|
||||
});
|
||||
}, { passive: false });
|
||||
|
||||
this._sliderTouchMoveListener = dom.addStandardDisposableListener(this._domNode.domNode, EventType.Change, (e: GestureEvent) => {
|
||||
this._sliderTouchMoveListener = dom.addDisposableListener(this._domNode.domNode, EventType.Change, (e: GestureEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (this._lastRenderData && this._gestureInProgress) {
|
||||
this.scrollDueToTouchEvent(e);
|
||||
}
|
||||
});
|
||||
}, { passive: false });
|
||||
|
||||
this._sliderTouchEndListener = dom.addStandardDisposableListener(this._domNode.domNode, EventType.End, (e: GestureEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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.") }
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>');
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import { FoldingDecorationProvider } from './foldingDecorations';
|
||||
import { FoldingRegions, FoldingRegion } from './foldingRanges';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { IMarginData } from 'vs/editor/browser/controller/mouseTarget';
|
||||
import { IMarginData, IEmptyContentData } from 'vs/editor/browser/controller/mouseTarget';
|
||||
import { HiddenRangeModel } from 'vs/editor/contrib/folding/hiddenRangeModel';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||
@@ -62,6 +62,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
private readonly editor: ICodeEditor;
|
||||
private _isEnabled: boolean;
|
||||
private _useFoldingProviders: boolean;
|
||||
private _unfoldOnClickInEmptyContent: boolean;
|
||||
|
||||
private readonly foldingDecorationProvider: FoldingDecorationProvider;
|
||||
|
||||
@@ -91,6 +92,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
const options = this.editor.getOptions();
|
||||
this._isEnabled = options.get(EditorOption.folding);
|
||||
this._useFoldingProviders = options.get(EditorOption.foldingStrategy) !== 'indentation';
|
||||
this._unfoldOnClickInEmptyContent = options.get(EditorOption.unfoldOnClickInEmptyContent);
|
||||
|
||||
this.foldingModel = null;
|
||||
this.hiddenRangeModel = null;
|
||||
@@ -128,6 +130,9 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
this._useFoldingProviders = options.get(EditorOption.foldingStrategy) !== 'indentation';
|
||||
this.onFoldingStrategyChanged();
|
||||
}
|
||||
if (e.hasChanged(EditorOption.unfoldOnClickInEmptyContent)) {
|
||||
this._unfoldOnClickInEmptyContent = options.get(EditorOption.unfoldOnClickInEmptyContent);
|
||||
}
|
||||
}));
|
||||
this.onModelChanged();
|
||||
}
|
||||
@@ -364,6 +369,15 @@ export class FoldingController extends Disposable implements IEditorContribution
|
||||
|
||||
iconClicked = true;
|
||||
break;
|
||||
case MouseTargetType.CONTENT_EMPTY: {
|
||||
if (this._unfoldOnClickInEmptyContent && this.hiddenRangeModel.hasRanges()) {
|
||||
const data = e.target.detail as IEmptyContentData;
|
||||
if (!data.isAfterLines) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case MouseTargetType.CONTENT_TEXT: {
|
||||
if (this.hiddenRangeModel.hasRanges()) {
|
||||
let model = this.editor.getModel();
|
||||
|
||||
@@ -397,7 +397,7 @@ class MarkerNavigationAction extends EditorAction {
|
||||
|
||||
return editorService.openCodeEditor({
|
||||
resource: newMarker.resource,
|
||||
options: { pinned: false, revealIfOpened: true, selectionRevealType: TextEditorSelectionRevealType.CenterIfOutsideViewport, selection: newMarker }
|
||||
options: { pinned: false, revealIfOpened: true, selectionRevealType: TextEditorSelectionRevealType.NearTop, selection: newMarker }
|
||||
}, editor).then(editor => {
|
||||
if (!editor) {
|
||||
return undefined;
|
||||
|
||||
@@ -52,11 +52,11 @@ class MessageWidget {
|
||||
|
||||
const domNode = document.createElement('div');
|
||||
domNode.className = 'descriptioncontainer';
|
||||
domNode.setAttribute('aria-live', 'assertive');
|
||||
domNode.setAttribute('role', 'alert');
|
||||
|
||||
this._messageBlock = document.createElement('div');
|
||||
dom.addClass(this._messageBlock, 'message');
|
||||
this._messageBlock.setAttribute('aria-live', 'assertive');
|
||||
this._messageBlock.setAttribute('role', 'alert');
|
||||
domNode.appendChild(this._messageBlock);
|
||||
|
||||
this._relatedBlock = document.createElement('div');
|
||||
@@ -88,7 +88,8 @@ class MessageWidget {
|
||||
dispose(this._disposables);
|
||||
}
|
||||
|
||||
update({ source, message, relatedInformation, code }: IMarker): void {
|
||||
update(marker: IMarker): void {
|
||||
const { source, message, relatedInformation, code } = marker;
|
||||
let sourceAndCodeLength = (source?.length || 0) + '()'.length;
|
||||
if (code) {
|
||||
if (typeof code === 'string') {
|
||||
@@ -106,6 +107,7 @@ class MessageWidget {
|
||||
}
|
||||
|
||||
dom.clearNode(this._messageBlock);
|
||||
this._messageBlock.setAttribute('aria-label', this.getAriaLabel(marker));
|
||||
this._editor.applyFontInfo(this._messageBlock);
|
||||
let lastLineElement = this._messageBlock;
|
||||
for (const line of lines) {
|
||||
@@ -192,6 +194,32 @@ class MessageWidget {
|
||||
getHeightInLines(): number {
|
||||
return Math.min(17, this._lines);
|
||||
}
|
||||
|
||||
private getAriaLabel(marker: IMarker): string {
|
||||
let severityLabel = '';
|
||||
switch (marker.severity) {
|
||||
case MarkerSeverity.Error:
|
||||
severityLabel = nls.localize('Error', "Error");
|
||||
break;
|
||||
case MarkerSeverity.Warning:
|
||||
severityLabel = nls.localize('Warning', "Warning");
|
||||
break;
|
||||
case MarkerSeverity.Info:
|
||||
severityLabel = nls.localize('Info', "Info");
|
||||
break;
|
||||
case MarkerSeverity.Hint:
|
||||
severityLabel = nls.localize('Hint', "Hint");
|
||||
break;
|
||||
}
|
||||
|
||||
let ariaLabel = nls.localize('marker aria', "{0} at {1}. ", severityLabel, marker.startLineNumber + ':' + marker.startColumn);
|
||||
const model = this._editor.getModel();
|
||||
if (model && (marker.startLineNumber <= model.getLineCount()) && (marker.startLineNumber >= 1)) {
|
||||
const lineContent = model.getLineContent(marker.startLineNumber);
|
||||
ariaLabel = `${lineContent}, ${ariaLabel}`;
|
||||
}
|
||||
return ariaLabel;
|
||||
}
|
||||
}
|
||||
|
||||
export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
@@ -316,7 +344,7 @@ export class MarkerNavigationWidget extends PeekViewWidget {
|
||||
}
|
||||
this._icon.className = `codicon ${SeverityIcon.className(MarkerSeverity.toSeverity(this._severity))}`;
|
||||
|
||||
this.editor.revealPositionInCenter(position, ScrollType.Smooth);
|
||||
this.editor.revealPositionNearTop(position, ScrollType.Smooth);
|
||||
this.editor.focus();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ suite('Editor ViewLayout - ViewLineParts', () => {
|
||||
]);
|
||||
|
||||
assert.deepEqual(result, [
|
||||
new DecorationSegment(0, 1, 'c1'),
|
||||
new DecorationSegment(2, 2, 'c2 c1'),
|
||||
new DecorationSegment(3, 9, 'c1'),
|
||||
new DecorationSegment(0, 1, 'c1', 0),
|
||||
new DecorationSegment(2, 2, 'c2 c1', 0),
|
||||
new DecorationSegment(3, 9, 'c1', 0),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -32,8 +32,8 @@ suite('Editor ViewLayout - ViewLineParts', () => {
|
||||
]);
|
||||
|
||||
assert.deepEqual(result, [
|
||||
new DecorationSegment(14, 18, 'mtkw'),
|
||||
new DecorationSegment(19, 19, 'mtkw inline-folded')
|
||||
new DecorationSegment(14, 18, 'mtkw', 0),
|
||||
new DecorationSegment(19, 19, 'mtkw inline-folded', 0)
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -66,24 +66,24 @@ suite('Editor ViewLayout - ViewLineParts', () => {
|
||||
new LineDecoration(1, 2, 'c1', InlineDecorationType.Regular),
|
||||
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
|
||||
]), [
|
||||
new DecorationSegment(0, 0, 'c1'),
|
||||
new DecorationSegment(2, 2, 'c2')
|
||||
new DecorationSegment(0, 0, 'c1', 0),
|
||||
new DecorationSegment(2, 2, 'c2', 0)
|
||||
]);
|
||||
|
||||
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
|
||||
new LineDecoration(1, 3, 'c1', InlineDecorationType.Regular),
|
||||
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
|
||||
]), [
|
||||
new DecorationSegment(0, 1, 'c1'),
|
||||
new DecorationSegment(2, 2, 'c2')
|
||||
new DecorationSegment(0, 1, 'c1', 0),
|
||||
new DecorationSegment(2, 2, 'c2', 0)
|
||||
]);
|
||||
|
||||
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
|
||||
new LineDecoration(1, 4, 'c1', InlineDecorationType.Regular),
|
||||
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
|
||||
]), [
|
||||
new DecorationSegment(0, 1, 'c1'),
|
||||
new DecorationSegment(2, 2, 'c1 c2')
|
||||
new DecorationSegment(0, 1, 'c1', 0),
|
||||
new DecorationSegment(2, 2, 'c1 c2', 0)
|
||||
]);
|
||||
|
||||
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
|
||||
@@ -91,8 +91,8 @@ suite('Editor ViewLayout - ViewLineParts', () => {
|
||||
new LineDecoration(1, 4, 'c1*', InlineDecorationType.Regular),
|
||||
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
|
||||
]), [
|
||||
new DecorationSegment(0, 1, 'c1 c1*'),
|
||||
new DecorationSegment(2, 2, 'c1 c1* c2')
|
||||
new DecorationSegment(0, 1, 'c1 c1*', 0),
|
||||
new DecorationSegment(2, 2, 'c1 c1* c2', 0)
|
||||
]);
|
||||
|
||||
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
|
||||
@@ -101,8 +101,8 @@ suite('Editor ViewLayout - ViewLineParts', () => {
|
||||
new LineDecoration(1, 4, 'c1**', InlineDecorationType.Regular),
|
||||
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular)
|
||||
]), [
|
||||
new DecorationSegment(0, 1, 'c1 c1* c1**'),
|
||||
new DecorationSegment(2, 2, 'c1 c1* c1** c2')
|
||||
new DecorationSegment(0, 1, 'c1 c1* c1**', 0),
|
||||
new DecorationSegment(2, 2, 'c1 c1* c1** c2', 0)
|
||||
]);
|
||||
|
||||
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
|
||||
@@ -112,8 +112,8 @@ suite('Editor ViewLayout - ViewLineParts', () => {
|
||||
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular),
|
||||
new LineDecoration(3, 4, 'c2*', InlineDecorationType.Regular)
|
||||
]), [
|
||||
new DecorationSegment(0, 1, 'c1 c1* c1**'),
|
||||
new DecorationSegment(2, 2, 'c1 c1* c1** c2 c2*')
|
||||
new DecorationSegment(0, 1, 'c1 c1* c1**', 0),
|
||||
new DecorationSegment(2, 2, 'c1 c1* c1** c2 c2*', 0)
|
||||
]);
|
||||
|
||||
assert.deepEqual(LineDecorationsNormalizer.normalize('abcabcabcabcabcabcabcabcabcabc', [
|
||||
@@ -123,9 +123,9 @@ suite('Editor ViewLayout - ViewLineParts', () => {
|
||||
new LineDecoration(3, 4, 'c2', InlineDecorationType.Regular),
|
||||
new LineDecoration(3, 5, 'c2*', InlineDecorationType.Regular)
|
||||
]), [
|
||||
new DecorationSegment(0, 1, 'c1 c1* c1**'),
|
||||
new DecorationSegment(2, 2, 'c1 c1* c1** c2 c2*'),
|
||||
new DecorationSegment(3, 3, 'c2*')
|
||||
new DecorationSegment(0, 1, 'c1 c1* c1**', 0),
|
||||
new DecorationSegment(2, 2, 'c1 c1* c1** c2 c2*', 0),
|
||||
new DecorationSegment(3, 3, 'c2*', 0)
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -388,6 +388,66 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr, [12, 12, 24, 1, 21, 2, 1, 20, 1, 1]);
|
||||
});
|
||||
|
||||
test('issue #91178: after decoration type shown before cursor', () => {
|
||||
const lineText = '//just a comment';
|
||||
const lineParts = createViewLineTokens([
|
||||
createPart(16, 1)
|
||||
]);
|
||||
const expectedOutput = [
|
||||
'<span class="mtk1">//just\u00a0a\u00a0com</span>',
|
||||
'<span class="mtk1 dec2"></span>',
|
||||
'<span class="mtk1 dec1"></span>',
|
||||
'<span class="mtk1">ment</span>',
|
||||
].join('');
|
||||
|
||||
const expectedCharacterMapping = new CharacterMapping(17, 4);
|
||||
expectedCharacterMapping.setPartData(0, 0, 0, 0);
|
||||
expectedCharacterMapping.setPartData(1, 0, 1, 0);
|
||||
expectedCharacterMapping.setPartData(2, 0, 2, 0);
|
||||
expectedCharacterMapping.setPartData(3, 0, 3, 0);
|
||||
expectedCharacterMapping.setPartData(4, 0, 4, 0);
|
||||
expectedCharacterMapping.setPartData(5, 0, 5, 0);
|
||||
expectedCharacterMapping.setPartData(6, 0, 6, 0);
|
||||
expectedCharacterMapping.setPartData(7, 0, 7, 0);
|
||||
expectedCharacterMapping.setPartData(8, 0, 8, 0);
|
||||
expectedCharacterMapping.setPartData(9, 0, 9, 0);
|
||||
expectedCharacterMapping.setPartData(10, 0, 10, 0);
|
||||
expectedCharacterMapping.setPartData(11, 0, 11, 0);
|
||||
expectedCharacterMapping.setPartData(12, 2, 0, 12);
|
||||
expectedCharacterMapping.setPartData(13, 3, 1, 12);
|
||||
expectedCharacterMapping.setPartData(14, 3, 2, 12);
|
||||
expectedCharacterMapping.setPartData(15, 3, 3, 12);
|
||||
expectedCharacterMapping.setPartData(16, 3, 4, 12);
|
||||
|
||||
const actual = renderViewLine(new RenderLineInput(
|
||||
true,
|
||||
false,
|
||||
lineText,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
0,
|
||||
lineParts,
|
||||
[
|
||||
new LineDecoration(13, 13, 'dec1', InlineDecorationType.After),
|
||||
new LineDecoration(13, 13, 'dec2', InlineDecorationType.Before),
|
||||
],
|
||||
4,
|
||||
0,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
-1,
|
||||
'none',
|
||||
false,
|
||||
false,
|
||||
null
|
||||
));
|
||||
|
||||
assert.equal(actual.html, '<span>' + expectedOutput + '</span>');
|
||||
assertCharacterMapping2(actual.characterMapping, expectedCharacterMapping);
|
||||
});
|
||||
|
||||
test('issue Microsoft/monaco-editor#280: Improved source code rendering for RTL languages', () => {
|
||||
let lineText = 'var קודמות = \"מיותר קודמות צ\'ט של, אם לשון העברית שינויים ויש, אם\";';
|
||||
|
||||
@@ -693,6 +753,33 @@ suite('viewLineRenderer.renderLine', () => {
|
||||
assert.equal(_actual.html, '<span>' + expectedOutput + '</span>');
|
||||
});
|
||||
|
||||
interface ICharMappingData {
|
||||
charOffset: number;
|
||||
partIndex: number;
|
||||
charIndex: number;
|
||||
}
|
||||
|
||||
function decodeCharacterMapping(source: CharacterMapping) {
|
||||
const mapping: ICharMappingData[] = [];
|
||||
for (let charOffset = 0; charOffset < source.length; charOffset++) {
|
||||
const partData = source.charOffsetToPartData(charOffset);
|
||||
const partIndex = CharacterMapping.getPartIndex(partData);
|
||||
const charIndex = CharacterMapping.getCharIndex(partData);
|
||||
mapping.push({ charOffset, partIndex, charIndex });
|
||||
}
|
||||
const absoluteOffsets: number[] = [];
|
||||
for (const absoluteOffset of source.getAbsoluteOffsets()) {
|
||||
absoluteOffsets.push(absoluteOffset);
|
||||
}
|
||||
return { mapping, absoluteOffsets };
|
||||
}
|
||||
|
||||
function assertCharacterMapping2(actual: CharacterMapping, expected: CharacterMapping): void {
|
||||
const _actual = decodeCharacterMapping(actual);
|
||||
const _expected = decodeCharacterMapping(expected);
|
||||
assert.deepEqual(_actual, _expected);
|
||||
}
|
||||
|
||||
function assertCharacterMapping(actual: CharacterMapping, expectedCharPartOffsets: number[][], expectedPartLengths: number[]): void {
|
||||
|
||||
assertCharPartOffsets(actual, expectedCharPartOffsets);
|
||||
|
||||
Reference in New Issue
Block a user