From a5d63ae52e4f8cbfddba4dd8151d81834592e7ec Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 4 Mar 2019 15:53:55 -0800 Subject: [PATCH] Strict null work on tabsTitleControl --- src/tsconfig.strictNullChecks.json | 2 + .../parts/editor/noTabsTitleControl.ts | 26 +++++--- .../browser/parts/editor/tabsTitleControl.ts | 61 ++++++++++++------- src/vs/workbench/common/editor.ts | 2 +- 4 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index 7eb6cc2e03d..835e5e859a2 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -123,9 +123,11 @@ "./vs/workbench/browser/parts/editor/editorDropTarget.ts", "./vs/workbench/browser/parts/editor/editorPicker.ts", "./vs/workbench/browser/parts/editor/editorWidgets.ts", + "./vs/workbench/browser/parts/editor/noTabsTitleControl.ts", "./vs/workbench/browser/parts/editor/rangeDecorations.ts", "./vs/workbench/browser/parts/editor/resourceViewer.ts", "./vs/workbench/browser/parts/editor/sideBySideEditor.ts", + "./vs/workbench/browser/parts/editor/tabsTitleControl.ts", "./vs/workbench/browser/parts/editor/textDiffEditor.ts", "./vs/workbench/browser/parts/editor/textEditor.ts", "./vs/workbench/browser/parts/editor/textResourceEditor.ts", diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index 4e1e729e2b7..e250e63ab42 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -16,7 +16,7 @@ import { CLOSE_EDITOR_COMMAND_ID } from 'vs/workbench/browser/parts/editor/edito import { Color } from 'vs/base/common/color'; interface IRenderedEditorLabel { - editor: IEditorInput; + editor?: IEditorInput; pinned: boolean; } @@ -72,8 +72,16 @@ export class NoTabsTitleControl extends TitleControl { this._register(addDisposableListener(this.titleContainer, TouchEventType.Tap, (e: GestureEvent) => this.onTitleClick(e))); // Context Menu - this._register(addDisposableListener(this.titleContainer, EventType.CONTEXT_MENU, (e: Event) => this.onContextMenu(this.group.activeEditor, e, this.titleContainer))); - this._register(addDisposableListener(this.titleContainer, TouchEventType.Contextmenu, (e: Event) => this.onContextMenu(this.group.activeEditor, e, this.titleContainer))); + this._register(addDisposableListener(this.titleContainer, EventType.CONTEXT_MENU, (e: Event) => { + if (this.group.activeEditor) { + this.onContextMenu(this.group.activeEditor, e, this.titleContainer); + } + })); + this._register(addDisposableListener(this.titleContainer, TouchEventType.Contextmenu, (e: Event) => { + if (this.group.activeEditor) { + this.onContextMenu(this.group.activeEditor, e, this.titleContainer); + } + })); } private onTitleLabelClick(e: MouseEvent): void { @@ -95,7 +103,9 @@ export class NoTabsTitleControl extends TitleControl { if (e instanceof MouseEvent && e.button === 1 /* Middle Button */) { EventHelper.stop(e, true /* for https://github.com/Microsoft/vscode/issues/56715 */); - this.group.closeEditor(this.group.activeEditor); + if (this.group.activeEditor) { + this.group.closeEditor(this.group.activeEditor); + } } } @@ -167,7 +177,7 @@ export class NoTabsTitleControl extends TitleControl { if ( !this.activeLabel.editor && this.group.activeEditor || // active editor changed from null => editor this.activeLabel.editor && !this.group.activeEditor || // active editor changed from editor => null - !this.group.isActive(this.activeLabel.editor) // active editor changed from editorA => editorB + (!this.activeLabel.editor || !this.group.isActive(this.activeLabel.editor)) // active editor changed from editorA => editorB ) { fn(); @@ -197,10 +207,10 @@ export class NoTabsTitleControl extends TitleControl { private redraw(): void { const editor = this.group.activeEditor; - const isEditorPinned = this.group.isPinned(this.group.activeEditor); + const isEditorPinned = this.group.activeEditor ? this.group.isPinned(this.group.activeEditor) : false; const isGroupActive = this.accessor.activeGroup === this.group; - this.activeLabel = { editor, pinned: isEditorPinned }; + this.activeLabel = { editor: editor || undefined, pinned: isEditorPinned }; // Update Breadcrumbs if (this.breadcrumbsControl) { @@ -244,7 +254,7 @@ export class NoTabsTitleControl extends TitleControl { title = ''; // dont repeat what is already shown } - this.editorLabel.setResource({ name, description, resource: resource || undefined }, { title, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] }); + this.editorLabel.setResource({ name, description, resource: resource || undefined }, { title: typeof title === 'string' ? title : undefined, italic: !isEditorPinned, extraClasses: ['no-tabs', 'title-label'] }); if (isGroupActive) { this.editorLabel.element.style.color = this.getColor(TAB_ACTIVE_FOREGROUND); } else { diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index e2bfb8d2cd7..aa38992e096 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -212,7 +212,7 @@ export class TabsTitleControl extends TitleControl { if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { isLocalDragAndDrop = true; - const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier; + const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier; if (this.group.id === localDraggedEditor.groupId && this.group.getIndexOfEditor(localDraggedEditor.editor) === this.group.count - 1) { e.dataTransfer!.dropEffect = 'none'; return; @@ -469,7 +469,10 @@ export class TabsTitleControl extends TitleControl { } // Open tabs editor - this.group.openEditor(this.group.getEditor(index)); + const input = this.group.getEditor(index); + if (input) { + this.group.openEditor(input); + } return undefined; }; @@ -477,7 +480,10 @@ export class TabsTitleControl extends TitleControl { const showContextMenu = (e: Event) => { EventHelper.stop(e); - this.onContextMenu(this.group.getEditor(index), e, tab); + const input = this.group.getEditor(index); + if (input) { + this.onContextMenu(input, e, tab); + } }; // Open on Click / Touch @@ -524,7 +530,10 @@ export class TabsTitleControl extends TitleControl { // Run action on Enter/Space if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) { handled = true; - this.group.openEditor(this.group.getEditor(index)); + const input = this.group.getEditor(index); + if (input) { + this.group.openEditor(input); + } } // Navigate in editors @@ -569,12 +578,19 @@ export class TabsTitleControl extends TitleControl { disposables.push(addDisposableListener(tab, EventType.CONTEXT_MENU, (e: Event) => { EventHelper.stop(e, true); - this.onContextMenu(this.group.getEditor(index), e, tab); + const input = this.group.getEditor(index); + if (input) { + this.onContextMenu(input, e, tab); + } }, true /* use capture to fix https://github.com/Microsoft/vscode/issues/19145 */)); // Drag support disposables.push(addDisposableListener(tab, EventType.DRAG_START, (e: DragEvent) => { const editor = this.group.getEditor(index); + if (!editor) { + return; + } + this.editorTransfer.setData([new DraggedEditorIdentifier({ editor, groupId: this.group.id })], DraggedEditorIdentifier.prototype); e.dataTransfer!.effectAllowed = 'copyMove'; @@ -608,7 +624,7 @@ export class TabsTitleControl extends TitleControl { if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { isLocalDragAndDrop = true; - const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier; + const localDraggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier; if (localDraggedEditor.editor === this.group.getEditor(index) && localDraggedEditor.groupId === this.group.id) { e.dataTransfer!.dropEffect = 'none'; return; @@ -649,7 +665,7 @@ export class TabsTitleControl extends TitleControl { private isSupportedDropTransfer(e: DragEvent): boolean { if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - const group = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0]; + const group = this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0]; if (group.identifier === this.group.id) { return false; // groups cannot be dropped on title area it originates from } @@ -764,7 +780,7 @@ export class TabsTitleControl extends TitleControl { // Remove description if all descriptions are identical if (descriptions.length === 1) { - for (const label of mapDescriptionToDuplicates.get(descriptions[0])) { + for (const label of mapDescriptionToDuplicates.get(descriptions[0]) || []) { label.description = ''; } @@ -774,7 +790,7 @@ export class TabsTitleControl extends TitleControl { // Shorten descriptions const shortenedDescriptions = shorten(descriptions); descriptions.forEach((description, i) => { - for (const label of mapDescriptionToDuplicates.get(description)) { + for (const label of mapDescriptionToDuplicates.get(description) || []) { label.description = shortenedDescriptions[i]; } }); @@ -860,7 +876,7 @@ export class TabsTitleControl extends TitleControl { tabContainer.title = title; // Label - tabLabelWidget.setResource({ name, description, resource: toResource(editor, { supportSideBySide: true }) }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) }); + tabLabelWidget.setResource({ name, description, resource: toResource(editor, { supportSideBySide: true }) || undefined }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) }); } private redrawEditorActiveAndDirty(isGroupActive: boolean, editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel): void { @@ -963,7 +979,7 @@ export class TabsTitleControl extends TitleControl { layout(dimension: Dimension): void { this.dimension = dimension; - const activeTab = this.getTab(this.group.activeEditor); + const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined; if (!activeTab || !this.dimension) { return; } @@ -980,7 +996,7 @@ export class TabsTitleControl extends TitleControl { } private doLayout(dimension: Dimension): void { - const activeTab = this.getTab(this.group.activeEditor); + const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined; if (!activeTab) { return; } @@ -993,8 +1009,8 @@ export class TabsTitleControl extends TitleControl { const visibleContainerWidth = this.tabsContainer.offsetWidth; const totalContainerWidth = this.tabsContainer.scrollWidth; - let activeTabPosX: number | undefined; - let activeTabWidth: number | undefined; + let activeTabPosX: number; + let activeTabWidth: number; if (!this.blockRevealActiveTab) { activeTabPosX = activeTab.offsetLeft; @@ -1015,20 +1031,20 @@ export class TabsTitleControl extends TitleControl { // Reveal the active one const containerScrollPosX = this.tabsScrollbar.getScrollPosition().scrollLeft; - const activeTabFits = activeTabWidth <= visibleContainerWidth; + const activeTabFits = activeTabWidth! <= visibleContainerWidth; // Tab is overflowing to the right: Scroll minimally until the element is fully visible to the right // Note: only try to do this if we actually have enough width to give to show the tab fully! - if (activeTabFits && containerScrollPosX + visibleContainerWidth < activeTabPosX + activeTabWidth) { + if (activeTabFits && containerScrollPosX + visibleContainerWidth < activeTabPosX! + activeTabWidth!) { this.tabsScrollbar.setScrollPosition({ - scrollLeft: containerScrollPosX + ((activeTabPosX + activeTabWidth) /* right corner of tab */ - (containerScrollPosX + visibleContainerWidth) /* right corner of view port */) + scrollLeft: containerScrollPosX + ((activeTabPosX! + activeTabWidth!) /* right corner of tab */ - (containerScrollPosX + visibleContainerWidth) /* right corner of view port */) }); } // Tab is overlflowng to the left or does not fit: Scroll it into view to the left - else if (containerScrollPosX > activeTabPosX || !activeTabFits) { + else if (containerScrollPosX > activeTabPosX! || !activeTabFits) { this.tabsScrollbar.setScrollPosition({ - scrollLeft: activeTabPosX + scrollLeft: activeTabPosX! }); } } @@ -1071,7 +1087,7 @@ export class TabsTitleControl extends TitleControl { // Local Editor DND if (this.editorTransfer.hasData(DraggedEditorIdentifier.prototype)) { - const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)[0].identifier; + const draggedEditor = this.editorTransfer.getData(DraggedEditorIdentifier.prototype)![0].identifier; const sourceGroup = this.accessor.getGroup(draggedEditor.groupId); // Move editor to target position and index @@ -1090,7 +1106,7 @@ export class TabsTitleControl extends TitleControl { // Local Editor Group DND else if (this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype)) { - const sourceGroup = this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)[0].identifier); + const sourceGroup = this.accessor.getGroup(this.groupTransfer.getData(DraggedEditorGroupIdentifier.prototype)![0].identifier); const mergeGroupOptions: IMergeGroupOptions = { index: targetIndex }; if (!this.isMoveOperation(e, sourceGroup.id)) { @@ -1119,7 +1135,8 @@ export class TabsTitleControl extends TitleControl { dispose(): void { super.dispose(); - this.layoutScheduled = dispose(this.layoutScheduled); + dispose(this.layoutScheduled); + this.layoutScheduled = undefined; } } diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index eb745aa83fc..a254b632c2e 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -974,7 +974,7 @@ export interface IResourceOptions { filter?: string | string[]; } -export function toResource(editor: IEditorInput, options?: IResourceOptions): URI | null { +export function toResource(editor: IEditorInput | null, options?: IResourceOptions): URI | null { if (!editor) { return null; } -- GitLab