Merge VS Code 1.31.1 (#4283)

This commit is contained in:
Matt Irvine
2019-03-15 13:09:45 -07:00
committed by GitHub
parent 7d31575149
commit 86bac90001
1716 changed files with 53308 additions and 48375 deletions

View File

@@ -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': {

View File

@@ -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}}

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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--;
}
}

View File

@@ -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;

View File

@@ -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];

View File

@@ -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);

View File

@@ -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));
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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()

View File

@@ -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)

View File

@@ -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
};
}

View File

@@ -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;

View File

@@ -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.

View File

@@ -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--) {

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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 [];

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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));

View File

@@ -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 {

View File

@@ -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>;

View File

@@ -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);
});
}

View File

@@ -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`);
}

View File

@@ -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 [];
}

View 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,
};
}
}

View 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;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 });
}

View File

@@ -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;

View File

@@ -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
}

View 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;
}
})));

View File

@@ -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.

View File

@@ -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
};

View File

@@ -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.'));

View File

@@ -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 {

View File

@@ -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); // &middot;
sb.write1(0xB7); // &middot;
}
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;

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}