diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 002a20d16bd..e2b158955ae 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -186,6 +186,8 @@ "./vs/editor/contrib/codeAction/codeActionTrigger.ts", "./vs/editor/contrib/codeAction/lightBulbWidget.ts", "./vs/editor/contrib/codelens/codelens.ts", + "./vs/editor/contrib/codelens/codelensController.ts", + "./vs/editor/contrib/codelens/codelensWidget.ts", "./vs/editor/contrib/colorPicker/color.ts", "./vs/editor/contrib/colorPicker/colorDetector.ts", "./vs/editor/contrib/colorPicker/colorPickerModel.ts", diff --git a/src/vs/editor/contrib/codelens/codelensController.ts b/src/vs/editor/contrib/codelens/codelensController.ts index 8e3665ec169..c75eb2498c5 100644 --- a/src/vs/editor/contrib/codelens/codelensController.ts +++ b/src/vs/editor/contrib/codelens/codelensController.ts @@ -27,9 +27,9 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { private _globalToDispose: IDisposable[]; private _localToDispose: IDisposable[]; private _lenses: CodeLens[]; - private _currentFindCodeLensSymbolsPromise: CancelablePromise; + private _currentFindCodeLensSymbolsPromise: CancelablePromise | null; private _modelChangeCounter: number; - private _currentResolveCodeLensSymbolsPromise: CancelablePromise; + private _currentResolveCodeLensSymbolsPromise: CancelablePromise | null; private _detectVisibleLenses: RunOnceScheduler; constructor( @@ -176,7 +176,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { scrollState.restore(this._editor); } else { // No accessors available - this._disposeAllLenses(null, null); + this._disposeAllLenses(void 0, void 0); } })); this._localToDispose.push(this._editor.onDidChangeConfiguration(e => { @@ -187,11 +187,11 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { } })); this._localToDispose.push(this._editor.onMouseUp(e => { - if (e.target.type === editorBrowser.MouseTargetType.CONTENT_WIDGET && e.target.element.tagName === 'A') { + if (e.target.type === editorBrowser.MouseTargetType.CONTENT_WIDGET && e.target.element && e.target.element.tagName === 'A') { for (const lens of this._lenses) { let command = lens.getCommand(e.target.element as HTMLLinkElement); if (command) { - this._commandService.executeCommand(command.id, ...command.arguments).catch(err => this._notificationService.error(err)); + this._commandService.executeCommand(command.id, ...(command.arguments || [])).catch(err => this._notificationService.error(err)); break; } } @@ -200,7 +200,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { scheduler.schedule(); } - private _disposeAllLenses(decChangeAccessor: IModelDecorationsChangeAccessor, viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor): void { + private _disposeAllLenses(decChangeAccessor: IModelDecorationsChangeAccessor | undefined, viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor | undefined): void { let helper = new CodeLensHelper(); this._lenses.forEach((lens) => lens.dispose(helper, viewZoneChangeAccessor)); if (decChangeAccessor) { @@ -210,13 +210,13 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { } private _renderCodeLensSymbols(symbols: ICodeLensData[]): void { - if (!this._editor.getModel()) { + if (!this._editor.hasModel()) { return; } let maxLineNumber = this._editor.getModel().getLineCount(); let groups: ICodeLensData[][] = []; - let lastGroup: ICodeLensData[]; + let lastGroup: ICodeLensData[] | undefined; for (let symbol of symbols) { let line = symbol.symbol.range.startLineNumber; @@ -307,7 +307,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution { const promises = toResolve.map((request, i) => { - const resolvedSymbols = new Array(request.length); + const resolvedSymbols = new Array(request.length); const promises = request.map((request, i) => { if (typeof request.provider.resolveCodeLens === 'function') { return Promise.resolve(request.provider.resolveCodeLens(model, request.symbol, token)).then(symbol => { diff --git a/src/vs/editor/contrib/codelens/codelensWidget.ts b/src/vs/editor/contrib/codelens/codelensWidget.ts index 300d6b5a06c..7ba3c9be7bf 100644 --- a/src/vs/editor/contrib/codelens/codelensWidget.ts +++ b/src/vs/editor/contrib/codelens/codelensWidget.ts @@ -95,9 +95,9 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget { } } - withCommands(symbols: ICodeLensSymbol[]): void { + withCommands(inSymbols: Array): void { this._commands = Object.create(null); - symbols = coalesce(symbols); + const symbols = coalesce(inSymbols); if (isFalsyOrEmpty(symbols)) { this._domNode.innerHTML = 'no commands'; return; @@ -105,16 +105,18 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget { let html: string[] = []; for (let i = 0; i < symbols.length; i++) { - let command = symbols[i].command; - let title = escape(command.title); - let part: string; - if (command.id) { - part = `${title}`; - this._commands[i] = command; - } else { - part = `${title}`; + const command = symbols[i].command; + if (command) { + const title = escape(command.title); + let part: string; + if (command.id) { + part = `${title}`; + this._commands[i] = command; + } else { + part = `${title}`; + } + html.push(part); } - html.push(part); } this._domNode.innerHTML = html.join(' | '); @@ -136,6 +138,9 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget { } setSymbolRange(range: Range): void { + if (!this._editor.hasModel()) { + return; + } const lineNumber = range.startLineNumber; const column = this._editor.getModel().getLineFirstNonWhitespaceColumn(lineNumber); this._widgetPosition = { @@ -206,7 +211,7 @@ export class CodeLens { this._data = data; this._decorationIds = new Array(this._data.length); - let range: Range; + let range: Range | undefined; this._data.forEach((codeLensData, i) => { helper.addDecoration({ @@ -222,16 +227,18 @@ export class CodeLens { } }); - this._contentWidget = new CodeLensContentWidget(editor, range); - this._viewZone = new CodeLensViewZone(range.startLineNumber - 1, updateCallback); + if (range) { + this._contentWidget = new CodeLensContentWidget(editor, range); + this._viewZone = new CodeLensViewZone(range.startLineNumber - 1, updateCallback); - this._viewZoneId = viewZoneChangeAccessor.addZone(this._viewZone); - this._editor.addContentWidget(this._contentWidget); + this._viewZoneId = viewZoneChangeAccessor.addZone(this._viewZone); + this._editor.addContentWidget(this._contentWidget); + } } - dispose(helper: CodeLensHelper, viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor): void { + dispose(helper: CodeLensHelper, viewZoneChangeAccessor?: editorBrowser.IViewZoneChangeAccessor): void { while (this._decorationIds.length) { - helper.removeDecoration(this._decorationIds.pop()); + helper.removeDecoration(this._decorationIds.pop()!); } if (viewZoneChangeAccessor) { viewZoneChangeAccessor.removeZone(this._viewZoneId); @@ -240,16 +247,20 @@ export class CodeLens { } isValid(): boolean { + if (!this._editor.hasModel()) { + return false; + } + const model = this._editor.getModel(); return this._decorationIds.some((id, i) => { - const range = this._editor.getModel().getDecorationRange(id); + const range = model.getDecorationRange(id); const symbol = this._data[i].symbol; - return range && Range.isEmpty(symbol.range) === range.isEmpty(); + return !!(range && Range.isEmpty(symbol.range) === range.isEmpty()); }); } updateCodeLensSymbols(data: ICodeLensData[], helper: CodeLensHelper): void { while (this._decorationIds.length) { - helper.removeDecoration(this._decorationIds.pop()); + helper.removeDecoration(this._decorationIds.pop()!); } this._data = data; this._decorationIds = new Array(this._data.length); @@ -261,7 +272,7 @@ export class CodeLens { }); } - computeIfNecessary(model: ITextModel): ICodeLensData[] { + computeIfNecessary(model: ITextModel): ICodeLensData[] | null { this._contentWidget.updateVisibility(); // trigger the fade in if (!this._contentWidget.isVisible()) { return null; @@ -269,12 +280,15 @@ export class CodeLens { // Read editor current state for (let i = 0; i < this._decorationIds.length; i++) { - this._data[i].symbol.range = model.getDecorationRange(this._decorationIds[i]); + const range = model.getDecorationRange(this._decorationIds[i]); + if (range) { + this._data[i].symbol.range = range; + } } return this._data; } - updateCommands(symbols: ICodeLensSymbol[]): void { + updateCommands(symbols: Array): void { this._contentWidget.withCommands(symbols); } @@ -287,22 +301,25 @@ export class CodeLens { } getLineNumber(): number { - const range = this._editor.getModel().getDecorationRange(this._decorationIds[0]); - if (range) { - return range.startLineNumber; + if (this._editor.hasModel()) { + const range = this._editor.getModel().getDecorationRange(this._decorationIds[0]); + if (range) { + return range.startLineNumber; + } } return -1; } update(viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor): void { - if (this.isValid()) { + if (this.isValid() && this._editor.hasModel()) { const range = this._editor.getModel().getDecorationRange(this._decorationIds[0]); + if (range) { + this._viewZone.afterLineNumber = range.startLineNumber - 1; + viewZoneChangeAccessor.layoutZone(this._viewZoneId); - this._viewZone.afterLineNumber = range.startLineNumber - 1; - viewZoneChangeAccessor.layoutZone(this._viewZoneId); - - this._contentWidget.setSymbolRange(range); - this._editor.layoutContentWidget(this._contentWidget); + this._contentWidget.setSymbolRange(range); + this._editor.layoutContentWidget(this._contentWidget); + } } } } diff --git a/src/vs/editor/contrib/documentSymbols/outlineModel.ts b/src/vs/editor/contrib/documentSymbols/outlineModel.ts index c3c2473bf5a..2e58a196724 100644 --- a/src/vs/editor/contrib/documentSymbols/outlineModel.ts +++ b/src/vs/editor/contrib/documentSymbols/outlineModel.ts @@ -49,7 +49,7 @@ export abstract class TreeElement { return id; } - static getElementById(id: string, element: TreeElement): TreeElement { + static getElementById(id: string, element: TreeElement): TreeElement | undefined { if (!id) { return undefined; } diff --git a/src/vs/editor/contrib/find/findModel.ts b/src/vs/editor/contrib/find/findModel.ts index 2375b532aea..59ab1deb7e9 100644 --- a/src/vs/editor/contrib/find/findModel.ts +++ b/src/vs/editor/contrib/find/findModel.ts @@ -131,7 +131,7 @@ export class FindModelBoundToEditorModel { // The find model is disposed during a find state changed event return; } - if (!this._editor.getModel()) { + if (!this._editor.hasModel()) { // The find model will be disposed momentarily return; } diff --git a/src/vs/editor/contrib/indentation/indentation.ts b/src/vs/editor/contrib/indentation/indentation.ts index 85963260837..f436a795573 100644 --- a/src/vs/editor/contrib/indentation/indentation.ts +++ b/src/vs/editor/contrib/indentation/indentation.ts @@ -461,7 +461,7 @@ export class AutoIndentOnPaste implements IEditorContribution { } // no model - if (!this.editor.getModel()) { + if (!this.editor.hasModel()) { return; } diff --git a/src/vs/workbench/common/editor/editorGroup.ts b/src/vs/workbench/common/editor/editorGroup.ts index ae5d6efed7e..be4baa64aa3 100644 --- a/src/vs/workbench/common/editor/editorGroup.ts +++ b/src/vs/workbench/common/editor/editorGroup.ts @@ -44,7 +44,7 @@ export interface ISerializedEditorGroup { id: number; editors: ISerializedEditorInput[]; mru: number[]; - preview: number; + preview?: number; } export function isSerializedEditorGroup(obj?: any): obj is ISerializedEditorGroup { @@ -94,8 +94,8 @@ export class EditorGroup extends Disposable { private mru: EditorInput[] = []; private mapResourceToEditorCount: ResourceMap = new ResourceMap(); - private preview: EditorInput; // editor in preview state - private active: EditorInput; // editor in active state + private preview: EditorInput | null; // editor in preview state + private active: EditorInput | null; // editor in active state private editorOpenPositioning: 'left' | 'right' | 'first' | 'last'; @@ -136,9 +136,9 @@ export class EditorGroup extends Disposable { return mru ? this.mru.slice(0) : this.editors.slice(0); } - getEditor(index: number): EditorInput; - getEditor(resource: URI): EditorInput; - getEditor(arg1: any): EditorInput { + getEditor(index: number): EditorInput | null; + getEditor(resource: URI): EditorInput | null; + getEditor(arg1: any): EditorInput | null { if (typeof arg1 === 'number') { return this.editors[arg1]; } @@ -159,7 +159,7 @@ export class EditorGroup extends Disposable { return null; } - get activeEditor(): EditorInput { + get activeEditor(): EditorInput | null { return this.active; } @@ -167,7 +167,7 @@ export class EditorGroup extends Disposable { return this.matches(this.active, editor); } - get previewEditor(): EditorInput { + get previewEditor(): EditorInput | null { return this.preview; } @@ -310,7 +310,7 @@ export class EditorGroup extends Disposable { } } - closeEditor(editor: EditorInput, openNext = true): number { + closeEditor(editor: EditorInput, openNext = true): number | undefined { const event = this.doCloseEditor(editor, openNext, false); if (event) { @@ -322,7 +322,7 @@ export class EditorGroup extends Disposable { return void 0; } - private doCloseEditor(editor: EditorInput, openNext: boolean, replaced: boolean): EditorCloseEvent { + private doCloseEditor(editor: EditorInput, openNext: boolean, replaced: boolean): EditorCloseEvent | null { const index = this.indexOf(editor); if (index === -1) { return null; // not found @@ -384,7 +384,9 @@ export class EditorGroup extends Disposable { // Optimize: close all non active editors first to produce less upstream work this.mru.filter(e => !this.matches(e, this.active)).forEach(e => this.closeEditor(e)); - this.closeEditor(this.active); + if (this.active) { + this.closeEditor(this.active); + } } moveEditor(editor: EditorInput, toIndex: number): void { @@ -455,7 +457,9 @@ export class EditorGroup extends Disposable { this._onDidEditorUnpin.fire(editor); // Close old preview editor if any - this.closeEditor(oldPreview); + if (oldPreview) { + this.closeEditor(oldPreview); + } } isPinned(editor: EditorInput): boolean; @@ -538,7 +542,7 @@ export class EditorGroup extends Disposable { } } - indexOf(candidate: EditorInput, editors = this.editors): number { + indexOf(candidate: EditorInput | null, editors = this.editors): number { if (!candidate) { return -1; } @@ -591,7 +595,7 @@ export class EditorGroup extends Disposable { this.mru.unshift(editor); } - private matches(editorA: EditorInput, editorB: EditorInput): boolean { + private matches(editorA: EditorInput | null, editorB: EditorInput | null): boolean { return !!editorA && !!editorB && editorA.matches(editorB); } @@ -615,7 +619,7 @@ export class EditorGroup extends Disposable { // from mru, active and preview if any. let serializableEditors: EditorInput[] = []; let serializedEditors: ISerializedEditorInput[] = []; - let serializablePreviewIndex: number; + let serializablePreviewIndex: number | undefined; this.editors.forEach(e => { let factory = registry.getEditorInputFactory(e.getTypeId()); if (factory) { @@ -667,6 +671,8 @@ export class EditorGroup extends Disposable { })); this.mru = data.mru.map(i => this.editors[i]); this.active = this.mru[0]; - this.preview = this.editors[data.preview]; + if (typeof data.preview === 'number') { + this.preview = this.editors[data.preview]; + } } } diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index 43578cf3350..620c08cf1aa 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -117,7 +117,7 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend } private onModelChanged(): void { - if (!this.editor.getModel()) { + if (!this.editor.hasModel()) { // model could have been disposed during the delay return; } diff --git a/src/vs/workbench/parts/snippets/electron-browser/insertSnippet.ts b/src/vs/workbench/parts/snippets/electron-browser/insertSnippet.ts index 908011350c6..015514b1913 100644 --- a/src/vs/workbench/parts/snippets/electron-browser/insertSnippet.ts +++ b/src/vs/workbench/parts/snippets/electron-browser/insertSnippet.ts @@ -65,7 +65,7 @@ class InsertSnippetAction extends EditorAction { const modeService = accessor.get(IModeService); const snippetService = accessor.get(ISnippetsService); - if (!editor.getModel()) { + if (!editor.hasModel()) { return undefined; }