mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-14 12:08:36 -05:00
Merge VS Code 1.31.1 (#4283)
This commit is contained in:
@@ -33,7 +33,7 @@ export interface ITabFocus {
|
||||
export const TabFocus: ITabFocus = new class implements ITabFocus {
|
||||
private _tabFocus: boolean = false;
|
||||
|
||||
private readonly _onDidChangeTabFocus: Emitter<boolean> = new Emitter<boolean>();
|
||||
private readonly _onDidChangeTabFocus = new Emitter<boolean>();
|
||||
public readonly onDidChangeTabFocus: Event<boolean> = this._onDidChangeTabFocus.event;
|
||||
|
||||
public getTabFocusMode(): boolean {
|
||||
@@ -429,6 +429,11 @@ const editorConfiguration: IConfigurationNode = {
|
||||
'default': EDITOR_DEFAULTS.viewInfo.scrollbar.mouseWheelScrollSensitivity,
|
||||
'markdownDescription': nls.localize('mouseWheelScrollSensitivity', "A multiplier to be used on the `deltaX` and `deltaY` of mouse wheel scroll events.")
|
||||
},
|
||||
'editor.fastScrollSensitivity': {
|
||||
'type': 'number',
|
||||
'default': EDITOR_DEFAULTS.viewInfo.scrollbar.fastScrollSensitivity,
|
||||
'markdownDescription': nls.localize('fastScrollSensitivity', "Scrolling speed mulitiplier when pressing `Alt`.")
|
||||
},
|
||||
'editor.multiCursorModifier': {
|
||||
'type': 'string',
|
||||
'enum': ['ctrlCmd', 'alt'],
|
||||
@@ -639,6 +644,11 @@ const editorConfiguration: IConfigurationNode = {
|
||||
default: false,
|
||||
description: nls.localize('suggest.localityBonus', "Controls whether sorting favours words that appear close to the cursor.")
|
||||
},
|
||||
'editor.suggest.shareSuggestSelections': {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
markdownDescription: nls.localize('suggest.shareSuggestSelections', "Controls whether remembered suggestion selections are shared between multiple workspaces and windows (needs `#editor.suggestSelection#`).")
|
||||
},
|
||||
'editor.suggest.snippetsPreventQuickSuggestions': {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
@@ -647,7 +657,7 @@ const editorConfiguration: IConfigurationNode = {
|
||||
'editor.selectionHighlight': {
|
||||
'type': 'boolean',
|
||||
'default': EDITOR_DEFAULTS.contribInfo.selectionHighlight,
|
||||
'description': nls.localize('selectionHighlight', "Controls whether the editor should highlight matches similar to the selection")
|
||||
'description': nls.localize('selectionHighlight', "Controls whether the editor should highlight matches similar to the selection.")
|
||||
},
|
||||
'editor.occurrencesHighlight': {
|
||||
'type': 'boolean',
|
||||
@@ -742,12 +752,12 @@ const editorConfiguration: IConfigurationNode = {
|
||||
'editor.codeLens': {
|
||||
'type': 'boolean',
|
||||
'default': EDITOR_DEFAULTS.contribInfo.codeLens,
|
||||
'description': nls.localize('codeLens', "Controls whether the editor shows CodeLens")
|
||||
'description': nls.localize('codeLens', "Controls whether the editor shows CodeLens.")
|
||||
},
|
||||
'editor.folding': {
|
||||
'type': 'boolean',
|
||||
'default': EDITOR_DEFAULTS.contribInfo.folding,
|
||||
'description': nls.localize('folding', "Controls whether the editor has code folding enabled")
|
||||
'description': nls.localize('folding', "Controls whether the editor has code folding enabled.")
|
||||
},
|
||||
'editor.foldingStrategy': {
|
||||
'type': 'string',
|
||||
@@ -828,6 +838,10 @@ const editorConfiguration: IConfigurationNode = {
|
||||
'source.organizeImports': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('codeActionsOnSave.organizeImports', "Controls whether organize imports action should be run on file save.")
|
||||
},
|
||||
'source.fixAll': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('codeActionsOnSave.fixAll', "Controls whether auto fix action should be run on file save.")
|
||||
}
|
||||
},
|
||||
'additionalProperties': {
|
||||
|
||||
@@ -198,7 +198,7 @@ export interface ISuggestOptions {
|
||||
/**
|
||||
* Enable using global storage for remembering suggestions.
|
||||
*/
|
||||
useGlobalStorageForSuggestions?: boolean;
|
||||
shareSuggestSelections?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -458,6 +458,11 @@ export interface IEditorOptions {
|
||||
* Defaults to 1.
|
||||
*/
|
||||
mouseWheelScrollSensitivity?: number;
|
||||
/**
|
||||
* FastScrolling mulitplier speed when pressing `Alt`
|
||||
* Defaults to 5.
|
||||
*/
|
||||
fastScrollSensitivity?: number;
|
||||
/**
|
||||
* The modifier to be used to add multiple cursors with the mouse.
|
||||
* Defaults to 'alt'
|
||||
@@ -875,6 +880,7 @@ export interface InternalEditorScrollbarOptions {
|
||||
readonly verticalScrollbarSize: number;
|
||||
readonly verticalSliderSize: number;
|
||||
readonly mouseWheelScrollSensitivity: number;
|
||||
readonly fastScrollSensitivity: number;
|
||||
}
|
||||
|
||||
export interface InternalEditorMinimapOptions {
|
||||
@@ -1292,6 +1298,7 @@ export class InternalEditorOptions {
|
||||
&& a.verticalScrollbarSize === b.verticalScrollbarSize
|
||||
&& a.verticalSliderSize === b.verticalSliderSize
|
||||
&& a.mouseWheelScrollSensitivity === b.mouseWheelScrollSensitivity
|
||||
&& a.fastScrollSensitivity === b.fastScrollSensitivity
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1795,7 +1802,7 @@ export class EditorOptionsValidator {
|
||||
};
|
||||
}
|
||||
|
||||
private static _sanitizeScrollbarOpts(opts: IEditorScrollbarOptions | undefined, defaults: InternalEditorScrollbarOptions, mouseWheelScrollSensitivity: number): InternalEditorScrollbarOptions {
|
||||
private static _sanitizeScrollbarOpts(opts: IEditorScrollbarOptions | undefined, defaults: InternalEditorScrollbarOptions, mouseWheelScrollSensitivity: number, fastScrollSensitivity: number): InternalEditorScrollbarOptions {
|
||||
if (typeof opts !== 'object') {
|
||||
return defaults;
|
||||
}
|
||||
@@ -1818,7 +1825,8 @@ export class EditorOptionsValidator {
|
||||
verticalSliderSize: _clampedInt(opts.verticalSliderSize, verticalScrollbarSize, 0, 1000),
|
||||
|
||||
handleMouseWheel: _boolean(opts.handleMouseWheel, defaults.handleMouseWheel),
|
||||
mouseWheelScrollSensitivity: mouseWheelScrollSensitivity
|
||||
mouseWheelScrollSensitivity: mouseWheelScrollSensitivity,
|
||||
fastScrollSensitivity: fastScrollSensitivity,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1835,7 +1843,7 @@ export class EditorOptionsValidator {
|
||||
};
|
||||
}
|
||||
|
||||
private static _santizeFindOpts(opts: IEditorFindOptions | undefined, defaults: InternalEditorFindOptions): InternalEditorFindOptions {
|
||||
private static _sanitizeFindOpts(opts: IEditorFindOptions | undefined, defaults: InternalEditorFindOptions): InternalEditorFindOptions {
|
||||
if (typeof opts !== 'object') {
|
||||
return defaults;
|
||||
}
|
||||
@@ -1858,7 +1866,7 @@ export class EditorOptionsValidator {
|
||||
};
|
||||
}
|
||||
|
||||
private static _santizeHoverOpts(_opts: boolean | IEditorHoverOptions | undefined, defaults: InternalEditorHoverOptions): InternalEditorHoverOptions {
|
||||
private static _sanitizeHoverOpts(_opts: boolean | IEditorHoverOptions | undefined, defaults: InternalEditorHoverOptions): InternalEditorHoverOptions {
|
||||
let opts: IEditorHoverOptions;
|
||||
if (typeof _opts === 'boolean') {
|
||||
opts = {
|
||||
@@ -1884,7 +1892,7 @@ export class EditorOptionsValidator {
|
||||
snippets: _stringSet<'top' | 'bottom' | 'inline' | 'none'>(opts.snippetSuggestions, defaults.snippets, ['top', 'bottom', 'inline', 'none']),
|
||||
snippetsPreventQuickSuggestions: _boolean(suggestOpts.snippetsPreventQuickSuggestions, defaults.filterGraceful),
|
||||
localityBonus: _boolean(suggestOpts.localityBonus, defaults.localityBonus),
|
||||
shareSuggestSelections: _boolean(suggestOpts.useGlobalStorageForSuggestions, defaults.shareSuggestSelections)
|
||||
shareSuggestSelections: _boolean(suggestOpts.shareSuggestSelections, defaults.shareSuggestSelections)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1946,7 +1954,7 @@ export class EditorOptionsValidator {
|
||||
} else if (<any>renderWhitespace === false) {
|
||||
renderWhitespace = 'none';
|
||||
}
|
||||
renderWhitespace = _stringSet<'none' | 'boundary' | 'all'>(opts.renderWhitespace, defaults.renderWhitespace, ['none', 'boundary', 'all']);
|
||||
renderWhitespace = _stringSet<'none' | 'boundary' | 'all'>(renderWhitespace, defaults.renderWhitespace, ['none', 'boundary', 'all']);
|
||||
}
|
||||
|
||||
let renderLineHighlight = opts.renderLineHighlight;
|
||||
@@ -1957,7 +1965,7 @@ export class EditorOptionsValidator {
|
||||
} else if (<any>renderLineHighlight === false) {
|
||||
renderLineHighlight = 'none';
|
||||
}
|
||||
renderLineHighlight = _stringSet<'none' | 'gutter' | 'line' | 'all'>(opts.renderLineHighlight, defaults.renderLineHighlight, ['none', 'gutter', 'line', 'all']);
|
||||
renderLineHighlight = _stringSet<'none' | 'gutter' | 'line' | 'all'>(renderLineHighlight, defaults.renderLineHighlight, ['none', 'gutter', 'line', 'all']);
|
||||
}
|
||||
|
||||
let mouseWheelScrollSensitivity = _float(opts.mouseWheelScrollSensitivity, defaults.scrollbar.mouseWheelScrollSensitivity);
|
||||
@@ -1965,7 +1973,12 @@ export class EditorOptionsValidator {
|
||||
// Disallow 0, as it would prevent/block scrolling
|
||||
mouseWheelScrollSensitivity = 1;
|
||||
}
|
||||
const scrollbar = this._sanitizeScrollbarOpts(opts.scrollbar, defaults.scrollbar, mouseWheelScrollSensitivity);
|
||||
|
||||
let fastScrollSensitivity = _float(opts.fastScrollSensitivity, defaults.scrollbar.fastScrollSensitivity);
|
||||
if (fastScrollSensitivity <= 0) {
|
||||
fastScrollSensitivity = defaults.scrollbar.fastScrollSensitivity;
|
||||
}
|
||||
const scrollbar = this._sanitizeScrollbarOpts(opts.scrollbar, defaults.scrollbar, mouseWheelScrollSensitivity, fastScrollSensitivity);
|
||||
const minimap = this._sanitizeMinimapOpts(opts.minimap, defaults.minimap);
|
||||
|
||||
return {
|
||||
@@ -2014,10 +2027,10 @@ export class EditorOptionsValidator {
|
||||
if (typeof opts.acceptSuggestionOnEnter === 'boolean') {
|
||||
opts.acceptSuggestionOnEnter = opts.acceptSuggestionOnEnter ? 'on' : 'off';
|
||||
}
|
||||
const find = this._santizeFindOpts(opts.find, defaults.find);
|
||||
const find = this._sanitizeFindOpts(opts.find, defaults.find);
|
||||
return {
|
||||
selectionClipboard: _boolean(opts.selectionClipboard, defaults.selectionClipboard),
|
||||
hover: this._santizeHoverOpts(opts.hover, defaults.hover),
|
||||
hover: this._sanitizeHoverOpts(opts.hover, defaults.hover),
|
||||
links: _boolean(opts.links, defaults.links),
|
||||
contextmenu: _boolean(opts.contextmenu, defaults.contextmenu),
|
||||
quickSuggestions: quickSuggestions,
|
||||
@@ -2535,7 +2548,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = {
|
||||
wordWrapMinified: true,
|
||||
wrappingIndent: WrappingIndent.Same,
|
||||
wordWrapBreakBeforeCharacters: '([{‘“〈《「『【〔([{「£¥$£¥++',
|
||||
wordWrapBreakAfterCharacters: ' \t})]?|&,;¢°′″‰℃、。。、¢,.:;?!%・・ゝゞヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻ァィゥェォャュョッー”〉》」』】〕)]}」',
|
||||
wordWrapBreakAfterCharacters: ' \t})]?|/&,;¢°′″‰℃、。。、¢,.:;?!%・・ゝゞヽヾーァィゥェォッャュョヮヵヶぁぃぅぇぉっゃゅょゎゕゖㇰㇱㇲㇳㇴㇵㇶㇷㇸㇹㇺㇻㇼㇽㇾㇿ々〻ァィゥェォャュョッー”〉》」』】〕)]}」',
|
||||
wordWrapBreakObtrusiveCharacters: '.',
|
||||
autoClosingBrackets: 'languageDefined',
|
||||
autoClosingQuotes: 'languageDefined',
|
||||
@@ -2592,6 +2605,7 @@ export const EDITOR_DEFAULTS: IValidatedEditorOptions = {
|
||||
verticalSliderSize: 14,
|
||||
handleMouseWheel: true,
|
||||
mouseWheelScrollSensitivity: 1,
|
||||
fastScrollSensitivity: 5,
|
||||
},
|
||||
minimap: {
|
||||
// {{SQL CARBON EDIT}}
|
||||
|
||||
@@ -15,7 +15,7 @@ export const EditorZoom: IEditorZoom = new class implements IEditorZoom {
|
||||
|
||||
private _zoomLevel: number = 0;
|
||||
|
||||
private readonly _onDidChangeZoomLevel: Emitter<number> = new Emitter<number>();
|
||||
private readonly _onDidChangeZoomLevel = new Emitter<number>();
|
||||
public readonly onDidChangeZoomLevel: Event<number> = this._onDidChangeZoomLevel.event;
|
||||
|
||||
public getZoomLevel(): number {
|
||||
|
||||
@@ -194,7 +194,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
public setStates(source: string, reason: CursorChangeReason, states: PartialCursorState[] | null): void {
|
||||
if (states !== null && states.length > Cursor.MAX_CURSOR_COUNT) {
|
||||
states = states.slice(0, Cursor.MAX_CURSOR_COUNT);
|
||||
this._onDidReachMaxCursorCount.fire(void 0);
|
||||
this._onDidReachMaxCursorCount.fire(undefined);
|
||||
}
|
||||
|
||||
const oldState = new CursorModelState(this._model, this);
|
||||
@@ -467,7 +467,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors {
|
||||
if (this._configuration.editor.readOnly) {
|
||||
// All the remaining handlers will try to edit the model,
|
||||
// but we cannot edit when read only...
|
||||
this._onDidAttemptReadOnlyEdit.fire(void 0);
|
||||
this._onDidAttemptReadOnlyEdit.fire(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -675,8 +675,7 @@ class CommandExecutor {
|
||||
for (let i = 0; i < ctx.selectionsBefore.length; i++) {
|
||||
groupedInverseEditOperations[i] = [];
|
||||
}
|
||||
for (let i = 0; i < inverseEditOperations.length; i++) {
|
||||
const op = inverseEditOperations[i];
|
||||
for (const op of inverseEditOperations) {
|
||||
if (!op.identifier) {
|
||||
// perhaps auto whitespace trim edits
|
||||
continue;
|
||||
@@ -728,8 +727,8 @@ class CommandExecutor {
|
||||
});
|
||||
|
||||
// Remove losing cursors
|
||||
for (let i = 0; i < losingCursors.length; i++) {
|
||||
selectionsAfter.splice(losingCursors[i], 1);
|
||||
for (const losingCursor of losingCursors) {
|
||||
selectionsAfter.splice(losingCursor, 1);
|
||||
}
|
||||
|
||||
return selectionsAfter;
|
||||
|
||||
@@ -254,9 +254,9 @@ export class CursorCollection {
|
||||
cursors[winnerIndex].setState(this.context, resultingState.modelState, resultingState.viewState);
|
||||
}
|
||||
|
||||
for (let j = 0; j < sortedCursors.length; j++) {
|
||||
if (sortedCursors[j].index > looserIndex) {
|
||||
sortedCursors[j].index--;
|
||||
for (const sortedCursor of sortedCursors) {
|
||||
if (sortedCursor.index > looserIndex) {
|
||||
sortedCursor.index--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,16 +148,16 @@ export class CursorConfiguration {
|
||||
|
||||
let autoClosingPairs = CursorConfiguration._getAutoClosingPairs(languageIdentifier);
|
||||
if (autoClosingPairs) {
|
||||
for (let i = 0; i < autoClosingPairs.length; i++) {
|
||||
this.autoClosingPairsOpen[autoClosingPairs[i].open] = autoClosingPairs[i].close;
|
||||
this.autoClosingPairsClose[autoClosingPairs[i].close] = autoClosingPairs[i].open;
|
||||
for (const pair of autoClosingPairs) {
|
||||
this.autoClosingPairsOpen[pair.open] = pair.close;
|
||||
this.autoClosingPairsClose[pair.close] = pair.open;
|
||||
}
|
||||
}
|
||||
|
||||
let surroundingPairs = CursorConfiguration._getSurroundingPairs(languageIdentifier);
|
||||
if (surroundingPairs) {
|
||||
for (let i = 0; i < surroundingPairs.length; i++) {
|
||||
this.surroundingPairs[surroundingPairs[i].open] = surroundingPairs[i].close;
|
||||
for (const pair of surroundingPairs) {
|
||||
this.surroundingPairs[pair.open] = pair.close;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,8 +167,8 @@ export class CursorConfiguration {
|
||||
this._electricChars = {};
|
||||
let electricChars = CursorConfiguration._getElectricCharacters(this._languageIdentifier);
|
||||
if (electricChars) {
|
||||
for (let i = 0; i < electricChars.length; i++) {
|
||||
this._electricChars[electricChars[i]] = true;
|
||||
for (const char of electricChars) {
|
||||
this._electricChars[char] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -464,13 +464,13 @@ export class EditOperationResult {
|
||||
_editOperationResultBrand: void;
|
||||
|
||||
readonly type: EditOperationType;
|
||||
readonly commands: (ICommand | null)[];
|
||||
readonly commands: Array<ICommand | null>;
|
||||
readonly shouldPushStackElementBefore: boolean;
|
||||
readonly shouldPushStackElementAfter: boolean;
|
||||
|
||||
constructor(
|
||||
type: EditOperationType,
|
||||
commands: (ICommand | null)[],
|
||||
commands: Array<ICommand | null>,
|
||||
opts: {
|
||||
shouldPushStackElementBefore: boolean;
|
||||
shouldPushStackElementAfter: boolean;
|
||||
|
||||
@@ -13,8 +13,8 @@ import { ICommand } from 'vs/editor/common/editorCommon';
|
||||
|
||||
export class DeleteOperations {
|
||||
|
||||
public static deleteRight(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, (ICommand | null)[]] {
|
||||
let commands: (ICommand | null)[] = [];
|
||||
public static deleteRight(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, Array<ICommand | null>] {
|
||||
let commands: Array<ICommand | null> = [];
|
||||
let shouldPushStackElementBefore = (prevEditOperationType !== EditOperationType.DeletingRight);
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
const selection = selections[i];
|
||||
@@ -103,13 +103,13 @@ export class DeleteOperations {
|
||||
return [true, commands];
|
||||
}
|
||||
|
||||
public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, (ICommand | null)[]] {
|
||||
public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, Array<ICommand | null>] {
|
||||
|
||||
if (this._isAutoClosingPairDelete(config, model, selections)) {
|
||||
return this._runAutoClosingPairDelete(config, model, selections);
|
||||
}
|
||||
|
||||
let commands: (ICommand | null)[] = [];
|
||||
let commands: Array<ICommand | null> = [];
|
||||
let shouldPushStackElementBefore = (prevEditOperationType !== EditOperationType.DeletingLeft);
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
const selection = selections[i];
|
||||
@@ -164,7 +164,7 @@ export class DeleteOperations {
|
||||
}
|
||||
|
||||
public static cut(config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): EditOperationResult {
|
||||
let commands: (ICommand | null)[] = [];
|
||||
let commands: Array<ICommand | null> = [];
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
const selection = selections[i];
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ export class TypeOperations {
|
||||
action = expectedIndentAction.action;
|
||||
indentation = expectedIndentAction.indentation;
|
||||
} else if (lineNumber > 1) {
|
||||
let lastLineNumber = lineNumber - 1;
|
||||
let lastLineNumber: number;
|
||||
for (lastLineNumber = lineNumber - 1; lastLineNumber >= 1; lastLineNumber--) {
|
||||
let lineText = model.getLineContent(lastLineNumber);
|
||||
let nonWhitespaceIdx = strings.lastNonWhitespaceIndex(lineText);
|
||||
@@ -263,7 +263,7 @@ export class TypeOperations {
|
||||
}
|
||||
|
||||
public static replacePreviousChar(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[], txt: string, replaceCharCnt: number): EditOperationResult {
|
||||
let commands: (ICommand | null)[] = [];
|
||||
let commands: Array<ICommand | null> = [];
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
const selection = selections[i];
|
||||
if (!selection.isEmpty()) {
|
||||
@@ -825,7 +825,7 @@ export class TypeOperations {
|
||||
}
|
||||
|
||||
if (this._isAutoIndentType(config, model, selections)) {
|
||||
let commands: (ICommand | null)[] = [];
|
||||
let commands: Array<ICommand | null> = [];
|
||||
let autoIndentFails = false;
|
||||
for (let i = 0, len = selections.length; i < len; i++) {
|
||||
commands[i] = this._runAutoIndentType(config, model, selections[i], ch);
|
||||
|
||||
@@ -252,8 +252,10 @@ export class WordOperations {
|
||||
let lineNumber = position.lineNumber;
|
||||
let column = position.column;
|
||||
|
||||
let movedDown = false;
|
||||
if (column === model.getLineMaxColumn(lineNumber)) {
|
||||
if (lineNumber < model.getLineCount()) {
|
||||
movedDown = true;
|
||||
lineNumber = lineNumber + 1;
|
||||
column = 1;
|
||||
}
|
||||
@@ -274,7 +276,7 @@ export class WordOperations {
|
||||
column = model.getLineMaxColumn(lineNumber);
|
||||
}
|
||||
} else {
|
||||
if (nextWordOnLine && column >= nextWordOnLine.start + 1) {
|
||||
if (nextWordOnLine && !movedDown && column >= nextWordOnLine.start + 1) {
|
||||
nextWordOnLine = WordOperations._findNextWordOnLine(wordSeparators, model, new Position(lineNumber, nextWordOnLine.end + 1));
|
||||
}
|
||||
if (nextWordOnLine) {
|
||||
@@ -613,6 +615,6 @@ export class WordPartOperations extends WordOperations {
|
||||
}
|
||||
}
|
||||
|
||||
function enforceDefined<T>(arr: (T | undefined | null)[]): T[] {
|
||||
function enforceDefined<T>(arr: Array<T | undefined | null>): T[] {
|
||||
return <T[]>arr.filter(el => Boolean(el));
|
||||
}
|
||||
@@ -69,7 +69,7 @@ export class Position {
|
||||
/**
|
||||
* Test if position `a` equals position `b`
|
||||
*/
|
||||
public static equals(a: IPosition, b: IPosition): boolean {
|
||||
public static equals(a: IPosition | null, b: IPosition | null): boolean {
|
||||
if (!a && !b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ export class InternalEditorAction implements IEditorAction {
|
||||
|
||||
public run(): Promise<void> {
|
||||
if (!this.isSupported()) {
|
||||
return Promise.resolve(void 0);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const r = this._run();
|
||||
return r ? r : Promise.resolve(void 0);
|
||||
return r ? r : Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,8 +221,8 @@ export interface ICodeEditorViewState {
|
||||
* (Serializable) View state for the diff editor.
|
||||
*/
|
||||
export interface IDiffEditorViewState {
|
||||
original: ICodeEditorViewState;
|
||||
modified: ICodeEditorViewState;
|
||||
original: ICodeEditorViewState | null;
|
||||
modified: ICodeEditorViewState | null;
|
||||
}
|
||||
/**
|
||||
* An editor view state.
|
||||
|
||||
@@ -732,6 +732,12 @@ export interface ITextModel {
|
||||
*/
|
||||
findPreviousMatch(searchString: string, searchStart: IPosition, isRegex: boolean, matchCase: boolean, wordSeparators: string | null, captureMatches: boolean): FindMatch | null;
|
||||
|
||||
/**
|
||||
* Flush all tokenization state.
|
||||
* @internal
|
||||
*/
|
||||
flushTokens(): void;
|
||||
|
||||
/**
|
||||
* Force tokenization information for `lineNumber` to be accurate.
|
||||
* @internal
|
||||
|
||||
@@ -145,7 +145,7 @@ export class EditStack {
|
||||
this.pushStackElement();
|
||||
}
|
||||
|
||||
public pushEditOperation(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer): Selection[] | null {
|
||||
public pushEditOperation(beforeCursorState: Selection[], editOperations: IIdentifiedSingleEditOperation[], cursorStateComputer: ICursorStateComputer | null): Selection[] | null {
|
||||
// No support for parallel universes :(
|
||||
this.future = [];
|
||||
|
||||
@@ -174,7 +174,7 @@ export class EditStack {
|
||||
return stackElement!.afterCursorState;
|
||||
}
|
||||
|
||||
private static _computeCursorState(cursorStateComputer: ICursorStateComputer, inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] | null {
|
||||
private static _computeCursorState(cursorStateComputer: ICursorStateComputer | null, inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] | null {
|
||||
try {
|
||||
return cursorStateComputer ? cursorStateComputer(inverseEditOperations) : null;
|
||||
} catch (e) {
|
||||
|
||||
@@ -189,6 +189,12 @@ export function guessIndentation(source: ITextBuffer, defaultTabSize: number, de
|
||||
}
|
||||
});
|
||||
|
||||
// Let a tabSize of 2 win even if it is not the maximum
|
||||
// (only in case 4 was guessed)
|
||||
if (tabSize === 4 && spacesDiffCount[4] > 0 && spacesDiffCount[2] > 0 && spacesDiffCount[2] >= spacesDiffCount[4] / 2) {
|
||||
tabSize = 2;
|
||||
}
|
||||
|
||||
|
||||
// console.log('--------------------------');
|
||||
// console.log('linesIndentedWithTabsCount: ' + linesIndentedWithTabsCount + ', linesIndentedWithSpacesCount: ' + linesIndentedWithSpacesCount);
|
||||
|
||||
@@ -464,11 +464,9 @@ export function nodeAcceptEdit(node: IntervalNode, start: number, end: number, t
|
||||
const deltaColumn = (insertingCnt - deletingCnt);
|
||||
if (!startDone) {
|
||||
node.start = Math.max(0, nodeStart + deltaColumn);
|
||||
startDone = true;
|
||||
}
|
||||
if (!endDone) {
|
||||
node.end = Math.max(0, nodeEnd + deltaColumn);
|
||||
endDone = true;
|
||||
}
|
||||
|
||||
if (node.start > node.end) {
|
||||
|
||||
@@ -60,8 +60,7 @@ export class MirrorTextModel {
|
||||
|
||||
// Update my lines
|
||||
const changes = e.changes;
|
||||
for (let i = 0, len = changes.length; i < len; i++) {
|
||||
const change = changes[i];
|
||||
for (const change of changes) {
|
||||
this._acceptDeleteRange(change.range);
|
||||
this._acceptInsertText(new Position(change.range.startLineNumber, change.range.startColumn), change.text);
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ class PieceTreeSearchCache {
|
||||
|
||||
public valdiate(offset: number) {
|
||||
let hasInvalidVal = false;
|
||||
let tmp: (CacheEntry | null)[] = this._cache;
|
||||
let tmp: Array<CacheEntry | null> = this._cache;
|
||||
for (let i = 0; i < tmp.length; i++) {
|
||||
let nodePos = tmp[i]!;
|
||||
if (nodePos.node.parent === null || nodePos.nodeStartOffset >= offset) {
|
||||
@@ -254,8 +254,7 @@ class PieceTreeSearchCache {
|
||||
|
||||
if (hasInvalidVal) {
|
||||
let newArr: CacheEntry[] = [];
|
||||
for (let i = 0; i < tmp.length; i++) {
|
||||
const entry = tmp[i];
|
||||
for (const entry of tmp) {
|
||||
if (entry !== null) {
|
||||
newArr.push(entry);
|
||||
}
|
||||
@@ -1042,7 +1041,7 @@ export class PieceTreeBase {
|
||||
while (text.length > AverageBufferSize) {
|
||||
const lastChar = text.charCodeAt(AverageBufferSize - 1);
|
||||
let splitText;
|
||||
if (lastChar === CharCode.CarriageReturn || (lastChar >= 0xd800 && lastChar <= 0xdbff)) {
|
||||
if (lastChar === CharCode.CarriageReturn || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {
|
||||
// last character is \r or a high surrogate => keep it back
|
||||
splitText = text.substring(0, AverageBufferSize - 1);
|
||||
text = text.substring(AverageBufferSize - 1);
|
||||
|
||||
@@ -103,7 +103,7 @@ export class PieceTreeTextBufferBuilder implements ITextBufferBuilder {
|
||||
}
|
||||
|
||||
const lastChar = chunk.charCodeAt(chunk.length - 1);
|
||||
if (lastChar === CharCode.CarriageReturn || (lastChar >= 0xd800 && lastChar <= 0xdbff)) {
|
||||
if (lastChar === CharCode.CarriageReturn || (lastChar >= 0xD800 && lastChar <= 0xDBFF)) {
|
||||
// last character is \r or a high surrogate => keep it back
|
||||
this._acceptChunk1(chunk.substr(0, chunk.length - 1), false);
|
||||
this._hasPreviousChar = true;
|
||||
|
||||
@@ -315,6 +315,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
this._resetTokenizationState();
|
||||
this.emitModelTokensChangedEvent({
|
||||
tokenizationSupportChanged: true,
|
||||
ranges: [{
|
||||
fromLineNumber: 1,
|
||||
toLineNumber: this.getLineCount()
|
||||
@@ -1166,7 +1167,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
public pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] | null {
|
||||
public pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer | null): Selection[] | null {
|
||||
try {
|
||||
this._onDidChangeDecorations.beginDeferredEmit();
|
||||
this._eventEmitter.beginDeferredEmit();
|
||||
@@ -1177,7 +1178,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
private _pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer): Selection[] | null {
|
||||
private _pushEditOperations(beforeCursorState: Selection[], editOperations: model.IIdentifiedSingleEditOperation[], cursorStateComputer: model.ICursorStateComputer | null): Selection[] | null {
|
||||
if (this._options.trimAutoWhitespace && this._trimAutoWhitespaceLines) {
|
||||
// Go through each saved line number and insert a trim whitespace edit
|
||||
// if it is safe to do so (no conflicts with other edits).
|
||||
@@ -1760,42 +1761,41 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
public tokenizeViewport(startLineNumber: number, endLineNumber: number): void {
|
||||
if (!this._tokens.tokenizationSupport) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
// we tokenize `this._tokens.inValidLineStartIndex` lines in around 20ms so it's a good baseline.
|
||||
const contextBefore = Math.floor(this._tokens.inValidLineStartIndex * 0.3);
|
||||
startLineNumber = Math.max(1, startLineNumber - contextBefore);
|
||||
startLineNumber = Math.max(1, startLineNumber);
|
||||
endLineNumber = Math.min(this.getLineCount(), endLineNumber);
|
||||
|
||||
if (endLineNumber <= this._tokens.inValidLineStartIndex) {
|
||||
// nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
if (startLineNumber <= this._tokens.inValidLineStartIndex) {
|
||||
// tokenization has reached the viewport start...
|
||||
this.forceTokenization(endLineNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
const eventBuilder = new ModelTokensChangedEventBuilder();
|
||||
let nonWhitespaceColumn = this.getLineFirstNonWhitespaceColumn(startLineNumber);
|
||||
let fakeLines: string[] = [];
|
||||
let i = startLineNumber - 1;
|
||||
let initialState: IState | null = null;
|
||||
if (nonWhitespaceColumn > 0) {
|
||||
while (nonWhitespaceColumn > 0 && i >= 1) {
|
||||
let newNonWhitespaceIndex = this.getLineFirstNonWhitespaceColumn(i);
|
||||
for (let i = startLineNumber - 1; nonWhitespaceColumn > 0 && i >= 1; i--) {
|
||||
let newNonWhitespaceIndex = this.getLineFirstNonWhitespaceColumn(i);
|
||||
|
||||
if (newNonWhitespaceIndex === 0) {
|
||||
i--;
|
||||
continue;
|
||||
if (newNonWhitespaceIndex === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newNonWhitespaceIndex < nonWhitespaceColumn) {
|
||||
initialState = this._tokens._getState(i - 1);
|
||||
if (initialState) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (newNonWhitespaceIndex < nonWhitespaceColumn) {
|
||||
initialState = this._tokens._getState(i - 1);
|
||||
if (initialState) {
|
||||
break;
|
||||
}
|
||||
fakeLines.push(this.getLineContent(i));
|
||||
nonWhitespaceColumn = newNonWhitespaceIndex;
|
||||
}
|
||||
|
||||
i--;
|
||||
fakeLines.push(this.getLineContent(i));
|
||||
nonWhitespaceColumn = newNonWhitespaceIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1813,19 +1813,16 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
const contextAfter = Math.floor(this._tokens.inValidLineStartIndex * 0.4);
|
||||
endLineNumber = Math.min(this.getLineCount(), endLineNumber + contextAfter);
|
||||
const eventBuilder = new ModelTokensChangedEventBuilder();
|
||||
for (let i = startLineNumber; i <= endLineNumber; i++) {
|
||||
let text = this.getLineContent(i);
|
||||
let r = this._tokens._tokenizeText(this._buffer, text, state);
|
||||
if (r) {
|
||||
this._tokens._setTokens(this._tokens.languageIdentifier.id, i - 1, text.length, r.tokens);
|
||||
/*
|
||||
* we think it's valid and give it a state but we don't update `_invalidLineStartIndex` then the top-to-bottom tokenization
|
||||
* goes through the viewport, it can skip them if they already have correct tokens and state, and the lines after the viewport
|
||||
* can still be tokenized.
|
||||
*/
|
||||
this._tokens._setIsInvalid(i - 1, false);
|
||||
|
||||
// We cannot trust these states/tokens to be valid!
|
||||
// (see https://github.com/Microsoft/vscode/issues/67607)
|
||||
this._tokens._setIsInvalid(i - 1, true);
|
||||
this._tokens._setState(i - 1, state);
|
||||
state = r.endState.clone();
|
||||
eventBuilder.registerChangedTokens(i);
|
||||
@@ -1840,6 +1837,17 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
}
|
||||
|
||||
public flushTokens(): void {
|
||||
this._resetTokenizationState();
|
||||
this.emitModelTokensChangedEvent({
|
||||
tokenizationSupportChanged: false,
|
||||
ranges: [{
|
||||
fromLineNumber: 1,
|
||||
toLineNumber: this.getLineCount()
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
public forceTokenization(lineNumber: number): void {
|
||||
if (lineNumber < 1 || lineNumber > this.getLineCount()) {
|
||||
throw new Error('Illegal value for lineNumber');
|
||||
@@ -1915,6 +1923,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
this._resetTokenizationState();
|
||||
|
||||
this.emitModelTokensChangedEvent({
|
||||
tokenizationSupportChanged: true,
|
||||
ranges: [{
|
||||
fromLineNumber: 1,
|
||||
toLineNumber: this.getLineCount()
|
||||
|
||||
@@ -82,6 +82,7 @@ export interface IModelDecorationsChangedEvent {
|
||||
* An event describing that some ranges of lines have been tokenized (their tokens have changed).
|
||||
*/
|
||||
export interface IModelTokensChangedEvent {
|
||||
readonly tokenizationSupportChanged: boolean;
|
||||
readonly ranges: {
|
||||
/**
|
||||
* The start of the range (inclusive)
|
||||
|
||||
@@ -154,7 +154,7 @@ class ModelLineTokens {
|
||||
|
||||
let fromTokenIndex = LineTokens.findIndexInTokensArray(tokens, chIndex);
|
||||
if (fromTokenIndex > 0) {
|
||||
const fromTokenStartOffset = (fromTokenIndex > 0 ? tokens[(fromTokenIndex - 1) << 1] : 0);
|
||||
const fromTokenStartOffset = tokens[(fromTokenIndex - 1) << 1];
|
||||
if (fromTokenStartOffset === chIndex) {
|
||||
fromTokenIndex--;
|
||||
}
|
||||
@@ -500,6 +500,7 @@ export class ModelTokensChangedEventBuilder {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
tokenizationSupportChanged: false,
|
||||
ranges: this._ranges
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ export const USUAL_WORD_SEPARATORS = '`~!#$%^&*()-=+[{]}\\|;:\'",.<>/?';
|
||||
*/
|
||||
function createWordRegExp(allowInWords: string = ''): RegExp {
|
||||
let source = '(-?\\d*\\.\\d\\w*)|([^';
|
||||
for (let i = 0; i < USUAL_WORD_SEPARATORS.length; i++) {
|
||||
if (allowInWords.indexOf(USUAL_WORD_SEPARATORS[i]) >= 0) {
|
||||
for (const sep of USUAL_WORD_SEPARATORS) {
|
||||
if (allowInWords.indexOf(sep) >= 0) {
|
||||
continue;
|
||||
}
|
||||
source += '\\' + USUAL_WORD_SEPARATORS[i];
|
||||
source += '\\' + sep;
|
||||
}
|
||||
source += '\\s]+)';
|
||||
return new RegExp(source, 'g');
|
||||
@@ -42,6 +42,9 @@ export function ensureValidWordDefinition(wordDefinition?: RegExp | null): RegEx
|
||||
if (wordDefinition.multiline) {
|
||||
flags += 'm';
|
||||
}
|
||||
if ((wordDefinition as any).unicode) {
|
||||
flags += 'u';
|
||||
}
|
||||
result = new RegExp(wordDefinition.source, flags);
|
||||
} else {
|
||||
result = wordDefinition;
|
||||
@@ -58,10 +61,6 @@ function getWordAtPosFast(column: number, wordDefinition: RegExp, text: string,
|
||||
|
||||
let pos = column - 1 - textOffset;
|
||||
let start = text.lastIndexOf(' ', pos - 1) + 1;
|
||||
let end = text.indexOf(' ', pos);
|
||||
if (end === -1) {
|
||||
end = text.length;
|
||||
}
|
||||
|
||||
wordDefinition.lastIndex = start;
|
||||
let match: RegExpMatchArray | null;
|
||||
|
||||
@@ -433,7 +433,7 @@ export interface CompletionItem {
|
||||
* *Note:* The range must be a [single line](#Range.isSingleLine) and it must
|
||||
* [contain](#Range.contains) the position at which completion has been [requested](#CompletionItemProvider.provideCompletionItems).
|
||||
*/
|
||||
range?: IRange;
|
||||
range: IRange;
|
||||
/**
|
||||
* An optional set of characters that when pressed while this completion is active will accept it first and
|
||||
* then type that character. *Note* that all commit characters should have `length=1` and that superfluous
|
||||
@@ -450,13 +450,6 @@ export interface CompletionItem {
|
||||
* A command that should be run upon acceptance of this item.
|
||||
*/
|
||||
command?: Command;
|
||||
|
||||
/**@internal*/
|
||||
_labelLow?: string;
|
||||
/**@internal*/
|
||||
_sortTextLow?: string;
|
||||
/**@internal*/
|
||||
_filterTextLow?: string;
|
||||
}
|
||||
|
||||
export interface CompletionList {
|
||||
@@ -523,6 +516,7 @@ export interface CodeAction {
|
||||
edit?: WorkspaceEdit;
|
||||
diagnostics?: IMarkerData[];
|
||||
kind?: string;
|
||||
isPreferred?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -625,6 +619,7 @@ export interface SignatureHelpContext {
|
||||
readonly triggerKind: SignatureHelpTriggerKind;
|
||||
readonly triggerCharacter?: string;
|
||||
readonly isRetrigger: boolean;
|
||||
readonly activeSignatureHelp?: SignatureHelp;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -721,20 +716,42 @@ export interface Location {
|
||||
*/
|
||||
range: IRange;
|
||||
}
|
||||
/**
|
||||
* The definition of a symbol represented as one or many [locations](#Location).
|
||||
* For most programming languages there is only one location at which a symbol is
|
||||
* defined.
|
||||
*/
|
||||
export type Definition = Location | Location[];
|
||||
|
||||
export interface DefinitionLink {
|
||||
origin?: IRange;
|
||||
export interface LocationLink {
|
||||
/**
|
||||
* A range to select where this link originates from.
|
||||
*/
|
||||
originSelectionRange?: IRange;
|
||||
|
||||
/**
|
||||
* The target uri this link points to.
|
||||
*/
|
||||
uri: URI;
|
||||
|
||||
/**
|
||||
* The full range this link points to.
|
||||
*/
|
||||
range: IRange;
|
||||
selectionRange?: IRange;
|
||||
|
||||
/**
|
||||
* A range to select this link points to. Must be contained
|
||||
* in `LocationLink.range`.
|
||||
*/
|
||||
targetSelectionRange?: IRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function isLocationLink(thing: any): thing is LocationLink {
|
||||
return thing
|
||||
&& URI.isUri((thing as LocationLink).uri)
|
||||
&& Range.isIRange((thing as LocationLink).range)
|
||||
&& (Range.isIRange((thing as LocationLink).originSelectionRange) || Range.isIRange((thing as LocationLink).targetSelectionRange));
|
||||
}
|
||||
|
||||
export type Definition = Location | Location[] | LocationLink[];
|
||||
|
||||
/**
|
||||
* The definition provider interface defines the contract between extensions and
|
||||
* the [go to definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition)
|
||||
@@ -744,7 +761,7 @@ export interface DefinitionProvider {
|
||||
/**
|
||||
* Provide the definition of the symbol at the given position and document.
|
||||
*/
|
||||
provideDefinition(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<Definition | DefinitionLink[]>;
|
||||
provideDefinition(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<Definition | LocationLink[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -756,7 +773,7 @@ export interface DeclarationProvider {
|
||||
/**
|
||||
* Provide the declaration of the symbol at the given position and document.
|
||||
*/
|
||||
provideDeclaration(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<Definition | DefinitionLink[]>;
|
||||
provideDeclaration(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<Definition | LocationLink[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -767,7 +784,7 @@ export interface ImplementationProvider {
|
||||
/**
|
||||
* Provide the implementation of the symbol at the given position and document.
|
||||
*/
|
||||
provideImplementation(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<Definition | DefinitionLink[]>;
|
||||
provideImplementation(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<Definition | LocationLink[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -778,7 +795,7 @@ export interface TypeDefinitionProvider {
|
||||
/**
|
||||
* Provide the type definition of the symbol at the given position and document.
|
||||
*/
|
||||
provideTypeDefinition(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<Definition | DefinitionLink[]>;
|
||||
provideTypeDefinition(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<Definition | LocationLink[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -896,6 +913,9 @@ export interface FormattingOptions {
|
||||
* the formatting-feature.
|
||||
*/
|
||||
export interface DocumentFormattingEditProvider {
|
||||
|
||||
displayName?: string;
|
||||
|
||||
/**
|
||||
* Provide formatting edits for a whole document.
|
||||
*/
|
||||
@@ -906,6 +926,9 @@ export interface DocumentFormattingEditProvider {
|
||||
* the formatting-feature.
|
||||
*/
|
||||
export interface DocumentRangeFormattingEditProvider {
|
||||
|
||||
displayName?: string;
|
||||
|
||||
/**
|
||||
* Provide formatting edits for a range in a document.
|
||||
*
|
||||
@@ -1032,11 +1055,16 @@ export interface DocumentColorProvider {
|
||||
provideColorPresentations(model: model.ITextModel, colorInfo: IColorInformation, token: CancellationToken): ProviderResult<IColorPresentation[]>;
|
||||
}
|
||||
|
||||
export interface SelectionRange {
|
||||
kind: string;
|
||||
range: IRange;
|
||||
}
|
||||
|
||||
export interface SelectionRangeProvider {
|
||||
/**
|
||||
* Provide ranges that should be selected from the given position.
|
||||
*/
|
||||
provideSelectionRanges(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<IRange[]>;
|
||||
provideSelectionRanges(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<SelectionRange[]>;
|
||||
}
|
||||
|
||||
export interface FoldingContext {
|
||||
@@ -1122,7 +1150,7 @@ export interface ResourceTextEdit {
|
||||
}
|
||||
|
||||
export interface WorkspaceEdit {
|
||||
edits?: Array<ResourceTextEdit | ResourceFileEdit>;
|
||||
edits: Array<ResourceTextEdit | ResourceFileEdit>;
|
||||
}
|
||||
|
||||
export interface Rejection {
|
||||
@@ -1150,6 +1178,7 @@ export interface Command {
|
||||
* @internal
|
||||
*/
|
||||
export interface CommentInfo {
|
||||
extensionId: string;
|
||||
threads: CommentThread[];
|
||||
commentingRanges?: IRange[];
|
||||
reply?: Command;
|
||||
@@ -1183,6 +1212,7 @@ export enum CommentThreadCollapsibleState {
|
||||
* @internal
|
||||
*/
|
||||
export interface CommentThread {
|
||||
extensionId: string;
|
||||
threadId: string;
|
||||
resource: string;
|
||||
range: IRange;
|
||||
@@ -1199,6 +1229,14 @@ export interface NewCommentAction {
|
||||
actions: Command[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface CommentReaction {
|
||||
readonly label?: string;
|
||||
readonly hasReacted?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -1211,6 +1249,7 @@ export interface Comment {
|
||||
readonly canDelete?: boolean;
|
||||
readonly command?: Command;
|
||||
readonly isDraft?: boolean;
|
||||
readonly commentReactions?: CommentReaction[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1247,13 +1286,18 @@ export interface DocumentCommentProvider {
|
||||
replyToCommentThread(resource: URI, range: Range, thread: CommentThread, text: string, token: CancellationToken): Promise<CommentThread>;
|
||||
editComment(resource: URI, comment: Comment, text: string, token: CancellationToken): Promise<void>;
|
||||
deleteComment(resource: URI, comment: Comment, token: CancellationToken): Promise<void>;
|
||||
startDraft?(token: CancellationToken): Promise<void>;
|
||||
deleteDraft?(token: CancellationToken): Promise<void>;
|
||||
finishDraft?(token: CancellationToken): Promise<void>;
|
||||
startDraft?(resource: URI, token: CancellationToken): Promise<void>;
|
||||
deleteDraft?(resource: URI, token: CancellationToken): Promise<void>;
|
||||
finishDraft?(resource: URI, token: CancellationToken): Promise<void>;
|
||||
|
||||
startDraftLabel?: string;
|
||||
deleteDraftLabel?: string;
|
||||
finishDraftLabel?: string;
|
||||
|
||||
addReaction?(resource: URI, comment: Comment, reaction: CommentReaction, token: CancellationToken): Promise<void>;
|
||||
deleteReaction?(resource: URI, comment: Comment, reaction: CommentReaction, token: CancellationToken): Promise<void>;
|
||||
reactionGroup?: CommentReaction[];
|
||||
|
||||
onDidChangeCommentThreads(): Event<CommentThreadChangedEvent>;
|
||||
}
|
||||
|
||||
@@ -1412,7 +1456,7 @@ export interface ITokenizationRegistry {
|
||||
/**
|
||||
* Register a promise for a tokenization support.
|
||||
*/
|
||||
registerPromise(language: string, promise: Thenable<ITokenizationSupport>): Thenable<IDisposable>;
|
||||
registerPromise(language: string, promise: Thenable<ITokenizationSupport>): IDisposable;
|
||||
|
||||
/**
|
||||
* Get the tokenization support for a language.
|
||||
|
||||
@@ -177,7 +177,7 @@ export class LanguageConfigurationRegistryImpl {
|
||||
|
||||
private _entries: RichEditSupport[];
|
||||
|
||||
private readonly _onDidChange: Emitter<LanguageConfigurationChangeEvent> = new Emitter<LanguageConfigurationChangeEvent>();
|
||||
private readonly _onDidChange = new Emitter<LanguageConfigurationChangeEvent>();
|
||||
public readonly onDidChange: Event<LanguageConfigurationChangeEvent> = this._onDidChange.event;
|
||||
|
||||
constructor() {
|
||||
@@ -332,7 +332,7 @@ export class LanguageConfigurationRegistryImpl {
|
||||
private getPrecedingValidLine(model: IVirtualModel, lineNumber: number, indentRulesSupport: IndentRulesSupport) {
|
||||
let languageID = model.getLanguageIdAtPosition(lineNumber, 0);
|
||||
if (lineNumber > 1) {
|
||||
let lastLineNumber = lineNumber - 1;
|
||||
let lastLineNumber: number;
|
||||
let resultLineNumber = -1;
|
||||
|
||||
for (lastLineNumber = lineNumber - 1; lastLineNumber >= 1; lastLineNumber--) {
|
||||
|
||||
@@ -30,7 +30,7 @@ export class LanguageFeatureRegistry<T> {
|
||||
|
||||
private _clock: number = 0;
|
||||
private _entries: Entry<T>[] = [];
|
||||
private readonly _onDidChange: Emitter<number> = new Emitter<number>();
|
||||
private readonly _onDidChange = new Emitter<number>();
|
||||
|
||||
constructor() {
|
||||
}
|
||||
@@ -119,8 +119,7 @@ export class LanguageFeatureRegistry<T> {
|
||||
|
||||
this._updateScores(model);
|
||||
|
||||
for (let from = 0; from < this._entries.length; from++) {
|
||||
let entry = this._entries[from];
|
||||
for (const entry of this._entries) {
|
||||
if (entry._score > 0) {
|
||||
callback(entry);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface LanguageFilter {
|
||||
exclusive?: boolean;
|
||||
}
|
||||
|
||||
export type LanguageSelector = string | LanguageFilter | (string | LanguageFilter)[];
|
||||
export type LanguageSelector = string | LanguageFilter | Array<string | LanguageFilter>;
|
||||
|
||||
export function score(selector: LanguageSelector, candidateUri: URI, candidateLanguage: string, candidateIsSynchronized: boolean): number {
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ export class LinkComputer {
|
||||
* document. *Note* that this operation is computational
|
||||
* expensive and should not run in the UI thread.
|
||||
*/
|
||||
export function computeLinks(model: ILinkComputerTarget): ILink[] {
|
||||
export function computeLinks(model: ILinkComputerTarget | null): ILink[] {
|
||||
if (!model || typeof model.getLineCount !== 'function' || typeof model.getLineContent !== 'function') {
|
||||
// Unknown caller!
|
||||
return [];
|
||||
|
||||
@@ -18,26 +18,28 @@ export const Extensions = {
|
||||
export class EditorModesRegistry {
|
||||
|
||||
private _languages: ILanguageExtensionPoint[];
|
||||
private _dynamicLanguages: ILanguageExtensionPoint[];
|
||||
|
||||
private readonly _onDidAddLanguages: Emitter<ILanguageExtensionPoint[]> = new Emitter<ILanguageExtensionPoint[]>();
|
||||
public readonly onDidAddLanguages: Event<ILanguageExtensionPoint[]> = this._onDidAddLanguages.event;
|
||||
private readonly _onDidChangeLanguages = new Emitter<void>();
|
||||
public readonly onDidChangeLanguages: Event<void> = this._onDidChangeLanguages.event;
|
||||
|
||||
constructor() {
|
||||
this._languages = [];
|
||||
this._dynamicLanguages = [];
|
||||
}
|
||||
|
||||
// --- languages
|
||||
|
||||
public registerLanguage(def: ILanguageExtensionPoint): void {
|
||||
this._languages.push(def);
|
||||
this._onDidAddLanguages.fire([def]);
|
||||
this._onDidChangeLanguages.fire(undefined);
|
||||
}
|
||||
public registerLanguages(def: ILanguageExtensionPoint[]): void {
|
||||
this._languages = this._languages.concat(def);
|
||||
this._onDidAddLanguages.fire(def);
|
||||
public setDynamicLanguages(def: ILanguageExtensionPoint[]): void {
|
||||
this._dynamicLanguages = def;
|
||||
this._onDidChangeLanguages.fire(undefined);
|
||||
}
|
||||
public getLanguages(): ILanguageExtensionPoint[] {
|
||||
return this._languages.slice(0);
|
||||
return (<ILanguageExtensionPoint[]>[]).concat(this._languages).concat(this._dynamicLanguages);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,9 +46,7 @@ export class CharacterPairSupport {
|
||||
let tokenIndex = context.findTokenIndexAtOffset(column - 2);
|
||||
let standardTokenType = context.getStandardTokenType(tokenIndex);
|
||||
|
||||
for (let i = 0; i < this._autoClosingPairs.length; ++i) {
|
||||
let autoClosingPair = this._autoClosingPairs[i];
|
||||
|
||||
for (const autoClosingPair of this._autoClosingPairs) {
|
||||
if (autoClosingPair.open === character) {
|
||||
return autoClosingPair.isOK(standardTokenType);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export class BracketElectricCharacterSupport {
|
||||
private readonly _richEditBrackets: RichEditBrackets | null;
|
||||
private readonly _complexAutoClosePairs: StandardAutoClosingPairConditional[];
|
||||
|
||||
constructor(richEditBrackets: RichEditBrackets | null, autoClosePairs: IAutoClosingPairConditional[], contribution: IBracketElectricCharacterContribution | undefined) {
|
||||
constructor(richEditBrackets: RichEditBrackets | null, autoClosePairs: IAutoClosingPairConditional[], contribution: IBracketElectricCharacterContribution | null | undefined) {
|
||||
contribution = contribution || {};
|
||||
this._richEditBrackets = richEditBrackets;
|
||||
this._complexAutoClosePairs = autoClosePairs.filter(pair => pair.open.length > 1 && !!pair.close).map(el => new StandardAutoClosingPairConditional(el));
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ColorId, ITokenizationRegistry, ITokenizationSupport, ITokenizationSupportChangedEvent } from 'vs/editor/common/modes';
|
||||
|
||||
export class TokenizationRegistryImpl implements ITokenizationRegistry {
|
||||
|
||||
private _map: { [language: string]: ITokenizationSupport };
|
||||
private _promises: { [language: string]: Thenable<IDisposable> };
|
||||
private _promises: { [language: string]: Thenable<void> };
|
||||
|
||||
private readonly _onDidChange: Emitter<ITokenizationSupportChangedEvent> = new Emitter<ITokenizationSupportChangedEvent>();
|
||||
private readonly _onDidChange = new Emitter<ITokenizationSupportChangedEvent>();
|
||||
public readonly onDidChange: Event<ITokenizationSupportChangedEvent> = this._onDidChange.event;
|
||||
|
||||
private _colorMap: Color[] | null;
|
||||
@@ -43,16 +43,25 @@ export class TokenizationRegistryImpl implements ITokenizationRegistry {
|
||||
});
|
||||
}
|
||||
|
||||
public registerPromise(language: string, supportPromise: Thenable<ITokenizationSupport | null>): Thenable<IDisposable> {
|
||||
const promise = this._promises[language] = supportPromise.then(support => {
|
||||
public registerPromise(language: string, supportPromise: Thenable<ITokenizationSupport | null>): IDisposable {
|
||||
|
||||
let registration: IDisposable | null = null;
|
||||
let isDisposed: boolean = false;
|
||||
|
||||
this._promises[language] = supportPromise.then(support => {
|
||||
delete this._promises[language];
|
||||
if (support) {
|
||||
return this.register(language, support);
|
||||
} else {
|
||||
return Disposable.None;
|
||||
if (isDisposed || !support) {
|
||||
return;
|
||||
}
|
||||
registration = this.register(language, support);
|
||||
});
|
||||
|
||||
return toDisposable(() => {
|
||||
isDisposed = true;
|
||||
if (registration) {
|
||||
registration.dispose();
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
public getPromise(language: string): Thenable<ITokenizationSupport> | null {
|
||||
|
||||
@@ -26,7 +26,7 @@ export interface IEditorWorkerService {
|
||||
canComputeDirtyDiff(original: URI, modified: URI): boolean;
|
||||
computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise<IChange[] | null>;
|
||||
|
||||
computeMoreMinimalEdits(resource: URI, edits: TextEdit[]): Promise<TextEdit[]>;
|
||||
computeMoreMinimalEdits(resource: URI, edits: TextEdit[] | null | undefined): Promise<TextEdit[] | null | undefined>;
|
||||
|
||||
canComputeWordRanges(resource: URI): boolean;
|
||||
computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null>;
|
||||
|
||||
@@ -19,6 +19,7 @@ import { EditorSimpleWorkerImpl } from 'vs/editor/common/services/editorSimpleWo
|
||||
import { IDiffComputationResult, IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { regExpFlags } from 'vs/base/common/strings';
|
||||
|
||||
/**
|
||||
* Stop syncing a model to the worker if it was not needed for 1 min.
|
||||
@@ -87,7 +88,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker
|
||||
return this._workerManager.withWorker().then(client => client.computeDirtyDiff(original, modified, ignoreTrimWhitespace));
|
||||
}
|
||||
|
||||
public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[]): Promise<modes.TextEdit[]> {
|
||||
public computeMoreMinimalEdits(resource: URI, edits: modes.TextEdit[] | null | undefined): Promise<modes.TextEdit[] | null | undefined> {
|
||||
if (!Array.isArray(edits) || edits.length === 0) {
|
||||
return Promise.resolve(edits);
|
||||
} else {
|
||||
@@ -237,8 +238,7 @@ class EditorModelManager extends Disposable {
|
||||
}
|
||||
|
||||
public esureSyncedResources(resources: URI[]): void {
|
||||
for (let i = 0; i < resources.length; i++) {
|
||||
let resource = resources[i];
|
||||
for (const resource of resources) {
|
||||
let resourceStr = resource.toString();
|
||||
|
||||
if (!this._syncedModels[resourceStr]) {
|
||||
@@ -261,8 +261,8 @@ class EditorModelManager extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < toRemove.length; i++) {
|
||||
this._stopModelSync(toRemove[i]);
|
||||
for (const e of toRemove) {
|
||||
this._stopModelSync(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ export class EditorWorkerClient extends Disposable {
|
||||
}
|
||||
|
||||
protected _getProxy(): Promise<EditorSimpleWorkerImpl> {
|
||||
return this._getOrCreateWorker().getProxyObject().then(null, (err) => {
|
||||
return this._getOrCreateWorker().getProxyObject().then(undefined, (err) => {
|
||||
logOnceWebWorkerWarning(err);
|
||||
this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl(null));
|
||||
return this._getOrCreateWorker().getProxyObject();
|
||||
@@ -413,7 +413,7 @@ export class EditorWorkerClient extends Disposable {
|
||||
}
|
||||
let wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageIdentifier().id);
|
||||
let wordDef = wordDefRegExp.source;
|
||||
let wordDefFlags = (wordDefRegExp.global ? 'g' : '') + (wordDefRegExp.ignoreCase ? 'i' : '') + (wordDefRegExp.multiline ? 'm' : '');
|
||||
let wordDefFlags = regExpFlags(wordDefRegExp);
|
||||
return proxy.textualSuggest(resource.toString(), position, wordDef, wordDefFlags);
|
||||
});
|
||||
}
|
||||
@@ -426,7 +426,7 @@ export class EditorWorkerClient extends Disposable {
|
||||
}
|
||||
let wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageIdentifier().id);
|
||||
let wordDef = wordDefRegExp.source;
|
||||
let wordDefFlags = (wordDefRegExp.global ? 'g' : '') + (wordDefRegExp.ignoreCase ? 'i' : '') + (wordDefRegExp.multiline ? 'm' : '');
|
||||
let wordDefFlags = regExpFlags(wordDefRegExp);
|
||||
return proxy.computeWordRanges(resource.toString(), range, wordDef, wordDefFlags);
|
||||
});
|
||||
}
|
||||
@@ -439,7 +439,7 @@ export class EditorWorkerClient extends Disposable {
|
||||
}
|
||||
let wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageIdentifier().id);
|
||||
let wordDef = wordDefRegExp.source;
|
||||
let wordDefFlags = (wordDefRegExp.global ? 'g' : '') + (wordDefRegExp.ignoreCase ? 'i' : '') + (wordDefRegExp.multiline ? 'm' : '');
|
||||
let wordDefFlags = regExpFlags(wordDefRegExp);
|
||||
return proxy.navigateValueSet(resource.toString(), range, up, wordDef, wordDefFlags);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { FileKind } from 'vs/platform/files/common/files';
|
||||
|
||||
export function getIconClasses(modelService: IModelService, modeService: IModeService, resource: uri, fileKind?: FileKind): string[] {
|
||||
export function getIconClasses(modelService: IModelService, modeService: IModeService, resource: uri | undefined, fileKind?: FileKind): string[] {
|
||||
// we always set these base classes even if we do not have a path
|
||||
const classes = fileKind === FileKind.ROOT_FOLDER ? ['rootfolder-icon'] : fileKind === FileKind.FOLDER ? ['folder-icon'] : ['file-icon'];
|
||||
if (resource) {
|
||||
// Get the path and name of the resource. For data-URIs, we need to parse specially
|
||||
let name: string;
|
||||
let path: string;
|
||||
let name: string | undefined;
|
||||
let path: string | undefined;
|
||||
if (resource.scheme === Schemas.data) {
|
||||
const metadata = DataUri.parseMetaData(resource);
|
||||
name = metadata.get(DataUri.META_DATA_LABEL);
|
||||
@@ -44,7 +44,7 @@ export function getIconClasses(modelService: IModelService, modeService: IModeSe
|
||||
}
|
||||
// Configured Language
|
||||
let configuredLangId: string | null = getConfiguredLangId(modelService, resource);
|
||||
configuredLangId = configuredLangId || modeService.getModeIdByFilepathOrFirstLine(path);
|
||||
configuredLangId = configuredLangId || (path ? modeService.getModeIdByFilepathOrFirstLine(path) : null);
|
||||
if (configuredLangId) {
|
||||
classes.push(`${cssEscape(configuredLangId)}-lang-file-icon`);
|
||||
}
|
||||
|
||||
@@ -33,39 +33,51 @@ export class LanguagesRegistry extends Disposable {
|
||||
private readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
public readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||
|
||||
private _nextLanguageId: number;
|
||||
private _languages: { [id: string]: IResolvedLanguage; };
|
||||
private _languageIds: string[];
|
||||
private readonly _warnOnOverwrite: boolean;
|
||||
|
||||
private _nextLanguageId2: number;
|
||||
private _languageIdToLanguage: string[];
|
||||
private _languageToLanguageId: { [id: string]: number; };
|
||||
|
||||
private _languages: { [id: string]: IResolvedLanguage; };
|
||||
private _mimeTypesMap: { [mimeType: string]: LanguageIdentifier; };
|
||||
private _nameMap: { [name: string]: LanguageIdentifier; };
|
||||
private _lowercaseNameMap: { [name: string]: LanguageIdentifier; };
|
||||
|
||||
private _warnOnOverwrite: boolean;
|
||||
|
||||
constructor(useModesRegistry = true, warnOnOverwrite = false) {
|
||||
super();
|
||||
this._nextLanguageId = 1;
|
||||
|
||||
this._warnOnOverwrite = warnOnOverwrite;
|
||||
|
||||
this._nextLanguageId2 = 1;
|
||||
this._languageIdToLanguage = [];
|
||||
this._languageToLanguageId = Object.create(null);
|
||||
|
||||
this._languages = {};
|
||||
this._mimeTypesMap = {};
|
||||
this._nameMap = {};
|
||||
this._lowercaseNameMap = {};
|
||||
this._languageIds = [];
|
||||
this._warnOnOverwrite = warnOnOverwrite;
|
||||
|
||||
if (useModesRegistry) {
|
||||
this._registerLanguages(ModesRegistry.getLanguages());
|
||||
this._register(ModesRegistry.onDidAddLanguages((m) => this._registerLanguages(m)));
|
||||
this._initializeFromRegistry();
|
||||
this._register(ModesRegistry.onDidChangeLanguages((m) => this._initializeFromRegistry()));
|
||||
}
|
||||
}
|
||||
|
||||
_registerLanguages(desc: ILanguageExtensionPoint[]): void {
|
||||
if (desc.length === 0) {
|
||||
return;
|
||||
}
|
||||
private _initializeFromRegistry(): void {
|
||||
this._languages = {};
|
||||
this._mimeTypesMap = {};
|
||||
this._nameMap = {};
|
||||
this._lowercaseNameMap = {};
|
||||
|
||||
for (let i = 0; i < desc.length; i++) {
|
||||
this._registerLanguage(desc[i]);
|
||||
const desc = ModesRegistry.getLanguages();
|
||||
this._registerLanguages(desc);
|
||||
}
|
||||
|
||||
_registerLanguages(desc: ILanguageExtensionPoint[]): void {
|
||||
|
||||
for (const d of desc) {
|
||||
this._registerLanguage(d);
|
||||
}
|
||||
|
||||
// Rebuild fast path maps
|
||||
@@ -90,6 +102,18 @@ export class LanguagesRegistry extends Disposable {
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
|
||||
private _getLanguageId(language: string): number {
|
||||
if (this._languageToLanguageId[language]) {
|
||||
return this._languageToLanguageId[language];
|
||||
}
|
||||
|
||||
const languageId = this._nextLanguageId2++;
|
||||
this._languageIdToLanguage[languageId] = language;
|
||||
this._languageToLanguageId[language] = languageId;
|
||||
|
||||
return languageId;
|
||||
}
|
||||
|
||||
private _registerLanguage(lang: ILanguageExtensionPoint): void {
|
||||
const langId = lang.id;
|
||||
|
||||
@@ -97,7 +121,7 @@ export class LanguagesRegistry extends Disposable {
|
||||
if (hasOwnProperty.call(this._languages, langId)) {
|
||||
resolvedLanguage = this._languages[langId];
|
||||
} else {
|
||||
let languageId = this._nextLanguageId++;
|
||||
const languageId = this._getLanguageId(langId);
|
||||
resolvedLanguage = {
|
||||
identifier: new LanguageIdentifier(langId, languageId),
|
||||
name: null,
|
||||
@@ -107,7 +131,6 @@ export class LanguagesRegistry extends Disposable {
|
||||
filenames: [],
|
||||
configurationFiles: []
|
||||
};
|
||||
this._languageIds[languageId] = langId;
|
||||
this._languages[langId] = resolvedLanguage;
|
||||
}
|
||||
|
||||
@@ -170,7 +193,7 @@ export class LanguagesRegistry extends Disposable {
|
||||
|
||||
resolvedLanguage.aliases.push(langId);
|
||||
|
||||
let langAliases: (string | null)[] | null = null;
|
||||
let langAliases: Array<string | null> | null = null;
|
||||
if (typeof lang.aliases !== 'undefined' && Array.isArray(lang.aliases)) {
|
||||
if (lang.aliases.length === 0) {
|
||||
// signal that this language should not get a name
|
||||
@@ -181,8 +204,7 @@ export class LanguagesRegistry extends Disposable {
|
||||
}
|
||||
|
||||
if (langAliases !== null) {
|
||||
for (let i = 0; i < langAliases.length; i++) {
|
||||
const langAlias = langAliases[i];
|
||||
for (const langAlias of langAliases) {
|
||||
if (!langAlias || langAlias.length === 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -281,7 +303,7 @@ export class LanguagesRegistry extends Disposable {
|
||||
if (typeof _modeId === 'string') {
|
||||
modeId = _modeId;
|
||||
} else {
|
||||
modeId = this._languageIds[_modeId];
|
||||
modeId = this._languageIdToLanguage[_modeId];
|
||||
if (!modeId) {
|
||||
return null;
|
||||
}
|
||||
@@ -303,7 +325,7 @@ export class LanguagesRegistry extends Disposable {
|
||||
return [];
|
||||
}
|
||||
|
||||
public getModeIdsFromFilepathOrFirstLine(filepath: string, firstLine?: string): string[] {
|
||||
public getModeIdsFromFilepathOrFirstLine(filepath: string | null, firstLine?: string): string[] {
|
||||
if (!filepath && !firstLine) {
|
||||
return [];
|
||||
}
|
||||
|
||||
210
src/vs/editor/common/services/markerDecorationsServiceImpl.ts
Normal file
210
src/vs/editor/common/services/markerDecorationsServiceImpl.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IMarkerService, IMarker, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IModelDeltaDecoration, ITextModel, IModelDecorationOptions, TrackedRangeStickiness, OverviewRulerLane, IModelDecoration } from 'vs/editor/common/model';
|
||||
import { ClassName } from 'vs/editor/common/model/intervalTree';
|
||||
import { themeColorFromId, ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { overviewRulerWarning, overviewRulerInfo, overviewRulerError } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
import { IMarkerDecorationsService } from 'vs/editor/common/services/markersDecorationService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
function MODEL_ID(resource: URI): string {
|
||||
return resource.toString();
|
||||
}
|
||||
|
||||
class MarkerDecorations extends Disposable {
|
||||
|
||||
private readonly _markersData: Map<string, IMarker> = new Map<string, IMarker>();
|
||||
|
||||
constructor(
|
||||
readonly model: ITextModel
|
||||
) {
|
||||
super();
|
||||
this._register(toDisposable(() => {
|
||||
this.model.deltaDecorations(keys(this._markersData), []);
|
||||
this._markersData.clear();
|
||||
}));
|
||||
}
|
||||
|
||||
public update(markers: IMarker[], newDecorations: IModelDeltaDecoration[]): void {
|
||||
const ids = this.model.deltaDecorations(keys(this._markersData), newDecorations);
|
||||
for (let index = 0; index < ids.length; index++) {
|
||||
this._markersData.set(ids[index], markers[index]);
|
||||
}
|
||||
}
|
||||
|
||||
getMarker(decoration: IModelDecoration): IMarker | undefined {
|
||||
return this._markersData.get(decoration.id);
|
||||
}
|
||||
}
|
||||
|
||||
export class MarkerDecorationsService extends Disposable implements IMarkerDecorationsService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private readonly _markerDecorations: Map<string, MarkerDecorations> = new Map<string, MarkerDecorations>();
|
||||
|
||||
constructor(
|
||||
@IModelService modelService: IModelService,
|
||||
@IMarkerService private readonly _markerService: IMarkerService
|
||||
) {
|
||||
super();
|
||||
modelService.getModels().forEach(model => this._onModelAdded(model));
|
||||
this._register(modelService.onModelAdded(this._onModelAdded, this));
|
||||
this._register(modelService.onModelRemoved(this._onModelRemoved, this));
|
||||
this._register(this._markerService.onMarkerChanged(this._handleMarkerChange, this));
|
||||
}
|
||||
|
||||
getMarker(model: ITextModel, decoration: IModelDecoration): IMarker | null {
|
||||
const markerDecorations = this._markerDecorations.get(MODEL_ID(model.uri));
|
||||
return markerDecorations ? markerDecorations.getMarker(decoration) || null : null;
|
||||
}
|
||||
|
||||
private _handleMarkerChange(changedResources: URI[]): void {
|
||||
changedResources.forEach((resource) => {
|
||||
const markerDecorations = this._markerDecorations.get(MODEL_ID(resource));
|
||||
if (markerDecorations) {
|
||||
this.updateDecorations(markerDecorations);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _onModelAdded(model: ITextModel): void {
|
||||
const markerDecorations = new MarkerDecorations(model);
|
||||
this._markerDecorations.set(MODEL_ID(model.uri), markerDecorations);
|
||||
this.updateDecorations(markerDecorations);
|
||||
}
|
||||
|
||||
private _onModelRemoved(model: ITextModel): void {
|
||||
const markerDecorations = this._markerDecorations.get(MODEL_ID(model.uri));
|
||||
if (markerDecorations) {
|
||||
markerDecorations.dispose();
|
||||
this._markerDecorations.delete(MODEL_ID(model.uri));
|
||||
}
|
||||
|
||||
// clean up markers for internal, transient models
|
||||
if (model.uri.scheme === Schemas.inMemory
|
||||
|| model.uri.scheme === Schemas.internal
|
||||
|| model.uri.scheme === Schemas.vscode) {
|
||||
if (this._markerService) {
|
||||
this._markerService.read({ resource: model.uri }).map(marker => marker.owner).forEach(owner => this._markerService.remove(owner, [model.uri]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateDecorations(markerDecorations: MarkerDecorations): void {
|
||||
// Limit to the first 500 errors/warnings
|
||||
const markers = this._markerService.read({ resource: markerDecorations.model.uri, take: 500 });
|
||||
let newModelDecorations: IModelDeltaDecoration[] = markers.map((marker) => {
|
||||
return {
|
||||
range: this._createDecorationRange(markerDecorations.model, marker),
|
||||
options: this._createDecorationOption(marker)
|
||||
};
|
||||
});
|
||||
markerDecorations.update(markers, newModelDecorations);
|
||||
}
|
||||
|
||||
private _createDecorationRange(model: ITextModel, rawMarker: IMarker): Range {
|
||||
|
||||
let ret = Range.lift(rawMarker);
|
||||
|
||||
if (rawMarker.severity === MarkerSeverity.Hint) {
|
||||
if (!rawMarker.tags || rawMarker.tags.indexOf(MarkerTag.Unnecessary) === -1) {
|
||||
// * never render hints on multiple lines
|
||||
// * make enough space for three dots
|
||||
ret = ret.setEndPosition(ret.startLineNumber, ret.startColumn + 2);
|
||||
}
|
||||
}
|
||||
|
||||
ret = model.validateRange(ret);
|
||||
|
||||
if (ret.isEmpty()) {
|
||||
let word = model.getWordAtPosition(ret.getStartPosition());
|
||||
if (word) {
|
||||
ret = new Range(ret.startLineNumber, word.startColumn, ret.endLineNumber, word.endColumn);
|
||||
} else {
|
||||
let maxColumn = model.getLineLastNonWhitespaceColumn(ret.startLineNumber) ||
|
||||
model.getLineMaxColumn(ret.startLineNumber);
|
||||
|
||||
if (maxColumn === 1) {
|
||||
// empty line
|
||||
// console.warn('marker on empty line:', marker);
|
||||
} else if (ret.endColumn >= maxColumn) {
|
||||
// behind eol
|
||||
ret = new Range(ret.startLineNumber, maxColumn - 1, ret.endLineNumber, maxColumn);
|
||||
} else {
|
||||
// extend marker to width = 1
|
||||
ret = new Range(ret.startLineNumber, ret.startColumn, ret.endLineNumber, ret.endColumn + 1);
|
||||
}
|
||||
}
|
||||
} else if (rawMarker.endColumn === Number.MAX_VALUE && rawMarker.startColumn === 1 && ret.startLineNumber === ret.endLineNumber) {
|
||||
let minColumn = model.getLineFirstNonWhitespaceColumn(rawMarker.startLineNumber);
|
||||
if (minColumn < ret.endColumn) {
|
||||
ret = new Range(ret.startLineNumber, minColumn, ret.endLineNumber, ret.endColumn);
|
||||
rawMarker.startColumn = minColumn;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private _createDecorationOption(marker: IMarker): IModelDecorationOptions {
|
||||
|
||||
let className: string;
|
||||
let color: ThemeColor | undefined = undefined;
|
||||
let zIndex: number;
|
||||
let inlineClassName: string | undefined = undefined;
|
||||
|
||||
switch (marker.severity) {
|
||||
case MarkerSeverity.Hint:
|
||||
if (marker.tags && marker.tags.indexOf(MarkerTag.Unnecessary) >= 0) {
|
||||
className = ClassName.EditorUnnecessaryDecoration;
|
||||
} else {
|
||||
className = ClassName.EditorHintDecoration;
|
||||
}
|
||||
zIndex = 0;
|
||||
break;
|
||||
case MarkerSeverity.Warning:
|
||||
className = ClassName.EditorWarningDecoration;
|
||||
color = themeColorFromId(overviewRulerWarning);
|
||||
zIndex = 20;
|
||||
break;
|
||||
case MarkerSeverity.Info:
|
||||
className = ClassName.EditorInfoDecoration;
|
||||
color = themeColorFromId(overviewRulerInfo);
|
||||
zIndex = 10;
|
||||
break;
|
||||
case MarkerSeverity.Error:
|
||||
default:
|
||||
className = ClassName.EditorErrorDecoration;
|
||||
color = themeColorFromId(overviewRulerError);
|
||||
zIndex = 30;
|
||||
break;
|
||||
}
|
||||
|
||||
if (marker.tags) {
|
||||
if (marker.tags.indexOf(MarkerTag.Unnecessary) !== -1) {
|
||||
inlineClassName = ClassName.EditorUnnecessaryInlineDecoration;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
className,
|
||||
showIfCollapsed: true,
|
||||
overviewRuler: {
|
||||
color,
|
||||
position: OverviewRulerLane.Right
|
||||
},
|
||||
zIndex,
|
||||
inlineClassName,
|
||||
};
|
||||
}
|
||||
}
|
||||
16
src/vs/editor/common/services/markersDecorationService.ts
Normal file
16
src/vs/editor/common/services/markersDecorationService.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ITextModel, IModelDecoration } from 'vs/editor/common/model';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IMarker } from 'vs/platform/markers/common/markers';
|
||||
|
||||
export const IMarkerDecorationsService = createDecorator<IMarkerDecorationsService>('markerDecorationsService');
|
||||
|
||||
export interface IMarkerDecorationsService {
|
||||
_serviceBrand: any;
|
||||
|
||||
getMarker(model: ITextModel, decoration: IModelDecoration): IMarker | null;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ export interface IModeService {
|
||||
// --- instantiation
|
||||
create(commaSeparatedMimetypesOrCommaSeparatedIds: string): ILanguageSelection;
|
||||
createByLanguageName(languageName: string): ILanguageSelection;
|
||||
createByFilepathOrFirstLine(filepath: string, firstLine?: string): ILanguageSelection;
|
||||
createByFilepathOrFirstLine(filepath: string | null, firstLine?: string): ILanguageSelection;
|
||||
|
||||
triggerMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): void;
|
||||
}
|
||||
|
||||
@@ -45,10 +45,10 @@ export class ModeServiceImpl implements IModeService {
|
||||
private readonly _instantiatedModes: { [modeId: string]: IMode; };
|
||||
private readonly _registry: LanguagesRegistry;
|
||||
|
||||
private readonly _onDidCreateMode: Emitter<IMode> = new Emitter<IMode>();
|
||||
private readonly _onDidCreateMode = new Emitter<IMode>();
|
||||
public readonly onDidCreateMode: Event<IMode> = this._onDidCreateMode.event;
|
||||
|
||||
protected readonly _onLanguagesMaybeChanged: Emitter<void> = new Emitter<void>();
|
||||
protected readonly _onLanguagesMaybeChanged = new Emitter<void>();
|
||||
private readonly onLanguagesMaybeChanged: Event<void> = this._onLanguagesMaybeChanged.event;
|
||||
|
||||
constructor(warnOnOverwrite = false) {
|
||||
@@ -94,7 +94,7 @@ export class ModeServiceImpl implements IModeService {
|
||||
return this._registry.getModeIdForLanguageNameLowercase(alias);
|
||||
}
|
||||
|
||||
public getModeIdByFilepathOrFirstLine(filepath: string, firstLine?: string): string | null {
|
||||
public getModeIdByFilepathOrFirstLine(filepath: string | null, firstLine?: string): string | null {
|
||||
const modeIds = this._registry.getModeIdsFromFilepathOrFirstLine(filepath, firstLine);
|
||||
|
||||
if (modeIds.length > 0) {
|
||||
@@ -138,7 +138,7 @@ export class ModeServiceImpl implements IModeService {
|
||||
});
|
||||
}
|
||||
|
||||
public createByFilepathOrFirstLine(filepath: string, firstLine?: string): ILanguageSelection {
|
||||
public createByFilepathOrFirstLine(filepath: string | null, firstLine?: string): ILanguageSelection {
|
||||
return new LanguageSelection(this.onLanguagesMaybeChanged, () => {
|
||||
const modeId = this.getModeIdByFilepathOrFirstLine(filepath, firstLine);
|
||||
return this._createModeAndGetLanguageIdentifier(modeId);
|
||||
|
||||
@@ -14,7 +14,7 @@ export const IModelService = createDecorator<IModelService>('modelService');
|
||||
export interface IModelService {
|
||||
_serviceBrand: any;
|
||||
|
||||
createModel(value: string | ITextBufferFactory, languageSelection: ILanguageSelection | null, resource: URI, isForSimpleWidget?: boolean): ITextModel;
|
||||
createModel(value: string | ITextBufferFactory, languageSelection: ILanguageSelection | null, resource: URI | undefined, isForSimpleWidget?: boolean): ITextModel;
|
||||
|
||||
updateModel(model: ITextModel, value: string | ITextBufferFactory): void;
|
||||
|
||||
|
||||
@@ -3,20 +3,14 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { escape } from 'vs/base/common/strings';
|
||||
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import * as network from 'vs/base/common/network';
|
||||
import { basename } from 'vs/base/common/paths';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { EDITOR_MODEL_DEFAULTS } from 'vs/editor/common/config/editorOptions';
|
||||
import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, IModelDecorationOptions, IModelDeltaDecoration, ITextBuffer, ITextBufferFactory, ITextModel, ITextModelCreationOptions, OverviewRulerLane, TrackedRangeStickiness } from 'vs/editor/common/model';
|
||||
import { ClassName } from 'vs/editor/common/model/intervalTree';
|
||||
import { DefaultEndOfLine, EndOfLinePreference, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextBuffer, ITextBufferFactory, ITextModel, ITextModelCreationOptions } from 'vs/editor/common/model';
|
||||
import { TextModel, createTextBuffer } from 'vs/editor/common/model/textModel';
|
||||
import { IModelLanguageChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
import { LanguageIdentifier } from 'vs/editor/common/modes';
|
||||
@@ -24,10 +18,7 @@ import { PLAINTEXT_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/modesRegis
|
||||
import { ILanguageSelection } from 'vs/editor/common/services/modeService';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { overviewRulerError, overviewRulerInfo, overviewRulerWarning } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IMarker, IMarkerService, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers';
|
||||
import { ThemeColor, themeColorFromId } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
function MODEL_ID(resource: URI): string {
|
||||
return resource.toString();
|
||||
@@ -39,7 +30,6 @@ class ModelData implements IDisposable {
|
||||
private _languageSelection: ILanguageSelection | null;
|
||||
private _languageSelectionListener: IDisposable | null;
|
||||
|
||||
private _markerDecorations: string[];
|
||||
private _modelEventListeners: IDisposable[];
|
||||
|
||||
constructor(
|
||||
@@ -52,8 +42,6 @@ class ModelData implements IDisposable {
|
||||
this._languageSelection = null;
|
||||
this._languageSelectionListener = null;
|
||||
|
||||
this._markerDecorations = [];
|
||||
|
||||
this._modelEventListeners = [];
|
||||
this._modelEventListeners.push(model.onWillDispose(() => onWillDispose(model)));
|
||||
this._modelEventListeners.push(model.onDidChangeLanguage((e) => onDidChangeLanguage(model, e)));
|
||||
@@ -71,15 +59,10 @@ class ModelData implements IDisposable {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._markerDecorations = this.model.deltaDecorations(this._markerDecorations, []);
|
||||
this._modelEventListeners = dispose(this._modelEventListeners);
|
||||
this._disposeLanguageSelection();
|
||||
}
|
||||
|
||||
public acceptMarkerDecorations(newDecorations: IModelDeltaDecoration[]): void {
|
||||
this._markerDecorations = this.model.deltaDecorations(this._markerDecorations, newDecorations);
|
||||
}
|
||||
|
||||
public setLanguage(languageSelection: ILanguageSelection): void {
|
||||
this._disposeLanguageSelection();
|
||||
this._languageSelection = languageSelection;
|
||||
@@ -88,155 +71,6 @@ class ModelData implements IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
class ModelMarkerHandler {
|
||||
|
||||
public static setMarkers(modelData: ModelData, markerService: IMarkerService): void {
|
||||
|
||||
// Limit to the first 500 errors/warnings
|
||||
const markers = markerService.read({ resource: modelData.model.uri, take: 500 });
|
||||
|
||||
let newModelDecorations: IModelDeltaDecoration[] = markers.map((marker) => {
|
||||
return {
|
||||
range: ModelMarkerHandler._createDecorationRange(modelData.model, marker),
|
||||
options: ModelMarkerHandler._createDecorationOption(marker)
|
||||
};
|
||||
});
|
||||
|
||||
modelData.acceptMarkerDecorations(newModelDecorations);
|
||||
}
|
||||
|
||||
private static _createDecorationRange(model: ITextModel, rawMarker: IMarker): Range {
|
||||
|
||||
let ret = Range.lift(rawMarker);
|
||||
|
||||
if (rawMarker.severity === MarkerSeverity.Hint) {
|
||||
if (!rawMarker.tags || rawMarker.tags.indexOf(MarkerTag.Unnecessary) === -1) {
|
||||
// * never render hints on multiple lines
|
||||
// * make enough space for three dots
|
||||
ret = ret.setEndPosition(ret.startLineNumber, ret.startColumn + 2);
|
||||
}
|
||||
}
|
||||
|
||||
ret = model.validateRange(ret);
|
||||
|
||||
if (ret.isEmpty()) {
|
||||
let word = model.getWordAtPosition(ret.getStartPosition());
|
||||
if (word) {
|
||||
ret = new Range(ret.startLineNumber, word.startColumn, ret.endLineNumber, word.endColumn);
|
||||
} else {
|
||||
let maxColumn = model.getLineLastNonWhitespaceColumn(ret.startLineNumber) ||
|
||||
model.getLineMaxColumn(ret.startLineNumber);
|
||||
|
||||
if (maxColumn === 1) {
|
||||
// empty line
|
||||
// console.warn('marker on empty line:', marker);
|
||||
} else if (ret.endColumn >= maxColumn) {
|
||||
// behind eol
|
||||
ret = new Range(ret.startLineNumber, maxColumn - 1, ret.endLineNumber, maxColumn);
|
||||
} else {
|
||||
// extend marker to width = 1
|
||||
ret = new Range(ret.startLineNumber, ret.startColumn, ret.endLineNumber, ret.endColumn + 1);
|
||||
}
|
||||
}
|
||||
} else if (rawMarker.endColumn === Number.MAX_VALUE && rawMarker.startColumn === 1 && ret.startLineNumber === ret.endLineNumber) {
|
||||
let minColumn = model.getLineFirstNonWhitespaceColumn(rawMarker.startLineNumber);
|
||||
if (minColumn < ret.endColumn) {
|
||||
ret = new Range(ret.startLineNumber, minColumn, ret.endLineNumber, ret.endColumn);
|
||||
rawMarker.startColumn = minColumn;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static _createDecorationOption(marker: IMarker): IModelDecorationOptions {
|
||||
|
||||
let className: string;
|
||||
let color: ThemeColor | undefined = undefined;
|
||||
let zIndex: number;
|
||||
let inlineClassName: string | undefined = undefined;
|
||||
|
||||
switch (marker.severity) {
|
||||
case MarkerSeverity.Hint:
|
||||
if (marker.tags && marker.tags.indexOf(MarkerTag.Unnecessary) >= 0) {
|
||||
className = ClassName.EditorUnnecessaryDecoration;
|
||||
} else {
|
||||
className = ClassName.EditorHintDecoration;
|
||||
}
|
||||
zIndex = 0;
|
||||
break;
|
||||
case MarkerSeverity.Warning:
|
||||
className = ClassName.EditorWarningDecoration;
|
||||
color = themeColorFromId(overviewRulerWarning);
|
||||
zIndex = 20;
|
||||
break;
|
||||
case MarkerSeverity.Info:
|
||||
className = ClassName.EditorInfoDecoration;
|
||||
color = themeColorFromId(overviewRulerInfo);
|
||||
zIndex = 10;
|
||||
break;
|
||||
case MarkerSeverity.Error:
|
||||
default:
|
||||
className = ClassName.EditorErrorDecoration;
|
||||
color = themeColorFromId(overviewRulerError);
|
||||
zIndex = 30;
|
||||
break;
|
||||
}
|
||||
|
||||
if (marker.tags) {
|
||||
if (marker.tags.indexOf(MarkerTag.Unnecessary) !== -1) {
|
||||
inlineClassName = ClassName.EditorUnnecessaryInlineDecoration;
|
||||
}
|
||||
}
|
||||
|
||||
let hoverMessage: MarkdownString | null = null;
|
||||
let { message, source, relatedInformation, code } = marker;
|
||||
|
||||
if (typeof message === 'string') {
|
||||
|
||||
hoverMessage = new MarkdownString();
|
||||
// Disable markdown renderer sanitize to allow html
|
||||
// Hence, escape all input strings
|
||||
hoverMessage.sanitize = false;
|
||||
|
||||
hoverMessage.appendMarkdown(`<div>`);
|
||||
hoverMessage.appendMarkdown(`<span style='font-family: Monaco, Menlo, Consolas, "Droid Sans Mono", "Inconsolata", "Courier New", monospace, "Droid Sans Fallback"; white-space: pre-wrap;'>${escape(message.trim())}</span>`);
|
||||
if (source) {
|
||||
hoverMessage.appendMarkdown(`<span style='opacity: 0.6; padding-left:6px;'>${escape(source)}</span>`);
|
||||
if (code) {
|
||||
hoverMessage.appendMarkdown(`<span style='opacity: 0.6; padding-left:2px;'>(${escape(code)})</span>`);
|
||||
}
|
||||
} else if (code) {
|
||||
hoverMessage.appendMarkdown(`<span style='opacity: 0.6; padding-left:6px;'>(${escape(code)})</span>`);
|
||||
}
|
||||
hoverMessage.appendMarkdown(`</div>`);
|
||||
|
||||
if (isNonEmptyArray(relatedInformation)) {
|
||||
hoverMessage.appendMarkdown(`<ul>`);
|
||||
for (const { message, resource, startLineNumber, startColumn } of relatedInformation) {
|
||||
hoverMessage.appendMarkdown(`<li>`);
|
||||
hoverMessage.appendMarkdown(`<a href='#' data-href='${resource.toString(false)}#${startLineNumber},${startColumn}'>${escape(basename(resource.path))}(${startLineNumber}, ${startColumn})</a>`);
|
||||
hoverMessage.appendMarkdown(`<span>: ${escape(message)}</span>`);
|
||||
hoverMessage.appendMarkdown(`</li>`);
|
||||
}
|
||||
hoverMessage.appendMarkdown(`</ul>`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
className,
|
||||
hoverMessage,
|
||||
showIfCollapsed: true,
|
||||
overviewRuler: {
|
||||
color,
|
||||
position: OverviewRulerLane.Right
|
||||
},
|
||||
zIndex,
|
||||
inlineClassName,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface IRawEditorConfig {
|
||||
tabSize?: any;
|
||||
insertSpaces?: any;
|
||||
@@ -256,8 +90,6 @@ const DEFAULT_EOL = (platform.isLinux || platform.isMacintosh) ? DefaultEndOfLin
|
||||
export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
public _serviceBrand: any;
|
||||
|
||||
private _markerService: IMarkerService;
|
||||
private _markerServiceSubscription: IDisposable;
|
||||
private _configurationService: IConfigurationService;
|
||||
private _configurationServiceSubscription: IDisposable;
|
||||
private _resourcePropertiesService: ITextResourcePropertiesService;
|
||||
@@ -268,7 +100,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
private readonly _onModelRemoved: Emitter<ITextModel> = this._register(new Emitter<ITextModel>());
|
||||
public readonly onModelRemoved: Event<ITextModel> = this._onModelRemoved.event;
|
||||
|
||||
private readonly _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }> = this._register(new Emitter<{ model: ITextModel; oldModeId: string; }>({ leakWarningThreshold: 500 }));
|
||||
private readonly _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }> = this._register(new Emitter<{ model: ITextModel; oldModeId: string; }>());
|
||||
public readonly onModelModeChanged: Event<{ model: ITextModel; oldModeId: string; }> = this._onModelModeChanged.event;
|
||||
|
||||
private _modelCreationOptionsByLanguageAndResource: {
|
||||
@@ -281,21 +113,15 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
private _models: { [modelId: string]: ModelData; };
|
||||
|
||||
constructor(
|
||||
@IMarkerService markerService: IMarkerService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService,
|
||||
@ITextResourcePropertiesService resourcePropertiesService: ITextResourcePropertiesService
|
||||
) {
|
||||
super();
|
||||
this._markerService = markerService;
|
||||
this._configurationService = configurationService;
|
||||
this._resourcePropertiesService = resourcePropertiesService;
|
||||
this._models = {};
|
||||
this._modelCreationOptionsByLanguageAndResource = Object.create(null);
|
||||
|
||||
if (this._markerService) {
|
||||
this._markerServiceSubscription = this._markerService.onMarkerChanged(this._handleMarkerChange, this);
|
||||
}
|
||||
|
||||
this._configurationServiceSubscription = this._configurationService.onDidChangeConfiguration(e => this._updateModelOptions());
|
||||
this._updateModelOptions();
|
||||
}
|
||||
@@ -351,7 +177,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
};
|
||||
}
|
||||
|
||||
public getCreationOptions(language: string, resource: URI, isForSimpleWidget: boolean): ITextModelCreationOptions {
|
||||
public getCreationOptions(language: string, resource: URI | null | undefined, isForSimpleWidget: boolean): ITextModelCreationOptions {
|
||||
let creationOptions = this._modelCreationOptionsByLanguageAndResource[language + resource];
|
||||
if (!creationOptions) {
|
||||
const editor = this._configurationService.getValue<IRawEditorConfig>('editor', { overrideIdentifier: language, resource });
|
||||
@@ -405,41 +231,13 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
if (this._markerServiceSubscription) {
|
||||
this._markerServiceSubscription.dispose();
|
||||
}
|
||||
this._configurationServiceSubscription.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private _handleMarkerChange(changedResources: URI[]): void {
|
||||
changedResources.forEach((resource) => {
|
||||
let modelId = MODEL_ID(resource);
|
||||
let modelData = this._models[modelId];
|
||||
if (!modelData) {
|
||||
return;
|
||||
}
|
||||
ModelMarkerHandler.setMarkers(modelData, this._markerService);
|
||||
});
|
||||
}
|
||||
|
||||
private _cleanUp(model: ITextModel): void {
|
||||
// clean up markers for internal, transient models
|
||||
if (model.uri.scheme === network.Schemas.inMemory
|
||||
|| model.uri.scheme === network.Schemas.internal
|
||||
|| model.uri.scheme === network.Schemas.vscode) {
|
||||
if (this._markerService) {
|
||||
this._markerService.read({ resource: model.uri }).map(marker => marker.owner).forEach(owner => this._markerService.remove(owner, [model.uri]));
|
||||
}
|
||||
}
|
||||
|
||||
// clean up cache
|
||||
delete this._modelCreationOptionsByLanguageAndResource[model.getLanguageIdentifier().language + model.uri];
|
||||
}
|
||||
|
||||
// --- begin IModelService
|
||||
|
||||
private _createModelData(value: string | ITextBufferFactory, languageIdentifier: LanguageIdentifier, resource: URI, isForSimpleWidget: boolean): ModelData {
|
||||
private _createModelData(value: string | ITextBufferFactory, languageIdentifier: LanguageIdentifier, resource: URI | null | undefined, isForSimpleWidget: boolean): ModelData {
|
||||
// create & save the model
|
||||
const options = this.getCreationOptions(languageIdentifier.language, resource, isForSimpleWidget);
|
||||
const model: TextModel = new TextModel(value, options, languageIdentifier, resource);
|
||||
@@ -530,7 +328,7 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
return [EditOperation.replaceMove(oldRange, textBuffer.getValueInRange(newRange, EndOfLinePreference.TextDefined))];
|
||||
}
|
||||
|
||||
public createModel(value: string | ITextBufferFactory, languageSelection: ILanguageSelection | null, resource: URI, isForSimpleWidget: boolean = false): ITextModel {
|
||||
public createModel(value: string | ITextBufferFactory, languageSelection: ILanguageSelection | null, resource: URI | null | undefined, isForSimpleWidget: boolean = false): ITextModel {
|
||||
let modelData: ModelData;
|
||||
|
||||
if (languageSelection) {
|
||||
@@ -540,11 +338,6 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
modelData = this._createModelData(value, PLAINTEXT_LANGUAGE_IDENTIFIER, resource, isForSimpleWidget);
|
||||
}
|
||||
|
||||
// handle markers (marker service => model)
|
||||
if (this._markerService) {
|
||||
ModelMarkerHandler.setMarkers(modelData, this._markerService);
|
||||
}
|
||||
|
||||
this._onModelAdded.fire(modelData.model);
|
||||
|
||||
return modelData.model;
|
||||
@@ -600,7 +393,9 @@ export class ModelServiceImpl extends Disposable implements IModelService {
|
||||
delete this._models[modelId];
|
||||
modelData.dispose();
|
||||
|
||||
this._cleanUp(model);
|
||||
// clean up cache
|
||||
delete this._modelCreationOptionsByLanguageAndResource[model.getLanguageIdentifier().language + model.uri];
|
||||
|
||||
this._onModelRemoved.fire(model);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { IDisposable, IReference } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IEditorModel } from 'vs/platform/editor/common/editor';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -19,12 +18,17 @@ export interface ITextModelService {
|
||||
* Provided a resource URI, it will return a model reference
|
||||
* which should be disposed once not needed anymore.
|
||||
*/
|
||||
createModelReference(resource: URI): TPromise<IReference<ITextEditorModel>>;
|
||||
createModelReference(resource: URI): Promise<IReference<ITextEditorModel>>;
|
||||
|
||||
/**
|
||||
* Registers a specific `scheme` content provider.
|
||||
*/
|
||||
registerTextModelContentProvider(scheme: string, provider: ITextModelContentProvider): IDisposable;
|
||||
|
||||
/**
|
||||
* Check if a provider for the given `scheme` exists
|
||||
*/
|
||||
hasTextModelContentProvider(scheme: string): boolean;
|
||||
}
|
||||
|
||||
export interface ITextModelContentProvider {
|
||||
@@ -32,7 +36,7 @@ export interface ITextModelContentProvider {
|
||||
/**
|
||||
* Given a resource, return the content of the resource as `ITextModel`.
|
||||
*/
|
||||
provideTextContent(resource: URI): Thenable<ITextModel>;
|
||||
provideTextContent(resource: URI): Promise<ITextModel> | null;
|
||||
}
|
||||
|
||||
export interface ITextEditorModel extends IEditorModel {
|
||||
@@ -40,7 +44,7 @@ export interface ITextEditorModel extends IEditorModel {
|
||||
/**
|
||||
* Provides access to the underlying `ITextModel`.
|
||||
*/
|
||||
textEditorModel: ITextModel;
|
||||
readonly textEditorModel: ITextModel;
|
||||
|
||||
isReadonly(): boolean;
|
||||
}
|
||||
|
||||
@@ -43,5 +43,5 @@ export interface ITextResourcePropertiesService {
|
||||
/**
|
||||
* Returns the End of Line characters for the given resource
|
||||
*/
|
||||
getEOL(resource: URI, language?: string): string;
|
||||
getEOL(resource: URI | null | undefined, language?: string): string;
|
||||
}
|
||||
@@ -20,9 +20,9 @@ export class TextResourceConfigurationService extends Disposable implements ITex
|
||||
public readonly onDidChangeConfiguration: Event<IConfigurationChangeEvent> = this._onDidChangeConfiguration.event;
|
||||
|
||||
constructor(
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IModelService private modelService: IModelService,
|
||||
@IModeService private modeService: IModeService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
) {
|
||||
super();
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => this._onDidChangeConfiguration.fire(e)));
|
||||
@@ -38,7 +38,7 @@ export class TextResourceConfigurationService extends Disposable implements ITex
|
||||
}
|
||||
|
||||
private _getValue<T>(resource: URI, position: IPosition | null, section: string | undefined): T {
|
||||
const language = resource ? this.getLanguage(resource, position) : void 0;
|
||||
const language = resource ? this.getLanguage(resource, position) : undefined;
|
||||
if (typeof section === 'undefined') {
|
||||
return this.configurationService.getValue<T>({ resource, overrideIdentifier: language });
|
||||
}
|
||||
|
||||
@@ -69,20 +69,20 @@ class MonacoWebWorkerImpl<T> extends EditorWorkerClient implements MonacoWebWork
|
||||
return proxy.loadForeignModule(this._foreignModuleId, this._foreignModuleCreateData).then((foreignMethods) => {
|
||||
this._foreignModuleCreateData = null;
|
||||
|
||||
let proxyMethodRequest = (method: string, args: any[]): Promise<any> => {
|
||||
const proxyMethodRequest = (method: string, args: any[]): Promise<any> => {
|
||||
return proxy.fmr(method, args);
|
||||
};
|
||||
|
||||
let createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => Promise<any>): Function => {
|
||||
const createProxyMethod = (method: string, proxyMethodRequest: (method: string, args: any[]) => Promise<any>): () => Promise<any> => {
|
||||
return function () {
|
||||
let args = Array.prototype.slice.call(arguments, 0);
|
||||
const args = Array.prototype.slice.call(arguments, 0);
|
||||
return proxyMethodRequest(method, args);
|
||||
};
|
||||
};
|
||||
|
||||
let foreignProxy = {} as T;
|
||||
for (let i = 0; i < foreignMethods.length; i++) {
|
||||
(<any>foreignProxy)[foreignMethods[i]] = createProxyMethod(foreignMethods[i], proxyMethodRequest);
|
||||
for (const foreignMethod of foreignMethods) {
|
||||
(<any>foreignProxy)[foreignMethod] = createProxyMethod(foreignMethod, proxyMethodRequest);
|
||||
}
|
||||
|
||||
return foreignProxy;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"name": "promise-polyfill",
|
||||
"repositoryUrl": "https://github.com/taylorhakes/promise-polyfill",
|
||||
"commitHash": "efe662be6ea569c439ec92a4f8662c0a7faf0b96"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
"version": "8.0.0"
|
||||
}
|
||||
],
|
||||
"version": 1
|
||||
}
|
||||
291
src/vs/editor/common/standalone/promise-polyfill/polyfill.js
Normal file
291
src/vs/editor/common/standalone/promise-polyfill/polyfill.js
Normal file
@@ -0,0 +1,291 @@
|
||||
/*!
|
||||
Copyright (c) 2014 Taylor Hakes
|
||||
Copyright (c) 2014 Forbes Lindesay
|
||||
*/
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(factory());
|
||||
}(this, (function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @this {Promise}
|
||||
*/
|
||||
function finallyConstructor(callback) {
|
||||
var constructor = this.constructor;
|
||||
return this.then(
|
||||
function (value) {
|
||||
return constructor.resolve(callback()).then(function () {
|
||||
return value;
|
||||
});
|
||||
},
|
||||
function (reason) {
|
||||
return constructor.resolve(callback()).then(function () {
|
||||
return constructor.reject(reason);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Store setTimeout reference so promise-polyfill will be unaffected by
|
||||
// other code modifying setTimeout (like sinon.useFakeTimers())
|
||||
var setTimeoutFunc = setTimeout;
|
||||
|
||||
function noop() { }
|
||||
|
||||
// Polyfill for Function.prototype.bind
|
||||
function bind(fn, thisArg) {
|
||||
return function () {
|
||||
fn.apply(thisArg, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {Function} fn
|
||||
*/
|
||||
function Promise(fn) {
|
||||
if (!(this instanceof Promise))
|
||||
throw new TypeError('Promises must be constructed via new');
|
||||
if (typeof fn !== 'function') throw new TypeError('not a function');
|
||||
/** @type {!number} */
|
||||
this._state = 0;
|
||||
/** @type {!boolean} */
|
||||
this._handled = false;
|
||||
/** @type {Promise|undefined} */
|
||||
this._value = undefined;
|
||||
/** @type {!Array<!Function>} */
|
||||
this._deferreds = [];
|
||||
|
||||
doResolve(fn, this);
|
||||
}
|
||||
|
||||
function handle(self, deferred) {
|
||||
while (self._state === 3) {
|
||||
self = self._value;
|
||||
}
|
||||
if (self._state === 0) {
|
||||
self._deferreds.push(deferred);
|
||||
return;
|
||||
}
|
||||
self._handled = true;
|
||||
Promise._immediateFn(function () {
|
||||
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
|
||||
if (cb === null) {
|
||||
(self._state === 1 ? resolve : reject)(deferred.promise, self._value);
|
||||
return;
|
||||
}
|
||||
var ret;
|
||||
try {
|
||||
ret = cb(self._value);
|
||||
} catch (e) {
|
||||
reject(deferred.promise, e);
|
||||
return;
|
||||
}
|
||||
resolve(deferred.promise, ret);
|
||||
});
|
||||
}
|
||||
|
||||
function resolve(self, newValue) {
|
||||
try {
|
||||
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
|
||||
if (newValue === self)
|
||||
throw new TypeError('A promise cannot be resolved with itself.');
|
||||
if (
|
||||
newValue &&
|
||||
(typeof newValue === 'object' || typeof newValue === 'function')
|
||||
) {
|
||||
var then = newValue.then;
|
||||
if (newValue instanceof Promise) {
|
||||
self._state = 3;
|
||||
self._value = newValue;
|
||||
finale(self);
|
||||
return;
|
||||
} else if (typeof then === 'function') {
|
||||
doResolve(bind(then, newValue), self);
|
||||
return;
|
||||
}
|
||||
}
|
||||
self._state = 1;
|
||||
self._value = newValue;
|
||||
finale(self);
|
||||
} catch (e) {
|
||||
reject(self, e);
|
||||
}
|
||||
}
|
||||
|
||||
function reject(self, newValue) {
|
||||
self._state = 2;
|
||||
self._value = newValue;
|
||||
finale(self);
|
||||
}
|
||||
|
||||
function finale(self) {
|
||||
if (self._state === 2 && self._deferreds.length === 0) {
|
||||
Promise._immediateFn(function () {
|
||||
if (!self._handled) {
|
||||
Promise._unhandledRejectionFn(self._value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = 0, len = self._deferreds.length; i < len; i++) {
|
||||
handle(self, self._deferreds[i]);
|
||||
}
|
||||
self._deferreds = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
function Handler(onFulfilled, onRejected, promise) {
|
||||
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
|
||||
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
|
||||
this.promise = promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a potentially misbehaving resolver function and make sure
|
||||
* onFulfilled and onRejected are only called once.
|
||||
*
|
||||
* Makes no guarantees about asynchrony.
|
||||
*/
|
||||
function doResolve(fn, self) {
|
||||
var done = false;
|
||||
try {
|
||||
fn(
|
||||
function (value) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
resolve(self, value);
|
||||
},
|
||||
function (reason) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
reject(self, reason);
|
||||
}
|
||||
);
|
||||
} catch (ex) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
reject(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
Promise.prototype['catch'] = function (onRejected) {
|
||||
return this.then(null, onRejected);
|
||||
};
|
||||
|
||||
Promise.prototype.then = function (onFulfilled, onRejected) {
|
||||
// @ts-ignore
|
||||
var prom = new this.constructor(noop);
|
||||
|
||||
handle(this, new Handler(onFulfilled, onRejected, prom));
|
||||
return prom;
|
||||
};
|
||||
|
||||
Promise.prototype['finally'] = finallyConstructor;
|
||||
|
||||
Promise.all = function (arr) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (!arr || typeof arr.length === 'undefined')
|
||||
throw new TypeError('Promise.all accepts an array');
|
||||
var args = Array.prototype.slice.call(arr);
|
||||
if (args.length === 0) return resolve([]);
|
||||
var remaining = args.length;
|
||||
|
||||
function res(i, val) {
|
||||
try {
|
||||
if (val && (typeof val === 'object' || typeof val === 'function')) {
|
||||
var then = val.then;
|
||||
if (typeof then === 'function') {
|
||||
then.call(
|
||||
val,
|
||||
function (val) {
|
||||
res(i, val);
|
||||
},
|
||||
reject
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
args[i] = val;
|
||||
if (--remaining === 0) {
|
||||
resolve(args);
|
||||
}
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < args.length; i++) {
|
||||
res(i, args[i]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Promise.resolve = function (value) {
|
||||
if (value && typeof value === 'object' && value.constructor === Promise) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
resolve(value);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.reject = function (value) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
reject(value);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.race = function (values) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
for (var i = 0, len = values.length; i < len; i++) {
|
||||
values[i].then(resolve, reject);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Use polyfill for setImmediate for performance gains
|
||||
Promise._immediateFn =
|
||||
(typeof setImmediate === 'function' &&
|
||||
function (fn) {
|
||||
setImmediate(fn);
|
||||
}) ||
|
||||
function (fn) {
|
||||
setTimeoutFunc(fn, 0);
|
||||
};
|
||||
|
||||
Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
|
||||
if (typeof console !== 'undefined' && console) {
|
||||
console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
|
||||
}
|
||||
};
|
||||
|
||||
/** @suppress {undefinedVars} */
|
||||
var globalNS = (function () {
|
||||
// the only reliable means to get the global object is
|
||||
// `Function('return this')()`
|
||||
// However, this causes CSP violations in Chrome apps.
|
||||
if (typeof self !== 'undefined') {
|
||||
return self;
|
||||
}
|
||||
if (typeof window !== 'undefined') {
|
||||
return window;
|
||||
}
|
||||
if (typeof global !== 'undefined') {
|
||||
return global;
|
||||
}
|
||||
throw new Error('unable to locate global object');
|
||||
})();
|
||||
|
||||
if (!('Promise' in globalNS)) {
|
||||
globalNS['Promise'] = Promise;
|
||||
} else if (!globalNS.Promise.prototype['finally']) {
|
||||
globalNS.Promise.prototype['finally'] = finallyConstructor;
|
||||
}
|
||||
|
||||
})));
|
||||
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2014 Taylor Hakes
|
||||
Copyright (c) 2014 Forbes Lindesay
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -3,11 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/editor/common/standalone/promise-polyfill/polyfill';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { KeyChord, KeyMod as ConstKeyMod } from 'vs/base/common/keyCodes';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
@@ -39,7 +39,6 @@ export function createMonacoBaseAPI(): typeof monaco {
|
||||
SelectionDirection: standaloneEnums.SelectionDirection,
|
||||
MarkerSeverity: standaloneEnums.MarkerSeverity,
|
||||
MarkerTag: standaloneEnums.MarkerTag,
|
||||
Promise: TPromise,
|
||||
Uri: <any>URI,
|
||||
Token: Token
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic
|
||||
*/
|
||||
export const editorLineHighlight = registerColor('editor.lineHighlightBackground', { dark: null, light: null, hc: null }, nls.localize('lineHighlight', 'Background color for the highlight of line at the cursor position.'));
|
||||
export const editorLineHighlightBorder = registerColor('editor.lineHighlightBorder', { dark: '#282828', light: '#eeeeee', hc: '#f38518' }, nls.localize('lineHighlightBorderBox', 'Background color for the border around the line at the cursor position.'));
|
||||
export const editorRangeHighlight = registerColor('editor.rangeHighlightBackground', { dark: '#ffffff0b', light: '#fdff0033', hc: null }, nls.localize('rangeHighlight', 'Background color of highlighted ranges, like by quick open and find features. The color must not be opaque to not hide underlying decorations.'), true);
|
||||
export const editorRangeHighlight = registerColor('editor.rangeHighlightBackground', { dark: '#ffffff0b', light: '#fdff0033', hc: null }, nls.localize('rangeHighlight', 'Background color of highlighted ranges, like by quick open and find features. The color must not be opaque so as not to hide underlying decorations.'), true);
|
||||
export const editorRangeHighlightBorder = registerColor('editor.rangeHighlightBorder', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('rangeHighlightBorder', 'Background color of the border around highlighted ranges.'), true);
|
||||
|
||||
export const editorCursorForeground = registerColor('editorCursor.foreground', { dark: '#AEAFAD', light: Color.black, hc: Color.white }, nls.localize('caret', 'Color of the editor cursor.'));
|
||||
@@ -49,11 +49,11 @@ export const editorInfoBorder = registerColor('editorInfo.border', { dark: null,
|
||||
export const editorHintForeground = registerColor('editorHint.foreground', { dark: Color.fromHex('#eeeeee').transparent(0.7), light: '#6c6c6c', hc: null }, nls.localize('hintForeground', 'Foreground color of hint squigglies in the editor.'));
|
||||
export const editorHintBorder = registerColor('editorHint.border', { dark: null, light: null, hc: Color.fromHex('#eeeeee').transparent(0.8) }, nls.localize('hintBorder', 'Border color of hint squigglies in the editor.'));
|
||||
|
||||
export const editorUnnecessaryCodeBorder = registerColor('editorUnnecessaryCode.border', { dark: null, light: null, hc: Color.fromHex('#fff').transparent(0.8) }, nls.localize('unnecessaryCodeBorder', 'Border of unnecessary code in the editor.'));
|
||||
export const editorUnnecessaryCodeOpacity = registerColor('editorUnnecessaryCode.opacity', { dark: Color.fromHex('#000a'), light: Color.fromHex('#0007'), hc: null }, nls.localize('unnecessaryCodeOpacity', 'Opacity of unnecessary code in the editor.'));
|
||||
export const editorUnnecessaryCodeBorder = registerColor('editorUnnecessaryCode.border', { dark: null, light: null, hc: Color.fromHex('#fff').transparent(0.8) }, nls.localize('unnecessaryCodeBorder', 'Border color of unnecessary (unused) source code in the editor.'));
|
||||
export const editorUnnecessaryCodeOpacity = registerColor('editorUnnecessaryCode.opacity', { dark: Color.fromHex('#000a'), light: Color.fromHex('#0007'), hc: null }, nls.localize('unnecessaryCodeOpacity', 'Opacity of unnecessary (unused) source code in the editor. For example, "#000000c0" will render the code with 75% opacity. For high contrast themes, use the \'editorUnnecessaryCode.border\' theme color to underline unnecessary code instead of fading it out.'));
|
||||
|
||||
const rulerRangeDefault = new Color(new RGBA(0, 122, 204, 0.6));
|
||||
export const overviewRulerRangeHighlight = registerColor('editorOverviewRuler.rangeHighlightForeground', { dark: rulerRangeDefault, light: rulerRangeDefault, hc: rulerRangeDefault }, nls.localize('overviewRulerRangeHighlight', 'Overview ruler marker color for range highlights. The color must not be opaque to not hide underlying decorations.'), true);
|
||||
export const overviewRulerRangeHighlight = registerColor('editorOverviewRuler.rangeHighlightForeground', { dark: rulerRangeDefault, light: rulerRangeDefault, hc: rulerRangeDefault }, nls.localize('overviewRulerRangeHighlight', 'Overview ruler marker color for range highlights. The color must not be opaque so as not to hide underlying decorations.'), true);
|
||||
export const overviewRulerError = registerColor('editorOverviewRuler.errorForeground', { dark: new Color(new RGBA(255, 18, 18, 0.7)), light: new Color(new RGBA(255, 18, 18, 0.7)), hc: new Color(new RGBA(255, 50, 50, 1)) }, nls.localize('overviewRuleError', 'Overview ruler marker color for errors.'));
|
||||
export const overviewRulerWarning = registerColor('editorOverviewRuler.warningForeground', { dark: new Color(new RGBA(18, 136, 18, 0.7)), light: new Color(new RGBA(18, 136, 18, 0.7)), hc: new Color(new RGBA(50, 255, 50, 1)) }, nls.localize('overviewRuleWarning', 'Overview ruler marker color for warnings.'));
|
||||
export const overviewRulerInfo = registerColor('editorOverviewRuler.infoForeground', { dark: new Color(new RGBA(18, 18, 136, 0.7)), light: new Color(new RGBA(18, 18, 136, 0.7)), hc: new Color(new RGBA(50, 50, 255, 1)) }, nls.localize('overviewRuleInfo', 'Overview ruler marker color for infos.'));
|
||||
|
||||
@@ -46,7 +46,7 @@ export class MinimapTokensColorTracker {
|
||||
}
|
||||
let backgroundLuminosity = colorMap[ColorId.DefaultBackground].getRelativeLuminance();
|
||||
this._backgroundIsLight = (backgroundLuminosity >= 0.5);
|
||||
this._onDidChange.fire(void 0);
|
||||
this._onDidChange.fire(undefined);
|
||||
}
|
||||
|
||||
public getColor(colorId: ColorId): RGBA8 {
|
||||
|
||||
@@ -735,7 +735,7 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
|
||||
if (!canUseHalfwidthRightwardsArrow || insertSpacesCount > 1) {
|
||||
sb.write1(0x2192); // RIGHTWARDS ARROW
|
||||
} else {
|
||||
sb.write1(0xffeb); // HALFWIDTH RIGHTWARDS ARROW
|
||||
sb.write1(0xFFEB); // HALFWIDTH RIGHTWARDS ARROW
|
||||
}
|
||||
insertSpacesCount--;
|
||||
}
|
||||
@@ -745,7 +745,7 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
|
||||
}
|
||||
} else {
|
||||
// must be CharCode.Space
|
||||
sb.write1(0xb7); // ·
|
||||
sb.write1(0xB7); // ·
|
||||
}
|
||||
|
||||
charOffsetInPart++;
|
||||
@@ -805,7 +805,7 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render
|
||||
|
||||
case CharCode.UTF8_BOM:
|
||||
case CharCode.LINE_SEPARATOR_2028:
|
||||
sb.write1(0xfffd);
|
||||
sb.write1(0xFFFD);
|
||||
partContentCnt++;
|
||||
break;
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ export interface ISplitLine {
|
||||
getViewLineMinColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number;
|
||||
getViewLineMaxColumn(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): number;
|
||||
getViewLineData(model: ISimpleModel, modelLineNumber: number, outputLineIndex: number): ViewLineData;
|
||||
getViewLinesData(model: ISimpleModel, modelLineNumber: number, fromOuputLineIndex: number, toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: (ViewLineData | null)[]): void;
|
||||
getViewLinesData(model: ISimpleModel, modelLineNumber: number, fromOuputLineIndex: number, toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: Array<ViewLineData | null>): void;
|
||||
|
||||
getModelColumnOfViewPosition(outputLineIndex: number, outputColumn: number): number;
|
||||
getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number): Position;
|
||||
@@ -87,7 +87,7 @@ export interface IViewModelLinesCollection {
|
||||
getViewLineMinColumn(viewLineNumber: number): number;
|
||||
getViewLineMaxColumn(viewLineNumber: number): number;
|
||||
getViewLineData(viewLineNumber: number): ViewLineData;
|
||||
getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): (ViewLineData | null)[];
|
||||
getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): Array<ViewLineData | null>;
|
||||
|
||||
getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): IOverviewRulerDecorations;
|
||||
getDecorationsInRange(range: Range, ownerId: number, filterOutValidation: boolean): IModelDecoration[];
|
||||
@@ -286,9 +286,9 @@ export class SplitLinesCollection implements IViewModelLinesCollection {
|
||||
// END TODO@Martin: Please stop calling this method on each model change!
|
||||
|
||||
let newDecorations: IModelDeltaDecoration[] = [];
|
||||
for (let i = 0; i < newRanges.length; i++) {
|
||||
for (const newRange of newRanges) {
|
||||
newDecorations.push({
|
||||
range: newRanges[i],
|
||||
range: newRange,
|
||||
options: ModelDecorationOptions.EMPTY
|
||||
});
|
||||
}
|
||||
@@ -403,8 +403,8 @@ export class SplitLinesCollection implements IViewModelLinesCollection {
|
||||
let hiddenAreas = this.getHiddenAreas();
|
||||
let isInHiddenArea = false;
|
||||
let testPosition = new Position(fromLineNumber, 1);
|
||||
for (let i = 0; i < hiddenAreas.length; i++) {
|
||||
if (hiddenAreas[i].containsPosition(testPosition)) {
|
||||
for (const hiddenArea of hiddenAreas) {
|
||||
if (hiddenArea.containsPosition(testPosition)) {
|
||||
isInHiddenArea = true;
|
||||
break;
|
||||
}
|
||||
@@ -788,8 +788,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection {
|
||||
public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): IOverviewRulerDecorations {
|
||||
const decorations = this.model.getOverviewRulerDecorations(ownerId, filterOutValidation);
|
||||
const result = new OverviewRulerDecorations();
|
||||
for (let i = 0, len = decorations.length; i < len; i++) {
|
||||
const decoration = decorations[i];
|
||||
for (const decoration of decorations) {
|
||||
const opts = <ModelDecorationOverviewRulerOptions>decoration.options.overviewRuler;
|
||||
const lane = opts ? opts.position : 0;
|
||||
if (lane === 0) {
|
||||
@@ -858,8 +857,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection {
|
||||
// Eliminate duplicate decorations that might have intersected our visible ranges multiple times
|
||||
let finalResult: IModelDecoration[] = [], finalResultLen = 0;
|
||||
let prevDecId: string | null = null;
|
||||
for (let i = 0, len = result.length; i < len; i++) {
|
||||
const dec = result[i];
|
||||
for (const dec of result) {
|
||||
const decId = dec.id;
|
||||
if (prevDecId === decId) {
|
||||
// skip
|
||||
@@ -922,7 +920,7 @@ class VisibleIdentitySplitLine implements ISplitLine {
|
||||
);
|
||||
}
|
||||
|
||||
public getViewLinesData(model: ISimpleModel, modelLineNumber: number, _fromOuputLineIndex: number, _toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: (ViewLineData | null)[]): void {
|
||||
public getViewLinesData(model: ISimpleModel, modelLineNumber: number, _fromOuputLineIndex: number, _toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: Array<ViewLineData | null>): void {
|
||||
if (!needed[globalStartIndex]) {
|
||||
result[globalStartIndex] = null;
|
||||
return;
|
||||
@@ -1136,7 +1134,7 @@ export class SplitLine implements ISplitLine {
|
||||
);
|
||||
}
|
||||
|
||||
public getViewLinesData(model: ITextModel, modelLineNumber: number, fromOuputLineIndex: number, toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: (ViewLineData | null)[]): void {
|
||||
public getViewLinesData(model: ITextModel, modelLineNumber: number, fromOuputLineIndex: number, toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: Array<ViewLineData | null>): void {
|
||||
if (!this._isVisible) {
|
||||
throw new Error('Not supported');
|
||||
}
|
||||
@@ -1360,12 +1358,12 @@ export class IdentityLinesCollection implements IViewModelLinesCollection {
|
||||
);
|
||||
}
|
||||
|
||||
public getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): (ViewLineData | null)[] {
|
||||
public getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): Array<ViewLineData | null> {
|
||||
const lineCount = this.model.getLineCount();
|
||||
viewStartLineNumber = Math.min(Math.max(1, viewStartLineNumber), lineCount);
|
||||
viewEndLineNumber = Math.min(Math.max(1, viewEndLineNumber), lineCount);
|
||||
|
||||
let result: (ViewLineData | null)[] = [];
|
||||
let result: Array<ViewLineData | null> = [];
|
||||
for (let lineNumber = viewStartLineNumber; lineNumber <= viewEndLineNumber; lineNumber++) {
|
||||
let idx = lineNumber - viewStartLineNumber;
|
||||
if (!needed[idx]) {
|
||||
@@ -1380,8 +1378,7 @@ export class IdentityLinesCollection implements IViewModelLinesCollection {
|
||||
public getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): IOverviewRulerDecorations {
|
||||
const decorations = this.model.getOverviewRulerDecorations(ownerId, filterOutValidation);
|
||||
const result = new OverviewRulerDecorations();
|
||||
for (let i = 0, len = decorations.length; i < len; i++) {
|
||||
const decoration = decorations[i];
|
||||
for (const decoration of decorations) {
|
||||
const opts = <ModelDecorationOverviewRulerOptions>decoration.options.overviewRuler;
|
||||
const lane = opts ? opts.position : 0;
|
||||
if (lane === 0) {
|
||||
|
||||
@@ -119,6 +119,7 @@ export interface IViewModel {
|
||||
* Gives a hint that a lot of requests are about to come in for these line numbers.
|
||||
*/
|
||||
setViewport(startLineNumber: number, endLineNumber: number, centeredLineNumber: number): void;
|
||||
tokenizeViewport(): void;
|
||||
setHasFocus(hasFocus: boolean): void;
|
||||
|
||||
getDecorationsInViewport(visibleRange: Range): ViewModelDecoration[];
|
||||
@@ -154,11 +155,11 @@ export interface IViewModel {
|
||||
|
||||
export class MinimapLinesRenderingData {
|
||||
public readonly tabSize: number;
|
||||
public readonly data: (ViewLineData | null)[];
|
||||
public readonly data: Array<ViewLineData | null>;
|
||||
|
||||
constructor(
|
||||
tabSize: number,
|
||||
data: (ViewLineData | null)[]
|
||||
data: Array<ViewLineData | null>
|
||||
) {
|
||||
this.tabSize = tabSize;
|
||||
this.data = data;
|
||||
|
||||
@@ -92,8 +92,7 @@ export class ViewModelDecorations implements IDisposable {
|
||||
}
|
||||
|
||||
public getDecorationsViewportData(viewRange: Range): IDecorationsViewportData {
|
||||
let cacheIsValid = true;
|
||||
cacheIsValid = cacheIsValid && (this._cachedModelDecorationsResolver !== null);
|
||||
let cacheIsValid = (this._cachedModelDecorationsResolver !== null);
|
||||
cacheIsValid = cacheIsValid && (viewRange.equalsRange(this._cachedModelDecorationsResolverViewRange));
|
||||
if (!cacheIsValid) {
|
||||
this._cachedModelDecorationsResolver = this._getDecorationsViewportData(viewRange);
|
||||
|
||||
@@ -23,6 +23,7 @@ import { IViewModelLinesCollection, IdentityLinesCollection, SplitLinesCollectio
|
||||
import { ICoordinatesConverter, IOverviewRulerDecorations, IViewModel, MinimapLinesRenderingData, ViewLineData, ViewLineRenderingData, ViewModelDecoration } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { ViewModelDecorations } from 'vs/editor/common/viewModel/viewModelDecorations';
|
||||
import { ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
|
||||
const USE_IDENTITY_LINES_COLLECTION = true;
|
||||
|
||||
@@ -31,6 +32,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
private readonly editorId: number;
|
||||
private readonly configuration: editorCommon.IConfiguration;
|
||||
private readonly model: ITextModel;
|
||||
private readonly _tokenizeViewportSoon: RunOnceScheduler;
|
||||
private hasFocus: boolean;
|
||||
private viewportStartLine: number;
|
||||
private viewportStartLineTrackedRange: string | null;
|
||||
@@ -38,7 +40,6 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
private readonly lines: IViewModelLinesCollection;
|
||||
public readonly coordinatesConverter: ICoordinatesConverter;
|
||||
public readonly viewLayout: ViewLayout;
|
||||
|
||||
private readonly decorations: ViewModelDecorations;
|
||||
|
||||
constructor(editorId: number, configuration: editorCommon.IConfiguration, model: ITextModel, scheduleAtNextAnimationFrame: (callback: () => void) => IDisposable) {
|
||||
@@ -47,6 +48,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
this.editorId = editorId;
|
||||
this.configuration = configuration;
|
||||
this.model = model;
|
||||
this._tokenizeViewportSoon = this._register(new RunOnceScheduler(() => this.tokenizeViewport(), 50));
|
||||
this.hasFocus = false;
|
||||
this.viewportStartLine = -1;
|
||||
this.viewportStartLineTrackedRange = null;
|
||||
@@ -80,6 +82,9 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
this.viewLayout = this._register(new ViewLayout(this.configuration, this.getLineCount(), scheduleAtNextAnimationFrame));
|
||||
|
||||
this._register(this.viewLayout.onDidScroll((e) => {
|
||||
if (e.scrollTopChanged) {
|
||||
this._tokenizeViewportSoon.schedule();
|
||||
}
|
||||
try {
|
||||
const eventsCollector = this._beginEmit();
|
||||
eventsCollector.emit(new viewEvents.ViewScrollChangedEvent(e));
|
||||
@@ -120,6 +125,13 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
this.viewportStartLineTrackedRange = this.model._setTrackedRange(this.viewportStartLineTrackedRange, null, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges);
|
||||
}
|
||||
|
||||
public tokenizeViewport(): void {
|
||||
const linesViewportData = this.viewLayout.getLinesViewportData();
|
||||
const startPosition = this.coordinatesConverter.convertViewPositionToModelPosition(new Position(linesViewportData.startLineNumber, 1));
|
||||
const endPosition = this.coordinatesConverter.convertViewPositionToModelPosition(new Position(linesViewportData.endLineNumber, 1));
|
||||
this.model.tokenizeViewport(startPosition.lineNumber, endPosition.lineNumber);
|
||||
}
|
||||
|
||||
public setHasFocus(hasFocus: boolean): void {
|
||||
this.hasFocus = hasFocus;
|
||||
}
|
||||
@@ -273,6 +285,10 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
} finally {
|
||||
this._endEmit();
|
||||
}
|
||||
|
||||
if (e.tokenizationSupportChanged) {
|
||||
this._tokenizeViewportSoon.schedule();
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this.model.onDidChangeLanguageConfiguration((e) => {
|
||||
@@ -537,8 +553,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
|
||||
public invalidateOverviewRulerColorCache(): void {
|
||||
const decorations = this.model.getOverviewRulerDecorations();
|
||||
for (let i = 0, len = decorations.length; i < len; i++) {
|
||||
const decoration = decorations[i];
|
||||
for (const decoration of decorations) {
|
||||
const opts = <ModelDecorationOverviewRulerOptions>decoration.options.overviewRuler;
|
||||
if (opts) {
|
||||
opts.invalidateCachedColor();
|
||||
@@ -611,8 +626,8 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
||||
}
|
||||
|
||||
let result: string[] = [];
|
||||
for (let i = 0; i < nonEmptyRanges.length; i++) {
|
||||
result.push(this.getValueInRange(nonEmptyRanges[i], forceCRLF ? EndOfLinePreference.CRLF : EndOfLinePreference.TextDefined));
|
||||
for (const nonEmptyRange of nonEmptyRanges) {
|
||||
result.push(this.getValueInRange(nonEmptyRange, forceCRLF ? EndOfLinePreference.CRLF : EndOfLinePreference.TextDefined));
|
||||
}
|
||||
return result.length === 1 ? result[0] : result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user