diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 43c3c987864..086ebb2ef78 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -54,6 +54,7 @@ "./vs/base/common/linkedList.ts", "./vs/base/common/map.ts", "./vs/base/common/marshalling.ts", + "./vs/base/common/mime.ts", "./vs/base/common/network.ts", "./vs/base/common/normalization.ts", "./vs/base/common/numbers.ts", @@ -96,13 +97,27 @@ "./vs/editor/browser/config/charWidthReader.ts", "./vs/editor/browser/config/elementSizeObserver.ts", "./vs/editor/browser/controller/textAreaState.ts", + "./vs/editor/common", "./vs/editor/common/commands/replaceCommand.ts", + "./vs/editor/common/commands/shiftCommand.ts", "./vs/editor/common/commands/surroundSelectionCommand.ts", "./vs/editor/common/commands/trimTrailingWhitespaceCommand.ts", + "./vs/editor/common/config/commonEditorConfig.ts", "./vs/editor/common/config/editorOptions.ts", "./vs/editor/common/config/editorZoom.ts", "./vs/editor/common/config/fontInfo.ts", + "./vs/editor/common/controller/cursor.ts", + "./vs/editor/common/controller/cursorCollection.ts", + "./vs/editor/common/controller/cursorColumnSelection.ts", + "./vs/editor/common/controller/cursorCommon.ts", + "./vs/editor/common/controller/cursorDeleteOperations.ts", "./vs/editor/common/controller/cursorEvents.ts", + "./vs/editor/common/controller/cursorEvents.ts", + "./vs/editor/common/controller/cursorMoveCommands.ts", + "./vs/editor/common/controller/cursorMoveOperations.ts", + "./vs/editor/common/controller/cursorTypeOperations.ts", + "./vs/editor/common/controller/cursorWordOperations.ts", + "./vs/editor/common/controller/oneCursor.ts", "./vs/editor/common/controller/wordCharacterClassifier.ts", "./vs/editor/common/core/characterClassifier.ts", "./vs/editor/common/core/editOperation.ts", @@ -139,6 +154,7 @@ "./vs/editor/common/modes/languageFeatureRegistry.ts", "./vs/editor/common/modes/languageSelector.ts", "./vs/editor/common/modes/linkComputer.ts", + "./vs/editor/common/modes/modesRegistry.ts", "./vs/editor/common/modes/nullMode.ts", "./vs/editor/common/modes/supports.ts", "./vs/editor/common/modes/supports/characterPair.ts", @@ -150,17 +166,40 @@ "./vs/editor/common/modes/supports/tokenization.ts", "./vs/editor/common/modes/textToHtmlTokenizer.ts", "./vs/editor/common/modes/tokenizationRegistry.ts", + "./vs/editor/common/services/editorSimpleWorker.ts", "./vs/editor/common/services/editorWorkerService.ts", + "./vs/editor/common/services/editorWorkerServiceImpl.ts", + "./vs/editor/common/services/languagesRegistry.ts", "./vs/editor/common/services/modelService.ts", + "./vs/editor/common/services/modelServiceImpl.ts", "./vs/editor/common/services/modeService.ts", + "./vs/editor/common/services/modeServiceImpl.ts", "./vs/editor/common/services/resolverService.ts", + "./vs/editor/common/services/resourceConfiguration.ts", + "./vs/editor/common/services/resourceConfigurationImpl.ts", + "./vs/editor/common/services/webWorker.ts", "./vs/editor/common/standalone/standaloneBase.ts", + "./vs/editor/common/view/editorColorRegistry.ts", "./vs/editor/common/view/minimapCharRenderer.ts", "./vs/editor/common/view/overviewZoneManager.ts", + "./vs/editor/common/view/renderingContext.ts", "./vs/editor/common/view/runtimeMinimapCharRenderer.ts", + "./vs/editor/common/view/viewContext.ts", + "./vs/editor/common/view/viewEventDispatcher.ts", "./vs/editor/common/view/viewEvents.ts", + "./vs/editor/common/viewLayout/lineDecorations.ts", + "./vs/editor/common/viewLayout/linesLayout.ts", + "./vs/editor/common/viewLayout/viewLayout.ts", + "./vs/editor/common/viewLayout/viewLineRenderer.ts", + "./vs/editor/common/viewLayout/viewLinesViewportData.ts", "./vs/editor/common/viewLayout/whitespaceComputer.ts", + "./vs/editor/common/viewModel/characterHardWrappingLineMapper.ts", "./vs/editor/common/viewModel/prefixSumComputer.ts", + "./vs/editor/common/viewModel/splitLinesCollection.ts", + "./vs/editor/common/viewModel/viewEventHandler.ts", + "./vs/editor/common/viewModel/viewModel.ts", + "./vs/editor/common/viewModel/viewModelDecorations.ts", + "./vs/editor/common/viewModel/viewModelImpl.ts", "./vs/editor/contrib/codeAction/codeActionTrigger.ts", "./vs/editor/contrib/colorPicker/colorPickerModel.ts", "./vs/editor/contrib/find/findState.ts", @@ -180,10 +219,13 @@ "./vs/editor/test/common/modes/supports/javascriptOnEnterRules.ts", "./vs/editor/test/common/modesTestUtils.ts", "./vs/monaco.d.ts", + "./vs/nls.d.ts", "./vs/nls.mock.ts", "./vs/platform/broadcast/electron-browser/broadcastService.ts", "./vs/platform/clipboard/common/clipboardService.ts", "./vs/platform/clipboard/electron-browser/clipboardService.ts", + "./vs/platform/configuration/common/configuration.ts", + "./vs/platform/configuration/common/configurationRegistry.ts", "./vs/platform/contextkey/common/contextkey.ts", "./vs/platform/download/common/download.ts", "./vs/platform/editor/common/editor.ts", @@ -228,6 +270,7 @@ "./vs/platform/url/common/url.ts", "./vs/platform/url/common/urlService.ts", "./vs/platform/workbench/common/contextkeys.ts", + "./vs/platform/workspace/common/workspace.ts", "./vs/workbench/api/shared/tasks.ts", "./vs/workbench/browser/parts/statusbar/statusbar.ts", "./vs/workbench/common/activity.ts", diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index e8b6ef67004..ba4aaa552e4 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -299,16 +299,16 @@ function topStep(array: T[], compare: (a: T, b: T) => number, result: T[], i: /** * @returns a new array with all undefined or null values removed. The original array is not modified at all. */ -export function coalesce(array: T[]): T[]; -export function coalesce(array: T[], inplace: true): void; -export function coalesce(array: T[], inplace?: true): void | T[] { +export function coalesce(array: (T | undefined | null)[]): T[]; +export function coalesce(array: (T | undefined | null)[], inplace: true): void; +export function coalesce(array: (T | undefined | null)[], inplace?: true): void | T[] { if (!array) { if (!inplace) { return array; } } if (!inplace) { - return array.filter(e => !!e); + return array.filter(e => !!e); } else { let to = 0; diff --git a/src/vs/base/common/mime.ts b/src/vs/base/common/mime.ts index bcfc10417e6..507067b2649 100644 --- a/src/vs/base/common/mime.ts +++ b/src/vs/base/common/mime.ts @@ -5,6 +5,7 @@ import * as paths from 'vs/base/common/paths'; import * as strings from 'vs/base/common/strings'; +import * as arrays from 'vs/base/common/arrays'; import { match } from 'vs/base/common/glob'; export const MIME_TEXT = 'text/plain'; @@ -136,10 +137,10 @@ export function guessMimeTypes(path: string, firstLine?: string): string[] { return [MIME_UNKNOWN]; } -function guessMimeTypeByPath(path: string, filename: string, associations: ITextMimeAssociationItem[]): string { - let filenameMatch: ITextMimeAssociationItem; - let patternMatch: ITextMimeAssociationItem; - let extensionMatch: ITextMimeAssociationItem; +function guessMimeTypeByPath(path: string, filename: string, associations: ITextMimeAssociationItem[]): string | null { + let filenameMatch: ITextMimeAssociationItem | null = null; + let patternMatch: ITextMimeAssociationItem | null = null; + let extensionMatch: ITextMimeAssociationItem | null = null; // We want to prioritize associations based on the order they are registered so that the last registered // association wins over all other. This is for https://github.com/Microsoft/vscode/issues/20074 @@ -154,9 +155,9 @@ function guessMimeTypeByPath(path: string, filename: string, associations: IText // Longest pattern match if (association.filepattern) { - if (!patternMatch || association.filepattern.length > patternMatch.filepattern.length) { + if (!patternMatch || association.filepattern.length > patternMatch.filepattern!.length) { const target = association.filepatternOnPath ? path : filename; // match on full path if pattern contains path separator - if (match(association.filepatternLowercase, target)) { + if (match(association.filepatternLowercase!, target)) { patternMatch = association; } } @@ -164,8 +165,8 @@ function guessMimeTypeByPath(path: string, filename: string, associations: IText // Longest extension match if (association.extension) { - if (!extensionMatch || association.extension.length > extensionMatch.extension.length) { - if (strings.endsWith(filename, association.extensionLowercase)) { + if (!extensionMatch || association.extension.length > extensionMatch.extension!.length) { + if (strings.endsWith(filename, association.extensionLowercase!)) { extensionMatch = association; } } @@ -190,7 +191,7 @@ function guessMimeTypeByPath(path: string, filename: string, associations: IText return null; } -function guessMimeTypeByFirstline(firstLine: string): string { +function guessMimeTypeByFirstline(firstLine: string): string | null { if (strings.startsWithUTF8BOM(firstLine)) { firstLine = firstLine.substr(1); } @@ -234,7 +235,7 @@ export function suggestFilename(langId: string, prefix: string): string { const extensions = registeredAssociations .filter(assoc => !assoc.userConfigured && assoc.extension && assoc.id === langId) .map(assoc => assoc.extension); - const extensionsWithDotFirst = extensions + const extensionsWithDotFirst = arrays.coalesce(extensions) .filter(assoc => strings.startsWith(assoc, '.')); if (extensionsWithDotFirst.length > 0) { diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index 31591c49df1..49fc60dd7f0 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -82,14 +82,14 @@ export function isBoolean(obj: any): obj is boolean { /** * @returns whether the provided parameter is undefined. */ -export function isUndefined(obj: any): boolean { +export function isUndefined(obj: any): obj is undefined { return typeof (obj) === _typeof.undefined; } /** * @returns whether the provided parameter is undefined or null. */ -export function isUndefinedOrNull(obj: any): boolean { +export function isUndefinedOrNull(obj: any): obj is undefined | null { return isUndefined(obj) || obj === null; } diff --git a/src/vs/base/worker/defaultWorkerFactory.ts b/src/vs/base/worker/defaultWorkerFactory.ts index a089a443094..eba95454048 100644 --- a/src/vs/base/worker/defaultWorkerFactory.ts +++ b/src/vs/base/worker/defaultWorkerFactory.ts @@ -67,10 +67,10 @@ export class DefaultWorkerFactory implements IWorkerFactory { private static LAST_WORKER_ID = 0; - private _label: string; + private _label: string | undefined; private _webWorkerFailedBeforeError: any; - constructor(label: string) { + constructor(label: string | undefined) { this._label = label; this._webWorkerFailedBeforeError = false; } diff --git a/src/vs/editor/common/config/commonEditorConfig.ts b/src/vs/editor/common/config/commonEditorConfig.ts index c8106f250c8..dca6389a780 100644 --- a/src/vs/editor/common/config/commonEditorConfig.ts +++ b/src/vs/editor/common/config/commonEditorConfig.ts @@ -85,7 +85,6 @@ export abstract class CommonEditorConfiguration extends Disposable implements ed this._rawOptions.parameterHints = objects.mixin({}, this._rawOptions.parameterHints || {}); this._validatedOptions = editorOptions.EditorOptionsValidator.validate(this._rawOptions, EDITOR_DEFAULTS); - this.editor = null; this._isDominatedByLongLines = false; this._lineNumbersDigitCount = 1; @@ -866,12 +865,12 @@ const editorConfiguration: IConfigurationNode = { } }; -let cachedEditorConfigurationKeys: { [key: string]: boolean; } = null; +let cachedEditorConfigurationKeys: { [key: string]: boolean; } | null = null; function getEditorConfigurationKeys(): { [key: string]: boolean; } { if (cachedEditorConfigurationKeys === null) { - cachedEditorConfigurationKeys = Object.create(null); - Object.keys(editorConfiguration.properties).forEach((prop) => { - cachedEditorConfigurationKeys[prop] = true; + cachedEditorConfigurationKeys = <{ [key: string]: boolean; }>Object.create(null); + Object.keys(editorConfiguration.properties!).forEach((prop) => { + cachedEditorConfigurationKeys![prop] = true; }); } return cachedEditorConfigurationKeys; diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 629a737d5e2..0004781a6d9 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -65,7 +65,7 @@ export class CursorModelState { this.cursorState = cursor.getAll(); } - public equals(other: CursorModelState): boolean { + public equals(other: CursorModelState | null): boolean { if (!other) { return false; } @@ -106,7 +106,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { private _isHandling: boolean; private _isDoingComposition: boolean; - private _columnSelectData: IColumnSelectData; + private _columnSelectData: IColumnSelectData | null; private _prevEditOperationType: EditOperationType; constructor(configuration: editorCommon.IConfiguration, model: ITextModel, viewModel: IViewModel) { @@ -347,7 +347,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { // ------ auxiliary handling logic - private _executeEditOperation(opResult: EditOperationResult): void { + private _executeEditOperation(opResult: EditOperationResult | null): void { if (!opResult) { // Nothing to execute @@ -371,7 +371,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { } } - private _interpretCommandResult(cursorState: Selection[]): void { + private _interpretCommandResult(cursorState: Selection[] | null): void { if (!cursorState || cursorState.length === 0) { cursorState = this._cursors.readSelectionFromMarkers(); } @@ -384,7 +384,7 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { // ----------------------------------------------------------------------------------------------------------- // ----- emitting events - private _emitStateChangedIfNecessary(source: string, reason: CursorChangeReason, oldState: CursorModelState): boolean { + private _emitStateChangedIfNecessary(source: string, reason: CursorChangeReason, oldState: CursorModelState | null): boolean { const newState = new CursorModelState(this._model, this); if (newState.equals(oldState)) { return false; @@ -619,7 +619,7 @@ interface ICommandsData { class CommandExecutor { - public static executeCommands(model: ITextModel, selectionsBefore: Selection[], commands: editorCommon.ICommand[]): Selection[] { + public static executeCommands(model: ITextModel, selectionsBefore: Selection[], commands: (editorCommon.ICommand | null)[]): Selection[] | null { const ctx: IExecContext = { model: model, @@ -637,7 +637,7 @@ class CommandExecutor { return result; } - private static _innerExecuteCommands(ctx: IExecContext, commands: editorCommon.ICommand[]): Selection[] { + private static _innerExecuteCommands(ctx: IExecContext, commands: (editorCommon.ICommand | null)[]): Selection[] | null { if (this._arrayIsEmpty(commands)) { return null; @@ -660,7 +660,7 @@ class CommandExecutor { // Remove operations belonging to losing cursors let filteredOperations: IIdentifiedSingleEditOperation[] = []; for (let i = 0, len = rawOperations.length; i < len; i++) { - if (!loserCursorsMap.hasOwnProperty(rawOperations[i].identifier.major.toString())) { + if (!loserCursorsMap.hasOwnProperty(rawOperations[i].identifier!.major.toString())) { filteredOperations.push(rawOperations[i]); } } @@ -670,7 +670,7 @@ class CommandExecutor { if (commandsData.hadTrackedEditOperation && filteredOperations.length > 0) { filteredOperations[0]._isTracked = true; } - const selectionsAfter = ctx.model.pushEditOperations(ctx.selectionsBefore, filteredOperations, (inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] => { + let selectionsAfter = ctx.model.pushEditOperations(ctx.selectionsBefore, filteredOperations, (inverseEditOperations: IIdentifiedSingleEditOperation[]): Selection[] => { let groupedInverseEditOperations: IIdentifiedSingleEditOperation[][] = []; for (let i = 0; i < ctx.selectionsBefore.length; i++) { groupedInverseEditOperations[i] = []; @@ -684,20 +684,20 @@ class CommandExecutor { groupedInverseEditOperations[op.identifier.major].push(op); } const minorBasedSorter = (a: IIdentifiedSingleEditOperation, b: IIdentifiedSingleEditOperation) => { - return a.identifier.minor - b.identifier.minor; + return a.identifier!.minor - b.identifier!.minor; }; let cursorSelections: Selection[] = []; for (let i = 0; i < ctx.selectionsBefore.length; i++) { if (groupedInverseEditOperations[i].length > 0) { groupedInverseEditOperations[i].sort(minorBasedSorter); - cursorSelections[i] = commands[i].computeCursorState(ctx.model, { + cursorSelections[i] = commands[i]!.computeCursorState(ctx.model, { getInverseEditOperations: () => { return groupedInverseEditOperations[i]; }, getTrackedSelection: (id: string) => { const idx = parseInt(id, 10); - const range = ctx.model._getTrackedRange(ctx.trackedRanges[idx]); + const range = ctx.model._getTrackedRange(ctx.trackedRanges[idx])!; if (ctx.trackedRangesDirection[idx] === SelectionDirection.LTR) { return new Selection(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); } @@ -710,6 +710,9 @@ class CommandExecutor { } return cursorSelections; }); + if (!selectionsAfter) { + selectionsAfter = ctx.selectionsBefore; + } // Extract losing cursors let losingCursors: number[] = []; @@ -732,7 +735,7 @@ class CommandExecutor { return selectionsAfter; } - private static _arrayIsEmpty(commands: editorCommon.ICommand[]): boolean { + private static _arrayIsEmpty(commands: (editorCommon.ICommand | null)[]): boolean { for (let i = 0, len = commands.length; i < len; i++) { if (commands[i]) { return false; @@ -741,13 +744,14 @@ class CommandExecutor { return true; } - private static _getEditOperations(ctx: IExecContext, commands: editorCommon.ICommand[]): ICommandsData { + private static _getEditOperations(ctx: IExecContext, commands: (editorCommon.ICommand | null)[]): ICommandsData { let operations: IIdentifiedSingleEditOperation[] = []; let hadTrackedEditOperation: boolean = false; for (let i = 0, len = commands.length; i < len; i++) { - if (commands[i]) { - const r = this._getEditOperationsFromCommand(ctx, i, commands[i]); + const command = commands[i]; + if (command) { + const r = this._getEditOperationsFromCommand(ctx, i, command); operations = operations.concat(r.operations); hadTrackedEditOperation = hadTrackedEditOperation || r.hadTrackedEditOperation; } @@ -860,17 +864,17 @@ class CommandExecutor { let loserMajor: number; - if (previousOp.identifier.major > currentOp.identifier.major) { + if (previousOp.identifier!.major > currentOp.identifier!.major) { // previousOp loses the battle - loserMajor = previousOp.identifier.major; + loserMajor = previousOp.identifier!.major; } else { - loserMajor = currentOp.identifier.major; + loserMajor = currentOp.identifier!.major; } loserCursorsMap[loserMajor.toString()] = true; for (let j = 0; j < operations.length; j++) { - if (operations[j].identifier.major === loserMajor) { + if (operations[j].identifier!.major === loserMajor) { operations.splice(j, 1); if (j < i) { i--; diff --git a/src/vs/editor/common/controller/cursorCommon.ts b/src/vs/editor/common/controller/cursorCommon.ts index c324bf27a4f..ca731b168ad 100644 --- a/src/vs/editor/common/controller/cursorCommon.ts +++ b/src/vs/editor/common/controller/cursorCommon.ts @@ -464,13 +464,13 @@ export class EditOperationResult { _editOperationResultBrand: void; readonly type: EditOperationType; - readonly commands: ICommand[]; + readonly commands: (ICommand | null)[]; readonly shouldPushStackElementBefore: boolean; readonly shouldPushStackElementAfter: boolean; constructor( type: EditOperationType, - commands: ICommand[], + commands: (ICommand | null)[], opts: { shouldPushStackElementBefore: boolean; shouldPushStackElementAfter: boolean; diff --git a/src/vs/editor/common/controller/cursorDeleteOperations.ts b/src/vs/editor/common/controller/cursorDeleteOperations.ts index a6f6a7c9c63..e1a7cf779d6 100644 --- a/src/vs/editor/common/controller/cursorDeleteOperations.ts +++ b/src/vs/editor/common/controller/cursorDeleteOperations.ts @@ -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[]] { - let commands: ICommand[] = []; + public static deleteRight(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, (ICommand | null)[]] { + let commands: (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[]] { + public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, (ICommand | null)[]] { if (this._isAutoClosingPairDelete(config, model, selections)) { return this._runAutoClosingPairDelete(config, model, selections); } - let commands: ICommand[] = []; + let commands: (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[] = []; + let commands: (ICommand | null)[] = []; for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; diff --git a/src/vs/editor/common/controller/cursorMoveCommands.ts b/src/vs/editor/common/controller/cursorMoveCommands.ts index 23c088e3193..886ad3a9cc8 100644 --- a/src/vs/editor/common/controller/cursorMoveCommands.ts +++ b/src/vs/editor/common/controller/cursorMoveCommands.ts @@ -259,7 +259,7 @@ export class CursorMoveCommands { return CursorState.fromViewState(cursor.viewState.move(inSelectionMode, viewPosition.lineNumber, viewPosition.column, 0)); } - public static move(context: CursorContext, cursors: CursorState[], args: CursorMove.ParsedArguments): PartialCursorState[] { + public static move(context: CursorContext, cursors: CursorState[], args: CursorMove.ParsedArguments): PartialCursorState[] | null { const inSelectionMode = args.select; const value = args.value; @@ -663,7 +663,7 @@ export namespace CursorMove { value?: number; } - export function parse(args: RawArguments): ParsedArguments { + export function parse(args: RawArguments): ParsedArguments | null { if (!args.to) { // illegal arguments return null; diff --git a/src/vs/editor/common/controller/cursorTypeOperations.ts b/src/vs/editor/common/controller/cursorTypeOperations.ts index 0ffa6699ed1..0c61759a83f 100644 --- a/src/vs/editor/common/controller/cursorTypeOperations.ts +++ b/src/vs/editor/common/controller/cursorTypeOperations.ts @@ -110,7 +110,7 @@ export class TypeOperations { }); } - private static _distributePasteToCursors(selections: Selection[], text: string, pasteOnNewLine: boolean, multicursorText: string[]): string[] { + private static _distributePasteToCursors(selections: Selection[], text: string, pasteOnNewLine: boolean, multicursorText: string[]): string[] | null { if (pasteOnNewLine) { return null; } @@ -146,9 +146,9 @@ export class TypeOperations { } } - private static _goodIndentForLine(config: CursorConfiguration, model: ITextModel, lineNumber: number): string { - let action: IndentAction | EnterAction; - let indentation: string; + private static _goodIndentForLine(config: CursorConfiguration, model: ITextModel, lineNumber: number): string | null { + let action: IndentAction | EnterAction | null = null; + let indentation: string = ''; let expectedIndentAction = config.autoIndent ? LanguageConfigurationRegistry.getInheritIndentForLine(model, lineNumber, false) : null; if (expectedIndentAction) { @@ -259,7 +259,7 @@ export class TypeOperations { } public static replacePreviousChar(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[], txt: string, replaceCharCnt: number): EditOperationResult { - let commands: ICommand[] = []; + let commands: (ICommand | null)[] = []; for (let i = 0, len = selections.length; i < len; i++) { const selection = selections[i]; if (!selection.isEmpty()) { @@ -399,7 +399,7 @@ export class TypeOperations { return true; } - private static _runAutoIndentType(config: CursorConfiguration, model: ITextModel, range: Range, ch: string): ICommand { + private static _runAutoIndentType(config: CursorConfiguration, model: ITextModel, range: Range, ch: string): ICommand | null { let currentIndentation = LanguageConfigurationRegistry.getIndentationAtPosition(model, range.startLineNumber, range.startColumn); let actualIndentation = LanguageConfigurationRegistry.getIndentActionForType(model, range, ch, { shiftIndent: (indentation) => { @@ -660,7 +660,7 @@ export class TypeOperations { return false; } - private static _typeInterceptorElectricChar(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selection: Selection, ch: string): EditOperationResult { + private static _typeInterceptorElectricChar(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selection: Selection, ch: string): EditOperationResult | null { if (!config.electricChars.hasOwnProperty(ch) || !selection.isEmpty()) { return null; } @@ -669,11 +669,12 @@ export class TypeOperations { model.forceTokenization(position.lineNumber); let lineTokens = model.getLineTokens(position.lineNumber); - let electricAction: IElectricAction; + let electricAction: IElectricAction | null; try { electricAction = LanguageConfigurationRegistry.onElectricCharacter(ch, lineTokens, position.column); } catch (e) { onUnexpectedError(e); + return null; } if (!electricAction) { @@ -723,7 +724,7 @@ export class TypeOperations { return null; } - public static compositionEndWithInterceptors(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[]): EditOperationResult { + public static compositionEndWithInterceptors(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ITextModel, selections: Selection[]): EditOperationResult | null { if (config.autoClosingQuotes === 'never') { return null; } @@ -820,7 +821,7 @@ export class TypeOperations { } if (this._isAutoIndentType(config, model, selections)) { - let commands: ICommand[] = []; + let commands: (ICommand | null)[] = []; let autoIndentFails = false; for (let i = 0, len = selections.length; i < len; i++) { commands[i] = this._runAutoIndentType(config, model, selections[i], ch); diff --git a/src/vs/editor/common/controller/oneCursor.ts b/src/vs/editor/common/controller/oneCursor.ts index 0a75e44cd4a..79321cdc2a0 100644 --- a/src/vs/editor/common/controller/oneCursor.ts +++ b/src/vs/editor/common/controller/oneCursor.ts @@ -70,12 +70,15 @@ export class OneCursor { this._setState(context, this.modelState, this.viewState); } - public setState(context: CursorContext, modelState: SingleCursorState, viewState: SingleCursorState): void { + public setState(context: CursorContext, modelState: SingleCursorState | null, viewState: SingleCursorState | null): void { this._setState(context, modelState, viewState); } - private _setState(context: CursorContext, modelState: SingleCursorState, viewState: SingleCursorState): void { + private _setState(context: CursorContext, modelState: SingleCursorState | null, viewState: SingleCursorState | null): void { if (!modelState) { + if (!viewState) { + return; + } // We only have the view state => compute the model state const selectionStart = context.model.validateRange( context.convertViewRangeToModelRange(viewState.selectionStart) diff --git a/src/vs/editor/common/core/range.ts b/src/vs/editor/common/core/range.ts index 864cc041bca..d010a6bd55a 100644 --- a/src/vs/editor/common/core/range.ts +++ b/src/vs/editor/common/core/range.ts @@ -216,7 +216,7 @@ export class Range { /** * Test if this range equals other. */ - public equalsRange(other: IRange): boolean { + public equalsRange(other: IRange | null): boolean { return Range.equalsRange(this, other); } diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts index f38ef53e4cb..393654b76e3 100644 --- a/src/vs/editor/common/model.ts +++ b/src/vs/editor/common/model.ts @@ -34,7 +34,7 @@ export interface IModelDecorationOverviewRulerOptions { * CSS color to render in the overview ruler. * e.g.: rgba(100, 100, 100, 0.5) or a color from the color registry */ - color: string | ThemeColor; + color: string | ThemeColor | undefined; /** * CSS color to render in the overview ruler. * e.g.: rgba(100, 100, 100, 0.5) or a color from the color registry @@ -934,7 +934,11 @@ export interface ITextModel { /** * @internal */ - _setTrackedRange(id: string | null, newRange: Range | null, newStickiness: TrackedRangeStickiness): string | null; + _setTrackedRange(id: string | null, newRange: null, newStickiness: TrackedRangeStickiness): null; + /** + * @internal + */ + _setTrackedRange(id: string | null, newRange: Range, newStickiness: TrackedRangeStickiness): string; /** * Normalize a string containing whitespace according to indentation rules (converts to spaces or to tabs). diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts index 1d82601e095..ce29fe68537 100644 --- a/src/vs/editor/common/model/textModel.ts +++ b/src/vs/editor/common/model/textModel.ts @@ -1552,6 +1552,8 @@ export class TextModel extends Disposable implements model.ITextModel { return this.getDecorationRange(id); } + _setTrackedRange(id: string | null, newRange: null, newStickiness: model.TrackedRangeStickiness): null; + _setTrackedRange(id: string | null, newRange: Range, newStickiness: model.TrackedRangeStickiness): string; _setTrackedRange(id: string | null, newRange: Range | null, newStickiness: model.TrackedRangeStickiness): string | null { const node = (id ? this._decorations[id] : null); diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 7c62ab125e5..92d30766481 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -853,11 +853,7 @@ export interface DocumentSymbolProvider { provideDocumentSymbols(model: model.ITextModel, token: CancellationToken): ProviderResult; } -export interface TextEdit { - range: IRange; - text: string; - eol?: model.EndOfLineSequence; -} +export type TextEdit = { range: IRange; text: string; eol?: model.EndOfLineSequence; } | { range: undefined; text: undefined; eol: model.EndOfLineSequence; }; /** * Interface used to format a model diff --git a/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts b/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts index e4e069b9376..3e92e29300d 100644 --- a/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts +++ b/src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts @@ -10,7 +10,7 @@ export class BasicInplaceReplace { public static readonly INSTANCE = new BasicInplaceReplace(); - public navigateValueSet(range1: IRange, text1: string, range2: IRange, text2: string, up: boolean): IInplaceReplaceSupportResult | null { + public navigateValueSet(range1: IRange, text1: string, range2: IRange, text2: string | null, up: boolean): IInplaceReplaceSupportResult | null { if (range1 && text1) { let result = this.doNavigateValueSet(text1, up); diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index b5e0c80454f..92dfcaae3de 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -61,7 +61,7 @@ export interface ICommonModel extends ILinkComputerTarget, IMirrorModel { createWordIterator(wordDefinition: RegExp): Iterator; getWordUntilPosition(position: IPosition, wordDefinition: RegExp): IWordAtPosition; getValueInRange(range: IRange): string; - getWordAtPosition(position: IPosition, wordDefinition: RegExp): Range; + getWordAtPosition(position: IPosition, wordDefinition: RegExp): Range | null; offsetAt(position: IPosition): number; positionAt(offset: number): IPosition; } @@ -114,7 +114,7 @@ class MirrorModel extends BaseMirrorModel implements ICommonModel { return this._lines[lineNumber - 1]; } - public getWordAtPosition(position: IPosition, wordDefinition: RegExp): Range { + public getWordAtPosition(position: IPosition, wordDefinition: RegExp): Range | null { let wordAtText = getWordAtText( position.column, @@ -194,7 +194,7 @@ class MirrorModel extends BaseMirrorModel implements ICommonModel { private _wordenize(content: string, wordDefinition: RegExp): IWordRange[] { const result: IWordRange[] = []; - let match: RegExpExecArray; + let match: RegExpExecArray | null; wordDefinition.lastIndex = 0; // reset lastIndex just to be sure @@ -232,7 +232,7 @@ class MirrorModel extends BaseMirrorModel implements ICommonModel { public offsetAt(position: IPosition): number { position = this._validatePosition(position); this._ensureLineStarts(); - return this._lineStarts.getAccumulatedValue(position.lineNumber - 2) + (position.column - 1); + return this._lineStarts!.getAccumulatedValue(position.lineNumber - 2) + (position.column - 1); } public positionAt(offset: number): IPosition { @@ -240,7 +240,7 @@ class MirrorModel extends BaseMirrorModel implements ICommonModel { offset = Math.max(0, offset); this._ensureLineStarts(); - let out = this._lineStarts.getIndexOf(offset); + let out = this._lineStarts!.getIndexOf(offset); let lineLength = this._lines[out.index].length; // Ensure we return a valid position @@ -321,10 +321,10 @@ declare var require: any; * @internal */ export abstract class BaseEditorSimpleWorker { - private _foreignModuleFactory: IForeignModuleFactory; + private _foreignModuleFactory: IForeignModuleFactory | null; private _foreignModule: any; - constructor(foreignModuleFactory: IForeignModuleFactory) { + constructor(foreignModuleFactory: IForeignModuleFactory | null) { this._foreignModuleFactory = foreignModuleFactory; this._foreignModule = null; } @@ -334,11 +334,11 @@ export abstract class BaseEditorSimpleWorker { // ---- BEGIN diff -------------------------------------------------------------------------- - public computeDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise { + public computeDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise { let original = this._getModel(originalUrl); let modified = this._getModel(modifiedUrl); if (!original || !modified) { - return null; + return Promise.resolve(null); } let originalLines = original.getLinesContent(); @@ -352,11 +352,11 @@ export abstract class BaseEditorSimpleWorker { return Promise.resolve(diffComputer.computeDiff()); } - public computeDirtyDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise { + public computeDirtyDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise { let original = this._getModel(originalUrl); let modified = this._getModel(modifiedUrl); if (!original || !modified) { - return null; + return Promise.resolve(null); } let originalLines = original.getLinesContent(); @@ -384,9 +384,17 @@ export abstract class BaseEditorSimpleWorker { } const result: TextEdit[] = []; - let lastEol: EndOfLineSequence; + let lastEol: EndOfLineSequence | undefined = undefined; - edits = mergeSort(edits, (a, b) => Range.compareRangesUsingStarts(a.range, b.range)); + edits = mergeSort(edits, (a, b) => { + if (a.range && b.range) { + return Range.compareRangesUsingStarts(a.range, b.range); + } + // eol only changes should go to the end + let aRng = a.range ? 0 : 1; + let bRng = b.range ? 0 : 1; + return aRng - bRng; + }); for (let { range, text, eol } of edits) { @@ -400,7 +408,7 @@ export abstract class BaseEditorSimpleWorker { } const original = model.getValueInRange(range); - text = text.replace(/\r\n|\n|\r/g, model.eol); + text = text!.replace(/\r\n|\n|\r/g, model.eol); if (original === text) { // noop @@ -440,10 +448,10 @@ export abstract class BaseEditorSimpleWorker { // ---- END minimal edits --------------------------------------------------------------- - public computeLinks(modelUrl: string): Promise { + public computeLinks(modelUrl: string): Promise { let model = this._getModel(modelUrl); if (!model) { - return null; + return Promise.resolve(null); } return Promise.resolve(computeLinks(model)); @@ -453,42 +461,43 @@ export abstract class BaseEditorSimpleWorker { private static readonly _suggestionsLimit = 10000; - public textualSuggest(modelUrl: string, position: IPosition, wordDef: string, wordDefFlags: string): Promise { + public textualSuggest(modelUrl: string, position: IPosition, wordDef: string, wordDefFlags: string): Promise { const model = this._getModel(modelUrl); - if (model) { - const suggestions: CompletionItem[] = []; - const wordDefRegExp = new RegExp(wordDef, wordDefFlags); - const currentWord = model.getWordUntilPosition(position, wordDefRegExp); + if (!model) { + return Promise.resolve(null); + } - const seen: Record = Object.create(null); - seen[currentWord.word] = true; + const suggestions: CompletionItem[] = []; + const wordDefRegExp = new RegExp(wordDef, wordDefFlags); + const currentWord = model.getWordUntilPosition(position, wordDefRegExp); - for ( - let iter = model.createWordIterator(wordDefRegExp), e = iter.next(); - !e.done && suggestions.length <= BaseEditorSimpleWorker._suggestionsLimit; - e = iter.next() - ) { - const word = e.value; - if (seen[word]) { - continue; - } - seen[word] = true; - if (!isNaN(Number(word))) { - continue; - } + const seen: Record = Object.create(null); + seen[currentWord.word] = true; - suggestions.push({ - kind: CompletionItemKind.Text, - label: word, - insertText: word, - noAutoAccept: true, - range: { startLineNumber: position.lineNumber, startColumn: currentWord.startColumn, endLineNumber: position.lineNumber, endColumn: currentWord.endColumn } - }); + for ( + let iter = model.createWordIterator(wordDefRegExp), e = iter.next(); + !e.done && suggestions.length <= BaseEditorSimpleWorker._suggestionsLimit; + e = iter.next() + ) { + const word = e.value; + if (seen[word]) { + continue; + } + seen[word] = true; + if (!isNaN(Number(word))) { + continue; } - return Promise.resolve({ suggestions }); + suggestions.push({ + kind: CompletionItemKind.Text, + label: word, + insertText: word, + noAutoAccept: true, + range: { startLineNumber: position.lineNumber, startColumn: currentWord.startColumn, endLineNumber: position.lineNumber, endColumn: currentWord.endColumn } + }); } - return undefined; + + return Promise.resolve({ suggestions }); } @@ -527,10 +536,10 @@ export abstract class BaseEditorSimpleWorker { //#endregion - public navigateValueSet(modelUrl: string, range: IRange, up: boolean, wordDef: string, wordDefFlags: string): Promise { + public navigateValueSet(modelUrl: string, range: IRange, up: boolean, wordDef: string, wordDefFlags: string): Promise { let model = this._getModel(modelUrl); if (!model) { - return null; + return Promise.resolve(null); } let wordDefRegExp = new RegExp(wordDef, wordDefFlags); @@ -547,11 +556,10 @@ export abstract class BaseEditorSimpleWorker { let selectionText = model.getValueInRange(range); let wordRange = model.getWordAtPosition({ lineNumber: range.startLineNumber, column: range.startColumn }, wordDefRegExp); - let word: string | null = null; - if (wordRange !== null) { - word = model.getValueInRange(wordRange); + if (!wordRange) { + return Promise.resolve(null); } - + let word = model.getValueInRange(wordRange); let result = BasicInplaceReplace.INSTANCE.navigateValueSet(range, selectionText, wordRange, word, up); return Promise.resolve(result); } @@ -623,7 +631,7 @@ export class EditorSimpleWorkerImpl extends BaseEditorSimpleWorker implements IR private _models: { [uri: string]: MirrorModel; }; - constructor(foreignModuleFactory: IForeignModuleFactory) { + constructor(foreignModuleFactory: IForeignModuleFactory | null) { super(foreignModuleFactory); this._models = Object.create(null); } diff --git a/src/vs/editor/common/services/editorWorkerService.ts b/src/vs/editor/common/services/editorWorkerService.ts index ff2fa9eb212..41ebb158571 100644 --- a/src/vs/editor/common/services/editorWorkerService.ts +++ b/src/vs/editor/common/services/editorWorkerService.ts @@ -16,16 +16,16 @@ export interface IEditorWorkerService { _serviceBrand: any; canComputeDiff(original: URI, modified: URI): boolean; - computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise; + computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise; canComputeDirtyDiff(original: URI, modified: URI): boolean; - computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise; + computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise; computeMoreMinimalEdits(resource: URI, edits: TextEdit[]): Promise; canComputeWordRanges(resource: URI): boolean; - computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] }>; + computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null>; canNavigateValueSet(resource: URI): boolean; - navigateValueSet(resource: URI, range: IRange, up: boolean): Promise; + navigateValueSet(resource: URI, range: IRange, up: boolean): Promise; } diff --git a/src/vs/editor/common/services/editorWorkerServiceImpl.ts b/src/vs/editor/common/services/editorWorkerServiceImpl.ts index db899de6fdb..381e9c90256 100644 --- a/src/vs/editor/common/services/editorWorkerServiceImpl.ts +++ b/src/vs/editor/common/services/editorWorkerServiceImpl.ts @@ -75,7 +75,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker return (canSyncModel(this._modelService, original) && canSyncModel(this._modelService, modified)); } - public computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { + public computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { return this._workerManager.withWorker().then(client => client.computeDiff(original, modified, ignoreTrimWhitespace)); } @@ -83,7 +83,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker return (canSyncModel(this._modelService, original) && canSyncModel(this._modelService, modified)); } - public computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { + public computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { return this._workerManager.withWorker().then(client => client.computeDirtyDiff(original, modified, ignoreTrimWhitespace)); } @@ -102,7 +102,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker return (canSyncModel(this._modelService, resource)); } - public navigateValueSet(resource: URI, range: IRange, up: boolean): Promise { + public navigateValueSet(resource: URI, range: IRange, up: boolean): Promise { return this._workerManager.withWorker().then(client => client.navigateValueSet(resource, range, up)); } @@ -110,7 +110,7 @@ export class EditorWorkerServiceImpl extends Disposable implements IEditorWorker return canSyncModel(this._modelService, resource); } - computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] }> { + computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null> { return this._workerManager.withWorker().then(client => client.computeWordRanges(resource, range)); } } @@ -131,7 +131,7 @@ class WordBasedCompletionItemProvider implements modes.CompletionItemProvider { this._modelService = modelService; } - provideCompletionItems(model: ITextModel, position: Position): Promise { + provideCompletionItems(model: ITextModel, position: Position): Promise | undefined { const { wordBasedSuggestions } = this._configurationService.getValue(model.uri, position, 'editor'); if (!wordBasedSuggestions) { return undefined; @@ -146,7 +146,7 @@ class WordBasedCompletionItemProvider implements modes.CompletionItemProvider { class WorkerManager extends Disposable { private _modelService: IModelService; - private _editorWorkerClient: EditorWorkerClient; + private _editorWorkerClient: EditorWorkerClient | null; private _lastWorkerUsedTime: number; constructor(modelService: IModelService) { @@ -322,8 +322,6 @@ class SynchronousWorkerClient implements IWorkerClient public dispose(): void { this._instance.dispose(); - this._instance = null; - this._proxyObj = null; } public getProxyObject(): Promise { @@ -334,11 +332,11 @@ class SynchronousWorkerClient implements IWorkerClient export class EditorWorkerClient extends Disposable { private _modelService: IModelService; - private _worker: IWorkerClient; + private _worker: IWorkerClient | null; private _workerFactory: DefaultWorkerFactory; - private _modelManager: EditorModelManager; + private _modelManager: EditorModelManager | null; - constructor(modelService: IModelService, label: string) { + constructor(modelService: IModelService, label: string | undefined) { super(); this._modelService = modelService; this._workerFactory = new DefaultWorkerFactory(label); @@ -383,13 +381,13 @@ export class EditorWorkerClient extends Disposable { }); } - public computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { + public computeDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { return this._withSyncedResources([original, modified]).then(proxy => { return proxy.computeDiff(original.toString(), modified.toString(), ignoreTrimWhitespace); }); } - public computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { + public computeDirtyDiff(original: URI, modified: URI, ignoreTrimWhitespace: boolean): Promise { return this._withSyncedResources([original, modified]).then(proxy => { return proxy.computeDirtyDiff(original.toString(), modified.toString(), ignoreTrimWhitespace); }); @@ -401,13 +399,13 @@ export class EditorWorkerClient extends Disposable { }); } - public computeLinks(resource: URI): Promise { + public computeLinks(resource: URI): Promise { return this._withSyncedResources([resource]).then(proxy => { return proxy.computeLinks(resource.toString()); }); } - public textualSuggest(resource: URI, position: IPosition): Promise { + public textualSuggest(resource: URI, position: IPosition): Promise { return this._withSyncedResources([resource]).then(proxy => { let model = this._modelService.getModel(resource); if (!model) { @@ -420,11 +418,11 @@ export class EditorWorkerClient extends Disposable { }); } - computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] }> { + computeWordRanges(resource: URI, range: IRange): Promise<{ [word: string]: IRange[] } | null> { return this._withSyncedResources([resource]).then(proxy => { let model = this._modelService.getModel(resource); if (!model) { - return null; + return Promise.resolve(null); } let wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageIdentifier().id); let wordDef = wordDefRegExp.source; @@ -433,7 +431,7 @@ export class EditorWorkerClient extends Disposable { }); } - public navigateValueSet(resource: URI, range: IRange, up: boolean): Promise { + public navigateValueSet(resource: URI, range: IRange, up: boolean): Promise { return this._withSyncedResources([resource]).then(proxy => { let model = this._modelService.getModel(resource); if (!model) { diff --git a/src/vs/editor/common/services/languagesRegistry.ts b/src/vs/editor/common/services/languagesRegistry.ts index b782fea97a9..85428ccca5e 100644 --- a/src/vs/editor/common/services/languagesRegistry.ts +++ b/src/vs/editor/common/services/languagesRegistry.ts @@ -18,7 +18,7 @@ const hasOwnProperty = Object.prototype.hasOwnProperty; export interface IResolvedLanguage { identifier: LanguageIdentifier; - name: string; + name: string | null; mimetypes: string[]; aliases: string[]; extensions: string[]; @@ -85,7 +85,7 @@ export class LanguagesRegistry { private _registerLanguage(lang: ILanguageExtensionPoint): void { const langId = lang.id; - let resolvedLanguage: IResolvedLanguage | null = null; + let resolvedLanguage: IResolvedLanguage; if (hasOwnProperty.call(this._languages, langId)) { resolvedLanguage = this._languages[langId]; } else { @@ -159,7 +159,7 @@ export class LanguagesRegistry { resolvedLanguage.aliases.push(langId); - let langAliases: string[] | null = null; + let langAliases: (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 @@ -171,18 +171,19 @@ export class LanguagesRegistry { if (langAliases !== null) { for (let i = 0; i < langAliases.length; i++) { - if (!langAliases[i] || langAliases[i].length === 0) { + const langAlias = langAliases[i]; + if (!langAlias || langAlias.length === 0) { continue; } - resolvedLanguage.aliases.push(langAliases[i]); + resolvedLanguage.aliases.push(langAlias); } } let containsAliases = (langAliases !== null && langAliases.length > 0); - if (containsAliases && langAliases[0] === null) { + if (containsAliases && langAliases![0] === null) { // signal that this language should not get a name } else { - let bestName = (containsAliases ? langAliases[0] : null) || langId; + let bestName = (containsAliases ? langAliases![0] : null) || langId; if (containsAliases || !resolvedLanguage.name) { resolvedLanguage.name = bestName; } @@ -210,14 +211,14 @@ export class LanguagesRegistry { return Object.keys(this._nameMap); } - public getLanguageName(modeId: string): string { + public getLanguageName(modeId: string): string | null { if (!hasOwnProperty.call(this._languages, modeId)) { return null; } return this._languages[modeId].name; } - public getModeIdForLanguageNameLowercase(languageNameLower: string): string { + public getModeIdForLanguageNameLowercase(languageNameLower: string): string | null { if (!hasOwnProperty.call(this._lowercaseNameMap, languageNameLower)) { return null; } @@ -231,7 +232,7 @@ export class LanguagesRegistry { return this._languages[modeId].configurationFiles || []; } - public getMimeForMode(modeId: string): string { + public getMimeForMode(modeId: string): string | null { if (!hasOwnProperty.call(this._languages, modeId)) { return null; } @@ -260,7 +261,7 @@ export class LanguagesRegistry { ); } - public getLanguageIdentifier(_modeId: string | LanguageId): LanguageIdentifier { + public getLanguageIdentifier(_modeId: string | LanguageId): LanguageIdentifier | null { if (_modeId === NULL_MODE_ID || _modeId === LanguageId.Null) { return NULL_LANGUAGE_IDENTIFIER; } diff --git a/src/vs/editor/common/services/modeService.ts b/src/vs/editor/common/services/modeService.ts index b7d0b440561..46041b2b644 100644 --- a/src/vs/editor/common/services/modeService.ts +++ b/src/vs/editor/common/services/modeService.ts @@ -32,16 +32,16 @@ export interface IModeService { getRegisteredLanguageNames(): string[]; getExtensions(alias: string): string[]; getFilenames(alias: string): string[]; - getMimeForMode(modeId: string): string; - getLanguageName(modeId: string): string; - getModeIdForLanguageName(alias: string): string; - getModeIdByFilepathOrFirstLine(filepath: string, firstLine?: string): string; - getModeId(commaSeparatedMimetypesOrCommaSeparatedIds: string): string; - getLanguageIdentifier(modeId: string | LanguageId): LanguageIdentifier; + getMimeForMode(modeId: string): string | null; + getLanguageName(modeId: string): string | null; + getModeIdForLanguageName(alias: string): string | null; + getModeIdByFilepathOrFirstLine(filepath: string, firstLine?: string): string | null; + getModeId(commaSeparatedMimetypesOrCommaSeparatedIds: string): string | null; + getLanguageIdentifier(modeId: string | LanguageId): LanguageIdentifier | null; getConfigurationFiles(modeId: string): URI[]; // --- instantiation - getMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): IMode; + getMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): IMode | null; getOrCreateMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): Promise; getOrCreateModeByLanguageName(languageName: string): Promise; getOrCreateModeByFilepathOrFirstLine(filepath: string, firstLine?: string): Promise; diff --git a/src/vs/editor/common/services/modeServiceImpl.ts b/src/vs/editor/common/services/modeServiceImpl.ts index 61b1a81b9f0..73bed4eca50 100644 --- a/src/vs/editor/common/services/modeServiceImpl.ts +++ b/src/vs/editor/common/services/modeServiceImpl.ts @@ -10,6 +10,7 @@ import { FrankensteinMode } from 'vs/editor/common/modes/abstractMode'; import { LanguagesRegistry } from 'vs/editor/common/services/languagesRegistry'; import { IModeService } from 'vs/editor/common/services/modeService'; import { URI } from 'vs/base/common/uri'; +import { NULL_LANGUAGE_IDENTIFIER } from 'vs/editor/common/modes/nullMode'; export class ModeServiceImpl implements IModeService { public _serviceBrand: any; @@ -50,19 +51,19 @@ export class ModeServiceImpl implements IModeService { return this._registry.getFilenames(alias); } - public getMimeForMode(modeId: string): string { + public getMimeForMode(modeId: string): string | null { return this._registry.getMimeForMode(modeId); } - public getLanguageName(modeId: string): string { + public getLanguageName(modeId: string): string | null { return this._registry.getLanguageName(modeId); } - public getModeIdForLanguageName(alias: string): string { + public getModeIdForLanguageName(alias: string): string | null { return this._registry.getModeIdForLanguageNameLowercase(alias); } - public getModeIdByFilepathOrFirstLine(filepath: string, firstLine?: string): string { + public getModeIdByFilepathOrFirstLine(filepath: string, firstLine?: string): string | null { const modeIds = this._registry.getModeIdsFromFilepathOrFirstLine(filepath, firstLine); if (modeIds.length > 0) { @@ -72,7 +73,7 @@ export class ModeServiceImpl implements IModeService { return null; } - public getModeId(commaSeparatedMimetypesOrCommaSeparatedIds: string): string { + public getModeId(commaSeparatedMimetypesOrCommaSeparatedIds: string): string | null { const modeIds = this._registry.extractModeIds(commaSeparatedMimetypesOrCommaSeparatedIds); if (modeIds.length > 0) { @@ -82,7 +83,7 @@ export class ModeServiceImpl implements IModeService { return null; } - public getLanguageIdentifier(modeId: string | LanguageId): LanguageIdentifier { + public getLanguageIdentifier(modeId: string | LanguageId): LanguageIdentifier | null { return this._registry.getLanguageIdentifier(modeId); } @@ -92,7 +93,7 @@ export class ModeServiceImpl implements IModeService { // --- instantiation - public getMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): IMode { + public getMode(commaSeparatedMimetypesOrCommaSeparatedIds: string): IMode | null { const modeIds = this._registry.extractModeIds(commaSeparatedMimetypesOrCommaSeparatedIds); let isPlainText = false; @@ -130,7 +131,7 @@ export class ModeServiceImpl implements IModeService { }); } - private _getModeIdByLanguageName(languageName: string): string { + private _getModeIdByLanguageName(languageName: string): string | null { const modeIds = this._registry.getModeIdsFromLanguageName(languageName); if (modeIds.length > 0) { @@ -150,7 +151,7 @@ export class ModeServiceImpl implements IModeService { private _getOrCreateMode(modeId: string): IMode { if (!this._instantiatedModes.hasOwnProperty(modeId)) { - let languageIdentifier = this.getLanguageIdentifier(modeId); + let languageIdentifier = this.getLanguageIdentifier(modeId) || NULL_LANGUAGE_IDENTIFIER; this._instantiatedModes[modeId] = new FrankensteinMode(languageIdentifier); this._onDidCreateMode.fire(this._instantiatedModes[modeId]); diff --git a/src/vs/editor/common/services/modelService.ts b/src/vs/editor/common/services/modelService.ts index c9994204338..729f9264f48 100644 --- a/src/vs/editor/common/services/modelService.ts +++ b/src/vs/editor/common/services/modelService.ts @@ -26,7 +26,7 @@ export interface IModelService { getCreationOptions(language: string, resource: URI, isForSimpleWidget: boolean): ITextModelCreationOptions; - getModel(resource: URI): ITextModel; + getModel(resource: URI): ITextModel | null; onModelAdded: Event; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 301941c34d8..47704688916 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import * as network from 'vs/base/common/network'; import { Event, Emitter } from 'vs/base/common/event'; import { MarkdownString } from 'vs/base/common/htmlContent'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IMarker, IMarkerService, MarkerSeverity, MarkerTag } from 'vs/platform/markers/common/markers'; import { Range } from 'vs/editor/common/core/range'; @@ -55,7 +55,6 @@ class ModelData implements IDisposable { public dispose(): void { this._markerDecorations = this.model.deltaDecorations(this._markerDecorations, []); this._modelEventListeners = dispose(this._modelEventListeners); - this.model = null; } public acceptMarkerDecorations(newDecorations: IModelDeltaDecoration[]): void { @@ -126,9 +125,9 @@ class ModelMarkerHandler { private static _createDecorationOption(marker: IMarker): IModelDecorationOptions { let className: string; - let color: ThemeColor; + let color: ThemeColor | undefined = undefined; let zIndex: number; - let inlineClassName: string; + let inlineClassName: string | undefined = undefined; switch (marker.severity) { case MarkerSeverity.Hint: @@ -181,7 +180,7 @@ class ModelMarkerHandler { if (!isFalsyOrEmpty(relatedInformation)) { hoverMessage.appendMarkdown('\n'); - for (const { message, resource, startLineNumber, startColumn } of relatedInformation) { + for (const { message, resource, startLineNumber, startColumn } of relatedInformation!) { hoverMessage.appendMarkdown( `* [${basename(resource.path)}(${startLineNumber}, ${startColumn})](${resource.toString(false)}#${startLineNumber},${startColumn}): ` ); @@ -223,7 +222,7 @@ interface IRawConfig { const DEFAULT_EOL = (platform.isLinux || platform.isMacintosh) ? DefaultEndOfLine.LF : DefaultEndOfLine.CRLF; -export class ModelServiceImpl implements IModelService { +export class ModelServiceImpl extends Disposable implements IModelService { public _serviceBrand: any; private _markerService: IMarkerService; @@ -231,9 +230,14 @@ export class ModelServiceImpl implements IModelService { private _configurationService: IConfigurationService; private _configurationServiceSubscription: IDisposable; - private readonly _onModelAdded: Emitter; - private readonly _onModelRemoved: Emitter; - private readonly _onModelModeChanged: Emitter<{ model: ITextModel; oldModeId: string; }>; + private readonly _onModelAdded: Emitter = this._register(new Emitter()); + public readonly onModelAdded: Event = this._onModelAdded.event; + + private readonly _onModelRemoved: Emitter = this._register(new Emitter()); + public readonly onModelRemoved: Event = this._onModelRemoved.event; + + 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: { [languageAndResource: string]: ITextModelCreationOptions; @@ -248,13 +252,11 @@ export class ModelServiceImpl implements IModelService { @IMarkerService markerService: IMarkerService, @IConfigurationService configurationService: IConfigurationService, ) { + super(); this._markerService = markerService; this._configurationService = configurationService; this._models = {}; this._modelCreationOptionsByLanguageAndResource = Object.create(null); - this._onModelAdded = new Emitter(); - this._onModelRemoved = new Emitter(); - this._onModelModeChanged = new Emitter<{ model: ITextModel; oldModeId: string; }>(); if (this._markerService) { this._markerServiceSubscription = this._markerService.onMarkerChanged(this._handleMarkerChange, this); @@ -371,6 +373,7 @@ export class ModelServiceImpl implements IModelService { this._markerServiceSubscription.dispose(); } this._configurationServiceSubscription.dispose(); + super.dispose(); } private _handleMarkerChange(changedResources: URI[]): void { @@ -547,7 +550,7 @@ export class ModelServiceImpl implements IModelService { return ret; } - public getModel(resource: URI): ITextModel { + public getModel(resource: URI): ITextModel | null { let modelId = MODEL_ID(resource); let modelData = this._models[modelId]; if (!modelData) { @@ -556,18 +559,6 @@ export class ModelServiceImpl implements IModelService { return modelData.model; } - public get onModelAdded(): Event { - return this._onModelAdded ? this._onModelAdded.event : null; - } - - public get onModelRemoved(): Event { - return this._onModelRemoved ? this._onModelRemoved.event : null; - } - - public get onModelModeChanged(): Event<{ model: ITextModel; oldModeId: string; }> { - return this._onModelModeChanged ? this._onModelModeChanged.event : null; - } - // --- end IModelService private _onWillDispose(model: ITextModel): void { diff --git a/src/vs/editor/common/services/resourceConfigurationImpl.ts b/src/vs/editor/common/services/resourceConfigurationImpl.ts index c966623eafe..ff77e31a8de 100644 --- a/src/vs/editor/common/services/resourceConfigurationImpl.ts +++ b/src/vs/editor/common/services/resourceConfigurationImpl.ts @@ -31,16 +31,24 @@ export class TextResourceConfigurationService extends Disposable implements ITex getValue(resource: URI, section?: string): T; getValue(resource: URI, at?: IPosition, section?: string): T; getValue(resource: URI, arg2?: any, arg3?: any): T { - const position: IPosition = Position.isIPosition(arg2) ? arg2 : null; - const section: string = position ? (typeof arg3 === 'string' ? arg3 : void 0) : (typeof arg2 === 'string' ? arg2 : void 0); + if (typeof arg3 === 'string') { + return this._getValue(resource, Position.isIPosition(arg2) ? arg2 : null, arg3); + } + return this._getValue(resource, null, typeof arg2 === 'string' ? arg2 : undefined); + } + + private _getValue(resource: URI, position: IPosition | null, section: string | undefined): T { const language = resource ? this.getLanguage(resource, position) : void 0; + if (typeof section === 'undefined') { + return this.configurationService.getValue({ resource, overrideIdentifier: language }); + } return this.configurationService.getValue(section, { resource, overrideIdentifier: language }); } - private getLanguage(resource: URI, position: IPosition): string { + private getLanguage(resource: URI, position: IPosition | null): string | null { const model = this.modelService.getModel(resource); if (model) { - return position ? this.modeService.getLanguageIdentifier(model.getLanguageIdAtPosition(position.lineNumber, position.column)).language : model.getLanguageIdentifier().language; + return position ? this.modeService.getLanguageIdentifier(model.getLanguageIdAtPosition(position.lineNumber, position.column))!.language : model.getLanguageIdentifier().language; } return this.modeService.getModeIdByFilepathOrFirstLine(resource.path); diff --git a/src/vs/editor/common/services/webWorker.ts b/src/vs/editor/common/services/webWorker.ts index f0c97ae56a4..0ad1542e042 100644 --- a/src/vs/editor/common/services/webWorker.ts +++ b/src/vs/editor/common/services/webWorker.ts @@ -53,8 +53,8 @@ export interface IWebWorkerOptions { class MonacoWebWorkerImpl extends EditorWorkerClient implements MonacoWebWorker { private _foreignModuleId: string; - private _foreignModuleCreateData: any; - private _foreignProxy: Promise; + private _foreignModuleCreateData: any | null; + private _foreignProxy: Promise | null; constructor(modelService: IModelService, opts: IWebWorkerOptions) { super(modelService, opts.label); @@ -67,7 +67,6 @@ class MonacoWebWorkerImpl extends EditorWorkerClient implements MonacoWebWork if (!this._foreignProxy) { this._foreignProxy = this._getProxy().then((proxy) => { return proxy.loadForeignModule(this._foreignModuleId, this._foreignModuleCreateData).then((foreignMethods) => { - this._foreignModuleId = null; this._foreignModuleCreateData = null; let proxyMethodRequest = (method: string, args: any[]): Promise => { diff --git a/src/vs/editor/common/view/viewEventDispatcher.ts b/src/vs/editor/common/view/viewEventDispatcher.ts index f36e8d69535..0b784b3234f 100644 --- a/src/vs/editor/common/view/viewEventDispatcher.ts +++ b/src/vs/editor/common/view/viewEventDispatcher.ts @@ -10,7 +10,7 @@ export class ViewEventDispatcher { private _eventHandlerGateKeeper: (callback: () => void) => void; private _eventHandlers: ViewEventHandler[]; - private _eventQueue: ViewEvent[]; + private _eventQueue: ViewEvent[] | null; private _isConsumingQueue: boolean; constructor(eventHandlerGateKeeper: (callback: () => void) => void) { diff --git a/src/vs/editor/common/viewLayout/linesLayout.ts b/src/vs/editor/common/viewLayout/linesLayout.ts index bdc0107c668..2d6666bc098 100644 --- a/src/vs/editor/common/viewLayout/linesLayout.ts +++ b/src/vs/editor/common/viewLayout/linesLayout.ts @@ -401,7 +401,7 @@ export class LinesLayout { * @param verticalOffset The vertical offset. * @return Precisely the whitespace that is layouted at `verticaloffset` or null. */ - public getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData { + public getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData | null { verticalOffset = verticalOffset | 0; let candidateIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset); diff --git a/src/vs/editor/common/viewLayout/viewLayout.ts b/src/vs/editor/common/viewLayout/viewLayout.ts index e30111c16c2..37219081443 100644 --- a/src/vs/editor/common/viewLayout/viewLayout.ts +++ b/src/vs/editor/common/viewLayout/viewLayout.ts @@ -192,7 +192,7 @@ export class ViewLayout extends Disposable implements IViewLayout { return this._linesLayout.getLineNumberAtOrAfterVerticalOffset(verticalOffset); } - public getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData { + public getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData | null { return this._linesLayout.getWhitespaceAtVerticalOffset(verticalOffset); } public getLinesViewportData(): IPartialViewLinesViewportData { diff --git a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts index 6998c734192..f9d6cf5625e 100644 --- a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts +++ b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts @@ -74,7 +74,7 @@ export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactor return currentVisibleColumn + columnSize; } - public createLineMapping(lineText: string, tabSize: number, breakingColumn: number, columnsForFullWidthChar: number, hardWrappingIndent: WrappingIndent): ILineMapping { + public createLineMapping(lineText: string, tabSize: number, breakingColumn: number, columnsForFullWidthChar: number, hardWrappingIndent: WrappingIndent): ILineMapping | null { if (breakingColumn === -1) { return null; } diff --git a/src/vs/editor/common/viewModel/splitLinesCollection.ts b/src/vs/editor/common/viewModel/splitLinesCollection.ts index 84e5248438c..80f022d25e8 100644 --- a/src/vs/editor/common/viewModel/splitLinesCollection.ts +++ b/src/vs/editor/common/viewModel/splitLinesCollection.ts @@ -33,7 +33,7 @@ export interface ILineMapping { } export interface ILineMapperFactory { - createLineMapping(lineText: string, tabSize: number, wrappingColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent): ILineMapping; + createLineMapping(lineText: string, tabSize: number, wrappingColumn: number, columnsForFullWidthChar: number, wrappingIndent: WrappingIndent): ILineMapping | null; } export interface ISimpleModel { @@ -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[]): void; + getViewLinesData(model: ISimpleModel, modelLineNumber: number, fromOuputLineIndex: number, toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: (ViewLineData | null)[]): void; getModelColumnOfViewPosition(outputLineIndex: number, outputColumn: number): number; getViewPositionOfModelPosition(deltaLineNumber: number, inputColumn: number): Position; @@ -73,9 +73,9 @@ export interface IViewModelLinesCollection { setHiddenAreas(_ranges: Range[]): boolean; onModelFlushed(): void; - onModelLinesDeleted(versionId: number, fromLineNumber: number, toLineNumber: number): viewEvents.ViewLinesDeletedEvent; - onModelLinesInserted(versionId: number, fromLineNumber: number, toLineNumber: number, text: string[]): viewEvents.ViewLinesInsertedEvent; - onModelLineChanged(versionId: number, lineNumber: number, newText: string): [boolean, viewEvents.ViewLinesChangedEvent, viewEvents.ViewLinesInsertedEvent, viewEvents.ViewLinesDeletedEvent]; + onModelLinesDeleted(versionId: number, fromLineNumber: number, toLineNumber: number): viewEvents.ViewLinesDeletedEvent | null; + onModelLinesInserted(versionId: number, fromLineNumber: number, toLineNumber: number, text: string[]): viewEvents.ViewLinesInsertedEvent | null; + onModelLineChanged(versionId: number, lineNumber: number, newText: string): [boolean, viewEvents.ViewLinesChangedEvent | null, viewEvents.ViewLinesInsertedEvent | null, viewEvents.ViewLinesDeletedEvent | null]; acceptVersionId(versionId: number): void; getViewLineCount(): number; @@ -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[]; + getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): (ViewLineData | null)[]; getAllOverviewRulerDecorations(ownerId: number, filterOutValidation: boolean, theme: ITheme): IOverviewRulerDecorations; getDecorationsInRange(range: Range, ownerId: number, filterOutValidation: boolean): IModelDecoration[]; @@ -207,7 +207,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { let lineCount = linesContent.length; let values = new Uint32Array(lineCount); - let hiddenAreas = this.hiddenAreasIds.map((areaId) => this.model.getDecorationRange(areaId)).sort(Range.compareRangesUsingStarts); + let hiddenAreas = this.hiddenAreasIds.map((areaId) => this.model.getDecorationRange(areaId)!).sort(Range.compareRangesUsingStarts); let hiddenAreaStart = 1, hiddenAreaEnd = 0; let hiddenAreaIdx = -1; let nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : lineCount + 2; @@ -217,8 +217,8 @@ export class SplitLinesCollection implements IViewModelLinesCollection { if (lineNumber === nextLineNumberToUpdateHiddenArea) { hiddenAreaIdx++; - hiddenAreaStart = hiddenAreas[hiddenAreaIdx].startLineNumber; - hiddenAreaEnd = hiddenAreas[hiddenAreaIdx].endLineNumber; + hiddenAreaStart = hiddenAreas[hiddenAreaIdx]!.startLineNumber; + hiddenAreaEnd = hiddenAreas[hiddenAreaIdx]!.endLineNumber; nextLineNumberToUpdateHiddenArea = (hiddenAreaIdx + 1 < hiddenAreas.length) ? hiddenAreaEnd + 1 : lineCount + 2; } @@ -235,7 +235,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { public getHiddenAreas(): Range[] { return this.hiddenAreasIds.map((decId) => { - return this.model.getDecorationRange(decId); + return this.model.getDecorationRange(decId)!; }); } @@ -269,7 +269,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { let newRanges = this._reduceRanges(_ranges); // BEGIN TODO@Martin: Please stop calling this method on each model change! - let oldRanges = this.hiddenAreasIds.map((areaId) => this.model.getDecorationRange(areaId)).sort(Range.compareRangesUsingStarts); + let oldRanges = this.hiddenAreasIds.map((areaId) => this.model.getDecorationRange(areaId)!).sort(Range.compareRangesUsingStarts); if (newRanges.length === oldRanges.length) { let hasDifference = false; @@ -377,7 +377,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { this._constructLines(true); } - public onModelLinesDeleted(versionId: number, fromLineNumber: number, toLineNumber: number): viewEvents.ViewLinesDeletedEvent { + public onModelLinesDeleted(versionId: number, fromLineNumber: number, toLineNumber: number): viewEvents.ViewLinesDeletedEvent | null { if (versionId <= this._validModelVersionId) { // Here we check for versionId in case the lines were reconstructed in the meantime. // We don't want to apply stale change events on top of a newer read model state. @@ -393,7 +393,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { return new viewEvents.ViewLinesDeletedEvent(outputFromLineNumber, outputToLineNumber); } - public onModelLinesInserted(versionId: number, fromLineNumber: number, _toLineNumber: number, text: string[]): viewEvents.ViewLinesInsertedEvent { + public onModelLinesInserted(versionId: number, fromLineNumber: number, _toLineNumber: number, text: string[]): viewEvents.ViewLinesInsertedEvent | null { if (versionId <= this._validModelVersionId) { // Here we check for versionId in case the lines were reconstructed in the meantime. // We don't want to apply stale change events on top of a newer read model state. @@ -433,7 +433,7 @@ export class SplitLinesCollection implements IViewModelLinesCollection { return new viewEvents.ViewLinesInsertedEvent(outputFromLineNumber, outputFromLineNumber + totalOutputLineCount - 1); } - public onModelLineChanged(versionId: number, lineNumber: number, newText: string): [boolean, viewEvents.ViewLinesChangedEvent, viewEvents.ViewLinesInsertedEvent, viewEvents.ViewLinesDeletedEvent] { + public onModelLineChanged(versionId: number, lineNumber: number, newText: string): [boolean, viewEvents.ViewLinesChangedEvent | null, viewEvents.ViewLinesInsertedEvent | null, viewEvents.ViewLinesDeletedEvent | null] { if (versionId <= this._validModelVersionId) { // Here we check for versionId in case the lines were reconstructed in the meantime. // We don't want to apply stale change events on top of a newer read model state. @@ -922,7 +922,7 @@ class VisibleIdentitySplitLine implements ISplitLine { ); } - public getViewLinesData(model: ISimpleModel, modelLineNumber: number, _fromOuputLineIndex: number, _toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: ViewLineData[]): void { + public getViewLinesData(model: ISimpleModel, modelLineNumber: number, _fromOuputLineIndex: number, _toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: (ViewLineData | null)[]): void { if (!needed[globalStartIndex]) { result[globalStartIndex] = null; return; @@ -1136,7 +1136,7 @@ export class SplitLine implements ISplitLine { ); } - public getViewLinesData(model: ITextModel, modelLineNumber: number, fromOuputLineIndex: number, toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: ViewLineData[]): void { + public getViewLinesData(model: ITextModel, modelLineNumber: number, fromOuputLineIndex: number, toOutputLineIndex: number, globalStartIndex: number, needed: boolean[], result: (ViewLineData | null)[]): void { if (!this._isVisible) { throw new Error('Not supported'); } @@ -1293,15 +1293,15 @@ export class IdentityLinesCollection implements IViewModelLinesCollection { public onModelFlushed(): void { } - public onModelLinesDeleted(_versionId: number, fromLineNumber: number, toLineNumber: number): viewEvents.ViewLinesDeletedEvent { + public onModelLinesDeleted(_versionId: number, fromLineNumber: number, toLineNumber: number): viewEvents.ViewLinesDeletedEvent | null { return new viewEvents.ViewLinesDeletedEvent(fromLineNumber, toLineNumber); } - public onModelLinesInserted(_versionId: number, fromLineNumber: number, toLineNumber: number, _text: string[]): viewEvents.ViewLinesInsertedEvent { + public onModelLinesInserted(_versionId: number, fromLineNumber: number, toLineNumber: number, _text: string[]): viewEvents.ViewLinesInsertedEvent | null { return new viewEvents.ViewLinesInsertedEvent(fromLineNumber, toLineNumber); } - public onModelLineChanged(_versionId: number, lineNumber: number, _newText: string): [boolean, viewEvents.ViewLinesChangedEvent, viewEvents.ViewLinesInsertedEvent, viewEvents.ViewLinesDeletedEvent] { + public onModelLineChanged(_versionId: number, lineNumber: number, _newText: string): [boolean, viewEvents.ViewLinesChangedEvent | null, viewEvents.ViewLinesInsertedEvent | null, viewEvents.ViewLinesDeletedEvent | null] { return [false, new viewEvents.ViewLinesChangedEvent(lineNumber, lineNumber), null, null]; } @@ -1360,12 +1360,12 @@ export class IdentityLinesCollection implements IViewModelLinesCollection { ); } - public getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): ViewLineData[] { + public getViewLinesData(viewStartLineNumber: number, viewEndLineNumber: number, needed: boolean[]): (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[] = []; + let result: (ViewLineData | null)[] = []; for (let lineNumber = viewStartLineNumber; lineNumber <= viewEndLineNumber; lineNumber++) { let idx = lineNumber - viewStartLineNumber; if (!needed[idx]) { diff --git a/src/vs/editor/common/viewModel/viewModel.ts b/src/vs/editor/common/viewModel/viewModel.ts index 56a55a307b0..602483c89d9 100644 --- a/src/vs/editor/common/viewModel/viewModel.ts +++ b/src/vs/editor/common/viewModel/viewModel.ts @@ -66,7 +66,7 @@ export interface IViewLayout { isAfterLines(verticalOffset: number): boolean; getLineNumberAtVerticalOffset(verticalOffset: number): number; getVerticalOffsetForLineNumber(lineNumber: number): number; - getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData; + getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData | null; // --------------- Begin vertical whitespace management @@ -149,16 +149,16 @@ export interface IViewModel { deduceModelPositionRelativeToViewPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position; getEOL(): string; getPlainTextToCopy(ranges: Range[], emptySelectionClipboard: boolean, forceCRLF: boolean): string | string[]; - getHTMLToCopy(ranges: Range[], emptySelectionClipboard: boolean): string; + getHTMLToCopy(ranges: Range[], emptySelectionClipboard: boolean): string | null; } export class MinimapLinesRenderingData { public readonly tabSize: number; - public readonly data: ViewLineData[]; + public readonly data: (ViewLineData | null)[]; constructor( tabSize: number, - data: ViewLineData[] + data: (ViewLineData | null)[] ) { this.tabSize = tabSize; this.data = data; diff --git a/src/vs/editor/common/viewModel/viewModelDecorations.ts b/src/vs/editor/common/viewModel/viewModelDecorations.ts index 94e0d106cf9..abac42d2ecc 100644 --- a/src/vs/editor/common/viewModel/viewModelDecorations.ts +++ b/src/vs/editor/common/viewModel/viewModelDecorations.ts @@ -32,8 +32,8 @@ export class ViewModelDecorations implements IDisposable { private _decorationsCache: { [decorationId: string]: ViewModelDecoration; }; - private _cachedModelDecorationsResolver: IDecorationsViewportData; - private _cachedModelDecorationsResolverViewRange: Range; + private _cachedModelDecorationsResolver: IDecorationsViewportData | null; + private _cachedModelDecorationsResolverViewRange: Range | null; constructor(editorId: number, model: ITextModel, configuration: editorCommon.IConfiguration, linesCollection: IViewModelLinesCollection, coordinatesConverter: ICoordinatesConverter) { this.editorId = editorId; @@ -51,7 +51,7 @@ export class ViewModelDecorations implements IDisposable { } public dispose(): void { - this._decorationsCache = null; + this._decorationsCache = Object.create(null); this._clearCachedModelDecorationsResolver(); } @@ -99,7 +99,7 @@ export class ViewModelDecorations implements IDisposable { this._cachedModelDecorationsResolver = this._getDecorationsViewportData(viewRange); this._cachedModelDecorationsResolverViewRange = viewRange; } - return this._cachedModelDecorationsResolver; + return this._cachedModelDecorationsResolver!; } private _getDecorationsViewportData(viewportRange: Range): IDecorationsViewportData { diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index d2e0cd8deda..ec5227de86b 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -33,7 +33,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel private readonly model: ITextModel; private hasFocus: boolean; private viewportStartLine: number; - private viewportStartLineTrackedRange: string; + private viewportStartLineTrackedRange: string | null; private viewportStartLineDelta: number; private readonly lines: IViewModelLinesCollection; public readonly coordinatesConverter: ICoordinatesConverter; @@ -428,7 +428,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel private _reduceRestoreStateCompatibility(state: editorCommon.IViewState): { scrollLeft: number; scrollTop: number; } { return { scrollLeft: state.scrollLeft, - scrollTop: state.scrollTopWithoutViewZones + scrollTop: state.scrollTopWithoutViewZones! }; } @@ -617,7 +617,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel return result.length === 1 ? result[0] : result; } - public getHTMLToCopy(viewRanges: Range[], emptySelectionClipboard: boolean): string { + public getHTMLToCopy(viewRanges: Range[], emptySelectionClipboard: boolean): string | null { if (this.model.getLanguageIdentifier().id === LanguageId.PlainText) { return null; } @@ -683,9 +683,11 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel private _getColorMap(): string[] { let colorMap = TokenizationRegistry.getColorMap(); - let result: string[] = [null]; - for (let i = 1, len = colorMap.length; i < len; i++) { - result[i] = Color.Format.CSS.formatHex(colorMap[i]); + let result: string[] = ['#000000']; + if (colorMap) { + for (let i = 1, len = colorMap.length; i < len; i++) { + result[i] = Color.Format.CSS.formatHex(colorMap[i]); + } } return result; } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index df8acc21d1c..1a3e59fcdde 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -620,7 +620,7 @@ declare namespace monaco { /** * Test if this range equals other. */ - equalsRange(other: IRange): boolean; + equalsRange(other: IRange | null): boolean; /** * Test if range `a` equals `b`. */ @@ -1198,7 +1198,7 @@ declare namespace monaco.editor { * CSS color to render in the overview ruler. * e.g.: rgba(100, 100, 100, 0.5) or a color from the color registry */ - color: string | ThemeColor; + color: string | ThemeColor | undefined; /** * CSS color to render in the overview ruler. * e.g.: rgba(100, 100, 100, 0.5) or a color from the color registry @@ -5094,11 +5094,15 @@ declare namespace monaco.languages { provideDocumentSymbols(model: editor.ITextModel, token: CancellationToken): ProviderResult; } - export interface TextEdit { + export type TextEdit = { range: IRange; text: string; eol?: editor.EndOfLineSequence; - } + } | { + range: undefined; + text: undefined; + eol: editor.EndOfLineSequence; + }; /** * Interface used to format a model diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index d3fa4674483..8dbe9b65055 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -23,7 +23,7 @@ export function isConfigurationOverrides(thing: any): thing is IConfigurationOve } export interface IConfigurationOverrides { - overrideIdentifier?: string; + overrideIdentifier?: string | null; resource?: URI; } @@ -126,7 +126,7 @@ export interface IConfigurationData { export function compare(from: IConfigurationModel, to: IConfigurationModel): { added: string[], removed: string[], updated: string[] } { const added = to.keys.filter(key => from.keys.indexOf(key) === -1); const removed = from.keys.filter(key => to.keys.indexOf(key) === -1); - const updated = []; + const updated: string[] = []; for (const key of from.keys) { const value1 = getConfigurationValue(from.contents, key); @@ -171,7 +171,7 @@ export function toValuesTree(properties: { [qualifiedKey: string]: any }, confli export function addToValueTree(settingsTreeRoot: any, key: string, value: any, conflictReporter: (message: string) => void): void { const segments = key.split('.'); - const last = segments.pop(); + const last = segments.pop()!; let curr = settingsTreeRoot; for (let i = 0; i < segments.length; i++) { @@ -203,7 +203,7 @@ export function removeFromValueTree(valueTree: any, key: string): void { } function doRemoveFromValueTree(valueTree: any, segments: string[]): void { - const first = segments.shift(); + const first = segments.shift()!; if (segments.length === 0) { // Reached last segment delete valueTree[first]; diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 5c450325893..18f9c6084db 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -161,7 +161,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { this.updateOverridePropertyPatternKey(); } - private toConfiguration(defaultConfigurations: IDefaultConfigurationExtension[]): IConfigurationNode { + private toConfiguration(defaultConfigurations: IDefaultConfigurationExtension[]): IConfigurationNode | null { const configurationNode: IConfigurationNode = { id: 'defaultOverrides', title: nls.localize('defaultConfigurations.title', "Default Configuration Overrides"), @@ -171,7 +171,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { for (const key in defaultConfiguration.defaults) { const defaultValue = defaultConfiguration.defaults[key]; if (OVERRIDE_PROPERTY_PATTERN.test(key) && typeof defaultValue === 'object') { - configurationNode.properties[key] = { + configurationNode.properties![key] = { type: 'object', default: defaultValue, description: nls.localize('overrideSettings.description', "Configure editor settings to be overridden for {0} language.", key), @@ -180,13 +180,13 @@ class ConfigurationRegistry implements IConfigurationRegistry { } } } - return Object.keys(configurationNode.properties).length ? configurationNode : null; + return Object.keys(configurationNode.properties!).length ? configurationNode : null; } private validateAndRegisterProperties(configuration: IConfigurationNode, validate: boolean = true, scope: ConfigurationScope = ConfigurationScope.WINDOW, overridable: boolean = false): string[] { scope = types.isUndefinedOrNull(configuration.scope) ? scope : configuration.scope; overridable = configuration.overridable || overridable; - let propertyKeys = []; + let propertyKeys: string[] = []; let properties = configuration.properties; if (properties) { for (let key in properties) { @@ -313,7 +313,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { if (properties) { for (let key in properties) { if (properties[key].overridable) { - this.editorConfigurationSchema.properties[key] = this.getConfigurationProperties()[key]; + this.editorConfigurationSchema.properties![key] = this.getConfigurationProperties()[key]; } } } @@ -333,7 +333,7 @@ const OVERRIDE_PROPERTY = '\\[.*\\]$'; const OVERRIDE_PATTERN_WITH_SUBSTITUTION = '\\[(${0})\\]$'; export const OVERRIDE_PROPERTY_PATTERN = new RegExp(OVERRIDE_PROPERTY); -function getDefaultValue(type: string | string[]): any { +function getDefaultValue(type: string | string[] | undefined): any { const t = Array.isArray(type) ? (type)[0] : type; switch (t) { case 'boolean': @@ -356,7 +356,7 @@ function getDefaultValue(type: string | string[]): any { const configurationRegistry = new ConfigurationRegistry(); Registry.add(Extensions.Configuration, configurationRegistry); -export function validateProperty(property: string): string { +export function validateProperty(property: string): string | null { if (OVERRIDE_PROPERTY_PATTERN.test(property)) { return nls.localize('config.property.languageDefault', "Cannot register '{0}'. This matches property pattern '\\\\[.*\\\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.", property); } diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index 9a185a68f15..78a8bd74f86 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -17,7 +17,7 @@ export type ColorIdentifier = string; export interface ColorContribution { readonly id: ColorIdentifier; readonly description: string; - readonly defaults: ColorDefaults; + readonly defaults: ColorDefaults | null; readonly needsTransparency: boolean; readonly deprecationMessage: string | undefined; } @@ -86,7 +86,7 @@ class ColorRegistry implements IColorRegistry { this.colorsById = {}; } - public registerColor(id: string, defaults: ColorDefaults, description: string, needsTransparency = false, deprecationMessage?: string): ColorIdentifier { + public registerColor(id: string, defaults: ColorDefaults | null, description: string, needsTransparency = false, deprecationMessage?: string): ColorIdentifier { let colorContribution: ColorContribution = { id, description, defaults, needsTransparency, deprecationMessage }; this.colorsById[id] = colorContribution; let propertySchema: IJSONSchema = { type: 'string', description, format: 'color-hex', default: '#ff0000' }; @@ -138,7 +138,7 @@ class ColorRegistry implements IColorRegistry { const colorRegistry = new ColorRegistry(); platform.Registry.add(Extensions.ColorContribution, colorRegistry); -export function registerColor(id: string, defaults: ColorDefaults, description: string, needsTransparency?: boolean, deprecationMessage?: string): ColorIdentifier { +export function registerColor(id: string, defaults: ColorDefaults | null, description: string, needsTransparency?: boolean, deprecationMessage?: string): ColorIdentifier { return colorRegistry.registerColor(id, defaults, description, needsTransparency, deprecationMessage); } diff --git a/src/vs/platform/workspace/common/workspace.ts b/src/vs/platform/workspace/common/workspace.ts index dbedcbd5f6b..c40ac0382ab 100644 --- a/src/vs/platform/workspace/common/workspace.ts +++ b/src/vs/platform/workspace/common/workspace.ts @@ -99,7 +99,7 @@ export interface IWorkspace { /** * the location of the workspace configuration */ - readonly configuration?: URI; + readonly configuration?: URI | null; } export interface IWorkspaceFolderData { @@ -171,19 +171,19 @@ export class Workspace implements IWorkspace { return this._id; } - get ctime(): number { + get ctime(): number | undefined { return this._ctime; } - get configuration(): URI { + get configuration(): URI | null { return this._configuration; } - set configuration(configuration: URI) { + set configuration(configuration: URI | null) { this._configuration = configuration; } - getFolder(resource: URI): IWorkspaceFolder { + getFolder(resource: URI): IWorkspaceFolder | null | undefined { if (!resource) { return null; } @@ -231,9 +231,9 @@ export function toWorkspaceFolders(configuredFolders: IStoredWorkspaceFolder[], .map(({ uri, raw, name }, index) => new WorkspaceFolder({ uri, name: name || resources.basenameOrAuthority(uri), index }, raw)); } -function parseWorkspaceFolders(configuredFolders: IStoredWorkspaceFolder[], relativeTo: URI): WorkspaceFolder[] { +function parseWorkspaceFolders(configuredFolders: IStoredWorkspaceFolder[], relativeTo: URI | undefined): (WorkspaceFolder | undefined)[] { return configuredFolders.map((configuredFolder, index) => { - let uri: URI; + let uri: URI | null = null; if (isRawFileWorkspaceFolder(configuredFolder)) { uri = toUri(configuredFolder.path, relativeTo); } else if (isRawUriWorkspaceFolder(configuredFolder)) { @@ -251,11 +251,11 @@ function parseWorkspaceFolders(configuredFolders: IStoredWorkspaceFolder[], rela if (!uri) { return void 0; } - return new WorkspaceFolder({ uri, name: configuredFolder.name, index }, configuredFolder); + return new WorkspaceFolder({ uri, name: configuredFolder.name! /*is ensured in caller*/, index }, configuredFolder); }); } -function toUri(path: string, relativeTo: URI): URI { +function toUri(path: string, relativeTo: URI | undefined): URI | null { if (path) { if (paths.isAbsolute(path)) { return URI.file(path);