From 2b959fdadc1d103b9fe3309bda80fbe8dfc1dd98 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Fri, 21 May 2021 12:39:42 +0200 Subject: [PATCH 001/140] Listen on local interface only (#124350) --- src/vs/platform/remote/node/tunnelService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/remote/node/tunnelService.ts b/src/vs/platform/remote/node/tunnelService.ts index 6483000c870..0090bc0fe26 100644 --- a/src/vs/platform/remote/node/tunnelService.ts +++ b/src/vs/platform/remote/node/tunnelService.ts @@ -76,12 +76,12 @@ class NodeRemoteTunnel extends Disposable implements RemoteTunnel { // if that fails, the method above returns 0, which works out fine below... let address: string | net.AddressInfo | null = null; - address = (this._server.listen(localPort).address()); + address = (this._server.listen(localPort, '127.0.0.1').address()); // It is possible for findFreePortFaster to return a port that there is already a server listening on. This causes the previous listen call to error out. if (!address) { localPort = 0; - address = (this._server.listen(localPort).address()); + address = (this._server.listen(localPort, '127.0.0.1').address()); } this.tunnelLocalPort = address.port; From 18296326a9add48838c642410669300508b05346 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 21 May 2021 16:28:30 -0700 Subject: [PATCH 002/140] Set proper context on new cell output toolbar --- .../notebook/browser/view/renderers/cellOutput.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts index da239a7d247..20f77a62138 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -20,7 +20,8 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { CodeCellRenderTemplate, ICellOutputViewModel, IInsetRenderOutput, INotebookEditor, IRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions'; +import { CodeCellRenderTemplate, ICellOutputViewModel, ICellViewModel, IInsetRenderOutput, INotebookEditor, IRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { mimetypeIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; @@ -238,6 +239,10 @@ export class CellOutputElement extends Disposable { return; } + if (!this.notebookEditor.hasModel()) { + return; + } + const useConsolidatedButton = this.notebookEditor.notebookOptions.getLayoutConfiguration().consolidatedOutputButton; outputItemDiv.style.position = 'relative'; @@ -249,6 +254,12 @@ export class CellOutputElement extends Disposable { getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id), renderDropdownAsChildElement: true })); + toolbar.context = { + ui: true, + cell: this.output.cellViewModel as ICellViewModel, + notebookEditor: this.notebookEditor, + $mid: 12 + }; // TODO: This could probably be a real registered action, but it has to talk to this output element const pickAction = new Action('notebook.output.pickMimetype', nls.localize('pickMimeType', "Choose a different output mimetype"), ThemeIcon.asClassName(mimetypeIcon), undefined, From 2b6564c1015edb4699a950e251131af8d2535352 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 24 May 2021 10:33:24 -0700 Subject: [PATCH 003/140] insert toolbar on the left. --- .../notebook/browser/contrib/coreActions.ts | 50 +++++++++++++++++-- .../notebook/browser/notebookEditorWidget.ts | 32 +++++++++++- .../browser/view/renderers/cellRenderer.ts | 21 +++++--- .../contrib/notebook/common/notebookCommon.ts | 1 + .../notebook/common/notebookOptions.ts | 29 +++++++++-- 5 files changed, 118 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 4cad4eb65fe..b7779cf8668 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -1027,7 +1027,25 @@ MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, { }, order: 0, group: 'inline', - when: NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true) + when: ContextKeyExpr.and( + NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true), + ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left') + ) +}); + +MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, { + command: { + id: INSERT_CODE_CELL_BELOW_COMMAND_ID, + title: localize('notebookActions.menu.insertCode.minimalToolbar', "Add Code"), + icon: Codicon.add, + tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell") + }, + order: 0, + group: 'inline', + when: ContextKeyExpr.and( + NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true), + ContextKeyExpr.equals('config.notebook.experimental.insertToolbarAlignment', 'left') + ) }); MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, { @@ -1054,7 +1072,25 @@ MenuRegistry.appendMenuItem(MenuId.NotebookCellListTop, { }, order: 0, group: 'inline', - when: NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true) + when: ContextKeyExpr.and( + NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true), + ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left') + ) +}); + +MenuRegistry.appendMenuItem(MenuId.NotebookCellListTop, { + command: { + id: INSERT_CODE_CELL_AT_TOP_COMMAND_ID, + title: localize('notebookActions.menu.insertCode.minimaltoolbar', "Add Code"), + icon: Codicon.add, + tooltip: localize('notebookActions.menu.insertCode.tooltip', "Add Code Cell") + }, + order: 0, + group: 'inline', + when: ContextKeyExpr.and( + NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true), + ContextKeyExpr.equals('config.notebook.experimental.insertToolbarAlignment', 'left') + ) }); registerAction2(class InsertMarkdownCellAboveAction extends InsertCellCommand { @@ -1097,7 +1133,10 @@ MenuRegistry.appendMenuItem(MenuId.NotebookCellBetween, { }, order: 1, group: 'inline', - when: NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true) + when: ContextKeyExpr.and( + NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true), + ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left') + ) }); MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, { @@ -1124,7 +1163,10 @@ MenuRegistry.appendMenuItem(MenuId.NotebookCellListTop, { }, order: 1, group: 'inline', - when: NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true) + when: ContextKeyExpr.and( + NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true), + ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarAlignment', 'left') + ) }); registerAction2(class EditCellAction extends NotebookCellAction { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index c3de76e5f67..8345a9b1707 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -369,7 +369,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._updateForNotebookConfiguration(); } - if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize) { + if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.insertToolbarAlignment) { this._styleElement?.remove(); this._createLayoutStyles(); this._webview?.updateOptions(this.notebookOptions.computeWebviewOptions()); @@ -564,6 +564,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor compactView, focusIndicator, insertToolbarPosition, + insertToolbarAlignment, fontSize } = this._notebookOptions.getLayoutConfiguration(); @@ -669,6 +670,35 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .cell-list-top-cell-toolbar-container { display: none; }`); } + if (insertToolbarAlignment === 'left') { + styleSheets.push(` + .monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container .action-item:first-child, + .monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container .action-item:first-child, .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container .action-item:first-child { + margin-right: 0px !important; + }`); + + styleSheets.push(` + .monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container .monaco-toolbar .action-label, + .monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container .monaco-toolbar .action-label, .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container .monaco-toolbar .action-label { + padding: 0px !important; + justify-content: center; + }`); + + styleSheets.push(` + .monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container, + .monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container, .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container { + align-items: flex-start; + justify-content: left; + margin: 0 16px 0 8px; + }`); + + styleSheets.push(` + .monaco-workbench .notebookOverlay .cell-list-top-cell-toolbar-container, + .notebookOverlay .cell-bottom-toolbar-container .action-item { + border: 0px; + }`); + } + // top insert toolbar const topInsertToolbarHeight = this._notebookOptions.computeTopInserToolbarHeight(this.viewModel?.viewType); styleSheets.push(`.notebookOverlay .cell-list-top-cell-toolbar-container { top: -${topInsertToolbarHeight}px }`); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 555c743706c..a1abbac5a74 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -26,7 +26,7 @@ import { ITextModel } from 'vs/editor/common/model'; import * as modes from 'vs/editor/common/modes'; import { tokenizeLineToHTML } from 'vs/editor/common/modes/textToHtmlTokenizer'; import { localize } from 'vs/nls'; -import { createActionViewItem, createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { createActionViewItem, createAndFillInActionBarActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IMenu, MenuItemAction } from 'vs/platform/actions/common/actions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -52,6 +52,7 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { errorStateIcon, successStateIcon, unfoldIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { syncing } from 'vs/platform/theme/common/iconRegistry'; import { CellEditorOptions } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions'; +import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; const $ = DOM.$; @@ -108,12 +109,15 @@ abstract class AbstractCellRenderer { this.dndController = undefined; } - protected createBetweenCellToolbar(container: HTMLElement, disposables: DisposableStore, contextKeyService: IContextKeyService): ToolBar { + protected createBetweenCellToolbar(container: HTMLElement, disposables: DisposableStore, contextKeyService: IContextKeyService, notebookOptions: NotebookOptions): ToolBar { const toolbar = new ToolBar(container, this.contextMenuService, { actionViewItemProvider: action => { if (action instanceof MenuItemAction) { - const item = new CodiconActionViewItem(action, this.keybindingService, this.notificationService); - return item; + if (notebookOptions.getLayoutConfiguration().insertToolbarAlignment === 'center') { + return new CodiconActionViewItem(action, this.keybindingService, this.notificationService); + } else { + return new MenuEntryActionViewItem(action, this.keybindingService, this.notificationService); + } } return undefined; @@ -129,6 +133,11 @@ abstract class AbstractCellRenderer { }; disposables.add(menu.onDidChange(() => updateActions())); + disposables.add(notebookOptions.onDidChangeOptions((e) => { + if (e.insertToolbarAlignment) { + updateActions(); + } + })); updateActions(); return toolbar; @@ -342,7 +351,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR const { collapsedPart, expandButton } = this.setupCollapsedPart(container); const bottomCellContainer = DOM.append(container, $('.cell-bottom-toolbar-container')); - const betweenCellToolbar = disposables.add(this.createBetweenCellToolbar(bottomCellContainer, disposables, contextKeyService)); + const betweenCellToolbar = disposables.add(this.createBetweenCellToolbar(bottomCellContainer, disposables, contextKeyService, this.notebookEditor.notebookOptions)); const focusIndicatorBottom = DOM.append(container, $('.cell-focus-indicator.cell-focus-indicator-bottom')); const statusBar = disposables.add(this.instantiationService.createInstance(CellEditorStatusBar, editorPart)); @@ -727,7 +736,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende focusSinkElement.setAttribute('tabindex', '0'); const bottomCellContainer = DOM.append(container, $('.cell-bottom-toolbar-container')); const focusIndicatorBottom = DOM.append(container, $('.cell-focus-indicator.cell-focus-indicator-bottom')); - const betweenCellToolbar = this.createBetweenCellToolbar(bottomCellContainer, disposables, contextKeyService); + const betweenCellToolbar = this.createBetweenCellToolbar(bottomCellContainer, disposables, contextKeyService, this.notebookEditor.notebookOptions); const titleMenu = disposables.add(this.cellMenus.getCellTitleMenu(contextKeyService)); diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 7c748333af8..3a1bdaa6591 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -908,6 +908,7 @@ export const ExperimentalUseMarkdownRenderer = 'notebook.experimental.useMarkdow export const ExperimentalCompactView = 'notebook.experimental.compactView'; export const ExperimentalFocusIndicator = 'notebook.experimental.cellFocusIndicator'; export const ExperimentalInsertToolbarPosition = 'notebook.experimental.insertToolbarPosition'; +export const ExperimentalInsertToolbarAlignment = 'notebook.experimental.insertToolbarAlignment'; export const ExperimentalGlobalToolbar = 'notebook.experimental.globalToolbar'; export const ExperimentalUndoRedoPerCell = 'notebook.experimental.undoRedoPerCell'; export const ExperimentalConsolidatedOutputButton = 'notebook.experimental.consolidatedOutputButton'; diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 0e877655b5b..644eb383abb 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -6,7 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { CellToolbarLocKey, CellToolbarVisibility, ExperimentalCompactView, ExperimentalConsolidatedOutputButton, ExperimentalDragAndDropEnabled, ExperimentalFocusIndicator, ExperimentalGlobalToolbar, ExperimentalInsertToolbarPosition, ExperimentalShowFoldingControls, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellToolbarLocKey, CellToolbarVisibility, ExperimentalCompactView, ExperimentalConsolidatedOutputButton, ExperimentalDragAndDropEnabled, ExperimentalFocusIndicator, ExperimentalGlobalToolbar, ExperimentalInsertToolbarAlignment, ExperimentalInsertToolbarPosition, ExperimentalShowFoldingControls, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; const SCROLLABLE_ELEMENT_PADDING_TOP = 18; @@ -49,6 +49,7 @@ export interface NotebookLayoutConfiguration { compactView: boolean; focusIndicator: 'border' | 'gutter'; insertToolbarPosition: 'betweenCells' | 'notebookToolbar' | 'both' | 'hidden'; + insertToolbarAlignment: 'left' | 'center'; globalToolbar: boolean; consolidatedOutputButton: boolean; showFoldingControls: 'always' | 'mouseover'; @@ -64,6 +65,7 @@ interface NotebookOptionsChangeEvent { compactView?: boolean; focusIndicator?: boolean; insertToolbarPosition?: boolean; + insertToolbarAlignment?: boolean; globalToolbar?: boolean; showFoldingControls?: boolean; consolidatedOutputButton?: boolean; @@ -103,8 +105,9 @@ export class NotebookOptions { const compactView = this.configurationService.getValue(ExperimentalCompactView); const focusIndicator = this._computeFocusIndicatorOption(); const insertToolbarPosition = this._computeInsertToolbarPositionOption(); + const insertToolbarAlignment = this._computeInsertToolbarAlignmentOption(); const showFoldingControls = this._computeShowFoldingControlsOption(); - const { bottomToolbarGap, bottomToolbarHeight } = this._computeBottomToolbarDimensions(compactView, insertToolbarPosition); + const { bottomToolbarGap, bottomToolbarHeight } = this._computeBottomToolbarDimensions(compactView, insertToolbarPosition, insertToolbarAlignment); const fontSize = this.configurationService.getValue('editor.fontSize'); this._disposables = []; @@ -132,6 +135,7 @@ export class NotebookOptions { compactView, focusIndicator, insertToolbarPosition, + insertToolbarAlignment, showFoldingControls, fontSize }; @@ -155,6 +159,7 @@ export class NotebookOptions { const compactView = e.affectsConfiguration(ExperimentalCompactView); const focusIndicator = e.affectsConfiguration(ExperimentalFocusIndicator); const insertToolbarPosition = e.affectsConfiguration(ExperimentalInsertToolbarPosition); + const insertToolbarAlignment = e.affectsConfiguration(ExperimentalInsertToolbarAlignment); const globalToolbar = e.affectsConfiguration(ExperimentalGlobalToolbar); const consolidatedOutputButton = e.affectsConfiguration(ExperimentalConsolidatedOutputButton); const showFoldingControls = e.affectsConfiguration(ExperimentalShowFoldingControls); @@ -168,6 +173,7 @@ export class NotebookOptions { && !compactView && !focusIndicator && !insertToolbarPosition + && !insertToolbarAlignment && !globalToolbar && !consolidatedOutputButton && !showFoldingControls @@ -202,9 +208,13 @@ export class NotebookOptions { configuration.compactView = compactViewValue; } + if (insertToolbarAlignment) { + configuration.insertToolbarAlignment = this._computeInsertToolbarAlignmentOption(); + } + if (insertToolbarPosition) { configuration.insertToolbarPosition = this._computeInsertToolbarPositionOption(); - const { bottomToolbarGap, bottomToolbarHeight } = this._computeBottomToolbarDimensions(configuration.compactView, configuration.insertToolbarPosition); + const { bottomToolbarGap, bottomToolbarHeight } = this._computeBottomToolbarDimensions(configuration.compactView, configuration.insertToolbarPosition, configuration.insertToolbarAlignment); configuration.bottomToolbarHeight = bottomToolbarHeight; configuration.bottomToolbarGap = bottomToolbarGap; } @@ -239,6 +249,7 @@ export class NotebookOptions { compactView, focusIndicator, insertToolbarPosition, + insertToolbarAlignment, globalToolbar, showFoldingControls, consolidatedOutputButton, @@ -251,6 +262,10 @@ export class NotebookOptions { return this.configurationService.getValue<'betweenCells' | 'notebookToolbar' | 'both' | 'hidden'>(ExperimentalInsertToolbarPosition) ?? 'both'; } + private _computeInsertToolbarAlignmentOption() { + return this.configurationService.getValue<'left' | 'center'>(ExperimentalInsertToolbarAlignment) ?? 'center'; + } + private _computeShowFoldingControlsOption() { return this.configurationService.getValue<'always' | 'mouseover'>(ExperimentalShowFoldingControls) ?? 'always'; } @@ -259,7 +274,13 @@ export class NotebookOptions { return this.configurationService.getValue<'border' | 'gutter'>(ExperimentalFocusIndicator) ?? 'border'; } - private _computeBottomToolbarDimensions(compactView: boolean, insertToolbarPosition: 'betweenCells' | 'notebookToolbar' | 'both' | 'hidden'): { bottomToolbarGap: number, bottomToolbarHeight: number } { + private _computeBottomToolbarDimensions(compactView: boolean, insertToolbarPosition: 'betweenCells' | 'notebookToolbar' | 'both' | 'hidden', insertToolbarAlignment: 'left' | 'center'): { bottomToolbarGap: number, bottomToolbarHeight: number } { + if (insertToolbarAlignment === 'left') { + return { + bottomToolbarGap: 18, + bottomToolbarHeight: 22 + }; + } if (insertToolbarPosition === 'betweenCells' || insertToolbarPosition === 'both') { return compactView ? { bottomToolbarGap: 12, From 41d869f5514a7ad6666a494edbaa3effebe68f93 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 24 May 2021 13:34:26 -0700 Subject: [PATCH 004/140] move nb layout settings out of experiments. --- .../notebook/browser/contrib/coreActions.ts | 20 +++--- .../browser/contrib/status/editorStatus.ts | 8 +-- .../notebook/browser/notebook.contribution.ts | 63 +++++++++++++++++-- .../notebook/browser/notebookEditorToolbar.ts | 8 +-- .../contrib/notebook/common/notebookCommon.ts | 16 ++--- .../notebook/common/notebookOptions.ts | 38 +++++------ 6 files changed, 103 insertions(+), 50 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index b7779cf8668..1928186275d 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -679,7 +679,7 @@ registerAction2(class ExecuteNotebookAction extends NotebookAction { NOTEBOOK_IS_ACTIVE_EDITOR, executeNotebookCondition, ContextKeyExpr.or(NOTEBOOK_INTERRUPTIBLE_KERNEL.toNegated(), NOTEBOOK_HAS_RUNNING_CELL.toNegated()), - ContextKeyExpr.notEquals('config.notebook.experimental.globalToolbar', true) + ContextKeyExpr.notEquals('config.notebook.globalToolbar', true) ) }, { @@ -689,7 +689,7 @@ registerAction2(class ExecuteNotebookAction extends NotebookAction { when: ContextKeyExpr.and( executeNotebookCondition, ContextKeyExpr.or(NOTEBOOK_INTERRUPTIBLE_KERNEL.toNegated(), NOTEBOOK_HAS_RUNNING_CELL.toNegated()), - ContextKeyExpr.equals('config.notebook.experimental.globalToolbar', true) + ContextKeyExpr.equals('config.notebook.globalToolbar', true) ) } ] @@ -750,7 +750,7 @@ registerAction2(class CancelNotebook extends NotebookAction { NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, - ContextKeyExpr.notEquals('config.notebook.experimental.globalToolbar', true) + ContextKeyExpr.notEquals('config.notebook.globalToolbar', true) ) }, { @@ -760,7 +760,7 @@ registerAction2(class CancelNotebook extends NotebookAction { when: ContextKeyExpr.and( NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, - ContextKeyExpr.equals('config.notebook.experimental.globalToolbar', true) + ContextKeyExpr.equals('config.notebook.globalToolbar', true) ) } ] @@ -1059,8 +1059,8 @@ MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, { group: 'navigation/add', when: ContextKeyExpr.and( NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true), - ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarPosition', 'betweenCells'), - ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarPosition', 'hidden') + ContextKeyExpr.notEquals('config.notebook.insertToolbarPosition', 'betweenCells'), + ContextKeyExpr.notEquals('config.notebook.insertToolbarPosition', 'hidden') ) }); @@ -1150,8 +1150,8 @@ MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, { group: 'navigation/add', when: ContextKeyExpr.and( NOTEBOOK_EDITOR_EDITABLE.isEqualTo(true), - ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarPosition', 'betweenCells'), - ContextKeyExpr.notEquals('config.notebook.experimental.insertToolbarPosition', 'hidden') + ContextKeyExpr.notEquals('config.notebook.insertToolbarPosition', 'betweenCells'), + ContextKeyExpr.notEquals('config.notebook.insertToolbarPosition', 'hidden') ) }); @@ -1582,14 +1582,14 @@ registerAction2(class ClearAllCellOutputsAction extends NotebookAction { id: MenuId.EditorTitle, when: ContextKeyExpr.and( NOTEBOOK_IS_ACTIVE_EDITOR, - ContextKeyExpr.notEquals('config.notebook.experimental.globalToolbar', true) + ContextKeyExpr.notEquals('config.notebook.globalToolbar', true) ), group: 'navigation', order: 0 }, { id: MenuId.NotebookToolbar, - when: ContextKeyExpr.equals('config.notebook.experimental.globalToolbar', true), + when: ContextKeyExpr.equals('config.notebook.globalToolbar', true), group: 'navigation/execute', order: 0 } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts index 4a415850196..6c77b8311e5 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts @@ -42,8 +42,8 @@ registerAction2(class extends Action2 { when: ContextKeyExpr.and( NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), - ContextKeyExpr.equals('config.notebook.experimental.showKernelInEditorTitle', true), - ContextKeyExpr.notEquals('config.notebook.experimental.globalToolbar', true) + ContextKeyExpr.equals('config.notebook.showKernelInEditorTitle', true), + ContextKeyExpr.notEquals('config.notebook.globalToolbar', true) ), group: 'navigation', order: -10 @@ -51,8 +51,8 @@ registerAction2(class extends Action2 { id: MenuId.NotebookToolbar, when: ContextKeyExpr.and( NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), - ContextKeyExpr.equals('config.notebook.experimental.showKernelInEditorTitle', true), - ContextKeyExpr.equals('config.notebook.experimental.globalToolbar', true) + ContextKeyExpr.equals('config.notebook.showKernelInEditorTitle', true), + ContextKeyExpr.equals('config.notebook.globalToolbar', true) ), group: 'status', order: -10 diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index c2fe1b21212..d6ddcffac33 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -29,7 +29,7 @@ import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEd import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { NotebookService } from 'vs/workbench/contrib/notebook/browser/notebookServiceImpl'; -import { CellKind, CellToolbarLocKey, CellToolbarVisibility, CellUri, DisplayOrderKey, ExperimentalUndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, CellToolbarLocKey, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey, CompactView, FocusIndicator, InsertToolbarPosition, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService'; @@ -192,7 +192,7 @@ export class NotebookContribution extends Disposable implements IWorkbenchContri ) { super(); - const undoRedoPerCell = configurationService.getValue(ExperimentalUndoRedoPerCell); + const undoRedoPerCell = configurationService.getValue(UndoRedoPerCell); this._register(undoRedoService.registerUriComparisonKeyComputer(CellUri.scheme, { getComparisonKey: (uri: URI): string => { @@ -572,12 +572,14 @@ configurationRegistry.registerConfiguration({ }, default: { 'default': 'right' - } + }, + tags: ['notebookLayout'] }, [ShowCellStatusBarKey]: { description: nls.localize('notebook.showCellStatusbar.description', "Whether the cell status bar should be shown."), type: 'boolean', - default: true + default: true, + tags: ['notebookLayout'] }, [NotebookTextDiffEditorPreview]: { description: nls.localize('notebook.diff.enablePreview.description', "Whether to use the enhanced text diff editor for notebook."), @@ -593,7 +595,58 @@ configurationRegistry.registerConfiguration({ markdownDescription: nls.localize('notebook.cellToolbarVisibility.description', "Whether the cell toolbar should appear on hover or click."), type: 'string', enum: ['hover', 'click'], - default: 'click' + default: 'click', + tags: ['notebookLayout'] }, + [UndoRedoPerCell]: { + description: nls.localize('notebook.undoRedoPerCell.description', "Whether to use separate undo/redo stack for each cell."), + type: 'boolean', + default: false + }, + [CompactView]: { + description: nls.localize('notebook.compactView.description', "Control whether the notebook editor should be rendered in a compact form. "), + type: 'boolean', + default: false, + tags: ['notebookLayout'] + }, + [FocusIndicator]: { + description: nls.localize('notebook.focusIndicator.description', "Control whether to render the focus indicator as cell borders or a highlight bar on the left gutter"), + type: 'string', + enum: ['border', 'gutter'], + default: 'border', + tags: ['notebookLayout'] + }, + [InsertToolbarPosition]: { + description: nls.localize('notebook.insertToolbarPosition.description', "Control where the insert cell actions should be rendered."), + type: 'string', + enum: ['betweenCells', 'notebookToolbar', 'both', 'hidden'], + default: 'both', + tags: ['notebookLayout'] + }, + [GlobalToolbar]: { + description: nls.localize('notebook.globalToolbar.description', "Control whether to render a global toolbar inside the notebook editor."), + type: 'boolean', + default: false, + tags: ['notebookLayout'] + }, + [ConsolidatedOutputButton]: { + description: nls.localize('notebook.consolidatedOutputButton.description', "Control whether outputs action should be rendered in the output toolbar."), + type: 'boolean', + default: true, + tags: ['notebookLayout'] + }, + [ShowFoldingControls]: { + description: nls.localize('notebook.showFoldingControls.description', "Controls when the folding controls are shown."), + type: 'string', + enum: ['always', 'mouseover'], + default: 'always', + tags: ['notebookLayout'] + }, + [DragAndDropEnabled]: { + description: nls.localize('notebook.dragAndDrop.description', "Control whether the notebook editor should allow moving cells through drag and drop."), + type: 'boolean', + default: true, + tags: ['notebookLayout'] + } } }); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorToolbar.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorToolbar.ts index 0e2fd14c3cd..779804d8deb 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorToolbar.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorToolbar.ts @@ -23,7 +23,7 @@ import { INotebookEditor, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebo import { NotebooKernelActionViewItem } from 'vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem'; import { ActionViewWithLabel } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView'; import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus'; -import { ExperimentalGlobalToolbar } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { GlobalToolbar } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITASExperimentService } from 'vs/workbench/services/experiment/common/experimentService'; @@ -98,10 +98,10 @@ export class NotebookEditorToolbar extends Disposable { this._notebookGlobalActionsMenu = this._register(cellMenu.getNotebookToolbar(this.contextKeyService)); this._register(this._notebookGlobalActionsMenu); - this._useGlobalToolbar = this.configurationService.getValue(ExperimentalGlobalToolbar) ?? false; + this._useGlobalToolbar = this.configurationService.getValue(GlobalToolbar) ?? false; this._register(this.configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(ExperimentalGlobalToolbar)) { - this._useGlobalToolbar = this.configurationService.getValue(ExperimentalGlobalToolbar); + if (e.affectsConfiguration(GlobalToolbar)) { + this._useGlobalToolbar = this.configurationService.getValue(GlobalToolbar); this._showNotebookActionsinEditorToolbar(); } })); diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 3a1bdaa6591..9a6803d7544 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -905,15 +905,15 @@ export const CellToolbarVisibility = 'notebook.cellToolbarVisibility'; export const ShowCellStatusBarKey = 'notebook.showCellStatusBar'; export const NotebookTextDiffEditorPreview = 'notebook.diff.enablePreview'; export const ExperimentalUseMarkdownRenderer = 'notebook.experimental.useMarkdownRenderer'; -export const ExperimentalCompactView = 'notebook.experimental.compactView'; -export const ExperimentalFocusIndicator = 'notebook.experimental.cellFocusIndicator'; -export const ExperimentalInsertToolbarPosition = 'notebook.experimental.insertToolbarPosition'; export const ExperimentalInsertToolbarAlignment = 'notebook.experimental.insertToolbarAlignment'; -export const ExperimentalGlobalToolbar = 'notebook.experimental.globalToolbar'; -export const ExperimentalUndoRedoPerCell = 'notebook.experimental.undoRedoPerCell'; -export const ExperimentalConsolidatedOutputButton = 'notebook.experimental.consolidatedOutputButton'; -export const ExperimentalShowFoldingControls = 'notebook.experimental.showFoldingControls'; -export const ExperimentalDragAndDropEnabled = 'notebook.experimental.dragAndDropEnabled'; +export const CompactView = 'notebook.compactView'; +export const FocusIndicator = 'notebook.cellFocusIndicator'; +export const InsertToolbarPosition = 'notebook.insertToolbarPosition'; +export const GlobalToolbar = 'notebook.globalToolbar'; +export const UndoRedoPerCell = 'notebook.undoRedoPerCell'; +export const ConsolidatedOutputButton = 'notebook.consolidatedOutputButton'; +export const ShowFoldingControls = 'notebook.showFoldingControls'; +export const DragAndDropEnabled = 'notebook.dragAndDropEnabled'; export const enum CellStatusbarAlignment { Left = 1, diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 644eb383abb..5483d660529 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -6,7 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { CellToolbarLocKey, CellToolbarVisibility, ExperimentalCompactView, ExperimentalConsolidatedOutputButton, ExperimentalDragAndDropEnabled, ExperimentalFocusIndicator, ExperimentalGlobalToolbar, ExperimentalInsertToolbarAlignment, ExperimentalInsertToolbarPosition, ExperimentalShowFoldingControls, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellToolbarLocKey, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, DragAndDropEnabled, FocusIndicator, GlobalToolbar, ExperimentalInsertToolbarAlignment, InsertToolbarPosition, ShowFoldingControls, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; const SCROLLABLE_ELEMENT_PADDING_TOP = 18; @@ -97,12 +97,12 @@ export class NotebookOptions { constructor(private readonly configurationService: IConfigurationService) { const showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); - const globalToolbar = this.configurationService.getValue(ExperimentalGlobalToolbar) ?? false; - const consolidatedOutputButton = this.configurationService.getValue(ExperimentalConsolidatedOutputButton) ?? true; - const dragAndDropEnabled = this.configurationService.getValue(ExperimentalDragAndDropEnabled) ?? true; + const globalToolbar = this.configurationService.getValue(GlobalToolbar); + const consolidatedOutputButton = this.configurationService.getValue(ConsolidatedOutputButton); + const dragAndDropEnabled = this.configurationService.getValue(DragAndDropEnabled); const cellToolbarLocation = this.configurationService.getValue(CellToolbarLocKey); const cellToolbarInteraction = this.configurationService.getValue(CellToolbarVisibility); - const compactView = this.configurationService.getValue(ExperimentalCompactView); + const compactView = this.configurationService.getValue(CompactView); const focusIndicator = this._computeFocusIndicatorOption(); const insertToolbarPosition = this._computeInsertToolbarPositionOption(); const insertToolbarAlignment = this._computeInsertToolbarAlignmentOption(); @@ -156,14 +156,14 @@ export class NotebookOptions { const cellStatusBarVisibility = e.affectsConfiguration(ShowCellStatusBarKey); const cellToolbarLocation = e.affectsConfiguration(CellToolbarLocKey); const cellToolbarInteraction = e.affectsConfiguration(CellToolbarVisibility); - const compactView = e.affectsConfiguration(ExperimentalCompactView); - const focusIndicator = e.affectsConfiguration(ExperimentalFocusIndicator); - const insertToolbarPosition = e.affectsConfiguration(ExperimentalInsertToolbarPosition); + const compactView = e.affectsConfiguration(CompactView); + const focusIndicator = e.affectsConfiguration(FocusIndicator); + const insertToolbarPosition = e.affectsConfiguration(InsertToolbarPosition); const insertToolbarAlignment = e.affectsConfiguration(ExperimentalInsertToolbarAlignment); - const globalToolbar = e.affectsConfiguration(ExperimentalGlobalToolbar); - const consolidatedOutputButton = e.affectsConfiguration(ExperimentalConsolidatedOutputButton); - const showFoldingControls = e.affectsConfiguration(ExperimentalShowFoldingControls); - const dragAndDropEnabled = e.affectsConfiguration(ExperimentalDragAndDropEnabled); + const globalToolbar = e.affectsConfiguration(GlobalToolbar); + const consolidatedOutputButton = e.affectsConfiguration(ConsolidatedOutputButton); + const showFoldingControls = e.affectsConfiguration(ShowFoldingControls); + const dragAndDropEnabled = e.affectsConfiguration(DragAndDropEnabled); const fontSize = e.affectsConfiguration('editor.fontSize'); if ( @@ -201,7 +201,7 @@ export class NotebookOptions { } if (compactView) { - const compactViewValue = this.configurationService.getValue('notebook.experimental.compactView'); + const compactViewValue = this.configurationService.getValue(CompactView); configuration = Object.assign(configuration, { ...(compactViewValue ? compactConfigConstants : defaultConfigConstants), }); @@ -220,11 +220,11 @@ export class NotebookOptions { } if (globalToolbar) { - configuration.globalToolbar = this.configurationService.getValue(ExperimentalGlobalToolbar) ?? false; + configuration.globalToolbar = this.configurationService.getValue(GlobalToolbar); } if (consolidatedOutputButton) { - configuration.consolidatedOutputButton = this.configurationService.getValue(ExperimentalConsolidatedOutputButton) ?? true; + configuration.consolidatedOutputButton = this.configurationService.getValue(ConsolidatedOutputButton); } if (showFoldingControls) { @@ -232,7 +232,7 @@ export class NotebookOptions { } if (dragAndDropEnabled) { - configuration.dragAndDropEnabled = this.configurationService.getValue(ExperimentalDragAndDropEnabled) ?? true; + configuration.dragAndDropEnabled = this.configurationService.getValue(DragAndDropEnabled); } if (fontSize) { @@ -259,7 +259,7 @@ export class NotebookOptions { } private _computeInsertToolbarPositionOption() { - return this.configurationService.getValue<'betweenCells' | 'notebookToolbar' | 'both' | 'hidden'>(ExperimentalInsertToolbarPosition) ?? 'both'; + return this.configurationService.getValue<'betweenCells' | 'notebookToolbar' | 'both' | 'hidden'>(InsertToolbarPosition); } private _computeInsertToolbarAlignmentOption() { @@ -267,11 +267,11 @@ export class NotebookOptions { } private _computeShowFoldingControlsOption() { - return this.configurationService.getValue<'always' | 'mouseover'>(ExperimentalShowFoldingControls) ?? 'always'; + return this.configurationService.getValue<'always' | 'mouseover'>(ShowFoldingControls); } private _computeFocusIndicatorOption() { - return this.configurationService.getValue<'border' | 'gutter'>(ExperimentalFocusIndicator) ?? 'border'; + return this.configurationService.getValue<'border' | 'gutter'>(FocusIndicator); } private _computeBottomToolbarDimensions(compactView: boolean, insertToolbarPosition: 'betweenCells' | 'notebookToolbar' | 'both' | 'hidden', insertToolbarAlignment: 'left' | 'center'): { bottomToolbarGap: number, bottomToolbarHeight: number } { From d7ead317dcafd6743637823c1a4b36ee498682e5 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 24 May 2021 13:48:03 -0700 Subject: [PATCH 005/140] Close #122570 --- .../browser/gettingStartedExtensionPoint.ts | 15 ++++++++ .../browser/gettingStartedService.ts | 34 +++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedExtensionPoint.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedExtensionPoint.ts index 2977e1396df..8124026551e 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedExtensionPoint.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedExtensionPoint.ts @@ -138,6 +138,21 @@ export const walkthroughsExtensionPoint = ExtensionsRegistry.registerExtensionPo description: localize('walkthroughs.steps.completionEvents.onLink', 'Check off step when a given link is opened via a Getting Started step.'), body: 'onLink:${2:linkId}' }, + { + label: 'onView', + description: localize('walkthroughs.steps.completionEvents.onView', 'Check off step when a given view is opened'), + body: 'onView:${2:viewId}' + }, + { + label: 'onSettingChanged', + description: localize('walkthroughs.steps.completionEvents.onSettingChanged', 'Check off step when a given setting is changed'), + body: 'onSettingChanged:${2:settingName}' + }, + { + label: 'onContextKeyDefined', + description: localize('walkthroughs.steps.completionEvents.onContextKeyDefined', 'Check off step when a context key is defined to a truthy value. Note: this only accepts single context keys, not full context key expressions'), + body: 'onContextKeyDefined:${2:key}' + }, { label: 'extensionInstalled', description: localize('walkthroughs.steps.completionEvents.extensionInstalled', 'Check off step when an extension with the given id is installed. If the extension is already installed, the step will start off checked.'), diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts index c3e75b8d7c9..6d9741aface 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts @@ -29,6 +29,7 @@ import { walkthroughsExtensionPoint } from 'vs/workbench/contrib/welcome/getting import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { dirname } from 'vs/base/common/path'; import { coalesce, flatten } from 'vs/base/common/arrays'; +import { IViewsService } from 'vs/workbench/common/views'; export const IGettingStartedService = createDecorator('gettingStartedService'); @@ -164,7 +165,8 @@ export class GettingStartedService extends Disposable implements IGettingStarted private tasExperimentService?: ITASExperimentService; private sessionInstalledExtensions = new Set(); - private trackedContextKeys = new Set(); + private categoryVisibilityContextKeys = new Set(); + private stepCompletionContextKeys = new Set(); private triggerInstalledExtensionsRegistered!: () => void; installedExtensionsRegistered: Promise; @@ -178,6 +180,7 @@ export class GettingStartedService extends Disposable implements IGettingStarted @IConfigurationService private readonly configurationService: IConfigurationService, @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, @IHostService private readonly hostService: IHostService, + @IViewsService private readonly viewsService: IViewsService, @optional(ITASExperimentService) tasExperimentService: ITASExperimentService, ) { super(); @@ -206,7 +209,22 @@ export class GettingStartedService extends Disposable implements IGettingStarted })); this._register(this.contextService.onDidChangeContext(event => { - if (event.affectsSome(this.trackedContextKeys)) { this._onDidAddCategory.fire(); } + if (event.affectsSome(this.categoryVisibilityContextKeys)) { this._onDidAddCategory.fire(); } + if (event.affectsSome(this.stepCompletionContextKeys)) { + this.stepCompletionContextKeys.forEach(key => { + if (event.affectsSome(new Set([key])) && this.contextService.getContextKeyValue(key)) { + this.progressByEvent(`onContextKeyDefined:` + key); + } + }); + } + })); + + this._register(this.viewsService.onDidChangeViewVisibility(e => { + if (e.visible) { this.progressByEvent('onView:' + e.id); } + })); + + this._register(this.configurationService.onDidChangeConfiguration(e => { + e.affectedKeys.forEach(key => { this.progressByEvent('onSettingChanged:' + key); }); })); if (userDataAutoSyncEnablementService.isEnabled()) { this.progressByEvent('onEvent:sync-enabled'); } @@ -493,7 +511,8 @@ export class GettingStartedService extends Disposable implements IGettingStarted } switch (eventType) { - case 'onLink': case 'onEvent': break; + case 'onLink': case 'onEvent': case 'onView': case 'onContextKeyDefined': case 'onSettingChanged': + break; case 'stepSelected': event = eventType + ':' + step.id; break; @@ -590,6 +609,8 @@ export class GettingStartedService extends Disposable implements IGettingStarted } progressByEvent(event: string): void { + if (this.sessionEvents.has(event)) { return; } + this.sessionEvents.add(event); this.completionListeners.get(event)?.forEach(id => this.progressStep(id)); } @@ -620,7 +641,7 @@ export class GettingStartedService extends Disposable implements IGettingStarted if (this.steps.has(step.id)) { throw Error('Attempting to register step with id ' + step.id + ' twice. Second is dropped.'); } this.steps.set(step.id, step); this.registerDoneListeners(step); - this.trackedContextKeys.add(step.when.serialize()); + step.when.keys().forEach(key => this.categoryVisibilityContextKeys.add(key)); }); if (this.contextService.contextMatchesRules(category.when)) { @@ -631,7 +652,7 @@ export class GettingStartedService extends Disposable implements IGettingStarted if (override) { const old = category.when; const gnu = ContextKeyExpr.deserialize(override) ?? old; - this.trackedContextKeys.add(override); + this.categoryVisibilityContextKeys.add(override); category.when = gnu; if (this.contextService.contextMatchesRules(old) && !this.contextService.contextMatchesRules(gnu)) { @@ -641,8 +662,7 @@ export class GettingStartedService extends Disposable implements IGettingStarted } } }); - - this.trackedContextKeys.add(category.when.serialize()); + category.when.keys().forEach(key => this.categoryVisibilityContextKeys.add(key)); } private getStep(id: string): IGettingStartedStep { From f88c007f6c6bebc45a53d101b510dcaa18e2db49 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 24 May 2021 13:52:10 -0700 Subject: [PATCH 006/140] =?UTF-8?q?=F0=9F=91=8B=20Rachel,=20=F0=9F=91=8B?= =?UTF-8?q?=20Tyler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/classifier.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/classifier.json b/.github/classifier.json index 05e2b5bd9ea..d985c69a121 100644 --- a/.github/classifier.json +++ b/.github/classifier.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/microsoft/vscode-github-triage-actions/master/classifier-deep/apply/apply-labels/deep-classifier-config.schema.json", - "vacation": [], + "vacation": ["RMacfarlane"], "assignees": { "JacksonKearl": {"accuracy": 0.5} }, @@ -10,7 +10,7 @@ "api": {"assign": ["jrieken"]}, "api-finalization": {"assign": []}, "api-proposal": {"assign": ["jrieken"]}, - "authentication": {"assign": ["RMacfarlane"]}, + "authentication": {"assign": ["TylerLeonhardt"]}, "breadcrumbs": {"assign": ["jrieken"]}, "callhierarchy": {"assign": ["jrieken"]}, "code-lens": {"assign": ["jrieken"]}, @@ -88,7 +88,7 @@ "intellisense-config": {"assign": []}, "ipc": {"assign": ["joaomoreno"]}, "issue-bot": {"assign": ["chrmarti"]}, - "issue-reporter": {"assign": ["RMacfarlane"]}, + "issue-reporter": {"assign": ["TylerLeonhardt"]}, "javascript": {"assign": ["mjbvz"]}, "json": {"assign": ["aeschli"]}, "keybindings": {"assign": []}, @@ -152,7 +152,7 @@ "web": {"assign": ["bpasero"]}, "webview": {"assign": ["mjbvz"]}, "workbench-cli": {"assign": []}, - "workbench-diagnostics": {"assign": ["RMacfarlane"]}, + "workbench-diagnostics": {"assign": ["TylerLeonhardt"]}, "workbench-dnd": {"assign": ["bpasero"]}, "workbench-editor-grid": {"assign": ["sbatten"]}, "workbench-editors": {"assign": ["bpasero"]}, From 8a41d85d1bed7589a1760392580ee047bbcc5a7a Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 24 May 2021 14:03:03 -0700 Subject: [PATCH 007/140] notebook open layout settings. --- .../notebook/browser/contrib/coreActions.ts | 27 +++++++++++++++++++ .../notebook/browser/notebookEditorToolbar.ts | 2 +- .../view/renderers/cellEditorOptions.ts | 11 ++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 1928186275d..9f059f43276 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -24,6 +24,7 @@ import { ICellRange, isICellRange } from 'vs/workbench/contrib/notebook/common/n import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { EditorsOrder, IEditorCommandsContext } from 'vs/workbench/common/editor'; @@ -1767,6 +1768,32 @@ registerAction2(class ExpandCellOuputAction extends ChangeNotebookCellMetadataAc } }); +registerAction2(class NotebookConfigureLayoutAction extends Action2 { + constructor() { + super({ + id: 'workbench.notebook.layout.configure', + title: localize('workbench.notebook.layout.configure.label', "Configure Notebook Editor Layout Settings"), + f1: true, + category: NOTEBOOK_ACTIONS_CATEGORY, + menu: [ + { + id: MenuId.EditorTitle, + group: 'notebookLayout', + when: ContextKeyExpr.notEquals('config.notebook.globalToolbar', true) + }, + { + id: MenuId.NotebookToolbar, + group: 'notebookLayout', + when: ContextKeyExpr.equals('config.notebook.globalToolbar', true) + } + ] + }); + } + run(accessor: ServicesAccessor): void { + accessor.get(IPreferencesService).openSettings(false, '@tag:notebookLayout'); + } +}); + CommandsRegistry.registerCommand('_resolveNotebookContentProvider', (accessor, args): { viewType: string; displayName: string; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorToolbar.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorToolbar.ts index 779804d8deb..424eecf4304 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorToolbar.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorToolbar.ts @@ -186,7 +186,7 @@ export class NotebookEditorToolbar extends Disposable { }); const primaryRightGroup = groups.find(group => /^status/.test(group[0])); const primaryRightActions = primaryRightGroup ? primaryRightGroup[1] : []; - const secondaryActions = groups.filter(group => /^navigation/.test(group[0]) && /^status/.test(group[0])).reduce((prev: (MenuItemAction | SubmenuItemAction)[], curr) => { prev.push(...curr[1]); return prev; }, []); + const secondaryActions = groups.filter(group => !/^navigation/.test(group[0]) && !/^status/.test(group[0])).reduce((prev: (MenuItemAction | SubmenuItemAction)[], curr) => { prev.push(...curr[1]); return prev; }, []); this._notebookLeftToolbar.setActions(primaryActions, secondaryActions); this._notebookRightToolbar.setActions(primaryRightActions, []); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts index 6cfebf38da7..bf7dc140594 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellEditorOptions.ts @@ -135,9 +135,16 @@ registerAction2(class ToggleLineNumberAction extends Action2 { precondition: NOTEBOOK_EDITOR_FOCUSED, menu: [{ id: MenuId.EditorTitle, - group: 'LineNumber', + group: 'notebookLayout', order: 0, - when: NOTEBOOK_IS_ACTIVE_EDITOR + when: ContextKeyExpr.and( + NOTEBOOK_IS_ACTIVE_EDITOR, + ContextKeyExpr.notEquals('config.notebook.globalToolbar', true) + ) + }, { + id: MenuId.NotebookToolbar, + group: 'notebookLayout', + when: ContextKeyExpr.equals('config.notebook.globalToolbar', true) }], category: NOTEBOOK_ACTIONS_CATEGORY, f1: true, From 6ed2584f390de2d909f7cce6244806e42f3c396f Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 24 May 2021 14:21:28 -0700 Subject: [PATCH 008/140] fix unit tests. --- .../contrib/notebook/common/notebookOptions.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 5483d660529..56234848c49 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -97,9 +97,9 @@ export class NotebookOptions { constructor(private readonly configurationService: IConfigurationService) { const showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); - const globalToolbar = this.configurationService.getValue(GlobalToolbar); - const consolidatedOutputButton = this.configurationService.getValue(ConsolidatedOutputButton); - const dragAndDropEnabled = this.configurationService.getValue(DragAndDropEnabled); + const globalToolbar = this.configurationService.getValue(GlobalToolbar) ?? false; + const consolidatedOutputButton = this.configurationService.getValue(ConsolidatedOutputButton) ?? true; + const dragAndDropEnabled = this.configurationService.getValue(DragAndDropEnabled) ?? true; const cellToolbarLocation = this.configurationService.getValue(CellToolbarLocKey); const cellToolbarInteraction = this.configurationService.getValue(CellToolbarVisibility); const compactView = this.configurationService.getValue(CompactView); @@ -220,11 +220,11 @@ export class NotebookOptions { } if (globalToolbar) { - configuration.globalToolbar = this.configurationService.getValue(GlobalToolbar); + configuration.globalToolbar = this.configurationService.getValue(GlobalToolbar) ?? false; } if (consolidatedOutputButton) { - configuration.consolidatedOutputButton = this.configurationService.getValue(ConsolidatedOutputButton); + configuration.consolidatedOutputButton = this.configurationService.getValue(ConsolidatedOutputButton) ?? true; } if (showFoldingControls) { @@ -232,7 +232,7 @@ export class NotebookOptions { } if (dragAndDropEnabled) { - configuration.dragAndDropEnabled = this.configurationService.getValue(DragAndDropEnabled); + configuration.dragAndDropEnabled = this.configurationService.getValue(DragAndDropEnabled) ?? true; } if (fontSize) { @@ -259,7 +259,7 @@ export class NotebookOptions { } private _computeInsertToolbarPositionOption() { - return this.configurationService.getValue<'betweenCells' | 'notebookToolbar' | 'both' | 'hidden'>(InsertToolbarPosition); + return this.configurationService.getValue<'betweenCells' | 'notebookToolbar' | 'both' | 'hidden'>(InsertToolbarPosition) ?? 'both'; } private _computeInsertToolbarAlignmentOption() { @@ -267,11 +267,11 @@ export class NotebookOptions { } private _computeShowFoldingControlsOption() { - return this.configurationService.getValue<'always' | 'mouseover'>(ShowFoldingControls); + return this.configurationService.getValue<'always' | 'mouseover'>(ShowFoldingControls) ?? 'always'; } private _computeFocusIndicatorOption() { - return this.configurationService.getValue<'border' | 'gutter'>(FocusIndicator); + return this.configurationService.getValue<'border' | 'gutter'>(FocusIndicator) ?? 'border'; } private _computeBottomToolbarDimensions(compactView: boolean, insertToolbarPosition: 'betweenCells' | 'notebookToolbar' | 'both' | 'hidden', insertToolbarAlignment: 'left' | 'center'): { bottomToolbarGap: number, bottomToolbarHeight: number } { From 196e79256dc9fcda1bdc93f0ac321223d8ff9d56 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 24 May 2021 14:48:28 -0700 Subject: [PATCH 009/140] Add workspacePlatform context key for getting started items Closes #123824 --- .../browser/gettingStartedService.ts | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts index 6d9741aface..484c8c05ee8 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts @@ -9,7 +9,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag import { Memento } from 'vs/workbench/common/memento'; import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { ContextKeyExpr, ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { ContextKeyExpr, ContextKeyExpression, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { Disposable } from 'vs/base/common/lifecycle'; import { IUserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSync'; import { IExtensionDescription, IStartEntry } from 'vs/platform/extensions/common/extensions'; @@ -30,6 +30,11 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { dirname } from 'vs/base/common/path'; import { coalesce, flatten } from 'vs/base/common/arrays'; import { IViewsService } from 'vs/workbench/common/views'; +import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; +import { isLinux, isMacintosh, isWindows, OperatingSystem as OS, platform } from 'vs/base/common/platform'; +import { localize } from 'vs/nls'; + +export const WorkspacePlatform = new RawContextKey<'mac' | 'linux' | 'windows' | undefined>('workspacePlatform', undefined, localize('workspacePlatform', "The platform of the current workspace, which in remote contexts may be different from the platform of the UI")); export const IGettingStartedService = createDecorator('gettingStartedService'); @@ -181,6 +186,7 @@ export class GettingStartedService extends Disposable implements IGettingStarted @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, @IHostService private readonly hostService: IHostService, @IViewsService private readonly viewsService: IViewsService, + @IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService, @optional(ITASExperimentService) tasExperimentService: ITASExperimentService, ) { super(); @@ -227,6 +233,28 @@ export class GettingStartedService extends Disposable implements IGettingStarted e.affectedKeys.forEach(key => { this.progressByEvent('onSettingChanged:' + key); }); })); + this.remoteAgentService.getEnvironment().then(env => { + const remoteOS = env?.os; + + const remotePlatform = + remoteOS === OS.Macintosh ? 'mac' + : remoteOS === OS.Windows ? 'windows' + : remoteOS === OS.Linux ? 'linux' + : undefined; + + if (remotePlatform) { + WorkspacePlatform.bindTo(this.contextService).set(remotePlatform); + } else if (isMacintosh) { + WorkspacePlatform.bindTo(this.contextService).set('mac'); + } else if (isLinux) { + WorkspacePlatform.bindTo(this.contextService).set('linux'); + } else if (isWindows) { + WorkspacePlatform.bindTo(this.contextService).set('windows'); + } else { + WorkspacePlatform.bindTo(this.contextService).set(undefined); + } + }); + if (userDataAutoSyncEnablementService.isEnabled()) { this.progressByEvent('onEvent:sync-enabled'); } this._register(userDataAutoSyncEnablementService.onDidChangeEnablement(() => { if (userDataAutoSyncEnablementService.isEnabled()) { this.progressByEvent('onEvent:sync-enabled'); } From 6cfad71ce615c9de6451e68a8c251bef51b16f7f Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 24 May 2021 14:55:27 -0700 Subject: [PATCH 010/140] notebooks: remove deprecated vscode css vars from webview See https://github.com/microsoft/vscode/issues/107985 https://github.com/microsoft/vscode/issues/93265#issuecomment-847150188 --- .../view/renderers/backLayerWebView.ts | 16 +++++------ .../view/renderers/webviewThemeMapping.ts | 19 +++++++++++-- .../contrib/webview/browser/pre/main.js | 28 +++++++++---------- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 7ff4851f4dc..6c31eb26680 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -660,7 +660,7 @@ export class BackLayerWebView extends Disposable { } dragging { - background-color: var(--vscode-editor-background); + background-color: var(--theme-background); } @@ -682,7 +682,7 @@ export class BackLayerWebView extends Disposable { padding-bottom: var(--notebook-output-node-padding); padding-left: var(--notebook-output-node-left-padding); box-sizing: border-box; - background-color: var(--vscode-notebook-outputContainerBackgroundColor); + background-color: var(--theme-notebook-output-background); } /* markdown */ @@ -697,7 +697,7 @@ export class BackLayerWebView extends Disposable { white-space: nowrap; overflow: hidden; white-space: initial; - color: var(--vscode-foreground); + color: var(--theme-ui-foreground); } #container > div.preview.draggable { @@ -714,11 +714,11 @@ export class BackLayerWebView extends Disposable { } #container > div.preview.selected { - background: var(--vscode-notebook-selectedCellBackground); + background: var(--theme-notebook-cell-selected-background); } #container > div.preview.dragging { - background-color: var(--vscode-editor-background); + background-color: var(--theme-background); } .monaco-workbench.vs-dark .notebookOverlay .cell.markdown .latex img, @@ -727,15 +727,15 @@ export class BackLayerWebView extends Disposable { } #container > div.nb-symbolHighlight { - background-color: var(--vscode-notebook-symbolHighlightBackground); + background-color: var(--theme-notebook-symbol-highlight-background); } #container > div.nb-cellDeleted { - background-color: var(--vscode-diffEditor-removedTextBackground); + background-color: var(--theme-notebook-diff-removed-background); } #container > div.nb-cellAdded { - background-color: var(--vscode-diffEditor-insertedTextBackground); + background-color: var(--theme-notebook-diff-inserted-background); } #container > div > div:not(.preview) > div { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping.ts index 7da964fb6b7..cde518e26f6 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping.ts @@ -5,16 +5,23 @@ import { WebviewStyles } from 'vs/workbench/contrib/webview/browser/webview'; -const mapping: [target: string, src: string][] = [ +const mapping: ReadonlyMap = new Map([ ['theme-font-family', 'vscode-font-family'], ['theme-font-weight', 'vscode-font-weight'], ['theme-font-size', 'vscode-font-size'], ['theme-code-font-family', 'vscode-editor-font-family'], ['theme-code-font-weight', 'vscode-editor-font-weight'], ['theme-code-font-size', 'vscode-editor-font-size'], + ['theme-scrollbar-background', 'vscode-scrollbarSlider-background'], + ['theme-scrollbar-hover-background', 'vscode-scrollbarSlider-hoverBackground'], + ['theme-scrollbar-active-background', 'vscode-scrollbarSlider-activeBackground'], + ['theme-quote-background', 'vscode-textBlockQuote-background'], + ['theme-quote-border', 'vscode-textBlockQuote-border'], + ['theme-code-foreground', 'vscode-textPreformat-foreground'], // Editor ['theme-background', 'vscode-editor-background'], ['theme-foreground', 'vscode-editor-foreground'], + ['theme-ui-foreground', 'vscode-foreground'], ['theme-link', 'vscode-textLink-foreground'], ['theme-link-active', 'vscode-textLink-activeForeground'], // Buttons @@ -47,7 +54,13 @@ const mapping: [target: string, src: string][] = [ ['theme-warning-foreground', 'vscode-foreground'], ['theme-info-background', 'vscode-inputValidation-infoBackground'], ['theme-info-foreground', 'vscode-foreground'], -]; + // Notebook: + ['theme-notebook-output-background', 'vscode-notebook-outputContainerBackgroundColor'], + ['theme-notebook-cell-selected-background', 'vscode-notebook-selectedCellBackground'], + ['theme-notebook-symbol-highlight-background', 'vscode-notebook-symbolHighlightBackground'], + ['theme-notebook-diff-removed-background', 'vscode-diffEditor-removedTextBackground'], + ['theme-notebook-diff-inserted-background', 'vscode-diffEditor-insertedTextBackground'], +]); const constants: Readonly = { 'theme-input-border-width': '1px', @@ -62,7 +75,7 @@ const constants: Readonly = { * @see https://github.com/microsoft/vscode/issues/107985 for context */ export const transformWebviewThemeVars = (s: Readonly): WebviewStyles => { - const result = { ...s, ...constants }; // todo@connor4312: remove after a period of time to allow migration + const result = { ...constants }; for (const [target, src] of mapping) { result[target] = s[src]; } diff --git a/src/vs/workbench/contrib/webview/browser/pre/main.js b/src/vs/workbench/contrib/webview/browser/pre/main.js index 6e7e3273000..f0d25638b98 100644 --- a/src/vs/workbench/contrib/webview/browser/pre/main.js +++ b/src/vs/workbench/contrib/webview/browser/pre/main.js @@ -81,10 +81,10 @@ defaultStyles.textContent = ` body { background-color: transparent; - color: var(--vscode-editor-foreground); - font-family: var(--vscode-font-family); - font-weight: var(--vscode-font-weight); - font-size: var(--vscode-font-size); + color: var(--vscode-editor-foreground, var(--theme-foreground)); + font-family: var(--vscode-font-family, var(--theme-font-family)); + font-weight: var(--vscode-font-weight, var(--theme-font-weight)); + font-size: var(--vscode-font-size, var(--theme-font-size)); margin: 0; padding: 0 20px; } @@ -95,11 +95,11 @@ defaultStyles.textContent = ` } a { - color: var(--vscode-textLink-foreground); + color: var(--vscode-textLink-foreground, var(--theme-link)); } a:hover { - color: var(--vscode-textLink-activeForeground); + color: var(--vscode-textLink-activeForeground, var(--theme-link-active)); } a:focus, @@ -111,16 +111,16 @@ defaultStyles.textContent = ` } code { - color: var(--vscode-textPreformat-foreground); + color: var(--vscode-textPreformat-foreground, var(--theme-code-foreground)); } blockquote { - background: var(--vscode-textBlockQuote-background); - border-color: var(--vscode-textBlockQuote-border); + background: var(--vscode-textBlockQuote-background, var(--theme-quote-background)); + border-color: var(--vscode-textBlockQuote-border, var(--theme-quote-border)); } kbd { - color: var(--vscode-editor-foreground); + color: var(--vscode-editor-foreground, var(--theme-foreground)); border-radius: 3px; vertical-align: middle; padding: 1px 3px; @@ -143,17 +143,17 @@ defaultStyles.textContent = ` } ::-webkit-scrollbar-corner { - background-color: var(--vscode-editor-background); + background-color: var(--vscode-editor-background, var(--theme-background)); } ::-webkit-scrollbar-thumb { - background-color: var(--vscode-scrollbarSlider-background); + background-color: var(--vscode-scrollbarSlider-background, var(--theme-scrollbar-background)); } ::-webkit-scrollbar-thumb:hover { - background-color: var(--vscode-scrollbarSlider-hoverBackground); + background-color: var(--vscode-scrollbarSlider-hoverBackground, var(--theme-scrollbar-hover-background)); } ::-webkit-scrollbar-thumb:active { - background-color: var(--vscode-scrollbarSlider-activeBackground); + background-color: var(--vscode-scrollbarSlider-activeBackground, var(--theme-scrollbar-active-background)); }`; /** From 8b9f8595cc2649246ad002f81c49b9a617ed8e52 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 24 May 2021 14:58:54 -0700 Subject: [PATCH 011/140] Remove unused --- .../welcome/gettingStarted/browser/gettingStartedService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts index 484c8c05ee8..b53d1d88953 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedService.ts @@ -31,7 +31,7 @@ import { dirname } from 'vs/base/common/path'; import { coalesce, flatten } from 'vs/base/common/arrays'; import { IViewsService } from 'vs/workbench/common/views'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { isLinux, isMacintosh, isWindows, OperatingSystem as OS, platform } from 'vs/base/common/platform'; +import { isLinux, isMacintosh, isWindows, OperatingSystem as OS } from 'vs/base/common/platform'; import { localize } from 'vs/nls'; export const WorkspacePlatform = new RawContextKey<'mac' | 'linux' | 'windows' | undefined>('workspacePlatform', undefined, localize('workspacePlatform', "The platform of the current workspace, which in remote contexts may be different from the platform of the UI")); From d28d8802e42f2b75631780d2670d4feb0cf2b29e Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 24 May 2021 15:47:08 -0700 Subject: [PATCH 012/140] testing: add default keybindings --- .../testing/browser/testExplorerActions.ts | 68 +++++++++++++++++-- .../testing/browser/testing.contribution.ts | 7 ++ 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts index 75ed69346af..116624a7866 100644 --- a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts +++ b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts @@ -6,12 +6,13 @@ import { flatten } from 'vs/base/common/arrays'; import { Codicon } from 'vs/base/common/codicons'; import { Iterable } from 'vs/base/common/iterator'; -import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; +import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { isDefined } from 'vs/base/common/types'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; import { Range } from 'vs/editor/common/core/range'; +import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { localize } from 'vs/nls'; -import { Action2, MenuId } from 'vs/platform/actions/common/actions'; +import { Action2, IAction2Options, MenuId } from 'vs/platform/actions/common/actions'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { ContextKeyAndExpr, ContextKeyEqualsExpr, ContextKeyFalseExpr, ContextKeyTrueExpr } from 'vs/platform/contextkey/common/contextkey'; import { IFileService } from 'vs/platform/files/common/files'; @@ -263,13 +264,14 @@ const showDiscoveringWhile = (progress: IProgressService, task: Promise): }; abstract class RunOrDebugAllAllAction extends Action2 { - constructor(id: string, title: string, icon: ThemeIcon, private readonly debug: boolean, private noTestsFoundError: string) { + constructor(id: string, title: string, icon: ThemeIcon, private readonly debug: boolean, private noTestsFoundError: string, keybinding: IAction2Options['keybinding']) { super({ id, title, icon, f1: true, category, + keybinding, menu: { id: MenuId.ViewTitle, order: debug ? ActionOrder.Debug : ActionOrder.Run, @@ -327,6 +329,10 @@ export class RunAllAction extends RunOrDebugAllAllAction { icons.testingRunAllIcon, false, localize('noTestProvider', 'No tests found in this workspace. You may need to install a test provider extension'), + { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_A), + } ); } } @@ -340,6 +346,10 @@ export class DebugAllAction extends RunOrDebugAllAllAction { icons.testingDebugIcon, true, localize('noDebugTestProvider', 'No debuggable tests found in this workspace. You may need to install a test provider extension'), + { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_A), + } ); } } @@ -351,6 +361,10 @@ export class CancelTestRunAction extends Action2 { id: CancelTestRunAction.ID, title: localize('testing.cancelRun', "Cancel Test Run"), icon: icons.testingCancelIcon, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_X), + }, menu: { id: MenuId.ViewTitle, order: ActionOrder.Run, @@ -488,6 +502,10 @@ export class ShowMostRecentOutputAction extends Action2 { f1: true, category, icon: Codicon.terminal, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_O), + }, menu: { id: MenuId.ViewTitle, order: ActionOrder.Collapse, @@ -793,6 +811,11 @@ export class RunAtCursor extends RunOrDebugAtCursor { title: localize('testing.runAtCursor', "Run Test at Cursor"), f1: true, category, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + when: EditorContextKeys.editorTextFocus, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_C), + }, }); } @@ -816,6 +839,11 @@ export class DebugAtCursor extends RunOrDebugAtCursor { title: localize('testing.debugAtCursor', "Debug Test at Cursor"), f1: true, category, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + when: EditorContextKeys.editorTextFocus, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_C), + }, }); } @@ -875,6 +903,11 @@ export class RunCurrentFile extends RunOrDebugCurrentFile { title: localize('testing.runCurrentFile', "Run Tests in Current File"), f1: true, category, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + when: EditorContextKeys.editorTextFocus, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_F), + }, }); } @@ -898,6 +931,11 @@ export class DebugCurrentFile extends RunOrDebugCurrentFile { title: localize('testing.debugCurrentFile', "Debug Tests in Current File"), f1: true, category, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + when: EditorContextKeys.editorTextFocus, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_F), + }, }); } @@ -953,21 +991,21 @@ abstract class RunOrDebugFailedTests extends RunOrDebugExtsById { */ protected getTestExtIdsToRun(accessor: ServicesAccessor): Iterable { const { results } = accessor.get(ITestResultService); - const paths = new Set(); + const paths = new Map(); const sep = '$$TEST SEP$$'; for (let i = results.length - 1; i >= 0; i--) { const resultSet = results[i]; for (const test of resultSet.tests) { const path = getPathForTestInResult(test, resultSet).join(sep); if (isFailedState(test.ownComputedState)) { - paths.add(path); + paths.set(test.item.extId, path); } else { - paths.delete(path); + paths.delete(test.item.extId); } } } - return Iterable.map(paths, p => p.split(sep)); + return Iterable.map(paths.values(), p => p.split(sep)); } } @@ -997,6 +1035,10 @@ export class ReRunFailedTests extends RunOrDebugFailedTests { title: localize('testing.reRunFailTests', "Rerun Failed Tests"), f1: true, category, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_E), + }, }); } @@ -1020,6 +1062,10 @@ export class DebugFailedTests extends RunOrDebugFailedTests { title: localize('testing.debugFailTests', "Debug Failed Tests"), f1: true, category, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_E), + }, }); } @@ -1043,6 +1089,10 @@ export class ReRunLastRun extends RunOrDebugLastRun { title: localize('testing.reRunLastRun', "Rerun Last Run"), f1: true, category, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_L), + }, }); } @@ -1066,6 +1116,10 @@ export class DebugLastRun extends RunOrDebugLastRun { title: localize('testing.debugLastRun', "Debug Last Run"), f1: true, category, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_L), + }, }); } diff --git a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts index 15721c66065..527b889a0ea 100644 --- a/src/vs/workbench/contrib/testing/browser/testing.contribution.ts +++ b/src/vs/workbench/contrib/testing/browser/testing.contribution.ts @@ -54,6 +54,13 @@ const viewContainer = Registry.as(ViewContainerExtensio icon: testingViewIcon, alwaysUseContainerInfo: true, order: 6, + openCommandActionDescriptor: { + id: Testing.ViewletId, + mnemonicTitle: localize({ key: 'miViewTesting', comment: ['&& denotes a mnemonic'] }, "T&&esting"), + // todo: coordinate with joh whether this is available + // keybindings: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_SEMICOLON }, + order: 4, + }, hideIfEmpty: true, }, ViewContainerLocation.Sidebar); From 1da9f2d2e6a6806ef7cc08d37225846cbd2a160f Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Mon, 24 May 2021 16:26:52 -0700 Subject: [PATCH 013/140] Update subscribers.json --- .github/subscribers.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/subscribers.json b/.github/subscribers.json index 7ee6e5cdadd..25c676a47c7 100644 --- a/.github/subscribers.json +++ b/.github/subscribers.json @@ -4,6 +4,7 @@ "rchiodo", "greazer", "donjayamanne", - "jilljac" + "jilljac", + "IanMatthewHuff" ] } From af14bf673ab8855b1ce5152128107b96e6dbc3f4 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 24 May 2021 16:49:02 -0700 Subject: [PATCH 014/140] remove kernel picker config in menu contribution --- .../contrib/notebook/browser/contrib/status/editorStatus.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts index 6c77b8311e5..512f6467348 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts @@ -42,7 +42,6 @@ registerAction2(class extends Action2 { when: ContextKeyExpr.and( NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), - ContextKeyExpr.equals('config.notebook.showKernelInEditorTitle', true), ContextKeyExpr.notEquals('config.notebook.globalToolbar', true) ), group: 'navigation', @@ -51,7 +50,6 @@ registerAction2(class extends Action2 { id: MenuId.NotebookToolbar, when: ContextKeyExpr.and( NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), - ContextKeyExpr.equals('config.notebook.showKernelInEditorTitle', true), ContextKeyExpr.equals('config.notebook.globalToolbar', true) ), group: 'status', From fe3cab25c5f46226366a932446c71dc85459c0c5 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 24 May 2021 17:13:07 -0700 Subject: [PATCH 015/140] compute position/width of output action bar. --- .../contrib/notebook/browser/media/notebook.css | 7 +++++-- .../contrib/notebook/browser/notebookEditorWidget.ts | 10 ++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index 3099ad7e84e..012a0b71fa7 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -263,10 +263,13 @@ position: absolute; top: 4px; left: -32px; - width: 16px; height: 16px; cursor: pointer; - padding: 6px; + padding: 6px 0px; +} + +.monaco-workbench .notebookOverlay .output .cell-output-toolbar .actions-container { + justify-content: center; } .monaco-workbench .notebookOverlay .output pre { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 8345a9b1707..82072073879 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -556,6 +556,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor cellRunGutter, cellBottomMargin, codeCellLeftMargin, + markdownCellLeftMargin, markdownCellBottomMargin, markdownCellTopMargin, bottomToolbarGap: bottomCellToolbarGap, @@ -717,12 +718,17 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor styleSheets.push(`.notebookOverlay .output { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`); styleSheets.push(`.notebookOverlay .output { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`); + // output toolbar + styleSheets.push(`.monaco-workbench .notebookOverlay .output .cell-output-toolbar { left: -${cellRunGutter}px; }`); + styleSheets.push(`.monaco-workbench .notebookOverlay .output .cell-output-toolbar { width: ${cellRunGutter}px; }`); + styleSheets.push(`.notebookOverlay .output-show-more-container { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`); styleSheets.push(`.notebookOverlay .output-show-more-container { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`); - - styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`); styleSheets.push(`.notebookOverlay .cell .run-button-container { width: ${cellRunGutter}px; left: ${codeCellLeftMargin}px }`); styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .execution-count-label { left: ${codeCellLeftMargin}px; width: ${cellRunGutter}px; }`); + + styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`); + styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { left: ${(markdownCellLeftMargin - 20) / 2}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${cellTopMargin}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${bottomCellToolbarGap}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left, From fe41fcc58d6ee4e6aa5a8ce0efe7dd4b7701ff7e Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 24 May 2021 17:22:40 -0700 Subject: [PATCH 016/140] :lipstick: --- .../workbench/contrib/notebook/browser/notebookEditorWidget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 82072073879..49e1d98cf4c 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -658,7 +658,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-right:before, .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-left:before, .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-right:before { - top: 0px; height: 100%px; + top: 0px; height: 100%; }`); } From e9f3fe9f30157bbd2e2033ac4809fb0772929196 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 24 May 2021 17:27:45 -0700 Subject: [PATCH 017/140] rename markdown layout section. --- .../contrib/notebook/browser/notebookEditorWidget.ts | 4 ++-- .../workbench/contrib/notebook/common/notebookOptions.ts | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 49e1d98cf4c..40b99af2831 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -556,7 +556,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor cellRunGutter, cellBottomMargin, codeCellLeftMargin, - markdownCellLeftMargin, + markdownCellGutter, markdownCellBottomMargin, markdownCellTopMargin, bottomToolbarGap: bottomCellToolbarGap, @@ -728,7 +728,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .execution-count-label { left: ${codeCellLeftMargin}px; width: ${cellRunGutter}px; }`); styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`); - styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { left: ${(markdownCellLeftMargin - 20) / 2}px; }`); + styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { left: ${(markdownCellGutter - 20) / 2}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${cellTopMargin}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${bottomCellToolbarGap}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left, diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 56234848c49..1175c23ed00 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -31,7 +31,7 @@ export interface NotebookLayoutConfiguration { cellBottomMargin: number; cellOutputPadding: number; codeCellLeftMargin: number; - markdownCellLeftMargin: number; + markdownCellGutter: number; markdownCellTopMargin: number; markdownCellBottomMargin: number; markdownPreviewPadding: number; @@ -78,7 +78,7 @@ const defaultConfigConstants = { cellRunGutter: 32, markdownCellTopMargin: 8, markdownCellBottomMargin: 8, - markdownCellLeftMargin: 32, + markdownCellGutter: 32, }; const compactConfigConstants = { @@ -86,7 +86,7 @@ const compactConfigConstants = { cellRunGutter: 32, markdownCellTopMargin: 6, markdownCellBottomMargin: 6, - markdownCellLeftMargin: 32, + markdownCellGutter: 32, }; export class NotebookOptions { @@ -384,7 +384,7 @@ export class NotebookOptions { outputNodePadding: this._layoutConfiguration.cellOutputPadding, outputNodeLeftPadding: this._layoutConfiguration.cellOutputPadding, previewNodePadding: this._layoutConfiguration.markdownPreviewPadding, - markdownLeftMargin: this._layoutConfiguration.markdownCellLeftMargin, + markdownLeftMargin: this._layoutConfiguration.markdownCellGutter, leftMargin: this._layoutConfiguration.codeCellLeftMargin, rightMargin: this._layoutConfiguration.cellRightMargin, runGutter: this._layoutConfiguration.cellRunGutter, From 28803975a1ae2aa74cdc48ecf498ef94186730de Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 24 May 2021 18:21:38 -0700 Subject: [PATCH 018/140] Add @feature/notebook --- .../preferences/browser/settingsEditor2.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 1657bc1f187..1b29e99765e 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -92,7 +92,25 @@ export class SettingsEditor2 extends EditorPane { private static CONFIG_SCHEMA_UPDATE_DELAYER = 500; private static readonly SUGGESTIONS: string[] = [ - `@${MODIFIED_SETTING_TAG}`, '@tag:usesOnlineServices', '@tag:sync', `@tag:${REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG}`, `@${ID_SETTING_TAG}`, `@${EXTENSION_SETTING_TAG}`, `@${FEATURE_SETTING_TAG}scm`, `@${FEATURE_SETTING_TAG}explorer`, `@${FEATURE_SETTING_TAG}search`, `@${FEATURE_SETTING_TAG}debug`, `@${FEATURE_SETTING_TAG}extensions`, `@${FEATURE_SETTING_TAG}terminal`, `@${FEATURE_SETTING_TAG}task`, `@${FEATURE_SETTING_TAG}problems`, `@${FEATURE_SETTING_TAG}output`, `@${FEATURE_SETTING_TAG}comments`, `@${FEATURE_SETTING_TAG}remote`, `@${FEATURE_SETTING_TAG}timeline` + `@${MODIFIED_SETTING_TAG}`, + '@tag:usesOnlineServices', + '@tag:sync', + `@tag:${REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG}`, + `@${ID_SETTING_TAG}`, + `@${EXTENSION_SETTING_TAG}`, + `@${FEATURE_SETTING_TAG}scm`, + `@${FEATURE_SETTING_TAG}explorer`, + `@${FEATURE_SETTING_TAG}search`, + `@${FEATURE_SETTING_TAG}debug`, + `@${FEATURE_SETTING_TAG}extensions`, + `@${FEATURE_SETTING_TAG}terminal`, + `@${FEATURE_SETTING_TAG}task`, + `@${FEATURE_SETTING_TAG}problems`, + `@${FEATURE_SETTING_TAG}output`, + `@${FEATURE_SETTING_TAG}comments`, + `@${FEATURE_SETTING_TAG}remote`, + `@${FEATURE_SETTING_TAG}timeline`, + `@${FEATURE_SETTING_TAG}notebook`, ]; private static shouldSettingUpdateFast(type: SettingValueType | SettingValueType[]): boolean { From 8173a0e0398920a00c7422ae5655b5c42b32a1bc Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 24 May 2021 18:22:06 -0700 Subject: [PATCH 019/140] Fix hang when typing incomplete @feature in settings editor Fix #124520 --- .../workbench/contrib/preferences/browser/settingsTreeModels.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index 9a29509d851..8146cf7e1fd 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -701,7 +701,7 @@ export class SearchResultModel extends SettingsTreeModel { const isRemote = !!this.environmentService.remoteAuthority; this.root.children = this.root.children - .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && (this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : true)); + .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && (this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : false)); if (this.newExtensionSearchResults && this.newExtensionSearchResults.filterMatches.length) { const resultExtensionIds = this.newExtensionSearchResults.filterMatches From c3c2113c3687c3559bf036ec72108b40f06a333e Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 24 May 2021 21:33:19 -0700 Subject: [PATCH 020/140] Preserve execution summary when converting dto --- .../workbench/api/common/extHostTypeConverters.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 94bfff83773..8069ae08a73 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1433,6 +1433,18 @@ export namespace NotebookCellMetadata { } } +export namespace NotebookCellInternalMetadata { + + export function to(data: notebooks.NotebookCellInternalMetadata): vscode.NotebookCellExecutionSummary { + return { + endTime: data.runEndTime, + startTime: data.runStartTime, + executionOrder: data.executionOrder, + success: data.lastRunSuccess + }; + } +} + export namespace NotebookDocumentMetadata { export function from(data: types.NotebookDocumentMetadata): notebooks.NotebookDocumentMetadata { @@ -1528,6 +1540,7 @@ export namespace NotebookCellData { data.language, data.outputs ? data.outputs.map(NotebookCellOutput.to) : undefined, data.metadata ? NotebookCellMetadata.to(data.metadata) : undefined, + data.internalMetadata ? NotebookCellInternalMetadata.to(data.internalMetadata) : undefined ); } } From 286b643ecd231f66f3f2e67e1456f3c601838b46 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 25 May 2021 13:41:03 +0900 Subject: [PATCH 021/140] chore: bump electron@12.0.9 Fixes https://github.com/microsoft/vscode/issues/122352 --- .yarnrc | 2 +- cgmanifest.json | 4 ++-- package.json | 2 +- yarn.lock | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.yarnrc b/.yarnrc index 0b7e2206650..ba290809667 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://electronjs.org/headers" -target "12.0.7" +target "12.0.9" runtime "electron" diff --git a/cgmanifest.json b/cgmanifest.json index 474d6191ba5..22cbc50562c 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "8d55658bfa8b5983e1a90ad079c2e2ac91ee7af0" + "commitHash": "30f82dd1cb8140ccb5c6a4960eef8e3b8c15eeba" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "12.0.7" + "version": "12.0.9" }, { "component": { diff --git a/package.json b/package.json index 79c624acda1..3a2019dfa29 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "cssnano": "^4.1.11", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "12.0.7", + "electron": "12.0.9", "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", "event-stream": "3.3.4", diff --git a/yarn.lock b/yarn.lock index 8359b7fa542..43237c320ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3001,10 +3001,10 @@ electron-to-chromium@^1.3.634: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.642.tgz#8b884f50296c2ae2a9997f024d0e3e57facc2b94" integrity sha512-cev+jOrz/Zm1i+Yh334Hed6lQVOkkemk2wRozfMF4MtTR7pxf3r3L5Rbd7uX1zMcEqVJ7alJBnJL7+JffkC6FQ== -electron@12.0.7: - version "12.0.7" - resolved "https://registry.yarnpkg.com/electron/-/electron-12.0.7.tgz#e0fca2c8be34cb7da48c4d15cfb1d2ad666d2718" - integrity sha512-722TZNKDuLpEmj96AzTYFKHaJEH98xgOBH0aldStaPXI1xDFfb9SJQQuirvwFlkwG5OqQdz6Ne3OwwJ7Dbs5nQ== +electron@12.0.9: + version "12.0.9" + resolved "https://registry.yarnpkg.com/electron/-/electron-12.0.9.tgz#d582afa8f6fc0c429606f0961a4c89b376994823" + integrity sha512-p5aEt1tIh/PYjwN+6MHTc5HtW529XR9r4Qlj9PPcSb5ubkotSsS0BtWJoRPhDenSAN8sgHk3sbZLxXPJtdnRYA== dependencies: "@electron/get" "^1.0.1" "@types/node" "^14.6.2" From b1823157d5450eb44297871a93a3280fa71b4f0b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 24 May 2021 22:36:22 -0700 Subject: [PATCH 022/140] Fall back to existing published webview commit (#119295) --- .../vscode-api-tests/src/singlefolder-tests/webview.test.ts | 6 +++--- .../services/environment/browser/environmentService.ts | 2 +- test/integration/browser/src/index.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts index 629fbaace14..f706b64677f 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/webview.test.ts @@ -17,7 +17,7 @@ function workspaceFile(...segments: string[]) { const testDocument = workspaceFile('bower.json'); -suite.skip('vscode API - webview', () => { +suite('vscode API - webview', () => { const disposables: vscode.Disposable[] = []; function _register(disposable: T) { @@ -400,7 +400,7 @@ suite.skip('vscode API - webview', () => { }); } - test('webviews should transfer ArrayBuffers to and from webviews', async () => { + test.skip('webviews should transfer ArrayBuffers to and from webviews', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true })); const ready = getMessage(webview); webview.webview.html = createHtmlDocumentWithBody(/*html*/` @@ -451,7 +451,7 @@ suite.skip('vscode API - webview', () => { } }); - test('webviews should transfer Typed arrays to and from webviews', async () => { + test.skip('webviews should transfer Typed arrays to and from webviews', async () => { const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true })); const ready = getMessage(webview); webview.webview.html = createHtmlDocumentWithBody(/*html*/` diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 0602fedce3e..aa39a5ca577 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -233,7 +233,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment || 'https://{{uuid}}.vscode-webview.net/{{quality}}/{{commit}}/out/vs/workbench/contrib/webview/browser/pre/'; return endpoint - .replace('{{commit}}', this.productService.commit || '97740a7d253650f9f186c211de5247e2577ce9f7') + .replace('{{commit}}', this.payload?.get('webviewExternalEndpointCommit') ?? this.productService.commit ?? '97740a7d253650f9f186c211de5247e2577ce9f7') .replace('{{quality}}', this.productService.quality || 'insider'); } diff --git a/test/integration/browser/src/index.ts b/test/integration/browser/src/index.ts index fae55e5fb98..a9034524657 100644 --- a/test/integration/browser/src/index.ts +++ b/test/integration/browser/src/index.ts @@ -46,7 +46,7 @@ async function runTestsInBrowser(browserType: BrowserType, endpoint: url.UrlWith const testFilesUri = url.format({ pathname: URI.file(path.resolve(optimist.argv.extensionTestsPath)).path, protocol, host, slashes: true }); const folderParam = testWorkspaceUri; - const payloadParam = `[["extensionDevelopmentPath","${testExtensionUri}"],["extensionTestsPath","${testFilesUri}"],["enableProposedApi",""]]`; + const payloadParam = `[["extensionDevelopmentPath","${testExtensionUri}"],["extensionTestsPath","${testFilesUri}"],["enableProposedApi",""],["webviewExternalEndpointCommit","5319757634f77a050b49c10162939bfe60970c29"]]`; await page.goto(`${endpoint.href}&folder=${folderParam}&payload=${payloadParam}`); From 963f30f0871860eabfa9f5ba37cfbe03a115a885 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 09:12:40 +0200 Subject: [PATCH 023/140] :lipstick: --- .../browser/parts/editor/textDiffEditor.ts | 94 +++++++++---------- .../parts/editor/textResourceEditor.ts | 6 +- .../notebook/common/notebookEditorModel.ts | 8 +- .../common/untitledFileWorkingCopy.ts | 2 +- 4 files changed, 53 insertions(+), 57 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index e9a4d85f130..ad59d8f3151 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -9,7 +9,7 @@ import { isFunction, isObject, isArray, assertIsDefined, withUndefinedAsNull } f import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffEditorOptions, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor'; -import { TextEditorOptions, EditorInput, EditorOptions, TEXT_DIFF_EDITOR_ID, IEditorInputFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorInput, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { TextEditorOptions, EditorOptions, TEXT_DIFF_EDITOR_ID, IEditorInputFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorInput, IEditorOpenContext } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; @@ -106,7 +106,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan return this.instantiationService.createInstance(DiffEditorWidget, parent, configuration, {}); } - override async setInput(input: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: DiffEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise {// // Dispose previous diff navigator this.diffNavigatorDisposables.clear(); @@ -125,8 +125,9 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan return undefined; } - // Assert Model Instance - if (!(resolvedModel instanceof TextDiffEditorModel) && this.openAsBinary(input, options)) { + // Fallback to open as binary if not text + if (!(resolvedModel instanceof TextDiffEditorModel)) { + this.openAsBinary(input, options); return undefined; } @@ -165,7 +166,8 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan } catch (error) { // In case we tried to open a file and the response indicates that this is not a text file, fallback to binary diff. - if (this.isFileBinaryError(error) && this.openAsBinary(input, options)) { + if (this.isFileBinaryError(error)) { + this.openAsBinary(input, options); return; } @@ -173,62 +175,54 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan } } - private restoreTextDiffEditorViewState(editor: EditorInput, control: IDiffEditor): boolean { - if (editor instanceof DiffEditorInput) { - const resource = this.toDiffEditorViewStateResource(editor); - if (resource) { - const viewState = this.loadTextEditorViewState(resource); - if (viewState) { - control.restoreViewState(viewState); + private restoreTextDiffEditorViewState(editor: DiffEditorInput, control: IDiffEditor): boolean { + const resource = this.toDiffEditorViewStateResource(editor); + if (resource) { + const viewState = this.loadTextEditorViewState(resource); + if (viewState) { + control.restoreViewState(viewState); - return true; - } + return true; } } return false; } - private openAsBinary(input: EditorInput, options: EditorOptions | undefined): boolean { - if (input instanceof DiffEditorInput) { - const originalInput = input.originalInput; - const modifiedInput = input.modifiedInput; + private openAsBinary(input: DiffEditorInput, options: EditorOptions | undefined): void { + const originalInput = input.originalInput; + const modifiedInput = input.modifiedInput; - const binaryDiffInput = this.instantiationService.createInstance(DiffEditorInput, input.getName(), input.getDescription(), originalInput, modifiedInput, true); + const binaryDiffInput = this.instantiationService.createInstance(DiffEditorInput, input.getName(), input.getDescription(), originalInput, modifiedInput, true); - // Forward binary flag to input if supported - const fileEditorInputFactory = Registry.as(EditorExtensions.EditorInputFactories).getFileEditorInputFactory(); - if (fileEditorInputFactory.isFileEditorInput(originalInput)) { - originalInput.setForceOpenAsBinary(); - } - - if (fileEditorInputFactory.isFileEditorInput(modifiedInput)) { - modifiedInput.setForceOpenAsBinary(); - } - - // Make sure to not steal away the currently active group - // because we are triggering another openEditor() call - // and do not control the initial intent that resulted - // in us now opening as binary. - const preservingOptions: IEditorOptions = { - activation: EditorActivation.PRESERVE, - pinned: this.group?.isPinned(input), - sticky: this.group?.isSticky(input) - }; - - if (options) { - options.overwrite(preservingOptions); - } else { - options = EditorOptions.create(preservingOptions); - } - - // Replace this editor with the binary one - this.editorService.replaceEditors([{ editor: input, replacement: binaryDiffInput, options }], this.group || ACTIVE_GROUP); - - return true; + // Forward binary flag to input if supported + const fileEditorInputFactory = Registry.as(EditorExtensions.EditorInputFactories).getFileEditorInputFactory(); + if (fileEditorInputFactory.isFileEditorInput(originalInput)) { + originalInput.setForceOpenAsBinary(); } - return false; + if (fileEditorInputFactory.isFileEditorInput(modifiedInput)) { + modifiedInput.setForceOpenAsBinary(); + } + + // Make sure to not steal away the currently active group + // because we are triggering another openEditor() call + // and do not control the initial intent that resulted + // in us now opening as binary. + const preservingOptions: IEditorOptions = { + activation: EditorActivation.PRESERVE, + pinned: this.group?.isPinned(input), + sticky: this.group?.isSticky(input) + }; + + if (options) { + options.overwrite(preservingOptions); + } else { + options = EditorOptions.create(preservingOptions); + } + + // Replace this editor with the binary one + this.editorService.replaceEditors([{ editor: input, replacement: binaryDiffInput, options }], this.group || ACTIVE_GROUP); } protected override computeConfiguration(configuration: IEditorConfiguration): ICodeEditorOptions { diff --git a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts index fd82899eddd..009b646894a 100644 --- a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { assertIsDefined, isFunction, withNullAsUndefined } from 'vs/base/common/types'; import { ICodeEditor, getCodeEditor, IPasteEvent } from 'vs/editor/browser/editorBrowser'; import { TextEditorOptions, EditorInput, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; -import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; +import { AbstractTextResourceEditorInput, TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; @@ -53,7 +53,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor { return localize('textEditor', "Text Editor"); } - override async setInput(input: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: AbstractTextResourceEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { // Remember view settings if input changes this.saveTextResourceEditorViewState(this.input); @@ -97,7 +97,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor { textEditor.updateOptions({ readOnly: resolvedModel.isReadonly() }); } - private restoreTextResourceEditorViewState(editor: EditorInput, control: IEditor) { + private restoreTextResourceEditorViewState(editor: AbstractTextResourceEditorInput, control: IEditor) { if (editor instanceof UntitledTextEditorInput || editor instanceof TextResourceEditorInput) { const viewState = this.loadTextEditorViewState(editor.resource); if (viewState) { diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index b0684bbf13f..7c0f047114c 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -23,7 +23,7 @@ import { TaskSequentializer } from 'vs/base/common/async'; import { bufferToStream, streamToBuffer, VSBuffer, VSBufferReadableStream } from 'vs/base/common/buffer'; import { assertType } from 'vs/base/common/types'; import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService'; -import { StoredFileWorkingCopy, StoredFileWorkingCopyState, IStoredFileWorkingCopy, IStoredFileWorkingCopyModel, IStoredFileWorkingCopyModelContentChangedEvent, IStoredFileWorkingCopyModelFactory } from 'vs/workbench/services/workingCopy/common/storedFileWorkingCopy'; +import { StoredFileWorkingCopyState, IStoredFileWorkingCopy, IStoredFileWorkingCopyModel, IStoredFileWorkingCopyModelContentChangedEvent, IStoredFileWorkingCopyModelFactory } from 'vs/workbench/services/workingCopy/common/storedFileWorkingCopy'; import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { canceled } from 'vs/base/common/errors'; import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; @@ -518,8 +518,10 @@ export class SimpleNotebookEditorModel extends EditorModel implements INotebookE return this._instantiationService.createInstance(NotebookEditorInput, newWorkingCopy.resource, this.viewType, {}); } - private static _isStoredFileWorkingCopy(candidate?: unknown): candidate is IStoredFileWorkingCopy { - return candidate instanceof StoredFileWorkingCopy; + private static _isStoredFileWorkingCopy(candidate?: IStoredFileWorkingCopy | IUntitledFileWorkingCopy): candidate is IStoredFileWorkingCopy { + const isUntitled = candidate && candidate.capabilities & WorkingCopyCapabilities.Untitled; + + return !isUntitled; } } diff --git a/src/vs/workbench/services/workingCopy/common/untitledFileWorkingCopy.ts b/src/vs/workbench/services/workingCopy/common/untitledFileWorkingCopy.ts index 2ce885dc70b..de26fda357f 100644 --- a/src/vs/workbench/services/workingCopy/common/untitledFileWorkingCopy.ts +++ b/src/vs/workbench/services/workingCopy/common/untitledFileWorkingCopy.ts @@ -76,7 +76,7 @@ export interface IUntitledFileWorkingCopySaveDelegate extends Disposable implements IUntitledFileWorkingCopy { - readonly capabilities: WorkingCopyCapabilities = WorkingCopyCapabilities.Untitled; + readonly capabilities = WorkingCopyCapabilities.Untitled; private _model: M | undefined = undefined; get model(): M | undefined { return this._model; } From 76523deb91ec56dcdbb76c02a49751fae272afa4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 May 2021 00:17:17 -0700 Subject: [PATCH 024/140] Bump browserslist from 4.16.1 to 4.16.6 (#124550) Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.16.1 to 4.16.6. - [Release notes](https://github.com/browserslist/browserslist/releases) - [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md) - [Commits](https://github.com/browserslist/browserslist/compare/4.16.1...4.16.6) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/yarn.lock b/yarn.lock index 43237c320ab..ba840aea436 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1631,15 +1631,15 @@ browserify-zlib@^0.2.0: pako "~1.0.5" browserslist@^4.0.0: - version "4.16.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766" - integrity sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA== + version "4.16.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" + integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== dependencies: - caniuse-lite "^1.0.30001173" - colorette "^1.2.1" - electron-to-chromium "^1.3.634" + caniuse-lite "^1.0.30001219" + colorette "^1.2.2" + electron-to-chromium "^1.3.723" escalade "^3.1.1" - node-releases "^1.1.69" + node-releases "^1.1.71" buffer-crc32@~0.2.3: version "0.2.13" @@ -1817,10 +1817,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001173: - version "1.0.30001179" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001179.tgz#b0803883b4471a6c62066fb1752756f8afc699c8" - integrity sha512-blMmO0QQujuUWZKyVrD1msR4WNDAqb/UPO1Sw2WWsQ7deoM5bJiicKnWJ1Y0NS/aGINSnKPIWBMw5luX+NDUCA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001219: + version "1.0.30001228" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz#bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa" + integrity sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A== caseless@~0.12.0: version "0.12.0" @@ -2174,10 +2174,10 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.4" -colorette@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" - integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== +colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== combined-stream@^1.0.6, combined-stream@~1.0.6: version "1.0.8" @@ -2996,10 +2996,10 @@ editorconfig@^0.15.2: semver "^5.6.0" sigmund "^1.0.1" -electron-to-chromium@^1.3.634: - version "1.3.642" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.642.tgz#8b884f50296c2ae2a9997f024d0e3e57facc2b94" - integrity sha512-cev+jOrz/Zm1i+Yh334Hed6lQVOkkemk2wRozfMF4MtTR7pxf3r3L5Rbd7uX1zMcEqVJ7alJBnJL7+JffkC6FQ== +electron-to-chromium@^1.3.723: + version "1.3.737" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.737.tgz#196f2e9656f4f3c31930750e1899c091b72d36b5" + integrity sha512-P/B84AgUSQXaum7a8m11HUsYL8tj9h/Pt5f7Hg7Ty6bm5DxlFq+e5+ouHUoNQMsKDJ7u4yGfI8mOErCmSH9wyg== electron@12.0.9: version "12.0.9" @@ -6567,10 +6567,10 @@ node-pty@0.11.0-beta7: dependencies: nan "^2.14.0" -node-releases@^1.1.69: - version "1.1.70" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" - integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw== +node-releases@^1.1.71: + version "1.1.72" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" + integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== node.extend@~1.1.2: version "1.1.8" From 0bada155580c70e12401f4e2a9ede222b8353530 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 25 May 2021 09:22:33 +0200 Subject: [PATCH 025/140] more API todos --- src/vs/vscode.proposed.d.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 94096b84ecf..91d7e3abfe5 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1274,7 +1274,7 @@ declare module 'vscode' { * @param mime Optional MIME type, defaults to `application/octet-stream`. * @returns A new output item object. */ - //todo@API better names: bytes, raw, buffer? + //todo@API REMOVE, dupe ctor static bytes(value: Uint8Array, mime?: string): NotebookCellOutputItem; /** @@ -1317,10 +1317,13 @@ declare module 'vscode' { * The value of this output item. Must always be an array of unsigned 8-bit integers. */ //todo@API only Unit8Array + //todo@API RENAME to data value: Uint8Array | unknown; metadata?: { [key: string]: any }; + //todo@API RENAME to data + //todo@API swap args /** * Create a new notbook cell output item. * @@ -1654,6 +1657,7 @@ declare module 'vscode' { * @param cell The notebook cell for which to create the execution. * @returns A notebook cell execution. */ + // todo@API rename to NotebookCellExecution createNotebookCellExecutionTask(cell: NotebookCell): NotebookCellExecutionTask; // todo@API find a better name than "preloads" From e0f751f12875370eb9b501a238299b4c442c0cc8 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 09:26:18 +0200 Subject: [PATCH 026/140] editors - introduce and adopt capabilities --- src/vs/workbench/browser/contextkeys.ts | 4 +- .../browser/parts/editor/editorActions.ts | 4 +- .../browser/parts/editor/editorAutoSave.ts | 4 +- .../browser/parts/editor/editorCommands.ts | 4 +- .../browser/parts/editor/editorControl.ts | 6 +- .../browser/parts/editor/editorDropTarget.ts | 4 +- .../browser/parts/editor/editorGroupView.ts | 4 +- .../browser/parts/editor/editorStatus.ts | 10 +- .../browser/parts/editor/textDiffEditor.ts | 10 +- .../browser/parts/editor/textEditor.ts | 4 +- src/vs/workbench/common/editor.ts | 153 ++++++++++-------- .../common/editor/resourceEditorInput.ts | 30 ++-- .../customEditor/browser/customEditorInput.ts | 28 ++-- .../extensions/common/extensionsInput.ts | 10 +- .../common/runtimeExtensionsInput.ts | 10 +- .../files/browser/editors/fileEditorInput.ts | 28 ++-- .../files/browser/editors/textFileEditor.ts | 4 +- .../contrib/files/browser/fileCommands.ts | 6 +- .../files/browser/views/openEditorsView.ts | 4 +- .../browser/notebookDiffEditorInput.ts | 22 +-- .../notebook/browser/notebookEditor.ts | 8 +- .../notebook/common/notebookEditorInput.ts | 40 +++-- .../searchEditor/browser/searchEditor.ts | 4 +- .../searchEditor/browser/searchEditorInput.ts | 25 ++- .../browser/webviewEditorInput.ts | 10 +- .../services/editor/browser/editorService.ts | 10 +- .../test/browser/parts/editor/editor.test.ts | 55 ++++++- .../browser/parts/editor/editorPane.test.ts | 7 +- ...orInput.ts => resourceEditorInput.test.ts} | 6 +- .../test/browser/workbenchTestServices.ts | 10 +- 30 files changed, 309 insertions(+), 215 deletions(-) rename src/vs/workbench/test/browser/parts/editor/{resourceEditorInput.ts => resourceEditorInput.test.ts} (88%) diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index 46cd14f0600..847d044083f 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -8,7 +8,7 @@ import { Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext } from 'vs/platform/contextkey/common/contextkeys'; -import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext } from 'vs/workbench/common/editor'; +import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { trackFocus, addDisposableListener, EventType, WebFileSystemAccess } from 'vs/base/browser/dom'; import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -241,7 +241,7 @@ export class WorkbenchContextKeysHandler extends Disposable { if (activeEditorPane) { this.activeEditorContext.set(activeEditorPane.getId()); - this.activeEditorIsReadonly.set(activeEditorPane.input.isReadonly()); + this.activeEditorIsReadonly.set(activeEditorPane.input.hasCapability(EditorInputCapabilities.Readonly)); const activeEditorResource = activeEditorPane.input.resource; const editors = activeEditorResource ? this.editorOverrideService.getEditorIds(activeEditorResource) : []; diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index df9038eb81d..8e5196cb0b3 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -5,7 +5,7 @@ import { localize } from 'vs/nls'; import { Action } from 'vs/base/common/actions'; -import { IEditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason, EditorsOrder, SideBySideEditorInput, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason, EditorsOrder, SideBySideEditorInput, EditorInputCapabilities, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -594,7 +594,7 @@ abstract class BaseCloseAllAction extends Action { // Auto-save on focus change: assume to Save unless the editor is untitled // because bringing up a dialog would save in this case anyway. - if (this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.ON_FOCUS_CHANGE && !editor.isUntitled()) { + if (this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.ON_FOCUS_CHANGE && !editor.hasCapability(EditorInputCapabilities.Untitled)) { dirtyEditorsToAutoSave.add(editor); } diff --git a/src/vs/workbench/browser/parts/editor/editorAutoSave.ts b/src/vs/workbench/browser/parts/editor/editorAutoSave.ts index 8bddd352872..09ffc4af2a2 100644 --- a/src/vs/workbench/browser/parts/editor/editorAutoSave.ts +++ b/src/vs/workbench/browser/parts/editor/editorAutoSave.ts @@ -7,7 +7,7 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { Disposable, DisposableStore, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; import { IFilesConfigurationService, AutoSaveMode, IAutoSaveConfiguration } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { SaveReason, IEditorIdentifier, IEditorInput, GroupIdentifier, ISaveOptions } from 'vs/workbench/common/editor'; +import { SaveReason, IEditorIdentifier, IEditorInput, GroupIdentifier, ISaveOptions, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { withNullAsUndefined } from 'vs/base/common/types'; @@ -90,7 +90,7 @@ export class EditorAutoSave extends Disposable implements IWorkbenchContribution } private maybeTriggerAutoSave(reason: SaveReason, editorIdentifier?: IEditorIdentifier): void { - if (editorIdentifier && (editorIdentifier.editor.isReadonly() || editorIdentifier.editor.isUntitled())) { + if (editorIdentifier?.editor.hasCapability(EditorInputCapabilities.Readonly) || editorIdentifier?.editor.hasCapability(EditorInputCapabilities.Untitled)) { return; // no auto save for readonly or untitled editors } diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 34f61e1ec8a..32e73326a59 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { isObject, isString, isUndefined, isNumber, withNullAsUndefined } from 'vs/base/common/types'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { TextCompareEditorVisibleContext, EditorInput, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane, ActiveEditorStickyContext, EditorsOrder, viewColumnToEditorGroup, EditorGroupColumn } from 'vs/workbench/common/editor'; +import { TextCompareEditorVisibleContext, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane, ActiveEditorStickyContext, EditorsOrder, viewColumnToEditorGroup, EditorGroupColumn, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor'; @@ -632,7 +632,7 @@ export function splitEditor(editorGroupService: IEditorGroupsService, direction: } // Copy the editor to the new group, else create an empty group - if (editorToCopy && (editorToCopy as EditorInput).canSplit()) { + if (editorToCopy && !editorToCopy.hasCapability(EditorInputCapabilities.Singleton)) { sourceGroup.copyEditor(editorToCopy, newGroup); } diff --git a/src/vs/workbench/browser/parts/editor/editorControl.ts b/src/vs/workbench/browser/parts/editor/editorControl.ts index e6dcdc9c47a..00350cf59ac 100644 --- a/src/vs/workbench/browser/parts/editor/editorControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorControl.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { EditorExtensions, EditorInput, EditorOptions, IEditorOpenContext, IVisibleEditorPane } from 'vs/workbench/common/editor'; +import { EditorExtensions, EditorInput, EditorInputCapabilities, EditorOptions, IEditorOpenContext, IVisibleEditorPane } from 'vs/workbench/common/editor'; import { Dimension, show, hide } from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; import { IEditorRegistry, IEditorDescriptor } from 'vs/workbench/browser/editor'; @@ -72,7 +72,7 @@ export class EditorControl extends Disposable { // to handle errors properly. const editor = this._activeEditorPane?.input; const options = this._activeEditorPane?.options; - if (editor?.requiresWorkspaceTrust()) { + if (editor?.hasCapability(EditorInputCapabilities.RequiresTrust)) { this.groupView.openEditor(editor, options); } } @@ -91,7 +91,7 @@ export class EditorControl extends Disposable { } private getEditorDescriptor(editor: EditorInput): IEditorDescriptor { - if (editor.requiresWorkspaceTrust() && !this.workspaceTrustService.isWorkpaceTrusted()) { + if (editor.hasCapability(EditorInputCapabilities.RequiresTrust) && !this.workspaceTrustService.isWorkpaceTrusted()) { // Workspace trust: if an editor signals it needs workspace trust // but the current workspace is untrusted, we fallback to a generic // editor descriptor to indicate this an do NOT load the registered diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index dd119d85c00..3aa25a20977 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -10,7 +10,7 @@ import { IEditorGroupsAccessor, IEditorGroupView, getActiveTextEditorOptions } f import { EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; import { IThemeService, Themable } from 'vs/platform/theme/common/themeService'; import { activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { IEditorIdentifier, EditorInput, EditorOptions } from 'vs/workbench/common/editor'; +import { IEditorIdentifier, EditorOptions, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { isMacintosh, isWeb } from 'vs/base/common/platform'; import { GroupDirection, IEditorGroupsService, MergeGroupMode } from 'vs/workbench/services/editor/common/editorGroupsService'; import { toDisposable } from 'vs/base/common/lifecycle'; @@ -361,7 +361,7 @@ class DropOverlay extends Themable { } private isCopyOperation(e: DragEvent, draggedEditor?: IEditorIdentifier): boolean { - if (draggedEditor?.editor instanceof EditorInput && !draggedEditor.editor.canSplit()) { + if (draggedEditor?.editor.hasCapability(EditorInputCapabilities.Singleton)) { return false; } diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 7fda31b15b7..169b052dae4 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/editorgroupview'; import { EditorGroupModel, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroupModel, isSerializedEditorGroupModel } from 'vs/workbench/common/editor/editorGroupModel'; -import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, EditorResourceAccessor, IEditorMoveEvent, IEditorOpenEvent } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, EditorResourceAccessor, IEditorMoveEvent, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; import { Event, Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor, asCSSUrl } from 'vs/base/browser/dom'; @@ -1443,7 +1443,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { let confirmation: ConfirmResult; let saveReason = SaveReason.EXPLICIT; let autoSave = false; - if (this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.ON_FOCUS_CHANGE && !editor.isUntitled() && !options?.skipAutoSave) { + if (this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.ON_FOCUS_CHANGE && !editor.hasCapability(EditorInputCapabilities.Untitled) && !options?.skipAutoSave) { autoSave = true; confirmation = ConfirmResult.SAVE; saveReason = SaveReason.FOCUS_CHANGE; diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 75d2c9bc6a4..6552926b63d 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri'; import { Action, WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions'; import { Language } from 'vs/base/common/platform'; import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput'; -import { IFileEditorInput, EditorResourceAccessor, SideBySideEditorInput, IEditorPane, IEditorInput, SideBySideEditor } from 'vs/workbench/common/editor'; +import { IFileEditorInput, EditorResourceAccessor, SideBySideEditorInput, IEditorPane, IEditorInput, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { Disposable, MutableDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IEditorAction } from 'vs/editor/common/editorCommon'; import { EndOfLineSequence } from 'vs/editor/common/model'; @@ -369,7 +369,7 @@ export class EditorStatus extends Disposable implements IWorkbenchContribution { return this.quickInputService.pick([{ label: localize('noEditor', "No text editor active at this time") }]); } - if (this.editorService.activeEditor?.isReadonly()) { + if (this.editorService.activeEditor?.hasCapability(EditorInputCapabilities.Readonly)) { return this.quickInputService.pick([{ label: localize('noWritableCodeEditor', "The active code editor is read-only.") }]); } @@ -1279,7 +1279,7 @@ export class ChangeEOLAction extends Action { return; } - if (this.editorService.activeEditor?.isReadonly()) { + if (this.editorService.activeEditor?.hasCapability(EditorInputCapabilities.Readonly)) { await this.quickInputService.pick([{ label: localize('noWritableCodeEditor', "The active code editor is read-only.") }]); return; } @@ -1296,7 +1296,7 @@ export class ChangeEOLAction extends Action { const eol = await this.quickInputService.pick(EOLOptions, { placeHolder: localize('pickEndOfLine', "Select End of Line Sequence"), activeItem: EOLOptions[selectedIndex] }); if (eol) { const activeCodeEditor = getCodeEditor(this.editorService.activeTextEditorControl); - if (activeCodeEditor?.hasModel() && !this.editorService.activeEditor?.isReadonly()) { + if (activeCodeEditor?.hasModel() && !this.editorService.activeEditor?.hasCapability(EditorInputCapabilities.Readonly)) { textModel = activeCodeEditor.getModel(); textModel.pushStackElement(); textModel.pushEOL(eol.eol); @@ -1362,7 +1362,7 @@ export class ChangeEncodingAction extends Action { let action: IQuickPickItem | undefined; if (encodingSupport instanceof UntitledTextEditorInput) { action = saveWithEncodingPick; - } else if (activeEditorPane.input.isReadonly()) { + } else if (activeEditorPane.input.hasCapability(EditorInputCapabilities.Readonly)) { action = reopenWithEncodingPick; } else { action = await this.quickInputService.pick([reopenWithEncodingPick, saveWithEncodingPick], { placeHolder: localize('pickAction', "Select Action"), matchOnDetail: true }); diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index ad59d8f3151..12cbedcb79a 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -9,7 +9,7 @@ import { isFunction, isObject, isArray, assertIsDefined, withUndefinedAsNull } f import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffEditorOptions, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor'; -import { TextEditorOptions, EditorOptions, TEXT_DIFF_EDITOR_ID, IEditorInputFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorInput, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { TextEditorOptions, EditorOptions, TEXT_DIFF_EDITOR_ID, IEditorInputFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; @@ -79,8 +79,8 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan if (control && input instanceof DiffEditorInput) { if (input.originalInput.resource?.scheme === scheme || input.modifiedInput.resource?.scheme === scheme) { control.updateOptions({ - readOnly: input.modifiedInput.isReadonly(), - originalEditable: !input.originalInput.isReadonly() + readOnly: input.modifiedInput.hasCapability(EditorInputCapabilities.Readonly), + originalEditable: !input.originalInput.hasCapability(EditorInputCapabilities.Readonly) }); } } @@ -249,8 +249,8 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan protected override getConfigurationOverrides(): ICodeEditorOptions { const options: IDiffEditorOptions = super.getConfigurationOverrides(); - options.readOnly = this.input instanceof DiffEditorInput && this.input.modifiedInput.isReadonly(); - options.originalEditable = this.input instanceof DiffEditorInput && !this.input.originalInput.isReadonly(); + options.readOnly = this.input instanceof DiffEditorInput && this.input.modifiedInput.hasCapability(EditorInputCapabilities.Readonly); + options.originalEditable = this.input instanceof DiffEditorInput && !this.input.originalInput.hasCapability(EditorInputCapabilities.Readonly); options.lineDecorationsWidth = '2ch'; return options; diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index 756d2efd318..efd4885ae85 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -10,7 +10,7 @@ import { Event } from 'vs/base/common/event'; import { isObject, assertIsDefined, withNullAsUndefined, isFunction } from 'vs/base/common/types'; import { Dimension } from 'vs/base/browser/dom'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; -import { EditorInput, EditorOptions, IEditorMemento, ITextEditorPane, TextEditorOptions, IEditorCloseEvent, IEditorInput, IEditorOpenContext, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, IEditorMemento, ITextEditorPane, TextEditorOptions, IEditorCloseEvent, IEditorInput, IEditorOpenContext, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { computeEditorAriaLabel } from 'vs/workbench/browser/editor'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { IEditorViewState, IEditor, ScrollType } from 'vs/editor/common/editorCommon'; @@ -120,7 +120,7 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa overviewRulerLanes: 3, lineNumbersMinChars: 3, fixedOverflowWidgets: true, - readOnly: this.input?.isReadonly(), + readOnly: this.input?.hasCapability(EditorInputCapabilities.Readonly), // render problems even in readonly editors // https://github.com/microsoft/vscode/issues/89057 renderValidationDecorations: 'on' diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 22d8657b34e..5b06d29f964 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -367,6 +367,35 @@ export interface IMoveResult { options?: IEditorOptions; } +export const enum EditorInputCapabilities { + + /** + * Signals no specific capability for the input. + */ + None = 0, + + /** + * Signals that the input is readonly. + */ + Readonly = 1 << 1, + + /** + * Signals that the input is untitled. + */ + Untitled = 1 << 2, + + /** + * Signals that the input can only be shown in one group + * and not be split into multiple groups. + */ + Singleton = 1 << 3, + + /** + * Signals that the input requires workspace trust. + */ + RequiresTrust = 1 << 4, +} + export interface IEditorInput extends IDisposable { /** @@ -405,6 +434,16 @@ export interface IEditorInput extends IDisposable { */ readonly resource: URI | undefined; + /** + * The capabilities of the input. + */ + readonly capabilities: EditorInputCapabilities; + + /** + * Figure out if the input has the provided capability. + */ + hasCapability(capability: EditorInputCapabilities): boolean; + /** * Returns the display name of this input. */ @@ -432,21 +471,6 @@ export interface IEditorInput extends IDisposable { */ resolve(): Promise; - /** - * Returns if the input requires workspace trust or not. - */ - requiresWorkspaceTrust(): boolean - - /** - * Returns if this input is readonly or not. - */ - isReadonly(): boolean; - - /** - * Returns if the input is an untitled editor or not. - */ - isUntitled(): boolean; - /** * Returns if this input is dirty or not. */ @@ -498,9 +522,9 @@ export interface IEditorInput extends IDisposable { rename(group: GroupIdentifier, target: URI): IMoveResult | undefined; /** - * Subclasses can set this to false if it does not make sense to split the editor input. + * Returns a copy of the current editor input. Used when we can't just reuse the input */ - canSplit(): boolean; + copy(): IEditorInput; /** * Returns if the other object matches this input. @@ -511,11 +535,6 @@ export interface IEditorInput extends IDisposable { * Returns if this editor is disposed. */ isDisposed(): boolean; - - /** - * Returns a copy of the current editor input. Used when we can't just reuse the input - */ - copy(): IEditorInput; } /** @@ -539,6 +558,18 @@ export abstract class EditorInput extends Disposable implements IEditorInput { abstract get resource(): URI | undefined; + get capabilities(): EditorInputCapabilities { + return EditorInputCapabilities.Readonly; + } + + hasCapability(capability: EditorInputCapabilities): boolean { + if (capability === EditorInputCapabilities.None) { + return this.capabilities === EditorInputCapabilities.None; + } + + return (this.capabilities & capability) !== 0; + } + getName(): string { return `Editor ${this.typeId}`; } @@ -577,18 +608,6 @@ export abstract class EditorInput extends Disposable implements IEditorInput { return { typeId: this.typeId }; } - requiresWorkspaceTrust(): boolean { - return false; - } - - isReadonly(): boolean { - return true; - } - - isUntitled(): boolean { - return false; - } - isDirty(): boolean { return false; } @@ -615,18 +634,14 @@ export abstract class EditorInput extends Disposable implements IEditorInput { return undefined; } - canSplit(): boolean { - return true; + copy(): IEditorInput { + return this; } matches(otherInput: unknown): boolean { return this === otherInput; } - copy(): IEditorInput { - return this; - } - isDisposed(): boolean { return this.disposed; } @@ -738,6 +753,36 @@ export class SideBySideEditorInput extends EditorInput { return SideBySideEditorInput.ID; } + override get capabilities(): EditorInputCapabilities { + + // Use primary capabilities as main capabilities + let capabilities = this._primary.capabilities; + + // Trust: should be considered for both sides + if (this._secondary.hasCapability(EditorInputCapabilities.RequiresTrust)) { + capabilities |= EditorInputCapabilities.RequiresTrust; + } + + // Singleton: should be considered for both sides + if (this._secondary.hasCapability(EditorInputCapabilities.Singleton)) { + capabilities |= EditorInputCapabilities.Singleton; + } + + return capabilities; + } + + get resource(): URI | undefined { + return undefined; // use `EditorResourceAccessor` to obtain one side's resource + } + + get primary(): EditorInput { + return this._primary; + } + + get secondary(): EditorInput { + return this._secondary; + } + constructor( protected readonly name: string | undefined, protected readonly description: string | undefined, @@ -771,22 +816,6 @@ export class SideBySideEditorInput extends EditorInput { this._register(this.primary.onDidChangeLabel(() => this._onDidChangeLabel.fire())); } - /** - * Use `EditorResourceAccessor` utility method to access the resources - * of both sides of the diff editor. - */ - get resource(): URI | undefined { - return undefined; - } - - get primary(): EditorInput { - return this._primary; - } - - get secondary(): EditorInput { - return this._secondary; - } - override getName(): string { if (!this.name) { return localize('sideBySideLabels', "{0} - {1}", this._secondary.getName(), this._primary.getName()); @@ -799,18 +828,6 @@ export class SideBySideEditorInput extends EditorInput { return this.description; } - override requiresWorkspaceTrust(): boolean { - return this.primary.requiresWorkspaceTrust() || this.secondary.requiresWorkspaceTrust(); - } - - override isReadonly(): boolean { - return this.primary.isReadonly(); - } - - override isUntitled(): boolean { - return this.primary.isUntitled(); - } - override isDirty(): boolean { return this.primary.isDirty(); } diff --git a/src/vs/workbench/common/editor/resourceEditorInput.ts b/src/vs/workbench/common/editor/resourceEditorInput.ts index dcc12fdcac3..c03a97de99c 100644 --- a/src/vs/workbench/common/editor/resourceEditorInput.ts +++ b/src/vs/workbench/common/editor/resourceEditorInput.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { EditorInput, Verbosity, IEditorInputWithPreferredResource } from 'vs/workbench/common/editor'; +import { EditorInput, Verbosity, IEditorInputWithPreferredResource, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; import { IFileService, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; import { ILabelService } from 'vs/platform/label/common/label'; @@ -18,6 +18,20 @@ export abstract class AbstractResourceEditorInput extends EditorInput implements private _preferredResource: URI; get preferredResource(): URI { return this._preferredResource; } + override get capabilities(): EditorInputCapabilities { + let capabilities = EditorInputCapabilities.None; + + if (this.fileService.canHandleResource(this.resource)) { + if (this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly)) { + capabilities |= EditorInputCapabilities.Readonly; + } + } else { + capabilities |= EditorInputCapabilities.Untitled; + } + + return capabilities; + } + constructor( readonly resource: URI, preferredResource: URI | undefined, @@ -156,24 +170,12 @@ export abstract class AbstractResourceEditorInput extends EditorInput implements } private decorateLabel(label: string): string { - const readonly = this.isReadonly(); + const readonly = this.hasCapability(EditorInputCapabilities.Readonly); const orphaned = this.isOrphaned(); return decorateFileEditorLabel(label, { orphaned, readonly }); } - override isUntitled(): boolean { - return !this.fileService.canHandleResource(this.resource); - } - - override isReadonly(): boolean { - if (this.isUntitled()) { - return false; // untitled is never readonly - } - - return this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly); - } - isOrphaned(): boolean { return false; } diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index e19caa20fc8..b40dbba7bc2 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -16,7 +16,7 @@ import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILabelService } from 'vs/platform/label/common/label'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; -import { GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, Verbosity } from 'vs/workbench/common/editor'; +import { EditorInputCapabilities, GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, Verbosity } from 'vs/workbench/common/editor'; import { decorateFileEditorLabel } from 'vs/workbench/common/editor/resourceEditorInput'; import { defaultCustomEditor } from 'vs/workbench/contrib/customEditor/common/contributedCustomEditors'; import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; @@ -91,8 +91,22 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { return CustomEditorInput.typeId; } - public override canSplit() { - return !!this.customEditorService.getCustomEditorCapabilities(this.viewType)?.supportsMultipleEditorsPerDocument; + public override get capabilities(): EditorInputCapabilities { + let capabilities = EditorInputCapabilities.None; + + if (!this.customEditorService.getCustomEditorCapabilities(this.viewType)?.supportsMultipleEditorsPerDocument) { + capabilities |= EditorInputCapabilities.Singleton; + } + + if (this._modelRef && !this._modelRef.object.isEditable()) { + capabilities |= EditorInputCapabilities.Readonly; + } + + if (this.resource.scheme === Schemas.untitled) { + capabilities |= EditorInputCapabilities.Untitled; + } + + return capabilities; } override getName(): string { @@ -150,14 +164,6 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { }); } - public override isReadonly(): boolean { - return this._modelRef ? !this._modelRef.object.isEditable() : false; - } - - public override isUntitled(): boolean { - return this.resource.scheme === Schemas.untitled; - } - public override isDirty(): boolean { if (!this._modelRef) { return !!this._defaultDirtyState; diff --git a/src/vs/workbench/contrib/extensions/common/extensionsInput.ts b/src/vs/workbench/contrib/extensions/common/extensionsInput.ts index ad1f9febec2..9e8b657eb66 100644 --- a/src/vs/workbench/contrib/extensions/common/extensionsInput.ts +++ b/src/vs/workbench/contrib/extensions/common/extensionsInput.ts @@ -6,7 +6,7 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; -import { EditorInput } from 'vs/workbench/common/editor'; +import { EditorInput, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { IExtension } from 'vs/workbench/contrib/extensions/common/extensions'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { join } from 'vs/base/common/path'; @@ -19,6 +19,10 @@ export class ExtensionsInput extends EditorInput { return ExtensionsInput.ID; } + override get capabilities(): EditorInputCapabilities { + return EditorInputCapabilities.Readonly | EditorInputCapabilities.Singleton; + } + override get resource() { return URI.from({ scheme: Schemas.extension, @@ -36,10 +40,6 @@ export class ExtensionsInput extends EditorInput { return localize('extensionsInputName', "Extension: {0}", this.extension.displayName); } - override canSplit(): boolean { - return false; - } - override matches(other: unknown): boolean { if (super.matches(other)) { return true; diff --git a/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts b/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts index e5ff9281fd0..1f8c9cfe959 100644 --- a/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts +++ b/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; -import { EditorInput } from 'vs/workbench/common/editor'; +import { EditorInput, EditorInputCapabilities } from 'vs/workbench/common/editor'; export class RuntimeExtensionsInput extends EditorInput { @@ -15,6 +15,10 @@ export class RuntimeExtensionsInput extends EditorInput { return RuntimeExtensionsInput.ID; } + override get capabilities(): EditorInputCapabilities { + return EditorInputCapabilities.Readonly | EditorInputCapabilities.Singleton; + } + static _instance: RuntimeExtensionsInput; static get instance() { if (!RuntimeExtensionsInput._instance || RuntimeExtensionsInput._instance.isDisposed()) { @@ -33,10 +37,6 @@ export class RuntimeExtensionsInput extends EditorInput { return nls.localize('extensionsInputName', "Running Extensions"); } - override canSplit(): boolean { - return false; - } - override matches(other: unknown): boolean { return other instanceof RuntimeExtensionsInput; } diff --git a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts index 157124a0d7b..3aa6dba71e0 100644 --- a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, isTextEditorPane } from 'vs/workbench/common/editor'; +import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, isTextEditorPane, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; -import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files'; +import { FileOperationError, FileOperationResult, FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files'; import { ITextFileService, TextFileEditorModelState, TextFileResolveReason, TextFileOperationError, TextFileOperationResult, ITextFileEditorModel, EncodingMode } from 'vs/workbench/services/textfile/common/textfiles'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IReference, dispose, DisposableStore } from 'vs/base/common/lifecycle'; @@ -36,6 +36,22 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements return FILE_EDITOR_INPUT_ID; } + override get capabilities(): EditorInputCapabilities { + let capabilities = EditorInputCapabilities.None; + + if (this.model) { + if (this.model.isReadonly()) { + capabilities |= EditorInputCapabilities.Readonly; + } + } else { + if (this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly)) { + capabilities |= EditorInputCapabilities.Readonly; + } + } + + return capabilities; + } + private preferredName: string | undefined; private preferredDescription: string | undefined; private preferredEncoding: string | undefined; @@ -223,14 +239,6 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements return !!(this.model?.isDirty()); } - override isReadonly(): boolean { - if (this.model) { - return this.model.isReadonly(); - } - - return super.isReadonly(); - } - override isOrphaned(): boolean { if (this.model) { return this.model.hasState(TextFileEditorModelState.ORPHAN); diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index 920c0910892..d1ad34d4540 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -12,7 +12,7 @@ import { toAction } from 'vs/base/common/actions'; import { VIEWLET_ID, TEXT_FILE_EDITOR_ID } from 'vs/workbench/contrib/files/common/files'; import { ITextFileService, TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; -import { EditorOptions, TextEditorOptions, IEditorInput, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorOptions, TextEditorOptions, IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -84,7 +84,7 @@ export class TextFileEditor extends BaseTextEditor { const control = this.getControl(); const input = this.input; if (control && input?.resource.scheme === scheme) { - control.updateOptions({ readOnly: input.isReadonly() }); + control.updateOptions({ readOnly: input.hasCapability(EditorInputCapabilities.Readonly) }); } } diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index f2894496f22..ba086ef5c2a 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; -import { EditorResourceAccessor, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, SideBySideEditorInput, EditorsOrder } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, SideBySideEditorInput, EditorsOrder, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -386,7 +386,7 @@ async function saveSelectedEditors(accessor: ServicesAccessor, options?: ISaveEd // See also https://github.com/microsoft/vscode/issues/106330 if ( activeGroup.activeEditor instanceof SideBySideEditorInput && - !options?.saveAs && !(activeGroup.activeEditor.primary.isUntitled() || activeGroup.activeEditor.secondary.isUntitled()) + !options?.saveAs && !(activeGroup.activeEditor.primary.hasCapability(EditorInputCapabilities.Untitled) || activeGroup.activeEditor.secondary.hasCapability(EditorInputCapabilities.Untitled)) ) { editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.primary }); editors.push({ groupId: activeGroup.id, editor: activeGroup.activeEditor.secondary }); @@ -550,7 +550,7 @@ CommandsRegistry.registerCommand({ } try { - await editorService.revert(editors.filter(({ editor }) => !editor.isUntitled() /* all except untitled */), { force: true }); + await editorService.revert(editors.filter(({ editor }) => !editor.hasCapability(EditorInputCapabilities.Untitled) /* all except untitled */), { force: true }); } catch (error) { notificationService.error(nls.localize('genericRevertError', "Failed to revert '{0}': {1}", editors.map(({ editor }) => editor.getName()).join(', '), toErrorMessage(error, false))); } diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index 2aa047e2cb2..394405c926f 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -13,7 +13,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati import { IEditorGroupsService, IEditorGroup, GroupChangeKind, GroupsOrder, GroupOrientation } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IEditorInput, Verbosity, EditorResourceAccessor, SideBySideEditor } from 'vs/workbench/common/editor'; +import { IEditorInput, Verbosity, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { SaveAllInGroupAction, CloseGroupAction } from 'vs/workbench/contrib/files/browser/fileActions'; import { OpenEditorsFocusedContext, ExplorerFocusedContext, IFilesConfiguration, OpenEditor } from 'vs/workbench/contrib/files/common/files'; import { CloseAllEditorsAction, CloseEditorAction, UnpinEditorAction } from 'vs/workbench/browser/parts/editor/editorActions'; @@ -269,7 +269,7 @@ export class OpenEditorsView extends ViewPane { if (element instanceof OpenEditor) { const resource = element.getResource(); this.dirtyEditorFocusedContext.set(element.editor.isDirty() && !element.editor.isSaving()); - this.readonlyEditorFocusedContext.set(element.editor.isReadonly()); + this.readonlyEditorFocusedContext.set(element.editor.hasCapability(EditorInputCapabilities.Readonly)); this.resourceContext.set(withUndefinedAsNull(resource)); } else if (!!element) { this.groupFocusedContext.set(true); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookDiffEditorInput.ts b/src/vs/workbench/contrib/notebook/browser/notebookDiffEditorInput.ts index 3bb021439c8..b7ef97df99d 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookDiffEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookDiffEditorInput.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as glob from 'vs/base/common/glob'; -import { EditorInput, IEditorInput, GroupIdentifier, ISaveOptions, IMoveResult, IRevertOptions, EditorModel } from 'vs/workbench/common/editor'; +import { EditorInput, IEditorInput, GroupIdentifier, ISaveOptions, IMoveResult, IRevertOptions, EditorModel, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { URI } from 'vs/base/common/uri'; import { isEqual } from 'vs/base/common/resources'; @@ -78,6 +78,16 @@ export class NotebookDiffEditorInput extends EditorInput { return NotebookDiffEditorInput.ID; } + override get capabilities(): EditorInputCapabilities { + let capabilities = EditorInputCapabilities.None; + + if (this._modifiedTextModel?.object.resource.scheme === Schemas.untitled) { + capabilities |= EditorInputCapabilities.Untitled; + } + + return capabilities; + } + override getName(): string { return this.textDiffName; } @@ -89,18 +99,10 @@ export class NotebookDiffEditorInput extends EditorInput { return this._modifiedTextModel.object.isDirty(); } - override isUntitled(): boolean { - return this._modifiedTextModel?.object.resource.scheme === Schemas.untitled; - } - - override isReadonly() { - return false; - } - override async save(group: GroupIdentifier, options?: ISaveOptions): Promise { if (this._modifiedTextModel) { - if (this.isUntitled()) { + if (this.hasCapability(EditorInputCapabilities.Untitled)) { return this.saveAs(group, options); } else { await this._modifiedTextModel.object.save(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 218a8d1bec8..6771e6f2738 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -18,7 +18,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { EditorOptions, IEditorInput, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInputCapabilities, EditorOptions, IEditorInput, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget'; import { INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; @@ -75,7 +75,7 @@ export class NotebookEditor extends EditorPane { private onDidFileSystemProviderChange(scheme: string): void { if (this.input?.resource?.scheme === scheme && this._widget.value) { - this._widget.value.setOptions(new NotebookEditorOptions({ isReadOnly: this.input.isReadonly() })); + this._widget.value.setOptions(new NotebookEditorOptions({ isReadOnly: this.input.hasCapability(EditorInputCapabilities.Readonly) })); } } @@ -205,8 +205,8 @@ export class NotebookEditor extends EditorPane { this._widget.value?.setParentContextKeyService(this._contextKeyService); await this._widget.value!.setModel(model.notebook, viewState); - const isReadonly = input.isReadonly(); - await this._widget.value!.setOptions(options instanceof NotebookEditorOptions ? options.with({ isReadOnly: isReadonly }) : new NotebookEditorOptions({ isReadOnly: isReadonly })); + const isReadOnly = input.hasCapability(EditorInputCapabilities.Readonly); + await this._widget.value!.setOptions(options instanceof NotebookEditorOptions ? options.with({ isReadOnly }) : new NotebookEditorOptions({ isReadOnly })); this._widgetDisposableStore.add(this._widget.value!.onDidFocus(() => this._onDidFocusWidget.fire())); this._widgetDisposableStore.add(this._editorDropService.createEditorDropTarget(this._widget.value!.getDomNode(), { diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts index 4be911cb26b..40370832c54 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as glob from 'vs/base/common/glob'; -import { IEditorInput, GroupIdentifier, ISaveOptions, IMoveResult, IRevertOptions } from 'vs/workbench/common/editor'; +import { IEditorInput, GroupIdentifier, ISaveOptions, IMoveResult, IRevertOptions, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { URI } from 'vs/base/common/uri'; import { isEqual, joinPath } from 'vs/base/common/resources'; @@ -16,7 +16,7 @@ import { IResolvedNotebookEditorModel } from 'vs/workbench/contrib/notebook/comm import { ILabelService } from 'vs/platform/label/common/label'; import { Schemas } from 'vs/base/common/network'; import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; -import { IFileService } from 'vs/platform/files/common/files'; +import { FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files'; import { AbstractResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; interface NotebookEditorInputOptions { @@ -59,6 +59,26 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { return NotebookEditorInput.ID; } + override get capabilities(): EditorInputCapabilities { + let capabilities = EditorInputCapabilities.None; + + if (this.resource.scheme === Schemas.untitled) { + capabilities |= EditorInputCapabilities.Untitled; + } + + if (this._editorModelReference) { + if (this._editorModelReference.object.isReadonly()) { + capabilities |= EditorInputCapabilities.Readonly; + } + } else { + if (this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly)) { + capabilities |= EditorInputCapabilities.Readonly; + } + } + + return capabilities; + } + override isDirty() { if (!this._editorModelReference) { return this._defaultDirtyState; @@ -66,18 +86,6 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { return this._editorModelReference.object.isDirty(); } - override isUntitled(): boolean { - return this.resource.scheme === Schemas.untitled; - } - - override isReadonly() { - if (!this._editorModelReference) { - return super.isReadonly(); - } - - return this._editorModelReference.object.isReadonly(); - } - override isOrphaned() { if (!this._editorModelReference) { return super.isOrphaned(); @@ -89,7 +97,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { override async save(group: GroupIdentifier, options?: ISaveOptions): Promise { if (this._editorModelReference) { - if (this.isUntitled()) { + if (this.hasCapability(EditorInputCapabilities.Untitled)) { return this.saveAs(group, options); } else { await this._editorModelReference.object.save(options); @@ -112,7 +120,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { return undefined; } - const dialogPath = this.isUntitled() ? await this._suggestName(this.labelService.getUriBasenameLabel(this.resource)) : this._editorModelReference.object.resource; + const dialogPath = this.hasCapability(EditorInputCapabilities.Untitled) ? await this._suggestName(this.labelService.getUriBasenameLabel(this.resource)) : this._editorModelReference.object.resource; const target = await this._fileDialogService.pickFileToSave(dialogPath, options?.availableFileSystems); if (!target) { diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts index 686fd473eb0..81331918be9 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts @@ -37,7 +37,7 @@ import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInputCapabilities, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; import { ExcludePatternInputWidget, IncludePatternInputWidget } from 'vs/workbench/contrib/search/browser/patternInputWidget'; import { SearchWidget } from 'vs/workbench/contrib/search/browser/searchWidget'; import { InputBoxFocusedKey } from 'vs/workbench/contrib/search/common/constants'; @@ -578,7 +578,7 @@ export class SearchEditor extends BaseTextEditor { }); } - input.setDirty(!input.isUntitled()); + input.setDirty(!input.hasCapability(EditorInputCapabilities.Untitled)); input.setMatchRanges(results.matchRanges); } diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts index 2ef2e4bdbb8..c7ee48405fd 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts @@ -16,7 +16,7 @@ import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { EditorInput, GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, EditorResourceAccessor, IMoveResult } from 'vs/workbench/common/editor'; +import { EditorInput, GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, EditorResourceAccessor, IMoveResult, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { Memento } from 'vs/workbench/common/memento'; import { SearchEditorFindMatchClass, SearchEditorScheme, SearchEditorWorkingCopyTypeId } from 'vs/workbench/contrib/searchEditor/browser/constants'; import { SearchConfigurationModel, SearchEditorModel, searchEditorModelFactory } from 'vs/workbench/contrib/searchEditor/browser/searchEditorModel'; @@ -52,6 +52,15 @@ export class SearchEditorInput extends EditorInput { return SearchEditorInput.ID; } + override get capabilities(): EditorInputCapabilities { + let capabilities = EditorInputCapabilities.Singleton; + if (!this.backingUri) { + capabilities |= EditorInputCapabilities.Untitled; + } + + return capabilities; + } + private memento: Memento; private dirty: boolean = false; @@ -99,7 +108,7 @@ export class SearchEditorInput extends EditorInput { readonly typeId = SearchEditorWorkingCopyTypeId; readonly resource = input.modelUri; get name() { return input.getName(); } - readonly capabilities = input.isUntitled() ? WorkingCopyCapabilities.Untitled : WorkingCopyCapabilities.None; + readonly capabilities = input.hasCapability(EditorInputCapabilities.Untitled) ? WorkingCopyCapabilities.Untitled : WorkingCopyCapabilities.None; readonly onDidChangeDirty = input.onDidChangeDirty; readonly onDidChangeContent = input.onDidChangeContent; isDirty(): boolean { return input.isDirty(); } @@ -187,14 +196,6 @@ export class SearchEditorInput extends EditorInput { return this.dirty; } - override isReadonly() { - return false; - } - - override isUntitled() { - return !this.backingUri; - } - override rename(group: GroupIdentifier, target: URI): IMoveResult | undefined { if (extname(target) === SEARCH_EDITOR_EXT) { return { @@ -249,10 +250,6 @@ export class SearchEditorInput extends EditorInput { this.setDirty(false); } - override canSplit() { - return false; - } - private async backup(token: CancellationToken): Promise { const contents = await this.serializeForDisk(); if (token.isCancellationRequested) { diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts index fe15fcef6c7..467342013e8 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts @@ -5,7 +5,7 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; -import { EditorInput, GroupIdentifier, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; +import { EditorInput, EditorInputCapabilities, GroupIdentifier, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; import { WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewIconManager, WebviewIcons } from 'vs/workbench/contrib/webviewPanel/browser/webviewIconManager'; @@ -17,6 +17,10 @@ export class WebviewInput extends EditorInput { return WebviewInput.typeId; } + public override get capabilities(): EditorInputCapabilities { + return EditorInputCapabilities.Readonly | EditorInputCapabilities.Singleton; + } + private _name: string; private _iconPath?: WebviewIcons; private _group?: GroupIdentifier; @@ -99,10 +103,6 @@ export class WebviewInput extends EditorInput { this._group = group; } - public override canSplit() { - return false; - } - protected transfer(other: WebviewInput): WebviewInput | undefined { if (this._hasTransfered) { return undefined; diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 64d74a76331..9e9dbe25d7f 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -5,7 +5,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IResourceEditorInput, ITextEditorOptions, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; -import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, EditorInput, SideBySideEditorInput, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, TextEditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup } from 'vs/workbench/common/editor'; +import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, EditorInput, SideBySideEditorInput, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, TextEditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { Registry } from 'vs/platform/registry/common/platform'; import { ResourceMap } from 'vs/base/common/map'; @@ -388,7 +388,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { const editors: IEditorInput[] = []; function conditionallyAddEditor(editor: IEditorInput): void { - if (editor.isUntitled() && !options.includeUntitled) { + if (editor.hasCapability(EditorInputCapabilities.Untitled) && !options.includeUntitled) { return; } @@ -1156,7 +1156,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { editorsToSaveSequentially.push(...uniqueEditors); } else { for (const { groupId, editor } of uniqueEditors) { - if (editor.isUntitled()) { + if (editor.hasCapability(EditorInputCapabilities.Untitled)) { editorsToSaveSequentially.push({ groupId, editor }); } else { editorsToSaveParallel.push({ groupId, editor }); @@ -1202,7 +1202,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { // only selected group) if the resulting editor is different from the // current one. if (!result.matches(editor)) { - const targetGroups = editor.isUntitled() ? this.editorGroupService.groups.map(group => group.id) /* untitled replaces across all groups */ : [groupId]; + const targetGroups = editor.hasCapability(EditorInputCapabilities.Untitled) ? this.editorGroupService.groups.map(group => group.id) /* untitled replaces across all groups */ : [groupId]; for (const group of targetGroups) { await this.replaceEditors([{ editor, replacement: result, options: { pinned: true, viewState } }], group); } @@ -1251,7 +1251,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { continue; } - if (!options?.includeUntitled && editor.isUntitled()) { + if (!options?.includeUntitled && editor.hasCapability(EditorInputCapabilities.Untitled)) { continue; } diff --git a/src/vs/workbench/test/browser/parts/editor/editor.test.ts b/src/vs/workbench/test/browser/parts/editor/editor.test.ts index 85e45020deb..c1b9d28c0b5 100644 --- a/src/vs/workbench/test/browser/parts/editor/editor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editor.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, SideBySideEditorInput } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, SideBySideEditorInput, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { URI } from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -64,6 +64,59 @@ suite('Workbench editor', () => { disposables.clear(); }); + test('EditorInputCapabilities', () => { + const testInput1 = new TestFileEditorInput(URI.file('resource1'), 'testTypeId'); + const testInput2 = new TestFileEditorInput(URI.file('resource2'), 'testTypeId'); + + testInput1.capabilities = EditorInputCapabilities.None; + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.None), true); + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Readonly), false); + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Untitled), false); + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.RequiresTrust), false); + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Singleton), false); + + testInput1.capabilities |= EditorInputCapabilities.Readonly; + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Readonly), true); + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.None), false); + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Untitled), false); + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.RequiresTrust), false); + assert.strictEqual(testInput1.hasCapability(EditorInputCapabilities.Singleton), false); + + testInput1.capabilities = EditorInputCapabilities.None; + testInput2.capabilities = EditorInputCapabilities.None; + + const sideBySideInput = new SideBySideEditorInput('name', undefined, testInput1, testInput2); + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.None), true); + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Readonly), false); + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Untitled), false); + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.RequiresTrust), false); + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Singleton), false); + + testInput1.capabilities |= EditorInputCapabilities.Readonly; + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Readonly), false); + + testInput2.capabilities |= EditorInputCapabilities.Readonly; + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Readonly), true); + + testInput1.capabilities |= EditorInputCapabilities.Untitled; + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Untitled), false); + + testInput2.capabilities |= EditorInputCapabilities.Untitled; + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Untitled), true); + + testInput1.capabilities |= EditorInputCapabilities.RequiresTrust; + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.RequiresTrust), true); + + testInput2.capabilities |= EditorInputCapabilities.RequiresTrust; + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.RequiresTrust), true); + + testInput1.capabilities |= EditorInputCapabilities.Singleton; + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Singleton), true); + + testInput2.capabilities |= EditorInputCapabilities.Singleton; + assert.strictEqual(sideBySideInput.hasCapability(EditorInputCapabilities.Singleton), true); + }); + test('EditorResourceAccessor', () => { const service = accessor.untitledTextEditorService; diff --git a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts index d2a167b3998..1dd55703448 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { EditorPane, EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane'; import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor'; -import { EditorInput, EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; @@ -419,8 +419,8 @@ suite('Workbench EditorPane', () => { return 'trustRequiredTestInput'; } - override requiresWorkspaceTrust(): boolean { - return true; + override get capabilities(): EditorInputCapabilities { + return EditorInputCapabilities.RequiresTrust; } override resolve(): any { @@ -428,7 +428,6 @@ suite('Workbench EditorPane', () => { } } - const disposables = new DisposableStore(); const instantiationService = workbenchInstantiationService(); diff --git a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.ts b/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts similarity index 88% rename from src/vs/workbench/test/browser/parts/editor/resourceEditorInput.ts rename to src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts index e6f3a587d85..495a8ae7a75 100644 --- a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.ts +++ b/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts @@ -10,7 +10,7 @@ import { workbenchInstantiationService } from 'vs/workbench/test/browser/workben import { AbstractResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { ILabelService } from 'vs/platform/label/common/label'; import { IFileService } from 'vs/platform/files/common/files'; -import { Verbosity } from 'vs/workbench/common/editor'; +import { EditorInputCapabilities, Verbosity } from 'vs/workbench/common/editor'; suite('Resource editors', () => { @@ -48,8 +48,8 @@ suite('Resource editors', () => { assert.ok(input.getTitle(Verbosity.MEDIUM).length > 0); assert.ok(input.getTitle(Verbosity.LONG).length > 0); - assert.strictEqual(input.isReadonly(), false); - assert.strictEqual(input.isUntitled(), true); + assert.strictEqual(input.hasCapability(EditorInputCapabilities.Readonly), false); + assert.strictEqual(input.hasCapability(EditorInputCapabilities.Untitled), true); assert.strictEqual(input.isOrphaned(), false); }); }); diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 4a346053938..b5fba689809 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -9,7 +9,7 @@ import { basename } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; -import { IEditorInputWithOptions, IEditorIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInput, IEditorPane, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorInput, EditorOptions, EditorsOrder, IFileEditorInput, IEditorInputFactoryRegistry, IEditorInputSerializer, EditorExtensions, ISaveOptions, IMoveResult, ITextEditorPane, ITextDiffEditorPane, IVisibleEditorPane, IEditorOpenContext, SideBySideEditorInput, IEditorMoveEvent, EditorExtensions as Extensions, IEditorOpenEvent } from 'vs/workbench/common/editor'; +import { IEditorInputWithOptions, IEditorIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInput, IEditorPane, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorInput, EditorOptions, EditorsOrder, IFileEditorInput, IEditorInputFactoryRegistry, IEditorInputSerializer, EditorExtensions, ISaveOptions, IMoveResult, ITextEditorPane, ITextDiffEditorPane, IVisibleEditorPane, IEditorOpenContext, SideBySideEditorInput, IEditorMoveEvent, EditorExtensions as Extensions, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; import { EditorServiceImpl, IEditorGroupView, IEditorGroupsAccessor, IEditorGroupTitleHeight } from 'vs/workbench/browser/parts/editor/editor'; import { Event, Emitter } from 'vs/base/common/event'; import { IResolvedWorkingCopyBackup, IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup'; @@ -1426,6 +1426,11 @@ export class TestFileEditorInput extends EditorInput implements IFileEditorInput } override get typeId() { return this._typeId; } + + private _capabilities: EditorInputCapabilities = EditorInputCapabilities.None; + override get capabilities(): EditorInputCapabilities { return this._capabilities; } + override set capabilities(capabilities: EditorInputCapabilities) { this._capabilities = capabilities; } + override resolve(): Promise { return !this.fails ? Promise.resolve(null) : Promise.reject(new Error('fails')); } override matches(other: EditorInput): boolean { return !!(other?.resource && this.resource.toString() === other.resource.toString() && other instanceof TestFileEditorInput && other.typeId === this.typeId); } setPreferredResource(resource: URI): void { } @@ -1459,9 +1464,6 @@ export class TestFileEditorInput extends EditorInput implements IFileEditorInput override isDirty(): boolean { return this.dirty; } - override isReadonly(): boolean { - return false; - } isResolved(): boolean { return false; } override dispose(): void { super.dispose(); From dee37c6e7652d5912f10d3194ab13e0d31886663 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 09:26:57 +0200 Subject: [PATCH 027/140] web - offer upload action only for editable folders --- .../contrib/files/browser/fileActions.contribution.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts index 932206ea133..e682dd6ddc5 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts @@ -512,7 +512,9 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, ({ // only in web IsWebContext, // only on folders - ExplorerFolderContext + ExplorerFolderContext, + // only on editable folders + ExplorerResourceNotReadonlyContext ) })); From 59f5bbaf253e4e611f814b22a9cac5003eecacbe Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 09:33:09 +0200 Subject: [PATCH 028/140] editors - cleanup editor descriptors and :lipstick: --- .../browser/{menuActions.ts => actions.ts} | 8 + src/vs/workbench/browser/composite.ts | 11 +- src/vs/workbench/browser/editor.ts | 143 +++++++----------- src/vs/workbench/browser/panel.ts | 2 +- .../browser/parts/editor/editorControl.ts | 1 - .../browser/parts/editor/textDiffEditor.ts | 2 +- .../workbench/browser/parts/views/viewPane.ts | 2 +- .../browser/parts/views/viewPaneContainer.ts | 2 +- src/vs/workbench/browser/web.main.ts | 2 +- src/vs/workbench/browser/window.ts | 6 +- src/vs/workbench/common/editor.ts | 58 +++++-- .../common/editor/diffEditorInput.ts | 10 +- .../files/browser/editors/fileEditorInput.ts | 10 +- .../contrib/output/browser/outputView.ts | 2 +- .../preferences/browser/preferencesEditor.ts | 2 +- .../electron-sandbox/shared.desktop.main.ts | 2 +- .../browser/parts/editor/editorPane.test.ts | 111 +++++++------- 17 files changed, 192 insertions(+), 182 deletions(-) rename src/vs/workbench/browser/{menuActions.ts => actions.ts} (99%) diff --git a/src/vs/workbench/browser/menuActions.ts b/src/vs/workbench/browser/actions.ts similarity index 99% rename from src/vs/workbench/browser/menuActions.ts rename to src/vs/workbench/browser/actions.ts index 7aecec66eff..53eaf674196 100644 --- a/src/vs/workbench/browser/menuActions.ts +++ b/src/vs/workbench/browser/actions.ts @@ -32,7 +32,9 @@ class MenuActions extends Disposable { private readonly contextKeyService: IContextKeyService ) { super(); + this.menu = this._register(menuService.createMenu(menuId, contextKeyService)); + this._register(this.menu.onDidChange(() => this.updateActions())); this.updateActions(); } @@ -48,6 +50,7 @@ class MenuActions extends Disposable { private updateSubmenus(actions: readonly IAction[], submenus: { [id: number]: IMenu }): IDisposable { const disposables = new DisposableStore(); + for (const action of actions) { if (action instanceof SubmenuItemAction && !submenus[action.item.submenu.id]) { const menu = submenus[action.item.submenu.id] = disposables.add(this.menuService.createMenu(action.item.submenu, this.contextKeyService)); @@ -55,6 +58,7 @@ class MenuActions extends Disposable { disposables.add(this.updateSubmenus(action.actions, submenus)); } } + return disposables; } } @@ -75,7 +79,9 @@ export class CompositeMenuActions extends Disposable { @IMenuService private readonly menuService: IMenuService, ) { super(); + this.menuActions = this._register(new MenuActions(menuId, this.options, menuService, contextKeyService)); + this._register(this.menuActions.onDidChange(() => this._onDidChange.fire())); } @@ -89,11 +95,13 @@ export class CompositeMenuActions extends Disposable { getContextMenuActions(): IAction[] { const actions: IAction[] = []; + if (this.contextMenuId) { const menu = this.menuService.createMenu(this.contextMenuId, this.contextKeyService); this.contextMenuActionsDisposable.value = createAndFillInActionBarActions(menu, this.options, { primary: [], secondary: actions }); menu.dispose(); } + return actions; } } diff --git a/src/vs/workbench/browser/composite.ts b/src/vs/workbench/browser/composite.ts index 59cec8515e1..2239c0b9793 100644 --- a/src/vs/workbench/browser/composite.ts +++ b/src/vs/workbench/browser/composite.ts @@ -118,10 +118,6 @@ export abstract class Composite extends Component implements IComposite { this.parent = parent; } - override updateStyles(): void { - super.updateStyles(); - } - /** * Returns the container this composite is being build in. */ @@ -158,6 +154,13 @@ export abstract class Composite extends Component implements IComposite { */ abstract layout(dimension: Dimension): void; + /** + * Update the styles of the contents of this composite. + */ + override updateStyles(): void { + super.updateStyles(); + } + /** * Returns an array of actions to show in the action bar of the composite. */ diff --git a/src/vs/workbench/browser/editor.ts b/src/vs/workbench/browser/editor.ts index adce1b321d3..7413ec6abdc 100644 --- a/src/vs/workbench/browser/editor.ts +++ b/src/vs/workbench/browser/editor.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { EditorInput, EditorResourceAccessor, IEditorInput, EditorExtensions, SideBySideEditor } from 'vs/workbench/common/editor'; +import { EditorInput, EditorResourceAccessor, IEditorInput, EditorExtensions, SideBySideEditor, IEditorDescriptor as ICommonEditorDescriptor } from 'vs/workbench/common/editor'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { Registry } from 'vs/platform/registry/common/platform'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; @@ -20,22 +20,7 @@ import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsSe //#region Editors Registry -export interface IEditorDescriptor { - - /** - * The unique identifier of the editor - */ - getId(): string; - - /** - * The display name of the editor - */ - getName(): string; - - instantiate(instantiationService: IInstantiationService): EditorPane; - - describes(obj: unknown): boolean; -} +export interface IEditorDescriptor extends ICommonEditorDescriptor { } export interface IEditorRegistry { @@ -48,22 +33,12 @@ export interface IEditorRegistry { * @param inputDescriptors A set of constructor functions that return an instance of EditorInput for which the * registered editor should be used for. */ - registerEditor(descriptor: IEditorDescriptor, inputDescriptors: readonly SyncDescriptor[]): IDisposable; + registerEditor(editorDescriptor: IEditorDescriptor, inputDescriptors: readonly SyncDescriptor[]): IDisposable; /** * Returns the editor descriptor for the given input or `undefined` if none. */ getEditor(input: EditorInput): IEditorDescriptor | undefined; - - /** - * Returns the editor descriptor for the given identifier or `undefined` if none. - */ - getEditorById(editorId: string): IEditorDescriptor | undefined; - - /** - * Returns an array of registered editors known to the platform. - */ - getEditors(): readonly IEditorDescriptor[]; } /** @@ -74,36 +49,28 @@ export class EditorDescriptor implements IEditorDescriptor { static create( ctor: { new(...services: Services): EditorPane }, - id: string, + typeId: string, name: string ): EditorDescriptor { - return new EditorDescriptor(ctor as IConstructorSignature0, id, name); + return new EditorDescriptor(ctor as IConstructorSignature0, typeId, name); } - constructor( + private constructor( private readonly ctor: IConstructorSignature0, - private readonly id: string, - private readonly name: string + readonly typeId: string, + readonly name: string ) { } instantiate(instantiationService: IInstantiationService): EditorPane { return instantiationService.createInstance(this.ctor); } - getId(): string { - return this.id; - } - - getName(): string { - return this.name; - } - - describes(obj: unknown): boolean { - return obj instanceof EditorPane && obj.getId() === this.id; + describes(editorPane: EditorPane): boolean { + return editorPane.getId() === this.typeId; } } -class EditorRegistry implements IEditorRegistry { +export class EditorRegistry implements IEditorRegistry { private readonly editors: EditorDescriptor[] = []; private readonly mapEditorToInputs = new Map[]>(); @@ -120,58 +87,53 @@ class EditorRegistry implements IEditorRegistry { } getEditor(input: EditorInput): EditorDescriptor | undefined { - const findEditorDescriptors = (input: EditorInput, byInstanceOf?: boolean): EditorDescriptor[] => { - const matchingDescriptors: EditorDescriptor[] = []; + const descriptors = this.findEditorDescriptors(input); - for (const editor of this.editors) { - const inputDescriptors = this.mapEditorToInputs.get(editor) || []; - for (const inputDescriptor of inputDescriptors) { - const inputClass = inputDescriptor.ctor; + if (descriptors.length === 0) { + return undefined; + } - // Direct check on constructor type (ignores prototype chain) - if (!byInstanceOf && input.constructor === inputClass) { - matchingDescriptors.push(editor); - break; - } - - // Normal instanceof check - else if (byInstanceOf && input instanceof inputClass) { - matchingDescriptors.push(editor); - break; - } - } - } - - // If no descriptors found, continue search using instanceof and prototype chain - if (!byInstanceOf && matchingDescriptors.length === 0) { - return findEditorDescriptors(input, true); - } - - if (byInstanceOf) { - return matchingDescriptors; - } - - return matchingDescriptors; - }; - - const descriptors = findEditorDescriptors(input); - if (descriptors.length > 0) { - - // Ask the input for its preferred Editor - const preferredEditorId = input.getPreferredEditorId(descriptors.map(descriptor => descriptor.getId())); - if (preferredEditorId) { - return this.getEditorById(preferredEditorId); - } - - // Otherwise, first come first serve + if (descriptors.length === 1) { return descriptors[0]; } - return undefined; + return input.prefersEditor(descriptors); } - getEditorById(editorId: string): EditorDescriptor | undefined { - return this.editors.find(editor => editor.getId() === editorId); + private findEditorDescriptors(input: EditorInput, byInstanceOf?: boolean): EditorDescriptor[] { + const matchingDescriptors: EditorDescriptor[] = []; + + for (const editor of this.editors) { + const inputDescriptors = this.mapEditorToInputs.get(editor) || []; + for (const inputDescriptor of inputDescriptors) { + const inputClass = inputDescriptor.ctor; + + // Direct check on constructor type (ignores prototype chain) + if (!byInstanceOf && input.constructor === inputClass) { + matchingDescriptors.push(editor); + break; + } + + // Normal instanceof check + else if (byInstanceOf && input instanceof inputClass) { + matchingDescriptors.push(editor); + break; + } + } + } + + // If no descriptors found, continue search using instanceof and prototype chain + if (!byInstanceOf && matchingDescriptors.length === 0) { + return this.findEditorDescriptors(input, true); + } + + return matchingDescriptors; + } + + //#region Used for tests only + + getEditorByType(typeId: string): EditorDescriptor | undefined { + return this.editors.find(editor => editor.typeId === typeId); } getEditors(): readonly EditorDescriptor[] { @@ -189,6 +151,8 @@ class EditorRegistry implements IEditorRegistry { return inputClasses; } + + //#endregion } Registry.add(EditorExtensions.Editors, new EditorRegistry()); @@ -255,7 +219,6 @@ export function whenEditorClosed(accessor: ServicesAccessor, resources: URI[]): //#endregion - //#region ARIA export function computeEditorAriaLabel(input: IEditorInput, index: number | undefined, group: IEditorGroup | undefined, groupCount: number): string { diff --git a/src/vs/workbench/browser/panel.ts b/src/vs/workbench/browser/panel.ts index 1364f49a41e..8f861e04dc7 100644 --- a/src/vs/workbench/browser/panel.ts +++ b/src/vs/workbench/browser/panel.ts @@ -10,7 +10,7 @@ import { IConstructorSignature0, BrandedService, IInstantiationService } from 'v import { assertIsDefined } from 'vs/base/common/types'; import { PaneComposite } from 'vs/workbench/browser/panecomposite'; import { IAction, Separator } from 'vs/base/common/actions'; -import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; +import { CompositeMenuActions } from 'vs/workbench/browser/actions'; import { MenuId } from 'vs/platform/actions/common/actions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IStorageService } from 'vs/platform/storage/common/storage'; diff --git a/src/vs/workbench/browser/parts/editor/editorControl.ts b/src/vs/workbench/browser/parts/editor/editorControl.ts index 00350cf59ac..a61c2875178 100644 --- a/src/vs/workbench/browser/parts/editor/editorControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorControl.ts @@ -143,7 +143,6 @@ export class EditorControl extends Disposable { if (!editorPane.getContainer()) { const editorPaneContainer = document.createElement('div'); editorPaneContainer.classList.add('editor-instance'); - editorPaneContainer.setAttribute('data-editor-id', descriptor.getId()); editorPane.create(editorPaneContainer); } diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index 12cbedcb79a..dfa400ffb90 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -106,7 +106,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan return this.instantiationService.createInstance(DiffEditorWidget, parent, configuration, {}); } - override async setInput(input: DiffEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise {// + override async setInput(input: DiffEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { // Dispose previous diff navigator this.diffNavigatorDisposables.clear(); diff --git a/src/vs/workbench/browser/parts/views/viewPane.ts b/src/vs/workbench/browser/parts/views/viewPane.ts index f3c427fa2d3..d6b967b6a40 100644 --- a/src/vs/workbench/browser/parts/views/viewPane.ts +++ b/src/vs/workbench/browser/parts/views/viewPane.ts @@ -40,7 +40,7 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { URI } from 'vs/base/common/uri'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { Codicon } from 'vs/base/common/codicons'; -import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; +import { CompositeMenuActions } from 'vs/workbench/browser/actions'; export interface IViewPaneOptions extends IPaneOptions { id: string; diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 20730cc50cb..8cc73ad857b 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -35,7 +35,7 @@ import { RunOnceScheduler } from 'vs/base/common/async'; import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; -import { CompositeMenuActions } from 'vs/workbench/browser/menuActions'; +import { CompositeMenuActions } from 'vs/workbench/browser/actions'; import { createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; import { ScrollEvent } from 'vs/base/common/scrollable'; diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index e658791524a..866fedeed61 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -183,7 +183,7 @@ class BrowserMain extends Disposable { serviceCollection.set(IFileService, fileService); await this.registerFileSystemProviders(environmentService, fileService, remoteAgentService, logService, logsPath); - // IURIIdentityService + // URI Identity const uriIdentityService = new UriIdentityService(fileService); serviceCollection.set(IUriIdentityService, uriIdentityService); diff --git a/src/vs/workbench/browser/window.ts b/src/vs/workbench/browser/window.ts index d5d3991352d..05b9f806f35 100644 --- a/src/vs/workbench/browser/window.ts +++ b/src/vs/workbench/browser/window.ts @@ -5,7 +5,7 @@ import { setFullscreen } from 'vs/base/browser/browser'; import { addDisposableListener, addDisposableThrottledListener, detectFullscreen, EventHelper, EventType, windowOpenNoOpenerWithSuccess, windowOpenNoOpener } from 'vs/base/browser/dom'; -import { domEvent } from 'vs/base/browser/event'; +import { DomEmitter } from 'vs/base/browser/event'; import { timeout } from 'vs/base/common/async'; import { Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -89,8 +89,8 @@ export class BrowserWindow extends Disposable { // when shutdown has happened to not show the dialog e.g. // when navigation takes a longer time. Event.toPromise(Event.any( - Event.once(domEvent(document.body, EventType.KEY_DOWN, true)), - Event.once(domEvent(document.body, EventType.MOUSE_DOWN, true)) + Event.once(new DomEmitter(document.body, EventType.KEY_DOWN, true).event), + Event.once(new DomEmitter(document.body, EventType.MOUSE_DOWN, true).event) )).then(async () => { // Delay the dialog in case the user interacted diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 5b06d29f964..657e8201de1 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -68,6 +68,31 @@ export const TEXT_DIFF_EDITOR_ID = 'workbench.editors.textDiffEditor'; */ export const BINARY_DIFF_EDITOR_ID = 'workbench.editors.binaryResourceDiffEditor'; +export interface IEditorDescriptor { + + /** + * The unique type identifier of the editor. All instances + * of the same `IEditorPane` should have the same type + * identifier. + */ + readonly typeId: string; + + /** + * The display name of the editor. + */ + readonly name: string; + + /** + * Instantiates the editor pane using the provided services. + */ + instantiate(instantiationService: IInstantiationService): T; + + /** + * Whether the descriptor is for the provided editor pane. + */ + describes(editorPane: T): boolean; +} + /** * The editor pane is the container for workbench editors. */ @@ -414,7 +439,7 @@ export interface IEditorInput extends IDisposable { readonly onDidChangeLabel: Event; /** - * Unique type identifier for this inpput. Every editor input of the + * Unique type identifier for this input. Every editor input of the * same class should share the same type identifier. The type identifier * is used for example for serialising/deserialising editor inputs * via the serialisers of the `IEditorInputFactoryRegistry`. @@ -586,14 +611,6 @@ export abstract class EditorInput extends Disposable implements IEditorInput { return this.getTitle(Verbosity.SHORT); } - /** - * Returns the preferred editor for this input. A list of candidate editors is passed in that whee registered - * for the input. This allows subclasses to decide late which editor to use for the input on a case by case basis. - */ - getPreferredEditorId(candidates: string[]): string | undefined { - return firstOrDefault(candidates); - } - /** * Returns a descriptor suitable for telemetry events. * @@ -642,6 +659,17 @@ export abstract class EditorInput extends Disposable implements IEditorInput { return this === otherInput; } + /** + * If a input was registered onto multiple editors, this method + * will be asked to return the preferred one to use. + * + * @param editors a list of editor descriptors that are candidates + * for the editor input to open in. + */ + prefersEditor>(editors: T[]): T | undefined { + return firstOrDefault(editors); + } + isDisposed(): boolean { return this.disposed; } @@ -828,6 +856,12 @@ export class SideBySideEditorInput extends EditorInput { return this.description; } + override getTelemetryDescriptor(): { [key: string]: unknown } { + const descriptor = this.primary.getTelemetryDescriptor(); + + return Object.assign(descriptor, super.getTelemetryDescriptor()); + } + override isDirty(): boolean { return this.primary.isDirty(); } @@ -848,12 +882,6 @@ export class SideBySideEditorInput extends EditorInput { return this.primary.revert(group, options); } - override getTelemetryDescriptor(): { [key: string]: unknown } { - const descriptor = this.primary.getTelemetryDescriptor(); - - return Object.assign(descriptor, super.getTelemetryDescriptor()); - } - override matches(otherInput: unknown): boolean { if (otherInput === this) { return true; diff --git a/src/vs/workbench/common/editor/diffEditorInput.ts b/src/vs/workbench/common/editor/diffEditorInput.ts index 53800a77d3b..fee2f01b4bc 100644 --- a/src/vs/workbench/common/editor/diffEditorInput.ts +++ b/src/vs/workbench/common/editor/diffEditorInput.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EditorModel, EditorInput, SideBySideEditorInput, TEXT_DIFF_EDITOR_ID, BINARY_DIFF_EDITOR_ID, Verbosity } from 'vs/workbench/common/editor'; +import { EditorModel, EditorInput, SideBySideEditorInput, TEXT_DIFF_EDITOR_ID, BINARY_DIFF_EDITOR_ID, Verbosity, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { DiffEditorModel } from 'vs/workbench/common/editor/diffEditorModel'; import { TextDiffEditorModel } from 'vs/workbench/common/editor/textDiffEditorModel'; @@ -104,8 +104,12 @@ export class DiffEditorInput extends SideBySideEditorInput { return this.cachedModel; } - override getPreferredEditorId(candidates: string[]): string { - return this.forceOpenAsBinary ? BINARY_DIFF_EDITOR_ID : TEXT_DIFF_EDITOR_ID; + override prefersEditor>(editors: T[]): T | undefined { + if (this.forceOpenAsBinary) { + return editors.find(editor => editor.typeId === BINARY_DIFF_EDITOR_ID); + } + + return editors.find(editor => editor.typeId === TEXT_DIFF_EDITOR_ID); } private async createModel(): Promise { diff --git a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts index 3aa6dba71e0..f8c76e26442 100644 --- a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, isTextEditorPane, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, isTextEditorPane, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { FileOperationError, FileOperationResult, FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files'; @@ -264,8 +264,12 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements return super.isSaving(); } - override getPreferredEditorId(candidates: string[]): string { - return this.forceOpenAs === ForceOpenAs.Binary ? BINARY_FILE_EDITOR_ID : TEXT_FILE_EDITOR_ID; + override prefersEditor>(editors: T[]): T | undefined { + if (this.forceOpenAs === ForceOpenAs.Binary) { + return editors.find(editor => editor.typeId === BINARY_FILE_EDITOR_ID); + } + + return editors.find(editor => editor.typeId === TEXT_FILE_EDITOR_ID); } override resolve(): Promise { diff --git a/src/vs/workbench/contrib/output/browser/outputView.ts b/src/vs/workbench/contrib/output/browser/outputView.ts index 54e4474aa16..93cab3db91a 100644 --- a/src/vs/workbench/contrib/output/browser/outputView.ts +++ b/src/vs/workbench/contrib/output/browser/outputView.ts @@ -221,7 +221,7 @@ export class OutputEditor extends AbstractTextResourceEditor { return channel ? nls.localize('outputViewWithInputAriaLabel', "{0}, Output panel", channel.label) : nls.localize('outputViewAriaLabel', "Output panel"); } - override async setInput(input: TextResourceEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise {// + override async setInput(input: TextResourceEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { const focus = !(options && options.preserveFocus); if (input.matches(this.input)) { return; diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts index 71a30eac276..f77a8750c8a 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts @@ -151,7 +151,7 @@ export class PreferencesEditor extends EditorPane { this.preferencesRenderers.editFocusedPreference(); } - override setInput(input: PreferencesEditorInput, options: SettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise {// + override setInput(input: PreferencesEditorInput, options: SettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { this.defaultSettingsEditorContextKey.set(true); this.defaultSettingsJSONEditorContextKey.set(true); if (options && options.query) { diff --git a/src/vs/workbench/electron-sandbox/shared.desktop.main.ts b/src/vs/workbench/electron-sandbox/shared.desktop.main.ts index fa857a32a3d..3b3c6b80a01 100644 --- a/src/vs/workbench/electron-sandbox/shared.desktop.main.ts +++ b/src/vs/workbench/electron-sandbox/shared.desktop.main.ts @@ -208,7 +208,7 @@ export abstract class SharedDesktopMain extends Disposable { await result; } - // Uri Identity + // URI Identity const uriIdentityService = new UriIdentityService(fileService); serviceCollection.set(IUriIdentityService, uriIdentityService); diff --git a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts index 1dd55703448..7cb60385af2 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { EditorPane, EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane'; import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor'; -import { EditorInput, EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; @@ -16,7 +16,7 @@ import { workbenchInstantiationService, TestEditorGroupView, TestEditorGroupsSer import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; import { URI } from 'vs/base/common/uri'; -import { IEditorRegistry, EditorDescriptor } from 'vs/workbench/browser/editor'; +import { EditorDescriptor, EditorRegistry } from 'vs/workbench/browser/editor'; import { CancellationToken } from 'vs/base/common/cancellation'; import { IEditorModel } from 'vs/platform/editor/common/editor'; import { DisposableStore, dispose } from 'vs/base/common/lifecycle'; @@ -30,8 +30,8 @@ import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/w const NullThemeService = new TestThemeService(); -let EditorRegistry: IEditorRegistry = Registry.as(EditorExtensions.Editors); -let EditorInputRegistry: IEditorInputFactoryRegistry = Registry.as(EditorExtensions.EditorInputFactories); +const editorRegistry: EditorRegistry = Registry.as(EditorExtensions.Editors); +const editorInputRegistry: IEditorInputFactoryRegistry = Registry.as(EditorExtensions.EditorInputFactories); class TestEditor extends EditorPane { @@ -75,8 +75,8 @@ class TestInput extends EditorInput { readonly resource = undefined; - override getPreferredEditorId(ids: string[]) { - return ids[1]; + override prefersEditor>(editors: T[]): T | undefined { + return editors[1]; } override get typeId(): string { @@ -105,85 +105,85 @@ class TestResourceEditorInput extends TextResourceEditorInput { } suite('Workbench EditorPane', () => { test('EditorPane API', async () => { - let e = new TestEditor(NullTelemetryService); - let input = new OtherTestInput(); - let options = new EditorOptions(); + const editor = new TestEditor(NullTelemetryService); + const input = new OtherTestInput(); + const options = new EditorOptions(); - assert(!e.isVisible()); - assert(!e.input); + assert(!editor.isVisible()); + assert(!editor.input); - await e.setInput(input, options, Object.create(null), CancellationToken.None); - assert.strictEqual(input, e.input); + await editor.setInput(input, options, Object.create(null), CancellationToken.None); + assert.strictEqual(input, editor.input); const group = new TestEditorGroupView(1); - e.setVisible(true, group); - assert(e.isVisible()); - assert.strictEqual(e.group, group); + editor.setVisible(true, group); + assert(editor.isVisible()); + assert.strictEqual(editor.group, group); input.onWillDispose(() => { assert(false); }); - e.dispose(); - e.clearInput(); - e.setVisible(false, group); - assert(!e.isVisible()); - assert(!e.input); - assert(!e.getControl()); + editor.dispose(); + editor.clearInput(); + editor.setVisible(false, group); + assert(!editor.isVisible()); + assert(!editor.input); + assert(!editor.getControl()); }); test('EditorDescriptor', () => { - let d = EditorDescriptor.create(TestEditor, 'id', 'name'); - assert.strictEqual(d.getId(), 'id'); - assert.strictEqual(d.getName(), 'name'); + const editorDescriptor = EditorDescriptor.create(TestEditor, 'id', 'name'); + assert.strictEqual(editorDescriptor.typeId, 'id'); + assert.strictEqual(editorDescriptor.name, 'name'); }); test('Editor Registration', function () { - let d1 = EditorDescriptor.create(TestEditor, 'id1', 'name'); - let d2 = EditorDescriptor.create(OtherTestEditor, 'id2', 'name'); + const editorDescriptor1 = EditorDescriptor.create(TestEditor, 'id1', 'name'); + const editorDescriptor2 = EditorDescriptor.create(OtherTestEditor, 'id2', 'name'); - let oldEditorsCnt = EditorRegistry.getEditors().length; - let oldInputCnt = (EditorRegistry).getEditorInputs().length; + const oldEditorsCnt = editorRegistry.getEditors().length; + const oldInputCnt = editorRegistry.getEditorInputs().length; - const dispose1 = EditorRegistry.registerEditor(d1, [new SyncDescriptor(TestInput)]); - const dispose2 = EditorRegistry.registerEditor(d2, [new SyncDescriptor(TestInput), new SyncDescriptor(OtherTestInput)]); + const dispose1 = editorRegistry.registerEditor(editorDescriptor1, [new SyncDescriptor(TestInput)]); + const dispose2 = editorRegistry.registerEditor(editorDescriptor2, [new SyncDescriptor(TestInput), new SyncDescriptor(OtherTestInput)]); - assert.strictEqual(EditorRegistry.getEditors().length, oldEditorsCnt + 2); - assert.strictEqual((EditorRegistry).getEditorInputs().length, oldInputCnt + 3); + assert.strictEqual(editorRegistry.getEditors().length, oldEditorsCnt + 2); + assert.strictEqual(editorRegistry.getEditorInputs().length, oldInputCnt + 3); - assert.strictEqual(EditorRegistry.getEditor(new TestInput()), d2); - assert.strictEqual(EditorRegistry.getEditor(new OtherTestInput()), d2); + assert.strictEqual(editorRegistry.getEditor(new TestInput()), editorDescriptor2); + assert.strictEqual(editorRegistry.getEditor(new OtherTestInput()), editorDescriptor2); - assert.strictEqual(EditorRegistry.getEditorById('id1'), d1); - assert.strictEqual(EditorRegistry.getEditorById('id2'), d2); - assert(!EditorRegistry.getEditorById('id3')); + assert.strictEqual(editorRegistry.getEditorByType('id1'), editorDescriptor1); + assert.strictEqual(editorRegistry.getEditorByType('id2'), editorDescriptor2); + assert(!editorRegistry.getEditorByType('id3')); dispose([dispose1, dispose2]); }); test('Editor Lookup favors specific class over superclass (match on specific class)', function () { - let d1 = EditorDescriptor.create(TestEditor, 'id1', 'name'); + const d1 = EditorDescriptor.create(TestEditor, 'id1', 'name'); const disposables = new DisposableStore(); disposables.add(registerTestResourceEditor()); - disposables.add(EditorRegistry.registerEditor(d1, [new SyncDescriptor(TestResourceEditorInput)])); + disposables.add(editorRegistry.registerEditor(d1, [new SyncDescriptor(TestResourceEditorInput)])); - let inst = workbenchInstantiationService(); + const inst = workbenchInstantiationService(); - const editor = EditorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst); + const editor = editorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst); assert.strictEqual(editor.getId(), 'testEditor'); - const otherEditor = EditorRegistry.getEditor(inst.createInstance(TextResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst); + const otherEditor = editorRegistry.getEditor(inst.createInstance(TextResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst); assert.strictEqual(otherEditor.getId(), 'workbench.editors.textResourceEditor'); disposables.dispose(); }); test('Editor Lookup favors specific class over superclass (match on super class)', function () { - let inst = workbenchInstantiationService(); + const inst = workbenchInstantiationService(); const disposables = new DisposableStore(); disposables.add(registerTestResourceEditor()); - const editor = EditorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst); + const editor = editorRegistry.getEditor(inst.createInstance(TestResourceEditorInput, URI.file('/fake'), 'fake', '', undefined))!.instantiate(inst); assert.strictEqual('workbench.editors.textResourceEditor', editor.getId()); @@ -192,17 +192,17 @@ suite('Workbench EditorPane', () => { test('Editor Input Serializer', function () { const testInput = new TestEditorInput(URI.file('/fake'), 'testTypeId'); - workbenchInstantiationService().invokeFunction(accessor => EditorInputRegistry.start(accessor)); - const disposable = EditorInputRegistry.registerEditorInputSerializer(testInput.typeId, TestInputSerializer); + workbenchInstantiationService().invokeFunction(accessor => editorInputRegistry.start(accessor)); + const disposable = editorInputRegistry.registerEditorInputSerializer(testInput.typeId, TestInputSerializer); - let factory = EditorInputRegistry.getEditorInputSerializer('testTypeId'); + let factory = editorInputRegistry.getEditorInputSerializer('testTypeId'); assert(factory); - factory = EditorInputRegistry.getEditorInputSerializer(testInput); + factory = editorInputRegistry.getEditorInputSerializer(testInput); assert(factory); // throws when registering serializer for same type - assert.throws(() => EditorInputRegistry.registerEditorInputSerializer(testInput.typeId, TestInputSerializer)); + assert.throws(() => editorInputRegistry.registerEditorInputSerializer(testInput.typeId, TestInputSerializer)); disposable.dispose(); }); @@ -283,7 +283,7 @@ suite('Workbench EditorPane', () => { interface TestViewState { line: number; } const rawMemento = Object.create(null); - let memento = new EditorMemento('id', 'key', rawMemento, 3, editorGroupService); + const memento = new EditorMemento('id', 'key', rawMemento, 3, editorGroupService); memento.saveEditorState(testGroup0, URI.file('/some/folder/file-1.txt'), { line: 1 }); memento.saveEditorState(testGroup0, URI.file('/some/folder/file-2.txt'), { line: 2 }); @@ -326,7 +326,7 @@ suite('Workbench EditorPane', () => { } const rawMemento = Object.create(null); - let memento = new EditorMemento('id', 'key', rawMemento, 3, new TestEditorGroupsService()); + const memento = new EditorMemento('id', 'key', rawMemento, 3, new TestEditorGroupsService()); const testInputA = new TestEditorInput(URI.file('/A')); @@ -364,7 +364,7 @@ suite('Workbench EditorPane', () => { } const rawMemento = Object.create(null); - let memento = new EditorMemento('id', 'key', rawMemento, 3, new TestEditorGroupsService()); + const memento = new EditorMemento('id', 'key', rawMemento, 3, new TestEditorGroupsService()); const testInputA = new TestEditorInput(URI.file('/A')); @@ -401,6 +401,7 @@ suite('Workbench EditorPane', () => { }); test('WorkspaceTrustRequiredEditor', async function () { + class TrustRequiredTestEditor extends EditorPane { constructor(@ITelemetryService telemetryService: ITelemetryService) { super('TestEditor', NullTelemetryService, NullThemeService, new TestStorageService()); @@ -443,8 +444,8 @@ suite('Workbench EditorPane', () => { const group = editorPart.activeGroup; - let editorDescriptor = EditorDescriptor.create(TrustRequiredTestEditor, 'id1', 'name'); - disposables.add(EditorRegistry.registerEditor(editorDescriptor, [new SyncDescriptor(TrustRequiredTestInput)])); + const editorDescriptor = EditorDescriptor.create(TrustRequiredTestEditor, 'id1', 'name'); + disposables.add(editorRegistry.registerEditor(editorDescriptor, [new SyncDescriptor(TrustRequiredTestInput)])); const testInput = new TrustRequiredTestInput(); From ab793cf02ac97a5358f304fc156776c3140925de Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 09:41:59 +0200 Subject: [PATCH 029/140] editors - make dnd code ready to delegate serialisation to respective editors //cc @lramos15 --- src/vs/workbench/browser/dnd.ts | 228 +++++++++++------- .../browser/parts/editor/editorCommands.ts | 15 +- .../browser/parts/editor/editorDropTarget.ts | 4 +- .../browser/parts/editor/tabsTitleControl.ts | 2 +- .../browser/parts/editor/titleControl.ts | 52 ++-- src/vs/workbench/common/editor.ts | 24 +- .../customEditor/browser/customEditorInput.ts | 10 + .../files/browser/editors/fileEditorInput.ts | 7 + .../files/browser/views/explorerViewer.ts | 2 +- .../files/browser/views/openEditorsView.ts | 20 +- .../markers/browser/markersTreeViewer.ts | 4 +- .../notebook/common/notebookEditorInput.ts | 10 + .../search/browser/searchResultsView.ts | 5 +- .../common/untitledTextEditorInput.ts | 9 +- .../test/browser/parts/editor/editor.test.ts | 11 +- 15 files changed, 252 insertions(+), 151 deletions(-) diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index 17c55ea7b13..5dbcf6d4fc8 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { bufferToReadable, VSBuffer } from 'vs/base/common/buffer'; import { FileAccess, Schemas } from 'vs/base/common/network'; -import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { IResourceEditorInput, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd'; import { DragMouseEvent } from 'vs/base/browser/mouseEvent'; import { normalizeDriveLetter } from 'vs/base/common/labels'; @@ -21,17 +21,18 @@ import { MIME_BINARY } from 'vs/base/common/mime'; import { isWindows } from 'vs/base/common/platform'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; -import { IEditorIdentifier, GroupIdentifier, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorIdentifier, GroupIdentifier, IEditorInputFactoryRegistry, EditorExtensions, isEditorIdentifier } from 'vs/workbench/common/editor'; import { IEditorService, IResourceEditorInputType } from 'vs/workbench/services/editor/common/editorService'; import { Disposable, IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { addDisposableListener, EventType } from 'vs/base/browser/dom'; -import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; import { withNullAsUndefined } from 'vs/base/common/types'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup'; import { Emitter } from 'vs/base/common/event'; import { NO_TYPE_ID } from 'vs/workbench/services/workingCopy/common/workingCopy'; +import { coalesce } from 'vs/base/common/arrays'; export interface IDraggedResource { resource: URI; @@ -148,7 +149,7 @@ export interface IResourcesDropHandlerOptions { * Whether to open the actual workspace when a workspace configuration file is dropped * or whether to open the configuration file within the editor as normal file. */ - allowWorkspaceOpen: boolean; + readonly allowWorkspaceOpen: boolean; } /** @@ -158,7 +159,7 @@ export interface IResourcesDropHandlerOptions { export class ResourcesDropHandler { constructor( - private options: IResourcesDropHandlerOptions, + private readonly options: IResourcesDropHandlerOptions, @IFileService private readonly fileService: IFileService, @IWorkspacesService private readonly workspacesService: IWorkspacesService, @ITextFileService private readonly textFileService: ITextFileService, @@ -185,7 +186,7 @@ export class ResourcesDropHandler { } // Add external ones to recently open list unless dropped resource is a workspace - const recentFiles: IRecentFile[] = untitledOrFileResources.filter(untitledOrFileResource => untitledOrFileResource.isExternal && untitledOrFileResource.resource.scheme === Schemas.file).map(d => ({ fileUri: d.resource })); + const recentFiles: IRecentFile[] = untitledOrFileResources.filter(untitledOrFileResource => untitledOrFileResource.isExternal && untitledOrFileResource.resource.scheme === Schemas.file).map(file => ({ fileUri: file.resource })); if (recentFiles.length) { this.workspacesService.addRecentlyOpened(recentFiles); } @@ -220,7 +221,7 @@ export class ResourcesDropHandler { // Check for workspace file being dropped if we are allowed to do so if (this.options.allowWorkspaceOpen) { - const externalFileOnDiskResources = untitledOrFileResources.filter(untitledOrFileResource => untitledOrFileResource.isExternal && untitledOrFileResource.resource.scheme === Schemas.file).map(d => d.resource); + const externalFileOnDiskResources = untitledOrFileResources.filter(untitledOrFileResource => untitledOrFileResource.isExternal && untitledOrFileResource.resource.scheme === Schemas.file).map(file => file.resource); if (externalFileOnDiskResources.length > 0) { return this.handleWorkspaceFileDrop(externalFileOnDiskResources); } @@ -305,71 +306,112 @@ export class ResourcesDropHandler { } } -export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: (URI | { resource: URI, isDirectory: boolean })[], optionsCallback: ((resource: URI) => ITextEditorOptions) | undefined, event: DragMouseEvent | DragEvent): void { - if (resources.length === 0 || !event.dataTransfer) { +interface IResourceStat { + resource: URI; + isDirectory?: boolean; +} + +export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: URI[], event: DragMouseEvent | DragEvent): void; +export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: IResourceStat[], event: DragMouseEvent | DragEvent): void; +export function fillResourceDataTransfers(accessor: ServicesAccessor, editors: IEditorIdentifier[], event: DragMouseEvent | DragEvent): void; +export function fillResourceDataTransfers(accessor: ServicesAccessor, resourcesOrEditors: Array, event: DragMouseEvent | DragEvent): void { + if (resourcesOrEditors.length === 0 || !event.dataTransfer) { return; } - const sources = resources.map(obj => { - if (URI.isUri(obj)) { - return { resource: obj, isDirectory: false /* assume resource is not a directory */ }; + // Extract resources from URIs or Editors + const resources: IResourceStat[] = coalesce(resourcesOrEditors.map(resourceOrEditor => { + if (URI.isUri(resourceOrEditor)) { + return { resource: resourceOrEditor }; } - return obj; - }); + if (isEditorIdentifier(resourceOrEditor)) { + if (resourceOrEditor.editor.resource) { + return { resource: resourceOrEditor.editor.resource }; + } + + return undefined; // editor without resource + } + + return resourceOrEditor; + })); // Text: allows to paste into text-capable areas const lineDelimiter = isWindows ? '\r\n' : '\n'; - event.dataTransfer.setData(DataTransfers.TEXT, sources.map(source => source.resource.scheme === Schemas.file ? normalize(normalizeDriveLetter(source.resource.fsPath)) : source.resource.toString()).join(lineDelimiter)); + event.dataTransfer.setData(DataTransfers.TEXT, resources.map(({ resource }) => resource.scheme === Schemas.file ? normalize(normalizeDriveLetter(resource.fsPath)) : resource.toString()).join(lineDelimiter)); // Download URL: enables support to drag a tab as file to desktop (only single file supported) - if (!sources[0].isDirectory) { - event.dataTransfer.setData(DataTransfers.DOWNLOAD_URL, [MIME_BINARY, basename(sources[0].resource), FileAccess.asBrowserUri(sources[0].resource).toString()].join(':')); + const firstFile = resources.find(resource => !resource.isDirectory); + if (firstFile) { + event.dataTransfer.setData(DataTransfers.DOWNLOAD_URL, [MIME_BINARY, basename(firstFile.resource), FileAccess.asBrowserUri(firstFile.resource).toString()].join(':')); } // Resource URLs: allows to drop multiple resources to a target in VS Code (not directories) - const files = sources.filter(source => !source.isDirectory); + const files = resources.filter(resource => !resource.isDirectory); if (files.length) { - event.dataTransfer.setData(DataTransfers.RESOURCES, JSON.stringify(files.map(file => file.resource.toString()))); + event.dataTransfer.setData(DataTransfers.RESOURCES, JSON.stringify(files.map(({ resource }) => resource.toString()))); } - // Editors: enables cross window DND of tabs into the editor area + // Editors: enables cross window DND of editors + // into the editor area while presering UI state const textFileService = accessor.get(ITextFileService); const editorService = accessor.get(IEditorService); + const editorGroupService = accessor.get(IEditorGroupsService); const draggedEditors: ISerializedDraggedEditor[] = []; - files.forEach(file => { - let options: ITextEditorOptions | undefined = undefined; - // Use provided callback for editor options - if (typeof optionsCallback === 'function') { - options = optionsCallback(file.resource); - } + for (const resourceOrEditor of resourcesOrEditors) { - // Otherwise try to figure out the view state from opened editors that match - else { - options = { - viewState: (() => { - const textEditorControls = editorService.visibleTextEditorControls; - for (const textEditorControl of textEditorControls) { - if (isCodeEditor(textEditorControl)) { - const model = textEditorControl.getModel(); - if (isEqual(model?.uri, file.resource)) { - return withNullAsUndefined(textEditorControl.saveViewState()); - } - } + // Extract resource editor from provided object or URI + let editor: IResourceEditorInput; + if (isEditorIdentifier(resourceOrEditor)) { + const editorCandidate = resourceOrEditor.editor.asResourceEditorInput(resourceOrEditor.groupId); + if (!editorCandidate) { + return; // not transferable editor (not serializable) + } + + editor = editorCandidate; + + if (!editor.options?.viewState) { + const group = editorGroupService.getGroup(resourceOrEditor.groupId); + if (group?.activeEditor === resourceOrEditor.editor) { + const activeControl = group.activeEditorPane?.getControl(); + if (isCodeEditor(activeControl)) { + editor.options = { + ...editor.options, + viewState: withNullAsUndefined(activeControl.saveViewState()) + }; } + } + } + } else { + const editorCandidate = URI.isUri(resourceOrEditor) ? { resource: resourceOrEditor } : !resourceOrEditor.isDirectory ? { resource: resourceOrEditor.resource } : undefined; + if (!editorCandidate) { + return; // not transferable editor (directory) + } - return undefined; - })() - }; + editor = editorCandidate; + + for (const textEditorControl of editorService.visibleTextEditorControls) { + if (isCodeEditor(textEditorControl)) { + const model = textEditorControl.getModel(); + if (isEqual(model?.uri, editor.resource)) { + editor.options = { + ...editor.options, + viewState: withNullAsUndefined(textEditorControl.saveViewState()) + }; + + break; + } + } + } } - // Try to find encoding and mode from text model + // Try to find encoding and mode from text model if any let encoding: string | undefined = undefined; let mode: string | undefined = undefined; - const model = file.resource.scheme === Schemas.untitled ? textFileService.untitled.get(file.resource) : textFileService.files.get(file.resource); + const model = editor.resource.scheme === Schemas.untitled ? textFileService.untitled.get(editor.resource) : textFileService.files.get(editor.resource); if (model) { encoding = model.getEncoding(); mode = model.getMode(); @@ -383,8 +425,8 @@ export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: } // Add as dragged editor - draggedEditors.push({ resource: file.resource.toString(), dirtyContent, options, encoding, mode }); - }); + draggedEditors.push({ resource: editor.resource.toString(), dirtyContent, options: editor.options, encoding, mode }); + } if (draggedEditors.length) { event.dataTransfer.setData(CodeDataTransfers.EDITORS, JSON.stringify(draggedEditors)); @@ -437,12 +479,12 @@ export class LocalSelectionTransfer { } export interface IDragAndDropObserverCallbacks { - onDragEnter: (e: DragEvent) => void; - onDragLeave: (e: DragEvent) => void; - onDrop: (e: DragEvent) => void; - onDragEnd: (e: DragEvent) => void; + readonly onDragEnter: (e: DragEvent) => void; + readonly onDragLeave: (e: DragEvent) => void; + readonly onDrop: (e: DragEvent) => void; + readonly onDragEnd: (e: DragEvent) => void; - onDragOver?: (e: DragEvent) => void; + readonly onDragOver?: (e: DragEvent) => void; } export class DragAndDropObserver extends Disposable { @@ -453,7 +495,7 @@ export class DragAndDropObserver extends Disposable { // repeadedly. private counter: number = 0; - constructor(private element: HTMLElement, private callbacks: IDragAndDropObserverCallbacks) { + constructor(private readonly element: HTMLElement, private readonly callbacks: IDragAndDropObserverCallbacks) { super(); this.registerListeners(); @@ -514,7 +556,10 @@ export function containsDragType(event: DragEvent, ...dragTypesToFind: string[]) return false; } -export type Before2D = { verticallyBefore: boolean; horizontallyBefore: boolean; }; +export type Before2D = { + readonly verticallyBefore: boolean; + readonly horizontallyBefore: boolean; +}; export interface ICompositeDragAndDrop { drop(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent, before?: Before2D): void; @@ -532,10 +577,13 @@ export interface ICompositeDragAndDropObserverCallbacks { } export class CompositeDragAndDropData implements IDragAndDropData { + constructor(private type: 'view' | 'composite', private id: string) { } + update(dataTransfer: DataTransfer): void { // no-op } + getData(): { type: 'view' | 'composite'; id: string; @@ -545,44 +593,51 @@ export class CompositeDragAndDropData implements IDragAndDropData { } export interface IDraggedCompositeData { - eventData: DragEvent; - dragAndDropData: CompositeDragAndDropData; + readonly eventData: DragEvent; + readonly dragAndDropData: CompositeDragAndDropData; } export class DraggedCompositeIdentifier { - constructor(private _compositeId: string) { } + + constructor(private compositeId: string) { } get id(): string { - return this._compositeId; + return this.compositeId; } } export class DraggedViewIdentifier { - constructor(private _viewId: string) { } + + constructor(private viewId: string) { } get id(): string { - return this._viewId; + return this.viewId; } } export type ViewType = 'composite' | 'view'; export class CompositeDragAndDropObserver extends Disposable { - private transferData: LocalSelectionTransfer; - private _onDragStart = this._register(new Emitter()); - private _onDragEnd = this._register(new Emitter()); - private static _instance: CompositeDragAndDropObserver | undefined; + + private static instance: CompositeDragAndDropObserver | undefined; + static get INSTANCE(): CompositeDragAndDropObserver { - if (!CompositeDragAndDropObserver._instance) { - CompositeDragAndDropObserver._instance = new CompositeDragAndDropObserver(); + if (!CompositeDragAndDropObserver.instance) { + CompositeDragAndDropObserver.instance = new CompositeDragAndDropObserver(); } - return CompositeDragAndDropObserver._instance; + + return CompositeDragAndDropObserver.instance; } + + private readonly transferData = LocalSelectionTransfer.getInstance(); + + private readonly onDragStart = this._register(new Emitter()); + private readonly onDragEnd = this._register(new Emitter()); + private constructor() { super(); - this.transferData = LocalSelectionTransfer.getInstance(); - this._register(this._onDragEnd.event(e => { + this._register(this.onDragEnd.event(e => { const id = e.dragAndDropData.getData().id; const type = e.dragAndDropData.getData().type; const data = this.readDragData(type); @@ -591,6 +646,7 @@ export class CompositeDragAndDropObserver extends Disposable { } })); } + private readDragData(type: ViewType): CompositeDragAndDropData | undefined { if (this.transferData.hasData(type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype)) { const data = this.transferData.getData(type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype); @@ -598,11 +654,14 @@ export class CompositeDragAndDropObserver extends Disposable { return new CompositeDragAndDropData(type, data[0].id); } } + return undefined; } + private writeDragData(id: string, type: ViewType): void { this.transferData.setData([type === 'view' ? new DraggedViewIdentifier(id) : new DraggedCompositeIdentifier(id)], type === 'view' ? DraggedViewIdentifier.prototype : DraggedCompositeIdentifier.prototype); } + registerTarget(element: HTMLElement, callbacks: ICompositeDragAndDropObserverCallbacks): IDisposable { const disposableStore = new DisposableStore(); disposableStore.add(new DragAndDropObserver(element, { @@ -611,6 +670,7 @@ export class CompositeDragAndDropObserver extends Disposable { }, onDragEnter: e => { e.preventDefault(); + if (callbacks.onDragEnter) { const data = this.readDragData('composite') || this.readDragData('view'); if (data) { @@ -634,11 +694,12 @@ export class CompositeDragAndDropObserver extends Disposable { callbacks.onDrop({ eventData: e, dragAndDropData: data! }); // Fire drag event in case drop handler destroys the dragged element - this._onDragEnd.fire({ eventData: e, dragAndDropData: data! }); + this.onDragEnd.fire({ eventData: e, dragAndDropData: data! }); } }, onDragOver: e => { e.preventDefault(); + if (callbacks.onDragOver) { const data = this.readDragData('composite') || this.readDragData('view'); if (!data) { @@ -649,45 +710,47 @@ export class CompositeDragAndDropObserver extends Disposable { } } })); + if (callbacks.onDragStart) { - this._onDragStart.event(e => { + this.onDragStart.event(e => { callbacks.onDragStart!(e); }, this, disposableStore); } + if (callbacks.onDragEnd) { - this._onDragEnd.event(e => { + this.onDragEnd.event(e => { callbacks.onDragEnd!(e); }); } + return this._register(disposableStore); } registerDraggable(element: HTMLElement, draggedItemProvider: () => { type: ViewType, id: string }, callbacks: ICompositeDragAndDropObserverCallbacks): IDisposable { element.draggable = true; + const disposableStore = new DisposableStore(); + disposableStore.add(addDisposableListener(element, EventType.DRAG_START, e => { const { id, type } = draggedItemProvider(); this.writeDragData(id, type); - if (e.dataTransfer) { - e.dataTransfer.setDragImage(element, 0, 0); - } + e.dataTransfer?.setDragImage(element, 0, 0); - this._onDragStart.fire({ eventData: e, dragAndDropData: this.readDragData(type)! }); + this.onDragStart.fire({ eventData: e, dragAndDropData: this.readDragData(type)! }); })); + disposableStore.add(new DragAndDropObserver(element, { onDragEnd: e => { const { type } = draggedItemProvider(); const data = this.readDragData(type); - if (!data) { return; } - this._onDragEnd.fire({ eventData: e, dragAndDropData: data! }); + this.onDragEnd.fire({ eventData: e, dragAndDropData: data! }); }, onDragEnter: e => { - if (callbacks.onDragEnter) { const data = this.readDragData('composite') || this.readDragData('view'); if (!data) { @@ -712,14 +775,14 @@ export class CompositeDragAndDropObserver extends Disposable { onDrop: e => { if (callbacks.onDrop) { const data = this.readDragData('composite') || this.readDragData('view'); - if (!data) { return; } + callbacks.onDrop({ eventData: e, dragAndDropData: data! }); // Fire drag event in case drop handler destroys the dragged element - this._onDragEnd.fire({ eventData: e, dragAndDropData: data! }); + this.onDragEnd.fire({ eventData: e, dragAndDropData: data! }); } }, onDragOver: e => { @@ -733,16 +796,19 @@ export class CompositeDragAndDropObserver extends Disposable { } } })); + if (callbacks.onDragStart) { - this._onDragStart.event(e => { + this.onDragStart.event(e => { callbacks.onDragStart!(e); }, this, disposableStore); } + if (callbacks.onDragEnd) { - this._onDragEnd.event(e => { + this.onDragEnd.event(e => { callbacks.onDragEnd!(e); }, this, disposableStore); } + return this._register(disposableStore); } } diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 32e73326a59..44f83d3e69e 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { isObject, isString, isUndefined, isNumber, withNullAsUndefined } from 'vs/base/common/types'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { TextCompareEditorVisibleContext, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane, ActiveEditorStickyContext, EditorsOrder, viewColumnToEditorGroup, EditorGroupColumn, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { TextCompareEditorVisibleContext, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane, ActiveEditorStickyContext, EditorsOrder, viewColumnToEditorGroup, EditorGroupColumn, EditorInputCapabilities, isEditorIdentifier } from 'vs/workbench/common/editor'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor'; @@ -1046,15 +1046,12 @@ export function getMultiSelectedEditorContexts(editorContext: IEditorCommandsCon } function isEditorGroup(thing: unknown): thing is IEditorGroup { - const group = thing as IEditorGroup; + const group = thing as IEditorGroup | undefined; + if (!group) { + return false; + } - return group && typeof group.id === 'number' && Array.isArray(group.editors); -} - -function isEditorIdentifier(thing: unknown): thing is IEditorIdentifier { - const identifier = thing as IEditorIdentifier; - - return identifier && typeof identifier.groupId === 'number'; + return typeof group.id === 'number' && Array.isArray(group.editors); } export function setup(): void { diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index 3aa25a20977..6771be93af0 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -354,9 +354,7 @@ class DropOverlay extends Themable { // Check for URI transfer else { const dropHandler = this.instantiationService.createInstance(ResourcesDropHandler, { allowWorkspaceOpen: true /* open workspace instead of file if dropped */ }); - dropHandler.handleDrop(event, () => ensureTargetGroup(), targetGroup => { - targetGroup?.focus(); - }); + dropHandler.handleDrop(event, () => ensureTargetGroup(), targetGroup => targetGroup?.focus()); } } diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index fc031fa5898..27b7757f895 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -802,7 +802,7 @@ export class TabsTitleControl extends TitleControl { } // Apply some datatransfer types to allow for dragging the element outside of the application - this.doFillResourceDataTransfers(editor, e); + this.doFillResourceDataTransfers([editor], e); // Fixes https://github.com/microsoft/vscode/issues/18733 tab.classList.add('dragged'); diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index 028cf936329..742d52430a5 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/titlecontrol'; +import { localize } from 'vs/nls'; import { applyDragImage, DataTransfers } from 'vs/base/browser/dnd'; import { addDisposableListener, Dimension, EventType } from 'vs/base/browser/dom'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; @@ -12,8 +13,6 @@ import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, SubmenuAction } from 'vs/base/common/actions'; import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { dispose, DisposableStore } from 'vs/base/common/lifecycle'; -import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; -import { localize } from 'vs/nls'; import { createActionViewItem, createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -31,13 +30,12 @@ import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs'; import { BreadcrumbsControl, IBreadcrumbsControlOptions } from 'vs/workbench/browser/parts/editor/breadcrumbsControl'; import { IEditorGroupsAccessor, IEditorGroupTitleHeight, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor'; -import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, EditorResourceAccessor, IEditorPartOptions, SideBySideEditor, ActiveEditorPinnedContext, ActiveEditorStickyContext } from 'vs/workbench/common/editor'; +import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, EditorResourceAccessor, IEditorPartOptions, SideBySideEditor, ActiveEditorPinnedContext, ActiveEditorStickyContext, EditorsOrder } from 'vs/workbench/common/editor'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { IFileService } from 'vs/platform/files/common/files'; import { withNullAsUndefined, withUndefinedAsNull, assertIsDefined } from 'vs/base/common/types'; import { isFirefox } from 'vs/base/browser/browser'; -import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { isPromiseCanceledError } from 'vs/base/common/errors'; export interface IToolbarActions { @@ -254,11 +252,16 @@ export abstract class TitleControl extends Themable { e.dataTransfer.effectAllowed = 'copyMove'; } - // If tabs are disabled, treat dragging as if an editor tab was dragged + // Drag all tabs of the group if tabs are enabled let hasDataTransfer = false; - if (!this.accessor.partOptions.showTabs) { + if (this.accessor.partOptions.showTabs) { + hasDataTransfer = this.doFillResourceDataTransfers(this.group.getEditors(EditorsOrder.SEQUENTIAL), e); + } + + // Otherwise only drag the active editor + else { if (this.group.activeEditor) { - hasDataTransfer = this.doFillResourceDataTransfers(this.group.activeEditor, e); + hasDataTransfer = this.doFillResourceDataTransfers([this.group.activeEditor], e); } } @@ -284,37 +287,14 @@ export abstract class TitleControl extends Themable { })); } - protected doFillResourceDataTransfers(editor: IEditorInput, e: DragEvent): boolean { - const resource = EditorResourceAccessor.getOriginalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }); - if (!resource) { - return false; + protected doFillResourceDataTransfers(editors: readonly IEditorInput[], e: DragEvent): boolean { + if (editors.length) { + this.instantiationService.invokeFunction(fillResourceDataTransfers, editors.map(editor => ({ editor, groupId: this.group.id })), e); + + return true; } - let editorOptions: ITextEditorOptions = { - viewState: (() => { - if (this.group.activeEditor === editor) { - const activeControl = this.group.activeEditorPane?.getControl(); - if (isCodeEditor(activeControl)) { - return withNullAsUndefined(activeControl.saveViewState()); - } - } - - return undefined; - })(), - sticky: this.group.isSticky(editor) - }; - - // If it's a custom editor or a notebook add the viewtype - if ((editor as object).hasOwnProperty('viewType')) { - interface EditorInputWithViewType extends IEditorInput { - viewType: string; - } - editorOptions = { ...editorOptions, override: (editor as EditorInputWithViewType).viewType }; - } - - this.instantiationService.invokeFunction(fillResourceDataTransfers, [resource], () => editorOptions, e); - - return true; + return false; } protected onContextMenu(editor: IEditorInput, e: Event, node: HTMLElement): void { diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 657e8201de1..2b3bd51ae6a 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -5,7 +5,7 @@ import { localize } from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; -import { withNullAsUndefined, assertIsDefined } from 'vs/base/common/types'; +import { withNullAsUndefined, assertIsDefined, isUndefinedOrNull } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IEditor, IEditorViewState, ScrollType, IDiffEditor } from 'vs/editor/common/editorCommon'; @@ -551,6 +551,15 @@ export interface IEditorInput extends IDisposable { */ copy(): IEditorInput; + /** + * Returns a representation of this typed editor input as untyped + * resource editor input that e.g. can be used to serialize the + * editor input into a form that it can be restored. + * + * May return `undefined` if a untyped representatin is not supported. + */ + asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput | undefined; + /** * Returns if the other object matches this input. */ @@ -670,6 +679,10 @@ export abstract class EditorInput extends Disposable implements IEditorInput { return firstOrDefault(editors); } + asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput | undefined { + return undefined; + } + isDisposed(): boolean { return this.disposed; } @@ -1259,6 +1272,15 @@ export interface IEditorIdentifier { editor: IEditorInput; } +export function isEditorIdentifier(thing: unknown): thing is IEditorIdentifier { + const identifier = thing as IEditorIdentifier | undefined; + if (!identifier) { + return false; + } + + return typeof identifier.groupId === 'number' && !isUndefinedOrNull(identifier.editor); +} + /** * The editor commands context is used for editor commands (e.g. in the editor title) * and we must ensure that the context is serializable because it potentially travels diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index b40dbba7bc2..c7e320798f9 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -13,6 +13,7 @@ import { assertIsDefined } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { generateUuid } from 'vs/base/common/uuid'; import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILabelService } from 'vs/platform/label/common/label'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; @@ -301,4 +302,13 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { get untitledDocumentData(): VSBuffer | undefined { return this._untitledDocumentData; } + + override asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput { + return { + resource: this.resource, + options: { + override: this.viewType + } + }; + } } diff --git a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts index f8c76e26442..190dd9fd7a0 100644 --- a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts @@ -6,6 +6,7 @@ import { URI } from 'vs/base/common/uri'; import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, isTextEditorPane, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; +import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { FileOperationError, FileOperationResult, FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files'; import { ITextFileService, TextFileEditorModelState, TextFileResolveReason, TextFileOperationError, TextFileOperationResult, ITextFileEditorModel, EncodingMode } from 'vs/workbench/services/textfile/common/textfiles'; @@ -364,6 +365,12 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements return undefined; } + override asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput | undefined { + return { + resource: this.preferredResource + }; + } + override matches(otherInput: unknown): boolean { if (otherInput === this) { return true; diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index d87372512ac..c2ebd34c508 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -928,7 +928,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { const items = FileDragAndDrop.getStatsFromDragAndDropData(data as ElementsDragAndDropData, originalEvent); if (items && items.length && originalEvent.dataTransfer) { // Apply some datatransfer types to allow for dragging the element outside of the application - this.instantiationService.invokeFunction(fillResourceDataTransfers, items, undefined, originalEvent); + this.instantiationService.invokeFunction(accessor => fillResourceDataTransfers(accessor, items, originalEvent)); // The only custom data transfer we set from the explorer is a file transfer // to be able to DND between multiple code file explorers across windows diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index 394405c926f..d0d6f9a83ac 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -13,7 +13,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati import { IEditorGroupsService, IEditorGroup, GroupChangeKind, GroupsOrder, GroupOrientation } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { IEditorInput, Verbosity, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { IEditorInput, Verbosity, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities, IEditorIdentifier } from 'vs/workbench/common/editor'; import { SaveAllInGroupAction, CloseGroupAction } from 'vs/workbench/contrib/files/browser/fileActions'; import { OpenEditorsFocusedContext, ExplorerFocusedContext, IFilesConfiguration, OpenEditor } from 'vs/workbench/contrib/files/common/files'; import { CloseAllEditorsAction, CloseEditorAction, UnpinEditorAction } from 'vs/workbench/browser/parts/editor/editorActions'; @@ -38,7 +38,6 @@ import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewl import { IDragAndDropData, DataTransfers } from 'vs/base/browser/dnd'; import { memoize } from 'vs/base/common/decorators'; import { ElementsDragAndDropData, NativeDragAndDropData } from 'vs/base/browser/ui/list/listView'; -import { URI } from 'vs/base/common/uri'; import { withUndefinedAsNull } from 'vs/base/common/types'; import { isWeb } from 'vs/base/common/platform'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; @@ -653,21 +652,18 @@ class OpenEditorsDragAndDrop implements IListDragAndDrop).elements; - const resources: URI[] = []; + const editors: IEditorIdentifier[] = []; if (items) { - items.forEach(i => { - if (i instanceof OpenEditor) { - const resource = i.getResource(); - if (resource) { - resources.push(resource); - } + for (const item of items) { + if (item instanceof OpenEditor) { + editors.push(item); } - }); + } } - if (resources.length) { + if (editors.length) { // Apply some datatransfer types to allow for dragging the element outside of the application - this.instantiationService.invokeFunction(fillResourceDataTransfers, resources, undefined, originalEvent); + this.instantiationService.invokeFunction(fillResourceDataTransfers, editors, originalEvent); } } diff --git a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts index d8852663af1..110a27668bc 100644 --- a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts +++ b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts @@ -892,13 +892,13 @@ export class ResourceDragAndDrop implements ITreeDragAndDrop { onDragStart(data: IDragAndDropData, originalEvent: DragEvent): void { const elements = (data as ElementsDragAndDropData).elements; - const resources: URI[] = elements + const resources = elements .filter(e => e instanceof ResourceMarkers) .map(resourceMarker => (resourceMarker as ResourceMarkers).resource); if (resources.length) { // Apply some datatransfer types to allow for dragging the element outside of the application - this.instantiationService.invokeFunction(fillResourceDataTransfers, resources, undefined, originalEvent); + this.instantiationService.invokeFunction(accessor => fillResourceDataTransfers(accessor, resources, originalEvent)); } } diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts index 40370832c54..50bc8a479c7 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts @@ -18,6 +18,7 @@ import { Schemas } from 'vs/base/common/network'; import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; import { FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files'; import { AbstractResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; +import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; interface NotebookEditorInputOptions { startDirty?: boolean; @@ -199,6 +200,15 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { return this._editorModelReference.object; } + override asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput { + return { + resource: this.preferredResource, + options: { + override: this.viewType + } + }; + } + override matches(otherInput: unknown): boolean { if (this === otherInput) { return true; diff --git a/src/vs/workbench/contrib/search/browser/searchResultsView.ts b/src/vs/workbench/contrib/search/browser/searchResultsView.ts index c1a29a74874..a056ae40054 100644 --- a/src/vs/workbench/contrib/search/browser/searchResultsView.ts +++ b/src/vs/workbench/contrib/search/browser/searchResultsView.ts @@ -29,7 +29,6 @@ import { FileMatch, Match, RenderableMatch, SearchModel, FolderMatch } from 'vs/ import { IDragAndDropData } from 'vs/base/browser/dnd'; import { fillResourceDataTransfers } from 'vs/workbench/browser/dnd'; import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; -import { URI } from 'vs/base/common/uri'; interface IFolderMatchTemplate { label: IResourceLabel; @@ -372,13 +371,13 @@ export class SearchDND implements ITreeDragAndDrop { onDragStart(data: IDragAndDropData, originalEvent: DragEvent): void { const elements = (data as ElementsDragAndDropData).elements; - const resources: URI[] = elements + const resources = elements .filter((e): e is FileMatch => e instanceof FileMatch) .map((fm: FileMatch) => fm.resource); if (resources.length) { // Apply some datatransfer types to allow for dragging the element outside of the application - this.instantiationService.invokeFunction(fillResourceDataTransfers, resources, undefined, originalEvent); + this.instantiationService.invokeFunction(accessor => fillResourceDataTransfers(accessor, resources, originalEvent)); } } diff --git a/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts b/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts index 435ffae63e2..5fb9b7321b4 100644 --- a/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts +++ b/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Verbosity } from 'vs/workbench/common/editor'; +import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { GroupIdentifier, Verbosity } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { IUntitledTextEditorModel } from 'vs/workbench/services/untitled/common/untitledTextEditorModel'; import { EncodingMode, IEncodingSupport, IModeSupport, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; @@ -115,6 +116,12 @@ export class UntitledTextEditorInput extends AbstractTextResourceEditorInput imp return this.model; } + override asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput | undefined { + return { + resource: this.model.resource + }; + } + override matches(otherInput: unknown): boolean { if (otherInput === this) { return true; diff --git a/src/vs/workbench/test/browser/parts/editor/editor.test.ts b/src/vs/workbench/test/browser/parts/editor/editor.test.ts index c1b9d28c0b5..fea37aa6b42 100644 --- a/src/vs/workbench/test/browser/parts/editor/editor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editor.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, SideBySideEditorInput, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, SideBySideEditorInput, EditorInputCapabilities, isEditorIdentifier } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { URI } from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -208,6 +208,15 @@ suite('Workbench editor', () => { assert.strictEqual(EditorResourceAccessor.getOriginalUri(fileWithPreferredResource)?.toString(), preferredResource.toString()); }); + test('isEditorIdentifier', () => { + assert.strictEqual(isEditorIdentifier(undefined), false); + assert.strictEqual(isEditorIdentifier('undefined'), false); + + const testInput1 = new TestFileEditorInput(URI.file('resource1'), 'testTypeId'); + assert.strictEqual(isEditorIdentifier(testInput1), false); + assert.strictEqual(isEditorIdentifier({ editor: testInput1, groupId: 3 }), true); + }); + test('whenEditorClosed (single editor)', async function () { return testWhenEditorClosed(false, false, toResource.call(this, '/path/index.txt')); }); From f2248508a68d76bd66e80443b44a0ab714c179ef Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 10:53:28 +0200 Subject: [PATCH 030/140] fix tests on windows --- .../test/browser/parts/editor/resourceEditorInput.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts b/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts index 495a8ae7a75..8ec1833c8ea 100644 --- a/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts @@ -34,7 +34,7 @@ suite('Resource editors', () => { }); test('basics', async () => { - const resource = URI.from({ scheme: 'testResource', path: 'thePath' }); + const resource = URI.from({ scheme: 'testResource', path: 'thePath/of/the/resource.txt' }); const input = instantiationService.createInstance(TestResourceEditorInput, resource); From 856fb393cb4191bbf51c273a50dedf5987356fbf Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 11:09:52 +0200 Subject: [PATCH 031/140] editors - more dnd code polish towards any editor dnd --- src/vs/workbench/browser/dnd.ts | 172 ++++++++---------- .../browser/parts/editor/titleControl.ts | 4 +- .../common/editor/textResourceEditorInput.ts | 15 +- .../files/browser/editors/fileEditorInput.ts | 32 ++-- .../contrib/files/browser/fileImportExport.ts | 4 +- .../files/browser/views/explorerViewer.ts | 4 +- .../files/browser/views/openEditorsView.ts | 4 +- .../markers/browser/markersTreeViewer.ts | 4 +- .../search/browser/searchResultsView.ts | 4 +- .../common/untitledTextEditorInput.ts | 9 +- 10 files changed, 124 insertions(+), 128 deletions(-) diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index 5dbcf6d4fc8..b464dcd2a3c 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { bufferToReadable, VSBuffer } from 'vs/base/common/buffer'; import { FileAccess, Schemas } from 'vs/base/common/network'; -import { IResourceEditorInput, ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd'; import { DragMouseEvent } from 'vs/base/browser/mouseEvent'; import { normalizeDriveLetter } from 'vs/base/common/labels'; @@ -25,7 +25,7 @@ import { IEditorIdentifier, GroupIdentifier, IEditorInputFactoryRegistry, Editor import { IEditorService, IResourceEditorInputType } from 'vs/workbench/services/editor/common/editorService'; import { Disposable, IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { addDisposableListener, EventType } from 'vs/base/browser/dom'; -import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; import { withNullAsUndefined } from 'vs/base/common/types'; import { IHostService } from 'vs/workbench/services/host/browser/host'; @@ -33,15 +33,7 @@ import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/com import { Emitter } from 'vs/base/common/event'; import { NO_TYPE_ID } from 'vs/workbench/services/workingCopy/common/workingCopy'; import { coalesce } from 'vs/base/common/arrays'; - -export interface IDraggedResource { - resource: URI; - isExternal: boolean; -} - -interface ISerializedDraggedResource { - resource: string; -} +import { parse, stringify } from 'vs/base/common/marshalling'; export class DraggedEditorIdentifier { @@ -53,23 +45,22 @@ export class DraggedEditorGroupIdentifier { constructor(readonly identifier: GroupIdentifier) { } } -interface IDraggedEditorProps { - dirtyContent?: string; - encoding?: string; - mode?: string; - options?: ITextEditorOptions; -} - -export interface IDraggedEditor extends IDraggedResource, IDraggedEditorProps { } - -export interface ISerializedDraggedEditor extends ISerializedDraggedResource, IDraggedEditorProps { } - export const CodeDataTransfers = { EDITORS: 'CodeEditors', FILES: 'CodeFiles' }; -export function extractResources(e: DragEvent, externalOnly?: boolean): Array { +interface IDraggedResource { + resource: URI; + isExternal?: boolean; +} + +interface IDraggedEditor extends IResourceEditorInput { + contents?: string; + isExternal?: boolean; +} + +export function extractResourceDropTransfers(e: DragEvent, externalOnly?: boolean): Array { const resources: Array = []; if (e.dataTransfer && e.dataTransfer.types.length > 0) { @@ -80,17 +71,7 @@ export function extractResources(e: DragEvent, externalOnly?: boolean): Array { - resources.push({ - resource: URI.parse(draggedEditor.resource), - dirtyContent: draggedEditor.dirtyContent, - options: draggedEditor.options, - encoding: draggedEditor.encoding, - mode: draggedEditor.mode, - isExternal: false - }); - }); + resources.push(...parse(rawEditorsData)); } catch (error) { // Invalid transfer } @@ -171,7 +152,7 @@ export class ResourcesDropHandler { } async handleDrop(event: DragEvent, resolveTargetGroup: () => IEditorGroup | undefined, afterDrop: (targetGroup: IEditorGroup | undefined) => void, targetIndex?: number): Promise { - const untitledOrFileResources = extractResources(event).filter(resource => this.fileService.canHandleResource(resource.resource) || resource.resource.scheme === Schemas.untitled); + const untitledOrFileResources = extractResourceDropTransfers(event).filter(resource => this.fileService.canHandleResource(resource.resource) || resource.resource.scheme === Schemas.untitled); if (!untitledOrFileResources.length) { return; } @@ -213,7 +194,7 @@ export class ResourcesDropHandler { private async doHandleDrop(untitledOrFileResources: Array): Promise { // Check for dirty editors being dropped - const dirtyEditors: IDraggedEditor[] = untitledOrFileResources.filter(untitledOrFileResource => !untitledOrFileResource.isExternal && typeof (untitledOrFileResource as IDraggedEditor).dirtyContent === 'string'); + const dirtyEditors: IDraggedEditor[] = untitledOrFileResources.filter(untitledOrFileResource => !untitledOrFileResource.isExternal && typeof (untitledOrFileResource as IDraggedEditor).contents === 'string'); if (dirtyEditors.length > 0) { await Promise.all(dirtyEditors.map(dirtyEditor => this.handleDirtyEditorDrop(dirtyEditor))); return false; @@ -237,7 +218,10 @@ export class ResourcesDropHandler { if (droppedDirtyEditor.resource.scheme === Schemas.untitled) { const untitledTextEditorResource = this.editorService.createEditorInput({ mode: droppedDirtyEditor.mode, encoding: droppedDirtyEditor.encoding, forceUntitled: true }).resource; if (untitledTextEditorResource) { - droppedDirtyEditor.resource = untitledTextEditorResource; + droppedDirtyEditor = { + ...droppedDirtyEditor, + resource: untitledTextEditorResource + }; } } @@ -248,9 +232,9 @@ export class ResourcesDropHandler { // If the dropped editor is dirty with content we simply take that // content and turn it into a backup so that it loads the contents - if (typeof droppedDirtyEditor.dirtyContent === 'string') { + if (typeof droppedDirtyEditor.contents === 'string') { try { - await this.workingCopyBackupService.backup({ resource: droppedDirtyEditor.resource, typeId: NO_TYPE_ID }, bufferToReadable(VSBuffer.fromString(droppedDirtyEditor.dirtyContent))); + await this.workingCopyBackupService.backup({ resource: droppedDirtyEditor.resource, typeId: NO_TYPE_ID }, bufferToReadable(VSBuffer.fromString(droppedDirtyEditor.contents))); } catch (e) { // Ignore error } @@ -311,10 +295,10 @@ interface IResourceStat { isDirectory?: boolean; } -export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: URI[], event: DragMouseEvent | DragEvent): void; -export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: IResourceStat[], event: DragMouseEvent | DragEvent): void; -export function fillResourceDataTransfers(accessor: ServicesAccessor, editors: IEditorIdentifier[], event: DragMouseEvent | DragEvent): void; -export function fillResourceDataTransfers(accessor: ServicesAccessor, resourcesOrEditors: Array, event: DragMouseEvent | DragEvent): void { +export function fillResourceDragTransfers(accessor: ServicesAccessor, resources: URI[], event: DragMouseEvent | DragEvent): void; +export function fillResourceDragTransfers(accessor: ServicesAccessor, resources: IResourceStat[], event: DragMouseEvent | DragEvent): void; +export function fillResourceDragTransfers(accessor: ServicesAccessor, editors: IEditorIdentifier[], event: DragMouseEvent | DragEvent): void; +export function fillResourceDragTransfers(accessor: ServicesAccessor, resourcesOrEditors: Array, event: DragMouseEvent | DragEvent): void { if (resourcesOrEditors.length === 0 || !event.dataTransfer) { return; } @@ -356,80 +340,74 @@ export function fillResourceDataTransfers(accessor: ServicesAccessor, resourcesO // into the editor area while presering UI state const textFileService = accessor.get(ITextFileService); const editorService = accessor.get(IEditorService); - const editorGroupService = accessor.get(IEditorGroupsService); - const draggedEditors: ISerializedDraggedEditor[] = []; + const draggedEditors: IDraggedEditor[] = []; for (const resourceOrEditor of resourcesOrEditors) { // Extract resource editor from provided object or URI - let editor: IResourceEditorInput; + let editor: IResourceEditorInput | undefined = undefined; if (isEditorIdentifier(resourceOrEditor)) { - const editorCandidate = resourceOrEditor.editor.asResourceEditorInput(resourceOrEditor.groupId); - if (!editorCandidate) { - return; // not transferable editor (not serializable) - } - - editor = editorCandidate; - - if (!editor.options?.viewState) { - const group = editorGroupService.getGroup(resourceOrEditor.groupId); - if (group?.activeEditor === resourceOrEditor.editor) { - const activeControl = group.activeEditorPane?.getControl(); - if (isCodeEditor(activeControl)) { - editor.options = { - ...editor.options, - viewState: withNullAsUndefined(activeControl.saveViewState()) - }; - } - } - } + editor = resourceOrEditor.editor.asResourceEditorInput(resourceOrEditor.groupId); } else { - const editorCandidate = URI.isUri(resourceOrEditor) ? { resource: resourceOrEditor } : !resourceOrEditor.isDirectory ? { resource: resourceOrEditor.resource } : undefined; - if (!editorCandidate) { - return; // not transferable editor (directory) + let resource: URI | undefined = undefined; + if (URI.isUri(resourceOrEditor)) { + resource = resourceOrEditor; + } else if (!resourceOrEditor.isDirectory) { + resource = resourceOrEditor.resource; } - editor = editorCandidate; + if (!resource) { + continue; + } - for (const textEditorControl of editorService.visibleTextEditorControls) { - if (isCodeEditor(textEditorControl)) { - const model = textEditorControl.getModel(); - if (isEqual(model?.uri, editor.resource)) { - editor.options = { - ...editor.options, - viewState: withNullAsUndefined(textEditorControl.saveViewState()) - }; + // If we only got a resource to work with, try to resolve as many + // editor properties as possible. This currently only works with + // text editors and not custom editors. + const model = resource.scheme === Schemas.untitled ? textFileService.untitled.get(resource) : textFileService.files.get(resource); - break; - } + editor = { + resource, + encoding: model?.getEncoding(), + mode: model?.getMode(), + options: { + viewState: (() => { + for (const textEditorControl of editorService.visibleTextEditorControls) { + if (isCodeEditor(textEditorControl)) { + const model = textEditorControl.getModel(); + if (isEqual(model?.uri, resource)) { + return withNullAsUndefined(textEditorControl.saveViewState()); + } + } + } + + return undefined; + })() } - } + }; } - // Try to find encoding and mode from text model if any - let encoding: string | undefined = undefined; - let mode: string | undefined = undefined; - - const model = editor.resource.scheme === Schemas.untitled ? textFileService.untitled.get(editor.resource) : textFileService.files.get(editor.resource); - if (model) { - encoding = model.getEncoding(); - mode = model.getMode(); - } - - // If the resource is dirty or untitled, send over its content - // to restore dirty state. Get that from the text model directly - let dirtyContent: string | undefined = undefined; - if (model?.isDirty()) { - dirtyContent = model.textEditorModel.getValue(); + if (!editor) { + continue; // skip over editors that cannot be transferred via dnd } // Add as dragged editor - draggedEditors.push({ resource: editor.resource.toString(), dirtyContent, options: editor.options, encoding, mode }); + draggedEditors.push({ + ...editor, + contents: (() => { + // TODO@bpasero this should not happen from here but from the asResourceEditorInput() method + const model = editor.resource.scheme === Schemas.untitled ? textFileService.untitled.get(editor.resource) : textFileService.files.get(editor.resource); + if (model?.isDirty()) { + return model.textEditorModel.getValue(); + } + + return undefined; + })() + }); } if (draggedEditors.length) { - event.dataTransfer.setData(CodeDataTransfers.EDITORS, JSON.stringify(draggedEditors)); + event.dataTransfer.setData(CodeDataTransfers.EDITORS, stringify(draggedEditors)); } } diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index 742d52430a5..bf2e7034b84 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -25,7 +25,7 @@ import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { listActiveSelectionBackground, listActiveSelectionForeground } from 'vs/platform/theme/common/colorRegistry'; import { IThemeService, registerThemingParticipant, Themable } from 'vs/platform/theme/common/themeService'; -import { DraggedEditorGroupIdentifier, DraggedEditorIdentifier, fillResourceDataTransfers, LocalSelectionTransfer } from 'vs/workbench/browser/dnd'; +import { DraggedEditorGroupIdentifier, DraggedEditorIdentifier, fillResourceDragTransfers, LocalSelectionTransfer } from 'vs/workbench/browser/dnd'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs'; import { BreadcrumbsControl, IBreadcrumbsControlOptions } from 'vs/workbench/browser/parts/editor/breadcrumbsControl'; @@ -289,7 +289,7 @@ export abstract class TitleControl extends Themable { protected doFillResourceDataTransfers(editors: readonly IEditorInput[], e: DragEvent): boolean { if (editors.length) { - this.instantiationService.invokeFunction(fillResourceDataTransfers, editors.map(editor => ({ editor, groupId: this.group.id })), e); + this.instantiationService.invokeFunction(fillResourceDragTransfers, editors.map(editor => ({ editor, groupId: this.group.id })), e); return true; } diff --git a/src/vs/workbench/common/editor/textResourceEditorInput.ts b/src/vs/workbench/common/editor/textResourceEditorInput.ts index 548e64782f5..f9c536a1089 100644 --- a/src/vs/workbench/common/editor/textResourceEditorInput.ts +++ b/src/vs/workbench/common/editor/textResourceEditorInput.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { GroupIdentifier, IEditorInput, IRevertOptions } from 'vs/workbench/common/editor'; +import { GroupIdentifier, IEditorInput, IRevertOptions, isTextEditorPane } from 'vs/workbench/common/editor'; import { AbstractResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput'; import { URI } from 'vs/base/common/uri'; import { ITextFileService, ITextFileSaveOptions, IModeSupport } from 'vs/workbench/services/textfile/common/textfiles'; @@ -15,6 +15,7 @@ import { isEqual } from 'vs/base/common/resources'; import { ITextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'; import { TextResourceEditorModel } from 'vs/workbench/common/editor/textResourceEditorModel'; import { IReference } from 'vs/base/common/lifecycle'; +import { IEditorViewState } from 'vs/editor/common/editorCommon'; /** * The base class for all editor inputs that open in text editors. @@ -78,6 +79,18 @@ export abstract class AbstractTextResourceEditorInput extends AbstractResourceEd override async revert(group: GroupIdentifier, options?: IRevertOptions): Promise { await this.textFileService.revert(this.resource, options); } + + protected getViewStateFor(group: GroupIdentifier): IEditorViewState | undefined { + for (const editorPane of this.editorService.visibleEditorPanes) { + if (editorPane.group.id === group && this.matches(editorPane.input)) { + if (isTextEditorPane(editorPane)) { + return editorPane.getViewState(); + } + } + } + + return undefined; + } } /** diff --git a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts index 190dd9fd7a0..547c9050b07 100644 --- a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, isTextEditorPane, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; +import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; @@ -19,7 +19,6 @@ import { AutoSaveMode, IFilesConfigurationService } from 'vs/workbench/services/ import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { isEqual } from 'vs/base/common/resources'; import { Event } from 'vs/base/common/event'; -import { IEditorViewState } from 'vs/editor/common/editorCommon'; import { Schemas } from 'vs/base/common/network'; const enum ForceOpenAs { @@ -211,6 +210,14 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements this.setForceOpenAsText(); } + getMode(): string | undefined { + if (this.model) { + return this.model.getMode(); + } + + return this.preferredMode; + } + getPreferredMode(): string | undefined { return this.preferredMode; } @@ -353,21 +360,14 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements }; } - private getViewStateFor(group: GroupIdentifier): IEditorViewState | undefined { - for (const editorPane of this.editorService.visibleEditorPanes) { - if (editorPane.group.id === group && this.matches(editorPane.input)) { - if (isTextEditorPane(editorPane)) { - return editorPane.getViewState(); - } - } - } - - return undefined; - } - - override asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput | undefined { + override asResourceEditorInput(group: GroupIdentifier): IResourceEditorInput | undefined { return { - resource: this.preferredResource + resource: this.preferredResource, + encoding: this.getEncoding(), + mode: this.getMode(), + options: { + viewState: this.getViewStateFor(group) + } }; } diff --git a/src/vs/workbench/contrib/files/browser/fileImportExport.ts b/src/vs/workbench/contrib/files/browser/fileImportExport.ts index a0a072c5cbc..2563718ab31 100644 --- a/src/vs/workbench/contrib/files/browser/fileImportExport.ts +++ b/src/vs/workbench/contrib/files/browser/fileImportExport.ts @@ -20,7 +20,7 @@ import { ExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel'; import { URI } from 'vs/base/common/uri'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { extractResources } from 'vs/workbench/browser/dnd'; +import { extractResourceDropTransfers } from 'vs/workbench/browser/dnd'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; import { isWeb } from 'vs/base/common/platform'; import { triggerDownload, WebFileSystemAccess } from 'vs/base/browser/dom'; @@ -418,7 +418,7 @@ export class NativeFileImport { private async doImport(target: ExplorerItem, source: DragEvent, token: CancellationToken): Promise { // Check for dropped external files to be folders - const droppedResources = extractResources(source, true); + const droppedResources = extractResourceDropTransfers(source, true); const resolvedFiles = await this.fileService.resolveAll(droppedResources.map(droppedResource => ({ resource: droppedResource.resource }))); if (token.isCancellationRequested) { diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index c2ebd34c508..0c7d0f8bbe8 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -30,7 +30,7 @@ import { equals, deepClone } from 'vs/base/common/objects'; import * as path from 'vs/base/common/path'; import { ExplorerItem, NewExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel'; import { compareFileExtensionsDefault, compareFileNamesDefault, compareFileNamesUpper, compareFileExtensionsUpper, compareFileNamesLower, compareFileExtensionsLower, compareFileNamesUnicode, compareFileExtensionsUnicode } from 'vs/base/common/comparers'; -import { fillResourceDataTransfers, CodeDataTransfers, containsDragType } from 'vs/workbench/browser/dnd'; +import { fillResourceDragTransfers, CodeDataTransfers, containsDragType } from 'vs/workbench/browser/dnd'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IDragAndDropData, DataTransfers } from 'vs/base/browser/dnd'; import { Schemas } from 'vs/base/common/network'; @@ -928,7 +928,7 @@ export class FileDragAndDrop implements ITreeDragAndDrop { const items = FileDragAndDrop.getStatsFromDragAndDropData(data as ElementsDragAndDropData, originalEvent); if (items && items.length && originalEvent.dataTransfer) { // Apply some datatransfer types to allow for dragging the element outside of the application - this.instantiationService.invokeFunction(accessor => fillResourceDataTransfers(accessor, items, originalEvent)); + this.instantiationService.invokeFunction(accessor => fillResourceDragTransfers(accessor, items, originalEvent)); // The only custom data transfer we set from the explorer is a file transfer // to be able to DND between multiple code file explorers across windows diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index d0d6f9a83ac..1c323554543 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -32,7 +32,7 @@ import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/m import { IMenuService, MenuId, IMenu, Action2, registerAction2, MenuRegistry } from 'vs/platform/actions/common/actions'; import { OpenEditorsDirtyEditorContext, OpenEditorsGroupContext, OpenEditorsReadonlyEditorContext, SAVE_ALL_LABEL, SAVE_ALL_COMMAND_ID, NEW_UNTITLED_FILE_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileCommands'; import { ResourceContextKey } from 'vs/workbench/common/resources'; -import { ResourcesDropHandler, fillResourceDataTransfers, CodeDataTransfers, containsDragType } from 'vs/workbench/browser/dnd'; +import { ResourcesDropHandler, fillResourceDragTransfers, CodeDataTransfers, containsDragType } from 'vs/workbench/browser/dnd'; import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet'; import { IDragAndDropData, DataTransfers } from 'vs/base/browser/dnd'; @@ -663,7 +663,7 @@ class OpenEditorsDragAndDrop implements IListDragAndDrop { if (resources.length) { // Apply some datatransfer types to allow for dragging the element outside of the application - this.instantiationService.invokeFunction(accessor => fillResourceDataTransfers(accessor, resources, originalEvent)); + this.instantiationService.invokeFunction(accessor => fillResourceDragTransfers(accessor, resources, originalEvent)); } } diff --git a/src/vs/workbench/contrib/search/browser/searchResultsView.ts b/src/vs/workbench/contrib/search/browser/searchResultsView.ts index a056ae40054..2803b678b4d 100644 --- a/src/vs/workbench/contrib/search/browser/searchResultsView.ts +++ b/src/vs/workbench/contrib/search/browser/searchResultsView.ts @@ -27,7 +27,7 @@ import { RemoveAction, ReplaceAction, ReplaceAllAction, ReplaceAllInFolderAction import { SearchView } from 'vs/workbench/contrib/search/browser/searchView'; import { FileMatch, Match, RenderableMatch, SearchModel, FolderMatch } from 'vs/workbench/contrib/search/common/searchModel'; import { IDragAndDropData } from 'vs/base/browser/dnd'; -import { fillResourceDataTransfers } from 'vs/workbench/browser/dnd'; +import { fillResourceDragTransfers } from 'vs/workbench/browser/dnd'; import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; interface IFolderMatchTemplate { @@ -377,7 +377,7 @@ export class SearchDND implements ITreeDragAndDrop { if (resources.length) { // Apply some datatransfer types to allow for dragging the element outside of the application - this.instantiationService.invokeFunction(accessor => fillResourceDataTransfers(accessor, resources, originalEvent)); + this.instantiationService.invokeFunction(accessor => fillResourceDragTransfers(accessor, resources, originalEvent)); } } diff --git a/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts b/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts index 5fb9b7321b4..3f270151d8f 100644 --- a/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts +++ b/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts @@ -116,9 +116,14 @@ export class UntitledTextEditorInput extends AbstractTextResourceEditorInput imp return this.model; } - override asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput | undefined { + override asResourceEditorInput(group: GroupIdentifier): IResourceEditorInput | undefined { return { - resource: this.model.resource + resource: this.model.resource, + encoding: this.getEncoding(), + mode: this.getMode(), + options: { + viewState: this.getViewStateFor(group) + } }; } From b5fc2b0a398f0de994345297ab09c2bc491db669 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 25 May 2021 11:21:29 +0200 Subject: [PATCH 032/140] NotebookCellOutputItem factories allow for metadata, expose "bytes" as data property, deprecate value-property, fix converter issues, https://github.com/microsoft/vscode/issues/123884 --- src/vs/vscode.proposed.d.ts | 45 +++++++++---------- .../api/common/extHostTypeConverters.ts | 15 +++---- src/vs/workbench/api/common/extHostTypes.ts | 34 ++++++++------ .../browser/api/extHostTypeConverter.test.ts | 22 ++++++++- 4 files changed, 68 insertions(+), 48 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 91d7e3abfe5..a6d4822e57e 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1247,11 +1247,12 @@ declare module 'vscode' { * * *Note* that an UTF-8 encoder is used to create bytes for the string. * - * @param value A string/ + * @param value A string. * @param mime Optional MIME type, defaults to `text/plain`. + * @param metadata Optional metadata. * @returns A new output item object. */ - static text(value: string, mime?: string): NotebookCellOutputItem; + static text(value: string, mime?: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` from @@ -1263,46 +1264,40 @@ declare module 'vscode' { * * @param value A JSON-stringifyable value. * @param mime Optional MIME type, defaults to `application/json` + * @param metadata Optional metadata. * @returns A new output item object. */ - static json(value: any, mime?: string): NotebookCellOutputItem; - - /** - * Factory function to create a `NotebookCellOutputItem` from bytes. - * - * @param value An array of unsigned 8-bit integers. - * @param mime Optional MIME type, defaults to `application/octet-stream`. - * @returns A new output item object. - */ - //todo@API REMOVE, dupe ctor - static bytes(value: Uint8Array, mime?: string): NotebookCellOutputItem; + static json(value: any, mime?: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` that uses * uses the `application/vnd.code.notebook.stdout` mime type. * * @param value A string. + * @param metadata Optional metadata. * @returns A new output item object. */ - static stdout(value: string): NotebookCellOutputItem; + static stdout(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` that uses * uses the `application/vnd.code.notebook.stderr` mime type. * * @param value A string. + * @param metadata Optional metadata. * @returns A new output item object. */ - static stderr(value: string): NotebookCellOutputItem; + static stderr(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` that uses * uses the `application/vnd.code.notebook.error` mime type. * * @param value An error object. + * @param metadata Optional metadata. * @returns A new output item object. */ - static error(value: Error): NotebookCellOutputItem; + static error(value: Error, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * The mime type which determines how the {@link NotebookCellOutputItem.value `value`}-property @@ -1314,24 +1309,26 @@ declare module 'vscode' { mime: string; /** - * The value of this output item. Must always be an array of unsigned 8-bit integers. + * The data of this output item. Must always be an array of unsigned 8-bit integers. */ - //todo@API only Unit8Array - //todo@API RENAME to data - value: Uint8Array | unknown; + data: Uint8Array; + /** + * @deprecated + */ + value: unknown; + + //todo@API metadata?: { [key: string]: any }; - //todo@API RENAME to data - //todo@API swap args /** * Create a new notbook cell output item. * + * @param data The value of the output item. * @param mime The mime type of the output item. - * @param value The value of the output item. * @param metadata Optional metadata for this output item. */ - constructor(mime: string, value: Uint8Array | unknown, metadata?: { [key: string]: any }); + constructor(data: Uint8Array, mime: string, metadata?: { [key: string]: any }); } // @jrieken transient diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 94bfff83773..9cb42ef3d54 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays'; -import { VSBuffer } from 'vs/base/common/buffer'; import * as htmlContent from 'vs/base/common/htmlContent'; import { DisposableStore } from 'vs/base/common/lifecycle'; import * as marked from 'vs/base/common/marked/marked'; @@ -1536,9 +1535,9 @@ export namespace NotebookCellOutputItem { export function from(item: types.NotebookCellOutputItem): notebooks.IOutputItemDto { let value: unknown; let valueBytes: number[] | undefined; - if (item.value instanceof Uint8Array) { + if (item.data instanceof Uint8Array) { //todo@jrieken this HACKY and SLOW... hoist VSBuffer instead - valueBytes = Array.from(item.value); + valueBytes = Array.from(item.data); } else { value = item.value; } @@ -1551,15 +1550,13 @@ export namespace NotebookCellOutputItem { } export function to(item: notebooks.IOutputItemDto): types.NotebookCellOutputItem { - - let value: Uint8Array | unknown; - if (item.value instanceof VSBuffer) { - value = item.value.buffer; + let value: Uint8Array | any; + if (Array.isArray(item.valueBytes)) { + value = new Uint8Array(item.valueBytes); } else { value = item.value; } - - return new types.NotebookCellOutputItem(item.mime, value, item.metadata); + return new types.NotebookCellOutputItem(value, item.mime, item.metadata); } } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 1dfecfab513..fdccb8c119c 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3112,44 +3112,50 @@ export class NotebookCellOutputItem { return typeof (obj).mime === 'string'; } - static error(err: Error | { name: string, message?: string, stack?: string }): NotebookCellOutputItem { + static error(err: Error | { name: string, message?: string, stack?: string }, metadata?: { [key: string]: any }): NotebookCellOutputItem { const obj = { name: err.name, message: err.message, stack: err.stack }; - return NotebookCellOutputItem.json(obj, 'application/vnd.code.notebook.error'); + return NotebookCellOutputItem.json(obj, 'application/vnd.code.notebook.error', metadata); } - static stdout(value: string): NotebookCellOutputItem { - return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stdout'); + static stdout(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem { + return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stdout', metadata); } - static stderr(value: string): NotebookCellOutputItem { - return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stderr'); + static stderr(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem { + return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stderr', metadata); } - static bytes(value: Uint8Array, mime: string = 'application/octet-stream'): NotebookCellOutputItem { - return new NotebookCellOutputItem(mime, value); + static bytes(value: Uint8Array, mime: string = 'application/octet-stream', metadata?: { [key: string]: any }): NotebookCellOutputItem { + return new NotebookCellOutputItem(value, mime, metadata); } static #encoder = new TextEncoder(); - static text(value: string, mime: string = 'text/plain'): NotebookCellOutputItem { + static text(value: string, mime: string = 'text/plain', metadata?: { [key: string]: any }): NotebookCellOutputItem { const bytes = NotebookCellOutputItem.#encoder.encode(String(value)); - return new NotebookCellOutputItem(mime, bytes); + return new NotebookCellOutputItem(bytes, mime, metadata); } - static json(value: any, mime: string = 'application/json'): NotebookCellOutputItem { + static json(value: any, mime: string = 'application/json', metadata?: { [key: string]: any }): NotebookCellOutputItem { const rawStr = JSON.stringify(value, undefined, '\t'); - return NotebookCellOutputItem.text(rawStr, mime); + return NotebookCellOutputItem.text(rawStr, mime, metadata); } + /** @deprecated */ + public value: Uint8Array | unknown; // JSON'able + constructor( + public data: Uint8Array, public mime: string, - public value: Uint8Array | unknown, // JSON'able - public metadata?: Record + public metadata?: { [key: string]: any } ) { + if (!(data instanceof Uint8Array)) { + this.value = data; + } if (isFalsyOrWhitespace(this.mime)) { throw new Error('INVALID mime type, must not be empty or falsy'); } diff --git a/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts b/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts index 0cc72cdd1bc..324cdd3c071 100644 --- a/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts @@ -5,7 +5,8 @@ import * as assert from 'assert'; -import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters'; +import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; +import { MarkdownString, NotebookCellOutputItem } from 'vs/workbench/api/common/extHostTypeConverters'; import { isEmptyObject } from 'vs/base/common/types'; import { forEach } from 'vs/base/common/collections'; import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log'; @@ -81,4 +82,23 @@ suite('ExtHostTypeConverter', function () { } }); }); + + test('NotebookCellOutputItem', function () { + + const item = extHostTypes.NotebookCellOutputItem.text('Hello', 'foo/bar'); + + const dto = NotebookCellOutputItem.from(item); + + assert.strictEqual(dto.mime, 'foo/bar'); + assert.strictEqual(dto.metadata, undefined); + assert.strictEqual(dto.value, undefined); + assert.deepStrictEqual(dto.valueBytes, Array.from(new TextEncoder().encode('Hello'))); + + const item2 = NotebookCellOutputItem.to(dto); + + assert.strictEqual(item2.mime, item.mime); + assert.strictEqual(item2.metadata, item.metadata); + assert.strictEqual(item2.value, item.value); + assert.deepStrictEqual(item2.data, item.data); + }); }); From e11764f84203e0343440159d08b3703e9bca2414 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 25 May 2021 11:32:31 +0200 Subject: [PATCH 033/140] add ICellInfo#data to eventually replace bytes --- .../notebook/browser/view/renderers/webviewPreloads.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index f097895be8b..f9d5bb8c2b3 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -468,8 +468,10 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re text(): string; json(): any; - bytes(): Uint8Array + data(): Uint8Array; blob(): Blob; + /** @deprecated */ + bytes(): Uint8Array; } interface IDestroyCellInfo { @@ -643,9 +645,10 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re mime: content.mimeType, value: content.value, metadata: content.metadata, - bytes() { + data() { return content.valueBytes; }, + bytes() { return this.data(); }, text() { return new TextDecoder().decode(content.valueBytes) || String(content.value); //todo@jrieken remove this once `value` is gone! @@ -1039,6 +1042,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re text() { return content; }, json() { return undefined; }, bytes() { return new Uint8Array(); }, + data() { return new Uint8Array(); }, blob() { return new Blob(); }, }); } From 42e59bd3777a4b9520756a1806c19419a92ce662 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 25 May 2021 11:36:31 +0200 Subject: [PATCH 034/140] more complete cell info for markup renderers --- .../notebook/browser/view/renderers/webviewPreloads.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index f9d5bb8c2b3..5b358b22026 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -1041,9 +1041,9 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re outputId: undefined, text() { return content; }, json() { return undefined; }, - bytes() { return new Uint8Array(); }, - data() { return new Uint8Array(); }, - blob() { return new Blob(); }, + bytes() { return this.data(); }, + data() { return new TextEncoder().encode(content); }, + blob() { return new Blob([this.data()], { type: this.mime }); }, }); } }(); From eebf8e876ab99688b167b98874ca2b3c17822e4f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 11:53:52 +0200 Subject: [PATCH 035/140] editors - extract input and side by side to own classes --- src/vs/workbench/browser/editor.ts | 3 +- src/vs/workbench/browser/layout.ts | 3 +- .../browser/parts/editor/binaryEditor.ts | 3 +- .../parts/editor/editor.contribution.ts | 7 +- .../workbench/browser/parts/editor/editor.ts | 3 +- .../browser/parts/editor/editorActions.ts | 3 +- .../browser/parts/editor/editorControl.ts | 3 +- .../browser/parts/editor/editorGroupView.ts | 4 +- .../browser/parts/editor/editorPane.ts | 3 +- .../browser/parts/editor/editorStatus.ts | 3 +- .../browser/parts/editor/editorsObserver.ts | 3 +- .../browser/parts/editor/sideBySideEditor.ts | 4 +- .../browser/parts/editor/textEditor.ts | 3 +- .../parts/editor/textResourceEditor.ts | 3 +- .../editor/workspaceTrustRequiredEditor.ts | 3 +- src/vs/workbench/common/editor.ts | 304 +----------------- .../common/editor/binaryEditorModel.ts | 2 +- .../common/editor/diffEditorInput.ts | 5 +- .../common/editor/diffEditorModel.ts | 2 +- .../common/editor/editorGroupModel.ts | 4 +- src/vs/workbench/common/editor/editorInput.ts | 137 ++++++++ src/vs/workbench/common/editor/editorModel.ts | 53 +++ .../common/editor/resourceEditorInput.ts | 3 +- .../common/editor/sideBySideEditoInput.ts | 135 ++++++++ .../common/editor/textEditorModel.ts | 2 +- .../customEditor/browser/customEditors.ts | 3 +- .../extensions/common/extensionsInput.ts | 3 +- .../common/runtimeExtensionsInput.ts | 3 +- .../extensions.contribution.ts | 3 +- .../files/browser/editors/binaryFileEditor.ts | 3 +- .../browser/editors/fileEditorHandler.ts | 3 +- .../contrib/files/browser/fileCommands.ts | 3 +- .../files/browser/files.contribution.ts | 4 +- .../files/browser/files.web.contribution.ts | 8 +- .../electron-sandbox/files.contribution.ts | 4 +- .../notebook/browser/notebook.contribution.ts | 3 +- .../browser/notebookDiffEditorInput.ts | 4 +- .../notebook/common/notebookEditorModel.ts | 3 +- .../notebook/test/testNotebookEditor.ts | 3 +- .../browser/preferences.contribution.ts | 3 +- .../preferences/browser/preferencesEditor.ts | 3 +- .../search/browser/anythingQuickAccess.ts | 3 +- .../searchEditor/browser/searchEditorInput.ts | 3 +- .../testing/browser/testingOutputPeek.ts | 2 +- .../webviewPanel/browser/webviewEditor.ts | 3 +- .../browser/webviewEditorInput.ts | 3 +- .../browser/gettingStartedInput.ts | 2 +- .../welcome/page/browser/welcomePage.ts | 3 +- .../browser/editor/editorWalkThrough.ts | 3 +- .../walkThrough/browser/walkThroughInput.ts | 3 +- .../browser/workspace.contribution.ts | 3 +- .../services/editor/browser/editorService.ts | 4 +- .../editor/test/browser/editorService.test.ts | 4 +- .../test/browser/editorsObserver.test.ts | 3 +- .../services/history/browser/history.ts | 3 +- .../browser/keybindingsEditorInput.ts | 2 +- .../browser/keybindingsEditorModel.ts | 2 +- .../preferences/browser/preferencesService.ts | 3 +- .../common/preferencesEditorInput.ts | 4 +- .../preferences/common/preferencesModels.ts | 2 +- .../common/untitledTextEditorHandler.ts | 3 +- .../browser/workspaceTrustEditorInput.ts | 2 +- .../test/browser/parts/editor/editor.test.ts | 3 +- .../parts/editor/editorGroupModel.test.ts | 3 +- .../browser/parts/editor/editorInput.test.ts | 2 +- .../browser/parts/editor/editorModel.test.ts | 2 +- .../browser/parts/editor/editorPane.test.ts | 3 +- .../test/browser/workbenchTestServices.ts | 10 +- 68 files changed, 464 insertions(+), 373 deletions(-) create mode 100644 src/vs/workbench/common/editor/editorInput.ts create mode 100644 src/vs/workbench/common/editor/editorModel.ts create mode 100644 src/vs/workbench/common/editor/sideBySideEditoInput.ts diff --git a/src/vs/workbench/browser/editor.ts b/src/vs/workbench/browser/editor.ts index 7413ec6abdc..8fae366d3e4 100644 --- a/src/vs/workbench/browser/editor.ts +++ b/src/vs/workbench/browser/editor.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { EditorInput, EditorResourceAccessor, IEditorInput, EditorExtensions, SideBySideEditor, IEditorDescriptor as ICommonEditorDescriptor } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, IEditorInput, EditorExtensions, SideBySideEditor, IEditorDescriptor as ICommonEditorDescriptor } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { Registry } from 'vs/platform/registry/common/platform'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 651f3cf61f5..1d967bf722f 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -10,7 +10,8 @@ import { onDidChangeFullscreen, isFullscreen } from 'vs/base/browser/browser'; import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup'; import { Registry } from 'vs/platform/registry/common/platform'; import { isWindows, isLinux, isMacintosh, isWeb, isNative } from 'vs/base/common/platform'; -import { pathsToEditors, SideBySideEditorInput } from 'vs/workbench/common/editor'; +import { pathsToEditors } from 'vs/workbench/common/editor'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart'; import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart'; import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel'; diff --git a/src/vs/workbench/browser/parts/editor/binaryEditor.ts b/src/vs/workbench/browser/parts/editor/binaryEditor.ts index edfc611887e..2a49d62abdb 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditor.ts @@ -6,7 +6,8 @@ import 'vs/css!./media/binaryeditor'; import { localize } from 'vs/nls'; import { Emitter } from 'vs/base/common/event'; -import { EditorInput, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 29a246e2b76..ad1085e7376 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -8,10 +8,11 @@ import { localize } from 'vs/nls'; import { URI } from 'vs/base/common/uri'; import { IEditorRegistry, EditorDescriptor } from 'vs/workbench/browser/editor'; import { - EditorInput, IEditorInputSerializer, SideBySideEditorInput, IEditorInputFactoryRegistry, TextCompareEditorActiveContext, ActiveEditorPinnedContext, - EditorGroupEditorsCountContext, ActiveEditorStickyContext, ActiveEditorAvailableEditorIdsContext, MultipleEditorGroupsContext, ActiveEditorDirtyContext, - EditorExtensions + IEditorInputSerializer, IEditorInputFactoryRegistry, TextCompareEditorActiveContext, ActiveEditorPinnedContext, EditorExtensions, + EditorGroupEditorsCountContext, ActiveEditorStickyContext, ActiveEditorAvailableEditorIdsContext, MultipleEditorGroupsContext, ActiveEditorDirtyContext } from 'vs/workbench/common/editor'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; diff --git a/src/vs/workbench/browser/parts/editor/editor.ts b/src/vs/workbench/browser/parts/editor/editor.ts index 6984779b870..959615f8a06 100644 --- a/src/vs/workbench/browser/parts/editor/editor.ts +++ b/src/vs/workbench/browser/parts/editor/editor.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { GroupIdentifier, IWorkbenchEditorConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditorPartOptions, IEditorPartOptionsChangeEvent, EditorInput } from 'vs/workbench/common/editor'; +import { GroupIdentifier, IWorkbenchEditorConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditorPartOptions, IEditorPartOptionsChangeEvent } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { IEditorGroup, GroupDirection, IAddGroupOptions, IMergeGroupOptions, GroupsOrder, GroupsArrangement } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IDisposable } from 'vs/base/common/lifecycle'; import { Dimension } from 'vs/base/browser/dom'; diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 8e5196cb0b3..25f0817a50d 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -5,7 +5,8 @@ import { localize } from 'vs/nls'; import { Action } from 'vs/base/common/actions'; -import { IEditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason, EditorsOrder, SideBySideEditorInput, EditorInputCapabilities, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason, EditorsOrder, EditorInputCapabilities, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; diff --git a/src/vs/workbench/browser/parts/editor/editorControl.ts b/src/vs/workbench/browser/parts/editor/editorControl.ts index a61c2875178..2d2bc02c9a6 100644 --- a/src/vs/workbench/browser/parts/editor/editorControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorControl.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { EditorExtensions, EditorInput, EditorInputCapabilities, EditorOptions, IEditorOpenContext, IVisibleEditorPane } from 'vs/workbench/common/editor'; +import { EditorExtensions, EditorInputCapabilities, EditorOptions, IEditorOpenContext, IVisibleEditorPane } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { Dimension, show, hide } from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; import { IEditorRegistry, IEditorDescriptor } from 'vs/workbench/browser/editor'; diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 169b052dae4..95554e9e644 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -5,7 +5,9 @@ import 'vs/css!./media/editorgroupview'; import { EditorGroupModel, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroupModel, isSerializedEditorGroupModel } from 'vs/workbench/common/editor/editorGroupModel'; -import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, EditorResourceAccessor, IEditorMoveEvent, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; +import { EditorOptions, GroupIdentifier, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, EditorResourceAccessor, IEditorMoveEvent, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; import { Event, Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor, asCSSUrl } from 'vs/base/browser/dom'; diff --git a/src/vs/workbench/browser/parts/editor/editorPane.ts b/src/vs/workbench/browser/parts/editor/editorPane.ts index 5af2b24f169..8928712c164 100644 --- a/src/vs/workbench/browser/parts/editor/editorPane.ts +++ b/src/vs/workbench/browser/parts/editor/editorPane.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { Composite } from 'vs/workbench/browser/composite'; -import { EditorInput, EditorOptions, IEditorPane, GroupIdentifier, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorPane, GroupIdentifier, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { CancellationToken } from 'vs/base/common/cancellation'; diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 6552926b63d..7f33306af4e 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri'; import { Action, WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions'; import { Language } from 'vs/base/common/platform'; import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput'; -import { IFileEditorInput, EditorResourceAccessor, SideBySideEditorInput, IEditorPane, IEditorInput, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { IFileEditorInput, EditorResourceAccessor, IEditorPane, IEditorInput, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { Disposable, MutableDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IEditorAction } from 'vs/editor/common/editorCommon'; import { EndOfLineSequence } from 'vs/editor/common/model'; @@ -53,6 +53,7 @@ import { IMarker, IMarkerService, MarkerSeverity, IMarkerData } from 'vs/platfor import { STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND } from 'vs/workbench/common/theme'; import { themeColorFromId } from 'vs/platform/theme/common/themeService'; import { ITelemetryData, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; class SideBySideEditorEncodingSupport implements IEncodingSupport { constructor(private primary: IEncodingSupport, private secondary: IEncodingSupport) { } diff --git a/src/vs/workbench/browser/parts/editor/editorsObserver.ts b/src/vs/workbench/browser/parts/editor/editorsObserver.ts index 1abe2fd4004..95b03402738 100644 --- a/src/vs/workbench/browser/parts/editor/editorsObserver.ts +++ b/src/vs/workbench/browser/parts/editor/editorsObserver.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IEditorInput, IEditorInputFactoryRegistry, IEditorIdentifier, GroupIdentifier, EditorExtensions, IEditorPartOptionsChangeEvent, EditorsOrder, SideBySideEditorInput } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorInputFactoryRegistry, IEditorIdentifier, GroupIdentifier, EditorExtensions, IEditorPartOptionsChangeEvent, EditorsOrder } from 'vs/workbench/common/editor'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; diff --git a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts index d27103d4dbf..0cf8386bbe0 100644 --- a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts +++ b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts @@ -5,7 +5,9 @@ import { Dimension, $, clearNode } from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; -import { EditorInput, EditorOptions, SideBySideEditorInput, IEditorControl, IEditorPane, IEditorOpenContext, EditorExtensions } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorControl, IEditorPane, IEditorOpenContext, EditorExtensions } from 'vs/workbench/common/editor'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index efd4885ae85..c36c799c8c9 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -10,7 +10,8 @@ import { Event } from 'vs/base/common/event'; import { isObject, assertIsDefined, withNullAsUndefined, isFunction } from 'vs/base/common/types'; import { Dimension } from 'vs/base/browser/dom'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; -import { EditorInput, EditorOptions, IEditorMemento, ITextEditorPane, TextEditorOptions, IEditorCloseEvent, IEditorInput, IEditorOpenContext, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorMemento, ITextEditorPane, TextEditorOptions, IEditorCloseEvent, IEditorInput, IEditorOpenContext, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { computeEditorAriaLabel } from 'vs/workbench/browser/editor'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { IEditorViewState, IEditor, ScrollType } from 'vs/editor/common/editorCommon'; diff --git a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts index 009b646894a..f0861ae8b51 100644 --- a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts @@ -6,7 +6,8 @@ import { localize } from 'vs/nls'; import { assertIsDefined, isFunction, withNullAsUndefined } from 'vs/base/common/types'; import { ICodeEditor, getCodeEditor, IPasteEvent } from 'vs/editor/browser/editorBrowser'; -import { TextEditorOptions, EditorInput, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { TextEditorOptions, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { AbstractTextResourceEditorInput, TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput'; diff --git a/src/vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor.ts b/src/vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor.ts index 2583fcf803f..9019d27eb43 100644 --- a/src/vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor.ts +++ b/src/vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor.ts @@ -5,7 +5,8 @@ import 'vs/css!./media/workspacetrusteditor'; import { localize } from 'vs/nls'; -import { EditorInput, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 2b3bd51ae6a..ecb9d90d7c5 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { Event, Emitter } from 'vs/base/common/event'; +import { Event } from 'vs/base/common/event'; import { withNullAsUndefined, assertIsDefined, isUndefinedOrNull } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; -import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IEditor, IEditorViewState, ScrollType, IDiffEditor } from 'vs/editor/common/editorCommon'; import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceEditorInput, IResourceEditorInput, EditorActivation, EditorOpenContext, ITextEditorSelection, TextEditorSelectionRevealType, EditorOverride } from 'vs/platform/editor/common/editor'; import { IInstantiationService, IConstructorSignature0, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation'; @@ -19,10 +19,12 @@ import { ICompositeControl, IComposite } from 'vs/workbench/common/composite'; import { ActionRunner, IAction } from 'vs/base/common/actions'; import { IFileService } from 'vs/platform/files/common/files'; import { IPathData } from 'vs/platform/windows/common/windows'; -import { coalesce, firstOrDefault } from 'vs/base/common/arrays'; +import { coalesce } from 'vs/base/common/arrays'; import { ACTIVE_GROUP, IResourceEditorInputType, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IRange } from 'vs/editor/common/core/range'; import { IExtUri } from 'vs/base/common/resources'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; // Static values for editor contributions export const EditorExtensions = { @@ -571,132 +573,6 @@ export interface IEditorInput extends IDisposable { isDisposed(): boolean; } -/** - * Editor inputs are lightweight objects that can be passed to the workbench API to open inside the editor part. - * Each editor input is mapped to an editor that is capable of opening it through the Platform facade. - */ -export abstract class EditorInput extends Disposable implements IEditorInput { - - protected readonly _onDidChangeDirty = this._register(new Emitter()); - readonly onDidChangeDirty = this._onDidChangeDirty.event; - - protected readonly _onDidChangeLabel = this._register(new Emitter()); - readonly onDidChangeLabel = this._onDidChangeLabel.event; - - private readonly _onWillDispose = this._register(new Emitter()); - readonly onWillDispose = this._onWillDispose.event; - - private disposed: boolean = false; - - abstract get typeId(): string; - - abstract get resource(): URI | undefined; - - get capabilities(): EditorInputCapabilities { - return EditorInputCapabilities.Readonly; - } - - hasCapability(capability: EditorInputCapabilities): boolean { - if (capability === EditorInputCapabilities.None) { - return this.capabilities === EditorInputCapabilities.None; - } - - return (this.capabilities & capability) !== 0; - } - - getName(): string { - return `Editor ${this.typeId}`; - } - - getDescription(verbosity?: Verbosity): string | undefined { - return undefined; - } - - getTitle(verbosity?: Verbosity): string { - return this.getName(); - } - - getAriaLabel(): string { - return this.getTitle(Verbosity.SHORT); - } - - /** - * Returns a descriptor suitable for telemetry events. - * - * Subclasses should extend if they can contribute. - */ - getTelemetryDescriptor(): { [key: string]: unknown } { - /* __GDPR__FRAGMENT__ - "EditorTelemetryDescriptor" : { - "typeId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } - } - */ - return { typeId: this.typeId }; - } - - isDirty(): boolean { - return false; - } - - isSaving(): boolean { - return false; - } - - async resolve(): Promise { - return null; - } - - async save(group: GroupIdentifier, options?: ISaveOptions): Promise { - return this; - } - - async saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { - return this; - } - - async revert(group: GroupIdentifier, options?: IRevertOptions): Promise { } - - rename(group: GroupIdentifier, target: URI): IMoveResult | undefined { - return undefined; - } - - copy(): IEditorInput { - return this; - } - - matches(otherInput: unknown): boolean { - return this === otherInput; - } - - /** - * If a input was registered onto multiple editors, this method - * will be asked to return the preferred one to use. - * - * @param editors a list of editor descriptors that are candidates - * for the editor input to open in. - */ - prefersEditor>(editors: T[]): T | undefined { - return firstOrDefault(editors); - } - - asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput | undefined { - return undefined; - } - - isDisposed(): boolean { - return this.disposed; - } - - override dispose(): void { - if (!this.disposed) { - this.disposed = true; - this._onWillDispose.fire(); - } - - super.dispose(); - } -} - export interface IEditorInputWithPreferredResource { /** @@ -783,176 +659,6 @@ export interface IFileEditorInput extends IEditorInput, IEncodingSupport, IModeS isResolved(): boolean; } -/** - * Side by side editor inputs that have a primary and secondary side. - */ -export class SideBySideEditorInput extends EditorInput { - - static readonly ID: string = 'workbench.editorinputs.sidebysideEditorInput'; - - override get typeId(): string { - return SideBySideEditorInput.ID; - } - - override get capabilities(): EditorInputCapabilities { - - // Use primary capabilities as main capabilities - let capabilities = this._primary.capabilities; - - // Trust: should be considered for both sides - if (this._secondary.hasCapability(EditorInputCapabilities.RequiresTrust)) { - capabilities |= EditorInputCapabilities.RequiresTrust; - } - - // Singleton: should be considered for both sides - if (this._secondary.hasCapability(EditorInputCapabilities.Singleton)) { - capabilities |= EditorInputCapabilities.Singleton; - } - - return capabilities; - } - - get resource(): URI | undefined { - return undefined; // use `EditorResourceAccessor` to obtain one side's resource - } - - get primary(): EditorInput { - return this._primary; - } - - get secondary(): EditorInput { - return this._secondary; - } - - constructor( - protected readonly name: string | undefined, - protected readonly description: string | undefined, - private readonly _secondary: EditorInput, - private readonly _primary: EditorInput - ) { - super(); - - this.registerListeners(); - } - - private registerListeners(): void { - - // When the primary or secondary input gets disposed, dispose this diff editor input - const onceSecondaryDisposed = Event.once(this.secondary.onWillDispose); - this._register(onceSecondaryDisposed(() => { - if (!this.isDisposed()) { - this.dispose(); - } - })); - - const oncePrimaryDisposed = Event.once(this.primary.onWillDispose); - this._register(oncePrimaryDisposed(() => { - if (!this.isDisposed()) { - this.dispose(); - } - })); - - // Reemit some events from the primary side to the outside - this._register(this.primary.onDidChangeDirty(() => this._onDidChangeDirty.fire())); - this._register(this.primary.onDidChangeLabel(() => this._onDidChangeLabel.fire())); - } - - override getName(): string { - if (!this.name) { - return localize('sideBySideLabels', "{0} - {1}", this._secondary.getName(), this._primary.getName()); - } - - return this.name; - } - - override getDescription(): string | undefined { - return this.description; - } - - override getTelemetryDescriptor(): { [key: string]: unknown } { - const descriptor = this.primary.getTelemetryDescriptor(); - - return Object.assign(descriptor, super.getTelemetryDescriptor()); - } - - override isDirty(): boolean { - return this.primary.isDirty(); - } - - override isSaving(): boolean { - return this.primary.isSaving(); - } - - override save(group: GroupIdentifier, options?: ISaveOptions): Promise { - return this.primary.save(group, options); - } - - override saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { - return this.primary.saveAs(group, options); - } - - override revert(group: GroupIdentifier, options?: IRevertOptions): Promise { - return this.primary.revert(group, options); - } - - override matches(otherInput: unknown): boolean { - if (otherInput === this) { - return true; - } - - if (otherInput instanceof SideBySideEditorInput) { - return this.primary.matches(otherInput.primary) && this.secondary.matches(otherInput.secondary); - } - - return false; - } -} - -/** - * The editor model is the heavyweight counterpart of editor input. Depending on the editor input, it - * resolves from a file system retrieve content and may allow for saving it back or reverting it. - * Editor models are typically cached for some while because they are expensive to construct. - */ -export class EditorModel extends Disposable implements IEditorModel { - - private readonly _onWillDispose = this._register(new Emitter()); - readonly onWillDispose = this._onWillDispose.event; - - private disposed = false; - private resolved = false; - - /** - * Causes this model to resolve returning a promise when loading is completed. - */ - async resolve(): Promise { - this.resolved = true; - } - - /** - * Returns whether this model was loaded or not. - */ - isResolved(): boolean { - return this.resolved; - } - - /** - * Find out if this model has been disposed. - */ - isDisposed(): boolean { - return this.disposed; - } - - /** - * Subclasses should implement to free resources that have been claimed through loading. - */ - override dispose(): void { - this.disposed = true; - this._onWillDispose.fire(); - - super.dispose(); - } -} - export interface IEditorInputWithOptions { editor: IEditorInput; options?: IEditorOptions | ITextEditorOptions; diff --git a/src/vs/workbench/common/editor/binaryEditorModel.ts b/src/vs/workbench/common/editor/binaryEditorModel.ts index b591076f47c..7e4e6a7ae46 100644 --- a/src/vs/workbench/common/editor/binaryEditorModel.ts +++ b/src/vs/workbench/common/editor/binaryEditorModel.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EditorModel } from 'vs/workbench/common/editor'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { URI } from 'vs/base/common/uri'; import { IFileService } from 'vs/platform/files/common/files'; import { MIME_BINARY } from 'vs/base/common/mime'; diff --git a/src/vs/workbench/common/editor/diffEditorInput.ts b/src/vs/workbench/common/editor/diffEditorInput.ts index fee2f01b4bc..67edf472669 100644 --- a/src/vs/workbench/common/editor/diffEditorInput.ts +++ b/src/vs/workbench/common/editor/diffEditorInput.ts @@ -3,7 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EditorModel, EditorInput, SideBySideEditorInput, TEXT_DIFF_EDITOR_ID, BINARY_DIFF_EDITOR_ID, Verbosity, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; +import { TEXT_DIFF_EDITOR_ID, BINARY_DIFF_EDITOR_ID, Verbosity, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { DiffEditorModel } from 'vs/workbench/common/editor/diffEditorModel'; import { TextDiffEditorModel } from 'vs/workbench/common/editor/textDiffEditorModel'; diff --git a/src/vs/workbench/common/editor/diffEditorModel.ts b/src/vs/workbench/common/editor/diffEditorModel.ts index 9de37bf7e02..cddd3bbb0fb 100644 --- a/src/vs/workbench/common/editor/diffEditorModel.ts +++ b/src/vs/workbench/common/editor/diffEditorModel.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EditorModel } from 'vs/workbench/common/editor'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { IEditorModel } from 'vs/platform/editor/common/editor'; /** diff --git a/src/vs/workbench/common/editor/editorGroupModel.ts b/src/vs/workbench/common/editor/editorGroupModel.ts index 85076d88d21..20ab00e585f 100644 --- a/src/vs/workbench/common/editor/editorGroupModel.ts +++ b/src/vs/workbench/common/editor/editorGroupModel.ts @@ -4,7 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { Event, Emitter } from 'vs/base/common/event'; -import { IEditorInputFactoryRegistry, EditorInput, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, SideBySideEditorInput, IEditorInput, EditorsOrder, EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorInputFactoryRegistry, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, IEditorInput, EditorsOrder, EditorExtensions } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; diff --git a/src/vs/workbench/common/editor/editorInput.ts b/src/vs/workbench/common/editor/editorInput.ts new file mode 100644 index 00000000000..3827f049afd --- /dev/null +++ b/src/vs/workbench/common/editor/editorInput.ts @@ -0,0 +1,137 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter } from 'vs/base/common/event'; +import { URI } from 'vs/base/common/uri'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IEditorModel, IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { firstOrDefault } from 'vs/base/common/arrays'; +import { IEditorInput, EditorInputCapabilities, Verbosity, GroupIdentifier, ISaveOptions, IRevertOptions, IMoveResult, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; + +/** + * Editor inputs are lightweight objects that can be passed to the workbench API to open inside the editor part. + * Each editor input is mapped to an editor that is capable of opening it through the Platform facade. + */ +export abstract class EditorInput extends Disposable implements IEditorInput { + + protected readonly _onDidChangeDirty = this._register(new Emitter()); + readonly onDidChangeDirty = this._onDidChangeDirty.event; + + protected readonly _onDidChangeLabel = this._register(new Emitter()); + readonly onDidChangeLabel = this._onDidChangeLabel.event; + + private readonly _onWillDispose = this._register(new Emitter()); + readonly onWillDispose = this._onWillDispose.event; + + private disposed: boolean = false; + + abstract get typeId(): string; + + abstract get resource(): URI | undefined; + + get capabilities(): EditorInputCapabilities { + return EditorInputCapabilities.Readonly; + } + + hasCapability(capability: EditorInputCapabilities): boolean { + if (capability === EditorInputCapabilities.None) { + return this.capabilities === EditorInputCapabilities.None; + } + + return (this.capabilities & capability) !== 0; + } + + getName(): string { + return `Editor ${this.typeId}`; + } + + getDescription(verbosity?: Verbosity): string | undefined { + return undefined; + } + + getTitle(verbosity?: Verbosity): string { + return this.getName(); + } + + getAriaLabel(): string { + return this.getTitle(Verbosity.SHORT); + } + + /** + * Returns a descriptor suitable for telemetry events. + * + * Subclasses should extend if they can contribute. + */ + getTelemetryDescriptor(): { [key: string]: unknown } { + /* __GDPR__FRAGMENT__ + "EditorTelemetryDescriptor" : { + "typeId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } + } + */ + return { typeId: this.typeId }; + } + + isDirty(): boolean { + return false; + } + + isSaving(): boolean { + return false; + } + + async resolve(): Promise { + return null; + } + + async save(group: GroupIdentifier, options?: ISaveOptions): Promise { + return this; + } + + async saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { + return this; + } + + async revert(group: GroupIdentifier, options?: IRevertOptions): Promise { } + + rename(group: GroupIdentifier, target: URI): IMoveResult | undefined { + return undefined; + } + + copy(): IEditorInput { + return this; + } + + matches(otherInput: unknown): boolean { + return this === otherInput; + } + + /** + * If a input was registered onto multiple editors, this method + * will be asked to return the preferred one to use. + * + * @param editors a list of editor descriptors that are candidates + * for the editor input to open in. + */ + prefersEditor>(editors: T[]): T | undefined { + return firstOrDefault(editors); + } + + asResourceEditorInput(groupId: GroupIdentifier): IResourceEditorInput | undefined { + return undefined; + } + + isDisposed(): boolean { + return this.disposed; + } + + override dispose(): void { + if (!this.disposed) { + this.disposed = true; + this._onWillDispose.fire(); + } + + super.dispose(); + } +} diff --git a/src/vs/workbench/common/editor/editorModel.ts b/src/vs/workbench/common/editor/editorModel.ts new file mode 100644 index 00000000000..ae5ba0d1cc3 --- /dev/null +++ b/src/vs/workbench/common/editor/editorModel.ts @@ -0,0 +1,53 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Emitter } from 'vs/base/common/event'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { IEditorModel } from 'vs/platform/editor/common/editor'; + +/** + * The editor model is the heavyweight counterpart of editor input. Depending on the editor input, it + * resolves from a file system retrieve content and may allow for saving it back or reverting it. + * Editor models are typically cached for some while because they are expensive to construct. + */ +export class EditorModel extends Disposable implements IEditorModel { + + private readonly _onWillDispose = this._register(new Emitter()); + readonly onWillDispose = this._onWillDispose.event; + + private disposed = false; + private resolved = false; + + /** + * Causes this model to resolve returning a promise when loading is completed. + */ + async resolve(): Promise { + this.resolved = true; + } + + /** + * Returns whether this model was loaded or not. + */ + isResolved(): boolean { + return this.resolved; + } + + /** + * Find out if this model has been disposed. + */ + isDisposed(): boolean { + return this.disposed; + } + + /** + * Subclasses should implement to free resources that have been claimed through loading. + */ + override dispose(): void { + this.disposed = true; + this._onWillDispose.fire(); + + super.dispose(); + } +} diff --git a/src/vs/workbench/common/editor/resourceEditorInput.ts b/src/vs/workbench/common/editor/resourceEditorInput.ts index c03a97de99c..66e0948e66e 100644 --- a/src/vs/workbench/common/editor/resourceEditorInput.ts +++ b/src/vs/workbench/common/editor/resourceEditorInput.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { EditorInput, Verbosity, IEditorInputWithPreferredResource, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { Verbosity, IEditorInputWithPreferredResource, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { URI } from 'vs/base/common/uri'; import { IFileService, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; import { ILabelService } from 'vs/platform/label/common/label'; diff --git a/src/vs/workbench/common/editor/sideBySideEditoInput.ts b/src/vs/workbench/common/editor/sideBySideEditoInput.ts new file mode 100644 index 00000000000..a06f6aa7c76 --- /dev/null +++ b/src/vs/workbench/common/editor/sideBySideEditoInput.ts @@ -0,0 +1,135 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; +import { URI } from 'vs/base/common/uri'; +import { localize } from 'vs/nls'; +import { IEditorInput, EditorInputCapabilities, GroupIdentifier, ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; + +/** + * Side by side editor inputs that have a primary and secondary side. + */ +export class SideBySideEditorInput extends EditorInput { + + static readonly ID: string = 'workbench.editorinputs.sidebysideEditorInput'; + + override get typeId(): string { + return SideBySideEditorInput.ID; + } + + override get capabilities(): EditorInputCapabilities { + + // Use primary capabilities as main capabilities + let capabilities = this._primary.capabilities; + + // Trust: should be considered for both sides + if (this._secondary.hasCapability(EditorInputCapabilities.RequiresTrust)) { + capabilities |= EditorInputCapabilities.RequiresTrust; + } + + // Singleton: should be considered for both sides + if (this._secondary.hasCapability(EditorInputCapabilities.Singleton)) { + capabilities |= EditorInputCapabilities.Singleton; + } + + return capabilities; + } + + get resource(): URI | undefined { + return undefined; // use `EditorResourceAccessor` to obtain one side's resource + } + + get primary(): EditorInput { + return this._primary; + } + + get secondary(): EditorInput { + return this._secondary; + } + + constructor( + protected readonly name: string | undefined, + protected readonly description: string | undefined, + private readonly _secondary: EditorInput, + private readonly _primary: EditorInput + ) { + super(); + + this.registerListeners(); + } + + private registerListeners(): void { + + // When the primary or secondary input gets disposed, dispose this diff editor input + const onceSecondaryDisposed = Event.once(this.secondary.onWillDispose); + this._register(onceSecondaryDisposed(() => { + if (!this.isDisposed()) { + this.dispose(); + } + })); + + const oncePrimaryDisposed = Event.once(this.primary.onWillDispose); + this._register(oncePrimaryDisposed(() => { + if (!this.isDisposed()) { + this.dispose(); + } + })); + + // Reemit some events from the primary side to the outside + this._register(this.primary.onDidChangeDirty(() => this._onDidChangeDirty.fire())); + this._register(this.primary.onDidChangeLabel(() => this._onDidChangeLabel.fire())); + } + + override getName(): string { + if (!this.name) { + return localize('sideBySideLabels', "{0} - {1}", this._secondary.getName(), this._primary.getName()); + } + + return this.name; + } + + override getDescription(): string | undefined { + return this.description; + } + + override getTelemetryDescriptor(): { [key: string]: unknown } { + const descriptor = this.primary.getTelemetryDescriptor(); + + return Object.assign(descriptor, super.getTelemetryDescriptor()); + } + + override isDirty(): boolean { + return this.primary.isDirty(); + } + + override isSaving(): boolean { + return this.primary.isSaving(); + } + + override save(group: GroupIdentifier, options?: ISaveOptions): Promise { + return this.primary.save(group, options); + } + + override saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { + return this.primary.saveAs(group, options); + } + + override revert(group: GroupIdentifier, options?: IRevertOptions): Promise { + return this.primary.revert(group, options); + } + + override matches(otherInput: unknown): boolean { + if (otherInput === this) { + return true; + } + + if (otherInput instanceof SideBySideEditorInput) { + return this.primary.matches(otherInput.primary) && this.secondary.matches(otherInput.secondary); + } + + return false; + } +} diff --git a/src/vs/workbench/common/editor/textEditorModel.ts b/src/vs/workbench/common/editor/textEditorModel.ts index e7bd48733ce..bff2d6e78f5 100644 --- a/src/vs/workbench/common/editor/textEditorModel.ts +++ b/src/vs/workbench/common/editor/textEditorModel.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { ITextModel, ITextBufferFactory, ITextSnapshot, ModelConstants } from 'vs/editor/common/model'; -import { EditorModel } from 'vs/workbench/common/editor'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { IModeSupport } from 'vs/workbench/services/textfile/common/textfiles'; import { URI } from 'vs/base/common/uri'; import { ITextEditorModel, IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 56b0f3e55a2..ff0a67cfdea 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -16,8 +16,9 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IStorageService } from 'vs/platform/storage/common/storage'; import * as colorRegistry from 'vs/platform/theme/common/colorRegistry'; import { registerThemingParticipant } from 'vs/platform/theme/common/themeService'; -import { EditorInput, EditorExtensions, GroupIdentifier, IEditorInput, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; +import { EditorExtensions, GroupIdentifier, IEditorInput, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { CONTEXT_ACTIVE_CUSTOM_EDITOR_ID, CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CustomEditorCapabilities, CustomEditorInfo, CustomEditorInfoCollection, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { CustomEditorModelManager } from 'vs/workbench/contrib/customEditor/common/customEditorModelManager'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; diff --git a/src/vs/workbench/contrib/extensions/common/extensionsInput.ts b/src/vs/workbench/contrib/extensions/common/extensionsInput.ts index 9e8b657eb66..2c142d26a6b 100644 --- a/src/vs/workbench/contrib/extensions/common/extensionsInput.ts +++ b/src/vs/workbench/contrib/extensions/common/extensionsInput.ts @@ -6,7 +6,8 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; -import { EditorInput, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { IExtension } from 'vs/workbench/contrib/extensions/common/extensions'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { join } from 'vs/base/common/path'; diff --git a/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts b/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts index 1f8c9cfe959..c153c41d107 100644 --- a/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts +++ b/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.ts @@ -5,7 +5,8 @@ import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; -import { EditorInput, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; export class RuntimeExtensionsInput extends EditorInput { diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/extensions.contribution.ts index 6b0ba3cad76..56013118867 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/extensions.contribution.ts @@ -14,7 +14,8 @@ import { EditorDescriptor, IEditorRegistry } from 'vs/workbench/browser/editor'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { RuntimeExtensionsEditor, StartExtensionHostProfileAction, StopExtensionHostProfileAction, CONTEXT_PROFILE_SESSION_STATE, CONTEXT_EXTENSION_HOST_PROFILE_RECORDED, SaveExtensionHostProfileAction } from 'vs/workbench/contrib/extensions/electron-sandbox/runtimeExtensionsEditor'; import { DebugExtensionHostAction } from 'vs/workbench/contrib/extensions/electron-sandbox/debugExtensionHostAction'; -import { EditorInput, IEditorInputSerializer, IEditorInputFactoryRegistry, ActiveEditorContext, EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorInputSerializer, IEditorInputFactoryRegistry, ActiveEditorContext, EditorExtensions } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { OpenExtensionsFolderAction } from 'vs/workbench/contrib/extensions/electron-sandbox/extensionsActions'; diff --git a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts index 44b36d01db2..fb97428e1f6 100644 --- a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts @@ -7,7 +7,8 @@ import { localize } from 'vs/nls'; import { BaseBinaryResourceEditor } from 'vs/workbench/browser/parts/editor/binaryEditor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { EditorInput, EditorOptions } from 'vs/workbench/common/editor'; +import { EditorOptions } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; import { BINARY_FILE_EDITOR_ID } from 'vs/workbench/contrib/files/common/files'; import { IStorageService } from 'vs/platform/storage/common/storage'; diff --git a/src/vs/workbench/contrib/files/browser/editors/fileEditorHandler.ts b/src/vs/workbench/contrib/files/browser/editors/fileEditorHandler.ts index b3c1deaec71..7d1270d53b9 100644 --- a/src/vs/workbench/contrib/files/browser/editors/fileEditorHandler.ts +++ b/src/vs/workbench/contrib/files/browser/editors/fileEditorHandler.ts @@ -5,7 +5,8 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { URI, UriComponents } from 'vs/base/common/uri'; -import { EditorInput, IEditorInputSerializer } from 'vs/workbench/common/editor'; +import { IEditorInputSerializer } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { isEqual } from 'vs/base/common/resources'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index ba086ef5c2a..48743323723 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -5,7 +5,8 @@ import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; -import { EditorResourceAccessor, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, SideBySideEditorInput, EditorsOrder, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, EditorsOrder, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/workbench/contrib/files/browser/files.contribution.ts b/src/vs/workbench/contrib/files/browser/files.contribution.ts index f2e19055f8f..a04b25b9ae5 100644 --- a/src/vs/workbench/contrib/files/browser/files.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.contribution.ts @@ -8,7 +8,7 @@ import { sep } from 'vs/base/common/path'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { EditorInput, IFileEditorInput, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; +import { IFileEditorInput, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; import { AutoSaveConfiguration, HotExitConfiguration, FILES_EXCLUDE_CONFIG, FILES_ASSOCIATIONS_CONFIG } from 'vs/platform/files/common/files'; import { SortOrder, LexicographicOptions, FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files'; import { TextFileEditorTracker } from 'vs/workbench/contrib/files/browser/editors/textFileEditorTracker'; @@ -61,7 +61,7 @@ Registry.as(EditorExtensions.Editors).registerEditor( nls.localize('binaryFileEditor', "Binary File Editor") ), [ - new SyncDescriptor(FileEditorInput) + new SyncDescriptor(FileEditorInput) ] ); diff --git a/src/vs/workbench/contrib/files/browser/files.web.contribution.ts b/src/vs/workbench/contrib/files/browser/files.web.contribution.ts index c4fb73b4475..b91ef6e6e06 100644 --- a/src/vs/workbench/contrib/files/browser/files.web.contribution.ts +++ b/src/vs/workbench/contrib/files/browser/files.web.contribution.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; +import { localize } from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; -import { EditorExtensions, EditorInput } from 'vs/workbench/common/editor'; +import { EditorExtensions } from 'vs/workbench/common/editor'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IEditorRegistry, EditorDescriptor } from 'vs/workbench/browser/editor'; @@ -16,9 +16,9 @@ Registry.as(EditorExtensions.Editors).registerEditor( EditorDescriptor.create( TextFileEditor, TextFileEditor.ID, - nls.localize('textFileEditor', "Text File Editor") + localize('textFileEditor', "Text File Editor") ), [ - new SyncDescriptor(FileEditorInput) + new SyncDescriptor(FileEditorInput) ] ); diff --git a/src/vs/workbench/contrib/files/electron-sandbox/files.contribution.ts b/src/vs/workbench/contrib/files/electron-sandbox/files.contribution.ts index 16dedbc28bf..71724d78250 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/files.contribution.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/files.contribution.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; -import { EditorExtensions, EditorInput } from 'vs/workbench/common/editor'; +import { EditorExtensions } from 'vs/workbench/common/editor'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IEditorRegistry, EditorDescriptor } from 'vs/workbench/browser/editor'; @@ -19,6 +19,6 @@ Registry.as(EditorExtensions.Editors).registerEditor( nls.localize('textFileEditor', "Text File Editor") ), [ - new SyncDescriptor(FileEditorInput) + new SyncDescriptor(FileEditorInput) ] ); diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index d6ddcffac33..18c20f8a83b 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -24,7 +24,8 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle import { Registry } from 'vs/platform/registry/common/platform'; import { EditorDescriptor, IEditorRegistry } from 'vs/workbench/browser/editor'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; -import { EditorInput, IEditorInput, IEditorInputSerializer, IEditorInputFactoryRegistry, IEditorInputWithOptions, EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorInputSerializer, IEditorInputFactoryRegistry, IEditorInputWithOptions, EditorExtensions } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor'; import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookDiffEditorInput.ts b/src/vs/workbench/contrib/notebook/browser/notebookDiffEditorInput.ts index b7ef97df99d..08136de8607 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookDiffEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookDiffEditorInput.ts @@ -4,7 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import * as glob from 'vs/base/common/glob'; -import { EditorInput, IEditorInput, GroupIdentifier, ISaveOptions, IMoveResult, IRevertOptions, EditorModel, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { IEditorInput, GroupIdentifier, ISaveOptions, IMoveResult, IRevertOptions, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { URI } from 'vs/base/common/uri'; import { isEqual } from 'vs/base/common/resources'; diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index 7c0f047114c..17238c876a8 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import { EditorModel, IEditorInput, IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor'; +import { IEditorInput, IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { Emitter, Event } from 'vs/base/common/event'; import { ICellDto2, INotebookEditorModel, INotebookLoadOptions, IResolvedNotebookEditorModel, NotebookCellsChangeType, NotebookDataDto, NotebookDocumentBackupData } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 7f474ee7440..4ddb7ad7ba4 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -14,7 +14,8 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { IListService, ListService } from 'vs/platform/list/browser/listService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; -import { EditorModel, IEditorInput } from 'vs/workbench/common/editor'; +import { IEditorInput } from 'vs/workbench/common/editor'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { ICellViewModel, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; diff --git a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts index c0109b78a12..fa2a6e88116 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts @@ -26,7 +26,7 @@ import { RemoteNameContext, WorkbenchStateContext } from 'vs/workbench/browser/c import { EditorDescriptor, IEditorRegistry } from 'vs/workbench/browser/editor'; import { AbstractSideBySideEditorInputSerializer } from 'vs/workbench/browser/parts/editor/editor.contribution'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; -import { EditorInput, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { ExplorerFolderContext, ExplorerRootContext } from 'vs/workbench/contrib/files/common/files'; import { KeybindingsEditor } from 'vs/workbench/contrib/preferences/browser/keybindingsEditor'; @@ -42,6 +42,7 @@ import { IPreferencesService } from 'vs/workbench/services/preferences/common/pr import { DefaultPreferencesEditorInput, PreferencesEditorInput, SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; import { preferencesOpenSettingsIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; import { KeybindingsEditorInput } from 'vs/workbench/services/preferences/browser/keybindingsEditorInput'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; const SETTINGS_EDITOR_COMMAND_SEARCH = 'settings.action.search'; diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts index f77a8750c8a..a8a3874f73a 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts @@ -41,7 +41,8 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IEditorRegistry } from 'vs/workbench/browser/editor'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; -import { EditorExtensions, EditorInput, EditorOptions, IEditorControl, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorExtensions, EditorOptions, IEditorControl, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { TextResourceEditorModel } from 'vs/workbench/common/editor/textResourceEditorModel'; import { DefaultSettingsRenderer, FolderSettingsRenderer, IPreferencesRenderer, UserSettingsRenderer, WorkspaceSettingsRenderer } from 'vs/workbench/contrib/preferences/browser/preferencesRenderers'; import { SearchWidget, SettingsTarget, SettingsTargetsWidget } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets'; diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 6b923801cb9..ea12b245a9f 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -27,7 +27,7 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { localize } from 'vs/nls'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkbenchEditorConfiguration, IEditorInput, EditorInput, EditorResourceAccessor } from 'vs/workbench/common/editor'; +import { IWorkbenchEditorConfiguration, IEditorInput, EditorResourceAccessor } from 'vs/workbench/common/editor'; import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { Range, IRange } from 'vs/editor/common/core/range'; import { ThrottledDelayer } from 'vs/base/common/async'; @@ -51,6 +51,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { Codicon } from 'vs/base/common/codicons'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { stripIcons } from 'vs/base/common/iconLabels'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; interface IAnythingQuickPickItem extends IPickerQuickAccessItem, IQuickPickItemWithResource { } diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts index c7ee48405fd..723993196c9 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts @@ -16,7 +16,7 @@ import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { EditorInput, GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, EditorResourceAccessor, IMoveResult, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, EditorResourceAccessor, IMoveResult, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { Memento } from 'vs/workbench/common/memento'; import { SearchEditorFindMatchClass, SearchEditorScheme, SearchEditorWorkingCopyTypeId } from 'vs/workbench/contrib/searchEditor/browser/constants'; import { SearchConfigurationModel, SearchEditorModel, searchEditorModelFactory } from 'vs/workbench/contrib/searchEditor/browser/searchEditorModel'; @@ -29,6 +29,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ISearchComplete, ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search'; import { bufferToReadable, VSBuffer } from 'vs/base/common/buffer'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; export type SearchConfiguration = { query: string, diff --git a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts index b28a25928a6..26cd479c42e 100644 --- a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts +++ b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts @@ -32,7 +32,7 @@ import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { createDecorator, IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService'; -import { EditorModel } from 'vs/workbench/common/editor'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { testingPeekBorder } from 'vs/workbench/contrib/testing/browser/theme'; import { AutoOpenPeekViewWhen, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration'; import { Testing } from 'vs/workbench/contrib/testing/common/constants'; diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts index af616fb2422..6b535316dd5 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts @@ -14,7 +14,8 @@ import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { EditorInput, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewWindowDragMonitor } from 'vs/workbench/contrib/webview/browser/webviewWindowDragMonitor'; import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput'; diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts index 467342013e8..9cd51fd72ef 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput.ts @@ -5,7 +5,8 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; -import { EditorInput, EditorInputCapabilities, GroupIdentifier, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; +import { EditorInputCapabilities, GroupIdentifier, IEditorInput, Verbosity } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewIconManager, WebviewIcons } from 'vs/workbench/contrib/webviewPanel/browser/webviewIconManager'; diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedInput.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedInput.ts index 6aa2d4ec4eb..fab174551d9 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedInput.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedInput.ts @@ -5,7 +5,7 @@ import 'vs/css!./gettingStarted'; import { localize } from 'vs/nls'; -import { EditorInput } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; diff --git a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts index 89702ffe4d1..a67789529a4 100644 --- a/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts +++ b/src/vs/workbench/contrib/welcome/page/browser/welcomePage.ts @@ -32,7 +32,7 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic import { focusBorder, textLinkForeground, textLinkActiveForeground, foreground, descriptionForeground, contrastBorder, activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils'; import { IExtensionsViewPaneContainer, IExtensionsWorkbenchService, VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions'; -import { IEditorInputSerializer, EditorInput } from 'vs/workbench/common/editor'; +import { IEditorInputSerializer } from 'vs/workbench/common/editor'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { TimeoutTimer } from 'vs/base/common/async'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; @@ -53,6 +53,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationNode, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; import { ILogService } from 'vs/platform/log/common/log'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; export const DEFAULT_STARTUP_EDITOR_CONFIG: IConfigurationNode = { diff --git a/src/vs/workbench/contrib/welcome/walkThrough/browser/editor/editorWalkThrough.ts b/src/vs/workbench/contrib/welcome/walkThrough/browser/editor/editorWalkThrough.ts index 44eeec072b2..f174ef7a7fc 100644 --- a/src/vs/workbench/contrib/welcome/walkThrough/browser/editor/editorWalkThrough.ts +++ b/src/vs/workbench/contrib/welcome/walkThrough/browser/editor/editorWalkThrough.ts @@ -10,8 +10,9 @@ import { Action } from 'vs/base/common/actions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { WalkThroughInput, WalkThroughInputOptions } from 'vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput'; import { FileAccess, Schemas } from 'vs/base/common/network'; -import { IEditorInputSerializer, EditorInput } from 'vs/workbench/common/editor'; +import { IEditorInputSerializer } from 'vs/workbench/common/editor'; import { EditorOverride } from 'vs/platform/editor/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; const typeId = 'workbench.editors.walkThroughInput'; const inputOptions: WalkThroughInputOptions = { diff --git a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts index be87363368f..de39f3dee71 100644 --- a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts +++ b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EditorInput, EditorModel } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { URI } from 'vs/base/common/uri'; import { DisposableStore, IReference } from 'vs/base/common/lifecycle'; import { ITextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'; diff --git a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts index e894eb2020d..217eb0ca959 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts @@ -26,7 +26,7 @@ import { IEditorRegistry, EditorDescriptor } from 'vs/workbench/browser/editor'; import { shieldIcon, WorkspaceTrustEditor } from 'vs/workbench/contrib/workspace/browser/workspaceTrustEditor'; import { WorkspaceTrustEditorInput } from 'vs/workbench/services/workspaces/browser/workspaceTrustEditorInput'; import { isWorkspaceTrustEnabled, WORKSPACE_TRUST_EMPTY_WINDOW, WORKSPACE_TRUST_ENABLED, WORKSPACE_TRUST_STARTUP_PROMPT, WORKSPACE_TRUST_UNTRUSTED_FILES } from 'vs/workbench/services/workspaces/common/workspaceTrust'; -import { EditorInput, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorResourceAccessor } from 'vs/workbench/common/editor'; +import { IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorResourceAccessor } from 'vs/workbench/common/editor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -45,6 +45,7 @@ import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IBannerItem, IBannerService } from 'vs/workbench/services/banner/browser/bannerService'; import { getVirtualWorkspaceScheme } from 'vs/platform/remote/common/remoteHosts'; import { verifyMicrosoftInternalDomain } from 'vs/platform/telemetry/common/commonProperties'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; const BANNER_RESTRICTED_MODE = 'workbench.banner.restrictedMode'; const BANNER_VIRTUAL_WORKSPACE = 'workbench.banner.virtualWorkspace'; diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 9e9dbe25d7f..cae07c689b3 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -5,7 +5,9 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IResourceEditorInput, ITextEditorOptions, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; -import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, EditorInput, SideBySideEditorInput, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, TextEditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, TextEditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { Registry } from 'vs/platform/registry/common/platform'; import { ResourceMap } from 'vs/base/common/map'; diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index e65343d8f27..08b04c5a3fe 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -8,7 +8,7 @@ import { EditorActivation, EditorOverride } from 'vs/platform/editor/common/edit import { URI } from 'vs/base/common/uri'; import { Event } from 'vs/base/common/event'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { EditorInput, EditorsOrder, SideBySideEditorInput } from 'vs/workbench/common/editor'; +import { EditorsOrder } from 'vs/workbench/common/editor'; import { workbenchInstantiationService, TestServiceAccessor, registerTestEditor, TestFileEditorInput, ITestInstantiationService, registerTestResourceEditor, registerTestSideBySideEditor, createEditorPart } from 'vs/workbench/test/browser/workbenchTestServices'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; @@ -33,6 +33,8 @@ import { MockScopableContextKeyService } from 'vs/platform/keybinding/test/commo import { ContributedEditorPriority } from 'vs/workbench/services/editor/common/editorOverrideService'; import { IWorkspaceTrustRequestService, WorkspaceTrustUriResponse } from 'vs/platform/workspace/common/workspaceTrust'; import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; suite('EditorService', () => { diff --git a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts index 8279ac530a3..36ea958e8c4 100644 --- a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EditorOptions, IEditorInputFactoryRegistry, EditorExtensions, SideBySideEditorInput } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; import { workbenchInstantiationService, TestFileEditorInput, registerTestEditor, TestEditorPart, createEditorPart, registerTestSideBySideEditor } from 'vs/workbench/test/browser/workbenchTestServices'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -17,6 +17,7 @@ import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { EditorsObserver } from 'vs/workbench/browser/parts/editor/editorsObserver'; import { timeout } from 'vs/base/common/async'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; suite('EditorsObserver', function () { diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index 4ce401e8a18..b76509ac97c 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -7,7 +7,8 @@ import { localize } from 'vs/nls'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IEditor } from 'vs/editor/common/editorCommon'; import { ITextEditorOptions, IResourceEditorInput, TextEditorSelectionRevealType, IEditorOptions } from 'vs/platform/editor/common/editor'; -import { IEditorInput, IEditorPane, EditorExtensions, EditorInput, IEditorCloseEvent, IEditorInputFactoryRegistry, EditorResourceAccessor, IEditorIdentifier, GroupIdentifier, EditorsOrder, SideBySideEditor } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorPane, EditorExtensions, IEditorCloseEvent, IEditorInputFactoryRegistry, EditorResourceAccessor, IEditorIdentifier, GroupIdentifier, EditorsOrder, SideBySideEditor } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { FileChangesEvent, IFileService, FileChangeType, FILES_EXCLUDE_CONFIG, FileOperationEvent, FileOperation } from 'vs/platform/files/common/files'; diff --git a/src/vs/workbench/services/preferences/browser/keybindingsEditorInput.ts b/src/vs/workbench/services/preferences/browser/keybindingsEditorInput.ts index 1721274da79..f26f2676a46 100644 --- a/src/vs/workbench/services/preferences/browser/keybindingsEditorInput.ts +++ b/src/vs/workbench/services/preferences/browser/keybindingsEditorInput.ts @@ -6,7 +6,7 @@ import { OS } from 'vs/base/common/platform'; import * as nls from 'vs/nls'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { EditorInput } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { KeybindingsEditorModel } from 'vs/workbench/services/preferences/browser/keybindingsEditorModel'; export interface IKeybindingsEditorSearchOptions { diff --git a/src/vs/workbench/services/preferences/browser/keybindingsEditorModel.ts b/src/vs/workbench/services/preferences/browser/keybindingsEditorModel.ts index ce411da0b73..87ba94a9d24 100644 --- a/src/vs/workbench/services/preferences/browser/keybindingsEditorModel.ts +++ b/src/vs/workbench/services/preferences/browser/keybindingsEditorModel.ts @@ -13,7 +13,7 @@ import { ResolvedKeybinding, ResolvedKeybindingPart } from 'vs/base/common/keyCo import { AriaLabelProvider, UserSettingsLabelProvider, UILabelProvider, ModifierLabels as ModLabels } from 'vs/base/common/keybindingLabels'; import { MenuRegistry, ILocalizedString, ICommandAction } from 'vs/platform/actions/common/actions'; import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions'; -import { EditorModel } from 'vs/workbench/common/editor'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem'; import { getAllUnboundCommands } from 'vs/workbench/services/keybinding/browser/unboundCommands'; diff --git a/src/vs/workbench/services/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts index b5e5abc53ef..6747f7b32ff 100644 --- a/src/vs/workbench/services/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -24,7 +24,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { EditorInput, IEditorInput, IEditorPane } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorPane } from 'vs/workbench/common/editor'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { GroupDirection, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -42,6 +42,7 @@ import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands'; import { getErrorMessage } from 'vs/base/common/errors'; import { EditorOverride } from 'vs/platform/editor/common/editor'; import { KeybindingsEditorInput } from 'vs/workbench/services/preferences/browser/keybindingsEditorInput'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; const emptyEditableSettingsContent = '{\n}'; diff --git a/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts index 385e64f438b..a0acb9d3b77 100644 --- a/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts +++ b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts @@ -9,7 +9,9 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService'; import * as nls from 'vs/nls'; import { IFileService } from 'vs/platform/files/common/files'; import { ILabelService } from 'vs/platform/label/common/label'; -import { EditorInput, SideBySideEditorInput, Verbosity } from 'vs/workbench/common/editor'; +import { Verbosity } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; diff --git a/src/vs/workbench/services/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts index 1195390b7ed..94e5753d719 100644 --- a/src/vs/workbench/services/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -18,7 +18,7 @@ import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configur import { ConfigurationScope, Extensions, IConfigurationNode, IConfigurationPropertySchema, IConfigurationRegistry, OVERRIDE_PROPERTY_PATTERN, IConfigurationExtensionInfo } from 'vs/platform/configuration/common/configurationRegistry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { Registry } from 'vs/platform/registry/common/platform'; -import { EditorModel } from 'vs/workbench/common/editor'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { IFilterMetadata, IFilterResult, IGroupFilter, IKeybindingsEditorModel, ISearchResultGroup, ISetting, ISettingMatch, ISettingMatcher, ISettingsEditorModel, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences'; import { withNullAsUndefined, isArray } from 'vs/base/common/types'; import { FOLDER_SCOPES, WORKSPACE_SCOPES } from 'vs/workbench/services/configuration/common/configuration'; diff --git a/src/vs/workbench/services/untitled/common/untitledTextEditorHandler.ts b/src/vs/workbench/services/untitled/common/untitledTextEditorHandler.ts index f1643175e52..611cb978127 100644 --- a/src/vs/workbench/services/untitled/common/untitledTextEditorHandler.ts +++ b/src/vs/workbench/services/untitled/common/untitledTextEditorHandler.ts @@ -6,7 +6,8 @@ import { Schemas } from 'vs/base/common/network'; import { Disposable } from 'vs/base/common/lifecycle'; import { URI, UriComponents } from 'vs/base/common/uri'; -import { EditorInput, IEditorInputSerializer } from 'vs/workbench/common/editor'; +import { IEditorInputSerializer } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { isEqual, toLocalResource } from 'vs/base/common/resources'; import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; diff --git a/src/vs/workbench/services/workspaces/browser/workspaceTrustEditorInput.ts b/src/vs/workbench/services/workspaces/browser/workspaceTrustEditorInput.ts index b24e0bb70c1..02bdd2e22bd 100644 --- a/src/vs/workbench/services/workspaces/browser/workspaceTrustEditorInput.ts +++ b/src/vs/workbench/services/workspaces/browser/workspaceTrustEditorInput.ts @@ -6,7 +6,7 @@ import { Schemas } from 'vs/base/common/network'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; -import { EditorInput } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; export class WorkspaceTrustEditorInput extends EditorInput { static readonly ID: string = 'workbench.input.workspaceTrust'; diff --git a/src/vs/workbench/test/browser/parts/editor/editor.test.ts b/src/vs/workbench/test/browser/parts/editor/editor.test.ts index fea37aa6b42..c39a6f18ee7 100644 --- a/src/vs/workbench/test/browser/parts/editor/editor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editor.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, SideBySideEditorInput, EditorInputCapabilities, isEditorIdentifier } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, SideBySideEditor, IEditorInputWithPreferredResource, EditorInputCapabilities, isEditorIdentifier } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { URI } from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -18,6 +18,7 @@ import { whenEditorClosed } from 'vs/workbench/browser/editor'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { EditorService } from 'vs/workbench/services/editor/browser/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; suite('Workbench editor', () => { diff --git a/src/vs/workbench/test/browser/parts/editor/editorGroupModel.test.ts b/src/vs/workbench/test/browser/parts/editor/editorGroupModel.test.ts index db2aa54b170..9c4022e5c99 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorGroupModel.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorGroupModel.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { EditorGroupModel, ISerializedEditorGroupModel, EditorCloseEvent } from 'vs/workbench/common/editor/editorGroupModel'; -import { EditorExtensions, IEditorInputFactoryRegistry, EditorInput, IFileEditorInput, IEditorInputSerializer, CloseDirection, EditorsOrder } from 'vs/workbench/common/editor'; +import { EditorExtensions, IEditorInputFactoryRegistry, IFileEditorInput, IEditorInputSerializer, CloseDirection, EditorsOrder } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; import { TestLifecycleService, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; @@ -22,6 +22,7 @@ import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { TestContextService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; suite('Workbench editor group model', () => { diff --git a/src/vs/workbench/test/browser/parts/editor/editorInput.test.ts b/src/vs/workbench/test/browser/parts/editor/editorInput.test.ts index 5070f701542..7193ade8867 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorInput.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorInput.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EditorInput } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices'; diff --git a/src/vs/workbench/test/browser/parts/editor/editorModel.test.ts b/src/vs/workbench/test/browser/parts/editor/editorModel.test.ts index a478426e96c..9bda61b8280 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorModel.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorModel.test.ts @@ -5,7 +5,6 @@ import * as assert from 'assert'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; -import { EditorModel } from 'vs/workbench/common/editor'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; @@ -26,6 +25,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati import { TestTextResourcePropertiesService } from 'vs/workbench/test/common/workbenchTestServices'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; +import { EditorModel } from 'vs/workbench/common/editor/editorModel'; suite('Workbench editor model', () => { diff --git a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts index 7cb60385af2..204d684454b 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { EditorPane, EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane'; import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor'; -import { EditorInput, EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; @@ -27,6 +27,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { TestWorkspaceTrustManagementService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService'; import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; const NullThemeService = new TestThemeService(); diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index b5fba689809..0ed3e95bcbb 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -9,7 +9,8 @@ import { basename } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; -import { IEditorInputWithOptions, IEditorIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInput, IEditorPane, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorInput, EditorOptions, EditorsOrder, IFileEditorInput, IEditorInputFactoryRegistry, IEditorInputSerializer, EditorExtensions, ISaveOptions, IMoveResult, ITextEditorPane, ITextDiffEditorPane, IVisibleEditorPane, IEditorOpenContext, SideBySideEditorInput, IEditorMoveEvent, EditorExtensions as Extensions, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { IEditorInputWithOptions, IEditorIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInput, IEditorPane, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorOptions, EditorsOrder, IFileEditorInput, IEditorInputFactoryRegistry, IEditorInputSerializer, EditorExtensions, ISaveOptions, IMoveResult, ITextEditorPane, ITextDiffEditorPane, IVisibleEditorPane, IEditorOpenContext, IEditorMoveEvent, EditorExtensions as Extensions, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; import { EditorServiceImpl, IEditorGroupView, IEditorGroupsAccessor, IEditorGroupTitleHeight } from 'vs/workbench/browser/parts/editor/editor'; import { Event, Emitter } from 'vs/base/common/event'; import { IResolvedWorkingCopyBackup, IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup'; @@ -139,6 +140,7 @@ import { BrowserElevatedFileService } from 'vs/workbench/services/files/browser/ import { IDiffComputationResult, IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService'; import { TextEdit, IInplaceReplaceSupportResult } from 'vs/editor/common/modes'; import { ResourceMap } from 'vs/base/common/map'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; export function createFileEditorInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput { return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined, undefined, undefined, undefined); @@ -1366,7 +1368,7 @@ export function registerTestFileEditor(): IDisposable { TestTextFileEditor.ID, 'Text File Editor' ), - [new SyncDescriptor(FileEditorInput)] + [new SyncDescriptor(FileEditorInput)] )); return disposables; @@ -1382,8 +1384,8 @@ export function registerTestResourceEditor(): IDisposable { 'Text Editor' ), [ - new SyncDescriptor(UntitledTextEditorInput), - new SyncDescriptor(TextResourceEditorInput) + new SyncDescriptor(UntitledTextEditorInput), + new SyncDescriptor(TextResourceEditorInput) ] )); From 52df34dcf196fff7be19f55776d4c67fc98584d5 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 25 May 2021 12:14:45 +0200 Subject: [PATCH 036/140] Fixes invalid cursor position around after decorations. --- src/vs/editor/common/viewLayout/viewLineRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/viewLayout/viewLineRenderer.ts b/src/vs/editor/common/viewLayout/viewLineRenderer.ts index a7dc3f33e45..76f0fc65430 100644 --- a/src/vs/editor/common/viewLayout/viewLineRenderer.ts +++ b/src/vs/editor/common/viewLayout/viewLineRenderer.ts @@ -852,7 +852,7 @@ function _renderLine(input: ResolvedRenderLineInput, sb: IStringBuilder): Render const partType = part.type; const partRendersWhitespace = (renderWhitespace !== RenderWhitespace.None && part.isWhitespace()); const partRendersWhitespaceWithWidth = partRendersWhitespace && !fontIsMonospace && (partType === 'mtkw'/*only whitespace*/ || !containsForeignElements); - const partIsEmptyAndHasPseudoAfter = (charIndex === partEndIndex && part.metadata === LinePartMetadata.PSEUDO_AFTER); + const partIsEmptyAndHasPseudoAfter = (charIndex === partEndIndex && part.isPseudoAfter()); charOffsetInPart = 0; sb.appendASCIIString('( { - extensionPoint: 'notebookOutputRenderer', + extensionPoint: 'notebookRenderer', jsonSchema: notebookRendererContribution }); From eff82a3cef1342d27361e013a56ee3a6d1282f97 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 25 May 2021 12:32:14 +0200 Subject: [PATCH 039/140] rename trusted types CSP from notebookOutputRenderer to just notebookRenderer --- src/vs/code/electron-browser/workbench/workbench.html | 2 +- src/vs/code/electron-sandbox/workbench/workbench.html | 2 +- .../contrib/notebook/browser/view/renderers/webviewPreloads.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/code/electron-browser/workbench/workbench.html b/src/vs/code/electron-browser/workbench/workbench.html index bd37436f1fd..38405e41e15 100644 --- a/src/vs/code/electron-browser/workbench/workbench.html +++ b/src/vs/code/electron-browser/workbench/workbench.html @@ -4,7 +4,7 @@ - + diff --git a/src/vs/code/electron-sandbox/workbench/workbench.html b/src/vs/code/electron-sandbox/workbench/workbench.html index bd37436f1fd..38405e41e15 100644 --- a/src/vs/code/electron-sandbox/workbench/workbench.html +++ b/src/vs/code/electron-sandbox/workbench/workbench.html @@ -4,7 +4,7 @@ - + diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 5b358b22026..8250b75e1f3 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -494,7 +494,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re postKernelMessage: (data: unknown) => postNotebookMessage('customKernelMessage', { message: data }), }; - const ttPolicy = window.trustedTypes?.createPolicy('notebookOutputRenderer', { + const ttPolicy = window.trustedTypes?.createPolicy('notebookRenderer', { createHTML: value => value, createScript: value => value, }); From 8bd49ffd50be25063837d65db5afa8a20bec76b5 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 25 May 2021 12:48:02 +0200 Subject: [PATCH 040/140] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a2019dfa29..7e3bd9ff769 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.57.0", - "distro": "d29fc1ecd33fd97734b5c245280f25489646d00e", + "distro": "f572cb079a417a61c1db45d011c3eefbbcf881f4", "author": { "name": "Microsoft Corporation" }, From 5364a9351fd82d9b1ee8e9663a6a7df0095fb8fa Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 25 May 2021 12:49:05 +0200 Subject: [PATCH 041/140] Adds option "editor.suggest.suggestionPreviewExpanded" to toggle whether suggestion previews are expanded by default. --- src/vs/editor/common/config/editorOptions.ts | 12 ++++++++++ .../inlineCompletions/ghostTextWidget.ts | 24 +++++++++++++++---- .../inlineCompletionsModel.ts | 8 +++---- .../suggestWidgetAdapterModel.ts | 4 ++-- src/vs/monaco.d.ts | 5 ++++ 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index dce74ab6954..e28386b5e36 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -3178,6 +3178,11 @@ export interface ISuggestOptions { * Enable or disable the rendering of the suggestion inline. */ showSuggestionPreview?: boolean; + /** + * Enable or disable the default expansion of the suggestion preview. + * Defaults to false. + */ + suggestionPreviewExpanded?: boolean; /** * Show details inline with the label. Defaults to true. */ @@ -3310,6 +3315,7 @@ class EditorSuggest extends BaseEditorOption value }); @@ -27,7 +28,7 @@ export interface GhostTextWidgetModel { readonly onDidChange: Event; readonly ghostText: GhostText | undefined; - expand(): void; + setExpanded(expanded: boolean): void; readonly expanded: boolean; readonly minReservedLineCount: number; @@ -41,7 +42,7 @@ export interface GhostText { export abstract class BaseGhostTextWidgetModel extends Disposable implements GhostTextWidgetModel { public abstract readonly ghostText: GhostText | undefined; - private _expanded = false; + private _expanded: boolean | undefined = undefined; protected readonly onDidChangeEmitter = new Emitter(); public readonly onDidChange = this.onDidChangeEmitter.event; @@ -49,10 +50,23 @@ export abstract class BaseGhostTextWidgetModel extends Disposable implements Gho public abstract readonly minReservedLineCount: number; public get expanded() { + if (this._expanded === undefined) { + return this.editor.getOption(EditorOption.suggest).suggestionPreviewExpanded; + } return this._expanded; } - public expand(): void { + constructor(protected readonly editor: IActiveCodeEditor) { + super(); + + this._register(editor.onDidChangeConfiguration((e) => { + if (e.hasChanged(EditorOption.suggest) && this._expanded === undefined) { + this.onDidChangeEmitter.fire(); + } + })); + } + + public setExpanded(expanded: boolean): void { this._expanded = true; this.onDidChangeEmitter.fire(); } @@ -215,7 +229,7 @@ export class GhostTextWidget extends Disposable { button.append(`+${remainingLinesLength} lines…`); disposableStore.add(dom.addStandardDisposableListener(button, 'click', (e) => { - this.model?.expand(); + this.model?.setExpanded(true); e.preventDefault(); this.editor.focus(); })); diff --git a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts index 9422394e66f..21fc23a3753 100644 --- a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts +++ b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts @@ -60,8 +60,8 @@ export class InlineCompletionsModel extends Disposable implements GhostTextWidge return this.session ? this.session.expanded : false; } - public expand(): void { - this.session?.expand(); + public setExpanded(expanded: boolean): void { + this.session?.setExpanded(expanded); } public setActive(active: boolean) { @@ -118,8 +118,8 @@ class InlineCompletionsSession extends BaseGhostTextWidgetModel { private updateSoon = this._register(new RunOnceScheduler(() => this.update(), 50)); private readonly textModel = this.editor.getModel(); - constructor(private readonly editor: IActiveCodeEditor, private readonly triggerPosition: Position, private readonly shouldUpdate: () => boolean) { - super(); + constructor(editor: IActiveCodeEditor, private readonly triggerPosition: Position, private readonly shouldUpdate: () => boolean) { + super(editor); this._register(toDisposable(() => { this.clearGhostTextPromise(); })); diff --git a/src/vs/editor/contrib/inlineCompletions/suggestWidgetAdapterModel.ts b/src/vs/editor/contrib/inlineCompletions/suggestWidgetAdapterModel.ts index 316ffb02f6b..a2892f1faad 100644 --- a/src/vs/editor/contrib/inlineCompletions/suggestWidgetAdapterModel.ts +++ b/src/vs/editor/contrib/inlineCompletions/suggestWidgetAdapterModel.ts @@ -24,9 +24,9 @@ export class SuggestWidgetAdapterModel extends BaseGhostTextWidgetModel { public get isActive() { return this.isSuggestWidgetVisible; } constructor( - private readonly editor: IActiveCodeEditor + editor: IActiveCodeEditor ) { - super(); + super(editor); const suggestController = SuggestController.get(this.editor); if (suggestController) { diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 62054af056b..61608d03849 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -3848,6 +3848,11 @@ declare namespace monaco.editor { * Enable or disable the rendering of the suggestion inline. */ showSuggestionPreview?: boolean; + /** + * Enable or disable the default expansion of the suggestion preview. + * Defaults to false. + */ + suggestionPreviewExpanded?: boolean; /** * Show details inline with the label. Defaults to true. */ From 0efc03fb1681a5d81f7119c0488f1e940ed9d50f Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 25 May 2021 12:54:02 +0200 Subject: [PATCH 042/140] Removes unused import. --- src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts b/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts index 1a4a1a4c9ef..178c62518c8 100644 --- a/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts +++ b/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts @@ -20,7 +20,6 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IModelDeltaDecoration } from 'vs/editor/common/model'; import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { editorSuggestPreviewBorder, editorSuggestPreviewOpacity } from 'vs/editor/common/view/editorColorRegistry'; -import { RGBA, Color } from 'vs/base/common/color'; const ttPolicy = window.trustedTypes?.createPolicy('editorGhostText', { createHTML: value => value }); From a26ecef44b5e091af5cc2ab904b0f1449ab957f4 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 25 May 2021 04:15:02 -0700 Subject: [PATCH 043/140] Add self to workbench-diagnostics --- .github/classifier.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/classifier.json b/.github/classifier.json index d985c69a121..8e580003259 100644 --- a/.github/classifier.json +++ b/.github/classifier.json @@ -152,7 +152,7 @@ "web": {"assign": ["bpasero"]}, "webview": {"assign": ["mjbvz"]}, "workbench-cli": {"assign": []}, - "workbench-diagnostics": {"assign": ["TylerLeonhardt"]}, + "workbench-diagnostics": {"assign": ["Tyriar"]}, "workbench-dnd": {"assign": ["bpasero"]}, "workbench-editor-grid": {"assign": ["sbatten"]}, "workbench-editors": {"assign": ["bpasero"]}, From 0685a4af28b39ea15765ff66a027f5efa50ce1da Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 25 May 2021 04:32:51 -0700 Subject: [PATCH 044/140] Default bash, zsh and fish to login shells on macOS Fixes #124409 --- .../terminal/common/terminalPlatformConfiguration.ts | 7 +++++-- .../terminal/browser/terminalProfileResolverService.ts | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts b/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts index bbff27d787b..3ab5f4e8620 100644 --- a/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts +++ b/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts @@ -227,13 +227,16 @@ const terminalPlatformConfiguration: IConfigurationNode = { default: { 'bash': { path: 'bash', + args: ['-l'], icon: 'terminal-bash' }, 'zsh': { - path: 'zsh' + path: 'zsh', + args: ['-l'] }, 'fish': { - path: 'fish' + path: 'fish', + args: ['-l'] }, 'tmux': { path: 'tmux', diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts b/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts index 2f6726d53d9..fd297b78720 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts @@ -228,7 +228,7 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro args = shellArgsSetting; } if (args === undefined) { - if (options.os === OperatingSystem.Macintosh && args === undefined && path.parse(executable).name.match(/(zsh|bash)/)) { + if (options.os === OperatingSystem.Macintosh && args === undefined && path.parse(executable).name.match(/(zsh|bash|fish)/)) { // macOS should launch a login shell by default args = ['--login']; } else { From 43b7187c3df24284fa05e7e4b2d72a2ae8b44333 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Tue, 25 May 2021 04:55:02 -0700 Subject: [PATCH 045/140] Force inheritEnv in ext debug terminals Fixes #124041 --- .../api/browser/mainThreadTerminalService.ts | 3 ++- src/vs/workbench/api/common/extHost.protocol.ts | 1 + .../api/common/extHostTerminalService.ts | 17 ++++++++++++----- .../workbench/api/node/extHostDebugService.ts | 5 ++++- .../api/node/extHostTerminalService.ts | 9 +++++---- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadTerminalService.ts b/src/vs/workbench/api/browser/mainThreadTerminalService.ts index 56d4075670c..38faa64474d 100644 --- a/src/vs/workbench/api/browser/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/browser/mainThreadTerminalService.ts @@ -139,7 +139,8 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape : undefined, extHostTerminalId: extHostTerminalId, isFeatureTerminal: launchConfig.isFeatureTerminal, - isExtensionOwnedTerminal: launchConfig.isExtensionOwnedTerminal + isExtensionOwnedTerminal: launchConfig.isExtensionOwnedTerminal, + useShellEnvironment: launchConfig.useShellEnvironment }; const terminal = this._terminalService.createTerminal(shellLaunchConfig); this._extHostTerminalIds.set(extHostTerminalId, terminal.instanceId); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 3bea115021f..6f5283ef893 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -463,6 +463,7 @@ export interface TerminalLaunchConfig { isExtensionCustomPtyTerminal?: boolean; isFeatureTerminal?: boolean; isExtensionOwnedTerminal?: boolean; + useShellEnvironment?: boolean; } export interface MainThreadTerminalServiceShape extends IDisposable { diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index be6ce95e65f..1deba734389 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -36,7 +36,7 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID onDidWriteTerminalData: Event; createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal; - createTerminalFromOptions(options: vscode.TerminalOptions, isFeatureTerminal?: boolean): vscode.Terminal; + createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal; createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal; attachPtyToTerminal(id: number, pty: vscode.Pseudoterminal): void; getDefaultShell(useAutomationShell: boolean): string; @@ -45,6 +45,11 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection; } +export interface ITerminalInternalOptions { + isFeatureTerminal?: boolean; + useShellEnvironment?: boolean; +} + export const IExtHostTerminalService = createDecorator('IExtHostTerminalService'); export class ExtHostTerminal { @@ -123,12 +128,13 @@ export class ExtHostTerminal { strictEnv?: boolean, hideFromUser?: boolean, isFeatureTerminal?: boolean, - isExtensionOwnedTerminal?: boolean + isExtensionOwnedTerminal?: boolean, + useShellEnvironment?: boolean ): Promise { if (typeof this._id !== 'string') { throw new Error('Terminal has already been created'); } - await this._proxy.$createTerminal(this._id, { name: this._name, shellPath, shellArgs, cwd, env, icon, initialText, waitOnExit, strictEnv, hideFromUser, isFeatureTerminal, isExtensionOwnedTerminal }); + await this._proxy.$createTerminal(this._id, { name: this._name, shellPath, shellArgs, cwd, env, icon, initialText, waitOnExit, strictEnv, hideFromUser, isFeatureTerminal, isExtensionOwnedTerminal, useShellEnvironment }); } public async createExtensionTerminal(iconPath?: URI | { light: URI; dark: URI } | ThemeIcon): Promise { @@ -335,7 +341,8 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I } public abstract createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal; - public abstract createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal; + public abstract createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal; + public getDefaultShell(useAutomationShell: boolean): string { const profile = useAutomationShell ? this._defaultAutomationProfile : this._defaultProfile; return profile?.path || ''; @@ -785,7 +792,7 @@ export class WorkerExtHostTerminalService extends BaseExtHostTerminalService { throw new NotSupportedError(); } - public createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal { + public createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal { throw new NotSupportedError(); } } diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index d09a89d23c8..193490ea7b0 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -98,7 +98,10 @@ export class ExtHostDebugService extends ExtHostDebugServiceBase { name: args.title || nls.localize('debug.terminal.title', "debuggee"), }; giveShellTimeToInitialize = true; - terminal = this._terminalService.createTerminalFromOptions(options, true); + terminal = this._terminalService.createTerminalFromOptions(options, { + isFeatureTerminal: true, + useShellEnvironment: true + }); this._integratedTerminalInstances.insert(terminal, shellConfig); } else { diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 8173c051ff2..8b70a2fb70f 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -6,7 +6,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { generateUuid } from 'vs/base/common/uuid'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; -import { BaseExtHostTerminalService, ExtHostTerminal } from 'vs/workbench/api/common/extHostTerminalService'; +import { BaseExtHostTerminalService, ExtHostTerminal, ITerminalInternalOptions } from 'vs/workbench/api/common/extHostTerminalService'; import type * as vscode from 'vscode'; export class ExtHostTerminalService extends BaseExtHostTerminalService { @@ -24,7 +24,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { return terminal.value; } - public createTerminalFromOptions(options: vscode.TerminalOptions, isFeatureTerminal?: boolean): vscode.Terminal { + public createTerminalFromOptions(options: vscode.TerminalOptions, internalOptions?: ITerminalInternalOptions): vscode.Terminal { const terminal = new ExtHostTerminal(this._proxy, generateUuid(), options, options.name); this._terminals.push(terminal); terminal.create( @@ -37,8 +37,9 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { /*options.waitOnExit*/ undefined, withNullAsUndefined(options.strictEnv), withNullAsUndefined(options.hideFromUser), - withNullAsUndefined(isFeatureTerminal), - true + withNullAsUndefined(internalOptions?.isFeatureTerminal), + true, + withNullAsUndefined(internalOptions?.useShellEnvironment) ); return terminal.value; } From 97d576cb08586d33e30419c91da05a80acf8cf8f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 14:50:13 +0200 Subject: [PATCH 046/140] editors - more cleanup of large files --- src/vs/workbench/browser/layout.ts | 2 +- .../parts/editor/editor.contribution.ts | 162 +++---------- .../browser/parts/editor/editorActions.ts | 2 +- .../browser/parts/editor/editorGroupView.ts | 2 +- .../browser/parts/editor/editorStatus.ts | 2 +- .../browser/parts/editor/editorsObserver.ts | 2 +- .../browser/parts/editor/sideBySideEditor.ts | 2 +- .../browser/parts/editor/tabsTitleControl.ts | 4 +- .../browser/parts/editor/titleControl.ts | 17 +- src/vs/workbench/common/editor.ts | 16 +- .../common/editor/diffEditorInput.ts | 10 +- .../common/editor/editorGroupModel.ts | 2 +- .../common/editor/sideBySideEditoInput.ts | 135 ----------- .../common/editor/sideBySideEditorInput.ts | 223 ++++++++++++++++++ .../contrib/files/browser/fileCommands.ts | 2 +- .../browser/preferences.contribution.ts | 2 +- .../services/editor/browser/editorService.ts | 2 +- .../editor/test/browser/editorService.test.ts | 2 +- .../test/browser/editorsObserver.test.ts | 2 +- .../common/preferencesEditorInput.ts | 2 +- .../test/browser/parts/editor/editor.test.ts | 2 +- .../test/browser/workbenchTestServices.ts | 2 +- 22 files changed, 301 insertions(+), 296 deletions(-) delete mode 100644 src/vs/workbench/common/editor/sideBySideEditoInput.ts create mode 100644 src/vs/workbench/common/editor/sideBySideEditorInput.ts diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 1d967bf722f..0c8569dff0a 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -11,7 +11,7 @@ import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/com import { Registry } from 'vs/platform/registry/common/platform'; import { isWindows, isLinux, isMacintosh, isWeb, isNative } from 'vs/base/common/platform'; import { pathsToEditors } from 'vs/workbench/common/editor'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart'; import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart'; import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel'; diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index ad1085e7376..5b579ff10f1 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -8,17 +8,15 @@ import { localize } from 'vs/nls'; import { URI } from 'vs/base/common/uri'; import { IEditorRegistry, EditorDescriptor } from 'vs/workbench/browser/editor'; import { - IEditorInputSerializer, IEditorInputFactoryRegistry, TextCompareEditorActiveContext, ActiveEditorPinnedContext, EditorExtensions, - EditorGroupEditorsCountContext, ActiveEditorStickyContext, ActiveEditorAvailableEditorIdsContext, MultipleEditorGroupsContext, ActiveEditorDirtyContext + IEditorInputFactoryRegistry, TextCompareEditorActiveContext, ActiveEditorPinnedContext, EditorExtensions, EditorGroupEditorsCountContext, + ActiveEditorStickyContext, ActiveEditorAvailableEditorIdsContext, MultipleEditorGroupsContext, ActiveEditorDirtyContext } from 'vs/workbench/common/editor'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; -import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { SideBySideEditorInput, SideBySideEditorInputSerializer } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor'; -import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; +import { DiffEditorInput, DiffEditorInputSerializer } from 'vs/workbench/common/editor/diffEditorInput'; import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor'; import { BinaryResourceDiffEditor } from 'vs/workbench/browser/parts/editor/binaryDiffEditor'; import { ChangeEncodingAction, ChangeEOLAction, ChangeModeAction, EditorStatus } from 'vs/workbench/browser/parts/editor/editorStatus'; @@ -44,7 +42,7 @@ import { CLOSE_EDITORS_AND_GROUP_COMMAND_ID, CLOSE_EDITORS_IN_GROUP_COMMAND_ID, CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID, CLOSE_EDITOR_COMMAND_ID, CLOSE_EDITOR_GROUP_COMMAND_ID, CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, CLOSE_PINNED_EDITOR_COMMAND_ID, CLOSE_SAVED_EDITORS_COMMAND_ID, GOTO_NEXT_CHANGE, GOTO_PREVIOUS_CHANGE, KEEP_EDITOR_COMMAND_ID, PIN_EDITOR_COMMAND_ID, SHOW_EDITORS_IN_GROUP, SPLIT_EDITOR_DOWN, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE, - TOGGLE_DIFF_SIDE_BY_SIDE, TOGGLE_KEEP_EDITORS_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, setup + TOGGLE_DIFF_SIDE_BY_SIDE, TOGGLE_KEEP_EDITORS_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, setup as registerEditorCommands } from 'vs/workbench/browser/parts/editor/editorCommands'; import { inQuickPickContext, getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -63,7 +61,8 @@ import { Codicon } from 'vs/base/common/codicons'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { UntitledTextEditorInputSerializer, UntitledTextEditorWorkingCopyEditorHandler } from 'vs/workbench/services/untitled/common/untitledTextEditorHandler'; -// Register Resource Text Editor +//#region Editor Registrations + Registry.as(EditorExtensions.Editors).registerEditor( EditorDescriptor.create( TextResourceEditor, @@ -76,7 +75,6 @@ Registry.as(EditorExtensions.Editors).registerEditor( ] ); -// Register Text Diff Editor Registry.as(EditorExtensions.Editors).registerEditor( EditorDescriptor.create( TextDiffEditor, @@ -88,7 +86,6 @@ Registry.as(EditorExtensions.Editors).registerEditor( ] ); -// Register Binary Resource Diff Editor Registry.as(EditorExtensions.Editors).registerEditor( EditorDescriptor.create( BinaryResourceDiffEditor, @@ -111,121 +108,24 @@ Registry.as(EditorExtensions.Editors).registerEditor( ] ); -// Register Untitled Text Editor Input Serializer & Handler Registry.as(EditorExtensions.EditorInputFactories).registerEditorInputSerializer(UntitledTextEditorInput.ID, UntitledTextEditorInputSerializer); -Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(UntitledTextEditorWorkingCopyEditorHandler, LifecyclePhase.Ready); - -// Register SideBySide/DiffEditor Input Serializer -interface ISerializedSideBySideEditorInput { - name: string; - description: string | undefined; - - primarySerialized: string; - secondarySerialized: string; - - primaryTypeId: string; - secondaryTypeId: string; -} - -export abstract class AbstractSideBySideEditorInputSerializer implements IEditorInputSerializer { - - private getInputSerializers(secondaryEditorInputTypeId: string, primaryEditorInputTypeId: string): [IEditorInputSerializer | undefined, IEditorInputSerializer | undefined] { - const registry = Registry.as(EditorExtensions.EditorInputFactories); - - return [registry.getEditorInputSerializer(secondaryEditorInputTypeId), registry.getEditorInputSerializer(primaryEditorInputTypeId)]; - } - - canSerialize(editorInput: EditorInput): boolean { - const input = editorInput as SideBySideEditorInput | DiffEditorInput; - - if (input.primary && input.secondary) { - const [secondaryInputSerializer, primaryInputSerializer] = this.getInputSerializers(input.secondary.typeId, input.primary.typeId); - - return !!(secondaryInputSerializer?.canSerialize(input.secondary) && primaryInputSerializer?.canSerialize(input.primary)); - } - - return false; - } - - serialize(editorInput: EditorInput): string | undefined { - const input = editorInput as SideBySideEditorInput | DiffEditorInput; - - if (input.primary && input.secondary) { - const [secondaryInputSerializer, primaryInputSerializer] = this.getInputSerializers(input.secondary.typeId, input.primary.typeId); - if (primaryInputSerializer && secondaryInputSerializer) { - const primarySerialized = primaryInputSerializer.serialize(input.primary); - const secondarySerialized = secondaryInputSerializer.serialize(input.secondary); - - if (primarySerialized && secondarySerialized) { - const serializedEditorInput: ISerializedSideBySideEditorInput = { - name: input.getName(), - description: input.getDescription(), - primarySerialized: primarySerialized, - secondarySerialized: secondarySerialized, - primaryTypeId: input.primary.typeId, - secondaryTypeId: input.secondary.typeId - }; - - return JSON.stringify(serializedEditorInput); - } - } - } - - return undefined; - } - - deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput | undefined { - const deserialized: ISerializedSideBySideEditorInput = JSON.parse(serializedEditorInput); - - const [secondaryInputSerializer, primaryInputSerializer] = this.getInputSerializers(deserialized.secondaryTypeId, deserialized.primaryTypeId); - if (primaryInputSerializer && secondaryInputSerializer) { - const primaryInput = primaryInputSerializer.deserialize(instantiationService, deserialized.primarySerialized); - const secondaryInput = secondaryInputSerializer.deserialize(instantiationService, deserialized.secondarySerialized); - - if (primaryInput && secondaryInput) { - return this.createEditorInput(instantiationService, deserialized.name, deserialized.description, secondaryInput, primaryInput); - } - } - - return undefined; - } - - protected abstract createEditorInput(instantiationService: IInstantiationService, name: string, description: string | undefined, secondaryInput: EditorInput, primaryInput: EditorInput): EditorInput; -} - -class SideBySideEditorInputSerializer extends AbstractSideBySideEditorInputSerializer { - - protected createEditorInput(instantiationService: IInstantiationService, name: string, description: string | undefined, secondaryInput: EditorInput, primaryInput: EditorInput): EditorInput { - return new SideBySideEditorInput(name, description, secondaryInput, primaryInput); - } -} - -class DiffEditorInputSerializer extends AbstractSideBySideEditorInputSerializer { - - protected createEditorInput(instantiationService: IInstantiationService, name: string, description: string | undefined, secondaryInput: EditorInput, primaryInput: EditorInput): EditorInput { - return instantiationService.createInstance(DiffEditorInput, name, description, secondaryInput, primaryInput, undefined); - } -} - Registry.as(EditorExtensions.EditorInputFactories).registerEditorInputSerializer(SideBySideEditorInput.ID, SideBySideEditorInputSerializer); Registry.as(EditorExtensions.EditorInputFactories).registerEditorInputSerializer(DiffEditorInput.ID, DiffEditorInputSerializer); -// Register Editor Contributions +//#endregion + +//#region Workbench Contributions + +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorAutoSave, LifecyclePhase.Ready); +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorStatus, LifecyclePhase.Ready); +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(UntitledTextEditorWorkingCopyEditorHandler, LifecyclePhase.Ready); + registerEditorContribution(OpenWorkspaceButtonContribution.ID, OpenWorkspaceButtonContribution); -// Register Editor Status -Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorStatus, LifecyclePhase.Ready); +//#endregion -// Register Editor Auto Save -Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorAutoSave, LifecyclePhase.Ready); +//#region Quick Access -// Register Status Actions -const registry = Registry.as(ActionExtensions.WorkbenchActions); -registry.registerWorkbenchAction(SyncActionDescriptor.from(ChangeModeAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_M) }), 'Change Language Mode', undefined, ContextKeyExpr.not('notebookEditorFocused')); -registry.registerWorkbenchAction(SyncActionDescriptor.from(ChangeEOLAction), 'Change End of Line Sequence'); -registry.registerWorkbenchAction(SyncActionDescriptor.from(ChangeEncodingAction), 'Change File Encoding'); - -// Register Editor Quick Access const quickAccessRegistry = Registry.as(QuickAccessExtensions.Quickaccess); const editorPickerContextKey = 'inEditorsPicker'; const editorPickerContext = ContextKeyExpr.and(inQuickPickContext, ContextKeyExpr.has(editorPickerContextKey)); @@ -254,7 +154,17 @@ quickAccessRegistry.registerQuickAccessProvider({ helpEntries: [{ description: localize('allEditorsByMostRecentlyUsedQuickAccess', "Show All Opened Editors By Most Recently Used"), needsEditor: false }] }); -// Register Editor Actions +//#endregion + +//#region Actions & Commands + +// Editor Status +const registry = Registry.as(ActionExtensions.WorkbenchActions); +registry.registerWorkbenchAction(SyncActionDescriptor.from(ChangeModeAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_M) }), 'Change Language Mode', undefined, ContextKeyExpr.not('notebookEditorFocused')); +registry.registerWorkbenchAction(SyncActionDescriptor.from(ChangeEOLAction), 'Change End of Line Sequence'); +registry.registerWorkbenchAction(SyncActionDescriptor.from(ChangeEncodingAction), 'Change File Encoding'); + +// Editor Management registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextEditor, { primary: KeyMod.CtrlCmd | KeyCode.PageDown, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_CLOSE_SQUARE_BRACKET] } }), 'View: Open Next Editor', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenPreviousEditor, { primary: KeyMod.CtrlCmd | KeyCode.PageUp, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_OPEN_SQUARE_BRACKET] } }), 'View: Open Previous Editor', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextEditorInGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.PageDown), mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow) } }), 'View: Open Next Editor in Group', CATEGORIES.View.value); @@ -335,15 +245,10 @@ registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoRowsRi registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoColumnsBottomAction), 'View: Two Columns Bottom Editor Layout', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(ReopenResourcesAction), 'View: Reopen Editor With...', CATEGORIES.View.value, ActiveEditorAvailableEditorIdsContext); registry.registerWorkbenchAction(SyncActionDescriptor.from(ReOpenInTextEditorAction), 'View: Reopen Editor With Text Editor', CATEGORIES.View.value, ActiveEditorAvailableEditorIdsContext); - -// Register Quick Editor Actions including built in quick navigate support for some - registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousRecentlyUsedEditorAction), 'View: Quick Open Previous Recently Used Editor', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessLeastRecentlyUsedEditorAction), 'View: Quick Open Least Recently Used Editor', CATEGORIES.View.value); - registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousRecentlyUsedEditorInGroupAction, { primary: KeyMod.CtrlCmd | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyCode.Tab } }), 'View: Quick Open Previous Recently Used Editor in Group', CATEGORIES.View.value); registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessLeastRecentlyUsedEditorInGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab } }), 'View: Quick Open Least Recently Used Editor in Group', CATEGORIES.View.value); - registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousEditorFromHistoryAction), 'Quick Open Previous Editor from History'); const quickAccessNavigateNextInEditorPickerId = 'workbench.action.quickOpenNavigateNextInEditorPicker'; @@ -366,10 +271,13 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab } }); -// Editor Commands -setup(); +registerEditorCommands(); -// Touch Bar +//#endregion Workbench Actions + +//#region Menus + +// macOS: Touchbar if (isMacintosh) { MenuRegistry.appendMenuItem(MenuId.TouchBarContext, { command: { id: NavigateBackwardsAction.ID, title: NavigateBackwardsAction.LABEL, icon: { dark: FileAccess.asFileUri('vs/workbench/browser/parts/editor/media/back-tb.png', require) } }, @@ -959,3 +867,5 @@ MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, { submenu: MenuId.MenubarSwitchGroupMenu, order: 2 }); + +//#endregion diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 25f0817a50d..e901b380587 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { IEditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason, EditorsOrder, EditorInputCapabilities, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 95554e9e644..8fcaa030c6a 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/editorgroupview'; import { EditorGroupModel, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroupModel, isSerializedEditorGroupModel } from 'vs/workbench/common/editor/editorGroupModel'; import { EditorOptions, GroupIdentifier, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, EditorResourceAccessor, IEditorMoveEvent, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { Event, Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor, asCSSUrl } from 'vs/base/browser/dom'; diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 7f33306af4e..cd87db7f04d 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -53,7 +53,7 @@ import { IMarker, IMarkerService, MarkerSeverity, IMarkerData } from 'vs/platfor import { STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND } from 'vs/workbench/common/theme'; import { themeColorFromId } from 'vs/platform/theme/common/themeService'; import { ITelemetryData, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; class SideBySideEditorEncodingSupport implements IEncodingSupport { constructor(private primary: IEncodingSupport, private secondary: IEncodingSupport) { } diff --git a/src/vs/workbench/browser/parts/editor/editorsObserver.ts b/src/vs/workbench/browser/parts/editor/editorsObserver.ts index 95b03402738..108a035f888 100644 --- a/src/vs/workbench/browser/parts/editor/editorsObserver.ts +++ b/src/vs/workbench/browser/parts/editor/editorsObserver.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IEditorInput, IEditorInputFactoryRegistry, IEditorIdentifier, GroupIdentifier, EditorExtensions, IEditorPartOptionsChangeEvent, EditorsOrder } from 'vs/workbench/common/editor'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; diff --git a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts index 0cf8386bbe0..f39d76281cd 100644 --- a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts +++ b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts @@ -6,7 +6,7 @@ import { Dimension, $, clearNode } from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; import { EditorOptions, IEditorControl, IEditorPane, IEditorOpenContext, EditorExtensions } from 'vs/workbench/common/editor'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 27b7757f895..464af3eee27 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/tabstitlecontrol'; import { isMacintosh, isWindows } from 'vs/base/common/platform'; import { shorten } from 'vs/base/common/labels'; -import { EditorResourceAccessor, GroupIdentifier, IEditorInput, Verbosity, EditorCommandsContextActionRunner, IEditorPartOptions, SideBySideEditor } from 'vs/workbench/common/editor'; +import { EditorResourceAccessor, GroupIdentifier, IEditorInput, Verbosity, IEditorPartOptions, SideBySideEditor } from 'vs/workbench/common/editor'; import { computeEditorAriaLabel } from 'vs/workbench/browser/editor'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { EventType as TouchEventType, GestureEvent, Gesture } from 'vs/base/browser/touch'; @@ -19,7 +19,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IMenuService } from 'vs/platform/actions/common/actions'; -import { ITitleControlDimensions, TitleControl } from 'vs/workbench/browser/parts/editor/titleControl'; +import { EditorCommandsContextActionRunner, ITitleControlDimensions, TitleControl } from 'vs/workbench/browser/parts/editor/titleControl'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { IDisposable, dispose, DisposableStore, combinedDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts index bf2e7034b84..6980a28a90c 100644 --- a/src/vs/workbench/browser/parts/editor/titleControl.ts +++ b/src/vs/workbench/browser/parts/editor/titleControl.ts @@ -10,7 +10,7 @@ import { addDisposableListener, Dimension, EventType } from 'vs/base/browser/dom import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { ActionsOrientation, IActionViewItem, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; -import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, SubmenuAction } from 'vs/base/common/actions'; +import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, SubmenuAction, ActionRunner } from 'vs/base/common/actions'; import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { dispose, DisposableStore } from 'vs/base/common/lifecycle'; import { createActionViewItem, createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem'; @@ -30,7 +30,7 @@ import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs'; import { BreadcrumbsControl, IBreadcrumbsControlOptions } from 'vs/workbench/browser/parts/editor/breadcrumbsControl'; import { IEditorGroupsAccessor, IEditorGroupTitleHeight, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor'; -import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, EditorResourceAccessor, IEditorPartOptions, SideBySideEditor, ActiveEditorPinnedContext, ActiveEditorStickyContext, EditorsOrder } from 'vs/workbench/common/editor'; +import { IEditorCommandsContext, IEditorInput, EditorResourceAccessor, IEditorPartOptions, SideBySideEditor, ActiveEditorPinnedContext, ActiveEditorStickyContext, EditorsOrder } from 'vs/workbench/common/editor'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { IFileService } from 'vs/platform/files/common/files'; @@ -57,6 +57,19 @@ export interface ITitleControlDimensions { available: Dimension; } +export class EditorCommandsContextActionRunner extends ActionRunner { + + constructor( + private context: IEditorCommandsContext + ) { + super(); + } + + override run(action: IAction): Promise { + return super.run(action, this.context); + } +} + export abstract class TitleControl extends Themable { protected readonly groupTransfer = LocalSelectionTransfer.getInstance(); diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index ecb9d90d7c5..7a1ab14dca1 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -16,7 +16,6 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IEncodingSupport, IModeSupport } from 'vs/workbench/services/textfile/common/textfiles'; import { GroupsOrder, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ICompositeControl, IComposite } from 'vs/workbench/common/composite'; -import { ActionRunner, IAction } from 'vs/base/common/actions'; import { IFileService } from 'vs/platform/files/common/files'; import { IPathData } from 'vs/platform/windows/common/windows'; import { coalesce } from 'vs/base/common/arrays'; @@ -24,7 +23,7 @@ import { ACTIVE_GROUP, IResourceEditorInputType, SIDE_GROUP } from 'vs/workbench import { IRange } from 'vs/editor/common/core/range'; import { IExtUri } from 'vs/base/common/resources'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; // Static values for editor contributions export const EditorExtensions = { @@ -997,19 +996,6 @@ export interface IEditorCommandsContext { editorIndex?: number; } -export class EditorCommandsContextActionRunner extends ActionRunner { - - constructor( - private context: IEditorCommandsContext - ) { - super(); - } - - override run(action: IAction): Promise { - return super.run(action, this.context); - } -} - export interface IEditorCloseEvent extends IEditorIdentifier { replaced: boolean; index: number; diff --git a/src/vs/workbench/common/editor/diffEditorInput.ts b/src/vs/workbench/common/editor/diffEditorInput.ts index 67edf472669..b224ed26010 100644 --- a/src/vs/workbench/common/editor/diffEditorInput.ts +++ b/src/vs/workbench/common/editor/diffEditorInput.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { AbstractSideBySideEditorInputSerializer, SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { EditorModel } from 'vs/workbench/common/editor/editorModel'; import { TEXT_DIFF_EDITOR_ID, BINARY_DIFF_EDITOR_ID, Verbosity, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; @@ -17,6 +17,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { IFileService } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; import { withNullAsUndefined } from 'vs/base/common/types'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; /** * The base editor input for the diff editor. It is made up of two editor inputs, the original version @@ -153,3 +154,10 @@ export class DiffEditorInput extends SideBySideEditorInput { super.dispose(); } } + +export class DiffEditorInputSerializer extends AbstractSideBySideEditorInputSerializer { + + protected createEditorInput(instantiationService: IInstantiationService, name: string, description: string | undefined, secondaryInput: EditorInput, primaryInput: EditorInput): EditorInput { + return instantiationService.createInstance(DiffEditorInput, name, description, secondaryInput, primaryInput, undefined); + } +} diff --git a/src/vs/workbench/common/editor/editorGroupModel.ts b/src/vs/workbench/common/editor/editorGroupModel.ts index 20ab00e585f..b953f0f0d7a 100644 --- a/src/vs/workbench/common/editor/editorGroupModel.ts +++ b/src/vs/workbench/common/editor/editorGroupModel.ts @@ -6,7 +6,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { IEditorInputFactoryRegistry, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, IEditorInput, EditorsOrder, EditorExtensions } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle'; diff --git a/src/vs/workbench/common/editor/sideBySideEditoInput.ts b/src/vs/workbench/common/editor/sideBySideEditoInput.ts deleted file mode 100644 index a06f6aa7c76..00000000000 --- a/src/vs/workbench/common/editor/sideBySideEditoInput.ts +++ /dev/null @@ -1,135 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Event } from 'vs/base/common/event'; -import { URI } from 'vs/base/common/uri'; -import { localize } from 'vs/nls'; -import { IEditorInput, EditorInputCapabilities, GroupIdentifier, ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor'; -import { EditorInput } from 'vs/workbench/common/editor/editorInput'; - -/** - * Side by side editor inputs that have a primary and secondary side. - */ -export class SideBySideEditorInput extends EditorInput { - - static readonly ID: string = 'workbench.editorinputs.sidebysideEditorInput'; - - override get typeId(): string { - return SideBySideEditorInput.ID; - } - - override get capabilities(): EditorInputCapabilities { - - // Use primary capabilities as main capabilities - let capabilities = this._primary.capabilities; - - // Trust: should be considered for both sides - if (this._secondary.hasCapability(EditorInputCapabilities.RequiresTrust)) { - capabilities |= EditorInputCapabilities.RequiresTrust; - } - - // Singleton: should be considered for both sides - if (this._secondary.hasCapability(EditorInputCapabilities.Singleton)) { - capabilities |= EditorInputCapabilities.Singleton; - } - - return capabilities; - } - - get resource(): URI | undefined { - return undefined; // use `EditorResourceAccessor` to obtain one side's resource - } - - get primary(): EditorInput { - return this._primary; - } - - get secondary(): EditorInput { - return this._secondary; - } - - constructor( - protected readonly name: string | undefined, - protected readonly description: string | undefined, - private readonly _secondary: EditorInput, - private readonly _primary: EditorInput - ) { - super(); - - this.registerListeners(); - } - - private registerListeners(): void { - - // When the primary or secondary input gets disposed, dispose this diff editor input - const onceSecondaryDisposed = Event.once(this.secondary.onWillDispose); - this._register(onceSecondaryDisposed(() => { - if (!this.isDisposed()) { - this.dispose(); - } - })); - - const oncePrimaryDisposed = Event.once(this.primary.onWillDispose); - this._register(oncePrimaryDisposed(() => { - if (!this.isDisposed()) { - this.dispose(); - } - })); - - // Reemit some events from the primary side to the outside - this._register(this.primary.onDidChangeDirty(() => this._onDidChangeDirty.fire())); - this._register(this.primary.onDidChangeLabel(() => this._onDidChangeLabel.fire())); - } - - override getName(): string { - if (!this.name) { - return localize('sideBySideLabels', "{0} - {1}", this._secondary.getName(), this._primary.getName()); - } - - return this.name; - } - - override getDescription(): string | undefined { - return this.description; - } - - override getTelemetryDescriptor(): { [key: string]: unknown } { - const descriptor = this.primary.getTelemetryDescriptor(); - - return Object.assign(descriptor, super.getTelemetryDescriptor()); - } - - override isDirty(): boolean { - return this.primary.isDirty(); - } - - override isSaving(): boolean { - return this.primary.isSaving(); - } - - override save(group: GroupIdentifier, options?: ISaveOptions): Promise { - return this.primary.save(group, options); - } - - override saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { - return this.primary.saveAs(group, options); - } - - override revert(group: GroupIdentifier, options?: IRevertOptions): Promise { - return this.primary.revert(group, options); - } - - override matches(otherInput: unknown): boolean { - if (otherInput === this) { - return true; - } - - if (otherInput instanceof SideBySideEditorInput) { - return this.primary.matches(otherInput.primary) && this.secondary.matches(otherInput.secondary); - } - - return false; - } -} diff --git a/src/vs/workbench/common/editor/sideBySideEditorInput.ts b/src/vs/workbench/common/editor/sideBySideEditorInput.ts new file mode 100644 index 00000000000..716ef507077 --- /dev/null +++ b/src/vs/workbench/common/editor/sideBySideEditorInput.ts @@ -0,0 +1,223 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Event } from 'vs/base/common/event'; +import { URI } from 'vs/base/common/uri'; +import { localize } from 'vs/nls'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IEditorInput, EditorInputCapabilities, GroupIdentifier, ISaveOptions, IRevertOptions, EditorExtensions, IEditorInputFactoryRegistry, IEditorInputSerializer } from 'vs/workbench/common/editor'; +import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; +import { EditorInput } from 'vs/workbench/common/editor/editorInput'; + +/** + * Side by side editor inputs that have a primary and secondary side. + */ +export class SideBySideEditorInput extends EditorInput { + + static readonly ID: string = 'workbench.editorinputs.sidebysideEditorInput'; + + override get typeId(): string { + return SideBySideEditorInput.ID; + } + + override get capabilities(): EditorInputCapabilities { + + // Use primary capabilities as main capabilities + let capabilities = this._primary.capabilities; + + // Trust: should be considered for both sides + if (this._secondary.hasCapability(EditorInputCapabilities.RequiresTrust)) { + capabilities |= EditorInputCapabilities.RequiresTrust; + } + + // Singleton: should be considered for both sides + if (this._secondary.hasCapability(EditorInputCapabilities.Singleton)) { + capabilities |= EditorInputCapabilities.Singleton; + } + + return capabilities; + } + + get resource(): URI | undefined { + return undefined; // use `EditorResourceAccessor` to obtain one side's resource + } + + get primary(): EditorInput { + return this._primary; + } + + get secondary(): EditorInput { + return this._secondary; + } + + constructor( + protected readonly name: string | undefined, + protected readonly description: string | undefined, + private readonly _secondary: EditorInput, + private readonly _primary: EditorInput + ) { + super(); + + this.registerListeners(); + } + + private registerListeners(): void { + + // When the primary or secondary input gets disposed, dispose this diff editor input + const onceSecondaryDisposed = Event.once(this.secondary.onWillDispose); + this._register(onceSecondaryDisposed(() => { + if (!this.isDisposed()) { + this.dispose(); + } + })); + + const oncePrimaryDisposed = Event.once(this.primary.onWillDispose); + this._register(oncePrimaryDisposed(() => { + if (!this.isDisposed()) { + this.dispose(); + } + })); + + // Reemit some events from the primary side to the outside + this._register(this.primary.onDidChangeDirty(() => this._onDidChangeDirty.fire())); + this._register(this.primary.onDidChangeLabel(() => this._onDidChangeLabel.fire())); + } + + override getName(): string { + if (!this.name) { + return localize('sideBySideLabels', "{0} - {1}", this._secondary.getName(), this._primary.getName()); + } + + return this.name; + } + + override getDescription(): string | undefined { + return this.description; + } + + override getTelemetryDescriptor(): { [key: string]: unknown } { + const descriptor = this.primary.getTelemetryDescriptor(); + + return Object.assign(descriptor, super.getTelemetryDescriptor()); + } + + override isDirty(): boolean { + return this.primary.isDirty(); + } + + override isSaving(): boolean { + return this.primary.isSaving(); + } + + override save(group: GroupIdentifier, options?: ISaveOptions): Promise { + return this.primary.save(group, options); + } + + override saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { + return this.primary.saveAs(group, options); + } + + override revert(group: GroupIdentifier, options?: IRevertOptions): Promise { + return this.primary.revert(group, options); + } + + override matches(otherInput: unknown): boolean { + if (otherInput === this) { + return true; + } + + if (otherInput instanceof SideBySideEditorInput) { + return this.primary.matches(otherInput.primary) && this.secondary.matches(otherInput.secondary); + } + + return false; + } +} + +// Register SideBySide/DiffEditor Input Serializer +interface ISerializedSideBySideEditorInput { + name: string; + description: string | undefined; + + primarySerialized: string; + secondarySerialized: string; + + primaryTypeId: string; + secondaryTypeId: string; +} + +export abstract class AbstractSideBySideEditorInputSerializer implements IEditorInputSerializer { + + private getInputSerializers(secondaryEditorInputTypeId: string, primaryEditorInputTypeId: string): [IEditorInputSerializer | undefined, IEditorInputSerializer | undefined] { + const registry = Registry.as(EditorExtensions.EditorInputFactories); + + return [registry.getEditorInputSerializer(secondaryEditorInputTypeId), registry.getEditorInputSerializer(primaryEditorInputTypeId)]; + } + + canSerialize(editorInput: EditorInput): boolean { + const input = editorInput as SideBySideEditorInput | DiffEditorInput; + + if (input.primary && input.secondary) { + const [secondaryInputSerializer, primaryInputSerializer] = this.getInputSerializers(input.secondary.typeId, input.primary.typeId); + + return !!(secondaryInputSerializer?.canSerialize(input.secondary) && primaryInputSerializer?.canSerialize(input.primary)); + } + + return false; + } + + serialize(editorInput: EditorInput): string | undefined { + const input = editorInput as SideBySideEditorInput; + + if (input.primary && input.secondary) { + const [secondaryInputSerializer, primaryInputSerializer] = this.getInputSerializers(input.secondary.typeId, input.primary.typeId); + if (primaryInputSerializer && secondaryInputSerializer) { + const primarySerialized = primaryInputSerializer.serialize(input.primary); + const secondarySerialized = secondaryInputSerializer.serialize(input.secondary); + + if (primarySerialized && secondarySerialized) { + const serializedEditorInput: ISerializedSideBySideEditorInput = { + name: input.getName(), + description: input.getDescription(), + primarySerialized: primarySerialized, + secondarySerialized: secondarySerialized, + primaryTypeId: input.primary.typeId, + secondaryTypeId: input.secondary.typeId + }; + + return JSON.stringify(serializedEditorInput); + } + } + } + + return undefined; + } + + deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput | undefined { + const deserialized: ISerializedSideBySideEditorInput = JSON.parse(serializedEditorInput); + + const [secondaryInputSerializer, primaryInputSerializer] = this.getInputSerializers(deserialized.secondaryTypeId, deserialized.primaryTypeId); + if (primaryInputSerializer && secondaryInputSerializer) { + const primaryInput = primaryInputSerializer.deserialize(instantiationService, deserialized.primarySerialized); + const secondaryInput = secondaryInputSerializer.deserialize(instantiationService, deserialized.secondarySerialized); + + if (primaryInput && secondaryInput) { + return this.createEditorInput(instantiationService, deserialized.name, deserialized.description, secondaryInput, primaryInput); + } + } + + return undefined; + } + + protected abstract createEditorInput(instantiationService: IInstantiationService, name: string, description: string | undefined, secondaryInput: EditorInput, primaryInput: EditorInput): EditorInput; +} + +export class SideBySideEditorInputSerializer extends AbstractSideBySideEditorInputSerializer { + + protected createEditorInput(instantiationService: IInstantiationService, name: string, description: string | undefined, secondaryInput: EditorInput, primaryInput: EditorInput): EditorInput { + return new SideBySideEditorInput(name, description, secondaryInput, primaryInput); + } +} diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index 48743323723..2a378027973 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; import { EditorResourceAccessor, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason, EditorsOrder, EditorInputCapabilities } from 'vs/workbench/common/editor'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; diff --git a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts index fa2a6e88116..333ce5c90c0 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts @@ -24,7 +24,6 @@ import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/p import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands'; import { RemoteNameContext, WorkbenchStateContext } from 'vs/workbench/browser/contextkeys'; import { EditorDescriptor, IEditorRegistry } from 'vs/workbench/browser/editor'; -import { AbstractSideBySideEditorInputSerializer } from 'vs/workbench/browser/parts/editor/editor.contribution'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; import { ResourceContextKey } from 'vs/workbench/common/resources'; @@ -43,6 +42,7 @@ import { DefaultPreferencesEditorInput, PreferencesEditorInput, SettingsEditor2I import { preferencesOpenSettingsIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; import { KeybindingsEditorInput } from 'vs/workbench/services/preferences/browser/keybindingsEditorInput'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; +import { AbstractSideBySideEditorInputSerializer } from 'vs/workbench/common/editor/sideBySideEditorInput'; const SETTINGS_EDITOR_COMMAND_SEARCH = 'settings.action.search'; diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index cae07c689b3..641c11097cb 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -7,7 +7,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IResourceEditorInput, ITextEditorOptions, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, TextEditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { Registry } from 'vs/platform/registry/common/platform'; import { ResourceMap } from 'vs/base/common/map'; diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index 08b04c5a3fe..8ce795464cb 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -33,7 +33,7 @@ import { MockScopableContextKeyService } from 'vs/platform/keybinding/test/commo import { ContributedEditorPriority } from 'vs/workbench/services/editor/common/editorOverrideService'; import { IWorkspaceTrustRequestService, WorkspaceTrustUriResponse } from 'vs/platform/workspace/common/workspaceTrust'; import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; suite('EditorService', () => { diff --git a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts index 36ea958e8c4..e911c950310 100644 --- a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts @@ -17,7 +17,7 @@ import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { EditorsObserver } from 'vs/workbench/browser/parts/editor/editorsObserver'; import { timeout } from 'vs/base/common/async'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; suite('EditorsObserver', function () { diff --git a/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts index a0acb9d3b77..b9da41ef675 100644 --- a/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts +++ b/src/vs/workbench/services/preferences/common/preferencesEditorInput.ts @@ -11,7 +11,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { ILabelService } from 'vs/platform/label/common/label'; import { Verbosity } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; diff --git a/src/vs/workbench/test/browser/parts/editor/editor.test.ts b/src/vs/workbench/test/browser/parts/editor/editor.test.ts index c39a6f18ee7..5d3dd7530a3 100644 --- a/src/vs/workbench/test/browser/parts/editor/editor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editor.test.ts @@ -18,7 +18,7 @@ import { whenEditorClosed } from 'vs/workbench/browser/editor'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { EditorService } from 'vs/workbench/services/editor/browser/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; suite('Workbench editor', () => { diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 0ed3e95bcbb..8a6f871e07c 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -140,7 +140,7 @@ import { BrowserElevatedFileService } from 'vs/workbench/services/files/browser/ import { IDiffComputationResult, IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService'; import { TextEdit, IInplaceReplaceSupportResult } from 'vs/editor/common/modes'; import { ResourceMap } from 'vs/base/common/map'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditoInput'; +import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; export function createFileEditorInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput { return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined, undefined, undefined, undefined); From 64b0c65b8cb7e851d6b188f5cb77823d314b0de5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 15:57:02 +0200 Subject: [PATCH 047/140] editors - fix cyclic dependencies --- src/vs/workbench/common/editor.ts | 39 +++++++++++++++---- .../common/editor/editorGroupModel.ts | 5 ++- .../common/editor/sideBySideEditorInput.ts | 6 +-- .../services/editor/browser/editorService.ts | 2 +- .../services/history/browser/history.ts | 2 +- 5 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 7a1ab14dca1..52a7127f95a 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -22,8 +22,6 @@ import { coalesce } from 'vs/base/common/arrays'; import { ACTIVE_GROUP, IResourceEditorInputType, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IRange } from 'vs/editor/common/core/range'; import { IExtUri } from 'vs/base/common/resources'; -import { EditorInput } from 'vs/workbench/common/editor/editorInput'; -import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; // Static values for editor contributions export const EditorExtensions = { @@ -275,7 +273,7 @@ export interface IEditorInputSerializer { * Returns an editor input from the provided serialized form of the editor input. This form matches * the value returned from the serialize() method. */ - deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput | undefined; + deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): IEditorInput | undefined; } export interface IUntitledTextResourceEditorInput extends IBaseResourceEditorInput { @@ -389,7 +387,7 @@ export interface IRevertOptions { } export interface IMoveResult { - editor: EditorInput | IResourceEditorInputType; + editor: IEditorInput | IResourceEditorInputType; options?: IEditorOptions; } @@ -595,9 +593,34 @@ export interface IEditorInputWithPreferredResource { } export function isEditorInputWithPreferredResource(obj: unknown): obj is IEditorInputWithPreferredResource { - const editorInputWithPreferredResource = obj as IEditorInputWithPreferredResource; + const editorInputWithPreferredResource = obj as IEditorInputWithPreferredResource | undefined; + if (!editorInputWithPreferredResource) { + return false; + } - return editorInputWithPreferredResource && !!editorInputWithPreferredResource.preferredResource; + return URI.isUri(editorInputWithPreferredResource.preferredResource); +} + +export interface ISideBySideEditorInput extends IEditorInput { + + /** + * The primary editor input is shown on the right hand side. + */ + primary: IEditorInput; + + /** + * The secondary editor input is shown on the left hand side. + */ + secondary: IEditorInput; +} + +function isSideBySideEditorInput(obj: unknown): obj is ISideBySideEditorInput { + const sideBySideEditorInput = obj as ISideBySideEditorInput | undefined; + if (!sideBySideEditorInput) { + return false; + } + + return !!sideBySideEditorInput.primary && !!sideBySideEditorInput.secondary; } /** @@ -1110,7 +1133,7 @@ class EditorResourceAccessorImpl { } // Optionally support side-by-side editors - if (options?.supportSideBySide && editor instanceof SideBySideEditorInput) { + if (options?.supportSideBySide && isSideBySideEditorInput(editor)) { if (options?.supportSideBySide === SideBySideEditor.BOTH) { return { primary: this.getOriginalUri(editor.primary, { filterByScheme: options.filterByScheme }), @@ -1152,7 +1175,7 @@ class EditorResourceAccessorImpl { } // Optionally support side-by-side editors - if (options?.supportSideBySide && editor instanceof SideBySideEditorInput) { + if (options?.supportSideBySide && isSideBySideEditorInput(editor)) { if (options?.supportSideBySide === SideBySideEditor.BOTH) { return { primary: this.getCanonicalUri(editor.primary, { filterByScheme: options.filterByScheme }), diff --git a/src/vs/workbench/common/editor/editorGroupModel.ts b/src/vs/workbench/common/editor/editorGroupModel.ts index b953f0f0d7a..bb835b762b0 100644 --- a/src/vs/workbench/common/editor/editorGroupModel.ts +++ b/src/vs/workbench/common/editor/editorGroupModel.ts @@ -812,8 +812,9 @@ export class EditorGroupModel extends Disposable { const editorSerializer = registry.getEditorInputSerializer(e.id); if (editorSerializer) { - editor = editorSerializer.deserialize(this.instantiationService, e.value); - if (editor) { + const deserializedEditor = editorSerializer.deserialize(this.instantiationService, e.value); + if (deserializedEditor instanceof EditorInput) { + editor = deserializedEditor; this.registerEditorListeners(editor); } } diff --git a/src/vs/workbench/common/editor/sideBySideEditorInput.ts b/src/vs/workbench/common/editor/sideBySideEditorInput.ts index 716ef507077..edd8cc12d74 100644 --- a/src/vs/workbench/common/editor/sideBySideEditorInput.ts +++ b/src/vs/workbench/common/editor/sideBySideEditorInput.ts @@ -8,14 +8,14 @@ import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IEditorInput, EditorInputCapabilities, GroupIdentifier, ISaveOptions, IRevertOptions, EditorExtensions, IEditorInputFactoryRegistry, IEditorInputSerializer } from 'vs/workbench/common/editor'; +import { IEditorInput, EditorInputCapabilities, GroupIdentifier, ISaveOptions, IRevertOptions, EditorExtensions, IEditorInputFactoryRegistry, IEditorInputSerializer, ISideBySideEditorInput } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; /** * Side by side editor inputs that have a primary and secondary side. */ -export class SideBySideEditorInput extends EditorInput { +export class SideBySideEditorInput extends EditorInput implements ISideBySideEditorInput { static readonly ID: string = 'workbench.editorinputs.sidebysideEditorInput'; @@ -204,7 +204,7 @@ export abstract class AbstractSideBySideEditorInputSerializer implements IEditor const primaryInput = primaryInputSerializer.deserialize(instantiationService, deserialized.primarySerialized); const secondaryInput = secondaryInputSerializer.deserialize(instantiationService, deserialized.secondarySerialized); - if (primaryInput && secondaryInput) { + if (primaryInput instanceof EditorInput && secondaryInput instanceof EditorInput) { return this.createEditorInput(instantiationService, deserialized.name, deserialized.description, secondaryInput, primaryInput); } } diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 641c11097cb..fc32bdb9d8f 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -308,7 +308,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { replacement: { ...moveResult.editor, options: { - ...moveResult.editor.options, + ...(moveResult.editor as IResourceEditorInputType).options, ...optionOverrides } } diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index b76509ac97c..d1094108c8c 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -1012,7 +1012,7 @@ export class HistoryService extends Disposable implements IHistoryService { const editorSerializer = this.editorInputFactory.getEditorInputSerializer(editorInputJSON.typeId); if (editorSerializer) { const input = editorSerializer.deserialize(this.instantiationService, editorInputJSON.deserialized); - if (input) { + if (input instanceof EditorInput) { this.onEditorDispose(input, () => this.removeFromHistory(input), this.editorHistoryListeners); } From afc2b0627035649eddb9a17defdcf883d4edb07d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 16:03:06 +0200 Subject: [PATCH 048/140] editors - start to remove typed editor options (notebooks, search) --- .../api/browser/mainThreadNotebookEditors.ts | 8 ++-- .../browser/parts/editor/editorPane.ts | 9 +++-- .../contrib/undoRedo/notebookUndoRedo.ts | 6 +-- .../notebook/browser/notebookBrowser.ts | 21 ++--------- .../notebook/browser/notebookEditor.ts | 12 +++--- .../notebook/browser/notebookEditorWidget.ts | 4 +- .../notebook/browser/notebookServiceImpl.ts | 6 +-- .../preferences/browser/preferencesEditor.ts | 10 ++--- .../preferences/browser/settingsEditor2.ts | 10 ++--- .../preferences/browser/preferencesService.ts | 10 ++--- .../preferences/common/preferences.ts | 37 ++++--------------- .../test/browser/preferencesService.test.ts | 10 +---- 12 files changed, 51 insertions(+), 92 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebookEditors.ts b/src/vs/workbench/api/browser/mainThreadNotebookEditors.ts index a8ca5a5ac46..704b1c392b1 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebookEditors.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebookEditors.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { DisposableStore, dispose } from 'vs/base/common/lifecycle'; -import { getNotebookEditorFromEditorPane, INotebookEditor, NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { getNotebookEditorFromEditorPane, INotebookEditor, INotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService'; import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookDocumentShowOptions, INotebookEditorViewColumnInfo, MainThreadNotebookEditorsShape, NotebookEditorRevealType } from '../common/extHost.protocol'; import { MainThreadNotebooksAndEditors } from 'vs/workbench/api/browser/mainThreadNotebookDocumentsAndEditors'; @@ -124,7 +124,7 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape async $tryShowNotebookDocument(resource: UriComponents, viewType: string, options: INotebookDocumentShowOptions): Promise { - const editorOptions = new NotebookEditorOptions({ + const editorOptions: INotebookEditorOptions = { cellSelections: options.selections, preserveFocus: options.preserveFocus, pinned: options.pinned, @@ -132,8 +132,8 @@ export class MainThreadNotebookEditors implements MainThreadNotebookEditorsShape // preserve pre 1.38 behaviour to not make group active when preserveFocus: true // but make sure to restore the editor to fix https://github.com/microsoft/vscode/issues/79633 activation: options.preserveFocus ? EditorActivation.RESTORE : undefined, - override: EditorOverride.DISABLED, - }); + override: EditorOverride.DISABLED + }; const input = NotebookEditorInput.create(this._instantiationService, URI.revive(resource), viewType); const editorPane = await this._editorService.openEditor(input, editorOptions, options.position); diff --git a/src/vs/workbench/browser/parts/editor/editorPane.ts b/src/vs/workbench/browser/parts/editor/editorPane.ts index 8928712c164..cd44c9851f8 100644 --- a/src/vs/workbench/browser/parts/editor/editorPane.ts +++ b/src/vs/workbench/browser/parts/editor/editorPane.ts @@ -21,6 +21,7 @@ import { joinPath, IExtUri, isEqual } from 'vs/base/common/resources'; import { indexOfPath } from 'vs/base/common/extpath'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; /** * The base class of editors in the workbench. Editors register themselves for specific editor inputs. @@ -103,9 +104,9 @@ export abstract class EditorPane extends Composite implements IEditorPane { * The provided cancellation token should be used to test if the operation * was cancelled. */ - async setInput(input: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + async setInput(input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { this._input = input; - this._options = options; + this._options = options as EditorOptions; } /** @@ -130,8 +131,8 @@ export abstract class EditorPane extends Composite implements IEditorPane { * Sets the given options to the editor. Clients should apply the options * to the current input. */ - setOptions(options: EditorOptions | undefined): void { - this._options = options; + setOptions(options: IEditorOptions | undefined): void { + this._options = options as EditorOptions; } override setVisible(visible: boolean, group?: IEditorGroup): void { diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/undoRedo/notebookUndoRedo.ts b/src/vs/workbench/contrib/notebook/browser/contrib/undoRedo/notebookUndoRedo.ts index 049ee309239..c2e5a97057e 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/undoRedo/notebookUndoRedo.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/undoRedo/notebookUndoRedo.ts @@ -9,7 +9,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { CellEditState, getNotebookEditorFromEditorPane, NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, getNotebookEditorFromEditorPane } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions'; class NotebookUndoRedoContribution extends Disposable { @@ -29,7 +29,7 @@ class NotebookUndoRedoContribution extends Disposable { } }); - editor?.setOptions(new NotebookEditorOptions({ cellOptions: { resource: cellResources[0] }, preserveFocus: true })); + editor?.setOptions({ cellOptions: { resource: cellResources[0] }, preserveFocus: true }); } }); } @@ -48,7 +48,7 @@ class NotebookUndoRedoContribution extends Disposable { } }); - editor?.setOptions(new NotebookEditorOptions({ cellOptions: { resource: cellResources[0] }, preserveFocus: true })); + editor?.setOptions({ cellOptions: { resource: cellResources[0] }, preserveFocus: true }); } }); } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index d99af644b75..9189bc2ee09 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -26,8 +26,8 @@ import { ICellRange, cellRangesToIndexes, reduceRanges } from 'vs/workbench/cont import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { IMenu } from 'vs/platform/actions/common/actions'; -import { EditorOptions, IEditorPane } from 'vs/workbench/common/editor'; -import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { IEditorPane } from 'vs/workbench/common/editor'; +import { IEditorOptions, IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation'; import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { INotebookWebviewMessage } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView'; @@ -320,23 +320,10 @@ export interface INotebookDeltaCellStatusBarItems { items: INotebookCellStatusBarItem[]; } -export class NotebookEditorOptions extends EditorOptions { - +export interface INotebookEditorOptions extends IEditorOptions { readonly cellOptions?: IResourceEditorInput; readonly cellSelections?: ICellRange[]; readonly isReadOnly?: boolean; - - constructor(options: Partial) { - super(); - this.overwrite(options); - this.cellOptions = options.cellOptions; - this.cellSelections = options.cellSelections; - this.isReadOnly = options.isReadOnly; - } - - with(options: Partial): NotebookEditorOptions { - return new NotebookEditorOptions({ ...this, ...options }); - } } export type INotebookEditorContributionCtor = IConstructorSignature1; @@ -406,7 +393,7 @@ export interface INotebookEditor extends ICommonNotebookEditor { hasWebviewFocus(): boolean; hasOutputTextSelection(): boolean; - setOptions(options: NotebookEditorOptions | undefined): Promise; + setOptions(options: INotebookEditorOptions | undefined): Promise; /** * Select & focus cell diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 6771e6f2738..b0000fdcc15 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -25,7 +25,7 @@ import { INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contri import { IEditorDropService } from 'vs/workbench/services/editor/browser/editorDropService'; import { IEditorGroup, IEditorGroupsService, GroupsOrder } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { NotebookEditorOptions, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookEditorOptions, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { IBorrowValue, INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService'; import { clearMarks, getAndClearMarks, mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; import { IFileService } from 'vs/platform/files/common/files'; @@ -75,7 +75,7 @@ export class NotebookEditor extends EditorPane { private onDidFileSystemProviderChange(scheme: string): void { if (this.input?.resource?.scheme === scheme && this._widget.value) { - this._widget.value.setOptions(new NotebookEditorOptions({ isReadOnly: this.input.hasCapability(EditorInputCapabilities.Readonly) })); + this._widget.value.setOptions({ isReadOnly: this.input.hasCapability(EditorInputCapabilities.Readonly) }); } } @@ -206,7 +206,7 @@ export class NotebookEditor extends EditorPane { this._widget.value?.setParentContextKeyService(this._contextKeyService); await this._widget.value!.setModel(model.notebook, viewState); const isReadOnly = input.hasCapability(EditorInputCapabilities.Readonly); - await this._widget.value!.setOptions(options instanceof NotebookEditorOptions ? options.with({ isReadOnly }) : new NotebookEditorOptions({ isReadOnly })); + await this._widget.value!.setOptions({ ...options, isReadOnly }); this._widgetDisposableStore.add(this._widget.value!.onDidFocus(() => this._onDidFocusWidget.fire())); this._widgetDisposableStore.add(this._editorDropService.createEditorDropTarget(this._widget.value!.getDomNode(), { @@ -277,10 +277,8 @@ export class NotebookEditor extends EditorPane { super.clearInput(); } - override setOptions(options: EditorOptions | undefined): void { - if (options instanceof NotebookEditorOptions) { - this._widget.value?.setOptions(options); - } + override setOptions(options: INotebookEditorOptions | undefined): void { + this._widget.value?.setOptions(options); super.setOptions(options); } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 49e1d98cf4c..425ada950d4 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -42,7 +42,7 @@ import { IEditorMemento } from 'vs/workbench/common/editor'; import { Memento, MementoObject } from 'vs/workbench/common/memento'; import { PANEL_BORDER } from 'vs/workbench/common/theme'; import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugColors'; -import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellOutputViewModel, ICellViewModel, ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IFocusNotebookCellOptions, IGenericCellViewModel, IInsetRenderOutput, INotebookCellList, INotebookCellOutputLayoutInfo, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_ID, NOTEBOOK_OUTPUT_FOCUSED, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellOutputViewModel, ICellViewModel, ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IFocusNotebookCellOptions, IGenericCellViewModel, IInsetRenderOutput, INotebookCellList, INotebookCellOutputLayoutInfo, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, INotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_ID, NOTEBOOK_OUTPUT_FOCUSED, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookDecorationCSSRules, NotebookRefCountedStyleSheet } from 'vs/workbench/contrib/notebook/browser/notebookEditorDecorations'; import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; import { NotebookEditorKernelManager } from 'vs/workbench/contrib/notebook/browser/notebookEditorKernelManager'; @@ -1021,7 +1021,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } } - async setOptions(options: NotebookEditorOptions | undefined) { + async setOptions(options: INotebookEditorOptions | undefined) { if (!this.hasModel()) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 90c4f8bc43e..ec4cc2a1859 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -28,7 +28,7 @@ import { IEditorInput } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { Memento } from 'vs/workbench/common/memento'; import { INotebookEditorContribution, notebooksExtensionPoint, notebookRendererExtensionPoint } from 'vs/workbench/contrib/notebook/browser/extensionPoint'; -import { NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; @@ -148,10 +148,10 @@ export class NotebookProviderInfoStore extends Disposable { if (data) { notebookUri = data.notebook; - cellOptions = { resource: resource, options: options }; + cellOptions = { resource, options }; } - const notebookOptions = new NotebookEditorOptions({ ...options, cellOptions }); + const notebookOptions: INotebookEditorOptions = { ...options, cellOptions }; return { editor: NotebookEditorInput.create(this._instantiationService, notebookUri, notebookProviderInfo.id), options: notebookOptions }; }; const notebookEditorDiffFactory: DiffEditorInputFactoryFunction = (diffEditorInput: DiffEditorInput, options, group) => { diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts index a8a3874f73a..569ddbc0665 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts @@ -49,7 +49,7 @@ import { SearchWidget, SettingsTarget, SettingsTargetsWidget } from 'vs/workbenc import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, IPreferencesSearchService, ISearchProvider } from 'vs/workbench/contrib/preferences/common/preferences'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { IFilterResult, IPreferencesService, ISetting, ISettingsEditorModel, ISettingsGroup, SettingsEditorOptions } from 'vs/workbench/services/preferences/common/preferences'; +import { IFilterResult, IPreferencesService, ISetting, ISettingsEditorModel, ISettingsEditorOptions, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences'; import { DefaultPreferencesEditorInput, PreferencesEditorInput } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; import { DefaultSettingsEditorModel, SettingsEditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; @@ -152,7 +152,7 @@ export class PreferencesEditor extends EditorPane { this.preferencesRenderers.editFocusedPreference(); } - override setInput(input: PreferencesEditorInput, options: SettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override setInput(input: PreferencesEditorInput, options: ISettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { this.defaultSettingsEditorContextKey.set(true); this.defaultSettingsJSONEditorContextKey.set(true); if (options && options.query) { @@ -205,7 +205,7 @@ export class PreferencesEditor extends EditorPane { super.setEditorVisible(visible, group); } - private updateInput(newInput: PreferencesEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + private updateInput(newInput: PreferencesEditorInput, options: ISettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { return this.sideBySidePreferencesWidget.setInput(newInput.secondary, newInput.primary, options, context, token).then(({ defaultPreferencesRenderer, editablePreferencesRenderer }) => { if (token.isCancellationRequested) { return; @@ -834,7 +834,7 @@ class SideBySidePreferencesWidget extends Widget { this._register(focusTracker.onDidFocus(() => this._onFocus.fire())); } - setInput(defaultPreferencesEditorInput: DefaultPreferencesEditorInput, editablePreferencesEditorInput: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<{ defaultPreferencesRenderer?: IPreferencesRenderer, editablePreferencesRenderer?: IPreferencesRenderer; }> { + setInput(defaultPreferencesEditorInput: DefaultPreferencesEditorInput, editablePreferencesEditorInput: EditorInput, options: ISettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<{ defaultPreferencesRenderer?: IPreferencesRenderer, editablePreferencesRenderer?: IPreferencesRenderer; }> { this.getOrCreateEditablePreferencesEditor(editablePreferencesEditorInput); this.settingsTargetsWidget.settingsTarget = this.getSettingsTarget(editablePreferencesEditorInput.resource!); return Promise.all([ @@ -917,7 +917,7 @@ class SideBySidePreferencesWidget extends Widget { return editor; } - private async updateInput(editor: EditorPane, input: EditorInput, editorContributionId: string, associatedPreferencesModelUri: URI, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise | undefined> { + private async updateInput(editor: EditorPane, input: EditorInput, editorContributionId: string, associatedPreferencesModelUri: URI, options: ISettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise | undefined> { await editor.setInput(input, options, context, token); if (token.isCancellationRequested) { diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 1657bc1f187..b90f83fc53b 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -47,7 +47,7 @@ import { settingsTextInputBorder } from 'vs/workbench/contrib/preferences/browse import { createTOCIterator, TOCTree, TOCTreeModel } from 'vs/workbench/contrib/preferences/browser/tocTree'; import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_ROW_FOCUS, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, EXTENSION_SETTING_TAG, FEATURE_SETTING_TAG, ID_SETTING_TAG, IPreferencesSearchService, ISearchProvider, MODIFIED_SETTING_TAG, REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS } from 'vs/workbench/contrib/preferences/common/preferences'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { IPreferencesService, ISearchResult, ISettingsEditorModel, ISettingsEditorOptions, SettingsEditorOptions, SettingValueType } from 'vs/workbench/services/preferences/common/preferences'; +import { validateSettingsEditorOptions, IPreferencesService, ISearchResult, ISettingsEditorModel, ISettingsEditorOptions, SettingValueType } from 'vs/workbench/services/preferences/common/preferences'; import { SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; import { Settings2EditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { IUserDataSyncWorkbenchService } from 'vs/workbench/services/userDataSync/common/userDataSync'; @@ -269,7 +269,7 @@ export class SettingsEditor2 extends EditorPane { this.updateStyles(); } - override async setInput(input: SettingsEditor2Input, options: SettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: SettingsEditor2Input, options: ISettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { this.inSettingsEditorContextKey.set(true); await super.setInput(input, options, context, token); await timeout(0); // Force setInput to be async @@ -290,7 +290,7 @@ export class SettingsEditor2 extends EditorPane { })); this.defaultSettingsEditorModel = model; - options = options || SettingsEditorOptions.create({}); + options = options || validateSettingsEditorOptions({}); if (!this.viewState.settingsTarget) { if (!options.target) { options.target = ConfigurationTarget.USER_LOCAL; @@ -329,7 +329,7 @@ export class SettingsEditor2 extends EditorPane { return withUndefinedAsNull(cachedState); } - override setOptions(options: SettingsEditorOptions | undefined): void { + override setOptions(options: ISettingsEditorOptions | undefined): void { super.setOptions(options); if (options) { @@ -337,7 +337,7 @@ export class SettingsEditor2 extends EditorPane { } } - private _setOptions(options: SettingsEditorOptions): void { + private _setOptions(options: ISettingsEditorOptions): void { if (options.focusSearch && !platform.isIOS) { // isIOS - #122044 this.focusSearch(); diff --git a/src/vs/workbench/services/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts index 6747f7b32ff..23b4928b03c 100644 --- a/src/vs/workbench/services/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -28,7 +28,7 @@ import { IEditorInput, IEditorPane } from 'vs/workbench/common/editor'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { GroupDirection, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { DEFAULT_SETTINGS_EDITOR_SETTING, FOLDER_SETTINGS_PATH, getSettingsTargetName, IKeybindingsEditorOptions, IKeybindingsEditorPane, IPreferencesEditorModel, IPreferencesService, ISetting, ISettingsEditorOptions, SettingsEditorOptions, USE_SPLIT_JSON_SETTING } from 'vs/workbench/services/preferences/common/preferences'; +import { validateSettingsEditorOptions, DEFAULT_SETTINGS_EDITOR_SETTING, FOLDER_SETTINGS_PATH, getSettingsTargetName, IKeybindingsEditorOptions, IKeybindingsEditorPane, IPreferencesEditorModel, IPreferencesService, ISetting, ISettingsEditorOptions, USE_SPLIT_JSON_SETTING } from 'vs/workbench/services/preferences/common/preferences'; import { DefaultPreferencesEditorInput, PreferencesEditorInput, SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput'; import { defaultKeybindingsContents, DefaultKeybindingsEditorModel, DefaultSettings, DefaultSettingsEditorModel, Settings2EditorModel, SettingsEditorModel, WorkspaceConfigurationEditorModel, DefaultRawSettingsEditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; @@ -223,7 +223,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic ...options, focusSearch: true }; - return this.editorService.openEditor(input, options ? SettingsEditorOptions.create(options) : { override: EditorOverride.DISABLED }) + return this.editorService.openEditor(input, validateSettingsEditorOptions(options)) .then(() => this.editorGroupService.activeGroup.activeEditorPane!); } @@ -379,7 +379,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic this.editorService.openEditor(editableSettingsEditorInput, { pinned: true, revealIfOpened: true, override: EditorOverride.DISABLED }, sideEditorGroup.id) ]).then(([defaultEditor, editor]) => withNullAsUndefined(editor)); } else { - return this.editorService.openEditor(editableSettingsEditorInput, SettingsEditorOptions.create(options), group); + return this.editorService.openEditor(editableSettingsEditorInput, validateSettingsEditorOptions(options), group); } }); } @@ -393,7 +393,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic options = { ...options, pinned: true }; } - return this.editorService.openEditor(preferencesEditorInput, SettingsEditorOptions.create(options), group); + return this.editorService.openEditor(preferencesEditorInput, validateSettingsEditorOptions(options), group); } private createSplitJsonEditorInput(configurationTarget: ConfigurationTarget, resource: URI, editableSettingsEditorInput: IEditorInput): IEditorInput { @@ -421,7 +421,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic return group.replaceEditors([{ editor: input, replacement: replaceWith, - options: options ? SettingsEditorOptions.create(options) : undefined + options: validateSettingsEditorOptions(options ?? {}) }]).then(() => { this.lastOpenedSettingsInput = replaceWith; return group.activeEditorPane!; diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts index 842dc51a00d..819726c5a00 100644 --- a/src/vs/workbench/services/preferences/common/preferences.ts +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -15,7 +15,7 @@ import { ConfigurationScope, IConfigurationExtensionInfo } from 'vs/platform/con import { EditorOverride, IEditorOptions } from 'vs/platform/editor/common/editor'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { EditorOptions, IEditorInput, IEditorPane } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorPane } from 'vs/workbench/common/editor'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { Settings2EditorModel } from 'vs/workbench/services/preferences/common/preferencesModels'; import { IMatch } from 'vs/base/common/filters'; @@ -173,36 +173,15 @@ export interface ISettingsEditorOptions extends IEditorOptions { focusSearch?: boolean; } -export class SettingsEditorOptions extends EditorOptions implements ISettingsEditorOptions { +export function validateSettingsEditorOptions(options: ISettingsEditorOptions): ISettingsEditorOptions { + return { + // Inherit provided options + ...options, - target?: ConfigurationTarget; - folderUri?: URI; - query?: string; - revealSetting?: { - key: string; - edit?: boolean; + // Enforce some options for settings specifically + override: EditorOverride.DISABLED, + pinned: true }; - focusSearch?: boolean; - - static override create(options: ISettingsEditorOptions): SettingsEditorOptions { - const newOptions = new SettingsEditorOptions(); - options = { - ...{ - override: EditorOverride.DISABLED, - pinned: true - }, - ...options - }; - newOptions.overwrite(options); - - newOptions.target = options.target; - newOptions.folderUri = options.folderUri; - newOptions.query = options.query; - newOptions.revealSetting = options.revealSetting; - newOptions.focusSearch = options.focusSearch; - - return newOptions; - } } export interface IKeybindingsEditorModel extends IPreferencesEditorModel { diff --git a/src/vs/workbench/services/preferences/test/browser/preferencesService.test.ts b/src/vs/workbench/services/preferences/test/browser/preferencesService.test.ts index 25c4bba9feb..705b06ccfbe 100644 --- a/src/vs/workbench/services/preferences/test/browser/preferencesService.test.ts +++ b/src/vs/workbench/services/preferences/test/browser/preferencesService.test.ts @@ -12,7 +12,7 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { TestJSONEditingService } from 'vs/workbench/services/configuration/test/common/testServices'; import { PreferencesService } from 'vs/workbench/services/preferences/browser/preferencesService'; -import { IPreferencesService, SettingsEditorOptions } from 'vs/workbench/services/preferences/common/preferences'; +import { IPreferencesService, ISettingsEditorOptions } from 'vs/workbench/services/preferences/common/preferences'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { TestRemoteAgentService } from 'vs/workbench/services/remote/test/common/testServices'; import { ITestInstantiationService, TestEditorService, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices'; @@ -40,15 +40,9 @@ suite('PreferencesService', () => { testObject = instantiationService.createInstance(PreferencesService); }); - test('openEditor is called with a SettingsEditorOptions instance', async () => { - testObject.openSettings(false, undefined); - const options = editorService.lastOpenEditorOptions as SettingsEditorOptions; - assert.strictEqual(options instanceof SettingsEditorOptions, true); - }); - test('options are preserved when calling openEditor', async () => { testObject.openSettings(false, 'test query'); - const options = editorService.lastOpenEditorOptions as SettingsEditorOptions; + const options = editorService.lastOpenEditorOptions as ISettingsEditorOptions; assert.strictEqual(options.focusSearch, true); assert.strictEqual(options.override, EditorOverride.DISABLED); assert.strictEqual(options.query, 'test query'); From b6551f8e4e34ea618665706df713a9346b9d41d5 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Tue, 25 May 2021 16:06:47 +0200 Subject: [PATCH 049/140] Workspace trust - no need to call setWorkspaceTrust (#124566) --- .../extensions/electron-browser/extensionService.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 67d5ce01398..1af959c4012 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -42,7 +42,6 @@ import { Schemas } from 'vs/base/common/network'; import { ExtensionHostExitCode } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; import { updateProxyConfigurationsScope } from 'vs/platform/request/common/request'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; -import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService'; export class ExtensionService extends AbstractExtensionService implements IExtensionService { @@ -71,7 +70,6 @@ export class ExtensionService extends AbstractExtensionService implements IExten @IRemoteExplorerService private readonly _remoteExplorerService: IRemoteExplorerService, @IExtensionGalleryService private readonly _extensionGalleryService: IExtensionGalleryService, @ILogService private readonly _logService: ILogService, - @IWorkspaceTrustManagementService private readonly _workspaceTrustManagementService: IWorkspaceTrustManagementService, @IExtensionManifestPropertiesService extensionManifestPropertiesService: IExtensionManifestPropertiesService, ) { super( @@ -373,10 +371,6 @@ export class ExtensionService extends AbstractExtensionService implements IExten return; } - if (resolverResult.options?.isTrusted) { - await this._workspaceTrustManagementService.setWorkspaceTrust(true); - } - // set the resolved authority this._remoteAuthorityResolverService._setResolvedAuthority(resolverResult.authority, resolverResult.options); this._remoteExplorerService.setTunnelInformation(resolverResult.tunnelInformation); From d4307f8d53491847061103ebb2dfdf24ca074679 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 25 May 2021 12:14:48 +0200 Subject: [PATCH 050/140] missing validation for top-level token color object --- src/vs/workbench/services/themes/common/themeConfiguration.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/services/themes/common/themeConfiguration.ts b/src/vs/workbench/services/themes/common/themeConfiguration.ts index 102b4307863..3b83103b21d 100644 --- a/src/vs/workbench/services/themes/common/themeConfiguration.ts +++ b/src/vs/workbench/services/themes/common/themeConfiguration.ts @@ -145,6 +145,7 @@ function tokenGroupSettings(description: string): IJSONSchema { } const tokenColorSchema: IJSONSchema = { + type: 'object', properties: { comments: tokenGroupSettings(nls.localize('editorColors.comments', "Sets the colors and styles for comments")), strings: tokenGroupSettings(nls.localize('editorColors.strings', "Sets the colors and styles for strings literals.")), From a78bc1aa96d6b09c7066b9adec0a54cd792a2a9c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 25 May 2021 12:17:09 +0200 Subject: [PATCH 051/140] icon label: supportIcons implies LabelWithHighlights --- src/vs/base/browser/ui/iconLabel/iconLabel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index ba6727884bf..22ccd0073d2 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -114,7 +114,7 @@ export class IconLabel extends Disposable { const nameContainer = dom.append(this.labelContainer, dom.$('span.monaco-icon-name-container')); this.descriptionContainer = this._register(new FastLabelNode(dom.append(this.labelContainer, dom.$('span.monaco-icon-description-container')))); - if (options?.supportHighlights) { + if (options?.supportHighlights || options?.supportIcons) { this.nameNode = new LabelWithHighlights(nameContainer, !!options.supportIcons); } else { this.nameNode = new Label(nameContainer); From f89fc476de388c673f01e890e14c83d64c1b75fa Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 25 May 2021 12:59:55 +0200 Subject: [PATCH 052/140] Fixes colors for dark & white theme. --- src/vs/editor/common/view/editorColorRegistry.ts | 2 +- .../editor/contrib/inlineCompletions/ghostTextWidget.ts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/view/editorColorRegistry.ts b/src/vs/editor/common/view/editorColorRegistry.ts index e36d2bbd7ea..b390b2cb22b 100644 --- a/src/vs/editor/common/view/editorColorRegistry.ts +++ b/src/vs/editor/common/view/editorColorRegistry.ts @@ -44,7 +44,7 @@ export const editorUnnecessaryCodeBorder = registerColor('editorUnnecessaryCode. export const editorUnnecessaryCodeOpacity = registerColor('editorUnnecessaryCode.opacity', { dark: Color.fromHex('#000a'), light: Color.fromHex('#0007'), hc: null }, nls.localize('unnecessaryCodeOpacity', 'Opacity of unnecessary (unused) source code in the editor. For example, "#000000c0" will render the code with 75% opacity. For high contrast themes, use the \'editorUnnecessaryCode.border\' theme color to underline unnecessary code instead of fading it out.')); export const editorSuggestPreviewBorder = registerColor('editorSuggestPreview.border', { dark: null, light: null, hc: Color.fromHex('#fff').transparent(0.8) }, nls.localize('editorSuggestPreviewBorder', 'Border color of inline suggestion preview in the editor.')); -export const editorSuggestPreviewOpacity = registerColor('editorSuggestPreview.opacity', { dark: Color.fromHex('#000a'), light: Color.fromHex('#0007'), hc: null }, nls.localize('editorSuggestPreviewOpacity', 'Opacity of inline suggestion preview in the editor. For example, "#000000c0" will render the code with 75% opacity. For high contrast themes, use the \'editorSuggestPreview.border\' theme color instead of fading it out.')); +export const editorSuggestPreviewOpacity = registerColor('editorSuggestPreview.opacity', { dark: Color.fromHex('#FFFa'), light: Color.fromHex('#0007'), hc: null }, nls.localize('editorSuggestPreviewOpacity', 'Opacity of inline suggestion preview in the editor. For example, "#000000c0" will render the code with 75% opacity. For high contrast themes, use the \'editorSuggestPreview.border\' theme color instead of fading it out.')); const rulerRangeDefault = new Color(new RGBA(0, 122, 204, 0.6)); export const overviewRulerRangeHighlight = registerColor('editorOverviewRuler.rangeHighlightForeground', { dark: rulerRangeDefault, light: rulerRangeDefault, hc: rulerRangeDefault }, nls.localize('overviewRulerRangeHighlight', 'Overview ruler marker color for range highlights. The color must not be opaque so as not to hide underlying decorations.'), true); diff --git a/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts b/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts index 178c62518c8..753b4af5ae4 100644 --- a/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts +++ b/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts @@ -20,6 +20,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IModelDeltaDecoration } from 'vs/editor/common/model'; import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { editorSuggestPreviewBorder, editorSuggestPreviewOpacity } from 'vs/editor/common/view/editorColorRegistry'; +import { RGBA, Color } from 'vs/base/common/color'; const ttPolicy = window.trustedTypes?.createPolicy('editorGhostText', { createHTML: value => value }); @@ -149,8 +150,15 @@ export class GhostTextWidget extends Disposable { if (renderData) { const suggestPreviewForeground = this._themeService.getColorTheme().getColor(editorSuggestPreviewOpacity); let opacity = '0.467'; + let color = 'white'; if (suggestPreviewForeground) { + function opaque(color: Color): Color { + const { r, b, g } = color.rgba; + return new Color(new RGBA(r, g, b, 255)); + } + opacity = String(suggestPreviewForeground.rgba.a); + color = Color.Format.CSS.format(opaque(suggestPreviewForeground))!; } // We add 0 to bring it before any other decoration. this.codeEditorDecorationTypeKey = `0-ghost-text-${++GhostTextWidget.decorationTypeCount}`; @@ -159,6 +167,7 @@ export class GhostTextWidget extends Disposable { // TODO: escape? contentText: renderData.lines[0], opacity, + color } }); } From 4d4ebbee5fc071be17a84b90d065b8e839ae0813 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 25 May 2021 13:11:03 +0200 Subject: [PATCH 053/140] Clear inline suggestions cache on commit. --- .../inlineCompletions/inlineCompletionsModel.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts index 21fc23a3753..bdb7c151668 100644 --- a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts +++ b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts @@ -122,6 +122,7 @@ class InlineCompletionsSession extends BaseGhostTextWidgetModel { super(editor); this._register(toDisposable(() => { this.clearGhostTextPromise(); + this.clearCache(); })); this._register(this.editor.onDidChangeModelDecorations(e => { @@ -213,6 +214,13 @@ class InlineCompletionsSession extends BaseGhostTextWidgetModel { }, onUnexpectedError); } + private clearCache(): void { + if (this.cachedCompletions) { + this.editor.deltaDecorations(this.cachedCompletions.map(c => c.decorationId), []); + this.cachedCompletions = undefined; + } + } + private clearGhostTextPromise(): void { if (this.updatePromise) { this.updatePromise.cancel(); @@ -232,12 +240,14 @@ class InlineCompletionsSession extends BaseGhostTextWidgetModel { } public commit(completion: NormalizedInlineCompletion): void { + this.clearCache(); this.editor.executeEdits( 'inlineCompletions.accept', [ EditOperation.replaceMove(completion.range, completion.text) ] ); + this.onDidChangeEmitter.fire(); } } From 3de3141ff56de73fde431872aaa505bf88568a06 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 25 May 2021 16:23:38 +0200 Subject: [PATCH 054/140] Implements basic cycling through completions. --- .../inlineCompletions/ghostTextController.ts | 83 ++++++++++++++--- .../inlineCompletions/ghostTextWidget.ts | 16 +++- .../inlineCompletionsModel.ts | 92 +++++++++++++++---- 3 files changed, 160 insertions(+), 31 deletions(-) diff --git a/src/vs/editor/contrib/inlineCompletions/ghostTextController.ts b/src/vs/editor/contrib/inlineCompletions/ghostTextController.ts index a165019671f..9b558362c2d 100644 --- a/src/vs/editor/contrib/inlineCompletions/ghostTextController.ts +++ b/src/vs/editor/contrib/inlineCompletions/ghostTextController.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { KeyCode } from 'vs/base/common/keyCodes'; +import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IActiveCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorAction, EditorCommand, registerEditorAction, registerEditorCommand, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; @@ -60,21 +60,23 @@ class GhostTextController extends Disposable { } public trigger(): void { - if (this.activeController.value) { - this.activeController.value.trigger(); - } + this.activeController.value?.trigger(); } public commit(): void { - if (this.activeController.value) { - this.activeController.value.commit(); - } + this.activeController.value?.commit(); } public hide(): void { - if (this.activeController.value) { - this.activeController.value.hide(); - } + this.activeController.value?.hide(); + } + + public showNextInlineCompletion(): void { + this.activeController.value?.showNextInlineCompletion(); + } + + public showPreviousInlineCompletion(): void { + this.activeController.value?.showPreviousInlineCompletion(); } } @@ -141,13 +143,26 @@ export class ActiveGhostTextController extends Disposable { } } + public showNextInlineCompletion(): void { + if (this.widget.model === this.inlineCompletionsModel) { + this.inlineCompletionsModel.showNextInlineCompletion(); + } + } + + public showPreviousInlineCompletion(): void { + if (this.widget.model === this.inlineCompletionsModel) { + this.inlineCompletionsModel.showPreviousInlineCompletion(); + } + } + private updateModel() { this.widget.setModel(this.suggestWidgetAdapterModel.isActive ? this.suggestWidgetAdapterModel : this.inlineCompletionsModel); this.inlineCompletionsModel.setActive(this.widget.model === this.inlineCompletionsModel); } } -const GhostTextCommand = EditorCommand.bindToContribution(GhostTextController.get); +const GhostTextCommand = EditorCommand.bindToContribution(GhostTextController.get); +const GhostTextAction = EditorAction.bindToContribution(GhostTextController.get); registerEditorCommand(new GhostTextCommand({ id: 'commitInlineCompletion', @@ -173,6 +188,50 @@ registerEditorCommand(new GhostTextCommand({ } })); +export class ShowNextInlineCompletionAction extends EditorAction { + constructor() { + super({ + id: 'editor.action.showNextInlineCompletion', + label: nls.localize('showNextInlineCompletion', "Show Next Inline Completion"), + alias: 'Show Next Inline Completion', + precondition: EditorContextKeys.writable, + kbOpts: { + weight: 100, + primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.RightArrow, + }, + }); + } + + public async run(accessor: ServicesAccessor | undefined, editor: ICodeEditor): Promise { + const controller = GhostTextController.get(editor); + if (controller) { + controller.showNextInlineCompletion(); + } + } +} + +export class ShowPreviousInlineCompletionAction extends EditorAction { + constructor() { + super({ + id: 'editor.action.showPreviousInlineCompletion', + label: nls.localize('showPreviousInlineCompletion', "Show Previous Inline Completion"), + alias: 'Show Previous Inline Completion', + precondition: EditorContextKeys.writable, + kbOpts: { + weight: 100, + primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyMod.Shift | KeyCode.LeftArrow, + }, + }); + } + + public async run(accessor: ServicesAccessor | undefined, editor: ICodeEditor): Promise { + const controller = GhostTextController.get(editor); + if (controller) { + controller.showNextInlineCompletion(); + } + } +} + export class TriggerInlineCompletionsAction extends EditorAction { constructor() { super({ @@ -193,3 +252,5 @@ export class TriggerInlineCompletionsAction extends EditorAction { registerEditorContribution(GhostTextController.ID, GhostTextController); registerEditorAction(TriggerInlineCompletionsAction); +registerEditorAction(ShowNextInlineCompletionAction); +registerEditorAction(ShowPreviousInlineCompletionAction); diff --git a/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts b/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts index 753b4af5ae4..a0038016935 100644 --- a/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts +++ b/src/vs/editor/contrib/inlineCompletions/ghostTextWidget.ts @@ -21,6 +21,7 @@ import { IModelDeltaDecoration } from 'vs/editor/common/model'; import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { editorSuggestPreviewBorder, editorSuggestPreviewOpacity } from 'vs/editor/common/view/editorColorRegistry'; import { RGBA, Color } from 'vs/base/common/color'; +import { MarkdownString } from 'vs/base/common/htmlContent'; const ttPolicy = window.trustedTypes?.createPolicy('editorGhostText', { createHTML: value => value }); @@ -80,6 +81,7 @@ export class GhostTextWidget extends Disposable { private decorationIds: string[] = []; private viewZoneId: string | null = null; private viewMoreContentWidget: ViewMoreLinesContentWidget | null = null; + private viewMoreContentWidget2: ViewMoreLinesContentWidget | null = null; constructor( private readonly editor: ICodeEditor, @@ -167,8 +169,8 @@ export class GhostTextWidget extends Disposable { // TODO: escape? contentText: renderData.lines[0], opacity, - color - } + color, + }, }); } @@ -176,7 +178,10 @@ export class GhostTextWidget extends Disposable { if (renderData && this.codeEditorDecorationTypeKey) { newDecorations.push({ range: Range.fromPositions(renderData.position, renderData.position), - options: this._codeEditorService.resolveDecorationOptions(this.codeEditorDecorationTypeKey, true) + options: { + hoverMessage: new MarkdownString('⬅️ Previous | Next ➡️'), + ...this._codeEditorService.resolveDecorationOptions(this.codeEditorDecorationTypeKey, true), + } }); } this.decorationIds = this.editor.deltaDecorations(this.decorationIds, newDecorations); @@ -186,6 +191,11 @@ export class GhostTextWidget extends Disposable { this.viewMoreContentWidget = null; } + if (this.viewMoreContentWidget2) { + this.viewMoreContentWidget2.dispose(); + this.viewMoreContentWidget2 = null; + } + this.editor.changeViewZones((changeAccessor) => { if (this.viewZoneId) { changeAccessor.removeZone(this.viewZoneId); diff --git a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts index bdb7c151668..6c64a6cf71a 100644 --- a/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts +++ b/src/vs/editor/contrib/inlineCompletions/inlineCompletionsModel.ts @@ -101,12 +101,30 @@ export class InlineCompletionsModel extends Disposable implements GhostTextWidge this.session.commitCurrentCompletion(); } } + + public showNextInlineCompletion(): void { + if (this.session) { + this.session.showNextInlineCompletion(); + } + } + + public showPreviousInlineCompletion(): void { + if (this.session) { + this.session.showPreviousInlineCompletion(); + } + } } -interface CachedInlineCompletion { - inlineCompletion: NormalizedInlineCompletion; - decorationId: string; - lastRange: Range; +class CachedInlineCompletion { + public readonly semanticId: string = JSON.stringify(this.inlineCompletion); + public lastRange: Range; + + constructor( + public readonly inlineCompletion: NormalizedInlineCompletion, + public readonly decorationId: string, + ) { + this.lastRange = inlineCompletion.range; + } } class InlineCompletionsSession extends BaseGhostTextWidgetModel { @@ -154,16 +172,55 @@ class InlineCompletionsSession extends BaseGhostTextWidgetModel { this.updateSoon.schedule(); } + //#region Selection + + // We use a semantic id to track the selection even if the cache changes. + private currentlySelectedCompletionId: string | undefined = undefined; + + private getIndexOfCurrentSelection(): number { + if (!this.currentlySelectedCompletionId || !this.cachedCompletions) { + return 0; + } + + return this.cachedCompletions.findIndex(v => v.semanticId === this.currentlySelectedCompletionId); + } + + private get currentCachedCompletion(): CachedInlineCompletion | undefined { + if (!this.cachedCompletions) { + return undefined; + } + return this.cachedCompletions[this.getIndexOfCurrentSelection()]; + } + + public showNextInlineCompletion(): void { + if (this.cachedCompletions && this.cachedCompletions.length > 0) { + const newIdx = (this.getIndexOfCurrentSelection() + 1) % this.cachedCompletions.length; + this.currentlySelectedCompletionId = this.cachedCompletions[newIdx].semanticId; + } else { + this.currentlySelectedCompletionId = undefined; + } + this.onDidChangeEmitter.fire(); + } + + public showPreviousInlineCompletion(): void { + if (this.cachedCompletions && this.cachedCompletions.length > 0) { + const newIdx = (this.getIndexOfCurrentSelection() + this.cachedCompletions.length - 1) % this.cachedCompletions.length; + this.currentlySelectedCompletionId = this.cachedCompletions[newIdx].semanticId; + } else { + this.currentlySelectedCompletionId = undefined; + } + this.onDidChangeEmitter.fire(); + } + + //#endregion + public get ghostText(): GhostText | undefined { const currentCompletion = this.currentCompletion; return currentCompletion ? inlineCompletionToGhostText(currentCompletion, this.editor.getModel()) : undefined; } get currentCompletion(): NormalizedInlineCompletion | undefined { - if (!this.cachedCompletions) { - return undefined; - } - const completion = this.cachedCompletions[0]; + const completion = this.currentCachedCompletion; if (!completion) { return undefined; } @@ -205,11 +262,7 @@ class InlineCompletionsSession extends BaseGhostTextWidgetModel { })) ); - this.cachedCompletions = result.items.map((item, idx) => ({ - decorationId: decorationIds[idx], - inlineCompletion: item, - lastRange: item.range - })); + this.cachedCompletions = result.items.map((item, idx) => new CachedInlineCompletion(item, decorationIds[idx])); this.onDidChangeEmitter.fire(); }, onUnexpectedError); } @@ -255,6 +308,9 @@ export interface NormalizedInlineCompletion extends InlineCompletion { range: Range; } +/** + * Contains no duplicated items. +*/ export interface NormalizedInlineCompletions extends InlineCompletions { } @@ -295,15 +351,17 @@ async function provideInlineCompletions( providers.map(provider => provider.provideInlineCompletions(model, position, context, token)) ); - const items = new Array(); + const itemsByHash = new Map(); for (const result of results) { if (result) { - items.push(...result.items.map(item => ({ + for (const item of result.items.map(item => ({ text: item.text, range: item.range ? Range.lift(item.range) : defaultReplaceRange - }))); + }))) { + itemsByHash.set(JSON.stringify({ text: item.text, range: item.range }), item); + } } } - return { items }; + return { items: [...itemsByHash.values()] }; } From 741beb8f264de4d9a779f1c3c1ca2c38714a06f0 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 25 May 2021 16:30:57 +0200 Subject: [PATCH 055/140] TestResolver, use 127.0.0.1, not localhost --- extensions/vscode-test-resolver/src/extension.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extensions/vscode-test-resolver/src/extension.ts b/extensions/vscode-test-resolver/src/extension.ts index 16a3d0cca57..78301260ea7 100644 --- a/extensions/vscode-test-resolver/src/extension.ts +++ b/extensions/vscode-test-resolver/src/extension.ts @@ -52,7 +52,7 @@ export function activate(context: vscode.ExtensionContext) { const match = lastProgressLine.match(/Extension host agent listening on (\d+)/); if (match) { isResolved = true; - res(new vscode.ResolvedAuthority('localhost', parseInt(match[1], 10))); // success! + res(new vscode.ResolvedAuthority('127.0.0.1', parseInt(match[1], 10))); // success! } lastProgressLine = ''; } else if (chr === CharCode.Backspace) { @@ -200,7 +200,7 @@ export function activate(context: vscode.ExtensionContext) { } }); }); - proxyServer.listen(0, () => { + proxyServer.listen(0, '127.0.0.1', () => { const port = (proxyServer.address()).port; outputChannel.appendLine(`Going through proxy at port ${port}`); const r: vscode.ResolverResult = new vscode.ResolvedAuthority('127.0.0.1', port); @@ -268,7 +268,7 @@ export function activate(context: vscode.ExtensionContext) { const port = Number.parseInt(result); vscode.workspace.openTunnel({ remoteAddress: { - host: 'localhost', + host: '127.0.0.1', port: port }, localAddressPort: port + 1 @@ -406,10 +406,10 @@ async function tunnelFactory(tunnelOptions: vscode.TunnelOptions, tunnelCreation if (localPort < 1024 && process.platform !== 'win32') { localPort = 0; } - proxyServer.listen(localPort, () => { + proxyServer.listen(localPort, '127.0.0.1', () => { const localPort = (proxyServer.address()).port; outputChannel.appendLine(`New test resolver tunnel service: Remote ${tunnelOptions.remoteAddress.port} -> local ${localPort}`); - const tunnel = newTunnel({ host: 'localhost', port: localPort }); + const tunnel = newTunnel({ host: '127.0.0.1', port: localPort }); tunnel.onDidDispose(() => proxyServer.close()); res(tunnel); }); @@ -423,8 +423,8 @@ function runHTTPTestServer(port: number): vscode.Disposable { res.end(`Hello, World from test server running on port ${port}!`); }); remoteServers.push(port); - server.listen(port); - const message = `Opened HTTP server on http://localhost:${port}`; + server.listen(port, '127.0.0.1'); + const message = `Opened HTTP server on http://127.0.0.1:${port}`; console.log(message); outputChannel.appendLine(message); return { From 593a25d41e1b9ad66aaee458c775814d9c349a01 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 16:35:11 +0200 Subject: [PATCH 056/140] editors - remove TextOptions#apply --- .../browser/parts/editor/textDiffEditor.ts | 11 ++--- .../browser/parts/editor/textEditor.ts | 11 +++-- .../parts/editor/textResourceEditor.ts | 12 ++--- src/vs/workbench/common/editor.ts | 44 +------------------ .../workbench/common/editor/editorOptions.ts | 44 +++++++++++++++++++ .../files/browser/editors/textFileEditor.ts | 11 ++--- .../editor/browser/codeEditorService.ts | 6 +-- 7 files changed, 71 insertions(+), 68 deletions(-) create mode 100644 src/vs/workbench/common/editor/editorOptions.ts diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index dfa400ffb90..b3e603c3980 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -5,11 +5,12 @@ import { localize } from 'vs/nls'; import { deepClone } from 'vs/base/common/objects'; -import { isFunction, isObject, isArray, assertIsDefined, withUndefinedAsNull } from 'vs/base/common/types'; +import { isObject, isArray, assertIsDefined, withUndefinedAsNull } from 'vs/base/common/types'; import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffEditorOptions, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor'; -import { TextEditorOptions, EditorOptions, TEXT_DIFF_EDITOR_ID, IEditorInputFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorOptions, TEXT_DIFF_EDITOR_ID, IEditorInputFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; @@ -136,10 +137,10 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan const resolvedDiffEditorModel = resolvedModel as TextDiffEditorModel; diffEditor.setModel(withUndefinedAsNull(resolvedDiffEditorModel.textDiffEditorModel)); - // Apply Options from TextOptions + /// Apply options to editor if any let optionsGotApplied = false; - if (options && isFunction((options).apply)) { - optionsGotApplied = (options).apply(diffEditor, ScrollType.Immediate); + if (options) { + optionsGotApplied = applyTextEditorOptions(options, diffEditor, ScrollType.Immediate); } // Otherwise restore View State unless disabled via settings diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index c36c799c8c9..4030f05aa15 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -7,10 +7,11 @@ import { localize } from 'vs/nls'; import { URI } from 'vs/base/common/uri'; import { distinct, deepClone } from 'vs/base/common/objects'; import { Event } from 'vs/base/common/event'; -import { isObject, assertIsDefined, withNullAsUndefined, isFunction } from 'vs/base/common/types'; +import { isObject, assertIsDefined, withNullAsUndefined } from 'vs/base/common/types'; import { Dimension } from 'vs/base/browser/dom'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; -import { EditorOptions, IEditorMemento, ITextEditorPane, TextEditorOptions, IEditorCloseEvent, IEditorInput, IEditorOpenContext, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorMemento, ITextEditorPane, IEditorCloseEvent, IEditorInput, IEditorOpenContext, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { computeEditorAriaLabel } from 'vs/workbench/browser/editor'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; @@ -167,10 +168,8 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa } override setOptions(options: EditorOptions | undefined): void { - const textOptions = options as TextEditorOptions; - if (textOptions && isFunction(textOptions.apply)) { - const textEditor = assertIsDefined(this.getControl()); - textOptions.apply(textEditor, ScrollType.Smooth); + if (options) { + applyTextEditorOptions(options, assertIsDefined(this.getControl()), ScrollType.Smooth); } } diff --git a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts index f0861ae8b51..0c2cc04db9a 100644 --- a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts @@ -4,9 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { localize } from 'vs/nls'; -import { assertIsDefined, isFunction, withNullAsUndefined } from 'vs/base/common/types'; +import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types'; import { ICodeEditor, getCodeEditor, IPasteEvent } from 'vs/editor/browser/editorBrowser'; -import { TextEditorOptions, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { AbstractTextResourceEditorInput, TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; @@ -78,11 +79,10 @@ export class AbstractTextResourceEditor extends BaseTextEditor { const textEditorModel = resolvedModel.textEditorModel; textEditor.setModel(textEditorModel); - // Apply Options from TextOptions + // Apply options to editor if any let optionsGotApplied = false; - const textOptions = options; - if (textOptions && isFunction(textOptions.apply)) { - optionsGotApplied = textOptions.apply(textEditor, ScrollType.Immediate); + if (options) { + optionsGotApplied = applyTextEditorOptions(options, textEditor, ScrollType.Immediate); } // Otherwise restore View State unless disabled via settings diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 52a7127f95a..c0a5e6db4f4 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -8,7 +8,7 @@ import { Event } from 'vs/base/common/event'; import { withNullAsUndefined, assertIsDefined, isUndefinedOrNull } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IEditor, IEditorViewState, ScrollType, IDiffEditor } from 'vs/editor/common/editorCommon'; +import { IEditor, IEditorViewState, IDiffEditor } from 'vs/editor/common/editorCommon'; import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceEditorInput, IResourceEditorInput, EditorActivation, EditorOpenContext, ITextEditorSelection, TextEditorSelectionRevealType, EditorOverride } from 'vs/platform/editor/common/editor'; import { IInstantiationService, IConstructorSignature0, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation'; import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -20,7 +20,6 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IPathData } from 'vs/platform/windows/common/windows'; import { coalesce } from 'vs/base/common/arrays'; import { ACTIVE_GROUP, IResourceEditorInputType, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; -import { IRange } from 'vs/editor/common/core/range'; import { IExtUri } from 'vs/base/common/resources'; // Static values for editor contributions @@ -936,47 +935,6 @@ export class TextEditorOptions extends EditorOptions implements ITextEditorOptio return options; } - - /** - * Apply the view state or selection to the given editor. - * - * @return if something was applied - */ - apply(editor: IEditor, scrollType: ScrollType): boolean { - let gotApplied = false; - - // First try viewstate - if (this.editorViewState) { - editor.restoreViewState(this.editorViewState); - gotApplied = true; - } - - // Otherwise check for selection - else if (this.selection) { - const range: IRange = { - startLineNumber: this.selection.startLineNumber, - startColumn: this.selection.startColumn, - endLineNumber: this.selection.endLineNumber ?? this.selection.startLineNumber, - endColumn: this.selection.endColumn ?? this.selection.startColumn - }; - - editor.setSelection(range); - - if (this.selectionRevealType === TextEditorSelectionRevealType.NearTop) { - editor.revealRangeNearTop(range, scrollType); - } else if (this.selectionRevealType === TextEditorSelectionRevealType.NearTopIfOutsideViewport) { - editor.revealRangeNearTopIfOutsideViewport(range, scrollType); - } else if (this.selectionRevealType === TextEditorSelectionRevealType.CenterIfOutsideViewport) { - editor.revealRangeInCenterIfOutsideViewport(range, scrollType); - } else { - editor.revealRangeInCenter(range, scrollType); - } - - gotApplied = true; - } - - return gotApplied; - } } /** diff --git a/src/vs/workbench/common/editor/editorOptions.ts b/src/vs/workbench/common/editor/editorOptions.ts new file mode 100644 index 00000000000..a9113b39f74 --- /dev/null +++ b/src/vs/workbench/common/editor/editorOptions.ts @@ -0,0 +1,44 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IRange } from 'vs/editor/common/core/range'; +import { IEditor, IEditorViewState, ScrollType } from 'vs/editor/common/editorCommon'; +import { ITextEditorOptions, TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor'; + +export function applyTextEditorOptions(options: ITextEditorOptions, editor: IEditor, scrollType: ScrollType): boolean { + + // First try viewstate + if (options.viewState) { + editor.restoreViewState(options.viewState as IEditorViewState); + + return true; + } + + // Otherwise check for selection + else if (options.selection) { + const range: IRange = { + startLineNumber: options.selection.startLineNumber, + startColumn: options.selection.startColumn, + endLineNumber: options.selection.endLineNumber ?? options.selection.startLineNumber, + endColumn: options.selection.endColumn ?? options.selection.startColumn + }; + + editor.setSelection(range); + + if (options.selectionRevealType === TextEditorSelectionRevealType.NearTop) { + editor.revealRangeNearTop(range, scrollType); + } else if (options.selectionRevealType === TextEditorSelectionRevealType.NearTopIfOutsideViewport) { + editor.revealRangeNearTopIfOutsideViewport(range, scrollType); + } else if (options.selectionRevealType === TextEditorSelectionRevealType.CenterIfOutsideViewport) { + editor.revealRangeInCenterIfOutsideViewport(range, scrollType); + } else { + editor.revealRangeInCenter(range, scrollType); + } + + return true; + } + + return false; +} diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index d1ad34d4540..659a04688bf 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -5,14 +5,15 @@ import { localize } from 'vs/nls'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import { isFunction, assertIsDefined } from 'vs/base/common/types'; +import { assertIsDefined } from 'vs/base/common/types'; import { isValidBasename } from 'vs/base/common/extpath'; import { basename } from 'vs/base/common/resources'; import { toAction } from 'vs/base/common/actions'; import { VIEWLET_ID, TEXT_FILE_EDITOR_ID } from 'vs/workbench/contrib/files/common/files'; import { ITextFileService, TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; -import { EditorOptions, TextEditorOptions, IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { EditorOptions, IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; @@ -140,9 +141,9 @@ export class TextFileEditor extends BaseTextEditor { } } - // TextOptions (avoiding instanceof here for a reason, do not change!) - if (options && isFunction((options).apply)) { - (options).apply(textEditor, ScrollType.Immediate); + // Apply options to editor if any + if (options) { + applyTextEditorOptions(options, textEditor, ScrollType.Immediate); } // Since the resolved model provides information about being readonly diff --git a/src/vs/workbench/services/editor/browser/codeEditorService.ts b/src/vs/workbench/services/editor/browser/codeEditorService.ts index dcef4106dfb..05d2321431a 100644 --- a/src/vs/workbench/services/editor/browser/codeEditorService.ts +++ b/src/vs/workbench/services/editor/browser/codeEditorService.ts @@ -8,12 +8,13 @@ import { CodeEditorServiceImpl } from 'vs/editor/browser/services/codeEditorServ import { ScrollType } from 'vs/editor/common/editorCommon'; import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IWorkbenchEditorConfiguration, TextEditorOptions } from 'vs/workbench/common/editor'; +import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { isEqual } from 'vs/base/common/resources'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; export class CodeEditorService extends CodeEditorServiceImpl { @@ -60,8 +61,7 @@ export class CodeEditorService extends CodeEditorServiceImpl { ) { const targetEditor = activeTextEditorControl.getModifiedEditor(); - const textOptions = TextEditorOptions.create(input.options); - textOptions.apply(targetEditor, ScrollType.Smooth); + applyTextEditorOptions(input.options, targetEditor, ScrollType.Smooth); return targetEditor; } From 9bdb8f888168568a81602d4c8f226b6a73be5888 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 16:39:17 +0200 Subject: [PATCH 057/140] editors - remove TextOptions#fromEditor --- .../workbench/browser/parts/editor/editor.ts | 11 ++++++++-- src/vs/workbench/common/editor.ts | 21 +------------------ 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editor.ts b/src/vs/workbench/browser/parts/editor/editor.ts index 959615f8a06..1bf7fe367f4 100644 --- a/src/vs/workbench/browser/parts/editor/editor.ts +++ b/src/vs/workbench/browser/parts/editor/editor.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { GroupIdentifier, IWorkbenchEditorConfiguration, EditorOptions, TextEditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditorPartOptions, IEditorPartOptionsChangeEvent } from 'vs/workbench/common/editor'; +import { GroupIdentifier, IWorkbenchEditorConfiguration, EditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditorPartOptions, IEditorPartOptionsChangeEvent } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { IEditorGroup, GroupDirection, IAddGroupOptions, IMergeGroupOptions, GroupsOrder, GroupsArrangement } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IDisposable } from 'vs/base/common/lifecycle'; @@ -14,6 +14,8 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ISerializableView } from 'vs/base/browser/ui/grid/grid'; import { getIEditor } from 'vs/editor/browser/editorBrowser'; import { IEditorService, IResourceEditorInputType } from 'vs/workbench/services/editor/common/editorService'; +import { withNullAsUndefined } from 'vs/base/common/types'; +import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; export interface IEditorPartCreationOptions { restorePreviousState: boolean; @@ -134,7 +136,12 @@ export function getActiveTextEditorOptions(group: IEditorGroup, expectedActiveEd const activeGroupCodeEditor = group.activeEditorPane ? getIEditor(group.activeEditorPane.getControl()) : undefined; if (activeGroupCodeEditor) { if (!expectedActiveEditor || expectedActiveEditor.matches(group.activeEditor)) { - return TextEditorOptions.fromEditor(activeGroupCodeEditor, presetOptions); + const textOptions: ITextEditorOptions = { + ...presetOptions, + viewState: withNullAsUndefined(activeGroupCodeEditor.saveViewState()) + }; + + return textOptions as EditorOptions; } } diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index c0a5e6db4f4..2b5faa994f5 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -5,7 +5,7 @@ import { localize } from 'vs/nls'; import { Event } from 'vs/base/common/event'; -import { withNullAsUndefined, assertIsDefined, isUndefinedOrNull } from 'vs/base/common/types'; +import { assertIsDefined, isUndefinedOrNull } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IEditor, IEditorViewState, IDiffEditor } from 'vs/editor/common/editorCommon'; @@ -916,25 +916,6 @@ export class TextEditorOptions extends EditorOptions implements ITextEditorOptio return this; } - - /** - * Returns if this options object has objects defined for the editor. - */ - hasOptionsDefined(): boolean { - return !!this.editorViewState || !!this.selectionRevealType || !!this.selection; - } - - /** - * Create a TextEditorOptions inline to be used when the editor is opening. - */ - static fromEditor(editor: IEditor, settings?: IEditorOptions): TextEditorOptions { - const options = TextEditorOptions.create(settings); - - // View state - options.editorViewState = withNullAsUndefined(editor.saveViewState()); - - return options; - } } /** From b10db1828d05a24e1d918f3eb7ed6236f31bba78 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 16:40:30 +0200 Subject: [PATCH 058/140] editors - remove TextOptions#from --- src/vs/workbench/common/editor.ts | 8 -------- src/vs/workbench/services/editor/browser/editorService.ts | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 2b5faa994f5..8028e3af21d 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -873,14 +873,6 @@ export class TextEditorOptions extends EditorOptions implements ITextEditorOptio */ selectionRevealType: TextEditorSelectionRevealType | undefined; - static from(input?: IBaseResourceEditorInput): TextEditorOptions | undefined { - if (!input?.options) { - return undefined; - } - - return TextEditorOptions.create(input.options); - } - /** * Helper to convert options bag to real class */ diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index fc32bdb9d8f..3dbccf9cf15 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -559,7 +559,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { const textInput = editor as IResourceEditorInputType; typedEditor = this.createEditorInput(textInput); if (typedEditor) { - typedOptions = TextEditorOptions.from(textInput); + typedOptions = textInput.options as EditorOptions; candidateGroup = optionsOrGroup as OpenInEditorGroup; resolvedGroup = this.findTargetGroup(typedEditor, typedOptions, candidateGroup); @@ -708,7 +708,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { return { editor: this.createEditorInput(editor), - options: TextEditorOptions.from(editor) + options: editor.options }; }); From 8adc16d6c50cbedd577daf8838c337459d95fab5 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 16:42:14 +0200 Subject: [PATCH 059/140] editors - remove TextOptions#create --- src/vs/workbench/common/editor.ts | 10 ---------- .../workbench/services/editor/browser/editorService.ts | 9 ++------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 8028e3af21d..2b1f69698cf 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -873,16 +873,6 @@ export class TextEditorOptions extends EditorOptions implements ITextEditorOptio */ selectionRevealType: TextEditorSelectionRevealType | undefined; - /** - * Helper to convert options bag to real class - */ - static override create(options: ITextEditorOptions = Object.create(null)): TextEditorOptions { - const textEditorOptions = new TextEditorOptions(); - textEditorOptions.overwrite(options); - - return textEditorOptions; - } - /** * Overwrites option values from the provided bag. */ diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 3dbccf9cf15..17ef1ad0f92 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -5,7 +5,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IResourceEditorInput, ITextEditorOptions, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; -import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, TextEditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; @@ -677,12 +677,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { return options as EditorOptions; } - const textOptions: ITextEditorOptions = options; - if (textOptions.selection || textOptions.viewState) { - return TextEditorOptions.create(options); - } - - return EditorOptions.create(options); + return (options ?? Object.create(null)) as EditorOptions; } //#endregion From 080f8b5e35ff5823e718a1a9734d82200ce25d64 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 16:44:41 +0200 Subject: [PATCH 060/140] editors - remove TextEditorOptions --- src/vs/workbench/common/editor.ts | 49 +------------------------------ 1 file changed, 1 insertion(+), 48 deletions(-) diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 2b1f69698cf..9d57b508d33 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -9,7 +9,7 @@ import { assertIsDefined, isUndefinedOrNull } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IEditor, IEditorViewState, IDiffEditor } from 'vs/editor/common/editorCommon'; -import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceEditorInput, IResourceEditorInput, EditorActivation, EditorOpenContext, ITextEditorSelection, TextEditorSelectionRevealType, EditorOverride } from 'vs/platform/editor/common/editor'; +import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceEditorInput, IResourceEditorInput, EditorActivation, EditorOpenContext, EditorOverride } from 'vs/platform/editor/common/editor'; import { IInstantiationService, IConstructorSignature0, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation'; import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -853,53 +853,6 @@ export class EditorOptions implements IEditorOptions { } } -/** - * Base Text Editor Options. - */ -export class TextEditorOptions extends EditorOptions implements ITextEditorOptions { - - /** - * Text editor selection. - */ - selection: ITextEditorSelection | undefined; - - /** - * Text editor view state. - */ - editorViewState: IEditorViewState | undefined; - - /** - * Option to control the text editor selection reveal type. - */ - selectionRevealType: TextEditorSelectionRevealType | undefined; - - /** - * Overwrites option values from the provided bag. - */ - override overwrite(options: ITextEditorOptions): TextEditorOptions { - super.overwrite(options); - - if (options.selection) { - this.selection = { - startLineNumber: options.selection.startLineNumber, - startColumn: options.selection.startColumn, - endLineNumber: options.selection.endLineNumber ?? options.selection.startLineNumber, - endColumn: options.selection.endColumn ?? options.selection.startColumn - }; - } - - if (options.viewState) { - this.editorViewState = options.viewState as IEditorViewState; - } - - if (typeof options.selectionRevealType !== 'undefined') { - this.selectionRevealType = options.selectionRevealType; - } - - return this; - } -} - /** * Context passed into `EditorPane#setInput` to give additional * context information around why the editor was opened. From 0249ae328714103e9c0bbbd30b05568a30543770 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 25 May 2021 16:46:08 +0200 Subject: [PATCH 061/140] clarify that NotebookController#id should be stable, https://github.com/microsoft/vscode/issues/124535 --- src/vs/vscode.proposed.d.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index a6d4822e57e..10df4b473fa 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1563,6 +1563,9 @@ declare module 'vscode' { /** * The identifier of this notebook controller. + * + * _Note_ that controllers are remembered by their identifier and that extensions should use + * stable identifiers across sessions. */ readonly id: string; From a21b824704bd74fedc500cb8e33f4eaf1337dacf Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 25 May 2021 08:07:25 -0700 Subject: [PATCH 062/140] Enable notebook renderers on web (#124557) --- .../workbench/contrib/notebook/browser/notebookEditorWidget.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 49e1d98cf4c..b9b697c5514 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -64,7 +64,6 @@ import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; -import { isWeb } from 'vs/base/common/platform'; import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; import { readFontInfo } from 'vs/editor/browser/config/configuration'; import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; @@ -332,7 +331,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor super(); this.isEmbedded = creationOptions.isEmbedded || false; - this.useRenderer = !isWeb && !!this.configurationService.getValue(ExperimentalUseMarkdownRenderer) && !accessibilityService.isScreenReaderOptimized(); + this.useRenderer = !!this.configurationService.getValue(ExperimentalUseMarkdownRenderer) && !accessibilityService.isScreenReaderOptimized(); this._notebookOptions = new NotebookOptions(this.configurationService); this._register(this._notebookOptions); this._viewContext = new ViewContext(this._notebookOptions, new NotebookEventDispatcher()); From f2b1f78ad45d5b19fe220e4533356efb31f4dcc1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 17:12:49 +0200 Subject: [PATCH 063/140] editors - remove EditorOptions --- src/vs/platform/editor/common/editor.ts | 30 ++-- .../browser/parts/editor/binaryEditor.ts | 9 +- .../workbench/browser/parts/editor/editor.ts | 10 +- .../browser/parts/editor/editorControl.ts | 7 +- .../browser/parts/editor/editorDropTarget.ts | 6 +- .../browser/parts/editor/editorGroupView.ts | 52 +++--- .../browser/parts/editor/editorPane.ts | 10 +- .../browser/parts/editor/sideBySideEditor.ts | 13 +- .../browser/parts/editor/textDiffEditor.ts | 15 +- .../browser/parts/editor/textEditor.ts | 19 ++- .../parts/editor/textResourceEditor.ts | 9 +- .../editor/workspaceTrustRequiredEditor.ts | 5 +- src/vs/workbench/common/editor.ts | 160 +----------------- .../extensions/browser/extensionEditor.ts | 5 +- .../files/browser/editors/binaryFileEditor.ts | 5 +- .../files/browser/editors/textFileEditor.ts | 19 +-- .../files/electron-sandbox/textFileEditor.ts | 4 +- .../browser/diff/notebookTextDiffEditor.ts | 9 +- .../notebook/browser/notebookEditor.ts | 6 +- .../contrib/output/browser/outputView.ts | 11 +- .../preferences/browser/keybindingsEditor.ts | 5 +- .../preferences/browser/preferencesEditor.ts | 11 +- .../searchEditor/browser/searchEditor.ts | 5 +- .../webviewPanel/browser/webviewEditor.ts | 5 +- .../gettingStarted/browser/gettingStarted.ts | 5 +- .../walkThrough/browser/walkThroughPart.ts | 9 +- .../workspace/browser/workspaceTrustEditor.ts | 5 +- .../services/editor/browser/editorService.ts | 28 ++- .../test/browser/editorGroupsService.test.ts | 26 +-- .../test/browser/editorsObserver.test.ts | 80 ++++----- .../history/test/browser/history.test.ts | 27 ++- .../browser/parts/editor/editorPane.test.ts | 4 +- .../test/browser/workbenchTestServices.ts | 6 +- 33 files changed, 231 insertions(+), 389 deletions(-) diff --git a/src/vs/platform/editor/common/editor.ts b/src/vs/platform/editor/common/editor.ts index c5611b87ae4..f14cfa60953 100644 --- a/src/vs/platform/editor/common/editor.ts +++ b/src/vs/platform/editor/common/editor.ts @@ -169,7 +169,7 @@ export interface IEditorOptions { * Will also not activate the group the editor opens in unless the group is already * the active one. This behaviour can be overridden via the `activation` option. */ - readonly preserveFocus?: boolean; + preserveFocus?: boolean; /** * This option is only relevant if an editor is opened into a group that is not active @@ -179,14 +179,14 @@ export interface IEditorOptions { * By default, the editor group will become active unless `preserveFocus` or `inactive` * is specified. */ - readonly activation?: EditorActivation; + activation?: EditorActivation; /** * Tells the editor to reload the editor input in the editor even if it is identical to the one * already showing. By default, the editor will not reload the input if it is identical to the * one showing. */ - readonly forceReload?: boolean; + forceReload?: boolean; /** * Will reveal the editor if it is already opened and visible in any of the opened editor groups. @@ -194,7 +194,7 @@ export interface IEditorOptions { * Note that this option is just a hint that might be ignored if the user wants to open an editor explicitly * to the side of another one or into a specific editor group. */ - readonly revealIfVisible?: boolean; + revealIfVisible?: boolean; /** * Will reveal the editor if it is already opened (even when not visible) in any of the opened editor groups. @@ -202,24 +202,24 @@ export interface IEditorOptions { * Note that this option is just a hint that might be ignored if the user wants to open an editor explicitly * to the side of another one or into a specific editor group. */ - readonly revealIfOpened?: boolean; + revealIfOpened?: boolean; /** * An editor that is pinned remains in the editor stack even when another editor is being opened. * An editor that is not pinned will always get replaced by another editor that is not pinned. */ - readonly pinned?: boolean; + pinned?: boolean; /** * An editor that is sticky moves to the beginning of the editors list within the group and will remain * there unless explicitly closed. Operations such as "Close All" will not close sticky editors. */ - readonly sticky?: boolean; + sticky?: boolean; /** * The index in the document stack where to insert the editor into when opening. */ - readonly index?: number; + index?: number; /** * An active editor that is opened will show its contents directly. Set to true to open an editor @@ -228,13 +228,13 @@ export interface IEditorOptions { * Will also not activate the group the editor opens in unless the group is already * the active one. This behaviour can be overridden via the `activation` option. */ - readonly inactive?: boolean; + inactive?: boolean; /** * Will not show an error in case opening the editor fails and thus allows to show a custom error * message as needed. By default, an error will be presented as notification if opening was not possible. */ - readonly ignoreError?: boolean; + ignoreError?: boolean; /** * Allows to override the editor that should be used to display the input: @@ -242,7 +242,7 @@ export interface IEditorOptions { * - `string`: specific override by id * - `EditorOverride`: specific override handling */ - readonly override?: string | EditorOverride; + override?: string | EditorOverride; /** * A optional hint to signal in which context the editor opens. @@ -254,7 +254,7 @@ export interface IEditorOptions { * some background task, the notification would show in the background, * not as a modal dialog. */ - readonly context?: EditorOpenContext; + context?: EditorOpenContext; } export interface ITextEditorSelection { @@ -289,16 +289,16 @@ export interface ITextEditorOptions extends IEditorOptions { /** * Text editor selection. */ - readonly selection?: ITextEditorSelection; + selection?: ITextEditorSelection; /** * Text editor view state. */ - readonly viewState?: object; + viewState?: object; /** * Option to control the text editor selection reveal type. * Defaults to TextEditorSelectionRevealType.Center */ - readonly selectionRevealType?: TextEditorSelectionRevealType; + selectionRevealType?: TextEditorSelectionRevealType; } diff --git a/src/vs/workbench/browser/parts/editor/binaryEditor.ts b/src/vs/workbench/browser/parts/editor/binaryEditor.ts index 2a49d62abdb..3608f7181b0 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditor.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/binaryeditor'; import { localize } from 'vs/nls'; import { Emitter } from 'vs/base/common/event'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; @@ -20,9 +20,10 @@ import { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/ import { IStorageService } from 'vs/platform/storage/common/storage'; import { assertIsDefined, assertAllDefined } from 'vs/base/common/types'; import { ByteSize } from 'vs/platform/files/common/files'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export interface IOpenCallbacks { - openInternal: (input: EditorInput, options: EditorOptions | undefined) => Promise; + openInternal: (input: EditorInput, options: IEditorOptions | undefined) => Promise; } /* @@ -71,7 +72,7 @@ export abstract class BaseBinaryResourceEditor extends EditorPane { parent.appendChild(this.scrollbar.getDomNode()); } - override async setInput(input: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); const model = await input.resolve(); @@ -89,7 +90,7 @@ export abstract class BaseBinaryResourceEditor extends EditorPane { this.inputDisposable.value = this.renderInput(input, options, model); } - private renderInput(input: EditorInput, options: EditorOptions | undefined, model: BinaryEditorModel): IDisposable { + private renderInput(input: EditorInput, options: IEditorOptions | undefined, model: BinaryEditorModel): IDisposable { const [binaryContainer, scrollbar] = assertAllDefined(this.binaryContainer, this.scrollbar); clearNode(binaryContainer); diff --git a/src/vs/workbench/browser/parts/editor/editor.ts b/src/vs/workbench/browser/parts/editor/editor.ts index 1bf7fe367f4..7cd15e24cf6 100644 --- a/src/vs/workbench/browser/parts/editor/editor.ts +++ b/src/vs/workbench/browser/parts/editor/editor.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { GroupIdentifier, IWorkbenchEditorConfiguration, EditorOptions, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditorPartOptions, IEditorPartOptionsChangeEvent } from 'vs/workbench/common/editor'; +import { GroupIdentifier, IWorkbenchEditorConfiguration, IEditorInput, IEditorIdentifier, IEditorCloseEvent, IEditorPartOptions, IEditorPartOptionsChangeEvent } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { IEditorGroup, GroupDirection, IAddGroupOptions, IMergeGroupOptions, GroupsOrder, GroupsArrangement } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IDisposable } from 'vs/base/common/lifecycle'; @@ -15,7 +15,7 @@ import { ISerializableView } from 'vs/base/browser/ui/grid/grid'; import { getIEditor } from 'vs/editor/browser/editorBrowser'; import { IEditorService, IResourceEditorInputType } from 'vs/workbench/services/editor/common/editorService'; import { withNullAsUndefined } from 'vs/base/common/types'; -import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor'; export interface IEditorPartCreationOptions { restorePreviousState: boolean; @@ -132,7 +132,7 @@ export interface IEditorGroupView extends IDisposable, ISerializableView, IEdito relayout(): void; } -export function getActiveTextEditorOptions(group: IEditorGroup, expectedActiveEditor?: IEditorInput, presetOptions?: EditorOptions): EditorOptions { +export function getActiveTextEditorOptions(group: IEditorGroup, expectedActiveEditor?: IEditorInput, presetOptions?: IEditorOptions): IEditorOptions { const activeGroupCodeEditor = group.activeEditorPane ? getIEditor(group.activeEditorPane.getControl()) : undefined; if (activeGroupCodeEditor) { if (!expectedActiveEditor || expectedActiveEditor.matches(group.activeEditor)) { @@ -141,11 +141,11 @@ export function getActiveTextEditorOptions(group: IEditorGroup, expectedActiveEd viewState: withNullAsUndefined(activeGroupCodeEditor.saveViewState()) }; - return textOptions as EditorOptions; + return textOptions; } } - return presetOptions || new EditorOptions(); + return presetOptions || Object.create(null); } /** diff --git a/src/vs/workbench/browser/parts/editor/editorControl.ts b/src/vs/workbench/browser/parts/editor/editorControl.ts index 2d2bc02c9a6..b49d6dd9e0f 100644 --- a/src/vs/workbench/browser/parts/editor/editorControl.ts +++ b/src/vs/workbench/browser/parts/editor/editorControl.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { EditorExtensions, EditorInputCapabilities, EditorOptions, IEditorOpenContext, IVisibleEditorPane } from 'vs/workbench/common/editor'; +import { EditorExtensions, EditorInputCapabilities, IEditorOpenContext, IVisibleEditorPane } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { Dimension, show, hide } from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -18,6 +18,7 @@ import { Emitter } from 'vs/base/common/event'; import { assertIsDefined } from 'vs/base/common/types'; import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export interface IOpenEditorResult { readonly editorPane: EditorPane; @@ -78,7 +79,7 @@ export class EditorControl extends Disposable { } } - async openEditor(editor: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext = Object.create(null)): Promise { + async openEditor(editor: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext = Object.create(null)): Promise { // Editor descriptor const descriptor = this.getEditorDescriptor(editor); @@ -182,7 +183,7 @@ export class EditorControl extends Disposable { this._onDidChangeSizeConstraints.fire(undefined); } - private async doSetInput(editorPane: EditorPane, editor: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext): Promise { + private async doSetInput(editorPane: EditorPane, editor: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext): Promise { // If the input did not change, return early and only apply the options // unless the options instruct us to force open it even if it is the same diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index 6771be93af0..4092e7396a5 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -10,7 +10,7 @@ import { IEditorGroupsAccessor, IEditorGroupView, getActiveTextEditorOptions } f import { EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; import { IThemeService, Themable } from 'vs/platform/theme/common/themeService'; import { activeContrastBorder } from 'vs/platform/theme/common/colorRegistry'; -import { IEditorIdentifier, EditorOptions, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { IEditorIdentifier, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { isMacintosh, isWeb } from 'vs/base/common/platform'; import { GroupDirection, IEditorGroupsService, MergeGroupMode } from 'vs/workbench/services/editor/common/editorGroupsService'; import { toDisposable } from 'vs/base/common/lifecycle'; @@ -281,10 +281,10 @@ class DropOverlay extends Themable { } // Open in target group - const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({ + const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, { pinned: true, // always pin dropped editor sticky: sourceGroup.isSticky(draggedEditor.editor), // preserve sticky state - })); + }); const copyEditor = this.isCopyOperation(event, draggedEditor); if (!copyEditor) { diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 8fcaa030c6a..a604990551a 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/editorgroupview'; import { EditorGroupModel, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroupModel, isSerializedEditorGroupModel } from 'vs/workbench/common/editor/editorGroupModel'; -import { EditorOptions, GroupIdentifier, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, EditorResourceAccessor, IEditorMoveEvent, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; +import { GroupIdentifier, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, EditorResourceAccessor, IEditorMoveEvent, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { Event, Emitter, Relay } from 'vs/base/common/event'; @@ -47,7 +47,7 @@ import { hash } from 'vs/base/common/hash'; import { guessMimeTypes } from 'vs/base/common/mime'; import { extname, isEqual } from 'vs/base/common/resources'; import { FileAccess, Schemas } from 'vs/base/common/network'; -import { EditorActivation, EditorOpenContext } from 'vs/platform/editor/common/editor'; +import { EditorActivation, EditorOpenContext, IEditorOptions } from 'vs/platform/editor/common/editor'; import { IDialogService, IFileDialogService, ConfirmResult } from 'vs/platform/dialogs/common/dialogs'; import { ILogService } from 'vs/platform/log/common/log'; import { Codicon } from 'vs/base/common/codicons'; @@ -291,7 +291,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { if (this.isEmpty) { EventHelper.stop(e); - this.openEditor(this.editorService.createEditorInput({ forceUntitled: true }), EditorOptions.create({ pinned: true })); + this.openEditor(this.editorService.createEditorInput({ forceUntitled: true }), { pinned: true }); } })); @@ -461,11 +461,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } // Determine editor options - let options: EditorOptions; + let options: IEditorOptions; if (from instanceof EditorGroupView) { options = getActiveTextEditorOptions(from); // if we copy from another group, ensure to copy its active editor viewstate } else { - options = new EditorOptions(); + options = Object.create(null); } const activeEditor = this.model.activeEditor; @@ -904,7 +904,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { //#region openEditor() - async openEditor(editor: EditorInput, options?: EditorOptions): Promise { + async openEditor(editor: EditorInput, options?: IEditorOptions): Promise { // Guard against invalid inputs. Disposed inputs // should never open because they emit no events @@ -988,7 +988,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { return showEditorResult; } - private doShowEditor(editor: EditorInput, context: { active: boolean, isNew: boolean }, options?: EditorOptions): Promise { + private doShowEditor(editor: EditorInput, context: { active: boolean, isNew: boolean }, options?: IEditorOptions): Promise { // Show in editor control if the active editor changed let openEditorPromise: Promise; @@ -1021,7 +1021,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { return openEditorPromise; } - private async doHandleOpenEditorError(error: Error, editor: EditorInput, options?: EditorOptions): Promise { + private async doHandleOpenEditorError(error: Error, editor: EditorInput, options?: IEditorOptions): Promise { // Report error only if we are not told to ignore errors that occur from opening an editor if (!isPromiseCanceledError(error) && (!options || !options.ignoreError)) { @@ -1111,7 +1111,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { //#region openEditors() - async openEditors(editors: { editor: EditorInput, options?: EditorOptions }[]): Promise { + async openEditors(editors: { editor: EditorInput, options?: IEditorOptions }[]): Promise { if (!editors.length) { return null; } @@ -1126,7 +1126,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // Open the other ones inactive const startingIndex = this.getIndexOfEditor(editor) + 1; await Promises.settled(editors.map(async ({ editor, options }, index) => { - const adjustedEditorOptions = options || new EditorOptions(); + const adjustedEditorOptions = options || Object.create(null); adjustedEditorOptions.inactive = true; adjustedEditorOptions.pinned = true; adjustedEditorOptions.index = startingIndex + index; @@ -1144,7 +1144,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { //#region moveEditor() - moveEditor(editor: EditorInput, target: IEditorGroupView, options?: EditorOptions): void { + moveEditor(editor: EditorInput, target: IEditorGroupView, options?: IEditorOptions): void { // Move within same group if (this === target) { @@ -1193,11 +1193,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // When moving/copying an editor, try to preserve as much view state as possible // by checking for the editor to be a text editor and creating the options accordingly // if so - const options = getActiveTextEditorOptions(this, editor, EditorOptions.create({ + const options = getActiveTextEditorOptions(this, editor, { ...openOptions, pinned: true, // always pin moved editor sticky: !keepCopy && this.model.isSticky(editor) // preserve sticky state only if editor is moved (https://github.com/microsoft/vscode/issues/99035) - })); + }); // Indicate will move event if (!keepCopy) { @@ -1221,7 +1221,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { //#region copyEditor() - copyEditor(editor: EditorInput, target: IEditorGroupView, options?: EditorOptions): void { + copyEditor(editor: EditorInput, target: IEditorGroupView, options?: IEditorOptions): void { // Move within same group because we do not support to show the same editor // multiple times in the same group @@ -1319,16 +1319,16 @@ export class EditorGroupView extends Themable implements IEditorGroupView { activation = EditorActivation.PRESERVE; } - const options = EditorOptions.create({ preserveFocus, activation }); - - // When closing an editor due to an error we can end up in a loop where we continue closing - // editors that fail to open (e.g. when the file no longer exists). We do not want to show - // repeated errors in this case to the user. As such, if we open the next editor and we are - // in a scope of a previous editor failing, we silence the input errors until the editor is - // opened by setting ignoreError: true. - if (fromError) { - options.ignoreError = true; - } + const options: IEditorOptions = { + preserveFocus, + activation, + // When closing an editor due to an error we can end up in a loop where we continue closing + // editors that fail to open (e.g. when the file no longer exists). We do not want to show + // repeated errors in this case to the user. As such, if we open the next editor and we are + // in a scope of a previous editor failing, we silence the input errors until the editor is + // opened by setting ignoreError: true. + ignoreError: fromError + }; this.openEditor(nextActiveEditor, options); } @@ -1651,7 +1651,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { if (options) { options.index = index; } else { - options = EditorOptions.create({ index }); + options = { index }; } options.inactive = !isActiveEditor; @@ -1793,7 +1793,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { export interface EditorReplacement extends IEditorReplacement { readonly editor: EditorInput; readonly replacement: EditorInput; - readonly options?: EditorOptions; + readonly options?: IEditorOptions; } registerThemingParticipant((theme, collector) => { diff --git a/src/vs/workbench/browser/parts/editor/editorPane.ts b/src/vs/workbench/browser/parts/editor/editorPane.ts index cd44c9851f8..b07b6a1c1f7 100644 --- a/src/vs/workbench/browser/parts/editor/editorPane.ts +++ b/src/vs/workbench/browser/parts/editor/editorPane.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Composite } from 'vs/workbench/browser/composite'; -import { EditorOptions, IEditorPane, GroupIdentifier, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorPane, GroupIdentifier, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; @@ -58,8 +58,8 @@ export abstract class EditorPane extends Composite implements IEditorPane { protected _input: EditorInput | undefined; get input(): EditorInput | undefined { return this._input; } - protected _options: EditorOptions | undefined; - get options(): EditorOptions | undefined { return this._options; } + protected _options: IEditorOptions | undefined; + get options(): IEditorOptions | undefined { return this._options; } private _group: IEditorGroup | undefined; get group(): IEditorGroup | undefined { return this._group; } @@ -106,7 +106,7 @@ export abstract class EditorPane extends Composite implements IEditorPane { */ async setInput(input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { this._input = input; - this._options = options as EditorOptions; + this._options = options; } /** @@ -132,7 +132,7 @@ export abstract class EditorPane extends Composite implements IEditorPane { * to the current input. */ setOptions(options: IEditorOptions | undefined): void { - this._options = options as EditorOptions; + this._options = options; } override setVisible(visible: boolean, group?: IEditorGroup): void { diff --git a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts index f39d76281cd..926dc846f47 100644 --- a/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts +++ b/src/vs/workbench/browser/parts/editor/sideBySideEditor.ts @@ -5,7 +5,7 @@ import { Dimension, $, clearNode } from 'vs/base/browser/dom'; import { Registry } from 'vs/platform/registry/common/platform'; -import { EditorOptions, IEditorControl, IEditorPane, IEditorOpenContext, EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorControl, IEditorPane, IEditorOpenContext, EditorExtensions } from 'vs/workbench/common/editor'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; @@ -20,6 +20,7 @@ import { SplitView, Sizing, Orientation } from 'vs/base/browser/ui/splitview/spl import { Event, Relay, Emitter } from 'vs/base/common/event'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { assertIsDefined } from 'vs/base/common/types'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export class SideBySideEditor extends EditorPane { @@ -96,14 +97,14 @@ export class SideBySideEditor extends EditorPane { this.updateStyles(); } - override async setInput(input: SideBySideEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: SideBySideEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { const oldInput = this.input; await super.setInput(input, options, context, token); return this.updateInput(oldInput, input, options, context, token); } - override setOptions(options: EditorOptions | undefined): void { + override setOptions(options: IEditorOptions | undefined): void { if (this.primaryEditorPane) { this.primaryEditorPane.setOptions(options); } @@ -164,7 +165,7 @@ export class SideBySideEditor extends EditorPane { return this.secondaryEditorPane; } - private async updateInput(oldInput: EditorInput | undefined, newInput: SideBySideEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + private async updateInput(oldInput: EditorInput | undefined, newInput: SideBySideEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { if (!newInput.matches(oldInput)) { if (oldInput) { this.disposeEditors(); @@ -183,7 +184,7 @@ export class SideBySideEditor extends EditorPane { ]); } - private setNewInput(newInput: SideBySideEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + private setNewInput(newInput: SideBySideEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { const secondaryEditor = this.doCreateEditor(newInput.secondary, assertIsDefined(this.secondaryEditorContainer)); const primaryEditor = this.doCreateEditor(newInput.primary, assertIsDefined(this.primaryEditorContainer)); @@ -203,7 +204,7 @@ export class SideBySideEditor extends EditorPane { return editor; } - private async onEditorsCreated(secondary: EditorPane, primary: EditorPane, secondaryInput: EditorInput, primaryInput: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + private async onEditorsCreated(secondary: EditorPane, primary: EditorPane, secondaryInput: EditorInput, primaryInput: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { this.secondaryEditorPane = secondary; this.primaryEditorPane = primary; diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index b3e603c3980..9c2d030f364 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -9,7 +9,7 @@ import { isObject, isArray, assertIsDefined, withUndefinedAsNull } from 'vs/base import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IDiffEditorOptions, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BaseTextEditor, IEditorConfiguration } from 'vs/workbench/browser/parts/editor/textEditor'; -import { EditorOptions, TEXT_DIFF_EDITOR_ID, IEditorInputFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { TEXT_DIFF_EDITOR_ID, IEditorInputFactoryRegistry, EditorExtensions, ITextDiffEditorPane, IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator'; @@ -107,7 +107,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan return this.instantiationService.createInstance(DiffEditorWidget, parent, configuration, {}); } - override async setInput(input: DiffEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: DiffEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { // Dispose previous diff navigator this.diffNavigatorDisposables.clear(); @@ -190,7 +190,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan return false; } - private openAsBinary(input: DiffEditorInput, options: EditorOptions | undefined): void { + private openAsBinary(input: DiffEditorInput, options: IEditorOptions | undefined): void { const originalInput = input.originalInput; const modifiedInput = input.modifiedInput; @@ -210,18 +210,13 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan // because we are triggering another openEditor() call // and do not control the initial intent that resulted // in us now opening as binary. - const preservingOptions: IEditorOptions = { + options = { + ...options, activation: EditorActivation.PRESERVE, pinned: this.group?.isPinned(input), sticky: this.group?.isSticky(input) }; - if (options) { - options.overwrite(preservingOptions); - } else { - options = EditorOptions.create(preservingOptions); - } - // Replace this editor with the binary one this.editorService.replaceEditors([{ editor: input, replacement: binaryDiffInput, options }], this.group || ACTIVE_GROUP); } diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index 4030f05aa15..5bab2bdab68 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -10,7 +10,7 @@ import { Event } from 'vs/base/common/event'; import { isObject, assertIsDefined, withNullAsUndefined } from 'vs/base/common/types'; import { Dimension } from 'vs/base/browser/dom'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; -import { EditorOptions, IEditorMemento, ITextEditorPane, IEditorCloseEvent, IEditorInput, IEditorOpenContext, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { IEditorMemento, ITextEditorPane, IEditorCloseEvent, IEditorInput, IEditorOpenContext, EditorResourceAccessor, SideBySideEditor, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { computeEditorAriaLabel } from 'vs/workbench/browser/editor'; @@ -21,7 +21,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; -import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { isCodeEditor, getCodeEditor } from 'vs/editor/browser/editorBrowser'; import { IEditorGroupsService, IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -29,6 +29,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IExtUri } from 'vs/base/common/resources'; import { MutableDisposable } from 'vs/base/common/lifecycle'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export interface IEditorConfiguration { editor: object; @@ -46,7 +47,7 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa private editorControl: IEditor | undefined; private editorContainer: HTMLElement | undefined; private hasPendingConfigurationChange: boolean | undefined; - private lastAppliedEditorOptions?: IEditorOptions; + private lastAppliedEditorOptions?: ICodeEditorOptions; private editorMemento: IEditorMemento; private readonly groupListener = this._register(new MutableDisposable()); @@ -101,10 +102,10 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa } } - protected computeConfiguration(configuration: IEditorConfiguration): IEditorOptions { + protected computeConfiguration(configuration: IEditorConfiguration): ICodeEditorOptions { // Specific editor options always overwrite user configuration - const editorConfiguration: IEditorOptions = isObject(configuration.editor) ? deepClone(configuration.editor) : Object.create(null); + const editorConfiguration: ICodeEditorOptions = isObject(configuration.editor) ? deepClone(configuration.editor) : Object.create(null); Object.assign(editorConfiguration, this.getConfigurationOverrides()); // ARIA label @@ -117,7 +118,7 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa return this._input ? computeEditorAriaLabel(this._input, undefined, this.group, this.editorGroupService.count) : localize('editor', "Editor"); } - protected getConfigurationOverrides(): IEditorOptions { + protected getConfigurationOverrides(): ICodeEditorOptions { return { overviewRulerLanes: 3, lineNumbersMinChars: 3, @@ -149,13 +150,13 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa * * The passed in configuration object should be passed to the editor control when creating it. */ - protected createEditorControl(parent: HTMLElement, configuration: IEditorOptions): IEditor { + protected createEditorControl(parent: HTMLElement, configuration: ICodeEditorOptions): IEditor { // Use a getter for the instantiation service since some subclasses might use scoped instantiation services return this.instantiationService.createInstance(CodeEditorWidget, parent, configuration, {}); } - override async setInput(input: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); // Update editor options after having set the input. We do this because there can be @@ -167,7 +168,7 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa editorContainer.setAttribute('aria-label', this.computeAriaLabel()); } - override setOptions(options: EditorOptions | undefined): void { + override setOptions(options: IEditorOptions | undefined): void { if (options) { applyTextEditorOptions(options, assertIsDefined(this.getControl()), ScrollType.Smooth); } diff --git a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts index 0c2cc04db9a..7c3930d3204 100644 --- a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { assertIsDefined, withNullAsUndefined } from 'vs/base/common/types'; import { ICodeEditor, getCodeEditor, IPasteEvent } from 'vs/editor/browser/editorBrowser'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { AbstractTextResourceEditorInput, TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; @@ -25,8 +25,9 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IModelService } from 'vs/editor/common/services/modelService'; import { IModeService } from 'vs/editor/common/services/modeService'; import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; -import { EditorOption, IEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { EditorOption, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { ModelConstants } from 'vs/editor/common/model'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; /** * An editor implementation that is capable of showing the contents of resource inputs. Uses @@ -55,7 +56,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor { return localize('textEditor', "Text Editor"); } - override async setInput(input: AbstractTextResourceEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: AbstractTextResourceEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { // Remember view settings if input changes this.saveTextResourceEditorViewState(this.input); @@ -181,7 +182,7 @@ export class TextResourceEditor extends AbstractTextResourceEditor { super(TextResourceEditor.ID, telemetryService, instantiationService, storageService, textResourceConfigurationService, themeService, editorGroupService, editorService); } - protected override createEditorControl(parent: HTMLElement, configuration: IEditorOptions): IEditor { + protected override createEditorControl(parent: HTMLElement, configuration: ICodeEditorOptions): IEditor { const control = super.createEditorControl(parent, configuration); // Install a listener for paste to update this editors diff --git a/src/vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor.ts b/src/vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor.ts index 9019d27eb43..a08710ea570 100644 --- a/src/vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor.ts +++ b/src/vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor.ts @@ -5,7 +5,7 @@ import 'vs/css!./media/workspacetrusteditor'; import { localize } from 'vs/nls'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -21,6 +21,7 @@ import { ICommandService } from 'vs/platform/commands/common/commands'; import { isSingleFolderWorkspaceIdentifier, toWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { EditorDescriptor } from 'vs/workbench/browser/editor'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export class WorkspaceTrustRequiredEditor extends EditorPane { @@ -59,7 +60,7 @@ export class WorkspaceTrustRequiredEditor extends EditorPane { parent.appendChild(this.scrollbar.getDomNode()); } - override async setInput(input: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); // Check for cancellation diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 9d57b508d33..84b57935f39 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -9,7 +9,7 @@ import { assertIsDefined, isUndefinedOrNull } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IEditor, IEditorViewState, IDiffEditor } from 'vs/editor/common/editorCommon'; -import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceEditorInput, IResourceEditorInput, EditorActivation, EditorOpenContext, EditorOverride } from 'vs/platform/editor/common/editor'; +import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceEditorInput, IResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IInstantiationService, IConstructorSignature0, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation'; import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -695,164 +695,6 @@ export function isEditorInputWithOptions(obj: unknown): obj is IEditorInputWithO return !!editorInputWithOptions && !!editorInputWithOptions.editor; } -/** - * The editor options is the base class of options that can be passed in when opening an editor. - */ -export class EditorOptions implements IEditorOptions { - - /** - * Helper to create EditorOptions inline. - */ - static create(settings: IEditorOptions): EditorOptions { - const options = new EditorOptions(); - options.overwrite(settings); - - return options; - } - - /** - * Tells the editor to not receive keyboard focus when the editor is being opened. - * - * Will also not activate the group the editor opens in unless the group is already - * the active one. This behaviour can be overridden via the `activation` option. - */ - preserveFocus: boolean | undefined; - - /** - * This option is only relevant if an editor is opened into a group that is not active - * already and allows to control if the inactive group should become active, restored - * or preserved. - * - * By default, the editor group will become active unless `preserveFocus` or `inactive` - * is specified. - */ - activation: EditorActivation | undefined; - - /** - * Tells the editor to reload the editor input in the editor even if it is identical to the one - * already showing. By default, the editor will not reload the input if it is identical to the - * one showing. - */ - forceReload: boolean | undefined; - - /** - * Will reveal the editor if it is already opened and visible in any of the opened editor groups. - */ - revealIfVisible: boolean | undefined; - - /** - * Will reveal the editor if it is already opened (even when not visible) in any of the opened editor groups. - */ - revealIfOpened: boolean | undefined; - - /** - * An editor that is pinned remains in the editor stack even when another editor is being opened. - * An editor that is not pinned will always get replaced by another editor that is not pinned. - */ - pinned: boolean | undefined; - - /** - * An editor that is sticky moves to the beginning of the editors list within the group and will remain - * there unless explicitly closed. Operations such as "Close All" will not close sticky editors. - */ - sticky: boolean | undefined; - - /** - * The index in the document stack where to insert the editor into when opening. - */ - index: number | undefined; - - /** - * An active editor that is opened will show its contents directly. Set to true to open an editor - * in the background without loading its contents. - * - * Will also not activate the group the editor opens in unless the group is already - * the active one. This behaviour can be overridden via the `activation` option. - */ - inactive: boolean | undefined; - - /** - * Will not show an error in case opening the editor fails and thus allows to show a custom error - * message as needed. By default, an error will be presented as notification if opening was not possible. - */ - ignoreError: boolean | undefined; - - /** - * Allows to override the editor that should be used to display the input: - * - `undefined`: let the editor decide for itself - * - `string`: specific override by id - * - `EditorOverride`: specific override handling - */ - override: string | EditorOverride | undefined; - - /** - * A optional hint to signal in which context the editor opens. - * - * If configured to be `EditorOpenContext.USER`, this hint can be - * used in various places to control the experience. For example, - * if the editor to open fails with an error, a notification could - * inform about this in a modal dialog. If the editor opened through - * some background task, the notification would show in the background, - * not as a modal dialog. - */ - context: EditorOpenContext | undefined; - - /** - * Overwrites option values from the provided bag. - */ - overwrite(options: IEditorOptions): EditorOptions { - if (typeof options.forceReload === 'boolean') { - this.forceReload = options.forceReload; - } - - if (typeof options.revealIfVisible === 'boolean') { - this.revealIfVisible = options.revealIfVisible; - } - - if (typeof options.revealIfOpened === 'boolean') { - this.revealIfOpened = options.revealIfOpened; - } - - if (typeof options.preserveFocus === 'boolean') { - this.preserveFocus = options.preserveFocus; - } - - if (typeof options.activation === 'number') { - this.activation = options.activation; - } - - if (typeof options.pinned === 'boolean') { - this.pinned = options.pinned; - } - - if (typeof options.sticky === 'boolean') { - this.sticky = options.sticky; - } - - if (typeof options.inactive === 'boolean') { - this.inactive = options.inactive; - } - - if (typeof options.ignoreError === 'boolean') { - this.ignoreError = options.ignoreError; - } - - if (typeof options.index === 'number') { - this.index = options.index; - } - - if (options.override !== undefined) { - this.override = options.override; - } - - if (typeof options.context === 'number') { - this.context = options.context; - } - - return this; - } -} - /** * Context passed into `EditorPane#setInput` to give additional * context information around why the editor was opened. diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index 3f99c17d638..ecc8962769e 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -25,7 +25,7 @@ import { ResolvedKeybinding, KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput'; import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, IExtension, ExtensionContainers } from 'vs/workbench/contrib/extensions/common/extensions'; import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { UpdateAction, ReloadAction, MaliciousStatusLabelAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction, SetFileIconThemeAction, SetColorThemeAction, @@ -69,6 +69,7 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { Delegate } from 'vs/workbench/contrib/extensions/browser/extensionsList'; import { renderMarkdown } from 'vs/base/browser/markdownRenderer'; import { attachKeybindingLabelStyler } from 'vs/platform/theme/common/styler'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; class NavBar extends Disposable { @@ -325,7 +326,7 @@ export class ExtensionEditor extends EditorPane { return disposables; } - override async setInput(input: ExtensionsInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: ExtensionsInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); if (this.template) { await this.updateTemplate(input, this.template, !!options?.preserveFocus); diff --git a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts index fb97428e1f6..15845c6758d 100644 --- a/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/binaryFileEditor.ts @@ -7,13 +7,12 @@ import { localize } from 'vs/nls'; import { BaseBinaryResourceEditor } from 'vs/workbench/browser/parts/editor/binaryEditor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { EditorOptions } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; import { BINARY_FILE_EDITOR_ID } from 'vs/workbench/contrib/files/common/files'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { EditorOverride } from 'vs/platform/editor/common/editor'; +import { EditorOverride, IEditorOptions } from 'vs/platform/editor/common/editor'; import { IEditorOverrideService } from 'vs/workbench/services/editor/common/editorOverrideService'; /** @@ -41,7 +40,7 @@ export class BinaryFileEditor extends BaseBinaryResourceEditor { ); } - private async openInternal(input: EditorInput, options: EditorOptions | undefined): Promise { + private async openInternal(input: EditorInput, options: IEditorOptions | undefined): Promise { if (input instanceof FileEditorInput && this.group) { // Enforce to open the input as text to enable our text based viewer diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index 659a04688bf..1687adad197 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -12,7 +12,7 @@ import { toAction } from 'vs/base/common/actions'; import { VIEWLET_ID, TEXT_FILE_EDITOR_ID } from 'vs/workbench/contrib/files/common/files'; import { ITextFileService, TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; -import { EditorOptions, IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorOpenContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; @@ -105,7 +105,7 @@ export class TextFileEditor extends BaseTextEditor { return this._input as FileEditorInput; } - override async setInput(input: FileEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: FileEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { // Update/clear view settings if input changes this.doSaveOrClearTextEditorViewState(this.input); @@ -157,7 +157,7 @@ export class TextFileEditor extends BaseTextEditor { } } - protected handleSetInputError(error: Error, input: FileEditorInput, options: EditorOptions | undefined): void { + protected handleSetInputError(error: Error, input: FileEditorInput, options: IEditorOptions | undefined): void { // In case we tried to open a file inside the text editor and the response // indicates that this is not a text file, reopen the file through the binary @@ -197,19 +197,18 @@ export class TextFileEditor extends BaseTextEditor { throw error; } - private openAsBinary(input: FileEditorInput, options: EditorOptions | undefined): void { + private openAsBinary(input: FileEditorInput, options: IEditorOptions | undefined): void { input.setForceOpenAsBinary(); // Make sure to not steal away the currently active group // because we are triggering another openEditor() call // and do not control the initial intent that resulted // in us now opening as binary. - const preservingOptions: IEditorOptions = { activation: EditorActivation.PRESERVE, override: EditorOverride.DISABLED }; - if (options) { - options.overwrite(preservingOptions); - } else { - options = EditorOptions.create(preservingOptions); - } + options = { + ...options, + activation: EditorActivation.PRESERVE, + override: EditorOverride.DISABLED + }; this.editorService.openEditor(input, options, this.group); } diff --git a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts index 534784dfc0f..0674515bb52 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts @@ -6,7 +6,6 @@ import { localize } from 'vs/nls'; import { TextFileEditor } from 'vs/workbench/contrib/files/browser/editors/textFileEditor'; import { FileEditorInput } from 'vs/workbench/contrib/files/browser/editors/fileEditorInput'; -import { EditorOptions } from 'vs/workbench/common/editor'; import { FileOperationError, FileOperationResult, IFileService, MIN_MAX_MEMORY_SIZE_MB, FALLBACK_MAX_MEMORY_SIZE_MB } from 'vs/platform/files/common/files'; import { createErrorWithActions } from 'vs/base/common/errors'; import { toAction } from 'vs/base/common/actions'; @@ -25,6 +24,7 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; import { IProductService } from 'vs/platform/product/common/productService'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; /** * An implementation of editor for file system resources. @@ -52,7 +52,7 @@ export class NativeTextFileEditor extends TextFileEditor { super(telemetryService, fileService, viewletService, instantiationService, contextService, storageService, textResourceConfigurationService, editorService, themeService, editorGroupService, textFileService, explorerService, uriIdentityService); } - protected override handleSetInputError(error: Error, input: FileEditorInput, options: EditorOptions | undefined): void { + protected override handleSetInputError(error: Error, input: FileEditorInput, options: IEditorOptions | undefined): void { // Allow to restart with higher memory limit if the file is too large if ((error).fileOperationResult === FileOperationResult.FILE_EXCEEDS_MEMORY_LIMIT) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 9472f2455ba..fe67cd9da07 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -8,7 +8,7 @@ import * as DOM from 'vs/base/browser/dom'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { notebookCellBorder, NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget'; import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService'; import { NotebookDiffEditorInput } from '../notebookDiffEditorInput'; @@ -20,7 +20,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { diffDiagonalFill, diffInserted, diffRemoved, editorBackground, focusBorder, foreground } from 'vs/platform/theme/common/colorRegistry'; import { INotebookEditorWorkerService } from 'vs/workbench/contrib/notebook/common/services/notebookWorkerService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo'; import { getPixelRatio, getZoomLevel } from 'vs/base/browser/browser'; import { CellEditState, ICellOutputViewModel, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel, IInsetRenderOutput, NotebookLayoutInfo, NOTEBOOK_DIFF_EDITOR_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; @@ -41,6 +41,7 @@ import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/ren import { NotebookDiffEditorEventDispatcher, NotebookDiffLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/diff/eventDispatcher'; import { readFontInfo } from 'vs/editor/browser/config/configuration'; import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; const $ = DOM.$; @@ -101,7 +102,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD super(NotebookTextDiffEditor.ID, telemetryService, themeService, storageService); this._notebookOptions = new NotebookOptions(this.configurationService); this._register(this._notebookOptions); - const editorOptions = this.configurationService.getValue('editor'); + const editorOptions = this.configurationService.getValue('editor'); this._fontInfo = readFontInfo(BareFontInfo.createFromRawSettings(editorOptions, getZoomLevel(), getPixelRatio())); this._revealFirst = true; this._outputRenderer = new OutputRenderer(this, this.instantiationService); @@ -292,7 +293,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } } - override async setInput(input: NotebookDiffEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: NotebookDiffEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); const model = await input.resolve(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index b0000fdcc15..4cd1cfb84ef 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -11,14 +11,14 @@ import 'vs/css!./media/notebook'; import { localize } from 'vs/nls'; import { extname } from 'vs/base/common/resources'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { EditorOverride } from 'vs/platform/editor/common/editor'; +import { EditorOverride, IEditorOptions } from 'vs/platform/editor/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { EditorInputCapabilities, EditorOptions, IEditorInput, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInputCapabilities, IEditorInput, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget'; import { INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; @@ -152,7 +152,7 @@ export class NotebookEditor extends EditorPane { return !!value && (DOM.isAncestor(activeElement, value.getDomNode() || DOM.isAncestor(activeElement, value.getOverflowContainerDomNode()))); } - override async setInput(input: NotebookEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: NotebookEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { clearMarks(input.resource); mark(input.resource, 'startTime'); const group = this.group!; diff --git a/src/vs/workbench/contrib/output/browser/outputView.ts b/src/vs/workbench/contrib/output/browser/outputView.ts index 93cab3db91a..5d8125642d1 100644 --- a/src/vs/workbench/contrib/output/browser/outputView.ts +++ b/src/vs/workbench/contrib/output/browser/outputView.ts @@ -6,13 +6,13 @@ import * as nls from 'vs/nls'; import { IAction } from 'vs/base/common/actions'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor'; import { OUTPUT_VIEW_ID, IOutputService, CONTEXT_IN_OUTPUT, IOutputChannel, CONTEXT_ACTIVE_LOG_OUTPUT, CONTEXT_OUTPUT_SCROLL_LOCK } from 'vs/workbench/contrib/output/common/output'; import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; @@ -37,6 +37,7 @@ import { editorBackground, selectBorder } from 'vs/platform/theme/common/colorRe import { SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { Dimension } from 'vs/base/browser/dom'; import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export class OutputViewPane extends ViewPane { @@ -146,7 +147,7 @@ export class OutputViewPane extends ViewPane { this.channelId = channel.id; const descriptor = this.outputService.getChannelDescriptor(channel.id); CONTEXT_ACTIVE_LOG_OUTPUT.bindTo(this.contextKeyService).set(!!descriptor?.file && descriptor?.log); - this.editorPromise = this.editor.setInput(this.createInput(channel), EditorOptions.create({ preserveFocus: true }), Object.create(null), CancellationToken.None) + this.editorPromise = this.editor.setInput(this.createInput(channel), { preserveFocus: true }, Object.create(null), CancellationToken.None) .then(() => this.editor); } @@ -186,7 +187,7 @@ export class OutputEditor extends AbstractTextResourceEditor { return nls.localize('output', "Output"); } - protected override getConfigurationOverrides(): IEditorOptions { + protected override getConfigurationOverrides(): ICodeEditorOptions { const options = super.getConfigurationOverrides(); options.wordWrap = 'on'; // all output editors wrap options.lineNumbers = 'off'; // all output editors hide line numbers @@ -221,7 +222,7 @@ export class OutputEditor extends AbstractTextResourceEditor { return channel ? nls.localize('outputViewWithInputAriaLabel', "{0}, Output panel", channel.label) : nls.localize('outputViewAriaLabel', "Output panel"); } - override async setInput(input: TextResourceEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: TextResourceEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { const focus = !(options && options.preserveFocus); if (input.matches(this.input)) { return; diff --git a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts index 21f20c9720e..e4f06586a13 100644 --- a/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts @@ -15,7 +15,7 @@ import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLa import { IAction, Action, Separator } from 'vs/base/common/actions'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { KeybindingsEditorModel, KEYBINDING_ENTRY_TEMPLATE_ID } from 'vs/workbench/services/preferences/browser/keybindingsEditorModel'; @@ -48,6 +48,7 @@ import { IKeybindingItemEntry, IKeybindingsEditorPane } from 'vs/workbench/servi import { keybindingsRecordKeysIcon, keybindingsSortIcon, keybindingsAddIcon, preferencesClearInputIcon, keybindingsEditIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons'; import { ITableRenderer, ITableVirtualDelegate } from 'vs/base/browser/ui/table/table'; import { KeybindingsEditorInput } from 'vs/workbench/services/preferences/browser/keybindingsEditorInput'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; const $ = DOM.$; @@ -146,7 +147,7 @@ export class KeybindingsEditor extends EditorPane implements IKeybindingsEditorP this.createBody(keybindingsEditorElement); } - override setInput(input: KeybindingsEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override setInput(input: KeybindingsEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { this.keybindingsEditorContextKey.set(true); return super.setInput(input, options, context, token) .then(() => this.render(!!(options && options.preserveFocus))); diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts index 569ddbc0665..c97ed166b2b 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts @@ -18,7 +18,7 @@ import { URI } from 'vs/base/common/uri'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { EditorExtensionsRegistry, IEditorContributionDescription, registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; -import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; +import { IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; import { FindController } from 'vs/editor/contrib/find/findController'; @@ -28,6 +28,7 @@ import { SelectionHighlighter } from 'vs/editor/contrib/multicursor/multicursor' import * as nls from 'vs/nls'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IConstructorSignature1, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; import { IEditorProgressService } from 'vs/platform/progress/common/progress'; @@ -41,7 +42,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IEditorRegistry } from 'vs/workbench/browser/editor'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; -import { EditorExtensions, EditorOptions, IEditorControl, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorExtensions, IEditorControl, IEditorOpenContext } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { TextResourceEditorModel } from 'vs/workbench/common/editor/textResourceEditorModel'; import { DefaultSettingsRenderer, FolderSettingsRenderer, IPreferencesRenderer, UserSettingsRenderer, WorkspaceSettingsRenderer } from 'vs/workbench/contrib/preferences/browser/preferencesRenderers'; @@ -984,7 +985,7 @@ export class DefaultPreferencesEditor extends BaseTextEditor { return contributions; } - override createEditorControl(parent: HTMLElement, configuration: IEditorOptions): editorCommon.IEditor { + override createEditorControl(parent: HTMLElement, configuration: ICodeEditorOptions): editorCommon.IEditor { const editor = this.instantiationService.createInstance(CodeEditorWidget, parent, configuration, { contributions: DefaultPreferencesEditor._getContributions() }); // Inform user about editor being readonly if user starts type @@ -1001,7 +1002,7 @@ export class DefaultPreferencesEditor extends BaseTextEditor { } } - protected override getConfigurationOverrides(): IEditorOptions { + protected override getConfigurationOverrides(): ICodeEditorOptions { const options = super.getConfigurationOverrides(); options.readOnly = true; if (this.input) { @@ -1022,7 +1023,7 @@ export class DefaultPreferencesEditor extends BaseTextEditor { return options; } - override async setInput(input: DefaultPreferencesEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: DefaultPreferencesEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); const editorModel = await this.input!.resolve(); if (!editorModel) { diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts index 81331918be9..5e1a19f6d27 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts @@ -37,7 +37,7 @@ import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { BaseTextEditor } from 'vs/workbench/browser/parts/editor/textEditor'; -import { EditorInputCapabilities, EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { EditorInputCapabilities, IEditorOpenContext } from 'vs/workbench/common/editor'; import { ExcludePatternInputWidget, IncludePatternInputWidget } from 'vs/workbench/contrib/search/browser/patternInputWidget'; import { SearchWidget } from 'vs/workbench/contrib/search/browser/searchWidget'; import { InputBoxFocusedKey } from 'vs/workbench/contrib/search/common/constants'; @@ -59,6 +59,7 @@ import { Schemas } from 'vs/base/common/network'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { TextSearchCompleteMessage } from 'vs/workbench/services/search/common/searchExtTypes'; import { INotificationService } from 'vs/platform/notification/common/notification'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; const RESULT_LINE_REGEX = /^(\s+)(\d+)(:| )(\s+)(.*)$/; const FILE_LINE_REGEX = /^(\S.*):$/; @@ -671,7 +672,7 @@ export class SearchEditor extends BaseTextEditor { if (config.showIncludesExcludes !== undefined) { this.toggleIncludesExcludes(config.showIncludesExcludes); } } - override async setInput(newInput: SearchEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(newInput: SearchEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { this.saveViewState(); await super.setInput(newInput, options, context, token); diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts index 6b535316dd5..7db0c86e234 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts @@ -10,11 +10,12 @@ import { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/ import { isWeb } from 'vs/base/common/platform'; import { generateUuid } from 'vs/base/common/uuid'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewWindowDragMonitor } from 'vs/workbench/contrib/webview/browser/webviewWindowDragMonitor'; @@ -122,7 +123,7 @@ export class WebviewEditor extends EditorPane { super.clearInput(); } - public override async setInput(input: EditorInput, options: EditorOptions, context: IEditorOpenContext, token: CancellationToken): Promise { + public override async setInput(input: EditorInput, options: IEditorOptions, context: IEditorOpenContext, token: CancellationToken): Promise { if (input.matches(this.input)) { return; } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index 69a09d7258a..9d0674428f1 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -6,7 +6,7 @@ import 'vs/css!./gettingStarted'; import { localize } from 'vs/nls'; import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation'; -import { EditorOptions, IEditorInputSerializer, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorInputSerializer, IEditorOpenContext } from 'vs/workbench/common/editor'; import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { assertIsDefined } from 'vs/base/common/types'; import { $, addDisposableListener, append, clearNode, Dimension, reset } from 'vs/base/browser/dom'; @@ -59,6 +59,7 @@ import { joinPath } from 'vs/base/common/resources'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { asWebviewUri } from 'vs/workbench/api/common/shared/webview'; import { Schemas } from 'vs/base/common/network'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; const SLIDE_TRANSITION_TIME_MS = 250; const configurationKey = 'workbench.startupEditor'; @@ -225,7 +226,7 @@ export class GettingStartedPage extends EditorPane { this.recentlyOpened = workspacesService.getRecentlyOpened(); } - override async setInput(newInput: GettingStartedInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken) { + override async setInput(newInput: GettingStartedInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken) { this.container.classList.remove('animationReady'); this.editorInput = newInput; await super.setInput(newInput, options, context, token); diff --git a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart.ts b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart.ts index 7b1af890696..676462d52b6 100644 --- a/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart.ts +++ b/src/vs/workbench/contrib/welcome/walkThrough/browser/walkThroughPart.ts @@ -10,7 +10,7 @@ import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import * as strings from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { IDisposable, dispose, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { EditorOptions, IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorMemento, IEditorOpenContext } from 'vs/workbench/common/editor'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { WalkThroughInput } from 'vs/workbench/contrib/welcome/walkThrough/browser/walkThroughInput'; @@ -26,7 +26,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { Event } from 'vs/base/common/event'; import { isObject } from 'vs/base/common/types'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { IEditorOptions, EditorOption } from 'vs/editor/common/config/editorOptions'; +import { IEditorOptions as ICodeEditorOptions, EditorOption } from 'vs/editor/common/config/editorOptions'; import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { registerColor, focusBorder, textLinkForeground, textLinkActiveForeground, textPreformatForeground, contrastBorder, textBlockQuoteBackground, textBlockQuoteBorder } from 'vs/platform/theme/common/colorRegistry'; import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils'; @@ -39,6 +39,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor import { CancellationToken } from 'vs/base/common/cancellation'; import { domEvent } from 'vs/base/browser/event'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export const WALK_THROUGH_FOCUS = new RawContextKey('interactivePlaygroundFocus', false); @@ -267,7 +268,7 @@ export class WalkThroughPart extends EditorPane { this.scrollbar.setScrollPosition({ scrollTop: scrollPosition.scrollTop + scrollDimensions.height }); } - override setInput(input: WalkThroughInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override setInput(input: WalkThroughInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { if (this.input instanceof WalkThroughInput) { this.saveTextEditorViewState(this.input); } @@ -420,7 +421,7 @@ export class WalkThroughPart extends EditorPane { }); } - private getEditorOptions(language: string): IEditorOptions { + private getEditorOptions(language: string): ICodeEditorOptions { const config = deepClone(this.configurationService.getValue('editor', { overrideIdentifier: language })); return { ...isObject(config) ? config : Object.create(null), diff --git a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts index 97135eddb9e..0e98b4d7d95 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts @@ -43,7 +43,7 @@ import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService' import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; import { isSingleFolderWorkspaceIdentifier, toWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { EditorOptions, IEditorOpenContext } from 'vs/workbench/common/editor'; +import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { ChoiceAction } from 'vs/workbench/common/notifications'; import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugColors'; import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; @@ -53,6 +53,7 @@ import { IWorkbenchConfigurationService } from 'vs/workbench/services/configurat import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { WorkspaceTrustEditorInput } from 'vs/workbench/services/workspaces/browser/workspaceTrustEditorInput'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; export const shieldIcon = registerCodicon('workspace-trust-icon', Codicon.shield); @@ -581,7 +582,7 @@ export class WorkspaceTrustEditor extends EditorPane { this.rootElement.focus(); } - override async setInput(input: WorkspaceTrustEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: WorkspaceTrustEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); if (token.isCancellationRequested) { return; } diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 17ef1ad0f92..c2cb9b269f2 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -5,7 +5,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IResourceEditorInput, ITextEditorOptions, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; -import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, EditorOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; +import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; @@ -526,7 +526,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { if (resolvedInputWithOptionsAndGroup) { return (resolvedInputWithOptionsAndGroup.group ?? resolvedGroup).openEditor( resolvedInputWithOptionsAndGroup.editor, - this.toOptions(resolvedInputWithOptionsAndGroup.options) ?? resolvedOptions + resolvedInputWithOptionsAndGroup.options ?? resolvedOptions ); } } @@ -538,17 +538,17 @@ export class EditorService extends Disposable implements EditorServiceImpl { return undefined; } - doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | ITextEditorOptions | OpenInEditorGroup, group?: OpenInEditorGroup): [IEditorGroup, EditorInput, EditorOptions | undefined] | undefined { + doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | ITextEditorOptions | OpenInEditorGroup, group?: OpenInEditorGroup): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined { let resolvedGroup: IEditorGroup | undefined; let candidateGroup: OpenInEditorGroup | undefined; let typedEditor: EditorInput | undefined; - let typedOptions: EditorOptions | undefined; + let typedOptions: IEditorOptions | undefined; // Typed Editor Support if (editor instanceof EditorInput) { typedEditor = editor; - typedOptions = this.toOptions(optionsOrGroup as IEditorOptions); + typedOptions = optionsOrGroup as IEditorOptions; candidateGroup = group; resolvedGroup = this.findTargetGroup(typedEditor, typedOptions, candidateGroup); @@ -559,7 +559,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { const textInput = editor as IResourceEditorInputType; typedEditor = this.createEditorInput(textInput); if (typedEditor) { - typedOptions = textInput.options as EditorOptions; + typedOptions = textInput.options; candidateGroup = optionsOrGroup as OpenInEditorGroup; resolvedGroup = this.findTargetGroup(typedEditor, typedOptions, candidateGroup); @@ -583,7 +583,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { // group is it is opened as `SIDE_GROUP` with `preserveFocus:true`. // repeated Alt-clicking of files in the explorer always open // into the same side group and not cause a group to be created each time. - typedOptions.overwrite({ activation: EditorActivation.ACTIVATE }); + typedOptions.activation = EditorActivation.ACTIVATE; } return [resolvedGroup, typedEditor, typedOptions]; @@ -672,14 +672,6 @@ export class EditorService extends Disposable implements EditorServiceImpl { return neighbourGroup; } - private toOptions(options?: IEditorOptions | ITextEditorOptions | EditorOptions): EditorOptions { - if (!options || options instanceof EditorOptions) { - return options as EditorOptions; - } - - return (options ?? Object.create(null)) as EditorOptions; - } - //#endregion //#region openEditors() @@ -742,7 +734,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { } targetGroupEditors.push(editorOverride ? - { editor: editorOverride.editor, options: this.toOptions(editorOverride.options) } : + { editor: editorOverride.editor, options: editorOverride.options } : { editor, options } ); } @@ -924,7 +916,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { editor: replacementArg.editor, replacement: replacementArg.replacement, forceReplaceDirty: replacementArg.forceReplaceDirty, - options: this.toOptions(replacementArg.options) + options: replacementArg.options }); } else { const replacementArg = replaceEditorArg as IResourceEditorReplacement; @@ -932,7 +924,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { typedEditors.push({ editor: this.createEditorInput(replacementArg.editor), replacement: this.createEditorInput(replacementArg.replacement), - options: this.toOptions(replacementArg.replacement.options) + options: replacementArg.replacement.options }); } } diff --git a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts index 8d1248291e3..96b167f9aa5 100644 --- a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { workbenchInstantiationService, registerTestEditor, TestFileEditorInput, TestEditorPart, ITestInstantiationService, TestServiceAccessor, createEditorPart } from 'vs/workbench/test/browser/workbenchTestServices'; import { GroupDirection, GroupsOrder, MergeGroupMode, GroupOrientation, GroupChangeKind, GroupLocation } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { EditorOptions, CloseDirection, IEditorPartOptions, EditorsOrder } from 'vs/workbench/common/editor'; +import { CloseDirection, IEditorPartOptions, EditorsOrder } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { DisposableStore } from 'vs/base/common/lifecycle'; @@ -196,10 +196,10 @@ suite('EditorGroupsService', () => { const downGroup = part.addGroup(rightGroup, GroupDirection.DOWN); const rootGroupInput = new TestFileEditorInput(URI.file('foo/bar1'), TEST_EDITOR_INPUT_ID); - await rootGroup.openEditor(rootGroupInput, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(rootGroupInput, { pinned: true }); const rightGroupInput = new TestFileEditorInput(URI.file('foo/bar2'), TEST_EDITOR_INPUT_ID); - await rightGroup.openEditor(rightGroupInput, EditorOptions.create({ pinned: true })); + await rightGroup.openEditor(rightGroupInput, { pinned: true }); assert.strictEqual(part.groups.length, 3); @@ -293,7 +293,7 @@ suite('EditorGroupsService', () => { const input = new TestFileEditorInput(URI.file('foo/bar'), TEST_EDITOR_INPUT_ID); - await rootGroup.openEditor(input, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input, { pinned: true }); const rightGroup = part.addGroup(rootGroup, GroupDirection.RIGHT, { activate: true }); const downGroup = part.copyGroup(rootGroup, rightGroup, GroupDirection.DOWN); assert.strictEqual(groupAddedCounter, 2); @@ -323,13 +323,13 @@ suite('EditorGroupsService', () => { const input2 = new TestFileEditorInput(URI.file('foo/bar2'), TEST_EDITOR_INPUT_ID); const input3 = new TestFileEditorInput(URI.file('foo/bar3'), TEST_EDITOR_INPUT_ID); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input1, { pinned: true }); const rightGroup = part.addGroup(rootGroup, GroupDirection.RIGHT); - await rightGroup.openEditor(input2, EditorOptions.create({ pinned: true })); + await rightGroup.openEditor(input2, { pinned: true }); const downGroup = part.copyGroup(rootGroup, rightGroup, GroupDirection.DOWN); - await downGroup.openEditor(input3, EditorOptions.create({ pinned: true })); + await downGroup.openEditor(input3, { pinned: true }); part.activateGroup(rootGroup); @@ -410,8 +410,8 @@ suite('EditorGroupsService', () => { const input = new TestFileEditorInput(URI.file('foo/bar'), TEST_EDITOR_INPUT_ID); const inputInactive = new TestFileEditorInput(URI.file('foo/bar/inactive'), TEST_EDITOR_INPUT_ID); - await group.openEditor(input, EditorOptions.create({ pinned: true })); - await group.openEditor(inputInactive, EditorOptions.create({ inactive: true })); + await group.openEditor(input, { pinned: true }); + await group.openEditor(inputInactive, { inactive: true }); assert.strictEqual(group.isActive(input), true); assert.strictEqual(group.isActive(inputInactive), false); @@ -1144,8 +1144,8 @@ suite('EditorGroupsService', () => { const input = new TestFileEditorInput(URI.file('foo/bar'), TEST_EDITOR_INPUT_ID); const inputInactive = new TestFileEditorInput(URI.file('foo/bar/inactive'), TEST_EDITOR_INPUT_ID); - await group.openEditor(input, EditorOptions.create({ pinned: true })); - await group.openEditor(inputInactive, EditorOptions.create({ inactive: true })); + await group.openEditor(input, { pinned: true }); + await group.openEditor(inputInactive, { inactive: true }); assert.strictEqual(group.stickyCount, 0); assert.strictEqual(group.isSticky(input), false); @@ -1206,7 +1206,7 @@ suite('EditorGroupsService', () => { const inputSticky = new TestFileEditorInput(URI.file('foo/bar/sticky'), TEST_EDITOR_INPUT_ID); - await group.openEditor(inputSticky, EditorOptions.create({ sticky: true })); + await group.openEditor(inputSticky, { sticky: true }); assert.strictEqual(group.stickyCount, 2); assert.strictEqual(group.isSticky(input), false); @@ -1217,7 +1217,7 @@ suite('EditorGroupsService', () => { assert.strictEqual(group.getIndexOfEditor(inputSticky), 1); assert.strictEqual(group.getIndexOfEditor(input), 2); - await group.openEditor(input, EditorOptions.create({ sticky: true })); + await group.openEditor(input, { sticky: true }); assert.strictEqual(group.stickyCount, 3); assert.strictEqual(group.isSticky(input), true); diff --git a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts index e911c950310..d77f97eaf25 100644 --- a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EditorOptions, IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorInputFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; import { workbenchInstantiationService, TestFileEditorInput, registerTestEditor, TestEditorPart, createEditorPart, registerTestSideBySideEditor } from 'vs/workbench/test/browser/workbenchTestServices'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -68,7 +68,7 @@ suite('EditorsObserver', function () { const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_SERIALIZABLE_EDITOR_INPUT_ID); - await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input1, { pinned: true }); currentEditorsMRU = observer.editors; assert.strictEqual(currentEditorsMRU.length, 1); @@ -85,8 +85,8 @@ suite('EditorsObserver', function () { assert.strictEqual(observer.hasEditors(input2.resource), false); assert.strictEqual(observer.hasEditor({ resource: input2.resource, typeId: input2.typeId }), false); - await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true })); - await part.activeGroup.openEditor(input3, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input2, { pinned: true }); + await part.activeGroup.openEditor(input3, { pinned: true }); currentEditorsMRU = observer.editors; assert.strictEqual(currentEditorsMRU.length, 3); @@ -99,7 +99,7 @@ suite('EditorsObserver', function () { assert.strictEqual(observer.hasEditor({ resource: input2.resource, typeId: input2.typeId }), true); assert.strictEqual(observer.hasEditor({ resource: input3.resource, typeId: input3.typeId }), true); - await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input2, { pinned: true }); currentEditorsMRU = observer.editors; assert.strictEqual(currentEditorsMRU.length, 3); @@ -149,8 +149,8 @@ suite('EditorsObserver', function () { const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_SERIALIZABLE_EDITOR_INPUT_ID); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true, activation: EditorActivation.ACTIVATE })); - await sideGroup.openEditor(input1, EditorOptions.create({ pinned: true, activation: EditorActivation.ACTIVATE })); + await rootGroup.openEditor(input1, { pinned: true, activation: EditorActivation.ACTIVATE }); + await sideGroup.openEditor(input1, { pinned: true, activation: EditorActivation.ACTIVATE }); currentEditorsMRU = observer.editors; assert.strictEqual(currentEditorsMRU.length, 2); @@ -161,7 +161,7 @@ suite('EditorsObserver', function () { assert.strictEqual(observer.hasEditors(input1.resource), true); assert.strictEqual(observer.hasEditor({ resource: input1.resource, typeId: input1.typeId }), true); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true, activation: EditorActivation.ACTIVATE })); + await rootGroup.openEditor(input1, { pinned: true, activation: EditorActivation.ACTIVATE }); currentEditorsMRU = observer.editors; assert.strictEqual(currentEditorsMRU.length, 2); @@ -176,7 +176,7 @@ suite('EditorsObserver', function () { // the most recent editor, but rather put it behind const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_SERIALIZABLE_EDITOR_INPUT_ID); - await rootGroup.openEditor(input2, EditorOptions.create({ inactive: true })); + await rootGroup.openEditor(input2, { inactive: true }); currentEditorsMRU = observer.editors; assert.strictEqual(currentEditorsMRU.length, 3); @@ -222,13 +222,13 @@ suite('EditorsObserver', function () { assert.strictEqual(observer.hasEditor({ resource: input1.resource, typeId: input1.typeId }), false); assert.strictEqual(observer.hasEditor({ resource: input2.resource, typeId: input2.typeId }), false); - await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input1, { pinned: true }); assert.strictEqual(observer.hasEditors(input1.resource), true); assert.strictEqual(observer.hasEditor({ resource: input1.resource, typeId: input1.typeId }), true); assert.strictEqual(observer.hasEditor({ resource: input2.resource, typeId: input2.typeId }), false); - await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input2, { pinned: true }); assert.strictEqual(observer.hasEditors(input1.resource), true); assert.strictEqual(observer.hasEditor({ resource: input1.resource, typeId: input1.typeId }), true); @@ -259,13 +259,13 @@ suite('EditorsObserver', function () { assert.strictEqual(observer.hasEditor({ resource: primary.resource, typeId: primary.typeId }), false); assert.strictEqual(observer.hasEditor({ resource: secondary.resource, typeId: secondary.typeId }), false); - await part.activeGroup.openEditor(input, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input, { pinned: true }); assert.strictEqual(observer.hasEditors(primary.resource), true); assert.strictEqual(observer.hasEditor({ resource: primary.resource, typeId: primary.typeId }), true); assert.strictEqual(observer.hasEditor({ resource: secondary.resource, typeId: secondary.typeId }), false); - await part.activeGroup.openEditor(primary, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(primary, { pinned: true }); assert.strictEqual(observer.hasEditors(primary.resource), true); assert.strictEqual(observer.hasEditor({ resource: primary.resource, typeId: primary.typeId }), true); @@ -293,9 +293,9 @@ suite('EditorsObserver', function () { const rootGroup = part.activeGroup; - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input2, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input3, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input1, { pinned: true }); + await rootGroup.openEditor(input2, { pinned: true }); + await rootGroup.openEditor(input3, { pinned: true }); let currentEditorsMRU = observer.editors; assert.strictEqual(currentEditorsMRU.length, 3); @@ -353,9 +353,9 @@ suite('EditorsObserver', function () { const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_SERIALIZABLE_EDITOR_INPUT_ID); const input3 = new TestFileEditorInput(URI.parse('foo://bar3'), TEST_SERIALIZABLE_EDITOR_INPUT_ID); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input2, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input3, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input1, { pinned: true }); + await rootGroup.openEditor(input2, { pinned: true }); + await rootGroup.openEditor(input3, { pinned: true }); const storage = new TestStorageService(); const observer = disposables.add(new EditorsObserver(part, storage)); @@ -400,11 +400,11 @@ suite('EditorsObserver', function () { const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_SERIALIZABLE_EDITOR_INPUT_ID); const input3 = new TestFileEditorInput(URI.parse('foo://bar3'), TEST_SERIALIZABLE_EDITOR_INPUT_ID); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input2, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input1, { pinned: true }); + await rootGroup.openEditor(input2, { pinned: true }); const sideGroup = part.addGroup(rootGroup, GroupDirection.RIGHT); - await sideGroup.openEditor(input3, EditorOptions.create({ pinned: true })); + await sideGroup.openEditor(input3, { pinned: true }); const storage = new TestStorageService(); const observer = disposables.add(new EditorsObserver(part, storage)); @@ -447,7 +447,7 @@ suite('EditorsObserver', function () { const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input1, { pinned: true }); const storage = new TestStorageService(); const observer = disposables.add(new EditorsObserver(part, storage)); @@ -484,10 +484,10 @@ suite('EditorsObserver', function () { const input3 = new TestFileEditorInput(URI.parse('foo://bar3'), TEST_EDITOR_INPUT_ID); const input4 = new TestFileEditorInput(URI.parse('foo://bar4'), TEST_EDITOR_INPUT_ID); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input2, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input3, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input4, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input1, { pinned: true }); + await rootGroup.openEditor(input2, { pinned: true }); + await rootGroup.openEditor(input3, { pinned: true }); + await rootGroup.openEditor(input4, { pinned: true }); assert.strictEqual(rootGroup.count, 3); assert.strictEqual(rootGroup.contains(input1), false); @@ -515,7 +515,7 @@ suite('EditorsObserver', function () { assert.strictEqual(observer.hasEditor({ resource: input4.resource, typeId: input4.typeId }), true); const input5 = new TestFileEditorInput(URI.parse('foo://bar5'), TEST_EDITOR_INPUT_ID); - await sideGroup.openEditor(input5, EditorOptions.create({ pinned: true })); + await sideGroup.openEditor(input5, { pinned: true }); assert.strictEqual(rootGroup.count, 1); assert.strictEqual(rootGroup.contains(input1), false); @@ -545,10 +545,10 @@ suite('EditorsObserver', function () { const input3 = new TestFileEditorInput(URI.parse('foo://bar3'), TEST_EDITOR_INPUT_ID); const input4 = new TestFileEditorInput(URI.parse('foo://bar4'), TEST_EDITOR_INPUT_ID); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input2, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input3, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input4, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input1, { pinned: true }); + await rootGroup.openEditor(input2, { pinned: true }); + await rootGroup.openEditor(input3, { pinned: true }); + await rootGroup.openEditor(input4, { pinned: true }); assert.strictEqual(rootGroup.count, 3); // 1 editor got closed due to our limit! assert.strictEqual(rootGroup.contains(input1), false); @@ -560,10 +560,10 @@ suite('EditorsObserver', function () { assert.strictEqual(observer.hasEditor({ resource: input3.resource, typeId: input3.typeId }), true); assert.strictEqual(observer.hasEditor({ resource: input4.resource, typeId: input4.typeId }), true); - await sideGroup.openEditor(input1, EditorOptions.create({ pinned: true })); - await sideGroup.openEditor(input2, EditorOptions.create({ pinned: true })); - await sideGroup.openEditor(input3, EditorOptions.create({ pinned: true })); - await sideGroup.openEditor(input4, EditorOptions.create({ pinned: true })); + await sideGroup.openEditor(input1, { pinned: true }); + await sideGroup.openEditor(input2, { pinned: true }); + await sideGroup.openEditor(input3, { pinned: true }); + await sideGroup.openEditor(input4, { pinned: true }); assert.strictEqual(sideGroup.count, 3); assert.strictEqual(sideGroup.contains(input1), false); @@ -611,10 +611,10 @@ suite('EditorsObserver', function () { const input3 = new TestFileEditorInput(URI.parse('foo://bar3'), TEST_EDITOR_INPUT_ID); const input4 = new TestFileEditorInput(URI.parse('foo://bar4'), TEST_EDITOR_INPUT_ID); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true, sticky: true })); - await rootGroup.openEditor(input2, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input3, EditorOptions.create({ pinned: true })); - await rootGroup.openEditor(input4, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input1, { pinned: true, sticky: true }); + await rootGroup.openEditor(input2, { pinned: true }); + await rootGroup.openEditor(input3, { pinned: true }); + await rootGroup.openEditor(input4, { pinned: true }); assert.strictEqual(rootGroup.count, 3); assert.strictEqual(rootGroup.contains(input1), true); diff --git a/src/vs/workbench/services/history/test/browser/history.test.ts b/src/vs/workbench/services/history/test/browser/history.test.ts index da0879a53ec..9927273df89 100644 --- a/src/vs/workbench/services/history/test/browser/history.test.ts +++ b/src/vs/workbench/services/history/test/browser/history.test.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { EditorOptions } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; import { workbenchInstantiationService, TestFileEditorInput, registerTestEditor, createEditorPart } from 'vs/workbench/test/browser/workbenchTestServices'; import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; @@ -53,11 +52,11 @@ suite('HistoryService', function () { const [part, historyService, editorService] = await createServices(); const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID); - await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input1, { pinned: true }); assert.strictEqual(part.activeGroup.activeEditor, input1); const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_EDITOR_INPUT_ID); - await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input2, { pinned: true }); assert.strictEqual(part.activeGroup.activeEditor, input2); let editorChangePromise = Event.toPromise(editorService.onDidActiveEditorChange); @@ -78,10 +77,10 @@ suite('HistoryService', function () { assert.strictEqual(history.length, 0); const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID); - await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input1, { pinned: true }); const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_EDITOR_INPUT_ID); - await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input2, { pinned: true }); history = historyService.getHistory(); assert.strictEqual(history.length, 2); @@ -98,7 +97,7 @@ suite('HistoryService', function () { assert.ok(!historyService.getLastActiveFile('foo')); const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID); - await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input1, { pinned: true }); assert.strictEqual(historyService.getLastActiveFile('foo')?.toString(), input1.resource.toString()); }); @@ -109,10 +108,10 @@ suite('HistoryService', function () { const input1 = new TestFileEditorInput(URI.parse('foo://bar1'), TEST_EDITOR_INPUT_ID); const input2 = new TestFileEditorInput(URI.parse('foo://bar2'), TEST_EDITOR_INPUT_ID); - await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input1, { pinned: true }); assert.strictEqual(part.activeGroup.activeEditor, input1); - await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input2, { pinned: true }); assert.strictEqual(part.activeGroup.activeEditor, input2); let editorChangePromise = Event.toPromise(editorService.onDidActiveEditorChange); @@ -145,8 +144,8 @@ suite('HistoryService', function () { const sideGroup = part.addGroup(rootGroup, GroupDirection.RIGHT); - await rootGroup.openEditor(input1, EditorOptions.create({ pinned: true })); - await sideGroup.openEditor(input2, EditorOptions.create({ pinned: true })); + await rootGroup.openEditor(input1, { pinned: true }); + await sideGroup.openEditor(input2, { pinned: true }); let editorChangePromise = Event.toPromise(editorService.onDidActiveEditorChange); historyService.openPreviouslyUsedEditor(); @@ -169,9 +168,9 @@ suite('HistoryService', function () { const input3 = new TestFileEditorInput(URI.parse('foo://bar3'), TEST_EDITOR_INPUT_ID); const input4 = new TestFileEditorInput(URI.parse('foo://bar4'), TEST_EDITOR_INPUT_ID); - await part.activeGroup.openEditor(input1, EditorOptions.create({ pinned: true })); - await part.activeGroup.openEditor(input2, EditorOptions.create({ pinned: true })); - await part.activeGroup.openEditor(input3, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input1, { pinned: true }); + await part.activeGroup.openEditor(input2, { pinned: true }); + await part.activeGroup.openEditor(input3, { pinned: true }); let editorChangePromise = Event.toPromise(editorService.onDidActiveEditorChange); historyService.openPreviouslyUsedEditor(); @@ -179,7 +178,7 @@ suite('HistoryService', function () { assert.strictEqual(part.activeGroup.activeEditor, input2); await timeout(0); - await part.activeGroup.openEditor(input4, EditorOptions.create({ pinned: true })); + await part.activeGroup.openEditor(input4, { pinned: true }); editorChangePromise = Event.toPromise(editorService.onDidActiveEditorChange); historyService.openPreviouslyUsedEditor(); diff --git a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts index 204d684454b..c703353b185 100644 --- a/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editorPane.test.ts @@ -6,7 +6,7 @@ import * as assert from 'assert'; import { EditorPane, EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane'; import { WorkspaceTrustRequiredEditor } from 'vs/workbench/browser/parts/editor/workspaceTrustRequiredEditor'; -import { EditorOptions, IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; +import { IEditorInputSerializer, IEditorInputFactoryRegistry, EditorExtensions, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; @@ -108,7 +108,7 @@ suite('Workbench EditorPane', () => { test('EditorPane API', async () => { const editor = new TestEditor(NullTelemetryService); const input = new OtherTestInput(); - const options = new EditorOptions(); + const options = {}; assert(!editor.isVisible()); assert(!editor.input); diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 8a6f871e07c..36c297e6732 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -10,7 +10,7 @@ import { URI } from 'vs/base/common/uri'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; -import { IEditorInputWithOptions, IEditorIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInput, IEditorPane, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorOptions, EditorsOrder, IFileEditorInput, IEditorInputFactoryRegistry, IEditorInputSerializer, EditorExtensions, ISaveOptions, IMoveResult, ITextEditorPane, ITextDiffEditorPane, IVisibleEditorPane, IEditorOpenContext, IEditorMoveEvent, EditorExtensions as Extensions, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; +import { IEditorInputWithOptions, IEditorIdentifier, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInput, IEditorPane, IEditorCloseEvent, IEditorPartOptions, IRevertOptions, GroupIdentifier, EditorsOrder, IFileEditorInput, IEditorInputFactoryRegistry, IEditorInputSerializer, EditorExtensions, ISaveOptions, IMoveResult, ITextEditorPane, ITextDiffEditorPane, IVisibleEditorPane, IEditorOpenContext, IEditorMoveEvent, EditorExtensions as Extensions, EditorInputCapabilities, IEditorOpenEvent } from 'vs/workbench/common/editor'; import { EditorServiceImpl, IEditorGroupView, IEditorGroupsAccessor, IEditorGroupTitleHeight } from 'vs/workbench/browser/parts/editor/editor'; import { Event, Emitter } from 'vs/base/common/event'; import { IResolvedWorkingCopyBackup, IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup'; @@ -811,7 +811,7 @@ export class TestEditorService implements EditorServiceImpl { async openEditor(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | ITextEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise { throw new Error('not implemented'); } - doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType): [IEditorGroup, EditorInput, EditorOptions | undefined] | undefined { + doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined { if (!this.editorGroupService) { return undefined; } @@ -1306,7 +1306,7 @@ export function registerTestEditor(id: string, inputs: SyncDescriptor { + override async setInput(input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { super.setInput(input, options, context, token); await input.resolve(); From c17917e6ba4eb5af9c94bd73efd2785a1cfa61db Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 25 May 2021 08:16:32 -0700 Subject: [PATCH 064/140] Enable notebook renderers on web (#124557) From de08dcdf276f79d19683a1002ecfce35f696aab7 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 25 May 2021 08:24:13 -0700 Subject: [PATCH 065/140] remove folding classes first when config change. --- .../contrib/notebook/browser/view/renderers/markdownCell.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index 1b0270c2b6d..79574328b08 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -250,6 +250,7 @@ export class StatefulMarkdownCell extends Disposable { private updateFoldingIconShowClass() { const showFoldingIcon = this.notebookEditor.notebookOptions.getLayoutConfiguration().showFoldingControls; + this.templateData.foldingIndicator.classList.remove('mouseover', 'always'); this.templateData.foldingIndicator.classList.add(showFoldingIcon); } From af0078d44d5682acd0a8d20f304555d66ab237ee Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 17:30:34 +0200 Subject: [PATCH 066/140] editors - more EditorOptions cleanup --- src/vs/platform/editor/common/editor.ts | 3 ++ src/vs/workbench/common/editor.ts | 2 +- .../quickaccess/gotoLineQuickAccess.ts | 7 ++-- .../quickaccess/gotoSymbolQuickAccess.ts | 7 ++-- .../common/preferencesContribution.ts | 4 +-- .../search/browser/anythingQuickAccess.ts | 7 +++- .../editor/browser/editorOverrideService.ts | 6 ++-- .../services/editor/browser/editorService.ts | 35 ++++++++++--------- .../editor/common/editorGroupsService.ts | 10 +++--- .../editor/common/editorOverrideService.ts | 8 ++--- .../services/editor/common/editorService.ts | 4 +-- .../test/browser/workbenchTestServices.ts | 10 +++--- 12 files changed, 59 insertions(+), 44 deletions(-) diff --git a/src/vs/platform/editor/common/editor.ts b/src/vs/platform/editor/common/editor.ts index f14cfa60953..2f3866f2b0f 100644 --- a/src/vs/platform/editor/common/editor.ts +++ b/src/vs/platform/editor/common/editor.ts @@ -269,14 +269,17 @@ export const enum TextEditorSelectionRevealType { * Option to scroll vertically or horizontally as necessary and reveal a range centered vertically. */ Center = 0, + /** * Option to scroll vertically or horizontally as necessary and reveal a range centered vertically only if it lies outside the viewport. */ CenterIfOutsideViewport = 1, + /** * Option to scroll vertically or horizontally as necessary and reveal a range close to the top of the viewport, but not quite at the top. */ NearTop = 2, + /** * Option to scroll vertically or horizontally as necessary and reveal a range close to the top of the viewport, but not quite at the top. * Only if it lies outside the viewport diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 84b57935f39..86069b6bfd7 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -682,7 +682,7 @@ export interface IFileEditorInput extends IEditorInput, IEncodingSupport, IModeS export interface IEditorInputWithOptions { editor: IEditorInput; - options?: IEditorOptions | ITextEditorOptions; + options?: IEditorOptions; } export interface IEditorInputWithOptionsAndGroup extends IEditorInputWithOptions { diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts index 73843d65ff6..d2054e83e51 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoLineQuickAccess.ts @@ -17,6 +17,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess'; +import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProvider { @@ -47,11 +48,13 @@ export class GotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProv if ((options.keyMods.alt || (this.configuration.openEditorPinned && options.keyMods.ctrlCmd) || options.forceSideBySide) && this.editorService.activeEditor) { context.restoreViewState?.(); // since we open to the side, restore view state in this editor - this.editorService.openEditor(this.editorService.activeEditor, { + const editorOptions: ITextEditorOptions = { selection: options.range, pinned: options.keyMods.ctrlCmd || this.configuration.openEditorPinned, preserveFocus: options.preserveFocus - }, SIDE_GROUP); + }; + + this.editorService.openEditor(this.editorService.activeEditor, editorOptions, SIDE_GROUP); } // Otherwise let parent handle it diff --git a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts index 7766be44b3a..c5772a73b67 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess.ts @@ -28,6 +28,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis import { IQuickAccessTextEditorContext } from 'vs/editor/contrib/quickAccess/editorNavigationQuickAccess'; import { IOutlineService, OutlineTarget } from 'vs/workbench/services/outline/browser/outline'; import { isCompositeEditor } from 'vs/editor/browser/editorBrowser'; +import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccessProvider { @@ -73,11 +74,13 @@ export class GotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccess if ((options.keyMods.alt || (this.configuration.openEditorPinned && options.keyMods.ctrlCmd) || options.forceSideBySide) && this.editorService.activeEditor) { context.restoreViewState?.(); // since we open to the side, restore view state in this editor - this.editorService.openEditor(this.editorService.activeEditor, { + const editorOptions: ITextEditorOptions = { selection: options.range, pinned: options.keyMods.ctrlCmd || this.configuration.openEditorPinned, preserveFocus: options.preserveFocus - }, SIDE_GROUP); + }; + + this.editorService.openEditor(this.editorService.activeEditor, editorOptions, SIDE_GROUP); } // Otherwise let parent handle it diff --git a/src/vs/workbench/contrib/preferences/common/preferencesContribution.ts b/src/vs/workbench/contrib/preferences/common/preferencesContribution.ts index a3b0d83cd1a..3fc23441ac0 100644 --- a/src/vs/workbench/contrib/preferences/common/preferencesContribution.ts +++ b/src/vs/workbench/contrib/preferences/common/preferencesContribution.ts @@ -13,7 +13,7 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService'; import * as nls from 'vs/nls'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConfigurationScope, Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import * as JSONContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -71,7 +71,7 @@ export class PreferencesContribution implements IWorkbenchContribution { priority: ContributedEditorPriority.builtin, }, {}, - (resource: URI, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IEditorInputWithOptions => { + (resource: URI, options: IEditorOptions | undefined, group: IEditorGroup): IEditorInputWithOptions => { // Global User Settings File if (isEqual(resource, this.environmentService.settingsResource)) { return { editor: this.preferencesService.getCurrentOrNewSplitJsonEditorInput(ConfigurationTarget.USER_LOCAL, resource, group), options }; diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index ea12b245a9f..5379422b968 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -144,9 +144,14 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { if (this.editorViewState) { + const options: ITextEditorOptions = { + viewState: this.editorViewState.state, + preserveFocus: true /* import to not close the picker as a result */ + }; + await this.editorService.openEditor( this.editorViewState.editor, - { viewState: this.editorViewState.state, preserveFocus: true /* import to not close the picker as a result */ }, + options, this.editorViewState.group ); } diff --git a/src/vs/workbench/services/editor/browser/editorOverrideService.ts b/src/vs/workbench/services/editor/browser/editorOverrideService.ts index 663f92280e2..397263fe5a6 100644 --- a/src/vs/workbench/services/editor/browser/editorOverrideService.ts +++ b/src/vs/workbench/services/editor/browser/editorOverrideService.ts @@ -9,7 +9,7 @@ import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle' import { basename, extname, isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { EditorActivation, EditorOverride, IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { EditorActivation, EditorOverride, IEditorOptions } from 'vs/platform/editor/common/editor'; import { EditorResourceAccessor, IEditorInput, IEditorInputWithOptions, IEditorInputWithOptionsAndGroup } from 'vs/workbench/common/editor'; import { IEditorGroup, IEditorGroupsService, preferredSideBySideGroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService'; import { Schemas } from 'vs/base/common/network'; @@ -80,7 +80,7 @@ export class EditorOverrideService extends Disposable implements IEditorOverride })); } - async resolveEditorOverride(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): Promise { + async resolveEditorOverride(editor: IEditorInput, options: IEditorOptions | undefined, group: IEditorGroup): Promise { // If it was an override before we await for the extensions to activate and then proceed with overriding or else they won't be registered if (this.cache && editor.resource && this.resourceMatchesCache(editor.resource)) { await this.extensionService.whenInstalledExtensionsRegistered(); @@ -292,7 +292,7 @@ export class EditorOverrideService extends Disposable implements IEditorOverride }; } - private async doOverrideEditorInput(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup, selectedContribution: ContributionPoint): Promise { + private async doOverrideEditorInput(editor: IEditorInput, options: IEditorOptions | undefined, group: IEditorGroup, selectedContribution: ContributionPoint): Promise { // If no activation option is provided, populate it. if (options && typeof options.activation === 'undefined') { diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index c2cb9b269f2..1d548efb56e 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IResourceEditorInput, ITextEditorOptions, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; +import { IResourceEditorInput, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; @@ -512,10 +512,10 @@ export class EditorService extends Disposable implements EditorServiceImpl { //#region openEditor() - openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: OpenInEditorGroup): Promise; + openEditor(editor: IEditorInput, options?: IEditorOptions, group?: OpenInEditorGroup): Promise; openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: OpenInEditorGroup): Promise; openEditor(editor: IResourceDiffEditorInput, group?: OpenInEditorGroup): Promise; - async openEditor(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | ITextEditorOptions | OpenInEditorGroup, group?: OpenInEditorGroup): Promise { + async openEditor(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | OpenInEditorGroup, group?: OpenInEditorGroup): Promise { const result = this.doResolveEditorOpenRequest(editor, optionsOrGroup, group); if (result) { const [resolvedGroup, resolvedEditor, resolvedOptions] = result; @@ -538,20 +538,20 @@ export class EditorService extends Disposable implements EditorServiceImpl { return undefined; } - doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | ITextEditorOptions | OpenInEditorGroup, group?: OpenInEditorGroup): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined { + doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | OpenInEditorGroup, group?: OpenInEditorGroup): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined { let resolvedGroup: IEditorGroup | undefined; let candidateGroup: OpenInEditorGroup | undefined; let typedEditor: EditorInput | undefined; - let typedOptions: IEditorOptions | undefined; + let options: IEditorOptions | undefined; // Typed Editor Support if (editor instanceof EditorInput) { typedEditor = editor; - typedOptions = optionsOrGroup as IEditorOptions; + options = optionsOrGroup as IEditorOptions; candidateGroup = group; - resolvedGroup = this.findTargetGroup(typedEditor, typedOptions, candidateGroup); + resolvedGroup = this.findTargetGroup(typedEditor, options, candidateGroup); } // Untyped Text Editor Support @@ -559,19 +559,19 @@ export class EditorService extends Disposable implements EditorServiceImpl { const textInput = editor as IResourceEditorInputType; typedEditor = this.createEditorInput(textInput); if (typedEditor) { - typedOptions = textInput.options; + options = textInput.options; candidateGroup = optionsOrGroup as OpenInEditorGroup; - resolvedGroup = this.findTargetGroup(typedEditor, typedOptions, candidateGroup); + resolvedGroup = this.findTargetGroup(typedEditor, options, candidateGroup); } } if (typedEditor && resolvedGroup) { if ( this.editorGroupService.activeGroup !== resolvedGroup && // only if target group is not already active - typedOptions && !typedOptions.inactive && // never for inactive editors - typedOptions.preserveFocus && // only if preserveFocus - typeof typedOptions.activation !== 'number' && // only if activation is not already defined (either true or false) + options && !options.inactive && // never for inactive editors + options.preserveFocus && // only if preserveFocus + typeof options.activation !== 'number' && // only if activation is not already defined (either true or false) candidateGroup !== SIDE_GROUP // never for the SIDE_GROUP ) { // If the resolved group is not the active one, we typically @@ -583,10 +583,10 @@ export class EditorService extends Disposable implements EditorServiceImpl { // group is it is opened as `SIDE_GROUP` with `preserveFocus:true`. // repeated Alt-clicking of files in the explorer always open // into the same side group and not cause a group to be created each time. - typedOptions.activation = EditorActivation.ACTIVATE; + options.activation = EditorActivation.ACTIVATE; } - return [resolvedGroup, typedEditor, typedOptions]; + return [resolvedGroup, typedEditor, options]; } return undefined; @@ -1179,6 +1179,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { if (isTextEditorPane(editorPane)) { viewState = editorPane.getViewState(); } + const editorOptions: ITextEditorOptions = { pinned: true, viewState }; const result = options?.saveAs ? await editor.saveAs(groupId, options) : await editor.save(groupId, options); saveResults.push(result); @@ -1193,7 +1194,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { if (!result.matches(editor)) { const targetGroups = editor.hasCapability(EditorInputCapabilities.Untitled) ? this.editorGroupService.groups.map(group => group.id) /* untitled replaces across all groups */ : [groupId]; for (const group of targetGroups) { - await this.replaceEditors([{ editor, replacement: result, options: { pinned: true, viewState } }], group); + await this.replaceEditors([{ editor, replacement: result, options: editorOptions }], group); } } } @@ -1300,10 +1301,10 @@ export class DelegatingEditorService implements IEditorService { @IEditorService private editorService: EditorService ) { } - openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: OpenInEditorGroup): Promise; + openEditor(editor: IEditorInput, options?: IEditorOptions, group?: OpenInEditorGroup): Promise; openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: OpenInEditorGroup): Promise; openEditor(editor: IResourceDiffEditorInput, group?: OpenInEditorGroup): Promise; - async openEditor(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | ITextEditorOptions | OpenInEditorGroup, group?: OpenInEditorGroup): Promise { + async openEditor(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | OpenInEditorGroup, group?: OpenInEditorGroup): Promise { const result = this.editorService.doResolveEditorOpenRequest(editor, optionsOrGroup, group); if (result) { const [resolvedGroup, resolvedEditor, resolvedOptions] = result; diff --git a/src/vs/workbench/services/editor/common/editorGroupsService.ts b/src/vs/workbench/services/editor/common/editorGroupsService.ts index 1e3a2fbd0ab..43c29c5c77f 100644 --- a/src/vs/workbench/services/editor/common/editorGroupsService.ts +++ b/src/vs/workbench/services/editor/common/editorGroupsService.ts @@ -6,7 +6,7 @@ import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IEditorInput, IEditorPane, GroupIdentifier, IEditorInputWithOptions, CloseDirection, IEditorPartOptions, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, IEditorCloseEvent, IEditorMoveEvent, IEditorOpenEvent } from 'vs/workbench/common/editor'; -import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IDimension } from 'vs/editor/common/editorCommon'; import { IDisposable } from 'vs/base/common/lifecycle'; @@ -101,7 +101,7 @@ export interface ICloseAllEditorsOptions { export interface IEditorReplacement { editor: IEditorInput; replacement: IEditorInput; - options?: IEditorOptions | ITextEditorOptions; + options?: IEditorOptions; /** * Skips asking the user for confirmation and doesn't @@ -520,7 +520,7 @@ export interface IEditorGroup { * @returns a promise that resolves around an IEditor instance unless * the call failed, or the editor was not opened as active editor. */ - openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions): Promise; + openEditor(editor: IEditorInput, options?: IEditorOptions): Promise; /** * Opens editors in this group. @@ -557,14 +557,14 @@ export interface IEditorGroup { /** * Move an editor from this group either within this group or to another group. */ - moveEditor(editor: IEditorInput, target: IEditorGroup, options?: IEditorOptions | ITextEditorOptions): void; + moveEditor(editor: IEditorInput, target: IEditorGroup, options?: IEditorOptions): void; /** * Copy an editor from this group to another group. * * Note: It is currently not supported to show the same editor more than once in the same group. */ - copyEditor(editor: IEditorInput, target: IEditorGroup, options?: IEditorOptions | ITextEditorOptions): void; + copyEditor(editor: IEditorInput, target: IEditorGroup, options?: IEditorOptions): void; /** * Close an editor from the group. This may trigger a confirmation dialog if diff --git a/src/vs/workbench/services/editor/common/editorOverrideService.ts b/src/vs/workbench/services/editor/common/editorOverrideService.ts index 29a50d46bed..966500293e3 100644 --- a/src/vs/workbench/services/editor/common/editorOverrideService.ts +++ b/src/vs/workbench/services/editor/common/editorOverrideService.ts @@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; import { Extensions as ConfigurationExtensions, IConfigurationNode, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; -import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { Registry } from 'vs/platform/registry/common/platform'; import { IEditorInput, IEditorInputWithOptions, IEditorInputWithOptionsAndGroup } from 'vs/workbench/common/editor'; @@ -97,9 +97,9 @@ export type ContributedEditorInfo = { priority: ContributedEditorPriority; }; -export type EditorInputFactoryFunction = (resource: URI, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup) => IEditorInputWithOptions; +export type EditorInputFactoryFunction = (resource: URI, options: IEditorOptions | undefined, group: IEditorGroup) => IEditorInputWithOptions; -export type DiffEditorInputFactoryFunction = (diffEditorInput: DiffEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup) => IEditorInputWithOptions; +export type DiffEditorInputFactoryFunction = (diffEditorInput: DiffEditorInput, options: IEditorOptions | undefined, group: IEditorGroup) => IEditorInputWithOptions; export interface IEditorOverrideService { readonly _serviceBrand: undefined; @@ -139,7 +139,7 @@ export interface IEditorOverrideService { * @param group The current group * @returns An IEditorInputWithOptionsAndGroup if there is an available override or undefined if there is not */ - resolveEditorOverride(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): Promise; + resolveEditorOverride(editor: IEditorInput, options: IEditorOptions | undefined, group: IEditorGroup): Promise; /** * Given a resource returns all the editor ids that match that resource diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index f27ac7ff9dd..a1e447a2295 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IResourceEditorInput, IEditorOptions, ITextEditorOptions, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; +import { IResourceEditorInput, IEditorOptions, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; import { IEditorInput, IEditorPane, GroupIdentifier, IEditorInputWithOptions, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, ITextEditorPane, ITextDiffEditorPane, IEditorIdentifier, ISaveOptions, IRevertOptions, EditorsOrder, IVisibleEditorPane, IEditorCloseEvent } from 'vs/workbench/common/editor'; import { Event } from 'vs/base/common/event'; import { IEditor, IDiffEditor } from 'vs/editor/common/editorCommon'; @@ -157,7 +157,7 @@ export interface IEditorService { * @returns the editor that opened or `undefined` if the operation failed or the editor was not * opened to be active. */ - openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IEditorInput, options?: IEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; openEditor(editor: IResourceDiffEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 36c297e6732..5e65b8874f7 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -18,7 +18,7 @@ import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configur import { IWorkbenchLayoutService, Parts, Position as PartPosition } from 'vs/workbench/services/layout/browser/layoutService'; import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; -import { IEditorOptions, IResourceEditorInput, IEditorModel, ITextEditorOptions, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; +import { IEditorOptions, IResourceEditorInput, IEditorModel, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; import { IUntitledTextEditorService, UntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { ILifecycleService, BeforeShutdownEvent, ShutdownReason, StartupKind, LifecyclePhase, WillShutdownEvent } from 'vs/workbench/services/lifecycle/common/lifecycle'; @@ -733,8 +733,8 @@ export class TestEditorGroupView implements IEditorGroupView { isSticky(_editor: IEditorInput): boolean { return false; } isActive(_editor: IEditorInput): boolean { return false; } contains(candidate: IEditorInput): boolean { return false; } - moveEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions | ITextEditorOptions): void { } - copyEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions | ITextEditorOptions): void { } + moveEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions): void { } + copyEditor(_editor: IEditorInput, _target: IEditorGroup, _options?: IEditorOptions): void { } async closeEditor(_editor?: IEditorInput, options?: ICloseEditorOptions): Promise { } async closeEditors(_editors: IEditorInput[] | ICloseEditorsFilter, options?: ICloseEditorOptions): Promise { } async closeAllEditors(options?: ICloseAllEditorsOptions): Promise { } @@ -805,10 +805,10 @@ export class TestEditorService implements EditorServiceImpl { constructor(private editorGroupService?: IEditorGroupsService) { } getEditors() { return []; } findEditors() { return [] as any; } - openEditor(editor: IEditorInput, options?: IEditorOptions | ITextEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IEditorInput, options?: IEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; openEditor(editor: IResourceDiffEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - async openEditor(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | ITextEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise { + async openEditor(editor: IEditorInput | IResourceEditorInputType, optionsOrGroup?: IEditorOptions | IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise { throw new Error('not implemented'); } doResolveEditorOpenRequest(editor: IEditorInput | IResourceEditorInputType): [IEditorGroup, EditorInput, IEditorOptions | undefined] | undefined { From 5254e33173dd743339be5c571dd60ddb6a2cba44 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 25 May 2021 17:31:39 +0200 Subject: [PATCH 067/140] Removes unused const. --- src/vs/editor/contrib/inlineCompletions/ghostTextController.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/editor/contrib/inlineCompletions/ghostTextController.ts b/src/vs/editor/contrib/inlineCompletions/ghostTextController.ts index 9b558362c2d..ceb81364c29 100644 --- a/src/vs/editor/contrib/inlineCompletions/ghostTextController.ts +++ b/src/vs/editor/contrib/inlineCompletions/ghostTextController.ts @@ -162,7 +162,6 @@ export class ActiveGhostTextController extends Disposable { } const GhostTextCommand = EditorCommand.bindToContribution(GhostTextController.get); -const GhostTextAction = EditorAction.bindToContribution(GhostTextController.get); registerEditorCommand(new GhostTextCommand({ id: 'commitInlineCompletion', From 19c88bc3c7aec9bc76da7625d7d6355be9cf9e5c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 25 May 2021 17:44:45 +0200 Subject: [PATCH 068/140] editors - more EditorOptions cleanup --- src/vs/workbench/browser/parts/editor/editor.ts | 2 +- .../contrib/search/browser/anythingQuickAccess.ts | 6 +----- .../workbench/services/editor/browser/editorService.ts | 10 ++++------ src/vs/workbench/services/history/browser/history.ts | 2 +- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editor.ts b/src/vs/workbench/browser/parts/editor/editor.ts index 7cd15e24cf6..0761fee8bf6 100644 --- a/src/vs/workbench/browser/parts/editor/editor.ts +++ b/src/vs/workbench/browser/parts/editor/editor.ts @@ -132,7 +132,7 @@ export interface IEditorGroupView extends IDisposable, ISerializableView, IEdito relayout(): void; } -export function getActiveTextEditorOptions(group: IEditorGroup, expectedActiveEditor?: IEditorInput, presetOptions?: IEditorOptions): IEditorOptions { +export function getActiveTextEditorOptions(group: IEditorGroup, expectedActiveEditor?: IEditorInput, presetOptions?: IEditorOptions): ITextEditorOptions { const activeGroupCodeEditor = group.activeEditorPane ? getIEditor(group.activeEditorPane.getControl()) : undefined; if (activeGroupCodeEditor) { if (!expectedActiveEditor || expectedActiveEditor.matches(group.activeEditor)) { diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index 5379422b968..2bbeb980cb4 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -149,11 +149,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider Date: Tue, 25 May 2021 10:37:28 -0700 Subject: [PATCH 069/140] Fix default shell args for debugging Fixes #124116 Co-Authored-By: Megan Rogge --- src/vs/workbench/api/common/extHostTerminalService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index 1deba734389..ea3e1713eff 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -350,7 +350,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I public getDefaultShellArgs(useAutomationShell: boolean): string[] | string { const profile = useAutomationShell ? this._defaultAutomationProfile : this._defaultProfile; - return profile?.args || ['']; + return profile?.args || []; } public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal { From 33eb149badaa232a1fce9237fa7fbade06f57239 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 25 May 2021 11:04:01 -0700 Subject: [PATCH 070/140] Add reset to default to terminal tab color selector --- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index b9f8ed26f93..4548a76d596 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1843,7 +1843,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } items.push({ type: 'separator' }); - const showAllColorsItem = { label: 'Show all colors' }; + const showAllColorsItem = { label: 'Reset to default' }; items.push(showAllColorsItem); styleElement.textContent = css; document.body.appendChild(styleElement); From c351b396cacdfd5bcbeec6ad89a2890cbdae9263 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Tue, 25 May 2021 13:13:22 -0500 Subject: [PATCH 071/140] Support terminal renaming inline in the tabs view (#124533) --- .../contrib/terminal/browser/terminal.ts | 10 +- .../terminal/browser/terminalActions.ts | 36 +++++- .../terminal/browser/terminalInstance.ts | 16 +-- .../terminal/browser/terminalService.ts | 23 +++- .../terminal/browser/terminalTabbedView.ts | 9 +- .../terminal/browser/terminalTabsList.ts | 118 ++++++++++++++++-- 6 files changed, 187 insertions(+), 25 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 00c2d9bbc06..d0fb01b93d7 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -17,6 +17,7 @@ import type { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl'; import { ITerminalStatusList } from 'vs/workbench/contrib/terminal/browser/terminalStatusList'; import { ICompleteTerminalConfiguration } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; +import { IEditableData } from 'vs/workbench/common/views'; export const ITerminalService = createDecorator('terminalService'); export const ITerminalInstanceService = createDecorator('terminalInstanceService'); @@ -206,6 +207,8 @@ export interface ITerminalService { requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise; isAttachedToTerminal(remoteTerm: IRemoteTerminalAttachTarget): boolean; + getEditableData(stat: ITerminalInstance): IEditableData | undefined; + setEditable(stat: ITerminalInstance, data: IEditableData | null): Promise; } export interface IRemoteTerminalService extends IOffProcessTerminalService { @@ -600,12 +603,13 @@ export interface ITerminalInstance { registerLinkProvider(provider: ITerminalExternalLinkProvider): IDisposable; /** - * Triggers a quick pick to rename this terminal. + * Sets the terminal name to the provided title or triggers a quick pick + * to take user input. */ - rename(): Promise; + rename(title?: string): Promise; /** - * Triggers a quick pick to rename this terminal. + * Triggers a quick pick to change the icon of this terminal. */ changeIcon(): Promise; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index af542818ef9..dac068f76df 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -23,7 +23,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ILabelService } from 'vs/platform/label/common/label'; import { IListService } from 'vs/platform/list/browser/listService'; -import { INotificationService } from 'vs/platform/notification/common/notification'; +import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IPickOptions, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ILocalTerminalService, ITerminalProfile, TerminalSettingId, TitleEventSource } from 'vs/platform/terminal/common/terminal'; @@ -811,9 +811,30 @@ export function registerTerminalActions() { }); } async run(accessor: ServicesAccessor) { - return getSelectedInstances(accessor)?.[0].rename(); + const terminalService = accessor.get(ITerminalService); + const notificationService = accessor.get(INotificationService); + + const instance = getSelectedInstances(accessor)?.[0]; + if (!instance) { + return; + } + + await terminalService.setEditable(instance, { + validationMessage: value => validateTerminalName(value), + onFinish: async (value, success) => { + if (success) { + try { + await instance.rename(value); + } catch (e) { + notificationService.error(e); + } + } + await terminalService.setEditable(instance, null); + } + }); } }); + registerAction2(class extends Action2 { constructor() { super({ @@ -1830,3 +1851,14 @@ function focusNext(accessor: ServicesAccessor): void { const listService = accessor.get(IListService); listService.lastFocusedList?.focusNext(); } + +export function validateTerminalName(name: string): { content: string, severity: Severity } | null { + if (!name || name.trim().length === 0) { + return { + content: localize('emptyTerminalNameError', "A name must be provided."), + severity: Severity.Error + }; + } + + return null; +} diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 4548a76d596..95c23746b47 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -1789,13 +1789,15 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return this._linkManager.registerExternalLinkProvider(this, provider); } - async rename() { - const name = await this._quickInputService.input({ - value: this.title, - prompt: nls.localize('workbench.action.terminal.rename.prompt', "Enter terminal name"), - }); - if (name) { - this.setTitle(name, TitleEventSource.Api); + async rename(title?: string) { + if (!title) { + title = await this._quickInputService.input({ + value: this.title, + prompt: nls.localize('workbench.action.terminal.rename.prompt', "Enter terminal name"), + }); + } + if (title) { + this.setTitle(title, TitleEventSource.Api); } } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index c724ea70dcb..ce934e8dc6b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -19,7 +19,7 @@ import { IKeyMods, IPickOptions, IQuickInputButton, IQuickInputService, IQuickPi import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ILocalTerminalService, IOffProcessTerminalService, IShellLaunchConfig, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; +import { IEditableData, IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; import { IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalGroup, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; @@ -69,6 +69,8 @@ export class TerminalService implements ITerminalService { private _localTerminalsInitPromise: Promise | undefined; private _connectionState: TerminalConnectionState; + private _editable: { instance: ITerminalInstance, data: IEditableData } | undefined; + public get activeGroupIndex(): number { return this._activeGroupIndex; } public get terminalGroups(): ITerminalGroup[] { return this._terminalGroups; } public get isProcessSupportRegistered(): boolean { return !!this._processSupportContextKey.get(); } @@ -316,6 +318,25 @@ export class TerminalService implements ITerminalService { return activeInstance ? activeInstance : this.createTerminal(undefined); } + async setEditable(instance: ITerminalInstance, data?: IEditableData | null): Promise { + if (!data) { + this._editable = undefined; + } else { + this._editable = { instance: instance, data }; + } + const pane = this._viewsService.getActiveViewWithId(TERMINAL_VIEW_ID); + const isEditing = this._isEditable(instance); + pane?.terminalTabbedView?.setEditable(isEditing); + } + + private _isEditable(instance: ITerminalInstance | undefined): boolean { + return !!this._editable && (this._editable.instance === instance || !instance); + } + + getEditableData(instance: ITerminalInstance): IEditableData | undefined { + return this._editable && this._editable.instance === instance ? this._editable.data : undefined; + } + requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise { // The initial request came from the extension host, no need to wait for it return new Promise(callback => { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts index 04fb6e4721a..69a0e7f6d62 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts @@ -288,7 +288,7 @@ export class TerminalTabbedView extends Disposable { const hasText = this._tabListElement.clientWidth > TerminalTabsListSizes.MidpointViewWidth; this._tabContainer.classList.toggle('has-text', hasText); this._terminalIsTabsNarrowContextKey.set(!hasText); - this._tabList.render(); + this._tabList.refresh(); } private _addSashListener() { @@ -469,6 +469,13 @@ export class TerminalTabbedView extends Disposable { ]; } + setEditable(isEditing: boolean): void { + if (!isEditing) { + this._tabList.domFocus(); + } + return this._tabList.refresh(); + } + focusTabs(): void { if (!this._shouldShowTabs()) { return; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts index 396ae88f448..6b9f9e5e683 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts @@ -26,7 +26,7 @@ import { DEFAULT_LABELS_CONTAINER, IResourceLabel, ResourceLabels } from 'vs/wor import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations'; import { IHoverAction, IHoverService } from 'vs/workbench/services/hover/browser/hover'; import Severity from 'vs/base/common/severity'; -import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IListDragAndDrop, IListDragOverReaction, IListRenderer, ListDragOverEffect } from 'vs/base/browser/ui/list/list'; import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd'; import { disposableTimeout } from 'vs/base/common/async'; @@ -34,6 +34,13 @@ import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; import { URI } from 'vs/base/common/uri'; import { getColorClass, getIconId, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; import { Schemas } from 'vs/base/common/network'; +import { IEditableData } from 'vs/workbench/common/views'; +import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; +import { once } from 'vs/base/common/functional'; +import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; +import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { KeyCode } from 'vs/base/common/keyCodes'; const $ = DOM.$; @@ -89,13 +96,13 @@ export class TerminalTabList extends WorkbenchList { configurationService, keybindingService, ); - this._terminalService.onInstancesChanged(() => this.render()); - this._terminalService.onGroupsChanged(() => this.render()); - this._terminalService.onInstanceTitleChanged(() => this.render()); - this._terminalService.onInstanceIconChanged(() => this.render()); - this._terminalService.onInstancePrimaryStatusChanged(() => this.render()); - this._terminalService.onDidChangeConnectionState(() => this.render()); - this._themeService.onDidColorThemeChange(() => this.render()); + this._terminalService.onInstancesChanged(() => this.refresh()); + this._terminalService.onGroupsChanged(() => this.refresh()); + this._terminalService.onInstanceTitleChanged(() => this.refresh()); + this._terminalService.onInstanceIconChanged(() => this.refresh()); + this._terminalService.onInstancePrimaryStatusChanged(() => this.refresh()); + this._terminalService.onDidChangeConnectionState(() => this.refresh()); + this._themeService.onDidColorThemeChange(() => this.refresh()); this._terminalService.onActiveInstanceChanged(e => { if (e) { const i = this._terminalService.terminalInstances.indexOf(e); @@ -157,10 +164,10 @@ export class TerminalTabList extends WorkbenchList { this._decorationsProvider = instantiationService.createInstance(TerminalDecorationsProvider); _decorationsService.registerDecorationsProvider(this._decorationsProvider); } - this.render(); + this.refresh(); } - render(): void { + refresh(): void { this.splice(0, this.length, this._terminalService.terminalInstances); } @@ -182,7 +189,8 @@ class TerminalTabsRenderer implements IListRenderer 1) { const terminalIndex = group.terminalInstances.indexOf(instance); @@ -323,6 +341,84 @@ class TerminalTabsRenderer implements IListRenderer { + const message = editableData.validationMessage(value); + if (!message || message.severity !== Severity.Error) { + return null; + } + + return { + content: message.content, + formatContent: true, + type: MessageType.ERROR + }; + } + }, + ariaLabel: localize('terminalInputAriaLabel', "Type terminal name. Press Enter to confirm or Escape to cancel.") + }); + const styler = attachInputBoxStyler(inputBox, this._themeService); + + inputBox.value = value; + inputBox.focus(); + inputBox.select({ start: 0, end: value.length }); + + const done = once((success: boolean, finishEditing: boolean) => { + inputBox.element.style.display = 'none'; + const value = inputBox.value; + dispose(toDispose); + inputBox.element.remove(); + if (finishEditing) { + editableData.onFinish(value, success); + } + }); + + const showInputBoxNotification = () => { + if (inputBox.isInputValid()) { + const message = editableData.validationMessage(inputBox.value); + if (message) { + inputBox.showMessage({ + content: message.content, + formatContent: true, + type: message.severity === Severity.Info ? MessageType.INFO : message.severity === Severity.Warning ? MessageType.WARNING : MessageType.ERROR + }); + } else { + inputBox.hideMessage(); + } + } + }; + showInputBoxNotification(); + + const toDispose = [ + inputBox, + DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: IKeyboardEvent) => { + if (e.equals(KeyCode.Enter)) { + done(inputBox.isInputValid(), true); + } else if (e.equals(KeyCode.Escape)) { + done(false, true); + } + }), + DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_UP, (e: IKeyboardEvent) => { + showInputBoxNotification(); + }), + DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => { + done(inputBox.isInputValid(), true); + }), + label, + styler + ]; + + return toDisposable(() => { + done(false, false); + }); + } + disposeElement(instance: ITerminalInstance, index: number, templateData: ITerminalTabEntryTemplate): void { templateData.elementDispoables?.dispose(); templateData.elementDispoables = undefined; From db6ffb43b90253d2fe37438ad8c791b8fb5e858d Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 25 May 2021 11:28:50 -0700 Subject: [PATCH 072/140] fix #124583 --- .../common/terminalPlatformConfiguration.ts | 3 ++- .../terminal/node/terminalProfiles.ts | 22 ++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts b/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts index 3ab5f4e8620..95e697e62cf 100644 --- a/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts +++ b/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts @@ -10,6 +10,7 @@ import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema'; import { Registry } from 'vs/platform/registry/common/platform'; import { Codicon, iconRegistry } from 'vs/base/common/codicons'; import { OperatingSystem } from 'vs/base/common/platform'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; const terminalProfileBaseProperties: IJSONSchemaMap = { args: { @@ -372,7 +373,7 @@ export function registerTerminalDefaultProfileConfiguration(detectedProfiles?: { } function createProfileDescription(profile: ITerminalProfile): string { - let description = `$(${profile.icon || Codicon.terminal.id}) ${profile.profileName}\n- path: ${profile.path}`; + let description = `$(${ThemeIcon.isThemeIcon(profile.icon) ? profile.icon.id : profile.icon ? profile.icon : Codicon.terminal.id}) ${profile.profileName}\n- path: ${profile.path}`; if (profile.args) { if (typeof profile.args === 'string') { description += `\n- args: "${profile.args}"`; diff --git a/src/vs/platform/terminal/node/terminalProfiles.ts b/src/vs/platform/terminal/node/terminalProfiles.ts index 8082d39f17f..8b218b0e9ca 100644 --- a/src/vs/platform/terminal/node/terminalProfiles.ts +++ b/src/vs/platform/terminal/node/terminalProfiles.ts @@ -245,23 +245,25 @@ async function getWslProfiles(wslPath: string, defaultProfileName: string | unde profileName, path: wslPath, args: [`-d`, `${distroName}`], - isDefault: profileName === defaultProfileName + isDefault: profileName === defaultProfileName, + icon: getWslIcon(distroName) }; - if (distroName.includes('Ubuntu')) { - profile.icon = ThemeIcon.asThemeIcon(Codicon.terminalUbuntu); - } - else if (distroName.includes('Debian')) { - profile.icon = ThemeIcon.asThemeIcon(Codicon.terminalDebian); - } else { - profile.icon = ThemeIcon.asThemeIcon(Codicon.terminalLinux); - } - // Add the profile profiles.push(profile); } return profiles; } +function getWslIcon(distroName: string): ThemeIcon { + if (distroName.includes('Ubuntu')) { + return ThemeIcon.asThemeIcon(Codicon.terminalUbuntu); + } else if (distroName.includes('Debian')) { + return ThemeIcon.asThemeIcon(Codicon.terminalDebian); + } else { + return ThemeIcon.asThemeIcon(Codicon.terminalLinux); + } +} + async function detectAvailableUnixProfiles( fsProvider: IFsProvider, logService?: ILogService, From 3ccbe2a6b1bea60c08df7af904e7dc3cbc63950a Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Tue, 25 May 2021 12:19:07 -0700 Subject: [PATCH 073/140] Fixes #124247 --- extensions/emmet/package.json | 6 +++++- extensions/emmet/yarn.lock | 12 ++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 0af69221a29..77b08c02ac9 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -226,7 +226,11 @@ }, "output.selfClosingStyle": { "type": "string", - "enum": ["html", "xhtml", "xml"], + "enum": [ + "html", + "xhtml", + "xml" + ], "default": "html", "markdownDescription": "%emmetPreferencesOutputSelfClosingStyle%" }, diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index b9d9785a550..2d35a2c78ab 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -54,9 +54,9 @@ integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI= "@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== + version "14.17.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.1.tgz#5e07e0cb2ff793aa7a1b41deae76221e6166049f" + integrity sha512-/tpUyFD7meeooTRwl3sYlihx2BrJE7q9XF71EguPFIySj9B7qgnRtHsHTho+0AUm4m1SvWGm6uSncrR94q6Vtw== emmet@^2.3.0: version "2.3.4" @@ -77,9 +77,9 @@ jsonc-parser@^2.3.0: integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg== vscode-emmet-helper@^2.3.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.6.2.tgz#777b471a7851ba0ca8e4151533be7f92511f39b0" - integrity sha512-SkL1WjZZsA+bfTo52QH4PgqXCQAJSqzOmJtAY3rOl17MKbY6iJhVv2T26PshjmUnHoXnXMNa7PcLMCS75RsQDQ== + version "2.6.4" + resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.6.4.tgz#bea47f17649bba26b412f3d1fac18aaee43eba25" + integrity sha512-fP0nunW1RUWEKGf4gqiYLOVNFFGXSRHjCl0pikxtwCFlty8WwimM+RBJ5o0aIiwerrYD30HqeaVyvDW027Sseg== dependencies: emmet "^2.3.0" jsonc-parser "^2.3.0" From 71cc917274fd088bc99a938165ef6f8254a49ceb Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 25 May 2021 12:10:49 -0700 Subject: [PATCH 074/140] Add option to show cell statusbar after execution --- .../notebook/browser/media/notebook.css | 2 +- .../notebook/browser/notebookEditorWidget.ts | 3 --- .../browser/view/renderers/cellRenderer.ts | 11 ++++++++--- .../browser/viewModel/baseCellViewModel.ts | 18 ++++++++++++++++-- .../browser/viewModel/codeCellViewModel.ts | 6 ++---- .../viewModel/markdownCellViewModel.ts | 2 +- .../common/model/notebookCellTextModel.ts | 3 ++- .../contrib/notebook/common/notebookCommon.ts | 2 ++ .../notebook/common/notebookOptions.ts | 19 +++++++++++++------ 9 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index 012a0b71fa7..a1769e49bcb 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -425,7 +425,7 @@ overflow: hidden; } -.monaco-workbench .notebookOverlay.cell-statusbar-hidden .cell-statusbar-container { +.monaco-workbench .notebookOverlay .cell-statusbar-hidden .cell-statusbar-container { display: none; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 40b99af2831..f79acc7418c 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -512,9 +512,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const cellToolbarLocation = this._notebookOptions.computeCellToolbarLocation(this.viewModel?.viewType); this._overlayContainer.classList.add(`cell-title-toolbar-${cellToolbarLocation}`); - const showCellStatusBar = this._notebookOptions.getLayoutConfiguration().showCellStatusBar; - this._overlayContainer.classList.toggle('cell-statusbar-hidden', !showCellStatusBar); - const cellToolbarInteraction = this._notebookOptions.getLayoutConfiguration().cellToolbarInteraction; let cellToolbarInteractionState = 'hover'; this._overlayContainer.classList.remove('cell-toolbar-hover'); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index a1abbac5a74..c58a65e0cc9 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -521,6 +521,8 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR templateData.focusIndicatorBottom.style.top = `${indicatorPostion.bottomIndicatorTop}px`; templateData.focusIndicatorLeft.style.height = `${indicatorPostion.verticalIndicatorHeight}px`; templateData.focusIndicatorRight.style.height = `${indicatorPostion.verticalIndicatorHeight}px`; + + templateData.container.classList.toggle('cell-statusbar-hidden', element.getEditorStatusbarHeight() === 0); } private updateForHover(element: MarkdownCellViewModel, templateData: MarkdownCellRenderTemplate): void { @@ -852,7 +854,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende } } - private updateForInternalMetadata(element: CodeCellViewModel, templateData: CodeCellRenderTemplate, editorOptions: CellEditorOptions): void { + private updateForInternalMetadata(element: CodeCellViewModel, templateData: CodeCellRenderTemplate): void { if (!this.notebookEditor.hasModel()) { return; } @@ -894,6 +896,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende templateData.outputContainer.style.top = `${element.layoutInfo.outputContainerOffset}px`; templateData.outputShowMoreContainer.style.top = `${element.layoutInfo.outputShowMoreContainerOffset}px`; templateData.dragHandle.style.height = `${element.layoutInfo.totalHeight - layoutInfo.bottomToolbarGap}px`; + + templateData.container.classList.toggle('cell-statusbar-hidden', element.getEditorStatusbarHeight() === 0); } renderElement(element: CodeCellViewModel, index: number, templateData: CodeCellRenderTemplate, height: number | undefined): void { @@ -959,13 +963,14 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende this.updateForLayout(element, templateData); })); - this.updateForInternalMetadata(element, templateData, cellEditorOptions); + this.updateForInternalMetadata(element, templateData); this.updateForHover(element, templateData); this.updateForFocus(element, templateData); cellEditorOptions.setLineNumbers(element.lineNumbers); elementDisposables.add(element.onDidChangeState((e) => { if (e.internalMetadataChanged) { - this.updateForInternalMetadata(element, templateData, cellEditorOptions); + this.updateForInternalMetadata(element, templateData); + this.updateForLayout(element, templateData); } if (e.outputIsHoveredChanged) { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index c1ebfdb4c06..e3bb83a117a 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -144,10 +144,14 @@ export abstract class BaseCellViewModel extends Disposable { this._register(model.onDidChangeInternalMetadata(e => { this._onDidChangeState.fire({ internalMetadataChanged: true, runStateChanged: e.runStateChanged }); + if (e.runStateChanged || e.lastRunSuccessChanged) { + // Statusbar visibility may change + this.layoutChange({}); + } })); this._register(this._viewContext.notebookOptions.onDidChangeOptions(e => { - if (e.cellStatusBarVisibility || e.insertToolbarPosition) { + if (e.cellStatusBarVisibility || e.cellStatusBarAfterExecuteVisibility || e.insertToolbarPosition) { this.layoutChange({}); } })); @@ -160,7 +164,17 @@ export abstract class BaseCellViewModel extends Disposable { } getEditorStatusbarHeight() { - return this._viewContext.notebookOptions.computeStatusBarHeight(); + return this.statusBarIsVisible() ? this._viewContext.notebookOptions.computeStatusBarHeight() : 0; + } + + private statusBarIsVisible(): boolean { + if (this._viewContext.notebookOptions.getLayoutConfiguration().showCellStatusBar) { + return true; + } else if (this._viewContext.notebookOptions.getLayoutConfiguration().showCellStatusBarAfterExecute) { + return typeof this.internalMetadata.lastRunSuccess === 'boolean' || this.internalMetadata.runState !== undefined; + } else { + return false; + } } abstract hasDynamicHeight(): boolean; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index e40a99e886a..26cf4593431 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -152,6 +152,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod const outputShowMoreContainerHeight = state.outputShowMoreContainerHeight ? state.outputShowMoreContainerHeight : this._layoutInfo.outputShowMoreContainerHeight; let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata.outputCollapsed ? notebookLayoutConfiguration.collapsedIndicatorHeight : this._outputsTop!.getTotalValue()); + const originalLayout = this.layoutInfo; if (!this.metadata.inputCollapsed) { let newState: CodeCellLayoutState; let editorHeight: number; @@ -235,10 +236,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod }; } - if (state.editorHeight || state.outputHeight) { - state.totalHeight = true; - } - + state.totalHeight = this.layoutInfo.totalHeight !== originalLayout.totalHeight; state.source = source; this._fireOnDidChangeLayout(state); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index c0b94acf079..42e899e05b0 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -53,7 +53,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie + layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + layoutConfiguration.markdownCellBottomMargin // MARKDOWN_CELL_BOTTOM_MARGIN + layoutConfiguration.bottomToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - + this.viewContext.notebookOptions.computeStatusBarHeight(); + + this.getEditorStatusbarHeight(); } get editorHeight() { diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts index b963316e2f2..17db539b562 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts @@ -59,13 +59,14 @@ export class NotebookCellTextModel extends Disposable implements ICell { set internalMetadata(newInternalMetadata: NotebookCellInternalMetadata) { const runStateChanged = this._internalMetadata.runState !== newInternalMetadata.runState; + const lastRunSuccessChanged = this._internalMetadata.lastRunSuccess !== newInternalMetadata.lastRunSuccess; newInternalMetadata = { ...newInternalMetadata, ...{ runStartTimeAdjustment: computeRunStartTimeAdjustment(this._internalMetadata, newInternalMetadata) } }; this._internalMetadata = newInternalMetadata; this._hash = null; - this._onDidChangeInternalMetadata.fire({ runStateChanged }); + this._onDidChangeInternalMetadata.fire({ runStateChanged, lastRunSuccessChanged }); } get language() { diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 9a6803d7544..3e63cb22a7c 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -189,6 +189,7 @@ export interface ICellOutput { export interface CellInternalMetadataChangedEvent { readonly runStateChanged?: boolean; + readonly lastRunSuccessChanged?: boolean; } export interface ICell { @@ -903,6 +904,7 @@ export const DisplayOrderKey = 'notebook.displayOrder'; export const CellToolbarLocKey = 'notebook.cellToolbarLocation'; export const CellToolbarVisibility = 'notebook.cellToolbarVisibility'; export const ShowCellStatusBarKey = 'notebook.showCellStatusBar'; +export const ShowCellStatusBarAfterExecuteKey = 'notebook.experimental.showCellStatusBarAfterExecute'; export const NotebookTextDiffEditorPreview = 'notebook.diff.enablePreview'; export const ExperimentalUseMarkdownRenderer = 'notebook.experimental.useMarkdownRenderer'; export const ExperimentalInsertToolbarAlignment = 'notebook.experimental.insertToolbarAlignment'; diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 1175c23ed00..561f46c0356 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -6,7 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { CellToolbarLocKey, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, DragAndDropEnabled, FocusIndicator, GlobalToolbar, ExperimentalInsertToolbarAlignment, InsertToolbarPosition, ShowFoldingControls, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellToolbarLocKey, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, DragAndDropEnabled, ExperimentalInsertToolbarAlignment, FocusIndicator, GlobalToolbar, InsertToolbarPosition, ShowCellStatusBarAfterExecuteKey, ShowCellStatusBarKey, ShowFoldingControls } from 'vs/workbench/contrib/notebook/common/notebookCommon'; const SCROLLABLE_ELEMENT_PADDING_TOP = 18; @@ -43,6 +43,7 @@ export interface NotebookLayoutConfiguration { editorBottomPaddingWithoutStatusBar: number; collapsedIndicatorHeight: number; showCellStatusBar: boolean; + showCellStatusBarAfterExecute: boolean; cellStatusBarHeight: number; cellToolbarLocation: string | { [key: string]: string }; cellToolbarInteraction: string; @@ -59,6 +60,7 @@ export interface NotebookLayoutConfiguration { interface NotebookOptionsChangeEvent { cellStatusBarVisibility?: boolean; + cellStatusBarAfterExecuteVisibility?: boolean; cellToolbarLocation?: boolean; cellToolbarInteraction?: boolean; editorTopPadding?: boolean; @@ -97,6 +99,7 @@ export class NotebookOptions { constructor(private readonly configurationService: IConfigurationService) { const showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); + const showCellStatusBarAfterExecute = this.configurationService.getValue(ShowCellStatusBarAfterExecuteKey); const globalToolbar = this.configurationService.getValue(GlobalToolbar) ?? false; const consolidatedOutputButton = this.configurationService.getValue(ConsolidatedOutputButton) ?? true; const dragAndDropEnabled = this.configurationService.getValue(DragAndDropEnabled) ?? true; @@ -127,6 +130,7 @@ export class NotebookOptions { editorBottomPaddingWithoutStatusBar: 12, collapsedIndicatorHeight: 24, showCellStatusBar, + showCellStatusBarAfterExecute, globalToolbar, consolidatedOutputButton, dragAndDropEnabled, @@ -154,6 +158,7 @@ export class NotebookOptions { private _updateConfiguration(e: IConfigurationChangeEvent) { const cellStatusBarVisibility = e.affectsConfiguration(ShowCellStatusBarKey); + const cellStatusBarAfterExecuteVisibility = e.affectsConfiguration(ShowCellStatusBarAfterExecuteKey); const cellToolbarLocation = e.affectsConfiguration(CellToolbarLocKey); const cellToolbarInteraction = e.affectsConfiguration(CellToolbarVisibility); const compactView = e.affectsConfiguration(CompactView); @@ -168,6 +173,7 @@ export class NotebookOptions { if ( !cellStatusBarVisibility + && !cellStatusBarAfterExecuteVisibility && !cellToolbarLocation && !cellToolbarInteraction && !compactView @@ -188,6 +194,10 @@ export class NotebookOptions { configuration.showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); } + if (cellStatusBarAfterExecuteVisibility) { + configuration.showCellStatusBarAfterExecute = this.configurationService.getValue(ShowCellStatusBarAfterExecuteKey); + } + if (cellToolbarLocation) { configuration.cellToolbarLocation = this.configurationService.getValue(CellToolbarLocKey); } @@ -244,6 +254,7 @@ export class NotebookOptions { // trigger event this._onDidChangeOptions.fire({ cellStatusBarVisibility, + cellStatusBarAfterExecuteVisibility, cellToolbarLocation, cellToolbarInteraction, compactView, @@ -329,11 +340,7 @@ export class NotebookOptions { } computeStatusBarHeight(): number { - if (this._layoutConfiguration.showCellStatusBar) { - return this._layoutConfiguration.cellStatusBarHeight; - } else { - return 0; - } + return this._layoutConfiguration.cellStatusBarHeight; } computeCellToolbarLocation(viewType?: string): 'right' | 'left' | 'hidden' { From 771446e4a21cd1a8870ea5bacead19080786212a Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 25 May 2021 12:34:56 -0700 Subject: [PATCH 075/140] Make showCellStatusBarAfterExecute not experimental --- .../contrib/notebook/browser/notebook.contribution.ts | 8 +++++++- .../workbench/contrib/notebook/common/notebookCommon.ts | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index d6ddcffac33..24a80bf6895 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -29,7 +29,7 @@ import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEd import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { NotebookService } from 'vs/workbench/contrib/notebook/browser/notebookServiceImpl'; -import { CellKind, CellToolbarLocKey, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey, CompactView, FocusIndicator, InsertToolbarPosition, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, CellToolbarLocKey, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey, CompactView, FocusIndicator, InsertToolbarPosition, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled, ShowCellStatusBarAfterExecuteKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService'; @@ -581,6 +581,12 @@ configurationRegistry.registerConfiguration({ default: true, tags: ['notebookLayout'] }, + [ShowCellStatusBarAfterExecuteKey]: { + description: nls.localize('notebook.showCellStatusbarAfterExecute.description', "Whether the cell status bar should be shown after the cell has been executed."), + type: 'boolean', + default: false, + tags: ['notebookLayout'] + }, [NotebookTextDiffEditorPreview]: { description: nls.localize('notebook.diff.enablePreview.description', "Whether to use the enhanced text diff editor for notebook."), type: 'boolean', diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 3e63cb22a7c..e3441192d96 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -904,7 +904,7 @@ export const DisplayOrderKey = 'notebook.displayOrder'; export const CellToolbarLocKey = 'notebook.cellToolbarLocation'; export const CellToolbarVisibility = 'notebook.cellToolbarVisibility'; export const ShowCellStatusBarKey = 'notebook.showCellStatusBar'; -export const ShowCellStatusBarAfterExecuteKey = 'notebook.experimental.showCellStatusBarAfterExecute'; +export const ShowCellStatusBarAfterExecuteKey = 'notebook.showCellStatusBarAfterExecute'; export const NotebookTextDiffEditorPreview = 'notebook.diff.enablePreview'; export const ExperimentalUseMarkdownRenderer = 'notebook.experimental.useMarkdownRenderer'; export const ExperimentalInsertToolbarAlignment = 'notebook.experimental.insertToolbarAlignment'; From 8f18f3c5ff2e987eff9561f8563ebfed07db6280 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Tue, 25 May 2021 12:35:01 -0700 Subject: [PATCH 076/140] oops --- .../workbench/api/common/extHostTypeConverters.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 8069ae08a73..661814f370a 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1433,18 +1433,6 @@ export namespace NotebookCellMetadata { } } -export namespace NotebookCellInternalMetadata { - - export function to(data: notebooks.NotebookCellInternalMetadata): vscode.NotebookCellExecutionSummary { - return { - endTime: data.runEndTime, - startTime: data.runStartTime, - executionOrder: data.executionOrder, - success: data.lastRunSuccess - }; - } -} - export namespace NotebookDocumentMetadata { export function from(data: types.NotebookDocumentMetadata): notebooks.NotebookDocumentMetadata { @@ -1540,7 +1528,7 @@ export namespace NotebookCellData { data.language, data.outputs ? data.outputs.map(NotebookCellOutput.to) : undefined, data.metadata ? NotebookCellMetadata.to(data.metadata) : undefined, - data.internalMetadata ? NotebookCellInternalMetadata.to(data.internalMetadata) : undefined + data.internalMetadata ? NotebookCellExecutionSummary.to(data.internalMetadata) : undefined ); } } From 7fd8f828c02e3b6628df5f649d4dea108fb198ee Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Tue, 25 May 2021 14:50:37 -0500 Subject: [PATCH 077/140] fix pwsh profile test failures (#124613) --- .../terminal/node/terminalProfiles.ts | 8 ++++--- .../test/node/terminalProfiles.test.ts | 22 +++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/vs/platform/terminal/node/terminalProfiles.ts b/src/vs/platform/terminal/node/terminalProfiles.ts index 8b218b0e9ca..878376b9e2a 100644 --- a/src/vs/platform/terminal/node/terminalProfiles.ts +++ b/src/vs/platform/terminal/node/terminalProfiles.ts @@ -37,6 +37,7 @@ export function detectAvailableProfiles( safeConfigProvider(TerminalSettingId.UseWslProfiles) !== false, safeConfigProvider(TerminalSettingId.ProfilesWindows), safeConfigProvider(TerminalSettingId.DefaultProfileWindows), + testPaths, variableResolver ); } @@ -58,6 +59,7 @@ async function detectAvailableWindowsProfiles( useWslProfiles?: boolean, configProfiles?: { [key: string]: ITerminalProfileObject }, defaultProfileName?: string, + testPaths?: string[], variableResolver?: (text: string[]) => Promise ): Promise { // Determine the correct System32 path. We want to point to Sysnative @@ -73,7 +75,7 @@ async function detectAvailableWindowsProfiles( useWSLexe = true; } - await initializeWindowsProfiles(); + await initializeWindowsProfiles(testPaths); const detectedProfiles: Map = new Map(); @@ -175,7 +177,7 @@ async function transformToTerminalProfiles( return resultProfiles; } -async function initializeWindowsProfiles(): Promise { +async function initializeWindowsProfiles(testPaths?: string[]): Promise { if (profileSources) { return; } @@ -197,7 +199,7 @@ async function initializeWindowsProfiles(): Promise { }); profileSources.set('PowerShell', { profileName: 'PowerShell', - paths: await getPowershellPaths(), + paths: testPaths || await getPowershellPaths(), icon: ThemeIcon.asThemeIcon(Codicon.terminalPowershell) }); } diff --git a/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts b/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts index 5e521205775..b16844d7758 100644 --- a/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts +++ b/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts @@ -115,36 +115,36 @@ suite('Workbench - TerminalProfiles', () => { } as ITestTerminalConfig) as ITerminalConfiguration; test('should prefer pwsh 7 to Windows PowerShell', async () => { - const fsProvider = createFsProvider([ + const expectedPaths = [ 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', 'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe', 'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - ]); - const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined); + ]; + const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), undefined, undefined, undefined, expectedPaths); const expected = [ { profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', isDefault: true } ]; profilesEqual(profiles, expected); }); test('should prefer pwsh 7 to pwsh 6', async () => { - const fsProvider = createFsProvider([ + const expectedPaths = [ 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', 'C:\\Program Files\\PowerShell\\6\\pwsh.exe', 'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe', 'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - ]); - const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined); + ]; + const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), undefined, undefined, undefined, expectedPaths); const expected = [ { profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', isDefault: true } ]; profilesEqual(profiles, expected); }); - test.skip('should fallback to Windows PowerShell', async () => { - const fsProvider = createFsProvider([ + test('should fallback to Windows PowerShell', async () => { + const expectedPaths = [ 'C:\\Windows\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe', 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - ]); - const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined); + ]; + const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), undefined, undefined, undefined, expectedPaths); strictEqual(profiles.length, 1); strictEqual(profiles[0].profileName, 'PowerShell'); }); @@ -228,7 +228,7 @@ suite('Workbench - TerminalProfiles', () => { }, async readFile(path: string): Promise { if (path !== '/etc/shells') { - fail('Unexected path'); + fail('Unexepected path'); } return Buffer.from(etcShellsContent); } From 33209f104dbd5af313f9cb31dcfd4b2f16d0a2cb Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 25 May 2021 11:45:48 -0700 Subject: [PATCH 078/140] update markdown height on options change. --- .../notebook/browser/notebookBrowser.ts | 3 ++ .../browser/viewModel/baseCellViewModel.ts | 6 --- .../browser/viewModel/codeCellViewModel.ts | 6 +++ .../viewModel/markdownCellViewModel.ts | 46 +++++++++++++------ 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index d99af644b75..a2c0b6f900a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -235,6 +235,7 @@ export interface MarkdownCellLayoutInfo { readonly fontInfo: FontInfo | null; readonly editorWidth: number; readonly editorHeight: number; + readonly previewHeight: number; readonly bottomToolbarOffset: number; readonly totalHeight: number; } @@ -242,6 +243,8 @@ export interface MarkdownCellLayoutInfo { export interface MarkdownCellLayoutChangeEvent { font?: FontInfo; outerWidth?: number; + editorHeight?: number; + previewHeight?: number; totalHeight?: number; } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index e3bb83a117a..a768023c05a 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -150,12 +150,6 @@ export abstract class BaseCellViewModel extends Disposable { } })); - this._register(this._viewContext.notebookOptions.onDidChangeOptions(e => { - if (e.cellStatusBarVisibility || e.cellStatusBarAfterExecuteVisibility || e.insertToolbarPosition) { - this.layoutChange({}); - } - })); - this._register(this._configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration('notebook.lineNumbers')) { this.lineNumbers = 'inherit'; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 26cf4593431..fbb26df5f1b 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -126,6 +126,12 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } })); + this._register(this.viewContext.notebookOptions.onDidChangeOptions(e => { + if (e.cellStatusBarVisibility || e.cellStatusBarAfterExecuteVisibility || e.insertToolbarPosition) { + this.layoutChange({}); + } + })); + this._outputCollection = new Array(this.model.outputs.length); this._layoutInfo = { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index 42e899e05b0..033d499e163 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -27,33 +27,25 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie return this._layoutInfo; } + private _previewHeight = 0; + set renderedMarkdownHeight(newHeight: number) { if (this.getEditState() === CellEditState.Preview) { - const newTotalHeight = newHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomToolbarGap; // BOTTOM_CELL_TOOLBAR_GAP; - this.totalHeight = newTotalHeight; + this._previewHeight = newHeight; + this._updateTotalHeight(this._previewHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomToolbarGap); } } - private set totalHeight(newHeight: number) { - if (newHeight !== this.layoutInfo.totalHeight) { - this.layoutChange({ totalHeight: newHeight }); - } - } - - private get totalHeight() { - throw new Error('MarkdownCellViewModel.totalHeight is write only'); - } - private _editorHeight = 0; set editorHeight(newHeight: number) { this._editorHeight = newHeight; const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration(); - this.totalHeight = this._editorHeight + this._updateTotalHeight(this._editorHeight + layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + layoutConfiguration.markdownCellBottomMargin // MARKDOWN_CELL_BOTTOM_MARGIN + layoutConfiguration.bottomToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - + this.getEditorStatusbarHeight(); + + this.viewContext.notebookOptions.computeStatusBarHeight()); } get editorHeight() { @@ -116,6 +108,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._layoutInfo = { editorHeight: 0, + previewHeight: 0, fontInfo: initialNotebookLayoutInfo?.fontInfo || null, editorWidth: initialNotebookLayoutInfo?.width ? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(initialNotebookLayoutInfo.width) @@ -133,6 +126,21 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._onDidHideInput.fire(); } })); + + this._register(this.viewContext.notebookOptions.onDidChangeOptions(e => { + if (e.cellStatusBarVisibility || e.cellStatusBarAfterExecuteVisibility || e.insertToolbarPosition) { + const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration(); + if (this.getEditState() === CellEditState.Editing) { + this._updateTotalHeight(this._editorHeight + + layoutConfiguration.markdownCellTopMargin + + layoutConfiguration.markdownCellBottomMargin + + layoutConfiguration.bottomToolbarGap + + this.viewContext.notebookOptions.computeStatusBarHeight()); + } else { + this._updateTotalHeight(this._previewHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomToolbarGap); + } + } + })); } /** @@ -151,6 +159,12 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._onDidChangeState.fire({ foldingStateChanged: true }); } + private _updateTotalHeight(newHeight: number) { + if (newHeight !== this.layoutInfo.totalHeight) { + this.layoutChange({ totalHeight: newHeight }); + } + } + layoutChange(state: MarkdownCellLayoutChangeEvent) { // recompute if (!this.metadata.inputCollapsed) { @@ -158,10 +172,12 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie ? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; const totalHeight = state.totalHeight === undefined ? this._layoutInfo.totalHeight : state.totalHeight; + const previewHeight = this._previewHeight; this._layoutInfo = { fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, + previewHeight, editorHeight: this._editorHeight, bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight @@ -178,6 +194,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, editorHeight: this._editorHeight, + previewHeight: this._previewHeight, bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight }; @@ -193,6 +210,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._layoutInfo = { fontInfo: this._layoutInfo.fontInfo, editorWidth: this._layoutInfo.editorWidth, + previewHeight: this._layoutInfo.previewHeight, bottomToolbarOffset: this._layoutInfo.bottomToolbarOffset, totalHeight: totalHeight, editorHeight: this._editorHeight From 5926c50d6c4b72eb83f10de8f42f2d1dcf74f09c Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 25 May 2021 13:01:20 -0700 Subject: [PATCH 079/140] fix missing markdown height update --- .../contrib/notebook/browser/notebookEditorWidget.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index f79acc7418c..a3e503afe98 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -2482,10 +2482,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const cell = this.getCellById(cellId); const layoutConfiguration = this._notebookOptions.getLayoutConfiguration(); if (cell && cell instanceof MarkdownCellViewModel) { - if (height + layoutConfiguration.bottomToolbarGap !== cell.layoutInfo.totalHeight) { - this._debug('updateMarkdownCellHeight', cell.handle, height + layoutConfiguration.bottomToolbarGap, isInit); - cell.renderedMarkdownHeight = height; - } + this._debug('updateMarkdownCellHeight', cell.handle, height + layoutConfiguration.bottomToolbarGap, isInit); + cell.renderedMarkdownHeight = height; } } From 68ba0141fbd7f4b406ea09cb98cec2dac36883be Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 25 May 2021 13:04:07 -0700 Subject: [PATCH 080/140] fixed notebook focus indicator margin --- .../notebook/browser/notebookEditorWidget.ts | 21 ++++++++++++------- .../notebook/common/notebookOptions.ts | 10 +++++++-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index a3e503afe98..fd4b95fa2de 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -554,6 +554,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor cellBottomMargin, codeCellLeftMargin, markdownCellGutter, + markdownCellLeftMargin, markdownCellBottomMargin, markdownCellTopMargin, bottomToolbarGap: bottomCellToolbarGap, @@ -563,7 +564,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor focusIndicator, insertToolbarPosition, insertToolbarAlignment, - fontSize + fontSize, + focusIndicatorLeftMargin } = this._notebookOptions.getLayoutConfiguration(); const styleSheets: string[] = []; @@ -641,12 +643,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor height: 100%; z-index: 10; } - - .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-left:before { - border-left: 1px solid transparent; - border-right: 1px solid transparent; - border-radius: 2px; - } `); // left and right border margins @@ -657,6 +653,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-right:before { top: 0px; height: 100%; }`); + + styleSheets.push(` + .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-left:before, + .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.selected .cell-focus-indicator-left:before { + border-left: 2px solid transparent; + border-right: 1px solid transparent; + border-radius: 2px; + margin-left: ${focusIndicatorLeftMargin}px; + }`); } // between cell insert toolbar @@ -725,7 +730,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .execution-count-label { left: ${codeCellLeftMargin}px; width: ${cellRunGutter}px; }`); styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`); - styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { left: ${(markdownCellGutter - 20) / 2}px; }`); + styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { left: ${(markdownCellGutter - 20) / 2 + markdownCellLeftMargin}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${cellTopMargin}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${bottomCellToolbarGap}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left, diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 561f46c0356..3b395ed6a37 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -31,6 +31,7 @@ export interface NotebookLayoutConfiguration { cellBottomMargin: number; cellOutputPadding: number; codeCellLeftMargin: number; + markdownCellLeftMargin: number; markdownCellGutter: number; markdownCellTopMargin: number; markdownCellBottomMargin: number; @@ -56,6 +57,7 @@ export interface NotebookLayoutConfiguration { showFoldingControls: 'always' | 'mouseover'; dragAndDropEnabled: boolean; fontSize: number; + focusIndicatorLeftMargin: number; } interface NotebookOptionsChangeEvent { @@ -80,15 +82,19 @@ const defaultConfigConstants = { cellRunGutter: 32, markdownCellTopMargin: 8, markdownCellBottomMargin: 8, + markdownCellLeftMargin: 0, markdownCellGutter: 32, + focusIndicatorLeftMargin: 4 }; const compactConfigConstants = { - codeCellLeftMargin: 0, + codeCellLeftMargin: 8, cellRunGutter: 32, markdownCellTopMargin: 6, markdownCellBottomMargin: 6, + markdownCellLeftMargin: 8, markdownCellGutter: 32, + focusIndicatorLeftMargin: 4 }; export class NotebookOptions { @@ -391,7 +397,7 @@ export class NotebookOptions { outputNodePadding: this._layoutConfiguration.cellOutputPadding, outputNodeLeftPadding: this._layoutConfiguration.cellOutputPadding, previewNodePadding: this._layoutConfiguration.markdownPreviewPadding, - markdownLeftMargin: this._layoutConfiguration.markdownCellGutter, + markdownLeftMargin: this._layoutConfiguration.markdownCellGutter + this._layoutConfiguration.markdownCellLeftMargin, leftMargin: this._layoutConfiguration.codeCellLeftMargin, rightMargin: this._layoutConfiguration.cellRightMargin, runGutter: this._layoutConfiguration.cellRunGutter, From cf2a866b7dd24f66d5b3c331908dac46f90382ce Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 25 May 2021 22:14:31 +0200 Subject: [PATCH 081/140] test resolver: supports untrusted workspaces --- extensions/vscode-test-resolver/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index ae6a4f0680f..d091467079f 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -32,7 +32,8 @@ "capabilities": { "untrustedWorkspaces": { "supported": true - } + }, + "virtualWorkspaces": true }, "contributes": { "resourceLabelFormatters": [ From 757fd91f040bceeaf793c6536b3efaf77e7e728a Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 25 May 2021 23:02:22 +0200 Subject: [PATCH 082/140] Hide TestReolver.newWindow when in virtual workspace --- extensions/vscode-test-resolver/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index d091467079f..9aa252ea511 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -89,7 +89,7 @@ "statusBar/remoteIndicator": [ { "command": "vscode-testresolver.newWindow", - "when": "!remoteName", + "when": "!remoteName && !virtualWorkspace", "group": "remote_90_test_1_local@2" }, { From 72c4bd69c04d539196f738a01eee499cffdb1b7c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 25 May 2021 23:05:37 +0200 Subject: [PATCH 083/140] remote menu: sort entries of current remote first --- .../contrib/remote/browser/remoteIndicator.ts | 120 +++++++++++++----- 1 file changed, 86 insertions(+), 34 deletions(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts index 342ce7934eb..535b8db4e37 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts @@ -25,7 +25,7 @@ import { isWeb } from 'vs/base/common/platform'; import { once } from 'vs/base/common/functional'; import { truncate } from 'vs/base/common/strings'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { getVirtualWorkspaceLocation } from 'vs/platform/remote/common/remoteHosts'; +import { getRemoteName, getVirtualWorkspaceLocation, getVirtualWorkspaceScheme, isVirtualWorkspace } from 'vs/platform/remote/common/remoteHosts'; import { getCodiconAriaLabel } from 'vs/base/common/codicons'; import { ILogService } from 'vs/platform/log/common/log'; import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions'; @@ -53,6 +53,9 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr private remoteMenuActionsGroups: ActionGroup[] | undefined; private readonly remoteAuthority = this.environmentService.remoteAuthority; + + private virtualWorkspaceScheme: string | undefined = undefined; + private connectionState: 'initializing' | 'connected' | 'reconnecting' | 'disconnected' | undefined = undefined; private readonly connectionStateContextKey = new RawContextKey<'' | 'initializing' | 'disconnected' | 'connected'>('remoteConnectionState', '').bindTo(this.contextKeyService); @@ -80,6 +83,8 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr if (this.remoteAuthority) { this.connectionState = 'initializing'; this.connectionStateContextKey.set(this.connectionState); + } else { + this.updateVirtualWorkspaceScheme(); } this.registerActions(); @@ -107,7 +112,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr }); // Close Remote Connection - if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID && this.remoteAuthority) { + if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID) { registerAction2(class extends Action2 { constructor() { super({ @@ -117,17 +122,18 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr f1: true }); } - run = () => that.remoteAuthority && that.hostService.openWindow({ forceReuseWindow: true, remoteAuthority: null }); - }); - - MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { - group: '6_close', - command: { - id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, - title: nls.localize({ key: 'miCloseRemote', comment: ['&& denotes a mnemonic'] }, "Close Re&&mote Connection") - }, - order: 3.5 + run = () => that.hostService.openWindow({ forceReuseWindow: true, remoteAuthority: null }); }); + if (this.remoteAuthority) { + MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { + group: '6_close', + command: { + id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, + title: nls.localize({ key: 'miCloseRemote', comment: ['&& denotes a mnemonic'] }, "Close Re&&mote Connection") + }, + order: 3.5 + }); + } } if (this.extensionGalleryService.isEnabled()) { @@ -196,10 +202,17 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr })); } } else { - this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this.updateRemoteStatusIndicator())); + this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => { + this.updateVirtualWorkspaceScheme(); + this.updateRemoteStatusIndicator(); + })); } } + private updateVirtualWorkspaceScheme() { + this.virtualWorkspaceScheme = getVirtualWorkspaceScheme(this.workspaceContextService.getWorkspace()); + } + private async updateWhenInstalledExtensionsRegistered(): Promise { await this.extensionService.whenInstalledExtensionsRegistered(); @@ -280,13 +293,13 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr this.renderRemoteStatusIndicator(`$(remote) ${truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('host.tooltip', "Editing on {0}", hostLabel)); } return; - } - - // Workspace with label: indicate editing source - const workspaceLabel = this.getWorkspaceLabel(); - if (workspaceLabel) { - this.renderRemoteStatusIndicator(`$(remote) ${truncate(workspaceLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('workspace.tooltip', "Editing on {0}", workspaceLabel)); - return; + } else if (this.virtualWorkspaceScheme) { + // Workspace with label: indicate editing source + const workspaceLabel = this.getWorkspaceLabel(); + if (workspaceLabel) { + this.renderRemoteStatusIndicator(`$(remote) ${truncate(workspaceLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('workspace.tooltip', "Editing on {0}", workspaceLabel)); + return; + } } // Remote actions: offer menu @@ -342,11 +355,37 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr return undefined; }; + const matchCurrentRemote = () => { + if (this.remoteAuthority) { + return new RegExp(`^remote_\\d\\d_${getRemoteName(this.remoteAuthority)}_`); + } else if (this.virtualWorkspaceScheme) { + if (this.virtualWorkspaceScheme === 'vscode-vfs') { + return new RegExp(`^remote_\\d\\d_vfs_`); + } else { + return new RegExp(`^vfs_\\d\\d_${this.virtualWorkspaceScheme}_`); + } + } + return undefined; + }; + const computeItems = () => { - const actionGroups = this.getRemoteMenuActions(true); + let actionGroups = this.getRemoteMenuActions(true); const items: (IQuickPickItem | IQuickPickSeparator)[] = []; + const currentRemoteMatcher = matchCurrentRemote(); + if (currentRemoteMatcher) { + // commands for the current remote go first + actionGroups = actionGroups.sort((g1, g2) => { + const isCurrentRemote1 = currentRemoteMatcher.test(g1[0]); + const isCurrentRemote2 = currentRemoteMatcher.test(g2[0]); + if (isCurrentRemote1 !== isCurrentRemote2) { + return isCurrentRemote1 ? -1 : 1; + } + return g1[0].localeCompare(g2[0]); + }); + } + let lastCategoryName: string | undefined = undefined; for (let actionGroup of actionGroups) { @@ -371,25 +410,38 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr } } - if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID && this.remoteAuthority) { - if (items.length) { - items.push({ type: 'separator' }); - } + if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID) { + if (this.remoteAuthority) { + if (items.length) { + items.push({ type: 'separator' }); + } - items.push({ - type: 'item', - id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, - label: nls.localize('closeRemote.title', 'Close Remote Connection') - }); - - if (this.connectionState === 'disconnected') { items.push({ type: 'item', - id: ReloadWindowAction.ID, - label: nls.localize('reloadWindow', 'Reload Window') + id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, + label: nls.localize('closeRemoteConnection.title', 'Close Remote Connection') + }); + + if (this.connectionState === 'disconnected') { + items.push({ + type: 'item', + id: ReloadWindowAction.ID, + label: nls.localize('reloadWindow', 'Reload Window') + }); + } + } else if (this.virtualWorkspaceScheme) { + if (items.length) { + items.push({ type: 'separator' }); + } + + items.push({ + type: 'item', + id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, + label: nls.localize('closeRemoteWindow.title', 'Close Remote') }); } } + if (!this.remoteAuthority && this.extensionGalleryService.isEnabled()) { items.push({ type: 'separator' From 032920fa2eee3346417efef03f852950193506a8 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Tue, 25 May 2021 23:15:09 +0200 Subject: [PATCH 084/140] vfs -> virtualfs --- src/vs/workbench/contrib/remote/browser/remoteIndicator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts index 535b8db4e37..28eb999f97a 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts @@ -362,7 +362,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr if (this.virtualWorkspaceScheme === 'vscode-vfs') { return new RegExp(`^remote_\\d\\d_vfs_`); } else { - return new RegExp(`^vfs_\\d\\d_${this.virtualWorkspaceScheme}_`); + return new RegExp(`^virtualfs_\\d\\d_${this.virtualWorkspaceScheme}_`); } } return undefined; From f378cff1a8e5fd2e7354334fedecb56902953047 Mon Sep 17 00:00:00 2001 From: meganrogge Date: Tue, 25 May 2021 14:22:13 -0700 Subject: [PATCH 085/140] dropAndDrop -> dragAndDrop --- src/vs/workbench/contrib/terminal/browser/terminalInstance.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 95c23746b47..dbcd7c31b7e 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -775,7 +775,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _initDragAndDrop(container: HTMLElement) { this._dndObserver?.dispose(); - const dndController = new TerminalInstanceDropAndDropController(container); + const dndController = new TerminalInstanceDragAndDropController(container); dndController.onDropTerminal(e => this._onRequestAddInstanceToGroup.fire(e)); dndController.onDropFile(async path => { const preparedPath = await this._terminalInstanceService.preparePathForTerminalAsync(path, this.shellLaunchConfig.executable, this.title, this.shellType, this.isRemote); @@ -1872,7 +1872,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } -class TerminalInstanceDropAndDropController extends Disposable implements IDragAndDropObserverCallbacks { +class TerminalInstanceDragAndDropController extends Disposable implements IDragAndDropObserverCallbacks { private _dropOverlay?: HTMLElement; private readonly _onDropFile = new Emitter(); From e1731e910484aa086b63851c5014ea173a07e8c9 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 25 May 2021 14:23:05 -0700 Subject: [PATCH 086/140] fix build --- .../src/singlefolder-tests/notebook.test.ts | 18 ++++++++---------- .../vscode-notebook-tests/src/extension.ts | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index b00302b2808..4d9d26c1554 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -60,13 +60,13 @@ class Kernel { task.executionOrder = 1; if (cell.notebook.uri.path.endsWith('customRenderer.vsctestnb')) { await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/custom', ['test'], undefined) + vscode.NotebookCellOutputItem.text('test', 'text/custom', undefined) ])]); return; } await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['my output'], undefined) + vscode.NotebookCellOutputItem.text('my output', 'text/plain', undefined) ])]); task.end({ success: true }); } @@ -129,7 +129,7 @@ suite('Notebook API tests', function () { kind: vscode.NotebookCellKind.Code, outputs: [ new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', 'Hello World', { testOutputItemMetadata: true }) + vscode.NotebookCellOutputItem.text('Hello World', 'text/plain', { testOutputItemMetadata: true }) ], { testOutputMetadata: true }) ], @@ -182,7 +182,7 @@ suite('Notebook API tests', function () { const task = this.controller.createNotebookCellExecutionTask(cell); task.start(); await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['my second output'], undefined) + vscode.NotebookCellOutputItem.text('my second output', 'text/plain', undefined) ])]); task.end({ success: true }); } @@ -779,7 +779,7 @@ suite('Notebook API tests', function () { task.start(); task.token.onCancellationRequested(async () => { await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['Canceled'], undefined) + vscode.NotebookCellOutputItem.text('Canceled', 'text/plain', undefined) ])]); task.end({}); }); @@ -801,9 +801,7 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ - 'Canceled' - ]); + assert.deepStrictEqual(cell.outputs[0].outputs[0].value, 'Canceled'); }); cancelableKernel.controller.dispose(); @@ -826,7 +824,7 @@ suite('Notebook API tests', function () { async interrupt() { await this._task!.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['Interrupted'], undefined) + vscode.NotebookCellOutputItem.text('Interrupted', 'text/plain', undefined) ])]); this._task!.end({}); } @@ -1188,7 +1186,7 @@ suite('Notebook API tests', function () { const task = this.controller.createNotebookCellExecutionTask(cell); task.start(); await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['Some output'], undefined) + vscode.NotebookCellOutputItem.text('Some output', 'text/plain', undefined) ])]); assert.strictEqual(cell.notebook.cellAt(0).outputs.length, 1); assert.deepStrictEqual(cell.notebook.cellAt(0).outputs[0].outputs[0].value, ['Some output']); diff --git a/extensions/vscode-notebook-tests/src/extension.ts b/extensions/vscode-notebook-tests/src/extension.ts index 7ca6edc14f6..935968c0b4e 100644 --- a/extensions/vscode-notebook-tests/src/extension.ts +++ b/extensions/vscode-notebook-tests/src/extension.ts @@ -69,7 +69,7 @@ export function activate(context: vscode.ExtensionContext): any { const task = controller.createNotebookCellExecutionTask(cell); task.start(); task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/html', ['test output'], undefined) + vscode.NotebookCellOutputItem.text('test output', 'text/html', undefined) ])]); task.end({ success: true }); } From b4f4839da5e01f9babb248a2aa3c26ccbd54821b Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 25 May 2021 14:31:40 -0700 Subject: [PATCH 087/140] fix integration test --- .../src/singlefolder-tests/notebook.test.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index 4d9d26c1554..98b9ac8c12b 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -7,6 +7,7 @@ import 'mocha'; import * as assert from 'assert'; import * as vscode from 'vscode'; import { createRandomFile, asPromise, disposeAll, closeAllEditors, revertAllDirty, saveAllEditors, assertNoRpc } from '../utils'; +import { TextDecoder } from 'util'; async function createRandomNotebookFile() { return createRandomFile('', undefined, '.vsctestnb'); @@ -476,7 +477,7 @@ suite('Notebook API tests', function () { assert.deepStrictEqual(secondCell!.outputs[0].metadata, { testOutputMetadata: true }); assert.strictEqual(secondCell!.outputs[0].outputs.length, 1); assert.strictEqual(secondCell!.outputs[0].outputs[0].mime, 'text/plain'); - assert.strictEqual(secondCell!.outputs[0].outputs[0].value, 'Hello World'); + assert.strictEqual(new TextDecoder().decode(secondCell!.outputs[0].outputs[0].data), 'Hello World'); assert.deepStrictEqual(secondCell!.outputs[0].outputs[0].metadata, { testOutputItemMetadata: true }); assert.strictEqual(secondCell!.executionSummary?.executionOrder, 5); assert.strictEqual(secondCell!.executionSummary?.success, true); @@ -747,9 +748,7 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ - 'my output' - ]); + assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'my output'); }); await withEvent(vscode.notebook.onDidChangeCellOutputs, async (event) => { @@ -759,9 +758,7 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ - 'my second output' - ]); + assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'my second output'); }); }); @@ -801,7 +798,7 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(cell.outputs[0].outputs[0].value, 'Canceled'); + assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'Canceled'); }); cancelableKernel.controller.dispose(); @@ -843,9 +840,7 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ - 'Interrupted' - ]); + assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'Interrupted'); }); interruptableKernel.controller.dispose(); @@ -1189,7 +1184,7 @@ suite('Notebook API tests', function () { vscode.NotebookCellOutputItem.text('Some output', 'text/plain', undefined) ])]); assert.strictEqual(cell.notebook.cellAt(0).outputs.length, 1); - assert.deepStrictEqual(cell.notebook.cellAt(0).outputs[0].outputs[0].value, ['Some output']); + assert.deepStrictEqual(new TextDecoder().decode(cell.notebook.cellAt(0).outputs[0].outputs[0].data), 'Some output'); task.end({}); called = true; } From 20ce9d57629988ca80d57f0b216187db406a7471 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 25 May 2021 14:49:23 -0700 Subject: [PATCH 088/140] fix weird border rendering on windows. --- .../workbench/contrib/notebook/browser/notebookEditorWidget.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 0820bd76bbc..0218baf679a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -656,8 +656,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor styleSheets.push(` .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-left:before, .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.selected .cell-focus-indicator-left:before { - border-left: 2px solid transparent; - border-right: 1px solid transparent; + border-left: 3px solid transparent; border-radius: 2px; margin-left: ${focusIndicatorLeftMargin}px; }`); From 0b2d890624cd456c1adee4c111d88e7830087996 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Tue, 25 May 2021 14:55:12 -0700 Subject: [PATCH 089/140] fixes #124619 #wt --- .../workbench/services/workspaces/common/workspaceTrust.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/services/workspaces/common/workspaceTrust.ts b/src/vs/workbench/services/workspaces/common/workspaceTrust.ts index 00ece8fe9b5..8652288abae 100644 --- a/src/vs/workbench/services/workspaces/common/workspaceTrust.ts +++ b/src/vs/workbench/services/workspaces/common/workspaceTrust.ts @@ -202,6 +202,11 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork } getUriTrustInfo(uri: URI): IWorkspaceTrustUriInfo { + // Return trusted when workspace trust is disabled + if (!isWorkspaceTrustEnabled(this.configurationService)) { + return { trusted: true, uri }; + } + let resultState = false; let maxLength = -1; From 2d9aa1868ae4a878a34e960bf3e5cfdbe3db3125 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 25 May 2021 15:50:59 -0700 Subject: [PATCH 090/140] Fix broken @tag in settings editor Better fix for #124520 --- .../preferences/browser/settingsTreeModels.ts | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index 8146cf7e1fd..581e95611bd 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -701,7 +701,7 @@ export class SearchResultModel extends SettingsTreeModel { const isRemote = !!this.environmentService.remoteAuthority; this.root.children = this.root.children - .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && (this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : false)); + .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && child.matchesAnyFeature(this._viewState.featureFilters)); if (this.newExtensionSearchResults && this.newExtensionSearchResults.filterMatches.length) { const resultExtensionIds = this.newExtensionSearchResults.filterMatches @@ -715,22 +715,6 @@ export class SearchResultModel extends SettingsTreeModel { } } - private containsValidFeature(): boolean { - if (!this._viewState.featureFilters || !this._viewState.featureFilters.size || !tocData.children) { - return false; - } - - const features = tocData.children.find(child => child.id === 'features'); - - if (features && features.children) { - return Array.from(this._viewState.featureFilters).some(filter => { - return features.children?.find(feature => 'features/' + filter === feature.id); - }); - } else { - return false; - } - } - private getFlatSettings(): ISetting[] { const flatSettings: ISetting[] = []; arrays.coalesce(this.getUniqueResults()) From bb19c28fe2c01d47bae0177d485d1dbc841691d8 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Tue, 25 May 2021 22:51:32 +0000 Subject: [PATCH 091/140] Getting started layout polish --- .../gettingStarted/browser/gettingStarted.css | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index d252616bc61..0600e81458a 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -84,7 +84,7 @@ } .monaco-workbench .part.editor > .content .gettingStartedContainer .gettingStartedSlideCategories { - padding: 12px; + padding: 24px; } .monaco-workbench .part.editor > .content .gettingStartedContainer.animationReady .gettingStartedSlide { @@ -557,14 +557,11 @@ } .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .codicon-arrow-small-right { - position: relative; - top: 3px; - left: 2px; + padding-left: 8px; } .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .codicon-check-all { - position: relative; - top: 3px; + padding-right: 8px; } .monaco-workbench .part.editor > .content .gettingStartedContainer .gettingStartedSlide .skip { @@ -606,6 +603,11 @@ display: none; } +.monaco-workbench .part.editor > .content .gettingStartedContainer .done-next-container { + display: flex; + padding: 8px 16px 16px; +} + .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link { padding: 0; background: transparent; @@ -616,9 +618,13 @@ max-width: 100%; } +.monaco-workbench .part.editor > .content .gettingStartedContainer .done-next-container .button-link { + display: flex; + align-items: center; +} + .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link.next { - position: absolute; - right: 0; + margin-left: auto; } .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link:hover { @@ -645,7 +651,7 @@ } .monaco-workbench .part.editor > .content .gettingStartedContainer .getting-started-category .codicon { - top: 0; + top: 3px; } .monaco-workbench .part.editor > .content .getting-started-category .codicon::before{ From b0f67df65d79f46c4c801f49c16c99d98f2a937a Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 25 May 2021 16:00:03 -0700 Subject: [PATCH 092/140] Fix build --- src/vs/workbench/contrib/remote/browser/remoteIndicator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts index 28eb999f97a..351b49194de 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts @@ -25,7 +25,7 @@ import { isWeb } from 'vs/base/common/platform'; import { once } from 'vs/base/common/functional'; import { truncate } from 'vs/base/common/strings'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { getRemoteName, getVirtualWorkspaceLocation, getVirtualWorkspaceScheme, isVirtualWorkspace } from 'vs/platform/remote/common/remoteHosts'; +import { getRemoteName, getVirtualWorkspaceLocation, getVirtualWorkspaceScheme } from 'vs/platform/remote/common/remoteHosts'; import { getCodiconAriaLabel } from 'vs/base/common/codicons'; import { ILogService } from 'vs/platform/log/common/log'; import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions'; From 8ccc1243fc062396f987fd471ddc1700fb866f77 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 25 May 2021 16:35:03 -0700 Subject: [PATCH 093/140] Fix notebook unit test --- .../workbench/test/browser/api/extHostTypes.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/test/browser/api/extHostTypes.test.ts b/src/vs/workbench/test/browser/api/extHostTypes.test.ts index 353096359eb..ac2117b6745 100644 --- a/src/vs/workbench/test/browser/api/extHostTypes.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTypes.test.ts @@ -696,28 +696,28 @@ suite('ExtHostTypes', function () { item = types.NotebookCellOutputItem.json(1); assert.strictEqual(item.mime, 'application/json'); - assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify(1))); + assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(1))); item = types.NotebookCellOutputItem.json(1, 'foo'); assert.strictEqual(item.mime, 'foo'); - assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify(1))); + assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(1))); item = types.NotebookCellOutputItem.json(true); assert.strictEqual(item.mime, 'application/json'); - assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify(true))); + assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(true))); item = types.NotebookCellOutputItem.json([true, 1, 'ddd']); assert.strictEqual(item.mime, 'application/json'); - assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify([true, 1, 'ddd'], undefined, '\t'))); + assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify([true, 1, 'ddd'], undefined, '\t'))); // --- text item = types.NotebookCellOutputItem.text('Hęłlö'); assert.strictEqual(item.mime, 'text/plain'); - assert.deepStrictEqual(item.value, new TextEncoder().encode('Hęłlö')); + assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö')); item = types.NotebookCellOutputItem.text('Hęłlö', 'foo/bar'); assert.strictEqual(item.mime, 'foo/bar'); - assert.deepStrictEqual(item.value, new TextEncoder().encode('Hęłlö')); + assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö')); }); }); From 225767683423adff07e6bfea3a5353010425327e Mon Sep 17 00:00:00 2001 From: Harald Kirschner Date: Wed, 26 May 2021 00:02:28 +0000 Subject: [PATCH 094/140] Applied new style to first getting started walkthrough --- .../common/gettingStartedContent.ts | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts b/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts index 677c337f4e9..99ae8d9e434 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/common/gettingStartedContent.ts @@ -170,8 +170,8 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ { id: 'Setup', - title: localize('gettingStarted.setup.title', "Customize your Setup"), - description: localize('gettingStarted.setup.description', "Extend and customize VS Code to make it yours."), + title: localize('gettingStarted.setup.title', "Get Started with VS Code"), + description: localize('gettingStarted.setup.description', "Discover the best customizations to make VS Code yours."), icon: setupIcon, next: 'Beginner', when: 'remoteName != codespaces', @@ -180,14 +180,14 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ steps: [ { id: 'pickColorTheme', - title: localize('gettingStarted.pickColor.title', "Customize the look with themes"), - description: localize('gettingStarted.pickColor.description', "Pick a color theme to match your taste and mood while coding.\n[Pick a Theme](command:workbench.action.selectTheme)"), + title: localize('gettingStarted.pickColor.title', "Choose the look you want"), + description: localize('gettingStarted.pickColor.description', "The right color palette helps you focus on your code, is easy on your eyes, and is simply more fun to use.\n[Browse Color Themes](command:workbench.action.selectTheme)"), media: { type: 'image', altText: 'Color theme preview for dark and light theme.', path: 'colorTheme.png', } }, { id: 'findLanguageExtensions', - title: localize('gettingStarted.findLanguageExts.title', "Code in any language"), - description: localize('gettingStarted.findLanguageExts.description', "VS Code supports over 50+ programming languages. While many are built-in, others can be easily installed as extensions in one click.\n[Browse Language Extensions](command:workbench.extensions.action.showLanguageExtensions)"), + title: localize('gettingStarted.findLanguageExts.title', "Rich support for all your languages"), + description: localize('gettingStarted.findLanguageExts.description', "Code smarter with syntax highlighting, code completion, linting and debugging. While many languages are built-in, many more can be added as extensions.\n[Browse Language Extensions](command:workbench.extensions.action.showLanguageExtensions)"), media: { type: 'image', altText: 'Language extensions', path: { dark: 'dark/languageExtensions.png', @@ -196,10 +196,22 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ } } }, + { + id: 'commandPaletteTask', + title: localize('gettingStarted.commandPalette.title', "One shortcut to access everything"), + description: localize('gettingStarted.commandPalette.description', "Commands Palette is the keyboard way to accomplish any task in VS Code. **Practice** by looking up your frequently used commands to save time and keep in the flow.\n[Open Command Palette](command:workbench.action.showCommands)\n__Try searching for 'view toggle'.__"), + media: { + type: 'image', altText: 'Command Palette overlay for searching and executing commands.', path: { + dark: 'dark/commandPalette.png', + light: 'light/commandPalette.png', + hc: 'hc/commandPalette.png', + } + }, + }, { id: 'keymaps', - title: localize('gettingStarted.keymaps.title', "Switch from other editors"), - description: localize('gettingStarted.keymaps.description', "Bring your favorite keyboard shortcuts from other editors into VS Code with keymaps.\n[Browse Keymap Extensions](command:workbench.extensions.action.showRecommendedKeymapExtensions)"), + title: localize('gettingStarted.keymaps.title', "Bring your favorite shortcuts"), + description: localize('gettingStarted.keymaps.description', "If you already have your favorite shortcuts from another editor, bring them into VS Code.\n[Browse Keymap Extensions](command:workbench.extensions.action.showRecommendedKeymapExtensions)"), media: { type: 'image', altText: 'List of keymap extensions.', path: { dark: 'dark/keymaps.png', @@ -210,8 +222,8 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ }, { id: 'settingsSync', - title: localize('gettingStarted.settingsSync.title', "Sync your favorite setup"), - description: localize('gettingStarted.settingsSync.description', "Never lose the perfect VS Code setup! Settings Sync will back up and share settings, keybindings & extensions across several VS Code instances.\n[Enable Settings Sync](command:workbench.userDataSync.actions.turnOn)"), + title: localize('gettingStarted.settingsSync.title', "Sync your stuff across devices"), + description: localize('gettingStarted.settingsSync.description', "Never lose the perfect VS Code setup! Settings Sync will back up and share settings, keybindings & extensions across several installations.\n[Enable Settings Sync](command:workbench.userDataSync.actions.turnOn)"), when: 'syncStatus != uninitialized', completionEvents: ['onEvent:sync-enabled'], media: { @@ -224,8 +236,8 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ }, { id: 'pickAFolderTask-Mac', - title: localize('gettingStarted.setup.OpenFolder.title', "Open your project folder"), - description: localize('gettingStarted.setup.OpenFolder.description', "Open a project folder to start coding!\n[Pick a Folder](command:workbench.action.files.openFileFolder)"), + title: localize('gettingStarted.setup.OpenFolder.title', "Open up your code"), + description: localize('gettingStarted.setup.OpenFolder.description', "You're all set to start coding. Open a project folder to get your files into VS Code.\n[Pick a Folder](command:workbench.action.files.openFileFolder)"), when: 'isMac && workspaceFolderCount == 0', media: { type: 'image', altText: 'Explorer view showing buttons for opening folder and cloning repository.', path: { @@ -237,8 +249,8 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ }, { id: 'pickAFolderTask-Other', - title: localize('gettingStarted.setup.OpenFolder.title', "Open your project folder"), - description: localize('gettingStarted.setup.OpenFolder.description2', "Open a project folder to start coding!\n[Pick a Folder](command:workbench.action.files.openFolder)"), + title: localize('gettingStarted.setup.OpenFolder.title', "Open up your code"), + description: localize('gettingStarted.setup.OpenFolder.description2', "You're all set to start coding. Open a project folder to get your files into VS Code.\n[Pick a Folder](command:workbench.action.files.openFolder)"), when: '!isMac && workspaceFolderCount == 0', media: { type: 'image', altText: 'Explorer view showing buttons for opening folder and cloning repository.', path: { @@ -250,7 +262,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ }, { id: 'quickOpen', - title: localize('gettingStarted.quickOpen.title', "Quick open files"), + title: localize('gettingStarted.quickOpen.title', "Quickly navigate between your file"), description: localize('gettingStarted.quickOpen.description', "Navigate between files in an instant with one keystroke. Tip: Open multiple files by pressing the right arrow key.\n[Quick Open a File](command:toSide:workbench.action.quickOpen)"), when: 'workspaceFolderCount != 0', media: { @@ -275,15 +287,15 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ type: 'steps', steps: [ { - id: 'commandPaletteTask', - title: localize('gettingStarted.commandPalette.title', "Find & run commands"), - description: localize('gettingStarted.commandPalette.description', "The easiest way to find everything VS Code can do. If you're ever looking for a feature or a shortcut, check here first!\n[Open Command Palette](command:workbench.action.showCommands)"), + id: 'playground', + title: localize('gettingStarted.playground.title', "Redefine your editing skills"), + description: localize('gettingStarted.playground.description', "Want to code faster and smarter? Practice powerful code editing features in the interactive playground.\n[Open Interactive Playground](command:toSide:workbench.action.showInteractivePlayground)"), media: { - type: 'image', altText: 'Command Palette overlay for searching and executing commands.', path: { - dark: 'dark/commandPalette.png', - light: 'light/commandPalette.png', - hc: 'hc/commandPalette.png', - } + type: 'image', altText: 'Interactive Playground.', path: { + dark: 'dark/playground.png', + light: 'light/playground.png', + hc: 'light/playground.png' + }, }, }, { @@ -341,18 +353,6 @@ export const walkthroughs: GettingStartedWalkthroughContent = [ content: { type: 'steps', steps: [ - { - id: 'playground', - title: localize('gettingStarted.playground.title', "Redefine your editing skills"), - description: localize('gettingStarted.playground.description', "Want to code faster and smarter? Practice powerful code editing features in the interactive playground.\n[Open Interactive Playground](command:toSide:workbench.action.showInteractivePlayground)"), - media: { - type: 'image', altText: 'Interactive Playground.', path: { - dark: 'dark/playground.png', - light: 'light/playground.png', - hc: 'light/playground.png' - }, - }, - }, { id: 'splitview', title: localize('gettingStarted.splitview.title', "Side by side editing"), From 7c01395da16c1e9af9c2a17bac4935e3177d1c33 Mon Sep 17 00:00:00 2001 From: Harald Kirschner Date: Tue, 25 May 2021 17:19:40 -0700 Subject: [PATCH 095/140] Revert "Merge branch 'main' of https://github.com/microsoft/vscode into main" This reverts commit 7a976501eb30cf48c162808f54a666fbffcd96c0, reversing changes made to 225767683423adff07e6bfea3a5353010425327e. --- extensions/emmet/package.json | 6 +- extensions/emmet/yarn.lock | 12 +- .../markdown-language-features/package.json | 2 +- .../notebook-markdown-extensions/package.json | 2 +- .../src/singlefolder-tests/notebook.test.ts | 35 +++-- extensions/vscode-notebook-tests/package.json | 2 +- .../vscode-notebook-tests/src/extension.ts | 2 +- extensions/vscode-test-resolver/package.json | 5 +- .../electron-browser/workbench/workbench.html | 2 +- .../electron-sandbox/workbench/workbench.html | 2 +- .../common/terminalPlatformConfiguration.ts | 3 +- .../terminal/node/terminalProfiles.ts | 30 ++--- src/vs/vscode.proposed.d.ts | 46 +++---- .../api/common/extHostTerminalService.ts | 2 +- .../api/common/extHostTypeConverters.ts | 15 ++- src/vs/workbench/api/common/extHostTypes.ts | 34 ++--- .../notebook/browser/extensionPoint.ts | 2 +- .../notebook/browser/media/notebook.css | 2 +- .../notebook/browser/notebook.contribution.ts | 8 +- .../notebook/browser/notebookBrowser.ts | 3 - .../notebook/browser/notebookEditorWidget.ts | 29 +++-- .../notebook/browser/notebookServiceImpl.ts | 4 +- .../browser/view/renderers/cellRenderer.ts | 11 +- .../browser/view/renderers/markdownCell.ts | 1 - .../browser/view/renderers/webviewPreloads.ts | 14 +- .../browser/viewModel/baseCellViewModel.ts | 18 +-- .../browser/viewModel/codeCellViewModel.ts | 12 +- .../viewModel/markdownCellViewModel.ts | 46 ++----- .../common/model/notebookCellTextModel.ts | 3 +- .../contrib/notebook/common/notebookCommon.ts | 2 - .../notebook/common/notebookOptions.ts | 33 ++--- .../preferences/browser/settingsEditor2.ts | 20 +-- .../preferences/browser/settingsTreeModels.ts | 18 ++- .../contrib/remote/browser/remoteIndicator.ts | 120 +++++------------- .../contrib/terminal/browser/terminal.ts | 10 +- .../terminal/browser/terminalActions.ts | 36 +----- .../terminal/browser/terminalInstance.ts | 22 ++-- .../terminal/browser/terminalService.ts | 23 +--- .../terminal/browser/terminalTabbedView.ts | 9 +- .../terminal/browser/terminalTabsList.ts | 118 ++--------------- .../test/node/terminalProfiles.test.ts | 22 ++-- .../gettingStarted/browser/gettingStarted.css | 24 ++-- .../workspaces/common/workspaceTrust.ts | 5 - .../browser/api/extHostTypeConverter.test.ts | 22 +--- .../test/browser/api/extHostTypes.test.ts | 12 +- 45 files changed, 264 insertions(+), 585 deletions(-) diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 77b08c02ac9..0af69221a29 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -226,11 +226,7 @@ }, "output.selfClosingStyle": { "type": "string", - "enum": [ - "html", - "xhtml", - "xml" - ], + "enum": ["html", "xhtml", "xml"], "default": "html", "markdownDescription": "%emmetPreferencesOutputSelfClosingStyle%" }, diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 2d35a2c78ab..b9d9785a550 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -54,9 +54,9 @@ integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI= "@types/node@14.x": - version "14.17.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.1.tgz#5e07e0cb2ff793aa7a1b41deae76221e6166049f" - integrity sha512-/tpUyFD7meeooTRwl3sYlihx2BrJE7q9XF71EguPFIySj9B7qgnRtHsHTho+0AUm4m1SvWGm6uSncrR94q6Vtw== + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== emmet@^2.3.0: version "2.3.4" @@ -77,9 +77,9 @@ jsonc-parser@^2.3.0: integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg== vscode-emmet-helper@^2.3.0: - version "2.6.4" - resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.6.4.tgz#bea47f17649bba26b412f3d1fac18aaee43eba25" - integrity sha512-fP0nunW1RUWEKGf4gqiYLOVNFFGXSRHjCl0pikxtwCFlty8WwimM+RBJ5o0aIiwerrYD30HqeaVyvDW027Sseg== + version "2.6.2" + resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.6.2.tgz#777b471a7851ba0ca8e4151533be7f92511f39b0" + integrity sha512-SkL1WjZZsA+bfTo52QH4PgqXCQAJSqzOmJtAY3rOl17MKbY6iJhVv2T26PshjmUnHoXnXMNa7PcLMCS75RsQDQ== dependencies: emmet "^2.3.0" jsonc-parser "^2.3.0" diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index a9e98206b3e..728a439f0dd 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -40,7 +40,7 @@ } }, "contributes": { - "notebookRenderer": [ + "notebookOutputRenderer": [ { "id": "markdownItRenderer", "displayName": "Markdown it renderer", diff --git a/extensions/notebook-markdown-extensions/package.json b/extensions/notebook-markdown-extensions/package.json index 981566798f6..ef3911f2eb9 100644 --- a/extensions/notebook-markdown-extensions/package.json +++ b/extensions/notebook-markdown-extensions/package.json @@ -21,7 +21,7 @@ } }, "contributes": { - "notebookRenderer": [ + "notebookOutputRenderer": [ { "id": "markdownItRenderer-katex", "displayName": "Markdown it katex renderer", diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index 98b9ac8c12b..b00302b2808 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -7,7 +7,6 @@ import 'mocha'; import * as assert from 'assert'; import * as vscode from 'vscode'; import { createRandomFile, asPromise, disposeAll, closeAllEditors, revertAllDirty, saveAllEditors, assertNoRpc } from '../utils'; -import { TextDecoder } from 'util'; async function createRandomNotebookFile() { return createRandomFile('', undefined, '.vsctestnb'); @@ -61,13 +60,13 @@ class Kernel { task.executionOrder = 1; if (cell.notebook.uri.path.endsWith('customRenderer.vsctestnb')) { await task.replaceOutput([new vscode.NotebookCellOutput([ - vscode.NotebookCellOutputItem.text('test', 'text/custom', undefined) + new vscode.NotebookCellOutputItem('text/custom', ['test'], undefined) ])]); return; } await task.replaceOutput([new vscode.NotebookCellOutput([ - vscode.NotebookCellOutputItem.text('my output', 'text/plain', undefined) + new vscode.NotebookCellOutputItem('text/plain', ['my output'], undefined) ])]); task.end({ success: true }); } @@ -130,7 +129,7 @@ suite('Notebook API tests', function () { kind: vscode.NotebookCellKind.Code, outputs: [ new vscode.NotebookCellOutput([ - vscode.NotebookCellOutputItem.text('Hello World', 'text/plain', { testOutputItemMetadata: true }) + new vscode.NotebookCellOutputItem('text/plain', 'Hello World', { testOutputItemMetadata: true }) ], { testOutputMetadata: true }) ], @@ -183,7 +182,7 @@ suite('Notebook API tests', function () { const task = this.controller.createNotebookCellExecutionTask(cell); task.start(); await task.replaceOutput([new vscode.NotebookCellOutput([ - vscode.NotebookCellOutputItem.text('my second output', 'text/plain', undefined) + new vscode.NotebookCellOutputItem('text/plain', ['my second output'], undefined) ])]); task.end({ success: true }); } @@ -477,7 +476,7 @@ suite('Notebook API tests', function () { assert.deepStrictEqual(secondCell!.outputs[0].metadata, { testOutputMetadata: true }); assert.strictEqual(secondCell!.outputs[0].outputs.length, 1); assert.strictEqual(secondCell!.outputs[0].outputs[0].mime, 'text/plain'); - assert.strictEqual(new TextDecoder().decode(secondCell!.outputs[0].outputs[0].data), 'Hello World'); + assert.strictEqual(secondCell!.outputs[0].outputs[0].value, 'Hello World'); assert.deepStrictEqual(secondCell!.outputs[0].outputs[0].metadata, { testOutputItemMetadata: true }); assert.strictEqual(secondCell!.executionSummary?.executionOrder, 5); assert.strictEqual(secondCell!.executionSummary?.success, true); @@ -748,7 +747,9 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'my output'); + assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ + 'my output' + ]); }); await withEvent(vscode.notebook.onDidChangeCellOutputs, async (event) => { @@ -758,7 +759,9 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'my second output'); + assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ + 'my second output' + ]); }); }); @@ -776,7 +779,7 @@ suite('Notebook API tests', function () { task.start(); task.token.onCancellationRequested(async () => { await task.replaceOutput([new vscode.NotebookCellOutput([ - vscode.NotebookCellOutputItem.text('Canceled', 'text/plain', undefined) + new vscode.NotebookCellOutputItem('text/plain', ['Canceled'], undefined) ])]); task.end({}); }); @@ -798,7 +801,9 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'Canceled'); + assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ + 'Canceled' + ]); }); cancelableKernel.controller.dispose(); @@ -821,7 +826,7 @@ suite('Notebook API tests', function () { async interrupt() { await this._task!.replaceOutput([new vscode.NotebookCellOutput([ - vscode.NotebookCellOutputItem.text('Interrupted', 'text/plain', undefined) + new vscode.NotebookCellOutputItem('text/plain', ['Interrupted'], undefined) ])]); this._task!.end({}); } @@ -840,7 +845,9 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'Interrupted'); + assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ + 'Interrupted' + ]); }); interruptableKernel.controller.dispose(); @@ -1181,10 +1188,10 @@ suite('Notebook API tests', function () { const task = this.controller.createNotebookCellExecutionTask(cell); task.start(); await task.replaceOutput([new vscode.NotebookCellOutput([ - vscode.NotebookCellOutputItem.text('Some output', 'text/plain', undefined) + new vscode.NotebookCellOutputItem('text/plain', ['Some output'], undefined) ])]); assert.strictEqual(cell.notebook.cellAt(0).outputs.length, 1); - assert.deepStrictEqual(new TextDecoder().decode(cell.notebook.cellAt(0).outputs[0].outputs[0].data), 'Some output'); + assert.deepStrictEqual(cell.notebook.cellAt(0).outputs[0].outputs[0].value, ['Some output']); task.end({}); called = true; } diff --git a/extensions/vscode-notebook-tests/package.json b/extensions/vscode-notebook-tests/package.json index 6a0e2d648de..c6c690151b6 100644 --- a/extensions/vscode-notebook-tests/package.json +++ b/extensions/vscode-notebook-tests/package.json @@ -46,7 +46,7 @@ ] } ], - "notebookRenderer": [ + "notebookOutputRenderer": [ { "id": "notebookCoreTestRenderer", "displayName": "Notebook Core Test Renderer", diff --git a/extensions/vscode-notebook-tests/src/extension.ts b/extensions/vscode-notebook-tests/src/extension.ts index 935968c0b4e..7ca6edc14f6 100644 --- a/extensions/vscode-notebook-tests/src/extension.ts +++ b/extensions/vscode-notebook-tests/src/extension.ts @@ -69,7 +69,7 @@ export function activate(context: vscode.ExtensionContext): any { const task = controller.createNotebookCellExecutionTask(cell); task.start(); task.replaceOutput([new vscode.NotebookCellOutput([ - vscode.NotebookCellOutputItem.text('test output', 'text/html', undefined) + new vscode.NotebookCellOutputItem('text/html', ['test output'], undefined) ])]); task.end({ success: true }); } diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index 9aa252ea511..ae6a4f0680f 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -32,8 +32,7 @@ "capabilities": { "untrustedWorkspaces": { "supported": true - }, - "virtualWorkspaces": true + } }, "contributes": { "resourceLabelFormatters": [ @@ -89,7 +88,7 @@ "statusBar/remoteIndicator": [ { "command": "vscode-testresolver.newWindow", - "when": "!remoteName && !virtualWorkspace", + "when": "!remoteName", "group": "remote_90_test_1_local@2" }, { diff --git a/src/vs/code/electron-browser/workbench/workbench.html b/src/vs/code/electron-browser/workbench/workbench.html index 38405e41e15..bd37436f1fd 100644 --- a/src/vs/code/electron-browser/workbench/workbench.html +++ b/src/vs/code/electron-browser/workbench/workbench.html @@ -4,7 +4,7 @@ - + diff --git a/src/vs/code/electron-sandbox/workbench/workbench.html b/src/vs/code/electron-sandbox/workbench/workbench.html index 38405e41e15..bd37436f1fd 100644 --- a/src/vs/code/electron-sandbox/workbench/workbench.html +++ b/src/vs/code/electron-sandbox/workbench/workbench.html @@ -4,7 +4,7 @@ - + diff --git a/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts b/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts index 95e697e62cf..3ab5f4e8620 100644 --- a/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts +++ b/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts @@ -10,7 +10,6 @@ import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema'; import { Registry } from 'vs/platform/registry/common/platform'; import { Codicon, iconRegistry } from 'vs/base/common/codicons'; import { OperatingSystem } from 'vs/base/common/platform'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; const terminalProfileBaseProperties: IJSONSchemaMap = { args: { @@ -373,7 +372,7 @@ export function registerTerminalDefaultProfileConfiguration(detectedProfiles?: { } function createProfileDescription(profile: ITerminalProfile): string { - let description = `$(${ThemeIcon.isThemeIcon(profile.icon) ? profile.icon.id : profile.icon ? profile.icon : Codicon.terminal.id}) ${profile.profileName}\n- path: ${profile.path}`; + let description = `$(${profile.icon || Codicon.terminal.id}) ${profile.profileName}\n- path: ${profile.path}`; if (profile.args) { if (typeof profile.args === 'string') { description += `\n- args: "${profile.args}"`; diff --git a/src/vs/platform/terminal/node/terminalProfiles.ts b/src/vs/platform/terminal/node/terminalProfiles.ts index 878376b9e2a..8082d39f17f 100644 --- a/src/vs/platform/terminal/node/terminalProfiles.ts +++ b/src/vs/platform/terminal/node/terminalProfiles.ts @@ -37,7 +37,6 @@ export function detectAvailableProfiles( safeConfigProvider(TerminalSettingId.UseWslProfiles) !== false, safeConfigProvider(TerminalSettingId.ProfilesWindows), safeConfigProvider(TerminalSettingId.DefaultProfileWindows), - testPaths, variableResolver ); } @@ -59,7 +58,6 @@ async function detectAvailableWindowsProfiles( useWslProfiles?: boolean, configProfiles?: { [key: string]: ITerminalProfileObject }, defaultProfileName?: string, - testPaths?: string[], variableResolver?: (text: string[]) => Promise ): Promise { // Determine the correct System32 path. We want to point to Sysnative @@ -75,7 +73,7 @@ async function detectAvailableWindowsProfiles( useWSLexe = true; } - await initializeWindowsProfiles(testPaths); + await initializeWindowsProfiles(); const detectedProfiles: Map = new Map(); @@ -177,7 +175,7 @@ async function transformToTerminalProfiles( return resultProfiles; } -async function initializeWindowsProfiles(testPaths?: string[]): Promise { +async function initializeWindowsProfiles(): Promise { if (profileSources) { return; } @@ -199,7 +197,7 @@ async function initializeWindowsProfiles(testPaths?: string[]): Promise { }); profileSources.set('PowerShell', { profileName: 'PowerShell', - paths: testPaths || await getPowershellPaths(), + paths: await getPowershellPaths(), icon: ThemeIcon.asThemeIcon(Codicon.terminalPowershell) }); } @@ -247,25 +245,23 @@ async function getWslProfiles(wslPath: string, defaultProfileName: string | unde profileName, path: wslPath, args: [`-d`, `${distroName}`], - isDefault: profileName === defaultProfileName, - icon: getWslIcon(distroName) + isDefault: profileName === defaultProfileName }; + if (distroName.includes('Ubuntu')) { + profile.icon = ThemeIcon.asThemeIcon(Codicon.terminalUbuntu); + } + else if (distroName.includes('Debian')) { + profile.icon = ThemeIcon.asThemeIcon(Codicon.terminalDebian); + } else { + profile.icon = ThemeIcon.asThemeIcon(Codicon.terminalLinux); + } + // Add the profile profiles.push(profile); } return profiles; } -function getWslIcon(distroName: string): ThemeIcon { - if (distroName.includes('Ubuntu')) { - return ThemeIcon.asThemeIcon(Codicon.terminalUbuntu); - } else if (distroName.includes('Debian')) { - return ThemeIcon.asThemeIcon(Codicon.terminalDebian); - } else { - return ThemeIcon.asThemeIcon(Codicon.terminalLinux); - } -} - async function detectAvailableUnixProfiles( fsProvider: IFsProvider, logService?: ILogService, diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 10df4b473fa..94096b84ecf 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1247,12 +1247,11 @@ declare module 'vscode' { * * *Note* that an UTF-8 encoder is used to create bytes for the string. * - * @param value A string. + * @param value A string/ * @param mime Optional MIME type, defaults to `text/plain`. - * @param metadata Optional metadata. * @returns A new output item object. */ - static text(value: string, mime?: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; + static text(value: string, mime?: string): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` from @@ -1264,40 +1263,46 @@ declare module 'vscode' { * * @param value A JSON-stringifyable value. * @param mime Optional MIME type, defaults to `application/json` - * @param metadata Optional metadata. * @returns A new output item object. */ - static json(value: any, mime?: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; + static json(value: any, mime?: string): NotebookCellOutputItem; + + /** + * Factory function to create a `NotebookCellOutputItem` from bytes. + * + * @param value An array of unsigned 8-bit integers. + * @param mime Optional MIME type, defaults to `application/octet-stream`. + * @returns A new output item object. + */ + //todo@API better names: bytes, raw, buffer? + static bytes(value: Uint8Array, mime?: string): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` that uses * uses the `application/vnd.code.notebook.stdout` mime type. * * @param value A string. - * @param metadata Optional metadata. * @returns A new output item object. */ - static stdout(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; + static stdout(value: string): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` that uses * uses the `application/vnd.code.notebook.stderr` mime type. * * @param value A string. - * @param metadata Optional metadata. * @returns A new output item object. */ - static stderr(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; + static stderr(value: string): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` that uses * uses the `application/vnd.code.notebook.error` mime type. * * @param value An error object. - * @param metadata Optional metadata. * @returns A new output item object. */ - static error(value: Error, metadata?: { [key: string]: any }): NotebookCellOutputItem; + static error(value: Error): NotebookCellOutputItem; /** * The mime type which determines how the {@link NotebookCellOutputItem.value `value`}-property @@ -1309,26 +1314,21 @@ declare module 'vscode' { mime: string; /** - * The data of this output item. Must always be an array of unsigned 8-bit integers. + * The value of this output item. Must always be an array of unsigned 8-bit integers. */ - data: Uint8Array; + //todo@API only Unit8Array + value: Uint8Array | unknown; - /** - * @deprecated - */ - value: unknown; - - //todo@API metadata?: { [key: string]: any }; /** * Create a new notbook cell output item. * - * @param data The value of the output item. * @param mime The mime type of the output item. + * @param value The value of the output item. * @param metadata Optional metadata for this output item. */ - constructor(data: Uint8Array, mime: string, metadata?: { [key: string]: any }); + constructor(mime: string, value: Uint8Array | unknown, metadata?: { [key: string]: any }); } // @jrieken transient @@ -1563,9 +1563,6 @@ declare module 'vscode' { /** * The identifier of this notebook controller. - * - * _Note_ that controllers are remembered by their identifier and that extensions should use - * stable identifiers across sessions. */ readonly id: string; @@ -1657,7 +1654,6 @@ declare module 'vscode' { * @param cell The notebook cell for which to create the execution. * @returns A notebook cell execution. */ - // todo@API rename to NotebookCellExecution createNotebookCellExecutionTask(cell: NotebookCell): NotebookCellExecutionTask; // todo@API find a better name than "preloads" diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index ea3e1713eff..1deba734389 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -350,7 +350,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I public getDefaultShellArgs(useAutomationShell: boolean): string[] | string { const profile = useAutomationShell ? this._defaultAutomationProfile : this._defaultProfile; - return profile?.args || []; + return profile?.args || ['']; } public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal { diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 9cb42ef3d54..94bfff83773 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays'; +import { VSBuffer } from 'vs/base/common/buffer'; import * as htmlContent from 'vs/base/common/htmlContent'; import { DisposableStore } from 'vs/base/common/lifecycle'; import * as marked from 'vs/base/common/marked/marked'; @@ -1535,9 +1536,9 @@ export namespace NotebookCellOutputItem { export function from(item: types.NotebookCellOutputItem): notebooks.IOutputItemDto { let value: unknown; let valueBytes: number[] | undefined; - if (item.data instanceof Uint8Array) { + if (item.value instanceof Uint8Array) { //todo@jrieken this HACKY and SLOW... hoist VSBuffer instead - valueBytes = Array.from(item.data); + valueBytes = Array.from(item.value); } else { value = item.value; } @@ -1550,13 +1551,15 @@ export namespace NotebookCellOutputItem { } export function to(item: notebooks.IOutputItemDto): types.NotebookCellOutputItem { - let value: Uint8Array | any; - if (Array.isArray(item.valueBytes)) { - value = new Uint8Array(item.valueBytes); + + let value: Uint8Array | unknown; + if (item.value instanceof VSBuffer) { + value = item.value.buffer; } else { value = item.value; } - return new types.NotebookCellOutputItem(value, item.mime, item.metadata); + + return new types.NotebookCellOutputItem(item.mime, value, item.metadata); } } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index fdccb8c119c..1dfecfab513 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3112,50 +3112,44 @@ export class NotebookCellOutputItem { return typeof (obj).mime === 'string'; } - static error(err: Error | { name: string, message?: string, stack?: string }, metadata?: { [key: string]: any }): NotebookCellOutputItem { + static error(err: Error | { name: string, message?: string, stack?: string }): NotebookCellOutputItem { const obj = { name: err.name, message: err.message, stack: err.stack }; - return NotebookCellOutputItem.json(obj, 'application/vnd.code.notebook.error', metadata); + return NotebookCellOutputItem.json(obj, 'application/vnd.code.notebook.error'); } - static stdout(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem { - return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stdout', metadata); + static stdout(value: string): NotebookCellOutputItem { + return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stdout'); } - static stderr(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem { - return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stderr', metadata); + static stderr(value: string): NotebookCellOutputItem { + return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stderr'); } - static bytes(value: Uint8Array, mime: string = 'application/octet-stream', metadata?: { [key: string]: any }): NotebookCellOutputItem { - return new NotebookCellOutputItem(value, mime, metadata); + static bytes(value: Uint8Array, mime: string = 'application/octet-stream'): NotebookCellOutputItem { + return new NotebookCellOutputItem(mime, value); } static #encoder = new TextEncoder(); - static text(value: string, mime: string = 'text/plain', metadata?: { [key: string]: any }): NotebookCellOutputItem { + static text(value: string, mime: string = 'text/plain'): NotebookCellOutputItem { const bytes = NotebookCellOutputItem.#encoder.encode(String(value)); - return new NotebookCellOutputItem(bytes, mime, metadata); + return new NotebookCellOutputItem(mime, bytes); } - static json(value: any, mime: string = 'application/json', metadata?: { [key: string]: any }): NotebookCellOutputItem { + static json(value: any, mime: string = 'application/json'): NotebookCellOutputItem { const rawStr = JSON.stringify(value, undefined, '\t'); - return NotebookCellOutputItem.text(rawStr, mime, metadata); + return NotebookCellOutputItem.text(rawStr, mime); } - /** @deprecated */ - public value: Uint8Array | unknown; // JSON'able - constructor( - public data: Uint8Array, public mime: string, - public metadata?: { [key: string]: any } + public value: Uint8Array | unknown, // JSON'able + public metadata?: Record ) { - if (!(data instanceof Uint8Array)) { - this.value = data; - } if (isFalsyOrWhitespace(this.mime)) { throw new Error('INVALID mime type, must not be empty or falsy'); } diff --git a/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts b/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts index 406d5a41951..e925a6fdf98 100644 --- a/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts +++ b/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts @@ -192,6 +192,6 @@ export const notebooksExtensionPoint = ExtensionsRegistry.registerExtensionPoint export const notebookRendererExtensionPoint = ExtensionsRegistry.registerExtensionPoint( { - extensionPoint: 'notebookRenderer', + extensionPoint: 'notebookOutputRenderer', jsonSchema: notebookRendererContribution }); diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index a1769e49bcb..012a0b71fa7 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -425,7 +425,7 @@ overflow: hidden; } -.monaco-workbench .notebookOverlay .cell-statusbar-hidden .cell-statusbar-container { +.monaco-workbench .notebookOverlay.cell-statusbar-hidden .cell-statusbar-container { display: none; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 69f20ea18bc..18c20f8a83b 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -30,7 +30,7 @@ import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEd import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { NotebookService } from 'vs/workbench/contrib/notebook/browser/notebookServiceImpl'; -import { CellKind, CellToolbarLocKey, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey, CompactView, FocusIndicator, InsertToolbarPosition, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled, ShowCellStatusBarAfterExecuteKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, CellToolbarLocKey, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey, CompactView, FocusIndicator, InsertToolbarPosition, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService'; @@ -582,12 +582,6 @@ configurationRegistry.registerConfiguration({ default: true, tags: ['notebookLayout'] }, - [ShowCellStatusBarAfterExecuteKey]: { - description: nls.localize('notebook.showCellStatusbarAfterExecute.description', "Whether the cell status bar should be shown after the cell has been executed."), - type: 'boolean', - default: false, - tags: ['notebookLayout'] - }, [NotebookTextDiffEditorPreview]: { description: nls.localize('notebook.diff.enablePreview.description', "Whether to use the enhanced text diff editor for notebook."), type: 'boolean', diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index a2c0b6f900a..d99af644b75 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -235,7 +235,6 @@ export interface MarkdownCellLayoutInfo { readonly fontInfo: FontInfo | null; readonly editorWidth: number; readonly editorHeight: number; - readonly previewHeight: number; readonly bottomToolbarOffset: number; readonly totalHeight: number; } @@ -243,8 +242,6 @@ export interface MarkdownCellLayoutInfo { export interface MarkdownCellLayoutChangeEvent { font?: FontInfo; outerWidth?: number; - editorHeight?: number; - previewHeight?: number; totalHeight?: number; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 0218baf679a..b9b697c5514 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -511,6 +511,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const cellToolbarLocation = this._notebookOptions.computeCellToolbarLocation(this.viewModel?.viewType); this._overlayContainer.classList.add(`cell-title-toolbar-${cellToolbarLocation}`); + const showCellStatusBar = this._notebookOptions.getLayoutConfiguration().showCellStatusBar; + this._overlayContainer.classList.toggle('cell-statusbar-hidden', !showCellStatusBar); + const cellToolbarInteraction = this._notebookOptions.getLayoutConfiguration().cellToolbarInteraction; let cellToolbarInteractionState = 'hover'; this._overlayContainer.classList.remove('cell-toolbar-hover'); @@ -552,7 +555,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor cellRunGutter, cellBottomMargin, codeCellLeftMargin, - markdownCellGutter, markdownCellLeftMargin, markdownCellBottomMargin, markdownCellTopMargin, @@ -563,8 +565,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor focusIndicator, insertToolbarPosition, insertToolbarAlignment, - fontSize, - focusIndicatorLeftMargin + fontSize } = this._notebookOptions.getLayoutConfiguration(); const styleSheets: string[] = []; @@ -642,6 +643,12 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor height: 100%; z-index: 10; } + + .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-left:before { + border-left: 1px solid transparent; + border-right: 1px solid transparent; + border-radius: 2px; + } `); // left and right border margins @@ -652,14 +659,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-right:before { top: 0px; height: 100%; }`); - - styleSheets.push(` - .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-left:before, - .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.selected .cell-focus-indicator-left:before { - border-left: 3px solid transparent; - border-radius: 2px; - margin-left: ${focusIndicatorLeftMargin}px; - }`); } // between cell insert toolbar @@ -728,7 +727,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .execution-count-label { left: ${codeCellLeftMargin}px; width: ${cellRunGutter}px; }`); styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`); - styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { left: ${(markdownCellGutter - 20) / 2 + markdownCellLeftMargin}px; }`); + styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { left: ${(markdownCellLeftMargin - 20) / 2}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${cellTopMargin}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${bottomCellToolbarGap}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left, @@ -2485,8 +2484,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const cell = this.getCellById(cellId); const layoutConfiguration = this._notebookOptions.getLayoutConfiguration(); if (cell && cell instanceof MarkdownCellViewModel) { - this._debug('updateMarkdownCellHeight', cell.handle, height + layoutConfiguration.bottomToolbarGap, isInit); - cell.renderedMarkdownHeight = height; + if (height + layoutConfiguration.bottomToolbarGap !== cell.layoutInfo.totalHeight) { + this._debug('updateMarkdownCellHeight', cell.handle, height + layoutConfiguration.bottomToolbarGap, isInit); + cell.renderedMarkdownHeight = height; + } } } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 7e6311c80a3..90c4f8bc43e 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -349,13 +349,13 @@ export class NotebookService extends Disposable implements INotebookService { for (const extension of renderers) { for (const notebookContribution of extension.value) { if (!notebookContribution.entrypoint) { // avoid crashing - extension.collector.error(`Notebook renderer does not specify entry point`); + console.error(`Cannot register renderer for ${extension.description.identifier.value} since it did not have an entrypoint. This is now required: https://github.com/microsoft/vscode/issues/102644`); continue; } const id = notebookContribution.id ?? notebookContribution.viewType; if (!id) { - extension.collector.error(`Notebook renderer does not specify id-property`); + console.error(`Notebook renderer from ${extension.description.identifier.value} is missing an 'id'`); continue; } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index c58a65e0cc9..a1abbac5a74 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -521,8 +521,6 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR templateData.focusIndicatorBottom.style.top = `${indicatorPostion.bottomIndicatorTop}px`; templateData.focusIndicatorLeft.style.height = `${indicatorPostion.verticalIndicatorHeight}px`; templateData.focusIndicatorRight.style.height = `${indicatorPostion.verticalIndicatorHeight}px`; - - templateData.container.classList.toggle('cell-statusbar-hidden', element.getEditorStatusbarHeight() === 0); } private updateForHover(element: MarkdownCellViewModel, templateData: MarkdownCellRenderTemplate): void { @@ -854,7 +852,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende } } - private updateForInternalMetadata(element: CodeCellViewModel, templateData: CodeCellRenderTemplate): void { + private updateForInternalMetadata(element: CodeCellViewModel, templateData: CodeCellRenderTemplate, editorOptions: CellEditorOptions): void { if (!this.notebookEditor.hasModel()) { return; } @@ -896,8 +894,6 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende templateData.outputContainer.style.top = `${element.layoutInfo.outputContainerOffset}px`; templateData.outputShowMoreContainer.style.top = `${element.layoutInfo.outputShowMoreContainerOffset}px`; templateData.dragHandle.style.height = `${element.layoutInfo.totalHeight - layoutInfo.bottomToolbarGap}px`; - - templateData.container.classList.toggle('cell-statusbar-hidden', element.getEditorStatusbarHeight() === 0); } renderElement(element: CodeCellViewModel, index: number, templateData: CodeCellRenderTemplate, height: number | undefined): void { @@ -963,14 +959,13 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende this.updateForLayout(element, templateData); })); - this.updateForInternalMetadata(element, templateData); + this.updateForInternalMetadata(element, templateData, cellEditorOptions); this.updateForHover(element, templateData); this.updateForFocus(element, templateData); cellEditorOptions.setLineNumbers(element.lineNumbers); elementDisposables.add(element.onDidChangeState((e) => { if (e.internalMetadataChanged) { - this.updateForInternalMetadata(element, templateData); - this.updateForLayout(element, templateData); + this.updateForInternalMetadata(element, templateData, cellEditorOptions); } if (e.outputIsHoveredChanged) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index 79574328b08..1b0270c2b6d 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -250,7 +250,6 @@ export class StatefulMarkdownCell extends Disposable { private updateFoldingIconShowClass() { const showFoldingIcon = this.notebookEditor.notebookOptions.getLayoutConfiguration().showFoldingControls; - this.templateData.foldingIndicator.classList.remove('mouseover', 'always'); this.templateData.foldingIndicator.classList.add(showFoldingIcon); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 8250b75e1f3..f097895be8b 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -468,10 +468,8 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re text(): string; json(): any; - data(): Uint8Array; + bytes(): Uint8Array blob(): Blob; - /** @deprecated */ - bytes(): Uint8Array; } interface IDestroyCellInfo { @@ -494,7 +492,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re postKernelMessage: (data: unknown) => postNotebookMessage('customKernelMessage', { message: data }), }; - const ttPolicy = window.trustedTypes?.createPolicy('notebookRenderer', { + const ttPolicy = window.trustedTypes?.createPolicy('notebookOutputRenderer', { createHTML: value => value, createScript: value => value, }); @@ -645,10 +643,9 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re mime: content.mimeType, value: content.value, metadata: content.metadata, - data() { + bytes() { return content.valueBytes; }, - bytes() { return this.data(); }, text() { return new TextDecoder().decode(content.valueBytes) || String(content.value); //todo@jrieken remove this once `value` is gone! @@ -1041,9 +1038,8 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re outputId: undefined, text() { return content; }, json() { return undefined; }, - bytes() { return this.data(); }, - data() { return new TextEncoder().encode(content); }, - blob() { return new Blob([this.data()], { type: this.mime }); }, + bytes() { return new Uint8Array(); }, + blob() { return new Blob(); }, }); } }(); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index a768023c05a..c1ebfdb4c06 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -144,8 +144,10 @@ export abstract class BaseCellViewModel extends Disposable { this._register(model.onDidChangeInternalMetadata(e => { this._onDidChangeState.fire({ internalMetadataChanged: true, runStateChanged: e.runStateChanged }); - if (e.runStateChanged || e.lastRunSuccessChanged) { - // Statusbar visibility may change + })); + + this._register(this._viewContext.notebookOptions.onDidChangeOptions(e => { + if (e.cellStatusBarVisibility || e.insertToolbarPosition) { this.layoutChange({}); } })); @@ -158,17 +160,7 @@ export abstract class BaseCellViewModel extends Disposable { } getEditorStatusbarHeight() { - return this.statusBarIsVisible() ? this._viewContext.notebookOptions.computeStatusBarHeight() : 0; - } - - private statusBarIsVisible(): boolean { - if (this._viewContext.notebookOptions.getLayoutConfiguration().showCellStatusBar) { - return true; - } else if (this._viewContext.notebookOptions.getLayoutConfiguration().showCellStatusBarAfterExecute) { - return typeof this.internalMetadata.lastRunSuccess === 'boolean' || this.internalMetadata.runState !== undefined; - } else { - return false; - } + return this._viewContext.notebookOptions.computeStatusBarHeight(); } abstract hasDynamicHeight(): boolean; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index fbb26df5f1b..e40a99e886a 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -126,12 +126,6 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } })); - this._register(this.viewContext.notebookOptions.onDidChangeOptions(e => { - if (e.cellStatusBarVisibility || e.cellStatusBarAfterExecuteVisibility || e.insertToolbarPosition) { - this.layoutChange({}); - } - })); - this._outputCollection = new Array(this.model.outputs.length); this._layoutInfo = { @@ -158,7 +152,6 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod const outputShowMoreContainerHeight = state.outputShowMoreContainerHeight ? state.outputShowMoreContainerHeight : this._layoutInfo.outputShowMoreContainerHeight; let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata.outputCollapsed ? notebookLayoutConfiguration.collapsedIndicatorHeight : this._outputsTop!.getTotalValue()); - const originalLayout = this.layoutInfo; if (!this.metadata.inputCollapsed) { let newState: CodeCellLayoutState; let editorHeight: number; @@ -242,7 +235,10 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod }; } - state.totalHeight = this.layoutInfo.totalHeight !== originalLayout.totalHeight; + if (state.editorHeight || state.outputHeight) { + state.totalHeight = true; + } + state.source = source; this._fireOnDidChangeLayout(state); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index 033d499e163..c0b94acf079 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -27,25 +27,33 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie return this._layoutInfo; } - private _previewHeight = 0; - set renderedMarkdownHeight(newHeight: number) { if (this.getEditState() === CellEditState.Preview) { - this._previewHeight = newHeight; - this._updateTotalHeight(this._previewHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomToolbarGap); + const newTotalHeight = newHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomToolbarGap; // BOTTOM_CELL_TOOLBAR_GAP; + this.totalHeight = newTotalHeight; } } + private set totalHeight(newHeight: number) { + if (newHeight !== this.layoutInfo.totalHeight) { + this.layoutChange({ totalHeight: newHeight }); + } + } + + private get totalHeight() { + throw new Error('MarkdownCellViewModel.totalHeight is write only'); + } + private _editorHeight = 0; set editorHeight(newHeight: number) { this._editorHeight = newHeight; const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration(); - this._updateTotalHeight(this._editorHeight + this.totalHeight = this._editorHeight + layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + layoutConfiguration.markdownCellBottomMargin // MARKDOWN_CELL_BOTTOM_MARGIN + layoutConfiguration.bottomToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - + this.viewContext.notebookOptions.computeStatusBarHeight()); + + this.viewContext.notebookOptions.computeStatusBarHeight(); } get editorHeight() { @@ -108,7 +116,6 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._layoutInfo = { editorHeight: 0, - previewHeight: 0, fontInfo: initialNotebookLayoutInfo?.fontInfo || null, editorWidth: initialNotebookLayoutInfo?.width ? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(initialNotebookLayoutInfo.width) @@ -126,21 +133,6 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._onDidHideInput.fire(); } })); - - this._register(this.viewContext.notebookOptions.onDidChangeOptions(e => { - if (e.cellStatusBarVisibility || e.cellStatusBarAfterExecuteVisibility || e.insertToolbarPosition) { - const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration(); - if (this.getEditState() === CellEditState.Editing) { - this._updateTotalHeight(this._editorHeight - + layoutConfiguration.markdownCellTopMargin - + layoutConfiguration.markdownCellBottomMargin - + layoutConfiguration.bottomToolbarGap - + this.viewContext.notebookOptions.computeStatusBarHeight()); - } else { - this._updateTotalHeight(this._previewHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomToolbarGap); - } - } - })); } /** @@ -159,12 +151,6 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._onDidChangeState.fire({ foldingStateChanged: true }); } - private _updateTotalHeight(newHeight: number) { - if (newHeight !== this.layoutInfo.totalHeight) { - this.layoutChange({ totalHeight: newHeight }); - } - } - layoutChange(state: MarkdownCellLayoutChangeEvent) { // recompute if (!this.metadata.inputCollapsed) { @@ -172,12 +158,10 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie ? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; const totalHeight = state.totalHeight === undefined ? this._layoutInfo.totalHeight : state.totalHeight; - const previewHeight = this._previewHeight; this._layoutInfo = { fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, - previewHeight, editorHeight: this._editorHeight, bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight @@ -194,7 +178,6 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, editorHeight: this._editorHeight, - previewHeight: this._previewHeight, bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight }; @@ -210,7 +193,6 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._layoutInfo = { fontInfo: this._layoutInfo.fontInfo, editorWidth: this._layoutInfo.editorWidth, - previewHeight: this._layoutInfo.previewHeight, bottomToolbarOffset: this._layoutInfo.bottomToolbarOffset, totalHeight: totalHeight, editorHeight: this._editorHeight diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts index 17db539b562..b963316e2f2 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts @@ -59,14 +59,13 @@ export class NotebookCellTextModel extends Disposable implements ICell { set internalMetadata(newInternalMetadata: NotebookCellInternalMetadata) { const runStateChanged = this._internalMetadata.runState !== newInternalMetadata.runState; - const lastRunSuccessChanged = this._internalMetadata.lastRunSuccess !== newInternalMetadata.lastRunSuccess; newInternalMetadata = { ...newInternalMetadata, ...{ runStartTimeAdjustment: computeRunStartTimeAdjustment(this._internalMetadata, newInternalMetadata) } }; this._internalMetadata = newInternalMetadata; this._hash = null; - this._onDidChangeInternalMetadata.fire({ runStateChanged, lastRunSuccessChanged }); + this._onDidChangeInternalMetadata.fire({ runStateChanged }); } get language() { diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index e3441192d96..9a6803d7544 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -189,7 +189,6 @@ export interface ICellOutput { export interface CellInternalMetadataChangedEvent { readonly runStateChanged?: boolean; - readonly lastRunSuccessChanged?: boolean; } export interface ICell { @@ -904,7 +903,6 @@ export const DisplayOrderKey = 'notebook.displayOrder'; export const CellToolbarLocKey = 'notebook.cellToolbarLocation'; export const CellToolbarVisibility = 'notebook.cellToolbarVisibility'; export const ShowCellStatusBarKey = 'notebook.showCellStatusBar'; -export const ShowCellStatusBarAfterExecuteKey = 'notebook.showCellStatusBarAfterExecute'; export const NotebookTextDiffEditorPreview = 'notebook.diff.enablePreview'; export const ExperimentalUseMarkdownRenderer = 'notebook.experimental.useMarkdownRenderer'; export const ExperimentalInsertToolbarAlignment = 'notebook.experimental.insertToolbarAlignment'; diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 3b395ed6a37..56234848c49 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -6,7 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { CellToolbarLocKey, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, DragAndDropEnabled, ExperimentalInsertToolbarAlignment, FocusIndicator, GlobalToolbar, InsertToolbarPosition, ShowCellStatusBarAfterExecuteKey, ShowCellStatusBarKey, ShowFoldingControls } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellToolbarLocKey, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, DragAndDropEnabled, FocusIndicator, GlobalToolbar, ExperimentalInsertToolbarAlignment, InsertToolbarPosition, ShowFoldingControls, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; const SCROLLABLE_ELEMENT_PADDING_TOP = 18; @@ -32,7 +32,6 @@ export interface NotebookLayoutConfiguration { cellOutputPadding: number; codeCellLeftMargin: number; markdownCellLeftMargin: number; - markdownCellGutter: number; markdownCellTopMargin: number; markdownCellBottomMargin: number; markdownPreviewPadding: number; @@ -44,7 +43,6 @@ export interface NotebookLayoutConfiguration { editorBottomPaddingWithoutStatusBar: number; collapsedIndicatorHeight: number; showCellStatusBar: boolean; - showCellStatusBarAfterExecute: boolean; cellStatusBarHeight: number; cellToolbarLocation: string | { [key: string]: string }; cellToolbarInteraction: string; @@ -57,12 +55,10 @@ export interface NotebookLayoutConfiguration { showFoldingControls: 'always' | 'mouseover'; dragAndDropEnabled: boolean; fontSize: number; - focusIndicatorLeftMargin: number; } interface NotebookOptionsChangeEvent { cellStatusBarVisibility?: boolean; - cellStatusBarAfterExecuteVisibility?: boolean; cellToolbarLocation?: boolean; cellToolbarInteraction?: boolean; editorTopPadding?: boolean; @@ -82,19 +78,15 @@ const defaultConfigConstants = { cellRunGutter: 32, markdownCellTopMargin: 8, markdownCellBottomMargin: 8, - markdownCellLeftMargin: 0, - markdownCellGutter: 32, - focusIndicatorLeftMargin: 4 + markdownCellLeftMargin: 32, }; const compactConfigConstants = { - codeCellLeftMargin: 8, + codeCellLeftMargin: 0, cellRunGutter: 32, markdownCellTopMargin: 6, markdownCellBottomMargin: 6, - markdownCellLeftMargin: 8, - markdownCellGutter: 32, - focusIndicatorLeftMargin: 4 + markdownCellLeftMargin: 32, }; export class NotebookOptions { @@ -105,7 +97,6 @@ export class NotebookOptions { constructor(private readonly configurationService: IConfigurationService) { const showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); - const showCellStatusBarAfterExecute = this.configurationService.getValue(ShowCellStatusBarAfterExecuteKey); const globalToolbar = this.configurationService.getValue(GlobalToolbar) ?? false; const consolidatedOutputButton = this.configurationService.getValue(ConsolidatedOutputButton) ?? true; const dragAndDropEnabled = this.configurationService.getValue(DragAndDropEnabled) ?? true; @@ -136,7 +127,6 @@ export class NotebookOptions { editorBottomPaddingWithoutStatusBar: 12, collapsedIndicatorHeight: 24, showCellStatusBar, - showCellStatusBarAfterExecute, globalToolbar, consolidatedOutputButton, dragAndDropEnabled, @@ -164,7 +154,6 @@ export class NotebookOptions { private _updateConfiguration(e: IConfigurationChangeEvent) { const cellStatusBarVisibility = e.affectsConfiguration(ShowCellStatusBarKey); - const cellStatusBarAfterExecuteVisibility = e.affectsConfiguration(ShowCellStatusBarAfterExecuteKey); const cellToolbarLocation = e.affectsConfiguration(CellToolbarLocKey); const cellToolbarInteraction = e.affectsConfiguration(CellToolbarVisibility); const compactView = e.affectsConfiguration(CompactView); @@ -179,7 +168,6 @@ export class NotebookOptions { if ( !cellStatusBarVisibility - && !cellStatusBarAfterExecuteVisibility && !cellToolbarLocation && !cellToolbarInteraction && !compactView @@ -200,10 +188,6 @@ export class NotebookOptions { configuration.showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); } - if (cellStatusBarAfterExecuteVisibility) { - configuration.showCellStatusBarAfterExecute = this.configurationService.getValue(ShowCellStatusBarAfterExecuteKey); - } - if (cellToolbarLocation) { configuration.cellToolbarLocation = this.configurationService.getValue(CellToolbarLocKey); } @@ -260,7 +244,6 @@ export class NotebookOptions { // trigger event this._onDidChangeOptions.fire({ cellStatusBarVisibility, - cellStatusBarAfterExecuteVisibility, cellToolbarLocation, cellToolbarInteraction, compactView, @@ -346,7 +329,11 @@ export class NotebookOptions { } computeStatusBarHeight(): number { - return this._layoutConfiguration.cellStatusBarHeight; + if (this._layoutConfiguration.showCellStatusBar) { + return this._layoutConfiguration.cellStatusBarHeight; + } else { + return 0; + } } computeCellToolbarLocation(viewType?: string): 'right' | 'left' | 'hidden' { @@ -397,7 +384,7 @@ export class NotebookOptions { outputNodePadding: this._layoutConfiguration.cellOutputPadding, outputNodeLeftPadding: this._layoutConfiguration.cellOutputPadding, previewNodePadding: this._layoutConfiguration.markdownPreviewPadding, - markdownLeftMargin: this._layoutConfiguration.markdownCellGutter + this._layoutConfiguration.markdownCellLeftMargin, + markdownLeftMargin: this._layoutConfiguration.markdownCellLeftMargin, leftMargin: this._layoutConfiguration.codeCellLeftMargin, rightMargin: this._layoutConfiguration.cellRightMargin, runGutter: this._layoutConfiguration.cellRunGutter, diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 1b29e99765e..1657bc1f187 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -92,25 +92,7 @@ export class SettingsEditor2 extends EditorPane { private static CONFIG_SCHEMA_UPDATE_DELAYER = 500; private static readonly SUGGESTIONS: string[] = [ - `@${MODIFIED_SETTING_TAG}`, - '@tag:usesOnlineServices', - '@tag:sync', - `@tag:${REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG}`, - `@${ID_SETTING_TAG}`, - `@${EXTENSION_SETTING_TAG}`, - `@${FEATURE_SETTING_TAG}scm`, - `@${FEATURE_SETTING_TAG}explorer`, - `@${FEATURE_SETTING_TAG}search`, - `@${FEATURE_SETTING_TAG}debug`, - `@${FEATURE_SETTING_TAG}extensions`, - `@${FEATURE_SETTING_TAG}terminal`, - `@${FEATURE_SETTING_TAG}task`, - `@${FEATURE_SETTING_TAG}problems`, - `@${FEATURE_SETTING_TAG}output`, - `@${FEATURE_SETTING_TAG}comments`, - `@${FEATURE_SETTING_TAG}remote`, - `@${FEATURE_SETTING_TAG}timeline`, - `@${FEATURE_SETTING_TAG}notebook`, + `@${MODIFIED_SETTING_TAG}`, '@tag:usesOnlineServices', '@tag:sync', `@tag:${REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG}`, `@${ID_SETTING_TAG}`, `@${EXTENSION_SETTING_TAG}`, `@${FEATURE_SETTING_TAG}scm`, `@${FEATURE_SETTING_TAG}explorer`, `@${FEATURE_SETTING_TAG}search`, `@${FEATURE_SETTING_TAG}debug`, `@${FEATURE_SETTING_TAG}extensions`, `@${FEATURE_SETTING_TAG}terminal`, `@${FEATURE_SETTING_TAG}task`, `@${FEATURE_SETTING_TAG}problems`, `@${FEATURE_SETTING_TAG}output`, `@${FEATURE_SETTING_TAG}comments`, `@${FEATURE_SETTING_TAG}remote`, `@${FEATURE_SETTING_TAG}timeline` ]; private static shouldSettingUpdateFast(type: SettingValueType | SettingValueType[]): boolean { diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index 581e95611bd..9a29509d851 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -701,7 +701,7 @@ export class SearchResultModel extends SettingsTreeModel { const isRemote = !!this.environmentService.remoteAuthority; this.root.children = this.root.children - .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && child.matchesAnyFeature(this._viewState.featureFilters)); + .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && (this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : true)); if (this.newExtensionSearchResults && this.newExtensionSearchResults.filterMatches.length) { const resultExtensionIds = this.newExtensionSearchResults.filterMatches @@ -715,6 +715,22 @@ export class SearchResultModel extends SettingsTreeModel { } } + private containsValidFeature(): boolean { + if (!this._viewState.featureFilters || !this._viewState.featureFilters.size || !tocData.children) { + return false; + } + + const features = tocData.children.find(child => child.id === 'features'); + + if (features && features.children) { + return Array.from(this._viewState.featureFilters).some(filter => { + return features.children?.find(feature => 'features/' + filter === feature.id); + }); + } else { + return false; + } + } + private getFlatSettings(): ISetting[] { const flatSettings: ISetting[] = []; arrays.coalesce(this.getUniqueResults()) diff --git a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts index 351b49194de..342ce7934eb 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts @@ -25,7 +25,7 @@ import { isWeb } from 'vs/base/common/platform'; import { once } from 'vs/base/common/functional'; import { truncate } from 'vs/base/common/strings'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { getRemoteName, getVirtualWorkspaceLocation, getVirtualWorkspaceScheme } from 'vs/platform/remote/common/remoteHosts'; +import { getVirtualWorkspaceLocation } from 'vs/platform/remote/common/remoteHosts'; import { getCodiconAriaLabel } from 'vs/base/common/codicons'; import { ILogService } from 'vs/platform/log/common/log'; import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions'; @@ -53,9 +53,6 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr private remoteMenuActionsGroups: ActionGroup[] | undefined; private readonly remoteAuthority = this.environmentService.remoteAuthority; - - private virtualWorkspaceScheme: string | undefined = undefined; - private connectionState: 'initializing' | 'connected' | 'reconnecting' | 'disconnected' | undefined = undefined; private readonly connectionStateContextKey = new RawContextKey<'' | 'initializing' | 'disconnected' | 'connected'>('remoteConnectionState', '').bindTo(this.contextKeyService); @@ -83,8 +80,6 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr if (this.remoteAuthority) { this.connectionState = 'initializing'; this.connectionStateContextKey.set(this.connectionState); - } else { - this.updateVirtualWorkspaceScheme(); } this.registerActions(); @@ -112,7 +107,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr }); // Close Remote Connection - if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID) { + if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID && this.remoteAuthority) { registerAction2(class extends Action2 { constructor() { super({ @@ -122,18 +117,17 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr f1: true }); } - run = () => that.hostService.openWindow({ forceReuseWindow: true, remoteAuthority: null }); + run = () => that.remoteAuthority && that.hostService.openWindow({ forceReuseWindow: true, remoteAuthority: null }); + }); + + MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { + group: '6_close', + command: { + id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, + title: nls.localize({ key: 'miCloseRemote', comment: ['&& denotes a mnemonic'] }, "Close Re&&mote Connection") + }, + order: 3.5 }); - if (this.remoteAuthority) { - MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { - group: '6_close', - command: { - id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, - title: nls.localize({ key: 'miCloseRemote', comment: ['&& denotes a mnemonic'] }, "Close Re&&mote Connection") - }, - order: 3.5 - }); - } } if (this.extensionGalleryService.isEnabled()) { @@ -202,17 +196,10 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr })); } } else { - this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => { - this.updateVirtualWorkspaceScheme(); - this.updateRemoteStatusIndicator(); - })); + this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this.updateRemoteStatusIndicator())); } } - private updateVirtualWorkspaceScheme() { - this.virtualWorkspaceScheme = getVirtualWorkspaceScheme(this.workspaceContextService.getWorkspace()); - } - private async updateWhenInstalledExtensionsRegistered(): Promise { await this.extensionService.whenInstalledExtensionsRegistered(); @@ -293,13 +280,13 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr this.renderRemoteStatusIndicator(`$(remote) ${truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('host.tooltip', "Editing on {0}", hostLabel)); } return; - } else if (this.virtualWorkspaceScheme) { - // Workspace with label: indicate editing source - const workspaceLabel = this.getWorkspaceLabel(); - if (workspaceLabel) { - this.renderRemoteStatusIndicator(`$(remote) ${truncate(workspaceLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('workspace.tooltip', "Editing on {0}", workspaceLabel)); - return; - } + } + + // Workspace with label: indicate editing source + const workspaceLabel = this.getWorkspaceLabel(); + if (workspaceLabel) { + this.renderRemoteStatusIndicator(`$(remote) ${truncate(workspaceLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('workspace.tooltip', "Editing on {0}", workspaceLabel)); + return; } // Remote actions: offer menu @@ -355,37 +342,11 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr return undefined; }; - const matchCurrentRemote = () => { - if (this.remoteAuthority) { - return new RegExp(`^remote_\\d\\d_${getRemoteName(this.remoteAuthority)}_`); - } else if (this.virtualWorkspaceScheme) { - if (this.virtualWorkspaceScheme === 'vscode-vfs') { - return new RegExp(`^remote_\\d\\d_vfs_`); - } else { - return new RegExp(`^virtualfs_\\d\\d_${this.virtualWorkspaceScheme}_`); - } - } - return undefined; - }; - const computeItems = () => { - let actionGroups = this.getRemoteMenuActions(true); + const actionGroups = this.getRemoteMenuActions(true); const items: (IQuickPickItem | IQuickPickSeparator)[] = []; - const currentRemoteMatcher = matchCurrentRemote(); - if (currentRemoteMatcher) { - // commands for the current remote go first - actionGroups = actionGroups.sort((g1, g2) => { - const isCurrentRemote1 = currentRemoteMatcher.test(g1[0]); - const isCurrentRemote2 = currentRemoteMatcher.test(g2[0]); - if (isCurrentRemote1 !== isCurrentRemote2) { - return isCurrentRemote1 ? -1 : 1; - } - return g1[0].localeCompare(g2[0]); - }); - } - let lastCategoryName: string | undefined = undefined; for (let actionGroup of actionGroups) { @@ -410,38 +371,25 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr } } - if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID) { - if (this.remoteAuthority) { - if (items.length) { - items.push({ type: 'separator' }); - } + if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID && this.remoteAuthority) { + if (items.length) { + items.push({ type: 'separator' }); + } + items.push({ + type: 'item', + id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, + label: nls.localize('closeRemote.title', 'Close Remote Connection') + }); + + if (this.connectionState === 'disconnected') { items.push({ type: 'item', - id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, - label: nls.localize('closeRemoteConnection.title', 'Close Remote Connection') - }); - - if (this.connectionState === 'disconnected') { - items.push({ - type: 'item', - id: ReloadWindowAction.ID, - label: nls.localize('reloadWindow', 'Reload Window') - }); - } - } else if (this.virtualWorkspaceScheme) { - if (items.length) { - items.push({ type: 'separator' }); - } - - items.push({ - type: 'item', - id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, - label: nls.localize('closeRemoteWindow.title', 'Close Remote') + id: ReloadWindowAction.ID, + label: nls.localize('reloadWindow', 'Reload Window') }); } } - if (!this.remoteAuthority && this.extensionGalleryService.isEnabled()) { items.push({ type: 'separator' diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index d0fb01b93d7..00c2d9bbc06 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -17,7 +17,6 @@ import type { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl'; import { ITerminalStatusList } from 'vs/workbench/contrib/terminal/browser/terminalStatusList'; import { ICompleteTerminalConfiguration } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; -import { IEditableData } from 'vs/workbench/common/views'; export const ITerminalService = createDecorator('terminalService'); export const ITerminalInstanceService = createDecorator('terminalInstanceService'); @@ -207,8 +206,6 @@ export interface ITerminalService { requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise; isAttachedToTerminal(remoteTerm: IRemoteTerminalAttachTarget): boolean; - getEditableData(stat: ITerminalInstance): IEditableData | undefined; - setEditable(stat: ITerminalInstance, data: IEditableData | null): Promise; } export interface IRemoteTerminalService extends IOffProcessTerminalService { @@ -603,13 +600,12 @@ export interface ITerminalInstance { registerLinkProvider(provider: ITerminalExternalLinkProvider): IDisposable; /** - * Sets the terminal name to the provided title or triggers a quick pick - * to take user input. + * Triggers a quick pick to rename this terminal. */ - rename(title?: string): Promise; + rename(): Promise; /** - * Triggers a quick pick to change the icon of this terminal. + * Triggers a quick pick to rename this terminal. */ changeIcon(): Promise; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index dac068f76df..af542818ef9 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -23,7 +23,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ILabelService } from 'vs/platform/label/common/label'; import { IListService } from 'vs/platform/list/browser/listService'; -import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; +import { INotificationService } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IPickOptions, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ILocalTerminalService, ITerminalProfile, TerminalSettingId, TitleEventSource } from 'vs/platform/terminal/common/terminal'; @@ -811,30 +811,9 @@ export function registerTerminalActions() { }); } async run(accessor: ServicesAccessor) { - const terminalService = accessor.get(ITerminalService); - const notificationService = accessor.get(INotificationService); - - const instance = getSelectedInstances(accessor)?.[0]; - if (!instance) { - return; - } - - await terminalService.setEditable(instance, { - validationMessage: value => validateTerminalName(value), - onFinish: async (value, success) => { - if (success) { - try { - await instance.rename(value); - } catch (e) { - notificationService.error(e); - } - } - await terminalService.setEditable(instance, null); - } - }); + return getSelectedInstances(accessor)?.[0].rename(); } }); - registerAction2(class extends Action2 { constructor() { super({ @@ -1851,14 +1830,3 @@ function focusNext(accessor: ServicesAccessor): void { const listService = accessor.get(IListService); listService.lastFocusedList?.focusNext(); } - -export function validateTerminalName(name: string): { content: string, severity: Severity } | null { - if (!name || name.trim().length === 0) { - return { - content: localize('emptyTerminalNameError', "A name must be provided."), - severity: Severity.Error - }; - } - - return null; -} diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index dbcd7c31b7e..b9f8ed26f93 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -775,7 +775,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _initDragAndDrop(container: HTMLElement) { this._dndObserver?.dispose(); - const dndController = new TerminalInstanceDragAndDropController(container); + const dndController = new TerminalInstanceDropAndDropController(container); dndController.onDropTerminal(e => this._onRequestAddInstanceToGroup.fire(e)); dndController.onDropFile(async path => { const preparedPath = await this._terminalInstanceService.preparePathForTerminalAsync(path, this.shellLaunchConfig.executable, this.title, this.shellType, this.isRemote); @@ -1789,15 +1789,13 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return this._linkManager.registerExternalLinkProvider(this, provider); } - async rename(title?: string) { - if (!title) { - title = await this._quickInputService.input({ - value: this.title, - prompt: nls.localize('workbench.action.terminal.rename.prompt', "Enter terminal name"), - }); - } - if (title) { - this.setTitle(title, TitleEventSource.Api); + async rename() { + const name = await this._quickInputService.input({ + value: this.title, + prompt: nls.localize('workbench.action.terminal.rename.prompt', "Enter terminal name"), + }); + if (name) { + this.setTitle(name, TitleEventSource.Api); } } @@ -1845,7 +1843,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } items.push({ type: 'separator' }); - const showAllColorsItem = { label: 'Reset to default' }; + const showAllColorsItem = { label: 'Show all colors' }; items.push(showAllColorsItem); styleElement.textContent = css; document.body.appendChild(styleElement); @@ -1872,7 +1870,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } -class TerminalInstanceDragAndDropController extends Disposable implements IDragAndDropObserverCallbacks { +class TerminalInstanceDropAndDropController extends Disposable implements IDragAndDropObserverCallbacks { private _dropOverlay?: HTMLElement; private readonly _onDropFile = new Emitter(); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index ce934e8dc6b..c724ea70dcb 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -19,7 +19,7 @@ import { IKeyMods, IPickOptions, IQuickInputButton, IQuickInputService, IQuickPi import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ILocalTerminalService, IOffProcessTerminalService, IShellLaunchConfig, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { IEditableData, IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; +import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; import { IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalGroup, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; @@ -69,8 +69,6 @@ export class TerminalService implements ITerminalService { private _localTerminalsInitPromise: Promise | undefined; private _connectionState: TerminalConnectionState; - private _editable: { instance: ITerminalInstance, data: IEditableData } | undefined; - public get activeGroupIndex(): number { return this._activeGroupIndex; } public get terminalGroups(): ITerminalGroup[] { return this._terminalGroups; } public get isProcessSupportRegistered(): boolean { return !!this._processSupportContextKey.get(); } @@ -318,25 +316,6 @@ export class TerminalService implements ITerminalService { return activeInstance ? activeInstance : this.createTerminal(undefined); } - async setEditable(instance: ITerminalInstance, data?: IEditableData | null): Promise { - if (!data) { - this._editable = undefined; - } else { - this._editable = { instance: instance, data }; - } - const pane = this._viewsService.getActiveViewWithId(TERMINAL_VIEW_ID); - const isEditing = this._isEditable(instance); - pane?.terminalTabbedView?.setEditable(isEditing); - } - - private _isEditable(instance: ITerminalInstance | undefined): boolean { - return !!this._editable && (this._editable.instance === instance || !instance); - } - - getEditableData(instance: ITerminalInstance): IEditableData | undefined { - return this._editable && this._editable.instance === instance ? this._editable.data : undefined; - } - requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise { // The initial request came from the extension host, no need to wait for it return new Promise(callback => { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts index 69a0e7f6d62..04fb6e4721a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts @@ -288,7 +288,7 @@ export class TerminalTabbedView extends Disposable { const hasText = this._tabListElement.clientWidth > TerminalTabsListSizes.MidpointViewWidth; this._tabContainer.classList.toggle('has-text', hasText); this._terminalIsTabsNarrowContextKey.set(!hasText); - this._tabList.refresh(); + this._tabList.render(); } private _addSashListener() { @@ -469,13 +469,6 @@ export class TerminalTabbedView extends Disposable { ]; } - setEditable(isEditing: boolean): void { - if (!isEditing) { - this._tabList.domFocus(); - } - return this._tabList.refresh(); - } - focusTabs(): void { if (!this._shouldShowTabs()) { return; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts index 6b9f9e5e683..396ae88f448 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts @@ -26,7 +26,7 @@ import { DEFAULT_LABELS_CONTAINER, IResourceLabel, ResourceLabels } from 'vs/wor import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations'; import { IHoverAction, IHoverService } from 'vs/workbench/services/hover/browser/hover'; import Severity from 'vs/base/common/severity'; -import { Disposable, DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; import { IListDragAndDrop, IListDragOverReaction, IListRenderer, ListDragOverEffect } from 'vs/base/browser/ui/list/list'; import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd'; import { disposableTimeout } from 'vs/base/common/async'; @@ -34,13 +34,6 @@ import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; import { URI } from 'vs/base/common/uri'; import { getColorClass, getIconId, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; import { Schemas } from 'vs/base/common/network'; -import { IEditableData } from 'vs/workbench/common/views'; -import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; -import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; -import { once } from 'vs/base/common/functional'; -import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; -import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { KeyCode } from 'vs/base/common/keyCodes'; const $ = DOM.$; @@ -96,13 +89,13 @@ export class TerminalTabList extends WorkbenchList { configurationService, keybindingService, ); - this._terminalService.onInstancesChanged(() => this.refresh()); - this._terminalService.onGroupsChanged(() => this.refresh()); - this._terminalService.onInstanceTitleChanged(() => this.refresh()); - this._terminalService.onInstanceIconChanged(() => this.refresh()); - this._terminalService.onInstancePrimaryStatusChanged(() => this.refresh()); - this._terminalService.onDidChangeConnectionState(() => this.refresh()); - this._themeService.onDidColorThemeChange(() => this.refresh()); + this._terminalService.onInstancesChanged(() => this.render()); + this._terminalService.onGroupsChanged(() => this.render()); + this._terminalService.onInstanceTitleChanged(() => this.render()); + this._terminalService.onInstanceIconChanged(() => this.render()); + this._terminalService.onInstancePrimaryStatusChanged(() => this.render()); + this._terminalService.onDidChangeConnectionState(() => this.render()); + this._themeService.onDidColorThemeChange(() => this.render()); this._terminalService.onActiveInstanceChanged(e => { if (e) { const i = this._terminalService.terminalInstances.indexOf(e); @@ -164,10 +157,10 @@ export class TerminalTabList extends WorkbenchList { this._decorationsProvider = instantiationService.createInstance(TerminalDecorationsProvider); _decorationsService.registerDecorationsProvider(this._decorationsProvider); } - this.refresh(); + this.render(); } - refresh(): void { + render(): void { this.splice(0, this.length, this._terminalService.terminalInstances); } @@ -189,8 +182,7 @@ class TerminalTabsRenderer implements IListRenderer 1) { const terminalIndex = group.terminalInstances.indexOf(instance); @@ -341,84 +323,6 @@ class TerminalTabsRenderer implements IListRenderer { - const message = editableData.validationMessage(value); - if (!message || message.severity !== Severity.Error) { - return null; - } - - return { - content: message.content, - formatContent: true, - type: MessageType.ERROR - }; - } - }, - ariaLabel: localize('terminalInputAriaLabel', "Type terminal name. Press Enter to confirm or Escape to cancel.") - }); - const styler = attachInputBoxStyler(inputBox, this._themeService); - - inputBox.value = value; - inputBox.focus(); - inputBox.select({ start: 0, end: value.length }); - - const done = once((success: boolean, finishEditing: boolean) => { - inputBox.element.style.display = 'none'; - const value = inputBox.value; - dispose(toDispose); - inputBox.element.remove(); - if (finishEditing) { - editableData.onFinish(value, success); - } - }); - - const showInputBoxNotification = () => { - if (inputBox.isInputValid()) { - const message = editableData.validationMessage(inputBox.value); - if (message) { - inputBox.showMessage({ - content: message.content, - formatContent: true, - type: message.severity === Severity.Info ? MessageType.INFO : message.severity === Severity.Warning ? MessageType.WARNING : MessageType.ERROR - }); - } else { - inputBox.hideMessage(); - } - } - }; - showInputBoxNotification(); - - const toDispose = [ - inputBox, - DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: IKeyboardEvent) => { - if (e.equals(KeyCode.Enter)) { - done(inputBox.isInputValid(), true); - } else if (e.equals(KeyCode.Escape)) { - done(false, true); - } - }), - DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_UP, (e: IKeyboardEvent) => { - showInputBoxNotification(); - }), - DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => { - done(inputBox.isInputValid(), true); - }), - label, - styler - ]; - - return toDisposable(() => { - done(false, false); - }); - } - disposeElement(instance: ITerminalInstance, index: number, templateData: ITerminalTabEntryTemplate): void { templateData.elementDispoables?.dispose(); templateData.elementDispoables = undefined; diff --git a/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts b/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts index b16844d7758..5e521205775 100644 --- a/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts +++ b/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts @@ -115,36 +115,36 @@ suite('Workbench - TerminalProfiles', () => { } as ITestTerminalConfig) as ITerminalConfiguration; test('should prefer pwsh 7 to Windows PowerShell', async () => { - const expectedPaths = [ + const fsProvider = createFsProvider([ 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', 'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe', 'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - ]; - const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), undefined, undefined, undefined, expectedPaths); + ]); + const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined); const expected = [ { profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', isDefault: true } ]; profilesEqual(profiles, expected); }); test('should prefer pwsh 7 to pwsh 6', async () => { - const expectedPaths = [ + const fsProvider = createFsProvider([ 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', 'C:\\Program Files\\PowerShell\\6\\pwsh.exe', 'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe', 'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - ]; - const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), undefined, undefined, undefined, expectedPaths); + ]); + const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined); const expected = [ { profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', isDefault: true } ]; profilesEqual(profiles, expected); }); - test('should fallback to Windows PowerShell', async () => { - const expectedPaths = [ + test.skip('should fallback to Windows PowerShell', async () => { + const fsProvider = createFsProvider([ 'C:\\Windows\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe', 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - ]; - const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), undefined, undefined, undefined, expectedPaths); + ]); + const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined); strictEqual(profiles.length, 1); strictEqual(profiles[0].profileName, 'PowerShell'); }); @@ -228,7 +228,7 @@ suite('Workbench - TerminalProfiles', () => { }, async readFile(path: string): Promise { if (path !== '/etc/shells') { - fail('Unexepected path'); + fail('Unexected path'); } return Buffer.from(etcShellsContent); } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index 0600e81458a..d252616bc61 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -84,7 +84,7 @@ } .monaco-workbench .part.editor > .content .gettingStartedContainer .gettingStartedSlideCategories { - padding: 24px; + padding: 12px; } .monaco-workbench .part.editor > .content .gettingStartedContainer.animationReady .gettingStartedSlide { @@ -557,11 +557,14 @@ } .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .codicon-arrow-small-right { - padding-left: 8px; + position: relative; + top: 3px; + left: 2px; } .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .codicon-check-all { - padding-right: 8px; + position: relative; + top: 3px; } .monaco-workbench .part.editor > .content .gettingStartedContainer .gettingStartedSlide .skip { @@ -603,11 +606,6 @@ display: none; } -.monaco-workbench .part.editor > .content .gettingStartedContainer .done-next-container { - display: flex; - padding: 8px 16px 16px; -} - .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link { padding: 0; background: transparent; @@ -618,13 +616,9 @@ max-width: 100%; } -.monaco-workbench .part.editor > .content .gettingStartedContainer .done-next-container .button-link { - display: flex; - align-items: center; -} - .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link.next { - margin-left: auto; + position: absolute; + right: 0; } .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link:hover { @@ -651,7 +645,7 @@ } .monaco-workbench .part.editor > .content .gettingStartedContainer .getting-started-category .codicon { - top: 3px; + top: 0; } .monaco-workbench .part.editor > .content .getting-started-category .codicon::before{ diff --git a/src/vs/workbench/services/workspaces/common/workspaceTrust.ts b/src/vs/workbench/services/workspaces/common/workspaceTrust.ts index 8652288abae..00ece8fe9b5 100644 --- a/src/vs/workbench/services/workspaces/common/workspaceTrust.ts +++ b/src/vs/workbench/services/workspaces/common/workspaceTrust.ts @@ -202,11 +202,6 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork } getUriTrustInfo(uri: URI): IWorkspaceTrustUriInfo { - // Return trusted when workspace trust is disabled - if (!isWorkspaceTrustEnabled(this.configurationService)) { - return { trusted: true, uri }; - } - let resultState = false; let maxLength = -1; diff --git a/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts b/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts index 324cdd3c071..0cc72cdd1bc 100644 --- a/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts @@ -5,8 +5,7 @@ import * as assert from 'assert'; -import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; -import { MarkdownString, NotebookCellOutputItem } from 'vs/workbench/api/common/extHostTypeConverters'; +import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters'; import { isEmptyObject } from 'vs/base/common/types'; import { forEach } from 'vs/base/common/collections'; import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log'; @@ -82,23 +81,4 @@ suite('ExtHostTypeConverter', function () { } }); }); - - test('NotebookCellOutputItem', function () { - - const item = extHostTypes.NotebookCellOutputItem.text('Hello', 'foo/bar'); - - const dto = NotebookCellOutputItem.from(item); - - assert.strictEqual(dto.mime, 'foo/bar'); - assert.strictEqual(dto.metadata, undefined); - assert.strictEqual(dto.value, undefined); - assert.deepStrictEqual(dto.valueBytes, Array.from(new TextEncoder().encode('Hello'))); - - const item2 = NotebookCellOutputItem.to(dto); - - assert.strictEqual(item2.mime, item.mime); - assert.strictEqual(item2.metadata, item.metadata); - assert.strictEqual(item2.value, item.value); - assert.deepStrictEqual(item2.data, item.data); - }); }); diff --git a/src/vs/workbench/test/browser/api/extHostTypes.test.ts b/src/vs/workbench/test/browser/api/extHostTypes.test.ts index ac2117b6745..353096359eb 100644 --- a/src/vs/workbench/test/browser/api/extHostTypes.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTypes.test.ts @@ -696,28 +696,28 @@ suite('ExtHostTypes', function () { item = types.NotebookCellOutputItem.json(1); assert.strictEqual(item.mime, 'application/json'); - assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(1))); + assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify(1))); item = types.NotebookCellOutputItem.json(1, 'foo'); assert.strictEqual(item.mime, 'foo'); - assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(1))); + assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify(1))); item = types.NotebookCellOutputItem.json(true); assert.strictEqual(item.mime, 'application/json'); - assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(true))); + assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify(true))); item = types.NotebookCellOutputItem.json([true, 1, 'ddd']); assert.strictEqual(item.mime, 'application/json'); - assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify([true, 1, 'ddd'], undefined, '\t'))); + assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify([true, 1, 'ddd'], undefined, '\t'))); // --- text item = types.NotebookCellOutputItem.text('Hęłlö'); assert.strictEqual(item.mime, 'text/plain'); - assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö')); + assert.deepStrictEqual(item.value, new TextEncoder().encode('Hęłlö')); item = types.NotebookCellOutputItem.text('Hęłlö', 'foo/bar'); assert.strictEqual(item.mime, 'foo/bar'); - assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö')); + assert.deepStrictEqual(item.value, new TextEncoder().encode('Hęłlö')); }); }); From 8822790908be166248e2da67af8ce5442938c103 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Tue, 25 May 2021 17:22:09 -0700 Subject: [PATCH 096/140] Merge pull request #124622 from microsoft/gettingstarted/navigateToStep Support navigation to category/section in getting started --- .../browser/gettingStarted.contribution.ts | 15 +++++++-------- .../gettingStarted/browser/gettingStarted.ts | 7 ++++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts index 70452c9d49d..78954625351 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.contribution.ts @@ -24,7 +24,6 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio import product from 'vs/platform/product/common/product'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { EditorOverride } from 'vs/platform/editor/common/editor'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -45,18 +44,19 @@ registerAction2(class extends Action2 { }); } - public run(accessor: ServicesAccessor, walkthroughID: string | undefined, toSide: boolean | undefined) { + public run(accessor: ServicesAccessor, walkthroughID: string | { category: string, step: string } | undefined, toSide: boolean | undefined) { const editorGroupsService = accessor.get(IEditorGroupsService); const instantiationService = accessor.get(IInstantiationService); const editorService = accessor.get(IEditorService); - const configurationService = accessor.get(IConfigurationService); if (walkthroughID) { + const selectedCategory = typeof walkthroughID === 'string' ? walkthroughID : walkthroughID.category; + const selectedStep = typeof walkthroughID === 'string' ? undefined : walkthroughID.step; // Try first to select the walkthrough on an active getting started page with no selected walkthrough for (const group of editorGroupsService.groups) { if (group.activeEditor instanceof GettingStartedInput) { if (!group.activeEditor.selectedCategory) { - (group.activeEditorPane as GettingStartedPage).makeCategoryVisibleWhenAvailable(walkthroughID); + (group.activeEditorPane as GettingStartedPage).makeCategoryVisibleWhenAvailable(selectedCategory, selectedStep); return; } } @@ -67,7 +67,8 @@ registerAction2(class extends Action2 { for (const { editor, groupId } of result) { if (editor instanceof GettingStartedInput) { if (!editor.selectedCategory) { - editor.selectedCategory = walkthroughID; + editor.selectedCategory = selectedCategory; + editor.selectedStep = selectedStep; editorService.openEditor(editor, { revealIfOpened: true, override: EditorOverride.DISABLED }, groupId); return; } @@ -75,9 +76,7 @@ registerAction2(class extends Action2 { } // Otherwise, just make a new one. - if (configurationService.getValue('workbench.welcomePage.experimental.extensionContributions')) { - editorService.openEditor(instantiationService.createInstance(GettingStartedInput, { selectedCategory: walkthroughID }), {}, toSide ? SIDE_GROUP : undefined); - } + editorService.openEditor(instantiationService.createInstance(GettingStartedInput, { selectedCategory: selectedCategory, selectedStep: selectedStep }), {}, toSide ? SIDE_GROUP : undefined); } else { editorService.openEditor(new GettingStartedInput({}), {}); } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts index 69a09d7258a..24a29b4dd3e 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.ts @@ -233,7 +233,7 @@ export class GettingStartedPage extends EditorPane { setTimeout(() => this.container.classList.add('animationReady'), 0); } - async makeCategoryVisibleWhenAvailable(categoryID: string) { + async makeCategoryVisibleWhenAvailable(categoryID: string, stepId?: string) { await this.gettingStartedService.installedExtensionsRegistered; this.gettingStartedCategories = this.gettingStartedService.getCategories(); @@ -244,7 +244,7 @@ export class GettingStartedPage extends EditorPane { if (ourCategory.content.type !== 'steps') { throw Error('internaal error: category is not steps'); } - this.scrollToCategory(categoryID); + this.scrollToCategory(categoryID, stepId); } private registerDispatchListeners() { @@ -870,10 +870,11 @@ export class GettingStartedPage extends EditorPane { }); } - private async scrollToCategory(categoryID: string) { + private async scrollToCategory(categoryID: string, stepId?: string) { this.inProgressScroll = this.inProgressScroll.then(async () => { reset(this.stepsContent); this.editorInput.selectedCategory = categoryID; + this.editorInput.selectedStep = stepId; this.currentCategory = this.gettingStartedCategories.find(category => category.id === categoryID); this.buildCategorySlide(categoryID); this.setSlide('details'); From 473cfe28bfa9577be05ae4ec05761d4e4045cd0a Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 25 May 2021 17:49:34 -0700 Subject: [PATCH 097/140] Revert "Revert "Merge branch 'main' of https://github.com/microsoft/vscode into main"" This reverts commit 7c01395da16c1e9af9c2a17bac4935e3177d1c33. --- extensions/emmet/package.json | 6 +- extensions/emmet/yarn.lock | 12 +- .../markdown-language-features/package.json | 2 +- .../notebook-markdown-extensions/package.json | 2 +- .../src/singlefolder-tests/notebook.test.ts | 35 ++--- extensions/vscode-notebook-tests/package.json | 2 +- .../vscode-notebook-tests/src/extension.ts | 2 +- extensions/vscode-test-resolver/package.json | 5 +- .../electron-browser/workbench/workbench.html | 2 +- .../electron-sandbox/workbench/workbench.html | 2 +- .../common/terminalPlatformConfiguration.ts | 3 +- .../terminal/node/terminalProfiles.ts | 30 +++-- src/vs/vscode.proposed.d.ts | 46 ++++--- .../api/common/extHostTerminalService.ts | 2 +- .../api/common/extHostTypeConverters.ts | 15 +-- src/vs/workbench/api/common/extHostTypes.ts | 34 +++-- .../notebook/browser/extensionPoint.ts | 2 +- .../notebook/browser/media/notebook.css | 2 +- .../notebook/browser/notebook.contribution.ts | 8 +- .../notebook/browser/notebookBrowser.ts | 3 + .../notebook/browser/notebookEditorWidget.ts | 29 ++--- .../notebook/browser/notebookServiceImpl.ts | 4 +- .../browser/view/renderers/cellRenderer.ts | 11 +- .../browser/view/renderers/markdownCell.ts | 1 + .../browser/view/renderers/webviewPreloads.ts | 14 +- .../browser/viewModel/baseCellViewModel.ts | 18 ++- .../browser/viewModel/codeCellViewModel.ts | 12 +- .../viewModel/markdownCellViewModel.ts | 46 +++++-- .../common/model/notebookCellTextModel.ts | 3 +- .../contrib/notebook/common/notebookCommon.ts | 2 + .../notebook/common/notebookOptions.ts | 33 +++-- .../preferences/browser/settingsEditor2.ts | 20 ++- .../preferences/browser/settingsTreeModels.ts | 18 +-- .../contrib/remote/browser/remoteIndicator.ts | 120 +++++++++++++----- .../contrib/terminal/browser/terminal.ts | 10 +- .../terminal/browser/terminalActions.ts | 36 +++++- .../terminal/browser/terminalInstance.ts | 22 ++-- .../terminal/browser/terminalService.ts | 23 +++- .../terminal/browser/terminalTabbedView.ts | 9 +- .../terminal/browser/terminalTabsList.ts | 118 +++++++++++++++-- .../test/node/terminalProfiles.test.ts | 22 ++-- .../gettingStarted/browser/gettingStarted.css | 24 ++-- .../workspaces/common/workspaceTrust.ts | 5 + .../browser/api/extHostTypeConverter.test.ts | 22 +++- .../test/browser/api/extHostTypes.test.ts | 12 +- 45 files changed, 585 insertions(+), 264 deletions(-) diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index 0af69221a29..77b08c02ac9 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -226,7 +226,11 @@ }, "output.selfClosingStyle": { "type": "string", - "enum": ["html", "xhtml", "xml"], + "enum": [ + "html", + "xhtml", + "xml" + ], "default": "html", "markdownDescription": "%emmetPreferencesOutputSelfClosingStyle%" }, diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index b9d9785a550..2d35a2c78ab 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -54,9 +54,9 @@ integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI= "@types/node@14.x": - version "14.14.43" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" - integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== + version "14.17.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.1.tgz#5e07e0cb2ff793aa7a1b41deae76221e6166049f" + integrity sha512-/tpUyFD7meeooTRwl3sYlihx2BrJE7q9XF71EguPFIySj9B7qgnRtHsHTho+0AUm4m1SvWGm6uSncrR94q6Vtw== emmet@^2.3.0: version "2.3.4" @@ -77,9 +77,9 @@ jsonc-parser@^2.3.0: integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg== vscode-emmet-helper@^2.3.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.6.2.tgz#777b471a7851ba0ca8e4151533be7f92511f39b0" - integrity sha512-SkL1WjZZsA+bfTo52QH4PgqXCQAJSqzOmJtAY3rOl17MKbY6iJhVv2T26PshjmUnHoXnXMNa7PcLMCS75RsQDQ== + version "2.6.4" + resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.6.4.tgz#bea47f17649bba26b412f3d1fac18aaee43eba25" + integrity sha512-fP0nunW1RUWEKGf4gqiYLOVNFFGXSRHjCl0pikxtwCFlty8WwimM+RBJ5o0aIiwerrYD30HqeaVyvDW027Sseg== dependencies: emmet "^2.3.0" jsonc-parser "^2.3.0" diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 728a439f0dd..a9e98206b3e 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -40,7 +40,7 @@ } }, "contributes": { - "notebookOutputRenderer": [ + "notebookRenderer": [ { "id": "markdownItRenderer", "displayName": "Markdown it renderer", diff --git a/extensions/notebook-markdown-extensions/package.json b/extensions/notebook-markdown-extensions/package.json index ef3911f2eb9..981566798f6 100644 --- a/extensions/notebook-markdown-extensions/package.json +++ b/extensions/notebook-markdown-extensions/package.json @@ -21,7 +21,7 @@ } }, "contributes": { - "notebookOutputRenderer": [ + "notebookRenderer": [ { "id": "markdownItRenderer-katex", "displayName": "Markdown it katex renderer", diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index b00302b2808..98b9ac8c12b 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -7,6 +7,7 @@ import 'mocha'; import * as assert from 'assert'; import * as vscode from 'vscode'; import { createRandomFile, asPromise, disposeAll, closeAllEditors, revertAllDirty, saveAllEditors, assertNoRpc } from '../utils'; +import { TextDecoder } from 'util'; async function createRandomNotebookFile() { return createRandomFile('', undefined, '.vsctestnb'); @@ -60,13 +61,13 @@ class Kernel { task.executionOrder = 1; if (cell.notebook.uri.path.endsWith('customRenderer.vsctestnb')) { await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/custom', ['test'], undefined) + vscode.NotebookCellOutputItem.text('test', 'text/custom', undefined) ])]); return; } await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['my output'], undefined) + vscode.NotebookCellOutputItem.text('my output', 'text/plain', undefined) ])]); task.end({ success: true }); } @@ -129,7 +130,7 @@ suite('Notebook API tests', function () { kind: vscode.NotebookCellKind.Code, outputs: [ new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', 'Hello World', { testOutputItemMetadata: true }) + vscode.NotebookCellOutputItem.text('Hello World', 'text/plain', { testOutputItemMetadata: true }) ], { testOutputMetadata: true }) ], @@ -182,7 +183,7 @@ suite('Notebook API tests', function () { const task = this.controller.createNotebookCellExecutionTask(cell); task.start(); await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['my second output'], undefined) + vscode.NotebookCellOutputItem.text('my second output', 'text/plain', undefined) ])]); task.end({ success: true }); } @@ -476,7 +477,7 @@ suite('Notebook API tests', function () { assert.deepStrictEqual(secondCell!.outputs[0].metadata, { testOutputMetadata: true }); assert.strictEqual(secondCell!.outputs[0].outputs.length, 1); assert.strictEqual(secondCell!.outputs[0].outputs[0].mime, 'text/plain'); - assert.strictEqual(secondCell!.outputs[0].outputs[0].value, 'Hello World'); + assert.strictEqual(new TextDecoder().decode(secondCell!.outputs[0].outputs[0].data), 'Hello World'); assert.deepStrictEqual(secondCell!.outputs[0].outputs[0].metadata, { testOutputItemMetadata: true }); assert.strictEqual(secondCell!.executionSummary?.executionOrder, 5); assert.strictEqual(secondCell!.executionSummary?.success, true); @@ -747,9 +748,7 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ - 'my output' - ]); + assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'my output'); }); await withEvent(vscode.notebook.onDidChangeCellOutputs, async (event) => { @@ -759,9 +758,7 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ - 'my second output' - ]); + assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'my second output'); }); }); @@ -779,7 +776,7 @@ suite('Notebook API tests', function () { task.start(); task.token.onCancellationRequested(async () => { await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['Canceled'], undefined) + vscode.NotebookCellOutputItem.text('Canceled', 'text/plain', undefined) ])]); task.end({}); }); @@ -801,9 +798,7 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ - 'Canceled' - ]); + assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'Canceled'); }); cancelableKernel.controller.dispose(); @@ -826,7 +821,7 @@ suite('Notebook API tests', function () { async interrupt() { await this._task!.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['Interrupted'], undefined) + vscode.NotebookCellOutputItem.text('Interrupted', 'text/plain', undefined) ])]); this._task!.end({}); } @@ -845,9 +840,7 @@ suite('Notebook API tests', function () { assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked assert.strictEqual(cell.outputs[0].outputs.length, 1); assert.strictEqual(cell.outputs[0].outputs[0].mime, 'text/plain'); - assert.deepStrictEqual(cell.outputs[0].outputs[0].value, [ - 'Interrupted' - ]); + assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].outputs[0].data), 'Interrupted'); }); interruptableKernel.controller.dispose(); @@ -1188,10 +1181,10 @@ suite('Notebook API tests', function () { const task = this.controller.createNotebookCellExecutionTask(cell); task.start(); await task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/plain', ['Some output'], undefined) + vscode.NotebookCellOutputItem.text('Some output', 'text/plain', undefined) ])]); assert.strictEqual(cell.notebook.cellAt(0).outputs.length, 1); - assert.deepStrictEqual(cell.notebook.cellAt(0).outputs[0].outputs[0].value, ['Some output']); + assert.deepStrictEqual(new TextDecoder().decode(cell.notebook.cellAt(0).outputs[0].outputs[0].data), 'Some output'); task.end({}); called = true; } diff --git a/extensions/vscode-notebook-tests/package.json b/extensions/vscode-notebook-tests/package.json index c6c690151b6..6a0e2d648de 100644 --- a/extensions/vscode-notebook-tests/package.json +++ b/extensions/vscode-notebook-tests/package.json @@ -46,7 +46,7 @@ ] } ], - "notebookOutputRenderer": [ + "notebookRenderer": [ { "id": "notebookCoreTestRenderer", "displayName": "Notebook Core Test Renderer", diff --git a/extensions/vscode-notebook-tests/src/extension.ts b/extensions/vscode-notebook-tests/src/extension.ts index 7ca6edc14f6..935968c0b4e 100644 --- a/extensions/vscode-notebook-tests/src/extension.ts +++ b/extensions/vscode-notebook-tests/src/extension.ts @@ -69,7 +69,7 @@ export function activate(context: vscode.ExtensionContext): any { const task = controller.createNotebookCellExecutionTask(cell); task.start(); task.replaceOutput([new vscode.NotebookCellOutput([ - new vscode.NotebookCellOutputItem('text/html', ['test output'], undefined) + vscode.NotebookCellOutputItem.text('test output', 'text/html', undefined) ])]); task.end({ success: true }); } diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index ae6a4f0680f..9aa252ea511 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -32,7 +32,8 @@ "capabilities": { "untrustedWorkspaces": { "supported": true - } + }, + "virtualWorkspaces": true }, "contributes": { "resourceLabelFormatters": [ @@ -88,7 +89,7 @@ "statusBar/remoteIndicator": [ { "command": "vscode-testresolver.newWindow", - "when": "!remoteName", + "when": "!remoteName && !virtualWorkspace", "group": "remote_90_test_1_local@2" }, { diff --git a/src/vs/code/electron-browser/workbench/workbench.html b/src/vs/code/electron-browser/workbench/workbench.html index bd37436f1fd..38405e41e15 100644 --- a/src/vs/code/electron-browser/workbench/workbench.html +++ b/src/vs/code/electron-browser/workbench/workbench.html @@ -4,7 +4,7 @@ - + diff --git a/src/vs/code/electron-sandbox/workbench/workbench.html b/src/vs/code/electron-sandbox/workbench/workbench.html index bd37436f1fd..38405e41e15 100644 --- a/src/vs/code/electron-sandbox/workbench/workbench.html +++ b/src/vs/code/electron-sandbox/workbench/workbench.html @@ -4,7 +4,7 @@ - + diff --git a/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts b/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts index 3ab5f4e8620..95e697e62cf 100644 --- a/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts +++ b/src/vs/platform/terminal/common/terminalPlatformConfiguration.ts @@ -10,6 +10,7 @@ import { IJSONSchema, IJSONSchemaMap } from 'vs/base/common/jsonSchema'; import { Registry } from 'vs/platform/registry/common/platform'; import { Codicon, iconRegistry } from 'vs/base/common/codicons'; import { OperatingSystem } from 'vs/base/common/platform'; +import { ThemeIcon } from 'vs/platform/theme/common/themeService'; const terminalProfileBaseProperties: IJSONSchemaMap = { args: { @@ -372,7 +373,7 @@ export function registerTerminalDefaultProfileConfiguration(detectedProfiles?: { } function createProfileDescription(profile: ITerminalProfile): string { - let description = `$(${profile.icon || Codicon.terminal.id}) ${profile.profileName}\n- path: ${profile.path}`; + let description = `$(${ThemeIcon.isThemeIcon(profile.icon) ? profile.icon.id : profile.icon ? profile.icon : Codicon.terminal.id}) ${profile.profileName}\n- path: ${profile.path}`; if (profile.args) { if (typeof profile.args === 'string') { description += `\n- args: "${profile.args}"`; diff --git a/src/vs/platform/terminal/node/terminalProfiles.ts b/src/vs/platform/terminal/node/terminalProfiles.ts index 8082d39f17f..878376b9e2a 100644 --- a/src/vs/platform/terminal/node/terminalProfiles.ts +++ b/src/vs/platform/terminal/node/terminalProfiles.ts @@ -37,6 +37,7 @@ export function detectAvailableProfiles( safeConfigProvider(TerminalSettingId.UseWslProfiles) !== false, safeConfigProvider(TerminalSettingId.ProfilesWindows), safeConfigProvider(TerminalSettingId.DefaultProfileWindows), + testPaths, variableResolver ); } @@ -58,6 +59,7 @@ async function detectAvailableWindowsProfiles( useWslProfiles?: boolean, configProfiles?: { [key: string]: ITerminalProfileObject }, defaultProfileName?: string, + testPaths?: string[], variableResolver?: (text: string[]) => Promise ): Promise { // Determine the correct System32 path. We want to point to Sysnative @@ -73,7 +75,7 @@ async function detectAvailableWindowsProfiles( useWSLexe = true; } - await initializeWindowsProfiles(); + await initializeWindowsProfiles(testPaths); const detectedProfiles: Map = new Map(); @@ -175,7 +177,7 @@ async function transformToTerminalProfiles( return resultProfiles; } -async function initializeWindowsProfiles(): Promise { +async function initializeWindowsProfiles(testPaths?: string[]): Promise { if (profileSources) { return; } @@ -197,7 +199,7 @@ async function initializeWindowsProfiles(): Promise { }); profileSources.set('PowerShell', { profileName: 'PowerShell', - paths: await getPowershellPaths(), + paths: testPaths || await getPowershellPaths(), icon: ThemeIcon.asThemeIcon(Codicon.terminalPowershell) }); } @@ -245,23 +247,25 @@ async function getWslProfiles(wslPath: string, defaultProfileName: string | unde profileName, path: wslPath, args: [`-d`, `${distroName}`], - isDefault: profileName === defaultProfileName + isDefault: profileName === defaultProfileName, + icon: getWslIcon(distroName) }; - if (distroName.includes('Ubuntu')) { - profile.icon = ThemeIcon.asThemeIcon(Codicon.terminalUbuntu); - } - else if (distroName.includes('Debian')) { - profile.icon = ThemeIcon.asThemeIcon(Codicon.terminalDebian); - } else { - profile.icon = ThemeIcon.asThemeIcon(Codicon.terminalLinux); - } - // Add the profile profiles.push(profile); } return profiles; } +function getWslIcon(distroName: string): ThemeIcon { + if (distroName.includes('Ubuntu')) { + return ThemeIcon.asThemeIcon(Codicon.terminalUbuntu); + } else if (distroName.includes('Debian')) { + return ThemeIcon.asThemeIcon(Codicon.terminalDebian); + } else { + return ThemeIcon.asThemeIcon(Codicon.terminalLinux); + } +} + async function detectAvailableUnixProfiles( fsProvider: IFsProvider, logService?: ILogService, diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 94096b84ecf..10df4b473fa 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1247,11 +1247,12 @@ declare module 'vscode' { * * *Note* that an UTF-8 encoder is used to create bytes for the string. * - * @param value A string/ + * @param value A string. * @param mime Optional MIME type, defaults to `text/plain`. + * @param metadata Optional metadata. * @returns A new output item object. */ - static text(value: string, mime?: string): NotebookCellOutputItem; + static text(value: string, mime?: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` from @@ -1263,46 +1264,40 @@ declare module 'vscode' { * * @param value A JSON-stringifyable value. * @param mime Optional MIME type, defaults to `application/json` + * @param metadata Optional metadata. * @returns A new output item object. */ - static json(value: any, mime?: string): NotebookCellOutputItem; - - /** - * Factory function to create a `NotebookCellOutputItem` from bytes. - * - * @param value An array of unsigned 8-bit integers. - * @param mime Optional MIME type, defaults to `application/octet-stream`. - * @returns A new output item object. - */ - //todo@API better names: bytes, raw, buffer? - static bytes(value: Uint8Array, mime?: string): NotebookCellOutputItem; + static json(value: any, mime?: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` that uses * uses the `application/vnd.code.notebook.stdout` mime type. * * @param value A string. + * @param metadata Optional metadata. * @returns A new output item object. */ - static stdout(value: string): NotebookCellOutputItem; + static stdout(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` that uses * uses the `application/vnd.code.notebook.stderr` mime type. * * @param value A string. + * @param metadata Optional metadata. * @returns A new output item object. */ - static stderr(value: string): NotebookCellOutputItem; + static stderr(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * Factory function to create a `NotebookCellOutputItem` that uses * uses the `application/vnd.code.notebook.error` mime type. * * @param value An error object. + * @param metadata Optional metadata. * @returns A new output item object. */ - static error(value: Error): NotebookCellOutputItem; + static error(value: Error, metadata?: { [key: string]: any }): NotebookCellOutputItem; /** * The mime type which determines how the {@link NotebookCellOutputItem.value `value`}-property @@ -1314,21 +1309,26 @@ declare module 'vscode' { mime: string; /** - * The value of this output item. Must always be an array of unsigned 8-bit integers. + * The data of this output item. Must always be an array of unsigned 8-bit integers. */ - //todo@API only Unit8Array - value: Uint8Array | unknown; + data: Uint8Array; + /** + * @deprecated + */ + value: unknown; + + //todo@API metadata?: { [key: string]: any }; /** * Create a new notbook cell output item. * + * @param data The value of the output item. * @param mime The mime type of the output item. - * @param value The value of the output item. * @param metadata Optional metadata for this output item. */ - constructor(mime: string, value: Uint8Array | unknown, metadata?: { [key: string]: any }); + constructor(data: Uint8Array, mime: string, metadata?: { [key: string]: any }); } // @jrieken transient @@ -1563,6 +1563,9 @@ declare module 'vscode' { /** * The identifier of this notebook controller. + * + * _Note_ that controllers are remembered by their identifier and that extensions should use + * stable identifiers across sessions. */ readonly id: string; @@ -1654,6 +1657,7 @@ declare module 'vscode' { * @param cell The notebook cell for which to create the execution. * @returns A notebook cell execution. */ + // todo@API rename to NotebookCellExecution createNotebookCellExecutionTask(cell: NotebookCell): NotebookCellExecutionTask; // todo@API find a better name than "preloads" diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index 1deba734389..ea3e1713eff 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -350,7 +350,7 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I public getDefaultShellArgs(useAutomationShell: boolean): string[] | string { const profile = useAutomationShell ? this._defaultAutomationProfile : this._defaultProfile; - return profile?.args || ['']; + return profile?.args || []; } public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal { diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 94bfff83773..9cb42ef3d54 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays'; -import { VSBuffer } from 'vs/base/common/buffer'; import * as htmlContent from 'vs/base/common/htmlContent'; import { DisposableStore } from 'vs/base/common/lifecycle'; import * as marked from 'vs/base/common/marked/marked'; @@ -1536,9 +1535,9 @@ export namespace NotebookCellOutputItem { export function from(item: types.NotebookCellOutputItem): notebooks.IOutputItemDto { let value: unknown; let valueBytes: number[] | undefined; - if (item.value instanceof Uint8Array) { + if (item.data instanceof Uint8Array) { //todo@jrieken this HACKY and SLOW... hoist VSBuffer instead - valueBytes = Array.from(item.value); + valueBytes = Array.from(item.data); } else { value = item.value; } @@ -1551,15 +1550,13 @@ export namespace NotebookCellOutputItem { } export function to(item: notebooks.IOutputItemDto): types.NotebookCellOutputItem { - - let value: Uint8Array | unknown; - if (item.value instanceof VSBuffer) { - value = item.value.buffer; + let value: Uint8Array | any; + if (Array.isArray(item.valueBytes)) { + value = new Uint8Array(item.valueBytes); } else { value = item.value; } - - return new types.NotebookCellOutputItem(item.mime, value, item.metadata); + return new types.NotebookCellOutputItem(value, item.mime, item.metadata); } } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 1dfecfab513..fdccb8c119c 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3112,44 +3112,50 @@ export class NotebookCellOutputItem { return typeof (obj).mime === 'string'; } - static error(err: Error | { name: string, message?: string, stack?: string }): NotebookCellOutputItem { + static error(err: Error | { name: string, message?: string, stack?: string }, metadata?: { [key: string]: any }): NotebookCellOutputItem { const obj = { name: err.name, message: err.message, stack: err.stack }; - return NotebookCellOutputItem.json(obj, 'application/vnd.code.notebook.error'); + return NotebookCellOutputItem.json(obj, 'application/vnd.code.notebook.error', metadata); } - static stdout(value: string): NotebookCellOutputItem { - return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stdout'); + static stdout(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem { + return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stdout', metadata); } - static stderr(value: string): NotebookCellOutputItem { - return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stderr'); + static stderr(value: string, metadata?: { [key: string]: any }): NotebookCellOutputItem { + return NotebookCellOutputItem.text(value, 'application/vnd.code.notebook.stderr', metadata); } - static bytes(value: Uint8Array, mime: string = 'application/octet-stream'): NotebookCellOutputItem { - return new NotebookCellOutputItem(mime, value); + static bytes(value: Uint8Array, mime: string = 'application/octet-stream', metadata?: { [key: string]: any }): NotebookCellOutputItem { + return new NotebookCellOutputItem(value, mime, metadata); } static #encoder = new TextEncoder(); - static text(value: string, mime: string = 'text/plain'): NotebookCellOutputItem { + static text(value: string, mime: string = 'text/plain', metadata?: { [key: string]: any }): NotebookCellOutputItem { const bytes = NotebookCellOutputItem.#encoder.encode(String(value)); - return new NotebookCellOutputItem(mime, bytes); + return new NotebookCellOutputItem(bytes, mime, metadata); } - static json(value: any, mime: string = 'application/json'): NotebookCellOutputItem { + static json(value: any, mime: string = 'application/json', metadata?: { [key: string]: any }): NotebookCellOutputItem { const rawStr = JSON.stringify(value, undefined, '\t'); - return NotebookCellOutputItem.text(rawStr, mime); + return NotebookCellOutputItem.text(rawStr, mime, metadata); } + /** @deprecated */ + public value: Uint8Array | unknown; // JSON'able + constructor( + public data: Uint8Array, public mime: string, - public value: Uint8Array | unknown, // JSON'able - public metadata?: Record + public metadata?: { [key: string]: any } ) { + if (!(data instanceof Uint8Array)) { + this.value = data; + } if (isFalsyOrWhitespace(this.mime)) { throw new Error('INVALID mime type, must not be empty or falsy'); } diff --git a/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts b/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts index e925a6fdf98..406d5a41951 100644 --- a/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts +++ b/src/vs/workbench/contrib/notebook/browser/extensionPoint.ts @@ -192,6 +192,6 @@ export const notebooksExtensionPoint = ExtensionsRegistry.registerExtensionPoint export const notebookRendererExtensionPoint = ExtensionsRegistry.registerExtensionPoint( { - extensionPoint: 'notebookOutputRenderer', + extensionPoint: 'notebookRenderer', jsonSchema: notebookRendererContribution }); diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index 012a0b71fa7..a1769e49bcb 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -425,7 +425,7 @@ overflow: hidden; } -.monaco-workbench .notebookOverlay.cell-statusbar-hidden .cell-statusbar-container { +.monaco-workbench .notebookOverlay .cell-statusbar-hidden .cell-statusbar-container { display: none; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 18c20f8a83b..69f20ea18bc 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -30,7 +30,7 @@ import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEd import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { NotebookService } from 'vs/workbench/contrib/notebook/browser/notebookServiceImpl'; -import { CellKind, CellToolbarLocKey, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey, CompactView, FocusIndicator, InsertToolbarPosition, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, CellToolbarLocKey, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey, CompactView, FocusIndicator, InsertToolbarPosition, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled, ShowCellStatusBarAfterExecuteKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService'; @@ -582,6 +582,12 @@ configurationRegistry.registerConfiguration({ default: true, tags: ['notebookLayout'] }, + [ShowCellStatusBarAfterExecuteKey]: { + description: nls.localize('notebook.showCellStatusbarAfterExecute.description', "Whether the cell status bar should be shown after the cell has been executed."), + type: 'boolean', + default: false, + tags: ['notebookLayout'] + }, [NotebookTextDiffEditorPreview]: { description: nls.localize('notebook.diff.enablePreview.description', "Whether to use the enhanced text diff editor for notebook."), type: 'boolean', diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index d99af644b75..a2c0b6f900a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -235,6 +235,7 @@ export interface MarkdownCellLayoutInfo { readonly fontInfo: FontInfo | null; readonly editorWidth: number; readonly editorHeight: number; + readonly previewHeight: number; readonly bottomToolbarOffset: number; readonly totalHeight: number; } @@ -242,6 +243,8 @@ export interface MarkdownCellLayoutInfo { export interface MarkdownCellLayoutChangeEvent { font?: FontInfo; outerWidth?: number; + editorHeight?: number; + previewHeight?: number; totalHeight?: number; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index b9b697c5514..0218baf679a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -511,9 +511,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const cellToolbarLocation = this._notebookOptions.computeCellToolbarLocation(this.viewModel?.viewType); this._overlayContainer.classList.add(`cell-title-toolbar-${cellToolbarLocation}`); - const showCellStatusBar = this._notebookOptions.getLayoutConfiguration().showCellStatusBar; - this._overlayContainer.classList.toggle('cell-statusbar-hidden', !showCellStatusBar); - const cellToolbarInteraction = this._notebookOptions.getLayoutConfiguration().cellToolbarInteraction; let cellToolbarInteractionState = 'hover'; this._overlayContainer.classList.remove('cell-toolbar-hover'); @@ -555,6 +552,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor cellRunGutter, cellBottomMargin, codeCellLeftMargin, + markdownCellGutter, markdownCellLeftMargin, markdownCellBottomMargin, markdownCellTopMargin, @@ -565,7 +563,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor focusIndicator, insertToolbarPosition, insertToolbarAlignment, - fontSize + fontSize, + focusIndicatorLeftMargin } = this._notebookOptions.getLayoutConfiguration(); const styleSheets: string[] = []; @@ -643,12 +642,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor height: 100%; z-index: 10; } - - .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-left:before { - border-left: 1px solid transparent; - border-right: 1px solid transparent; - border-radius: 2px; - } `); // left and right border margins @@ -659,6 +652,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor .monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-right:before { top: 0px; height: 100%; }`); + + styleSheets.push(` + .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-left:before, + .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.selected .cell-focus-indicator-left:before { + border-left: 3px solid transparent; + border-radius: 2px; + margin-left: ${focusIndicatorLeftMargin}px; + }`); } // between cell insert toolbar @@ -727,7 +728,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .execution-count-label { left: ${codeCellLeftMargin}px; width: ${cellRunGutter}px; }`); styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`); - styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { left: ${(markdownCellLeftMargin - 20) / 2}px; }`); + styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { left: ${(markdownCellGutter - 20) / 2 + markdownCellLeftMargin}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${cellTopMargin}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${bottomCellToolbarGap}px; }`); styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left, @@ -2484,10 +2485,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const cell = this.getCellById(cellId); const layoutConfiguration = this._notebookOptions.getLayoutConfiguration(); if (cell && cell instanceof MarkdownCellViewModel) { - if (height + layoutConfiguration.bottomToolbarGap !== cell.layoutInfo.totalHeight) { - this._debug('updateMarkdownCellHeight', cell.handle, height + layoutConfiguration.bottomToolbarGap, isInit); - cell.renderedMarkdownHeight = height; - } + this._debug('updateMarkdownCellHeight', cell.handle, height + layoutConfiguration.bottomToolbarGap, isInit); + cell.renderedMarkdownHeight = height; } } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 90c4f8bc43e..7e6311c80a3 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -349,13 +349,13 @@ export class NotebookService extends Disposable implements INotebookService { for (const extension of renderers) { for (const notebookContribution of extension.value) { if (!notebookContribution.entrypoint) { // avoid crashing - console.error(`Cannot register renderer for ${extension.description.identifier.value} since it did not have an entrypoint. This is now required: https://github.com/microsoft/vscode/issues/102644`); + extension.collector.error(`Notebook renderer does not specify entry point`); continue; } const id = notebookContribution.id ?? notebookContribution.viewType; if (!id) { - console.error(`Notebook renderer from ${extension.description.identifier.value} is missing an 'id'`); + extension.collector.error(`Notebook renderer does not specify id-property`); continue; } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index a1abbac5a74..c58a65e0cc9 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -521,6 +521,8 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR templateData.focusIndicatorBottom.style.top = `${indicatorPostion.bottomIndicatorTop}px`; templateData.focusIndicatorLeft.style.height = `${indicatorPostion.verticalIndicatorHeight}px`; templateData.focusIndicatorRight.style.height = `${indicatorPostion.verticalIndicatorHeight}px`; + + templateData.container.classList.toggle('cell-statusbar-hidden', element.getEditorStatusbarHeight() === 0); } private updateForHover(element: MarkdownCellViewModel, templateData: MarkdownCellRenderTemplate): void { @@ -852,7 +854,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende } } - private updateForInternalMetadata(element: CodeCellViewModel, templateData: CodeCellRenderTemplate, editorOptions: CellEditorOptions): void { + private updateForInternalMetadata(element: CodeCellViewModel, templateData: CodeCellRenderTemplate): void { if (!this.notebookEditor.hasModel()) { return; } @@ -894,6 +896,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende templateData.outputContainer.style.top = `${element.layoutInfo.outputContainerOffset}px`; templateData.outputShowMoreContainer.style.top = `${element.layoutInfo.outputShowMoreContainerOffset}px`; templateData.dragHandle.style.height = `${element.layoutInfo.totalHeight - layoutInfo.bottomToolbarGap}px`; + + templateData.container.classList.toggle('cell-statusbar-hidden', element.getEditorStatusbarHeight() === 0); } renderElement(element: CodeCellViewModel, index: number, templateData: CodeCellRenderTemplate, height: number | undefined): void { @@ -959,13 +963,14 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende this.updateForLayout(element, templateData); })); - this.updateForInternalMetadata(element, templateData, cellEditorOptions); + this.updateForInternalMetadata(element, templateData); this.updateForHover(element, templateData); this.updateForFocus(element, templateData); cellEditorOptions.setLineNumbers(element.lineNumbers); elementDisposables.add(element.onDidChangeState((e) => { if (e.internalMetadataChanged) { - this.updateForInternalMetadata(element, templateData, cellEditorOptions); + this.updateForInternalMetadata(element, templateData); + this.updateForLayout(element, templateData); } if (e.outputIsHoveredChanged) { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts index 1b0270c2b6d..79574328b08 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -250,6 +250,7 @@ export class StatefulMarkdownCell extends Disposable { private updateFoldingIconShowClass() { const showFoldingIcon = this.notebookEditor.notebookOptions.getLayoutConfiguration().showFoldingControls; + this.templateData.foldingIndicator.classList.remove('mouseover', 'always'); this.templateData.foldingIndicator.classList.add(showFoldingIcon); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index f097895be8b..8250b75e1f3 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -468,8 +468,10 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re text(): string; json(): any; - bytes(): Uint8Array + data(): Uint8Array; blob(): Blob; + /** @deprecated */ + bytes(): Uint8Array; } interface IDestroyCellInfo { @@ -492,7 +494,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re postKernelMessage: (data: unknown) => postNotebookMessage('customKernelMessage', { message: data }), }; - const ttPolicy = window.trustedTypes?.createPolicy('notebookOutputRenderer', { + const ttPolicy = window.trustedTypes?.createPolicy('notebookRenderer', { createHTML: value => value, createScript: value => value, }); @@ -643,9 +645,10 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re mime: content.mimeType, value: content.value, metadata: content.metadata, - bytes() { + data() { return content.valueBytes; }, + bytes() { return this.data(); }, text() { return new TextDecoder().decode(content.valueBytes) || String(content.value); //todo@jrieken remove this once `value` is gone! @@ -1038,8 +1041,9 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re outputId: undefined, text() { return content; }, json() { return undefined; }, - bytes() { return new Uint8Array(); }, - blob() { return new Blob(); }, + bytes() { return this.data(); }, + data() { return new TextEncoder().encode(content); }, + blob() { return new Blob([this.data()], { type: this.mime }); }, }); } }(); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts index c1ebfdb4c06..a768023c05a 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts @@ -144,10 +144,8 @@ export abstract class BaseCellViewModel extends Disposable { this._register(model.onDidChangeInternalMetadata(e => { this._onDidChangeState.fire({ internalMetadataChanged: true, runStateChanged: e.runStateChanged }); - })); - - this._register(this._viewContext.notebookOptions.onDidChangeOptions(e => { - if (e.cellStatusBarVisibility || e.insertToolbarPosition) { + if (e.runStateChanged || e.lastRunSuccessChanged) { + // Statusbar visibility may change this.layoutChange({}); } })); @@ -160,7 +158,17 @@ export abstract class BaseCellViewModel extends Disposable { } getEditorStatusbarHeight() { - return this._viewContext.notebookOptions.computeStatusBarHeight(); + return this.statusBarIsVisible() ? this._viewContext.notebookOptions.computeStatusBarHeight() : 0; + } + + private statusBarIsVisible(): boolean { + if (this._viewContext.notebookOptions.getLayoutConfiguration().showCellStatusBar) { + return true; + } else if (this._viewContext.notebookOptions.getLayoutConfiguration().showCellStatusBarAfterExecute) { + return typeof this.internalMetadata.lastRunSuccess === 'boolean' || this.internalMetadata.runState !== undefined; + } else { + return false; + } } abstract hasDynamicHeight(): boolean; diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index e40a99e886a..fbb26df5f1b 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -126,6 +126,12 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } })); + this._register(this.viewContext.notebookOptions.onDidChangeOptions(e => { + if (e.cellStatusBarVisibility || e.cellStatusBarAfterExecuteVisibility || e.insertToolbarPosition) { + this.layoutChange({}); + } + })); + this._outputCollection = new Array(this.model.outputs.length); this._layoutInfo = { @@ -152,6 +158,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod const outputShowMoreContainerHeight = state.outputShowMoreContainerHeight ? state.outputShowMoreContainerHeight : this._layoutInfo.outputShowMoreContainerHeight; let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata.outputCollapsed ? notebookLayoutConfiguration.collapsedIndicatorHeight : this._outputsTop!.getTotalValue()); + const originalLayout = this.layoutInfo; if (!this.metadata.inputCollapsed) { let newState: CodeCellLayoutState; let editorHeight: number; @@ -235,10 +242,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod }; } - if (state.editorHeight || state.outputHeight) { - state.totalHeight = true; - } - + state.totalHeight = this.layoutInfo.totalHeight !== originalLayout.totalHeight; state.source = source; this._fireOnDidChangeLayout(state); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts index c0b94acf079..033d499e163 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel.ts @@ -27,33 +27,25 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie return this._layoutInfo; } + private _previewHeight = 0; + set renderedMarkdownHeight(newHeight: number) { if (this.getEditState() === CellEditState.Preview) { - const newTotalHeight = newHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomToolbarGap; // BOTTOM_CELL_TOOLBAR_GAP; - this.totalHeight = newTotalHeight; + this._previewHeight = newHeight; + this._updateTotalHeight(this._previewHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomToolbarGap); } } - private set totalHeight(newHeight: number) { - if (newHeight !== this.layoutInfo.totalHeight) { - this.layoutChange({ totalHeight: newHeight }); - } - } - - private get totalHeight() { - throw new Error('MarkdownCellViewModel.totalHeight is write only'); - } - private _editorHeight = 0; set editorHeight(newHeight: number) { this._editorHeight = newHeight; const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration(); - this.totalHeight = this._editorHeight + this._updateTotalHeight(this._editorHeight + layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN + layoutConfiguration.markdownCellBottomMargin // MARKDOWN_CELL_BOTTOM_MARGIN + layoutConfiguration.bottomToolbarGap // BOTTOM_CELL_TOOLBAR_GAP - + this.viewContext.notebookOptions.computeStatusBarHeight(); + + this.viewContext.notebookOptions.computeStatusBarHeight()); } get editorHeight() { @@ -116,6 +108,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._layoutInfo = { editorHeight: 0, + previewHeight: 0, fontInfo: initialNotebookLayoutInfo?.fontInfo || null, editorWidth: initialNotebookLayoutInfo?.width ? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(initialNotebookLayoutInfo.width) @@ -133,6 +126,21 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._onDidHideInput.fire(); } })); + + this._register(this.viewContext.notebookOptions.onDidChangeOptions(e => { + if (e.cellStatusBarVisibility || e.cellStatusBarAfterExecuteVisibility || e.insertToolbarPosition) { + const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration(); + if (this.getEditState() === CellEditState.Editing) { + this._updateTotalHeight(this._editorHeight + + layoutConfiguration.markdownCellTopMargin + + layoutConfiguration.markdownCellBottomMargin + + layoutConfiguration.bottomToolbarGap + + this.viewContext.notebookOptions.computeStatusBarHeight()); + } else { + this._updateTotalHeight(this._previewHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomToolbarGap); + } + } + })); } /** @@ -151,6 +159,12 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._onDidChangeState.fire({ foldingStateChanged: true }); } + private _updateTotalHeight(newHeight: number) { + if (newHeight !== this.layoutInfo.totalHeight) { + this.layoutChange({ totalHeight: newHeight }); + } + } + layoutChange(state: MarkdownCellLayoutChangeEvent) { // recompute if (!this.metadata.inputCollapsed) { @@ -158,10 +172,12 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie ? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth; const totalHeight = state.totalHeight === undefined ? this._layoutInfo.totalHeight : state.totalHeight; + const previewHeight = this._previewHeight; this._layoutInfo = { fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, + previewHeight, editorHeight: this._editorHeight, bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight @@ -178,6 +194,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie fontInfo: state.font || this._layoutInfo.fontInfo, editorWidth, editorHeight: this._editorHeight, + previewHeight: this._previewHeight, bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight), totalHeight }; @@ -193,6 +210,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie this._layoutInfo = { fontInfo: this._layoutInfo.fontInfo, editorWidth: this._layoutInfo.editorWidth, + previewHeight: this._layoutInfo.previewHeight, bottomToolbarOffset: this._layoutInfo.bottomToolbarOffset, totalHeight: totalHeight, editorHeight: this._editorHeight diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts index b963316e2f2..17db539b562 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts @@ -59,13 +59,14 @@ export class NotebookCellTextModel extends Disposable implements ICell { set internalMetadata(newInternalMetadata: NotebookCellInternalMetadata) { const runStateChanged = this._internalMetadata.runState !== newInternalMetadata.runState; + const lastRunSuccessChanged = this._internalMetadata.lastRunSuccess !== newInternalMetadata.lastRunSuccess; newInternalMetadata = { ...newInternalMetadata, ...{ runStartTimeAdjustment: computeRunStartTimeAdjustment(this._internalMetadata, newInternalMetadata) } }; this._internalMetadata = newInternalMetadata; this._hash = null; - this._onDidChangeInternalMetadata.fire({ runStateChanged }); + this._onDidChangeInternalMetadata.fire({ runStateChanged, lastRunSuccessChanged }); } get language() { diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 9a6803d7544..e3441192d96 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -189,6 +189,7 @@ export interface ICellOutput { export interface CellInternalMetadataChangedEvent { readonly runStateChanged?: boolean; + readonly lastRunSuccessChanged?: boolean; } export interface ICell { @@ -903,6 +904,7 @@ export const DisplayOrderKey = 'notebook.displayOrder'; export const CellToolbarLocKey = 'notebook.cellToolbarLocation'; export const CellToolbarVisibility = 'notebook.cellToolbarVisibility'; export const ShowCellStatusBarKey = 'notebook.showCellStatusBar'; +export const ShowCellStatusBarAfterExecuteKey = 'notebook.showCellStatusBarAfterExecute'; export const NotebookTextDiffEditorPreview = 'notebook.diff.enablePreview'; export const ExperimentalUseMarkdownRenderer = 'notebook.experimental.useMarkdownRenderer'; export const ExperimentalInsertToolbarAlignment = 'notebook.experimental.insertToolbarAlignment'; diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 56234848c49..3b395ed6a37 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -6,7 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { CellToolbarLocKey, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, DragAndDropEnabled, FocusIndicator, GlobalToolbar, ExperimentalInsertToolbarAlignment, InsertToolbarPosition, ShowFoldingControls, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellToolbarLocKey, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, DragAndDropEnabled, ExperimentalInsertToolbarAlignment, FocusIndicator, GlobalToolbar, InsertToolbarPosition, ShowCellStatusBarAfterExecuteKey, ShowCellStatusBarKey, ShowFoldingControls } from 'vs/workbench/contrib/notebook/common/notebookCommon'; const SCROLLABLE_ELEMENT_PADDING_TOP = 18; @@ -32,6 +32,7 @@ export interface NotebookLayoutConfiguration { cellOutputPadding: number; codeCellLeftMargin: number; markdownCellLeftMargin: number; + markdownCellGutter: number; markdownCellTopMargin: number; markdownCellBottomMargin: number; markdownPreviewPadding: number; @@ -43,6 +44,7 @@ export interface NotebookLayoutConfiguration { editorBottomPaddingWithoutStatusBar: number; collapsedIndicatorHeight: number; showCellStatusBar: boolean; + showCellStatusBarAfterExecute: boolean; cellStatusBarHeight: number; cellToolbarLocation: string | { [key: string]: string }; cellToolbarInteraction: string; @@ -55,10 +57,12 @@ export interface NotebookLayoutConfiguration { showFoldingControls: 'always' | 'mouseover'; dragAndDropEnabled: boolean; fontSize: number; + focusIndicatorLeftMargin: number; } interface NotebookOptionsChangeEvent { cellStatusBarVisibility?: boolean; + cellStatusBarAfterExecuteVisibility?: boolean; cellToolbarLocation?: boolean; cellToolbarInteraction?: boolean; editorTopPadding?: boolean; @@ -78,15 +82,19 @@ const defaultConfigConstants = { cellRunGutter: 32, markdownCellTopMargin: 8, markdownCellBottomMargin: 8, - markdownCellLeftMargin: 32, + markdownCellLeftMargin: 0, + markdownCellGutter: 32, + focusIndicatorLeftMargin: 4 }; const compactConfigConstants = { - codeCellLeftMargin: 0, + codeCellLeftMargin: 8, cellRunGutter: 32, markdownCellTopMargin: 6, markdownCellBottomMargin: 6, - markdownCellLeftMargin: 32, + markdownCellLeftMargin: 8, + markdownCellGutter: 32, + focusIndicatorLeftMargin: 4 }; export class NotebookOptions { @@ -97,6 +105,7 @@ export class NotebookOptions { constructor(private readonly configurationService: IConfigurationService) { const showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); + const showCellStatusBarAfterExecute = this.configurationService.getValue(ShowCellStatusBarAfterExecuteKey); const globalToolbar = this.configurationService.getValue(GlobalToolbar) ?? false; const consolidatedOutputButton = this.configurationService.getValue(ConsolidatedOutputButton) ?? true; const dragAndDropEnabled = this.configurationService.getValue(DragAndDropEnabled) ?? true; @@ -127,6 +136,7 @@ export class NotebookOptions { editorBottomPaddingWithoutStatusBar: 12, collapsedIndicatorHeight: 24, showCellStatusBar, + showCellStatusBarAfterExecute, globalToolbar, consolidatedOutputButton, dragAndDropEnabled, @@ -154,6 +164,7 @@ export class NotebookOptions { private _updateConfiguration(e: IConfigurationChangeEvent) { const cellStatusBarVisibility = e.affectsConfiguration(ShowCellStatusBarKey); + const cellStatusBarAfterExecuteVisibility = e.affectsConfiguration(ShowCellStatusBarAfterExecuteKey); const cellToolbarLocation = e.affectsConfiguration(CellToolbarLocKey); const cellToolbarInteraction = e.affectsConfiguration(CellToolbarVisibility); const compactView = e.affectsConfiguration(CompactView); @@ -168,6 +179,7 @@ export class NotebookOptions { if ( !cellStatusBarVisibility + && !cellStatusBarAfterExecuteVisibility && !cellToolbarLocation && !cellToolbarInteraction && !compactView @@ -188,6 +200,10 @@ export class NotebookOptions { configuration.showCellStatusBar = this.configurationService.getValue(ShowCellStatusBarKey); } + if (cellStatusBarAfterExecuteVisibility) { + configuration.showCellStatusBarAfterExecute = this.configurationService.getValue(ShowCellStatusBarAfterExecuteKey); + } + if (cellToolbarLocation) { configuration.cellToolbarLocation = this.configurationService.getValue(CellToolbarLocKey); } @@ -244,6 +260,7 @@ export class NotebookOptions { // trigger event this._onDidChangeOptions.fire({ cellStatusBarVisibility, + cellStatusBarAfterExecuteVisibility, cellToolbarLocation, cellToolbarInteraction, compactView, @@ -329,11 +346,7 @@ export class NotebookOptions { } computeStatusBarHeight(): number { - if (this._layoutConfiguration.showCellStatusBar) { - return this._layoutConfiguration.cellStatusBarHeight; - } else { - return 0; - } + return this._layoutConfiguration.cellStatusBarHeight; } computeCellToolbarLocation(viewType?: string): 'right' | 'left' | 'hidden' { @@ -384,7 +397,7 @@ export class NotebookOptions { outputNodePadding: this._layoutConfiguration.cellOutputPadding, outputNodeLeftPadding: this._layoutConfiguration.cellOutputPadding, previewNodePadding: this._layoutConfiguration.markdownPreviewPadding, - markdownLeftMargin: this._layoutConfiguration.markdownCellLeftMargin, + markdownLeftMargin: this._layoutConfiguration.markdownCellGutter + this._layoutConfiguration.markdownCellLeftMargin, leftMargin: this._layoutConfiguration.codeCellLeftMargin, rightMargin: this._layoutConfiguration.cellRightMargin, runGutter: this._layoutConfiguration.cellRunGutter, diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 1657bc1f187..1b29e99765e 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -92,7 +92,25 @@ export class SettingsEditor2 extends EditorPane { private static CONFIG_SCHEMA_UPDATE_DELAYER = 500; private static readonly SUGGESTIONS: string[] = [ - `@${MODIFIED_SETTING_TAG}`, '@tag:usesOnlineServices', '@tag:sync', `@tag:${REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG}`, `@${ID_SETTING_TAG}`, `@${EXTENSION_SETTING_TAG}`, `@${FEATURE_SETTING_TAG}scm`, `@${FEATURE_SETTING_TAG}explorer`, `@${FEATURE_SETTING_TAG}search`, `@${FEATURE_SETTING_TAG}debug`, `@${FEATURE_SETTING_TAG}extensions`, `@${FEATURE_SETTING_TAG}terminal`, `@${FEATURE_SETTING_TAG}task`, `@${FEATURE_SETTING_TAG}problems`, `@${FEATURE_SETTING_TAG}output`, `@${FEATURE_SETTING_TAG}comments`, `@${FEATURE_SETTING_TAG}remote`, `@${FEATURE_SETTING_TAG}timeline` + `@${MODIFIED_SETTING_TAG}`, + '@tag:usesOnlineServices', + '@tag:sync', + `@tag:${REQUIRE_TRUSTED_WORKSPACE_SETTING_TAG}`, + `@${ID_SETTING_TAG}`, + `@${EXTENSION_SETTING_TAG}`, + `@${FEATURE_SETTING_TAG}scm`, + `@${FEATURE_SETTING_TAG}explorer`, + `@${FEATURE_SETTING_TAG}search`, + `@${FEATURE_SETTING_TAG}debug`, + `@${FEATURE_SETTING_TAG}extensions`, + `@${FEATURE_SETTING_TAG}terminal`, + `@${FEATURE_SETTING_TAG}task`, + `@${FEATURE_SETTING_TAG}problems`, + `@${FEATURE_SETTING_TAG}output`, + `@${FEATURE_SETTING_TAG}comments`, + `@${FEATURE_SETTING_TAG}remote`, + `@${FEATURE_SETTING_TAG}timeline`, + `@${FEATURE_SETTING_TAG}notebook`, ]; private static shouldSettingUpdateFast(type: SettingValueType | SettingValueType[]): boolean { diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index 9a29509d851..581e95611bd 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -701,7 +701,7 @@ export class SearchResultModel extends SettingsTreeModel { const isRemote = !!this.environmentService.remoteAuthority; this.root.children = this.root.children - .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && (this.containsValidFeature() ? child.matchesAnyFeature(this._viewState.featureFilters) : true)); + .filter(child => child instanceof SettingsTreeSettingElement && child.matchesAllTags(this._viewState.tagFilters) && child.matchesScope(this._viewState.settingsTarget, isRemote) && child.matchesAnyExtension(this._viewState.extensionFilters) && child.matchesAnyId(this._viewState.idFilters) && child.matchesAnyFeature(this._viewState.featureFilters)); if (this.newExtensionSearchResults && this.newExtensionSearchResults.filterMatches.length) { const resultExtensionIds = this.newExtensionSearchResults.filterMatches @@ -715,22 +715,6 @@ export class SearchResultModel extends SettingsTreeModel { } } - private containsValidFeature(): boolean { - if (!this._viewState.featureFilters || !this._viewState.featureFilters.size || !tocData.children) { - return false; - } - - const features = tocData.children.find(child => child.id === 'features'); - - if (features && features.children) { - return Array.from(this._viewState.featureFilters).some(filter => { - return features.children?.find(feature => 'features/' + filter === feature.id); - }); - } else { - return false; - } - } - private getFlatSettings(): ISetting[] { const flatSettings: ISetting[] = []; arrays.coalesce(this.getUniqueResults()) diff --git a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts index 342ce7934eb..351b49194de 100644 --- a/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts +++ b/src/vs/workbench/contrib/remote/browser/remoteIndicator.ts @@ -25,7 +25,7 @@ import { isWeb } from 'vs/base/common/platform'; import { once } from 'vs/base/common/functional'; import { truncate } from 'vs/base/common/strings'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; -import { getVirtualWorkspaceLocation } from 'vs/platform/remote/common/remoteHosts'; +import { getRemoteName, getVirtualWorkspaceLocation, getVirtualWorkspaceScheme } from 'vs/platform/remote/common/remoteHosts'; import { getCodiconAriaLabel } from 'vs/base/common/codicons'; import { ILogService } from 'vs/platform/log/common/log'; import { ReloadWindowAction } from 'vs/workbench/browser/actions/windowActions'; @@ -53,6 +53,9 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr private remoteMenuActionsGroups: ActionGroup[] | undefined; private readonly remoteAuthority = this.environmentService.remoteAuthority; + + private virtualWorkspaceScheme: string | undefined = undefined; + private connectionState: 'initializing' | 'connected' | 'reconnecting' | 'disconnected' | undefined = undefined; private readonly connectionStateContextKey = new RawContextKey<'' | 'initializing' | 'disconnected' | 'connected'>('remoteConnectionState', '').bindTo(this.contextKeyService); @@ -80,6 +83,8 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr if (this.remoteAuthority) { this.connectionState = 'initializing'; this.connectionStateContextKey.set(this.connectionState); + } else { + this.updateVirtualWorkspaceScheme(); } this.registerActions(); @@ -107,7 +112,7 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr }); // Close Remote Connection - if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID && this.remoteAuthority) { + if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID) { registerAction2(class extends Action2 { constructor() { super({ @@ -117,17 +122,18 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr f1: true }); } - run = () => that.remoteAuthority && that.hostService.openWindow({ forceReuseWindow: true, remoteAuthority: null }); - }); - - MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { - group: '6_close', - command: { - id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, - title: nls.localize({ key: 'miCloseRemote', comment: ['&& denotes a mnemonic'] }, "Close Re&&mote Connection") - }, - order: 3.5 + run = () => that.hostService.openWindow({ forceReuseWindow: true, remoteAuthority: null }); }); + if (this.remoteAuthority) { + MenuRegistry.appendMenuItem(MenuId.MenubarFileMenu, { + group: '6_close', + command: { + id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, + title: nls.localize({ key: 'miCloseRemote', comment: ['&& denotes a mnemonic'] }, "Close Re&&mote Connection") + }, + order: 3.5 + }); + } } if (this.extensionGalleryService.isEnabled()) { @@ -196,10 +202,17 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr })); } } else { - this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this.updateRemoteStatusIndicator())); + this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => { + this.updateVirtualWorkspaceScheme(); + this.updateRemoteStatusIndicator(); + })); } } + private updateVirtualWorkspaceScheme() { + this.virtualWorkspaceScheme = getVirtualWorkspaceScheme(this.workspaceContextService.getWorkspace()); + } + private async updateWhenInstalledExtensionsRegistered(): Promise { await this.extensionService.whenInstalledExtensionsRegistered(); @@ -280,13 +293,13 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr this.renderRemoteStatusIndicator(`$(remote) ${truncate(hostLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('host.tooltip', "Editing on {0}", hostLabel)); } return; - } - - // Workspace with label: indicate editing source - const workspaceLabel = this.getWorkspaceLabel(); - if (workspaceLabel) { - this.renderRemoteStatusIndicator(`$(remote) ${truncate(workspaceLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('workspace.tooltip', "Editing on {0}", workspaceLabel)); - return; + } else if (this.virtualWorkspaceScheme) { + // Workspace with label: indicate editing source + const workspaceLabel = this.getWorkspaceLabel(); + if (workspaceLabel) { + this.renderRemoteStatusIndicator(`$(remote) ${truncate(workspaceLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, nls.localize('workspace.tooltip', "Editing on {0}", workspaceLabel)); + return; + } } // Remote actions: offer menu @@ -342,11 +355,37 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr return undefined; }; + const matchCurrentRemote = () => { + if (this.remoteAuthority) { + return new RegExp(`^remote_\\d\\d_${getRemoteName(this.remoteAuthority)}_`); + } else if (this.virtualWorkspaceScheme) { + if (this.virtualWorkspaceScheme === 'vscode-vfs') { + return new RegExp(`^remote_\\d\\d_vfs_`); + } else { + return new RegExp(`^virtualfs_\\d\\d_${this.virtualWorkspaceScheme}_`); + } + } + return undefined; + }; + const computeItems = () => { - const actionGroups = this.getRemoteMenuActions(true); + let actionGroups = this.getRemoteMenuActions(true); const items: (IQuickPickItem | IQuickPickSeparator)[] = []; + const currentRemoteMatcher = matchCurrentRemote(); + if (currentRemoteMatcher) { + // commands for the current remote go first + actionGroups = actionGroups.sort((g1, g2) => { + const isCurrentRemote1 = currentRemoteMatcher.test(g1[0]); + const isCurrentRemote2 = currentRemoteMatcher.test(g2[0]); + if (isCurrentRemote1 !== isCurrentRemote2) { + return isCurrentRemote1 ? -1 : 1; + } + return g1[0].localeCompare(g2[0]); + }); + } + let lastCategoryName: string | undefined = undefined; for (let actionGroup of actionGroups) { @@ -371,25 +410,38 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr } } - if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID && this.remoteAuthority) { - if (items.length) { - items.push({ type: 'separator' }); - } + if (RemoteStatusIndicator.SHOW_CLOSE_REMOTE_COMMAND_ID) { + if (this.remoteAuthority) { + if (items.length) { + items.push({ type: 'separator' }); + } - items.push({ - type: 'item', - id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, - label: nls.localize('closeRemote.title', 'Close Remote Connection') - }); - - if (this.connectionState === 'disconnected') { items.push({ type: 'item', - id: ReloadWindowAction.ID, - label: nls.localize('reloadWindow', 'Reload Window') + id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, + label: nls.localize('closeRemoteConnection.title', 'Close Remote Connection') + }); + + if (this.connectionState === 'disconnected') { + items.push({ + type: 'item', + id: ReloadWindowAction.ID, + label: nls.localize('reloadWindow', 'Reload Window') + }); + } + } else if (this.virtualWorkspaceScheme) { + if (items.length) { + items.push({ type: 'separator' }); + } + + items.push({ + type: 'item', + id: RemoteStatusIndicator.CLOSE_REMOTE_COMMAND_ID, + label: nls.localize('closeRemoteWindow.title', 'Close Remote') }); } } + if (!this.remoteAuthority && this.extensionGalleryService.isEnabled()) { items.push({ type: 'separator' diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 00c2d9bbc06..d0fb01b93d7 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -17,6 +17,7 @@ import type { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl'; import { ITerminalStatusList } from 'vs/workbench/contrib/terminal/browser/terminalStatusList'; import { ICompleteTerminalConfiguration } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; import { Orientation } from 'vs/base/browser/ui/splitview/splitview'; +import { IEditableData } from 'vs/workbench/common/views'; export const ITerminalService = createDecorator('terminalService'); export const ITerminalInstanceService = createDecorator('terminalInstanceService'); @@ -206,6 +207,8 @@ export interface ITerminalService { requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise; isAttachedToTerminal(remoteTerm: IRemoteTerminalAttachTarget): boolean; + getEditableData(stat: ITerminalInstance): IEditableData | undefined; + setEditable(stat: ITerminalInstance, data: IEditableData | null): Promise; } export interface IRemoteTerminalService extends IOffProcessTerminalService { @@ -600,12 +603,13 @@ export interface ITerminalInstance { registerLinkProvider(provider: ITerminalExternalLinkProvider): IDisposable; /** - * Triggers a quick pick to rename this terminal. + * Sets the terminal name to the provided title or triggers a quick pick + * to take user input. */ - rename(): Promise; + rename(title?: string): Promise; /** - * Triggers a quick pick to rename this terminal. + * Triggers a quick pick to change the icon of this terminal. */ changeIcon(): Promise; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index af542818ef9..dac068f76df 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -23,7 +23,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { ILabelService } from 'vs/platform/label/common/label'; import { IListService } from 'vs/platform/list/browser/listService'; -import { INotificationService } from 'vs/platform/notification/common/notification'; +import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IPickOptions, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { ILocalTerminalService, ITerminalProfile, TerminalSettingId, TitleEventSource } from 'vs/platform/terminal/common/terminal'; @@ -811,9 +811,30 @@ export function registerTerminalActions() { }); } async run(accessor: ServicesAccessor) { - return getSelectedInstances(accessor)?.[0].rename(); + const terminalService = accessor.get(ITerminalService); + const notificationService = accessor.get(INotificationService); + + const instance = getSelectedInstances(accessor)?.[0]; + if (!instance) { + return; + } + + await terminalService.setEditable(instance, { + validationMessage: value => validateTerminalName(value), + onFinish: async (value, success) => { + if (success) { + try { + await instance.rename(value); + } catch (e) { + notificationService.error(e); + } + } + await terminalService.setEditable(instance, null); + } + }); } }); + registerAction2(class extends Action2 { constructor() { super({ @@ -1830,3 +1851,14 @@ function focusNext(accessor: ServicesAccessor): void { const listService = accessor.get(IListService); listService.lastFocusedList?.focusNext(); } + +export function validateTerminalName(name: string): { content: string, severity: Severity } | null { + if (!name || name.trim().length === 0) { + return { + content: localize('emptyTerminalNameError', "A name must be provided."), + severity: Severity.Error + }; + } + + return null; +} diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index b9f8ed26f93..dbcd7c31b7e 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -775,7 +775,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _initDragAndDrop(container: HTMLElement) { this._dndObserver?.dispose(); - const dndController = new TerminalInstanceDropAndDropController(container); + const dndController = new TerminalInstanceDragAndDropController(container); dndController.onDropTerminal(e => this._onRequestAddInstanceToGroup.fire(e)); dndController.onDropFile(async path => { const preparedPath = await this._terminalInstanceService.preparePathForTerminalAsync(path, this.shellLaunchConfig.executable, this.title, this.shellType, this.isRemote); @@ -1789,13 +1789,15 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return this._linkManager.registerExternalLinkProvider(this, provider); } - async rename() { - const name = await this._quickInputService.input({ - value: this.title, - prompt: nls.localize('workbench.action.terminal.rename.prompt', "Enter terminal name"), - }); - if (name) { - this.setTitle(name, TitleEventSource.Api); + async rename(title?: string) { + if (!title) { + title = await this._quickInputService.input({ + value: this.title, + prompt: nls.localize('workbench.action.terminal.rename.prompt', "Enter terminal name"), + }); + } + if (title) { + this.setTitle(title, TitleEventSource.Api); } } @@ -1843,7 +1845,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } items.push({ type: 'separator' }); - const showAllColorsItem = { label: 'Show all colors' }; + const showAllColorsItem = { label: 'Reset to default' }; items.push(showAllColorsItem); styleElement.textContent = css; document.body.appendChild(styleElement); @@ -1870,7 +1872,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } -class TerminalInstanceDropAndDropController extends Disposable implements IDragAndDropObserverCallbacks { +class TerminalInstanceDragAndDropController extends Disposable implements IDragAndDropObserverCallbacks { private _dropOverlay?: HTMLElement; private readonly _onDropFile = new Emitter(); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index c724ea70dcb..ce934e8dc6b 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -19,7 +19,7 @@ import { IKeyMods, IPickOptions, IQuickInputButton, IQuickInputService, IQuickPi import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ILocalTerminalService, IOffProcessTerminalService, IShellLaunchConfig, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalSettingId } from 'vs/platform/terminal/common/terminal'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; +import { IEditableData, IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; import { IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalGroup, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; @@ -69,6 +69,8 @@ export class TerminalService implements ITerminalService { private _localTerminalsInitPromise: Promise | undefined; private _connectionState: TerminalConnectionState; + private _editable: { instance: ITerminalInstance, data: IEditableData } | undefined; + public get activeGroupIndex(): number { return this._activeGroupIndex; } public get terminalGroups(): ITerminalGroup[] { return this._terminalGroups; } public get isProcessSupportRegistered(): boolean { return !!this._processSupportContextKey.get(); } @@ -316,6 +318,25 @@ export class TerminalService implements ITerminalService { return activeInstance ? activeInstance : this.createTerminal(undefined); } + async setEditable(instance: ITerminalInstance, data?: IEditableData | null): Promise { + if (!data) { + this._editable = undefined; + } else { + this._editable = { instance: instance, data }; + } + const pane = this._viewsService.getActiveViewWithId(TERMINAL_VIEW_ID); + const isEditing = this._isEditable(instance); + pane?.terminalTabbedView?.setEditable(isEditing); + } + + private _isEditable(instance: ITerminalInstance | undefined): boolean { + return !!this._editable && (this._editable.instance === instance || !instance); + } + + getEditableData(instance: ITerminalInstance): IEditableData | undefined { + return this._editable && this._editable.instance === instance ? this._editable.data : undefined; + } + requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise { // The initial request came from the extension host, no need to wait for it return new Promise(callback => { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts index 04fb6e4721a..69a0e7f6d62 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts @@ -288,7 +288,7 @@ export class TerminalTabbedView extends Disposable { const hasText = this._tabListElement.clientWidth > TerminalTabsListSizes.MidpointViewWidth; this._tabContainer.classList.toggle('has-text', hasText); this._terminalIsTabsNarrowContextKey.set(!hasText); - this._tabList.render(); + this._tabList.refresh(); } private _addSashListener() { @@ -469,6 +469,13 @@ export class TerminalTabbedView extends Disposable { ]; } + setEditable(isEditing: boolean): void { + if (!isEditing) { + this._tabList.domFocus(); + } + return this._tabList.refresh(); + } + focusTabs(): void { if (!this._shouldShowTabs()) { return; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts index 396ae88f448..6b9f9e5e683 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts @@ -26,7 +26,7 @@ import { DEFAULT_LABELS_CONTAINER, IResourceLabel, ResourceLabels } from 'vs/wor import { IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations'; import { IHoverAction, IHoverService } from 'vs/workbench/services/hover/browser/hover'; import Severity from 'vs/base/common/severity'; -import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IListDragAndDrop, IListDragOverReaction, IListRenderer, ListDragOverEffect } from 'vs/base/browser/ui/list/list'; import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd'; import { disposableTimeout } from 'vs/base/common/async'; @@ -34,6 +34,13 @@ import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; import { URI } from 'vs/base/common/uri'; import { getColorClass, getIconId, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; import { Schemas } from 'vs/base/common/network'; +import { IEditableData } from 'vs/workbench/common/views'; +import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; +import { once } from 'vs/base/common/functional'; +import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; +import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; +import { KeyCode } from 'vs/base/common/keyCodes'; const $ = DOM.$; @@ -89,13 +96,13 @@ export class TerminalTabList extends WorkbenchList { configurationService, keybindingService, ); - this._terminalService.onInstancesChanged(() => this.render()); - this._terminalService.onGroupsChanged(() => this.render()); - this._terminalService.onInstanceTitleChanged(() => this.render()); - this._terminalService.onInstanceIconChanged(() => this.render()); - this._terminalService.onInstancePrimaryStatusChanged(() => this.render()); - this._terminalService.onDidChangeConnectionState(() => this.render()); - this._themeService.onDidColorThemeChange(() => this.render()); + this._terminalService.onInstancesChanged(() => this.refresh()); + this._terminalService.onGroupsChanged(() => this.refresh()); + this._terminalService.onInstanceTitleChanged(() => this.refresh()); + this._terminalService.onInstanceIconChanged(() => this.refresh()); + this._terminalService.onInstancePrimaryStatusChanged(() => this.refresh()); + this._terminalService.onDidChangeConnectionState(() => this.refresh()); + this._themeService.onDidColorThemeChange(() => this.refresh()); this._terminalService.onActiveInstanceChanged(e => { if (e) { const i = this._terminalService.terminalInstances.indexOf(e); @@ -157,10 +164,10 @@ export class TerminalTabList extends WorkbenchList { this._decorationsProvider = instantiationService.createInstance(TerminalDecorationsProvider); _decorationsService.registerDecorationsProvider(this._decorationsProvider); } - this.render(); + this.refresh(); } - render(): void { + refresh(): void { this.splice(0, this.length, this._terminalService.terminalInstances); } @@ -182,7 +189,8 @@ class TerminalTabsRenderer implements IListRenderer 1) { const terminalIndex = group.terminalInstances.indexOf(instance); @@ -323,6 +341,84 @@ class TerminalTabsRenderer implements IListRenderer { + const message = editableData.validationMessage(value); + if (!message || message.severity !== Severity.Error) { + return null; + } + + return { + content: message.content, + formatContent: true, + type: MessageType.ERROR + }; + } + }, + ariaLabel: localize('terminalInputAriaLabel', "Type terminal name. Press Enter to confirm or Escape to cancel.") + }); + const styler = attachInputBoxStyler(inputBox, this._themeService); + + inputBox.value = value; + inputBox.focus(); + inputBox.select({ start: 0, end: value.length }); + + const done = once((success: boolean, finishEditing: boolean) => { + inputBox.element.style.display = 'none'; + const value = inputBox.value; + dispose(toDispose); + inputBox.element.remove(); + if (finishEditing) { + editableData.onFinish(value, success); + } + }); + + const showInputBoxNotification = () => { + if (inputBox.isInputValid()) { + const message = editableData.validationMessage(inputBox.value); + if (message) { + inputBox.showMessage({ + content: message.content, + formatContent: true, + type: message.severity === Severity.Info ? MessageType.INFO : message.severity === Severity.Warning ? MessageType.WARNING : MessageType.ERROR + }); + } else { + inputBox.hideMessage(); + } + } + }; + showInputBoxNotification(); + + const toDispose = [ + inputBox, + DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: IKeyboardEvent) => { + if (e.equals(KeyCode.Enter)) { + done(inputBox.isInputValid(), true); + } else if (e.equals(KeyCode.Escape)) { + done(false, true); + } + }), + DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_UP, (e: IKeyboardEvent) => { + showInputBoxNotification(); + }), + DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => { + done(inputBox.isInputValid(), true); + }), + label, + styler + ]; + + return toDisposable(() => { + done(false, false); + }); + } + disposeElement(instance: ITerminalInstance, index: number, templateData: ITerminalTabEntryTemplate): void { templateData.elementDispoables?.dispose(); templateData.elementDispoables = undefined; diff --git a/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts b/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts index 5e521205775..b16844d7758 100644 --- a/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts +++ b/src/vs/workbench/contrib/terminal/test/node/terminalProfiles.test.ts @@ -115,36 +115,36 @@ suite('Workbench - TerminalProfiles', () => { } as ITestTerminalConfig) as ITerminalConfiguration; test('should prefer pwsh 7 to Windows PowerShell', async () => { - const fsProvider = createFsProvider([ + const expectedPaths = [ 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', 'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe', 'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - ]); - const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined); + ]; + const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), undefined, undefined, undefined, expectedPaths); const expected = [ { profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', isDefault: true } ]; profilesEqual(profiles, expected); }); test('should prefer pwsh 7 to pwsh 6', async () => { - const fsProvider = createFsProvider([ + const expectedPaths = [ 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', 'C:\\Program Files\\PowerShell\\6\\pwsh.exe', 'C:\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe', 'C:\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - ]); - const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined); + ]; + const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), undefined, undefined, undefined, expectedPaths); const expected = [ { profileName: 'PowerShell', path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe', isDefault: true } ]; profilesEqual(profiles, expected); }); - test.skip('should fallback to Windows PowerShell', async () => { - const fsProvider = createFsProvider([ + test('should fallback to Windows PowerShell', async () => { + const expectedPaths = [ 'C:\\Windows\\Sysnative\\WindowsPowerShell\\v1.0\\powershell.exe', 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - ]); - const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), fsProvider, undefined, undefined, undefined); + ]; + const profiles = await detectAvailableProfiles(false, buildTestSafeConfigProvider(pwshSourceConfig), undefined, undefined, undefined, expectedPaths); strictEqual(profiles.length, 1); strictEqual(profiles[0].profileName, 'PowerShell'); }); @@ -228,7 +228,7 @@ suite('Workbench - TerminalProfiles', () => { }, async readFile(path: string): Promise { if (path !== '/etc/shells') { - fail('Unexected path'); + fail('Unexepected path'); } return Buffer.from(etcShellsContent); } diff --git a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css index d252616bc61..0600e81458a 100644 --- a/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css +++ b/src/vs/workbench/contrib/welcome/gettingStarted/browser/gettingStarted.css @@ -84,7 +84,7 @@ } .monaco-workbench .part.editor > .content .gettingStartedContainer .gettingStartedSlideCategories { - padding: 12px; + padding: 24px; } .monaco-workbench .part.editor > .content .gettingStartedContainer.animationReady .gettingStartedSlide { @@ -557,14 +557,11 @@ } .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .codicon-arrow-small-right { - position: relative; - top: 3px; - left: 2px; + padding-left: 8px; } .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link .codicon-check-all { - position: relative; - top: 3px; + padding-right: 8px; } .monaco-workbench .part.editor > .content .gettingStartedContainer .gettingStartedSlide .skip { @@ -606,6 +603,11 @@ display: none; } +.monaco-workbench .part.editor > .content .gettingStartedContainer .done-next-container { + display: flex; + padding: 8px 16px 16px; +} + .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link { padding: 0; background: transparent; @@ -616,9 +618,13 @@ max-width: 100%; } +.monaco-workbench .part.editor > .content .gettingStartedContainer .done-next-container .button-link { + display: flex; + align-items: center; +} + .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link.next { - position: absolute; - right: 0; + margin-left: auto; } .monaco-workbench .part.editor > .content .gettingStartedContainer .button-link:hover { @@ -645,7 +651,7 @@ } .monaco-workbench .part.editor > .content .gettingStartedContainer .getting-started-category .codicon { - top: 0; + top: 3px; } .monaco-workbench .part.editor > .content .getting-started-category .codicon::before{ diff --git a/src/vs/workbench/services/workspaces/common/workspaceTrust.ts b/src/vs/workbench/services/workspaces/common/workspaceTrust.ts index 00ece8fe9b5..8652288abae 100644 --- a/src/vs/workbench/services/workspaces/common/workspaceTrust.ts +++ b/src/vs/workbench/services/workspaces/common/workspaceTrust.ts @@ -202,6 +202,11 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork } getUriTrustInfo(uri: URI): IWorkspaceTrustUriInfo { + // Return trusted when workspace trust is disabled + if (!isWorkspaceTrustEnabled(this.configurationService)) { + return { trusted: true, uri }; + } + let resultState = false; let maxLength = -1; diff --git a/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts b/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts index 0cc72cdd1bc..324cdd3c071 100644 --- a/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTypeConverter.test.ts @@ -5,7 +5,8 @@ import * as assert from 'assert'; -import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters'; +import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; +import { MarkdownString, NotebookCellOutputItem } from 'vs/workbench/api/common/extHostTypeConverters'; import { isEmptyObject } from 'vs/base/common/types'; import { forEach } from 'vs/base/common/collections'; import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log'; @@ -81,4 +82,23 @@ suite('ExtHostTypeConverter', function () { } }); }); + + test('NotebookCellOutputItem', function () { + + const item = extHostTypes.NotebookCellOutputItem.text('Hello', 'foo/bar'); + + const dto = NotebookCellOutputItem.from(item); + + assert.strictEqual(dto.mime, 'foo/bar'); + assert.strictEqual(dto.metadata, undefined); + assert.strictEqual(dto.value, undefined); + assert.deepStrictEqual(dto.valueBytes, Array.from(new TextEncoder().encode('Hello'))); + + const item2 = NotebookCellOutputItem.to(dto); + + assert.strictEqual(item2.mime, item.mime); + assert.strictEqual(item2.metadata, item.metadata); + assert.strictEqual(item2.value, item.value); + assert.deepStrictEqual(item2.data, item.data); + }); }); diff --git a/src/vs/workbench/test/browser/api/extHostTypes.test.ts b/src/vs/workbench/test/browser/api/extHostTypes.test.ts index 353096359eb..ac2117b6745 100644 --- a/src/vs/workbench/test/browser/api/extHostTypes.test.ts +++ b/src/vs/workbench/test/browser/api/extHostTypes.test.ts @@ -696,28 +696,28 @@ suite('ExtHostTypes', function () { item = types.NotebookCellOutputItem.json(1); assert.strictEqual(item.mime, 'application/json'); - assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify(1))); + assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(1))); item = types.NotebookCellOutputItem.json(1, 'foo'); assert.strictEqual(item.mime, 'foo'); - assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify(1))); + assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(1))); item = types.NotebookCellOutputItem.json(true); assert.strictEqual(item.mime, 'application/json'); - assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify(true))); + assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify(true))); item = types.NotebookCellOutputItem.json([true, 1, 'ddd']); assert.strictEqual(item.mime, 'application/json'); - assert.deepStrictEqual(item.value, new TextEncoder().encode(JSON.stringify([true, 1, 'ddd'], undefined, '\t'))); + assert.deepStrictEqual(item.data, new TextEncoder().encode(JSON.stringify([true, 1, 'ddd'], undefined, '\t'))); // --- text item = types.NotebookCellOutputItem.text('Hęłlö'); assert.strictEqual(item.mime, 'text/plain'); - assert.deepStrictEqual(item.value, new TextEncoder().encode('Hęłlö')); + assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö')); item = types.NotebookCellOutputItem.text('Hęłlö', 'foo/bar'); assert.strictEqual(item.mime, 'foo/bar'); - assert.deepStrictEqual(item.value, new TextEncoder().encode('Hęłlö')); + assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö')); }); }); From 57af60a7b7f4774f007c78997763af5e2c67ceaa Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Tue, 25 May 2021 17:54:40 -0700 Subject: [PATCH 098/140] testing: initial test message split view --- src/vs/base/common/iterator.ts | 5 +- src/vs/platform/actions/common/actions.ts | 1 + .../browser/explorerProjections/display.ts | 6 + .../explorerProjections/hierarchalByName.ts | 3 +- .../contrib/testing/browser/icons.ts | 21 +- .../contrib/testing/browser/media/testing.css | 18 +- .../testing/browser/testExplorerActions.ts | 1 - .../testing/browser/testingOutputPeek.ts | 830 +++++++++++++++--- .../contrib/testing/common/testCollection.ts | 2 + .../contrib/testing/common/testResult.ts | 24 + .../testing/common/testingContextKeys.ts | 4 + .../test/common/testResultService.test.ts | 1 + 12 files changed, 766 insertions(+), 150 deletions(-) create mode 100644 src/vs/workbench/contrib/testing/browser/explorerProjections/display.ts diff --git a/src/vs/base/common/iterator.ts b/src/vs/base/common/iterator.ts index 8b60c8757dc..f7d81bf5bbc 100644 --- a/src/vs/base/common/iterator.ts +++ b/src/vs/base/common/iterator.ts @@ -61,9 +61,10 @@ export namespace Iterable { } } - export function* map(iterable: Iterable, fn: (t: T) => R): Iterable { + export function* map(iterable: Iterable, fn: (t: T, index: number) => R): Iterable { + let index = 0; for (const element of iterable) { - yield fn(element); + yield fn(element, index++); } } diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index c0673645936..2bdb2c70b32 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -127,6 +127,7 @@ export class MenuId { static readonly StatusBarWindowIndicatorMenu = new MenuId('StatusBarWindowIndicatorMenu'); static readonly StatusBarRemoteIndicatorMenu = new MenuId('StatusBarRemoteIndicatorMenu'); static readonly TestItem = new MenuId('TestItem'); + static readonly TestPeekElement = new MenuId('TestPeekElement'); static readonly TouchBarContext = new MenuId('TouchBarContext'); static readonly TitleBarContext = new MenuId('TitleBarContext'); static readonly TunnelContext = new MenuId('TunnelContext'); diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/display.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/display.ts new file mode 100644 index 00000000000..e2dccbe6462 --- /dev/null +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/display.ts @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export const flatTestItemDelimiter = ' › '; diff --git a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts index 1d84570af11..9c9bfcde9e4 100644 --- a/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts +++ b/src/vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByName.ts @@ -6,6 +6,7 @@ import { Iterable } from 'vs/base/common/iterator'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; import { TestExplorerTreeElement } from 'vs/workbench/contrib/testing/browser/explorerProjections'; +import { flatTestItemDelimiter } from 'vs/workbench/contrib/testing/browser/explorerProjections/display'; import { HierarchicalByLocationProjection as HierarchicalByLocationProjection } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalByLocation'; import { ByLocationTestItemElement, ByLocationFolderElement } from 'vs/workbench/contrib/testing/browser/explorerProjections/hierarchalNodes'; import { NodeRenderDirective } from 'vs/workbench/contrib/testing/browser/explorerProjections/nodeHelper'; @@ -38,7 +39,7 @@ export class ByNameTestItemElement extends ByLocationTestItemElement { public override get description() { let description: string | null = null; for (let parent = this.actualParent; parent && !parent.isTestRoot; parent = parent.actualParent) { - description = description ? `${parent.label} › ${description}` : parent.label; + description = description ? parent.label + flatTestItemDelimiter + description : parent.label; } return description; diff --git a/src/vs/workbench/contrib/testing/browser/icons.ts b/src/vs/workbench/contrib/testing/browser/icons.ts index d6792826f22..1ea865256b5 100644 --- a/src/vs/workbench/contrib/testing/browser/icons.ts +++ b/src/vs/workbench/contrib/testing/browser/icons.ts @@ -7,8 +7,8 @@ import { Codicon } from 'vs/base/common/codicons'; import { localize } from 'vs/nls'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; -import { testingColorRunAction, testStatesToIconColors } from 'vs/workbench/contrib/testing/browser/theme'; +import { TestMessageSeverity, TestResultState } from 'vs/workbench/api/common/extHostTypes'; +import { testingColorRunAction, testMessageSeverityColors, testStatesToIconColors } from 'vs/workbench/contrib/testing/browser/theme'; export const testingViewIcon = registerIcon('test-view-icon', Codicon.beaker, localize('testViewIcon', 'View icon of the test view.')); export const testingRunIcon = registerIcon('testing-run-icon', Codicon.run, localize('testingRunIcon', 'Icon of the "run test" action.')); @@ -32,6 +32,13 @@ export const testingStatesToIcons = new Map([ [TestResultState.Unset, registerIcon('testing-unset-icon', Codicon.circleOutline, localize('testingUnsetIcon', 'Icon shown for tests that are in an unset state.'))], ]); +export const testMessageSeverityToIcons = new Map([ + [TestMessageSeverity.Error, registerIcon('testing-error-message-icon', Codicon.error, localize('testingErrorIcon', 'Icon shown for tests that have an error.'))], + [TestMessageSeverity.Warning, registerIcon('testing-warning-message-icon', Codicon.warning, localize('testingErrorIcon', 'Icon shown for tests that have an error.'))], + [TestMessageSeverity.Information, registerIcon('testing-info-message-icon', Codicon.info, localize('testingErrorIcon', 'Icon shown for tests that have an error.'))], + [TestMessageSeverity.Hint, registerIcon('testing-hint-message-icon', Codicon.question, localize('testingErrorIcon', 'Icon shown for tests that have an error.'))], +]); + registerThemingParticipant((theme, collector) => { for (const [state, icon] of testingStatesToIcons.entries()) { const color = testStatesToIconColors[state]; @@ -43,6 +50,16 @@ registerThemingParticipant((theme, collector) => { }`); } + for (const [state, { decorationForeground }] of Object.entries(testMessageSeverityColors)) { + const icon = testMessageSeverityToIcons.get(Number(state)); + if (!icon) { + continue; + } + collector.addRule(`.monaco-workbench ${ThemeIcon.asCSSSelector(icon)} { + color: ${theme.getColor(decorationForeground)} !important; + }`); + } + collector.addRule(` .monaco-editor ${ThemeIcon.asCSSSelector(testingRunIcon)}, .monaco-editor ${ThemeIcon.asCSSSelector(testingRunAllIcon)} { diff --git a/src/vs/workbench/contrib/testing/browser/media/testing.css b/src/vs/workbench/contrib/testing/browser/media/testing.css index 6f11ee371eb..d7de6f4b83f 100644 --- a/src/vs/workbench/contrib/testing/browser/media/testing.css +++ b/src/vs/workbench/contrib/testing/browser/media/testing.css @@ -15,11 +15,13 @@ position: relative; } -.test-explorer .test-item { +.test-explorer .test-item, +.test-output-peek-tree .test-peek-item { display: flex; align-items: center; } +.test-output-peek-tree .monaco-list-row .monaco-action-bar, .test-explorer .monaco-list-row .monaco-action-bar, .test-explorer .monaco-list-row .codicon-testing-hidden { display: none; @@ -28,7 +30,9 @@ } .test-explorer .monaco-list-row:hover .monaco-action-bar, -.test-explorer .monaco-list-row:focus .monaco-action-bar { +.test-output-peek-tree .monaco-list-row:hover .monaco-action-bar, +.test-explorer .monaco-list-row:focus .monaco-action-bar, +.test-output-peek-tree .monaco-list-row:focus .monaco-action-bar { display: initial; } @@ -46,7 +50,8 @@ margin: 0; } -.test-explorer .name { +.test-explorer .name, +.test-output-peek-tree .name { overflow: hidden; text-overflow: ellipsis; flex-grow: 1; @@ -54,7 +59,8 @@ align-items: center; } -.test-explorer .computed-state { +.test-explorer .computed-state, +.test-output-peek-tree .computed-state { margin-right: 0.25em; } @@ -122,6 +128,10 @@ border-bottom-width: 2px; } +.monaco-editor .zone-widget.test-output-peek .test-output-peek-message-container { + height: 100%; +} + .monaco-editor .zone-widget.test-output-peek .preview-text { padding: 8px 12px 8px 20px; height: calc(100% - 16px); diff --git a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts index 116624a7866..f69b298ea1c 100644 --- a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts +++ b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts @@ -521,7 +521,6 @@ export class ShowMostRecentOutputAction extends Action2 { } } - export class CollapseAllAction extends ViewAction { public static readonly ID = 'testing.collapseAll'; constructor() { diff --git a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts index 26cd479c42e..9d830df192c 100644 --- a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts +++ b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts @@ -5,14 +5,24 @@ import * as dom from 'vs/base/browser/dom'; import { renderStringAsPlaintext } from 'vs/base/browser/markdownRenderer'; +import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { alert } from 'vs/base/browser/ui/aria/aria'; +import { IIdentityProvider } from 'vs/base/browser/ui/list/list'; import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; +import { Orientation, Sizing, SplitView } from 'vs/base/browser/ui/splitview/splitview'; +import { ICompressedTreeElement, ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; +import { ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree'; +import { ITreeContextMenuEvent, ITreeNode } from 'vs/base/browser/ui/tree/tree'; +import { Action, IAction, Separator } from 'vs/base/common/actions'; import { Codicon } from 'vs/base/common/codicons'; import { Color } from 'vs/base/common/color'; +import { Emitter, Event } from 'vs/base/common/event'; +import { FuzzyScore } from 'vs/base/common/filters'; import { IMarkdownString } from 'vs/base/common/htmlContent'; +import { Iterable } from 'vs/base/common/iterator'; import { KeyCode } from 'vs/base/common/keyCodes'; import { Lazy } from 'vs/base/common/lazy'; -import { Disposable, IReference, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, IDisposable, IReference, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { clamp } from 'vs/base/common/numbers'; import { count } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; @@ -26,31 +36,52 @@ import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService'; import { getOuterEditor, IPeekViewService, peekViewTitleBackground, peekViewTitleForeground, peekViewTitleInfoForeground, PeekViewWidget } from 'vs/editor/contrib/peekView/peekView'; import { localize } from 'vs/nls'; +import { createAndFillInActionBarActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; +import { IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions'; +import { ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { createDecorator, IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService'; +import { WorkbenchCompressibleObjectTree } from 'vs/platform/list/browser/listService'; +import { IColorTheme, IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; +import { IResourceLabel, ResourceLabels } from 'vs/workbench/browser/labels'; import { EditorModel } from 'vs/workbench/common/editor/editorModel'; +import { flatTestItemDelimiter } from 'vs/workbench/contrib/testing/browser/explorerProjections/display'; +import { testingStatesToIcons, testMessageSeverityToIcons } from 'vs/workbench/contrib/testing/browser/icons'; +import { ITestingOutputTerminalService } from 'vs/workbench/contrib/testing/browser/testingOutputTerminalService'; import { testingPeekBorder } from 'vs/workbench/contrib/testing/browser/theme'; import { AutoOpenPeekViewWhen, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration'; import { Testing } from 'vs/workbench/contrib/testing/common/constants'; -import { ITestItem, ITestMessage, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection'; +import { IRichLocation, ITestItem, ITestMessage, ITestRunTask, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection'; import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys'; import { isFailedState } from 'vs/workbench/contrib/testing/common/testingStates'; import { buildTestUri, parseTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri'; -import { ITestResult, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult'; +import { getPathForTestInResult, ITestResult, maxCountPriority, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult'; import { ITestResultService, ResultChangeEvent } from 'vs/workbench/contrib/testing/common/testResultService'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; -interface ITestDto { - test: ITestItem, +class TestDto { + test: ITestItem; messageIndex: number; messages: ITestMessage[]; expectedUri: URI; actualUri: URI; messageUri: URI; + + constructor(resultId: string, test: TestResultItem, taskIndex: number, messageIndex: number) { + this.test = test.item; + this.messages = test.tasks[taskIndex].messages; + this.messageIndex = messageIndex; + + const parts = { messageIndex, resultId, taskIndex, testExtId: test.item.extId }; + this.expectedUri = buildTestUri({ ...parts, type: TestUriType.ResultExpectedOutput }); + this.actualUri = buildTestUri({ ...parts, type: TestUriType.ResultActualOutput }); + this.messageUri = buildTestUri({ ...parts, type: TestUriType.ResultMessage }); + } } export interface ITestingPeekOpener { @@ -235,19 +266,15 @@ export class TestingOutputPeekController extends Disposable implements IEditorCo return; } - const ctor = message.actualOutput !== undefined && message.expectedOutput !== undefined - ? TestingDiffOutputPeek : TestingMessageOutputPeek; - const isNew = !(this.peek.value instanceof ctor); - if (isNew) { - this.peek.value = this.instantiationService.createInstance(ctor, this.editor); + + if (!this.peek.value) { + this.peek.value = this.instantiationService.createInstance(TestingOutputPeek, this.editor); this.peek.value.onDidClose(() => { this.visible.set(false); this.currentPeekUri = undefined; this.peek.value = undefined; }); - } - if (isNew) { this.visible.set(true); this.peek.value!.create(); } @@ -268,7 +295,7 @@ export class TestingOutputPeekController extends Disposable implements IEditorCo * Removes the peek view if it's being displayed on the given test ID. */ public removeIfPeekingForTest(testId: string) { - if (this.peek.value?.currentTest()?.extId === testId) { + if (this.peek.value?.currentTest?.extId === testId) { this.peek.clear(); } } @@ -291,31 +318,30 @@ export class TestingOutputPeekController extends Disposable implements IEditorCo } } - private retrieveTest(uri: URI): ITestDto | undefined { + private retrieveTest(uri: URI): TestDto | undefined { const parts = parseTestUri(uri); if (!parts) { return undefined; } - const test = this.testResults.getResult(parts.resultId)?.getStateById(parts.testExtId); + const { resultId, testExtId, taskIndex, messageIndex } = parts; + const test = this.testResults.getResult(parts.resultId)?.getStateById(testExtId); if (!test || !test.tasks[parts.taskIndex]) { return; } - return test && { - test: test.item, - messages: test.tasks[parts.taskIndex].messages, - messageIndex: parts.messageIndex, - expectedUri: buildTestUri({ ...parts, type: TestUriType.ResultExpectedOutput }), - actualUri: buildTestUri({ ...parts, type: TestUriType.ResultActualOutput }), - messageUri: buildTestUri({ ...parts, type: TestUriType.ResultMessage }), - }; + return new TestDto(resultId, test, taskIndex, messageIndex); } } -abstract class TestingOutputPeek extends PeekViewWidget { - protected readonly model = new MutableDisposable(); - protected dimension?: dom.Dimension; +class TestingOutputPeek extends PeekViewWidget { + private readonly visibilityChange = this._disposables.add(new Emitter()); + private readonly didReveal = this._disposables.add(new Emitter()); + private dimension?: dom.Dimension; + private splitView!: SplitView; + private contentProviders!: IPeekOutputRenderer[]; + + public currentTest?: ITestItem; constructor( editor: ICodeEditor, @@ -329,7 +355,7 @@ abstract class TestingOutputPeek extends PeekViewWidget { TestingContextKeys.isInPeek.bindTo(contextKeyService); this._disposables.add(themeService.onDidColorThemeChange(this.applyTheme, this)); - this._disposables.add(this.model); + this._disposables.add(this.onDidClose(() => this.visibilityChange.fire(false))); this.applyTheme(themeService.getColorTheme()); peekViewService.addExclusiveWidget(editor, this); } @@ -345,23 +371,102 @@ abstract class TestingOutputPeek extends PeekViewWidget { }); } + protected override _fillBody(containerElement: HTMLElement): void { + this.splitView = new SplitView(containerElement, { orientation: Orientation.HORIZONTAL }); + + const messageContainer = dom.append(containerElement, dom.$('.test-output-peek-message-container')); + this.contentProviders = [ + this._disposables.add(this.instantiationService.createInstance(DiffContentProvider, this.editor, messageContainer)), + this._disposables.add(this.instantiationService.createInstance(MarkdownTestMessagePeek, messageContainer)), + this._disposables.add(this.instantiationService.createInstance(PlainTextMessagePeek, this.editor, messageContainer)), + ]; + + const treeContainer = dom.append(containerElement, dom.$('.test-output-peek-tree')); + const tree = this._disposables.add(this.instantiationService.createInstance( + OutputPeekTree, + treeContainer, + this.visibilityChange.event, + this.didReveal.event, + )); + + this.splitView.addView({ + onDidChange: Event.None, + element: messageContainer, + minimumSize: 200, + maximumSize: Number.MAX_VALUE, + layout: width => { + if (this.dimension) { + for (const provider of this.contentProviders) { + provider.layout({ height: this.dimension.height, width }); + } + } + }, + }, Sizing.Distribute); + + this.splitView.addView({ + onDidChange: Event.None, + element: treeContainer, + minimumSize: 100, + maximumSize: Number.MAX_VALUE, + layout: width => { + if (this.dimension) { + tree.layout(this.dimension.height, width); + } + }, + }, Sizing.Distribute); + } + /** * Updates the test to be shown. */ - public abstract setModel(dto: ITestDto): Promise; + public setModel(dto: TestDto): Promise { + const message = dto.messages[dto.messageIndex]; + if (!message?.location) { + return Promise.resolve(); + } + + this.currentTest = dto.test; + this.show(message.location.range, hintDiffPeekHeight(message)); + return this.showInPlace(dto); + } /** - * Returns the test whose data is currently shown in the peek view. + * Shows a message in-place without showing or changing the peek location. + * This is mostly used if peeking a message without a location. */ - public abstract currentTest(): ITestItem | undefined; + public async showInPlace(dto: TestDto) { + const message = dto.messages[dto.messageIndex]; + this.setTitle(firstLine(renderStringAsPlaintext(message.message)), dto.test.label); + this.didReveal.fire(dto); + this.visibilityChange.fire(true); + await Promise.all(this.contentProviders.map(p => p.update(dto, message))); + } - /** - * @override - */ + /** @override */ protected override _doLayoutBody(height: number, width: number) { super._doLayoutBody(height, width); this.dimension = new dom.Dimension(width, height); + this.splitView.layout(width); } + + /** @override */ + protected override _onWidth(width: number) { + super._onWidth(width); + if (this.dimension) { + this.dimension = new dom.Dimension(width, this.dimension.height); + } + + this.splitView.layout(width); + } +} + +interface IPeekOutputRenderer extends IDisposable { + /** Updates the displayed test. Should clear if it cannot display the test. */ + update(dto: TestDto, message: ITestMessage): void; + /** Recalculate content layout. */ + layout(dimension: dom.IDimension): void; + /** Dispose the content provider. */ + dispose(): void; } const commonEditorOptions: IEditorOptions = { @@ -392,64 +497,61 @@ const diffEditorOptions: IDiffEditorOptions = { modifiedAriaLabel: localize('testingOutputActual', 'Actual result'), }; -class TestingDiffOutputPeek extends TestingOutputPeek { - private readonly diff = this._disposables.add(new MutableDisposable()); - private test: ITestItem | undefined; +const isDiffable = (message: ITestMessage): message is ITestMessage & { actualOutput: string; expectedOutput: string } => + message.actualOutput !== undefined && message.expectedOutput !== undefined; - /** - * @override - */ - protected _fillBody(containerElement: HTMLElement): void { - const diffContainer = dom.append(containerElement, dom.$('div.preview.inline')); - const preview = this.diff.value = this.instantiationService.createInstance(EmbeddedDiffEditorWidget, diffContainer, diffEditorOptions, this.editor); +class DiffContentProvider extends Disposable implements IPeekOutputRenderer { + private readonly widget = this._register(new MutableDisposable()); + private readonly model = this._register(new MutableDisposable()); + private dimension?: dom.IDimension; - if (this.dimension) { - preview.layout(this.dimension); - } + constructor( + private readonly editor: ICodeEditor, + private readonly container: HTMLElement, + @IInstantiationService private readonly instantiationService: IInstantiationService, + @ITextModelService private readonly modelService: ITextModelService, + ) { + super(); } - /** - * @override - */ - public async setModel({ test, messages, messageIndex, expectedUri, actualUri }: ITestDto) { - const message = messages[messageIndex]; - if (!message?.location) { - return; + public async update({ expectedUri, actualUri }: TestDto, message: ITestMessage) { + if (!isDiffable(message)) { + return this.clear(); } - this.test = test; - this.show(message.location.range, hintDiffPeekHeight(message)); - this.setTitle(firstLine(renderStringAsPlaintext(message.message)), test.label); - const [original, modified] = await Promise.all([ this.modelService.createModelReference(expectedUri), this.modelService.createModelReference(actualUri), ]); const model = this.model.value = new SimpleDiffEditorModel(original, modified); - if (!this.diff.value) { - this.model.value = undefined; - } else { - this.diff.value.setModel(model); - this.diff.value.updateOptions(this.getOptions( - isMultiline(message.expectedOutput) || isMultiline(message.actualOutput) - )); + if (!this.widget.value) { + this.widget.value = this.instantiationService.createInstance( + EmbeddedDiffEditorWidget, + this.container, + diffEditorOptions, + this.editor, + ); + + if (this.dimension) { + this.widget.value.layout(this.dimension); + } } + + this.widget.value.setModel(model); + this.widget.value.updateOptions(this.getOptions( + isMultiline(message.expectedOutput) || isMultiline(message.actualOutput) + )); } - /** - * @override - */ - public currentTest() { - return this.test; + private clear() { + this.model.clear(); + this.widget.clear(); } - /** - * @override - */ - protected override _doLayoutBody(height: number, width: number) { - super._doLayoutBody(height, width); - this.diff.value?.layout(this.dimension); + public layout(dimensions: dom.IDimension) { + this.dimension = dimensions; + this.widget.value?.layout(dimensions); } protected getOptions(isMultiline: boolean): IDiffEditorOptions { @@ -486,89 +588,85 @@ class ScrollableMarkdownMessage extends Disposable { } } -class TestingMessageOutputPeek extends TestingOutputPeek { - private readonly editorPreview = this._disposables.add(new MutableDisposable()); - private readonly textPreview = this._disposables.add(new MutableDisposable()); - private test: ITestItem | undefined; +class MarkdownTestMessagePeek extends Disposable implements IPeekOutputRenderer { private readonly markdown = new Lazy( - () => this._disposables.add(this.instantiationService.createInstance(MarkdownRenderer, {})), + () => this._register(this.instantiationService.createInstance(MarkdownRenderer, {})), ); - /** - * @override - */ - protected _fillBody(containerElement: HTMLElement): void { - const diffContainer = dom.append(containerElement, dom.$('div.preview.editor')); - const preview = this.editorPreview.value = this.instantiationService.createInstance( - EmbeddedCodeEditorWidget, - diffContainer, - commonEditorOptions, - this.editor, - ); + private readonly textPreview = this._register(new MutableDisposable()); - if (this.dimension) { - preview.layout(this.dimension); - } + constructor(private readonly container: HTMLElement, @IInstantiationService private readonly instantiationService: IInstantiationService) { + super(); } - /** - * @override - */ - public async setModel({ messages, test, messageIndex, messageUri }: ITestDto) { - const message = messages[messageIndex]; - if (!message?.location) { - return; + public update(_dto: TestDto, message: ITestMessage): void { + if (isDiffable(message) || typeof message.message === 'string') { + return this.textPreview.clear(); } - this.test = test; + this.textPreview.value = new ScrollableMarkdownMessage( + this.container, + this.markdown.getValue(), + message.message as IMarkdownString, + ); + } - const messageStr = renderStringAsPlaintext(message.message); - const isMarkdown = typeof message.message !== 'string'; - const hintedHeight = hintPeekStrHeight(messageStr); - // We can't estimate markdown message sizes as well, make sure it's - // reasonably big for them. - this.show(message.location.range, isMarkdown ? Math.max(hintedHeight, 7) : hintedHeight); - this.setTitle(firstLine(messageStr), test.label); + public layout(): void { + // no-op + } +} - if (isMarkdown) { - this.model.clear(); - this.textPreview.value = new ScrollableMarkdownMessage( - this._bodyElement!, - this.markdown.getValue(), - message.message as IMarkdownString, +class PlainTextMessagePeek extends Disposable implements IPeekOutputRenderer { + private readonly widget = this._register(new MutableDisposable()); + private readonly model = this._register(new MutableDisposable()); + private dimension?: dom.IDimension; + + constructor( + private readonly editor: ICodeEditor, + private readonly container: HTMLElement, + @IInstantiationService private readonly instantiationService: IInstantiationService, + @ITextModelService private readonly modelService: ITextModelService, + ) { + super(); + } + + public async update({ messageUri }: TestDto, message: ITestMessage) { + if (isDiffable(message) || typeof message.message !== 'string') { + return this.clear(); + } + + const modelRef = this.model.value = await this.modelService.createModelReference(messageUri); + if (!this.widget.value) { + this.widget.value = this.instantiationService.createInstance( + EmbeddedCodeEditorWidget, + this.container, + commonEditorOptions, + this.editor, ); - } else { - this.textPreview.clear(); - const modelRef = this.model.value = await this.modelService.createModelReference(messageUri); - if (this.editorPreview.value) { - this.editorPreview.value.setModel(modelRef.object.textEditorModel); - this.editorPreview.value.updateOptions(this.getOptions(isMultiline(messageStr))); - } else { - this.model.value = undefined; + + if (this.dimension) { + this.widget.value.layout(this.dimension); } } + + this.widget.value.setModel(modelRef.object.textEditorModel); + this.widget.value.updateOptions(this.getOptions(isMultiline(message.message))); } - /** - * @override - */ - public currentTest() { - return this.test; + private clear() { + this.model.clear(); + this.widget.clear(); } - /** - * @override - */ - protected override _doLayoutBody(height: number, width: number) { - super._doLayoutBody(height, width); - this.editorPreview.value?.layout(this.dimension); - this.textPreview.value?.layout(height, width); + public layout(dimensions: dom.IDimension) { + this.dimension = dimensions; + this.widget.value?.layout(dimensions); } - protected getOptions(isMultiline: boolean): IEditorOptions { + protected getOptions(isMultiline: boolean): IDiffEditorOptions { return isMultiline - ? { ...commonEditorOptions, lineNumbers: 'on' } - : { ...commonEditorOptions, lineNumbers: 'off' }; + ? { ...diffEditorOptions, lineNumbers: 'on' } + : { ...diffEditorOptions, lineNumbers: 'off' }; } } @@ -581,7 +679,7 @@ const firstLine = (str: string) => { }; const isMultiline = (str: string | undefined) => !!str && str.includes('\n'); -const hintPeekStrHeight = (str: string | undefined) => clamp(count(str || '', '\n'), 5, 20); +const hintPeekStrHeight = (str: string | undefined) => clamp(count(str || '', '\n'), 8, 20); class SimpleDiffEditorModel extends EditorModel { public readonly original = this._original.object.textEditorModel; @@ -635,3 +733,455 @@ export class CloseTestPeek extends EditorAction2 { TestingOutputPeekController.get(parent ?? editor).removePeek(); } } + +interface ITreeElement { + type: string; + context: unknown; + id: string; + label: string; + icon?: ThemeIcon; + description?: string; + ariaLabel?: string; +} + +export class TestResultElement implements ITreeElement { + public readonly type = 'result'; + public readonly context = this.value.id; + public readonly id = this.value.id; + public readonly label = this.value.name; + + public get icon() { + return testingStatesToIcons.get( + this.value.completedAt === undefined + ? TestResultState.Running + : maxCountPriority(this.value.counts) + ); + } + + constructor(public readonly value: ITestResult) { } +} + +export class TestCaseElement implements ITreeElement { + public readonly type = 'test'; + public readonly context = this.value.item.extId; + public readonly id = `${this.results.id}/${this.value.item.extId}`; + public readonly label = this.value.item.label; + public readonly description?: string; + + public get icon() { + return testingStatesToIcons.get(this.value.computedState); + } + + public get path() { + return getPathForTestInResult(this.value, this.results); + } + + constructor( + private readonly results: ITestResult, + public readonly value: TestResultItem, + ) { + for (const parent of this.parents()) { + this.description = this.description + ? parent.item.label + flatTestItemDelimiter + this.description + : parent.item.label; + } + } + + private *parents() { + for ( + let parent = this.value.parent && this.results.getStateById(this.value.parent); + parent; + parent = parent.parent && this.results.getStateById(parent.parent) + ) { + yield parent; + } + } +} + +class TestTaskElement implements ITreeElement { + public readonly type = 'task'; + public readonly task: ITestRunTask; + public readonly context: string; + public readonly id: string; + public readonly label: string; + public readonly icon = undefined; + + public get path() { + return getPathForTestInResult(this.test, this.results); + } + + constructor(private readonly results: ITestResult, private readonly test: TestResultItem, index: number) { + this.id = `${results.id}/${test.item.extId}/${index}`; + this.task = results.tasks[index]; + this.context = String(index); + this.label = this.task.name ?? localize('testUnnamedTask', 'Unnamed Task'); + } +} + +class TestMessageElement implements ITreeElement { + public readonly type = 'message'; + public readonly context: URI; + public readonly id: string; + public readonly label: string; + public readonly icon: ThemeIcon | undefined; + public readonly uri: URI; + public readonly location: IRichLocation | undefined; + + constructor( + public readonly result: ITestResult, + public readonly test: TestResultItem, + public readonly taskIndex: number, + public readonly messageIndex: number, + ) { + const { message, severity, location } = test.tasks[taskIndex].messages[messageIndex]; + + this.location = location; + this.uri = this.context = buildTestUri({ + type: TestUriType.ResultMessage, + messageIndex, + resultId: result.id, + taskIndex, + testExtId: test.item.extId + }); + + this.id = this.uri.toString(); + this.label = firstLine(renderStringAsPlaintext(message)); + this.icon = testMessageSeverityToIcons.get(severity); + } +} + +type TreeElement = TestResultElement | TestCaseElement | TestMessageElement | TestTaskElement; + +class OutputPeekTree extends Disposable { + private readonly tree: WorkbenchCompressibleObjectTree; + private readonly treeActions: TreeActionsProvider; + + constructor( + container: HTMLElement, + onDidChangeVisibility: Event, + onDidReveal: Event, + peekController: TestingOutputPeek, + @IContextMenuService private readonly contextMenuService: IContextMenuService, + @ITestResultService results: ITestResultService, + @IInstantiationService instantiationService: IInstantiationService, + @IEditorService editorService: IEditorService, + ) { + super(); + + this.treeActions = instantiationService.createInstance(TreeActionsProvider); + const labels = instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility }); + const diffIdentityProvider: IIdentityProvider = { + getId(e: TreeElement) { + return e.id; + } + }; + + this.tree = this._register(instantiationService.createInstance( + WorkbenchCompressibleObjectTree, + 'Test Output Peek', + container, + { + getHeight: () => 22, + getTemplateId: () => TestRunElementRenderer.ID, + }, + [instantiationService.createInstance(TestRunElementRenderer, labels, this.treeActions)], + { + compressionEnabled: true, + hideTwistiesOfChildlessElements: true, + identityProvider: diffIdentityProvider, + accessibilityProvider: { + getAriaLabel(element: ITreeElement) { + return element.ariaLabel || element.label; + }, + getWidgetAriaLabel() { + return localize('testingPeekLabel', 'Test Result Messages'); + } + } + }, + )) as WorkbenchCompressibleObjectTree; + + const creationCache = new WeakMap(); + const cachedCreate = (ref: object, factory: () => T): TreeElement => { + const existing = creationCache.get(ref); + if (existing) { + return existing; + } + + const fresh = factory(); + creationCache.set(ref, fresh); + return fresh; + }; + + const getTaskChildren = (result: ITestResult, test: TestResultItem, taskId: number): Iterable> => { + return Iterable.map(test.tasks[0].messages, (m, messageIndex) => ({ + element: cachedCreate(m, () => new TestMessageElement(result, test, taskId, messageIndex)), + incompressible: true, + })); + }; + + const getTestChildren = (result: ITestResult, test: TestResultItem): Iterable> => { + const tasks = Iterable.filter(test.tasks, task => task.messages.length > 0); + return Iterable.map(tasks, (t, taskId) => ({ + element: cachedCreate(t, () => new TestTaskElement(result, test, taskId)), + incompressible: false, + children: getTaskChildren(result, test, taskId), + })); + }; + + const getResultChildren = (result: ITestResult): Iterable> => { + const tests = Iterable.filter(result.tests, test => test.tasks.some(t => t.messages.length > 0)); + return Iterable.map(tests, test => ({ + element: cachedCreate(test, () => new TestCaseElement(result, test)), + incompressible: true, + children: getTestChildren(result, test), + })); + }; + + const getRootChildren = () => results.results.map(result => ({ + element: cachedCreate(result, () => new TestResultElement(result)), + incompressible: true, + collapsed: true, + children: getResultChildren(result) + })); + + this._register(results.onTestChanged(e => { + const itemNode = creationCache.get(e.item); + if (itemNode && this.tree.hasElement(itemNode)) { // update to existing test message/state + this.tree.setChildren(itemNode, getTestChildren(e.result, e.item)); + return; + } + + const resultNode = creationCache.get(e.result); + if (resultNode && this.tree.hasElement(resultNode)) { // new test + this.tree.setChildren(null, getRootChildren(), { diffIdentityProvider }); + return; + } + + // should be unreachable? + this.tree.setChildren(null, getRootChildren(), { diffIdentityProvider }); + })); + + this._register(results.onResultsChanged(e => { + if ('completed' in e) { + const resultNode = creationCache.get(e.completed); + if (resultNode && this.tree.hasElement(resultNode)) { + this.tree.setChildren(resultNode, getResultChildren(e.completed)); + return; + } + } + + this.tree.setChildren(null, getRootChildren(), { diffIdentityProvider }); + })); + + this._register(onDidReveal(dto => { + const messageNode = creationCache.get(dto.messages[dto.messageIndex]); + if (!messageNode || !this.tree.hasElement(messageNode)) { + return; + } + + const parents: TreeElement[] = []; + for (let parent = this.tree.getParentElement(messageNode); parent; parent = this.tree.getParentElement(parent)) { + parents.unshift(parent); + } + + for (const parent of parents) { + this.tree.expand(parent); + } + + if (this.tree.getRelativeTop(messageNode) === null) { + this.tree.reveal(messageNode, 0.5); + } + + this.tree.setFocus([messageNode]); + this.tree.setSelection([messageNode]); + })); + + this._register(this.tree.onDidOpen(async e => { + if (!(e.element instanceof TestMessageElement)) { + return; + } + + const location = e.element.location; + if (!location) { + peekController.showInPlace(new TestDto(e.element.result.id, e.element.test, e.element.taskIndex, e.element.messageIndex)); + return; + } + + const pane = await editorService.openEditor({ + resource: location.uri, + options: { + pinned: e.editorOptions.pinned, + selection: location.range, + preserveFocus: e.editorOptions.preserveFocus, + }, + }, e.sideBySide ? SIDE_GROUP : ACTIVE_GROUP); + + const control = pane?.getControl(); + if (isCodeEditor(control)) { + TestingOutputPeekController.get(control).show(e.element.uri); + } + })); + + + this._register(this.tree.onContextMenu(e => this.onContextMenu(e))); + + this.tree.setChildren(null, getRootChildren()); + } + + public layout(height: number, width: number) { + this.tree.layout(height, width); + } + + private onContextMenu(evt: ITreeContextMenuEvent) { + if (!evt.element) { + return; + } + + const actions = this.treeActions.provideActionBar(evt.element); + this.contextMenuService.showContextMenu({ + getAnchor: () => evt.anchor, + getActions: () => actions.value.secondary.length + ? [...actions.value.primary, new Separator(), ...actions.value.secondary] + : actions.value.primary, + getActionsContext: () => evt.element?.context, + onHide: () => actions.dispose(), + }); + } +} + +interface TemplateData { + label: IResourceLabel; + icon: HTMLElement; + actionBar: ActionBar; + elementDisposable: DisposableStore; + templateDisposable: DisposableStore; +} + +class TestRunElementRenderer implements ICompressibleTreeRenderer { + public static readonly ID = 'testRunElementRenderer'; + public readonly templateId = TestRunElementRenderer.ID; + + constructor( + private readonly labels: ResourceLabels, + private readonly treeActions: TreeActionsProvider, + @IInstantiationService private readonly instantiationService: IInstantiationService, + ) { } + + /** @inheritdoc */ + public renderCompressedElements(node: ITreeNode, FuzzyScore>, _index: number, templateData: TemplateData): void { + const chain = node.element.elements; + const lastElement = chain[chain.length - 1]; + if (lastElement instanceof TestTaskElement && chain.length >= 2) { + this.doRender(chain[chain.length - 2], templateData); + } else { + this.doRender(lastElement, templateData); + } + } + + /** @inheritdoc */ + public renderTemplate(container: HTMLElement): TemplateData { + const templateDisposable = new DisposableStore(); + const wrapper = dom.append(container, dom.$('.test-peek-item')); + const icon = dom.append(wrapper, dom.$('.state')); + const name = dom.append(wrapper, dom.$('.name')); + + const label = this.labels.create(name, { supportHighlights: true }); + templateDisposable.add(label); + + const actionBar = new ActionBar(wrapper, { + actionViewItemProvider: action => + action instanceof MenuItemAction + ? this.instantiationService.createInstance(MenuEntryActionViewItem, action) + : undefined + }); + + templateDisposable.add(actionBar); + + return { + icon, + label, + actionBar, + elementDisposable: new DisposableStore(), + templateDisposable, + }; + } + + /** @inheritdoc */ + public renderElement(element: ITreeNode, _index: number, templateData: TemplateData): void { + this.doRender(element.element, templateData); + } + + /** @inheritdoc */ + public disposeTemplate(templateData: TemplateData): void { + templateData.templateDisposable.dispose(); + } + + private doRender(element: ITreeElement, templateData: TemplateData) { + templateData.elementDisposable.clear(); + templateData.label.setLabel(element.label, element.description); + + const icon = element.icon; + templateData.icon.className = `computed-state ${icon ? ThemeIcon.asClassName(icon) : ''}`; + + const actions = this.treeActions.provideActionBar(element); + templateData.elementDisposable.add(actions); + templateData.actionBar.clear(); + templateData.actionBar.context = element; + templateData.actionBar.push(actions.value.primary, { icon: true, label: false }); + } +} + +class TreeActionsProvider { + constructor( + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @ITestingOutputTerminalService private readonly testTerminalService: ITestingOutputTerminalService, + @IMenuService private readonly menuService: IMenuService, + @ICommandService private readonly commandService: ICommandService, + ) { } + + public provideActionBar(element: ITreeElement) { + const test = element instanceof TestCaseElement ? element.value : undefined; + const contextOverlay = this.contextKeyService.createOverlay([ + ['view', Testing.OutputPeekContributionId], + [TestingContextKeys.peekItemType.key, element.type], + [TestingContextKeys.testItemExtId.key, test?.item.extId], + [TestingContextKeys.testItemHasUri.key, !!test?.item.uri], + [TestingContextKeys.hasDebuggableTests.key, test?.item.debuggable], + [TestingContextKeys.hasRunnableTests.key, test?.item.debuggable], + ]); + const menu = this.menuService.createMenu(MenuId.TestPeekElement, contextOverlay); + + try { + const primary: IAction[] = []; + const secondary: IAction[] = []; + + if (element instanceof TestResultElement) { + primary.push(new Action( + 'testing.showResultOutput', + localize('testing.showResultOutput', "Show Result Output"), + Codicon.terminal.classNames, + undefined, + () => this.testTerminalService.open(element.value) + )); + } + + if (element instanceof TestCaseElement || element instanceof TestTaskElement) { + primary.push(new Action( + 'testing.revealInExplorer', + localize('testing.revealInExplorer', "Reveal in Test Explorer"), + Codicon.listTree.classNames, + undefined, + () => this.commandService.executeCommand('vscode.revealTestInExplorer', element.path), + )); + } + const result = { primary, secondary }; + const actionsDisposable = createAndFillInActionBarActions(menu, { + shouldForwardArgs: true, + }, result, 'inline'); + + return { value: result, dispose: () => actionsDisposable.dispose }; + } finally { + menu.dispose(); + } + } +} diff --git a/src/vs/workbench/contrib/testing/common/testCollection.ts b/src/vs/workbench/contrib/testing/common/testCollection.ts index 55c05ea8fd1..8bdf7e1ee5b 100644 --- a/src/vs/workbench/contrib/testing/common/testCollection.ts +++ b/src/vs/workbench/contrib/testing/common/testCollection.ts @@ -171,6 +171,8 @@ export interface ISerializedTestResults { items: SerializedTestResultItem[]; /** Tasks involved in the run. */ tasks: ITestRunTask[]; + /** Human-readable name of the test run. */ + name: string; } export const enum TestDiffOpType { diff --git a/src/vs/workbench/contrib/testing/common/testResult.ts b/src/vs/workbench/contrib/testing/common/testResult.ts index bfb75fcd54a..e6dedb9d31a 100644 --- a/src/vs/workbench/contrib/testing/common/testResult.ts +++ b/src/vs/workbench/contrib/testing/common/testResult.ts @@ -9,6 +9,7 @@ import { Lazy } from 'vs/base/common/lazy'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { Range } from 'vs/editor/common/core/range'; +import { localize } from 'vs/nls'; import { TestResultState } from 'vs/workbench/api/common/extHostTypes'; import { IComputedStateAccessor, refreshComputedState } from 'vs/workbench/contrib/testing/common/getComputedState'; import { ExtensionRunTestsRequest, ISerializedTestResults, ITestItem, ITestMessage, ITestRunTask, ITestTaskState, RunTestsRequest, TestIdPath, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection'; @@ -36,6 +37,11 @@ export interface ITestResult { */ readonly isAutoRun?: boolean; + /** + * Human-readable name of the test result. + */ + readonly name: string; + /** * Gets all tests involved in the run. */ @@ -103,6 +109,16 @@ export const sumCounts = (counts: Iterable) => { return total; }; +export const maxCountPriority = (counts: Readonly) => { + for (const state of statesInOrder) { + if (counts[state] > 0) { + return state; + } + } + + return TestResultState.Unset; +}; + /** * Deals with output of a {@link LiveTestResult}. By default we pass-through * data into the underlying write stream, but if a client requests to read it @@ -225,6 +241,7 @@ export class LiveTestResult implements ITestResult { public readonly onChange = this.changeEmitter.event; public readonly onComplete = this.completeEmitter.event; public readonly tasks: ITestRunTask[] = []; + public readonly name = localize('runFinished', 'Test run at {0}', new Date().toLocaleString()); /** * Test IDs directly included in this run. @@ -505,6 +522,7 @@ export class LiveTestResult implements ITestResult { id: this.id, completedAt: this.completedAt!, tasks: this.tasks, + name: this.name, items: [...this.testById.values()].map(entry => ({ ...entry, retired: undefined, @@ -545,6 +563,11 @@ export class HydratedTestResult implements ITestResult { return this.testById.values(); } + /** + * @inheritdoc + */ + public readonly name: string; + private readonly testById = new Map(); constructor( @@ -555,6 +578,7 @@ export class HydratedTestResult implements ITestResult { this.id = serialized.id; this.completedAt = serialized.completedAt; this.tasks = serialized.tasks; + this.name = serialized.name; for (const item of serialized.items) { const cast: TestResultItem = { ...item, retired: true }; diff --git a/src/vs/workbench/contrib/testing/common/testingContextKeys.ts b/src/vs/workbench/contrib/testing/common/testingContextKeys.ts index 797eb97ded6..b373dc35c01 100644 --- a/src/vs/workbench/contrib/testing/common/testingContextKeys.ts +++ b/src/vs/workbench/contrib/testing/common/testingContextKeys.ts @@ -20,6 +20,10 @@ export namespace TestingContextKeys { export const explorerLocation = new RawContextKey('testing.explorerLocation', ViewContainerLocation.Sidebar); export const autoRun = new RawContextKey('testing.autoRun', false); + export const peekItemType = new RawContextKey('peekItemType', undefined, { + type: 'string', + description: localize('testing.peekItemType', 'Type of the item in the output peek view. Either a "test", "message", "task", or "result".'), + }); export const testItemExtId = new RawContextKey('testId', undefined, { type: 'string', description: localize('testing.testId', 'ID of the current test item, set when creating or opening menus on test items') diff --git a/src/vs/workbench/contrib/testing/test/common/testResultService.test.ts b/src/vs/workbench/contrib/testing/test/common/testResultService.test.ts index 04925971647..e37902c0f07 100644 --- a/src/vs/workbench/contrib/testing/test/common/testResultService.test.ts +++ b/src/vs/workbench/contrib/testing/test/common/testResultService.test.ts @@ -257,6 +257,7 @@ suite('Workbench - Test Results Service', () => { completedAt, id: 'some-id', tasks: [{ id: 't', running: false, name: undefined }], + name: 'hello world', items: [{ ...(await getInitializedMainTestCollection()).getNodeById('id-a')!, tasks: [{ state, duration: 0, messages: [] }], From 2521499104bb2067e78604666aa45eb843760daa Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Tue, 25 May 2021 18:06:51 -0700 Subject: [PATCH 099/140] testing: add clear test button to peek view title --- src/vs/platform/actions/common/actions.ts | 1 + .../testing/browser/testExplorerActions.ts | 6 ++++- .../testing/browser/testingOutputPeek.ts | 23 +++++++++++++++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 2bdb2c70b32..e85f9204b49 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -128,6 +128,7 @@ export class MenuId { static readonly StatusBarRemoteIndicatorMenu = new MenuId('StatusBarRemoteIndicatorMenu'); static readonly TestItem = new MenuId('TestItem'); static readonly TestPeekElement = new MenuId('TestPeekElement'); + static readonly TestPeekTitle = new MenuId('TestPeekTitle'); static readonly TouchBarContext = new MenuId('TouchBarContext'); static readonly TitleBarContext = new MenuId('TitleBarContext'); static readonly TunnelContext = new MenuId('TunnelContext'); diff --git a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts index f69b298ea1c..e5662ce40e2 100644 --- a/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts +++ b/src/vs/workbench/contrib/testing/browser/testExplorerActions.ts @@ -579,7 +579,11 @@ export class ClearTestResultsAction extends Action2 { id: ClearTestResultsAction.ID, title: localize('testing.clearResults', "Clear All Results"), category, - f1: true + f1: true, + icon: Codicon.trash, + menu: { + id: MenuId.TestPeekTitle, + }, }); } diff --git a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts index 9d830df192c..80e1c124015 100644 --- a/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts +++ b/src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts @@ -237,7 +237,7 @@ export class TestingOutputPeekController extends Disposable implements IEditorCo super(); this.visible = TestingContextKeys.isPeekVisible.bindTo(contextKeyService); this._register(editor.onDidChangeModel(() => this.peek.clear())); - this._register(testResults.onResultsChanged(this.closePeekOnRunStart, this)); + this._register(testResults.onResultsChanged(this.closePeekOnCertainResultEvents, this)); this._register(testResults.onTestChanged(this.closePeekOnTestChange, this)); } @@ -312,9 +312,13 @@ export class TestingOutputPeekController extends Disposable implements IEditorCo this.removeIfPeekingForTest(evt.item.item.extId); } - private closePeekOnRunStart(evt: ResultChangeEvent) { + private closePeekOnCertainResultEvents(evt: ResultChangeEvent) { if ('started' in evt) { - this.peek.clear(); + this.peek.clear(); // close peek when runs start + } + + if ('removed' in evt && this.testResults.results.length === 0) { + this.peek.clear(); // close the peek if results are cleared } } @@ -347,7 +351,8 @@ class TestingOutputPeek extends PeekViewWidget { editor: ICodeEditor, @IThemeService themeService: IThemeService, @IPeekViewService peekViewService: IPeekViewService, - @IContextKeyService contextKeyService: IContextKeyService, + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IMenuService private readonly menuService: IMenuService, @IInstantiationService instantiationService: IInstantiationService, @ITextModelService protected readonly modelService: ITextModelService, ) { @@ -371,6 +376,16 @@ class TestingOutputPeek extends PeekViewWidget { }); } + protected override _fillHead(container: HTMLElement): void { + super._fillHead(container); + + const actions: IAction[] = []; + const menu = this.menuService.createMenu(MenuId.TestPeekTitle, this.contextKeyService); + createAndFillInActionBarActions(menu, undefined, actions); + this._actionbarWidget!.push(actions, { label: false, icon: true, index: 0 }); + menu.dispose(); + } + protected override _fillBody(containerElement: HTMLElement): void { this.splitView = new SplitView(containerElement, { orientation: Orientation.HORIZONTAL }); From 7d50ce2061e363b4f507d92e3921a7f763cc4f60 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Tue, 25 May 2021 18:07:55 -0700 Subject: [PATCH 100/140] fix tests --- .../contrib/testing/test/common/testResultStorage.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/testing/test/common/testResultStorage.test.ts b/src/vs/workbench/contrib/testing/test/common/testResultStorage.test.ts index 074c4cf3cff..ef4c7c73820 100644 --- a/src/vs/workbench/contrib/testing/test/common/testResultStorage.test.ts +++ b/src/vs/workbench/contrib/testing/test/common/testResultStorage.test.ts @@ -75,7 +75,7 @@ suite('Workbench - Test Result Storage', () => { test('limits stored result by budget', async () => { const r = range(100).map(() => makeResult('a'.repeat(2048))); await storage.persist(r); - await assertStored(r.slice(0, 44)); + await assertStored(r.slice(0, 43)); }); test('always stores the min number of results', async () => { From 24a23a8ea056c830a6edbffa99bec03a1239a291 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 25 May 2021 18:18:47 -0700 Subject: [PATCH 101/140] Mark array params in vscode.d.ts readonly (#124599) I recently ran into an issue where I was trying to call showQuickPick with a readonly array. This is currently not allowed, even though `showQuickPick` never mutates the input This change marks a few places in `vscode.d.ts` where we take arrays as parameters as `readonly []`. It also caught a potential bug with`getSession` modifying the input array --- src/vs/vscode.d.ts | 26 +++++++++---------- .../workbench/api/common/extHost.api.impl.ts | 6 ++--- .../workbench/api/common/extHost.protocol.ts | 2 +- .../api/common/extHostAuthentication.ts | 8 +++--- .../api/common/extHostDebugService.ts | 4 +-- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 6ba49ea6a25..bf2d13e456f 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1163,7 +1163,7 @@ declare module 'vscode' { * @param decorationType A decoration type. * @param rangesOrOptions Either {@link Range ranges} or more detailed {@link DecorationOptions options}. */ - setDecorations(decorationType: TextEditorDecorationType, rangesOrOptions: Range[] | DecorationOptions[]): void; + setDecorations(decorationType: TextEditorDecorationType, rangesOrOptions: readonly Range[] | readonly DecorationOptions[]): void; /** * Scroll as indicated by `revealType` in order to reveal the given range. @@ -6015,7 +6015,7 @@ declare module 'vscode' { * * @param keys The set of keys whose values are synced. */ - setKeysForSync(keys: string[]): void; + setKeysForSync(keys: readonly string[]): void; }; /** @@ -8631,7 +8631,7 @@ declare module 'vscode' { * @param token A token that can be used to signal cancellation. * @return A promise that resolves to the selected items or `undefined`. */ - export function showQuickPick(items: string[] | Thenable, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Thenable; + export function showQuickPick(items: readonly string[] | Thenable, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Thenable; /** * Shows a selection list. @@ -8641,7 +8641,7 @@ declare module 'vscode' { * @param token A token that can be used to signal cancellation. * @return A promise that resolves to the selection or `undefined`. */ - export function showQuickPick(items: string[] | Thenable, options?: QuickPickOptions, token?: CancellationToken): Thenable; + export function showQuickPick(items: readonly string[] | Thenable, options?: QuickPickOptions, token?: CancellationToken): Thenable; /** * Shows a selection list allowing multiple selections. @@ -8651,7 +8651,7 @@ declare module 'vscode' { * @param token A token that can be used to signal cancellation. * @return A promise that resolves to the selected items or `undefined`. */ - export function showQuickPick(items: T[] | Thenable, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Thenable; + export function showQuickPick(items: readonly T[] | Thenable, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Thenable; /** * Shows a selection list. @@ -8661,7 +8661,7 @@ declare module 'vscode' { * @param token A token that can be used to signal cancellation. * @return A promise that resolves to the selected item or `undefined`. */ - export function showQuickPick(items: T[] | Thenable, options?: QuickPickOptions, token?: CancellationToken): Thenable; + export function showQuickPick(items: readonly T[] | Thenable, options?: QuickPickOptions, token?: CancellationToken): Thenable; /** * Shows a selection list of {@link workspace.workspaceFolders workspace folders} to pick from. @@ -12167,13 +12167,13 @@ declare module 'vscode' { * Add breakpoints. * @param breakpoints The breakpoints to add. */ - export function addBreakpoints(breakpoints: Breakpoint[]): void; + export function addBreakpoints(breakpoints: readonly Breakpoint[]): void; /** * Remove breakpoints. * @param breakpoints The breakpoints to remove. */ - export function removeBreakpoints(breakpoints: Breakpoint[]): void; + export function removeBreakpoints(breakpoints: readonly Breakpoint[]): void; /** * Converts a "Source" descriptor object received via the Debug Adapter Protocol into a Uri that can be used to load its contents. @@ -12512,7 +12512,7 @@ declare module 'vscode' { * @param range The range the comment thread is located within the document. * @param comments The ordered comments of the thread. */ - createCommentThread(uri: Uri, range: Range, comments: Comment[]): CommentThread; + createCommentThread(uri: Uri, range: Range, comments: readonly Comment[]): CommentThread; /** * Optional reaction handler for creating and deleting reactions on a {@link Comment}. @@ -12687,7 +12687,7 @@ declare module 'vscode' { * these permissions, otherwise all sessions should be returned. * @returns A promise that resolves to an array of authentication sessions. */ - getSessions(scopes?: string[]): Thenable>; + getSessions(scopes?: readonly string[]): Thenable>; /** * Prompts a user to login. @@ -12702,7 +12702,7 @@ declare module 'vscode' { * @param scopes A list of scopes, permissions, that the new session should be created with. * @returns A promise that resolves to an authentication session. */ - createSession(scopes: string[]): Thenable; + createSession(scopes: readonly string[]): Thenable; /** * Removes the session corresponding to session id. @@ -12733,7 +12733,7 @@ declare module 'vscode' { * @param options The {@link GetSessionOptions} to use * @returns A thenable that resolves to an authentication session */ - export function getSession(providerId: string, scopes: string[], options: AuthenticationGetSessionOptions & { createIfNone: true }): Thenable; + export function getSession(providerId: string, scopes: readonly string[], options: AuthenticationGetSessionOptions & { createIfNone: true }): Thenable; /** * Get an authentication session matching the desired scopes. Rejects if a provider with providerId is not @@ -12748,7 +12748,7 @@ declare module 'vscode' { * @param options The {@link GetSessionOptions} to use * @returns A thenable that resolves to an authentication session if available, or undefined if there are no sessions */ - export function getSession(providerId: string, scopes: string[], options?: AuthenticationGetSessionOptions): Thenable; + export function getSession(providerId: string, scopes: readonly string[], options?: AuthenticationGetSessionOptions): Thenable; /** * An {@link Event} which fires when the authentication sessions of an authentication provider have diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 9463dbd723f..05e4c4a1d1d 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -219,7 +219,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I })(); const authentication: typeof vscode.authentication = { - getSession(providerId: string, scopes: string[], options?: vscode.AuthenticationGetSessionOptions) { + getSession(providerId: string, scopes: readonly string[], options?: vscode.AuthenticationGetSessionOptions) { return extHostAuthentication.getSession(extension, providerId, scopes, options as any); }, get onDidChangeSessions(): Event { @@ -998,10 +998,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I stopDebugging(session?: vscode.DebugSession) { return extHostDebugService.stopDebugging(session); }, - addBreakpoints(breakpoints: vscode.Breakpoint[]) { + addBreakpoints(breakpoints: readonly vscode.Breakpoint[]) { return extHostDebugService.addBreakpoints(breakpoints); }, - removeBreakpoints(breakpoints: vscode.Breakpoint[]) { + removeBreakpoints(breakpoints: readonly vscode.Breakpoint[]) { return extHostDebugService.removeBreakpoints(breakpoints); }, asDebugSourceUri(source: vscode.DebugProtocolSource, session?: vscode.DebugSession): vscode.Uri { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 6f5283ef893..a9c6c7df8da 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -167,7 +167,7 @@ export interface MainThreadAuthenticationShape extends IDisposable { $unregisterAuthenticationProvider(id: string): void; $ensureProvider(id: string): Promise; $sendDidChangeSessions(providerId: string, event: modes.AuthenticationSessionsChangeEvent): void; - $getSession(providerId: string, scopes: string[], extensionId: string, extensionName: string, options: { createIfNone?: boolean, clearSessionPreference?: boolean }): Promise; + $getSession(providerId: string, scopes: readonly string[], extensionId: string, extensionName: string, options: { createIfNone?: boolean, clearSessionPreference?: boolean }): Promise; $removeSession(providerId: string, sessionId: string): Promise; } diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index be7640ce1d9..c134a357403 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -48,11 +48,11 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { return Object.freeze(this._providers.slice()); } - async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise; - async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise { + async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions & { createIfNone: true }): Promise; + async getSession(requestingExtension: IExtensionDescription, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise { const extensionId = ExtensionIdentifier.toKey(requestingExtension.identifier); const inFlightRequests = this._inFlightRequests.get(extensionId) || []; - const sortedScopes = scopes.sort().join(' '); + const sortedScopes = [...scopes].sort().join(' '); let inFlightRequest: GetSessionsRequest | undefined = inFlightRequests.find(request => request.scopes === sortedScopes); if (inFlightRequest) { @@ -81,7 +81,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { } } - private async _getSession(requestingExtension: IExtensionDescription, extensionId: string, providerId: string, scopes: string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise { + private async _getSession(requestingExtension: IExtensionDescription, extensionId: string, providerId: string, scopes: readonly string[], options: vscode.AuthenticationGetSessionOptions = {}): Promise { await this._proxy.$ensureProvider(providerId); const extensionName = requestingExtension.displayName || requestingExtension.name; return this._proxy.$getSession(providerId, scopes, extensionId, extensionName, options); diff --git a/src/vs/workbench/api/common/extHostDebugService.ts b/src/vs/workbench/api/common/extHostDebugService.ts index b2fd2327d03..406992259f6 100644 --- a/src/vs/workbench/api/common/extHostDebugService.ts +++ b/src/vs/workbench/api/common/extHostDebugService.ts @@ -48,8 +48,8 @@ export interface IExtHostDebugService extends ExtHostDebugServiceShape { onDidChangeBreakpoints: Event; breakpoints: vscode.Breakpoint[]; - addBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise; - removeBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise; + addBreakpoints(breakpoints0: readonly vscode.Breakpoint[]): Promise; + removeBreakpoints(breakpoints0: readonly vscode.Breakpoint[]): Promise; startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration, options: vscode.DebugSessionOptions): Promise; stopDebugging(session?: vscode.DebugSession): Promise; registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider, trigger: vscode.DebugConfigurationProviderTriggerKind): vscode.Disposable; From 0a7061ed002903dd4664d4d7012f570f4595968d Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 25 May 2021 18:23:22 -0700 Subject: [PATCH 102/140] ReadonlyArray -> readonly arr[] This syntax has been supported by TS for quite a few language versions now --- src/vs/vscode.d.ts | 84 +++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index bf2d13e456f..0fb21917d3e 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -536,7 +536,7 @@ declare module 'vscode' { /** * The new value for the {@link TextEditor.selections text editor's selections}. */ - readonly selections: ReadonlyArray; + readonly selections: readonly Selection[]; /** * The {@link TextEditorSelectionChangeKind change kind} which has triggered this * event. Can be `undefined`. @@ -555,7 +555,7 @@ declare module 'vscode' { /** * The new value for the {@link TextEditor.visibleRanges text editor's visible ranges}. */ - readonly visibleRanges: ReadonlyArray; + readonly visibleRanges: readonly Range[]; } /** @@ -1150,7 +1150,7 @@ declare module 'vscode' { * @return A promise that resolves with a value indicating if the snippet could be inserted. Note that the promise does not signal * that the snippet is completely filled-in or accepted. */ - insertSnippet(snippet: SnippetString, location?: Position | Range | ReadonlyArray | ReadonlyArray, options?: { undoStopBefore: boolean; undoStopAfter: boolean; }): Thenable; + insertSnippet(snippet: SnippetString, location?: Position | Range | readonly Position[] | readonly Range[], options?: { undoStopBefore: boolean; undoStopAfter: boolean; }): Thenable; /** * Adds a set of decorations to the text editor. If a set of decorations already exists with @@ -2211,7 +2211,7 @@ declare module 'vscode' { /** * An array of diagnostics. */ - readonly diagnostics: ReadonlyArray; + readonly diagnostics: readonly Diagnostic[]; /** * Requested kind of actions to return. @@ -2975,7 +2975,7 @@ declare module 'vscode' { /** * Tags for this symbol. */ - tags?: ReadonlyArray; + tags?: readonly SymbolTag[]; /** * The location of this symbol. @@ -3031,7 +3031,7 @@ declare module 'vscode' { /** * Tags for this symbol. */ - tags?: ReadonlyArray; + tags?: readonly SymbolTag[]; /** * The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code. @@ -3955,7 +3955,7 @@ declare module 'vscode' { /** * List of characters that trigger signature help. */ - readonly triggerCharacters: ReadonlyArray; + readonly triggerCharacters: readonly string[]; /** * List of characters that re-trigger signature help. @@ -3963,7 +3963,7 @@ declare module 'vscode' { * These trigger characters are only active when signature help is already showing. All trigger characters * are also counted as re-trigger characters. */ - readonly retriggerCharacters: ReadonlyArray; + readonly retriggerCharacters: readonly string[]; } /** @@ -4043,7 +4043,7 @@ declare module 'vscode' { /** * Tags for this completion item. */ - tags?: ReadonlyArray; + tags?: readonly CompletionItemTag[]; /** * A human-readable string with additional information @@ -4608,7 +4608,7 @@ declare module 'vscode' { /** * Tags for this item. */ - tags?: ReadonlyArray; + tags?: readonly SymbolTag[]; /** * More detail for this item, e.g. the signature of a function. @@ -5197,7 +5197,7 @@ declare module 'vscode' { /** * An array of resources for which diagnostics have changed. */ - readonly uris: ReadonlyArray; + readonly uris: readonly Uri[]; } /** @@ -5366,7 +5366,7 @@ declare module 'vscode' { * @param uri A resource identifier. * @param diagnostics Array of diagnostics or `undefined` */ - set(uri: Uri, diagnostics: ReadonlyArray | undefined): void; + set(uri: Uri, diagnostics: readonly Diagnostic[] | undefined): void; /** * Replace diagnostics for multiple resources in this collection. @@ -5378,7 +5378,7 @@ declare module 'vscode' { * * @param entries An array of tuples, like `[[file1, [d1, d2]], [file2, [d3, d4, d5]]]`, or `undefined`. */ - set(entries: ReadonlyArray<[Uri, ReadonlyArray | undefined]>): void; + set(entries: ReadonlyArray<[Uri, readonly Diagnostic[] | undefined]>): void; /** * Remove all diagnostics from this collection that belong @@ -5400,7 +5400,7 @@ declare module 'vscode' { * @param callback Function to execute for each entry. * @param thisArg The `this` context used when invoking the handler function. */ - forEach(callback: (uri: Uri, diagnostics: ReadonlyArray, collection: DiagnosticCollection) => any, thisArg?: any): void; + forEach(callback: (uri: Uri, diagnostics: readonly Diagnostic[], collection: DiagnosticCollection) => any, thisArg?: any): void; /** * Get the diagnostics for a given resource. *Note* that you cannot @@ -5409,7 +5409,7 @@ declare module 'vscode' { * @param uri A resource identifier. * @returns An immutable array of {@link Diagnostic diagnostics} or `undefined`. */ - get(uri: Uri): ReadonlyArray | undefined; + get(uri: Uri): readonly Diagnostic[] | undefined; /** * Check if this collection contains diagnostics for a @@ -6879,7 +6879,7 @@ declare module 'vscode' { /** * The currently active task executions or an empty array. */ - export const taskExecutions: ReadonlyArray; + export const taskExecutions: readonly TaskExecution[]; /** * Fires when a task starts. @@ -7327,7 +7327,7 @@ declare module 'vscode' { * * Pass in an empty array to disallow access to any local resources. */ - readonly localResourceRoots?: ReadonlyArray; + readonly localResourceRoots?: readonly Uri[]; /** * Mappings of localhost ports used inside the webview. @@ -7342,7 +7342,7 @@ declare module 'vscode' { * *Note* that port mappings only work for `http` or `https` urls. Websocket urls (e.g. `ws://localhost:3000`) * cannot be mapped to another port. */ - readonly portMapping?: ReadonlyArray; + readonly portMapping?: readonly WebviewPortMapping[]; } /** @@ -8408,7 +8408,7 @@ declare module 'vscode' { /** * The currently opened terminals or an empty array. */ - export const terminals: ReadonlyArray; + export const terminals: readonly Terminal[]; /** * The currently active terminal or `undefined`. The active terminal is the one that @@ -9849,7 +9849,7 @@ declare module 'vscode' { /** * Buttons for actions in the UI. */ - buttons: ReadonlyArray; + buttons: readonly QuickInputButton[]; /** * An event signaling when a button was triggered. @@ -9859,7 +9859,7 @@ declare module 'vscode' { /** * Items to pick from. */ - items: ReadonlyArray; + items: readonly T[]; /** * If multiple items can be selected at the same time. Defaults to false. @@ -9879,7 +9879,7 @@ declare module 'vscode' { /** * Active items. This can be read and updated by the extension. */ - activeItems: ReadonlyArray; + activeItems: readonly T[]; /** * An event signaling when the active items have changed. @@ -9889,7 +9889,7 @@ declare module 'vscode' { /** * Selected items. This can be read and updated by the extension. */ - selectedItems: ReadonlyArray; + selectedItems: readonly T[]; /** * An event signaling when the selected items have changed. @@ -9934,7 +9934,7 @@ declare module 'vscode' { /** * Buttons for actions in the UI. */ - buttons: ReadonlyArray; + buttons: readonly QuickInputButton[]; /** * An event signaling when a button was triggered. @@ -10022,7 +10022,7 @@ declare module 'vscode' { /** * An array of content changes. */ - readonly contentChanges: ReadonlyArray; + readonly contentChanges: readonly TextDocumentContentChangeEvent[]; } /** @@ -10110,7 +10110,7 @@ declare module 'vscode' { /** * The files that are going to be created. */ - readonly files: ReadonlyArray; + readonly files: readonly Uri[]; /** * Allows to pause the event and to apply a {@link WorkspaceEdit workspace edit}. @@ -10150,7 +10150,7 @@ declare module 'vscode' { /** * The files that got created. */ - readonly files: ReadonlyArray; + readonly files: readonly Uri[]; } /** @@ -10165,7 +10165,7 @@ declare module 'vscode' { /** * The files that are going to be deleted. */ - readonly files: ReadonlyArray; + readonly files: readonly Uri[]; /** * Allows to pause the event and to apply a {@link WorkspaceEdit workspace edit}. @@ -10205,7 +10205,7 @@ declare module 'vscode' { /** * The files that got deleted. */ - readonly files: ReadonlyArray; + readonly files: readonly Uri[]; } /** @@ -10270,12 +10270,12 @@ declare module 'vscode' { /** * Added workspace folders. */ - readonly added: ReadonlyArray; + readonly added: readonly WorkspaceFolder[]; /** * Removed workspace folders. */ - readonly removed: ReadonlyArray; + readonly removed: readonly WorkspaceFolder[]; } /** @@ -10350,7 +10350,7 @@ declare module 'vscode' { * * *Note* that the first entry corresponds to the value of `rootPath`. */ - export const workspaceFolders: ReadonlyArray | undefined; + export const workspaceFolders: readonly WorkspaceFolder[] | undefined; /** * The name of the workspace. `undefined` when no workspace @@ -10534,7 +10534,7 @@ declare module 'vscode' { /** * All text documents currently known to the editor. */ - export const textDocuments: ReadonlyArray; + export const textDocuments: readonly TextDocument[]; /** * Opens a document. Will return early if this document is already open. Otherwise @@ -11922,17 +11922,17 @@ declare module 'vscode' { /** * Added breakpoints. */ - readonly added: ReadonlyArray; + readonly added: readonly Breakpoint[]; /** * Removed breakpoints. */ - readonly removed: ReadonlyArray; + readonly removed: readonly Breakpoint[]; /** * Changed breakpoints. */ - readonly changed: ReadonlyArray; + readonly changed: readonly Breakpoint[]; } /** @@ -12299,7 +12299,7 @@ declare module 'vscode' { /** * The ordered comments of the thread. */ - comments: ReadonlyArray; + comments: readonly Comment[]; /** * Whether the thread should be collapsed or expanded when opening the document. @@ -12564,7 +12564,7 @@ declare module 'vscode' { * The permissions granted by the session's access token. Available scopes * are defined by the {@link AuthenticationProvider}. */ - readonly scopes: ReadonlyArray; + readonly scopes: readonly string[]; } /** @@ -12656,19 +12656,19 @@ declare module 'vscode' { /** * The {@link AuthenticationSession}s of the {@link AuthentiationProvider AuthenticationProvider} that have been added. */ - readonly added?: ReadonlyArray; + readonly added?: readonly AuthenticationSession[]; /** * The {@link AuthenticationSession}s of the {@link AuthentiationProvider AuthenticationProvider} that have been removed. */ - readonly removed?: ReadonlyArray; + readonly removed?: readonly AuthenticationSession[]; /** * The {@link AuthenticationSession}s of the {@link AuthentiationProvider AuthenticationProvider} that have been changed. * A session changes when its data excluding the id are updated. An example of this is a session refresh that results in a new * access token being set for the session. */ - readonly changed?: ReadonlyArray; + readonly changed?: readonly AuthenticationSession[]; } /** @@ -12687,7 +12687,7 @@ declare module 'vscode' { * these permissions, otherwise all sessions should be returned. * @returns A promise that resolves to an array of authentication sessions. */ - getSessions(scopes?: readonly string[]): Thenable>; + getSessions(scopes?: readonly string[]): Thenable; /** * Prompts a user to login. From ad41b3a12b5685f2568bed7aaa8635496b6358ef Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 25 May 2021 18:25:39 -0700 Subject: [PATCH 103/140] Mark a few more props as readonly --- src/vs/vscode.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 0fb21917d3e..a339d5c8640 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -10220,7 +10220,7 @@ declare module 'vscode' { /** * The files that are going to be renamed. */ - readonly files: ReadonlyArray<{ oldUri: Uri, newUri: Uri }>; + readonly files: ReadonlyArray<{ readonly oldUri: Uri, readonly newUri: Uri }>; /** * Allows to pause the event and to apply a {@link WorkspaceEdit workspace edit}. @@ -10260,7 +10260,7 @@ declare module 'vscode' { /** * The files that got renamed. */ - readonly files: ReadonlyArray<{ oldUri: Uri, newUri: Uri }>; + readonly files: ReadonlyArray<{ readonly oldUri: Uri, readonly newUri: Uri }>; } /** @@ -12242,7 +12242,7 @@ declare module 'vscode' { /** * All extensions currently known to the system. */ - export const all: ReadonlyArray>; + export const all: readonly Extension[]; /** * An event which fires when `extensions.all` changes. This can happen when extensions are From 68efd480d0e0e0fa5ad6438215559f396909e2bf Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 25 May 2021 18:30:18 -0700 Subject: [PATCH 104/140] Explicitly convert properties to strings before uploading --- .../src/languageFeatures/completions.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/extensions/typescript-language-features/src/languageFeatures/completions.ts b/extensions/typescript-language-features/src/languageFeatures/completions.ts index acdec8412ed..b181a122adf 100644 --- a/extensions/typescript-language-features/src/languageFeatures/completions.ts +++ b/extensions/typescript-language-features/src/languageFeatures/completions.ts @@ -817,11 +817,15 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider< } */ this.telemetryReporter.logTelemetry('completions.execute', { - duration: duration, + duration: String(duration), type: response?.type ?? 'unknown', - count: response?.type === 'response' && response.body ? response.body.entries.length : 0, - updateGraphDurationMs: response?.type === 'response' ? response.performanceData?.updateGraphDurationMs : undefined, - createAutoImportProviderProgramDurationMs: response?.type === 'response' ? response.performanceData?.createAutoImportProviderProgramDurationMs : undefined, + count: String(response?.type === 'response' && response.body ? response.body.entries.length : 0), + updateGraphDurationMs: response?.type === 'response' && typeof response.performanceData?.updateGraphDurationMs === 'number' + ? String(response.performanceData.updateGraphDurationMs) + : undefined, + createAutoImportProviderProgramDurationMs: response?.type === 'response' && typeof response.performanceData?.createAutoImportProviderProgramDurationMs === 'number' + ? String(response.performanceData.createAutoImportProviderProgramDurationMs) + : undefined, includesPackageJsonImport: includesPackageJsonImport ? 'true' : undefined, includesImportStatementCompletion: includesImportStatementCompletion ? 'true' : undefined, }); From 21162bfb68c43a0d608ee2161c9d26934725c437 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 25 May 2021 17:55:06 -0700 Subject: [PATCH 105/140] Shift execution count label down just a bit --- src/vs/workbench/contrib/notebook/browser/media/notebook.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index a1769e49bcb..e2030899479 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -521,6 +521,10 @@ text-align: center; } +.monaco-workbench .notebookOverlay>.cell-list-container>.monaco-list>.monaco-scrollable-element>.monaco-list-rows>.monaco-list-row .cell-statusbar-hidden .execution-count-label { + line-height: 15px; +} + .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .output-collapsed .execution-count-label { bottom: 24px; } From a18ea9c9ec25c59e599ba3c2eb668315546dd269 Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Tue, 25 May 2021 20:02:19 -0700 Subject: [PATCH 106/140] Allow extensions to create multiple sessions from the same provider (#124640) --- .../api/browser/mainThreadAuthentication.ts | 13 +- .../api/common/extHostAuthentication.ts | 5 +- .../browser/authenticationService.ts | 4 +- .../api/mainThreadAuthentication.test.ts | 136 ++++++++++++++++++ .../test/common/workbenchTestServices.ts | 19 +++ 5 files changed, 163 insertions(+), 14 deletions(-) create mode 100644 src/vs/workbench/test/browser/api/mainThreadAuthentication.test.ts diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index 19e704dff86..401db52faa2 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -183,21 +183,15 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu return choice === 0; } - private async setTrustedExtensionAndAccountPreference(providerId: string, accountName: string, extensionId: string, extensionName: string, sessionId: string): Promise { - this.authenticationService.updatedAllowedExtension(providerId, accountName, extensionId, extensionName, true); - this.storageService.store(`${extensionName}-${providerId}`, sessionId, StorageScope.GLOBAL, StorageTarget.MACHINE); - - } - private async selectSession(providerId: string, extensionId: string, extensionName: string, scopes: string[], potentialSessions: readonly modes.AuthenticationSession[], clearSessionPreference: boolean, silent: boolean): Promise { if (!potentialSessions.length) { throw new Error('No potential sessions found'); } if (clearSessionPreference) { - this.storageService.remove(`${extensionName}-${providerId}`, StorageScope.GLOBAL); + this.storageService.remove(`${extensionName}-${providerId}-${scopes.join('-')}`, StorageScope.GLOBAL); } else { - const existingSessionPreference = this.storageService.get(`${extensionName}-${providerId}`, StorageScope.GLOBAL); + const existingSessionPreference = this.storageService.get(`${extensionName}-${providerId}-${scopes.join('-')}`, StorageScope.GLOBAL); if (existingSessionPreference) { const matchingSession = potentialSessions.find(session => session.id === existingSessionPreference); if (matchingSession) { @@ -261,7 +255,8 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu } session = await this.authenticationService.createSession(providerId, scopes, true); - await this.setTrustedExtensionAndAccountPreference(providerId, session.account.label, extensionId, extensionName, session.id); + await this.authenticationService.updatedAllowedExtension(providerId, session.account.label, extensionId, extensionName, true); + this.storageService.store(`${extensionName}-${providerId}-${scopes.join('-')}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); } else { await this.authenticationService.requestNewSession(providerId, scopes, extensionId, extensionName); } diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index c134a357403..14acdb4343c 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -68,7 +68,8 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { this._inFlightRequests.set(extensionId, inFlightRequests); try { - await session; + const s = await session; + return s; } finally { const requestIndex = inFlightRequests.findIndex(request => request.scopes === sortedScopes); if (requestIndex > -1) { @@ -76,8 +77,6 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { this._inFlightRequests.set(extensionId, inFlightRequests); } } - - return session; } } diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts index b5da23219ea..1654f175077 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts @@ -503,7 +503,7 @@ export class AuthenticationService extends Disposable implements IAuthentication this.updatedAllowedExtension(providerId, accountName, extensionId, extensionName, true); this.removeAccessRequest(providerId, extensionId); - this.storageService.store(`${extensionName}-${providerId}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); + this.storageService.store(`${extensionName}-${providerId}-${scopes.join('-')}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); quickPick.dispose(); resolve(session); @@ -638,7 +638,7 @@ export class AuthenticationService extends Disposable implements IAuthentication this.updatedAllowedExtension(providerId, session.account.label, extensionId, extensionName, true); // And also set it as the preferred account for the extension - storageService.store(`${extensionName}-${providerId}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); + storageService.store(`${extensionName}-${providerId}-${scopes.join('-')}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); } }); diff --git a/src/vs/workbench/test/browser/api/mainThreadAuthentication.test.ts b/src/vs/workbench/test/browser/api/mainThreadAuthentication.test.ts new file mode 100644 index 00000000000..e4bd24e47b9 --- /dev/null +++ b/src/vs/workbench/test/browser/api/mainThreadAuthentication.test.ts @@ -0,0 +1,136 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { AuthenticationProviderInformation } from 'vs/editor/common/modes'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; +import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService'; +import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { INotificationService } from 'vs/platform/notification/common/notification'; +import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; +import { IQuickInputHideEvent, IQuickInputService, IQuickPickDidAcceptEvent } from 'vs/platform/quickinput/common/quickInput'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { MainThreadAuthentication } from 'vs/workbench/api/browser/mainThreadAuthentication'; +import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol'; +import { IActivityService } from 'vs/workbench/services/activity/common/activity'; +import { AuthenticationService, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService'; +import { ExtensionHostKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; +import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; +import { TestRemoteAgentService } from 'vs/workbench/services/remote/test/common/testServices'; +import { TestQuickInputService } from 'vs/workbench/test/browser/workbenchTestServices'; +import { TestActivityService, TestExtensionService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; + +function createSession(id: string = '1234', scope: string[] = []) { + return { + accessToken: '1234', + account: { + id: 'test@test.com', + label: 'Test Person' + }, + id: id, + scopes: scope + }; +} + +class AuthQuickPick { + private listener: ((e: IQuickPickDidAcceptEvent) => any) | undefined; + public items = []; + public get selectedItems(): string[] { + return this.items; + } + + onDidAccept(listener: (e: IQuickPickDidAcceptEvent) => any) { + this.listener = listener; + } + onDidHide(listener: (e: IQuickInputHideEvent) => any) { + + } + dispose() { + + } + show() { + this.listener!({ + inBackground: false + }); + } +} +class AuthTestQuickInputService extends TestQuickInputService { + override createQuickPick() { + return new AuthQuickPick(); + } +} + +suite('MainThreadAuthentication', () => { + let mainThreadAuthentication: MainThreadAuthentication; + suiteSetup(async () => { + // extHostContext: IExtHostContext, + const services = new ServiceCollection(); + const dialogService = new TestDialogService(); + const storageService = new TestStorageService(); + const quickInputService = new AuthTestQuickInputService(); + const extensionService = new TestExtensionService(); + + const activityService = new TestActivityService(); + const remoteAgentService = new TestRemoteAgentService(); + + services.set(IDialogService, dialogService); + services.set(IStorageService, storageService); + services.set(INotificationService, new TestNotificationService()); + services.set(IQuickInputService, quickInputService); + services.set(IExtensionService, extensionService); + services.set(IActivityService, activityService); + services.set(IRemoteAgentService, remoteAgentService); + + const instaService = new InstantiationService(services); + services.set(IAuthenticationService, instaService.createInstance(AuthenticationService)); + + mainThreadAuthentication = instaService.createInstance(MainThreadAuthentication, + new class implements IExtHostContext { + remoteAuthority = ''; + extensionHostKind = ExtensionHostKind.LocalProcess; + assertRegistered() { } + set(v: any): any { return null; } + getProxy(): any { + return { + $getSessions(id: string, scopes: string[]) { + return Promise.resolve([createSession(id, scopes)]); + }, + $createSession(id: string, scopes: string[]) { + return Promise.resolve(createSession(id, scopes)); + }, + $removeSession(id: string, sessionId: string) { return Promise.resolve(); }, + $onDidChangeAuthenticationSessions(id: string, label: string) { return Promise.resolve(); }, + $onDidChangeAuthenticationProviders(added: AuthenticationProviderInformation[], removed: AuthenticationProviderInformation[]) { return Promise.resolve(); }, + $setProviders(providers: AuthenticationProviderInformation[]) { return Promise.resolve(); } + }; + } + drain(): any { return null; } + }); + + await mainThreadAuthentication.$registerAuthenticationProvider('test', 'test provider', true); + }); + + suiteTeardown(() => { + mainThreadAuthentication.$unregisterAuthenticationProvider('test'); + }); + + test('Can get a session', async () => { + const session = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', { createIfNone: true, clearSessionPreference: false }); + assert.strictEqual(session?.id, 'test'); + assert.strictEqual(session?.scopes[0], 'foo'); + }); + + test('Can get multiple sessions (with different scopes) in one extension', async () => { + let session = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', { createIfNone: true, clearSessionPreference: false }); + session = await mainThreadAuthentication.$getSession('test', ['bar'], 'testextension', 'test extension', { createIfNone: true, clearSessionPreference: false }); + assert.strictEqual(session?.id, 'test'); + assert.strictEqual(session?.scopes[0], 'bar'); + + session = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', { createIfNone: false, clearSessionPreference: false }); + assert.strictEqual(session?.id, 'test'); + assert.strictEqual(session?.scopes[0], 'foo'); + }); +}); diff --git a/src/vs/workbench/test/common/workbenchTestServices.ts b/src/vs/workbench/test/common/workbenchTestServices.ts index b2ddf026545..f4450ecfcd5 100644 --- a/src/vs/workbench/test/common/workbenchTestServices.ts +++ b/src/vs/workbench/test/common/workbenchTestServices.ts @@ -22,6 +22,7 @@ import { IFileStatWithMetadata } from 'vs/platform/files/common/files'; import { ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor'; import { CancellationToken } from 'vs/base/common/cancellation'; import product from 'vs/platform/product/common/product'; +import { IActivity, IActivityService } from 'vs/workbench/services/activity/common/activity'; export class TestTextResourcePropertiesService implements ITextResourcePropertiesService { @@ -214,3 +215,21 @@ export interface Ctor { export class TestExtensionService extends NullExtensionService { } export const TestProductService = { _serviceBrand: undefined, ...product }; + +export class TestActivityService implements IActivityService { + _serviceBrand: undefined; + showViewContainerActivity(viewContainerId: string, badge: IActivity): IDisposable { + return this; + } + showViewActivity(viewId: string, badge: IActivity): IDisposable { + return this; + } + showAccountsActivity(activity: IActivity): IDisposable { + return this; + } + showGlobalActivity(activity: IActivity): IDisposable { + return this; + } + + dispose() { } +} From b82b90c1000a953a2caf6f5452326f202518ec49 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 26 May 2021 07:37:08 +0200 Subject: [PATCH 107/140] editor options - more :lipstick: before merge --- .../browser/parts/editor/textDiffEditor.ts | 32 ++++++++++--------- .../browser/parts/editor/textEditor.ts | 6 ++-- .../parts/editor/textResourceEditor.ts | 4 +-- .../files/browser/editors/textFileEditor.ts | 22 ++++++------- .../files/electron-sandbox/textFileEditor.ts | 4 +-- .../browser/diff/notebookTextDiffEditor.ts | 5 ++- .../notebook/browser/notebookEditor.ts | 4 +-- .../contrib/output/browser/outputView.ts | 4 +-- .../preferences/browser/preferencesEditor.ts | 3 +- 9 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts index 9c2d030f364..5e723df1bc0 100644 --- a/src/vs/workbench/browser/parts/editor/textDiffEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textDiffEditor.ts @@ -28,7 +28,7 @@ import { URI } from 'vs/base/common/uri'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { EditorActivation, IEditorOptions } from 'vs/platform/editor/common/editor'; +import { EditorActivation, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { isEqual } from 'vs/base/common/resources'; import { multibyteAwareBtoa } from 'vs/base/browser/dom'; @@ -107,7 +107,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan return this.instantiationService.createInstance(DiffEditorWidget, parent, configuration, {}); } - override async setInput(input: DiffEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: DiffEditorInput, options: ITextEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { // Dispose previous diff navigator this.diffNavigatorDisposables.clear(); @@ -190,7 +190,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan return false; } - private openAsBinary(input: DiffEditorInput, options: IEditorOptions | undefined): void { + private openAsBinary(input: DiffEditorInput, options: ITextEditorOptions | undefined): void { const originalInput = input.originalInput; const modifiedInput = input.modifiedInput; @@ -206,19 +206,21 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan modifiedInput.setForceOpenAsBinary(); } - // Make sure to not steal away the currently active group - // because we are triggering another openEditor() call - // and do not control the initial intent that resulted - // in us now opening as binary. - options = { - ...options, - activation: EditorActivation.PRESERVE, - pinned: this.group?.isPinned(input), - sticky: this.group?.isSticky(input) - }; - // Replace this editor with the binary one - this.editorService.replaceEditors([{ editor: input, replacement: binaryDiffInput, options }], this.group || ACTIVE_GROUP); + this.editorService.replaceEditors([{ + editor: input, + replacement: binaryDiffInput, + options: { + ...options, + // Make sure to not steal away the currently active group + // because we are triggering another openEditor() call + // and do not control the initial intent that resulted + // in us now opening as binary. + activation: EditorActivation.PRESERVE, + pinned: this.group?.isPinned(input), + sticky: this.group?.isSticky(input) + } + }], this.group || ACTIVE_GROUP); } protected override computeConfiguration(configuration: IEditorConfiguration): ICodeEditorOptions { diff --git a/src/vs/workbench/browser/parts/editor/textEditor.ts b/src/vs/workbench/browser/parts/editor/textEditor.ts index 5bab2bdab68..eea7340bdb9 100644 --- a/src/vs/workbench/browser/parts/editor/textEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textEditor.ts @@ -29,7 +29,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IExtUri } from 'vs/base/common/resources'; import { MutableDisposable } from 'vs/base/common/lifecycle'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IEditorOptions } from 'vs/platform/editor/common/editor'; +import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; export interface IEditorConfiguration { editor: object; @@ -156,7 +156,7 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa return this.instantiationService.createInstance(CodeEditorWidget, parent, configuration, {}); } - override async setInput(input: EditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: EditorInput, options: ITextEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); // Update editor options after having set the input. We do this because there can be @@ -168,7 +168,7 @@ export abstract class BaseTextEditor extends EditorPane implements ITextEditorPa editorContainer.setAttribute('aria-label', this.computeAriaLabel()); } - override setOptions(options: IEditorOptions | undefined): void { + override setOptions(options: ITextEditorOptions | undefined): void { if (options) { applyTextEditorOptions(options, assertIsDefined(this.getControl()), ScrollType.Smooth); } diff --git a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts index 7c3930d3204..562945e369c 100644 --- a/src/vs/workbench/browser/parts/editor/textResourceEditor.ts +++ b/src/vs/workbench/browser/parts/editor/textResourceEditor.ts @@ -27,7 +27,7 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry'; import { EditorOption, IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { ModelConstants } from 'vs/editor/common/model'; -import { IEditorOptions } from 'vs/platform/editor/common/editor'; +import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; /** * An editor implementation that is capable of showing the contents of resource inputs. Uses @@ -56,7 +56,7 @@ export class AbstractTextResourceEditor extends BaseTextEditor { return localize('textEditor', "Text Editor"); } - override async setInput(input: AbstractTextResourceEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: AbstractTextResourceEditorInput, options: ITextEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { // Remember view settings if input changes this.saveTextResourceEditorViewState(this.input); diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index 1687adad197..26c09dfc41a 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -29,7 +29,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { CancellationToken } from 'vs/base/common/cancellation'; import { createErrorWithActions } from 'vs/base/common/errors'; -import { EditorActivation, EditorOverride, IEditorOptions } from 'vs/platform/editor/common/editor'; +import { EditorActivation, EditorOverride, ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; @@ -105,7 +105,7 @@ export class TextFileEditor extends BaseTextEditor { return this._input as FileEditorInput; } - override async setInput(input: FileEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: FileEditorInput, options: ITextEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { // Update/clear view settings if input changes this.doSaveOrClearTextEditorViewState(this.input); @@ -157,7 +157,7 @@ export class TextFileEditor extends BaseTextEditor { } } - protected handleSetInputError(error: Error, input: FileEditorInput, options: IEditorOptions | undefined): void { + protected handleSetInputError(error: Error, input: FileEditorInput, options: ITextEditorOptions | undefined): void { // In case we tried to open a file inside the text editor and the response // indicates that this is not a text file, reopen the file through the binary @@ -197,20 +197,18 @@ export class TextFileEditor extends BaseTextEditor { throw error; } - private openAsBinary(input: FileEditorInput, options: IEditorOptions | undefined): void { + private openAsBinary(input: FileEditorInput, options: ITextEditorOptions | undefined): void { input.setForceOpenAsBinary(); - // Make sure to not steal away the currently active group - // because we are triggering another openEditor() call - // and do not control the initial intent that resulted - // in us now opening as binary. - options = { + this.editorService.openEditor(input, { ...options, + // Make sure to not steal away the currently active group + // because we are triggering another openEditor() call + // and do not control the initial intent that resulted + // in us now opening as binary. activation: EditorActivation.PRESERVE, override: EditorOverride.DISABLED - }; - - this.editorService.openEditor(input, options, this.group); + }, this.group); } private async openAsFolder(input: FileEditorInput): Promise { diff --git a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts index 0674515bb52..bb34adbf976 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/textFileEditor.ts @@ -24,7 +24,7 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { IExplorerService } from 'vs/workbench/contrib/files/browser/files'; import { IProductService } from 'vs/platform/product/common/productService'; -import { IEditorOptions } from 'vs/platform/editor/common/editor'; +import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; /** * An implementation of editor for file system resources. @@ -52,7 +52,7 @@ export class NativeTextFileEditor extends TextFileEditor { super(telemetryService, fileService, viewletService, instantiationService, contextService, storageService, textResourceConfigurationService, editorService, themeService, editorGroupService, textFileService, explorerService, uriIdentityService); } - protected override handleSetInputError(error: Error, input: FileEditorInput, options: IEditorOptions | undefined): void { + protected override handleSetInputError(error: Error, input: FileEditorInput, options: ITextEditorOptions | undefined): void { // Allow to restart with higher memory limit if the file is too large if ((error).fileOperationResult === FileOperationResult.FILE_EXCEEDS_MEMORY_LIMIT) { diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index fe67cd9da07..99ef173b1da 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -23,7 +23,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IEditorOptions as ICodeEditorOptions } from 'vs/editor/common/config/editorOptions'; import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo'; import { getPixelRatio, getZoomLevel } from 'vs/base/browser/browser'; -import { CellEditState, ICellOutputViewModel, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel, IInsetRenderOutput, NotebookLayoutInfo, NOTEBOOK_DIFF_EDITOR_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, ICellOutputViewModel, IDisplayOutputLayoutUpdateRequest, IGenericCellViewModel, IInsetRenderOutput, INotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_DIFF_EDITOR_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { DiffSide, DIFF_CELL_MARGIN, IDiffCellInfo, INotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser'; import { Emitter, Event } from 'vs/base/common/event'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; @@ -41,7 +41,6 @@ import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/ren import { NotebookDiffEditorEventDispatcher, NotebookDiffLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/diff/eventDispatcher'; import { readFontInfo } from 'vs/editor/browser/config/configuration'; import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions'; -import { IEditorOptions } from 'vs/platform/editor/common/editor'; const $ = DOM.$; @@ -293,7 +292,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD } } - override async setInput(input: NotebookDiffEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: NotebookDiffEditorInput, options: INotebookEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); const model = await input.resolve(); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 4cd1cfb84ef..de58dd26bc7 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -11,7 +11,7 @@ import 'vs/css!./media/notebook'; import { localize } from 'vs/nls'; import { extname } from 'vs/base/common/resources'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { EditorOverride, IEditorOptions } from 'vs/platform/editor/common/editor'; +import { EditorOverride } from 'vs/platform/editor/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -152,7 +152,7 @@ export class NotebookEditor extends EditorPane { return !!value && (DOM.isAncestor(activeElement, value.getDomNode() || DOM.isAncestor(activeElement, value.getOverflowContainerDomNode()))); } - override async setInput(input: NotebookEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: NotebookEditorInput, options: INotebookEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { clearMarks(input.resource); mark(input.resource, 'startTime'); const group = this.group!; diff --git a/src/vs/workbench/contrib/output/browser/outputView.ts b/src/vs/workbench/contrib/output/browser/outputView.ts index 5d8125642d1..ef3602468b7 100644 --- a/src/vs/workbench/contrib/output/browser/outputView.ts +++ b/src/vs/workbench/contrib/output/browser/outputView.ts @@ -37,7 +37,7 @@ import { editorBackground, selectBorder } from 'vs/platform/theme/common/colorRe import { SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { Dimension } from 'vs/base/browser/dom'; import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { IEditorOptions } from 'vs/platform/editor/common/editor'; +import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; export class OutputViewPane extends ViewPane { @@ -222,7 +222,7 @@ export class OutputEditor extends AbstractTextResourceEditor { return channel ? nls.localize('outputViewWithInputAriaLabel', "{0}, Output panel", channel.label) : nls.localize('outputViewAriaLabel', "Output panel"); } - override async setInput(input: TextResourceEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: TextResourceEditorInput, options: ITextEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { const focus = !(options && options.preserveFocus); if (input.matches(this.input)) { return; diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts index c97ed166b2b..8fcd0a27cf7 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts @@ -28,7 +28,6 @@ import { SelectionHighlighter } from 'vs/editor/contrib/multicursor/multicursor' import * as nls from 'vs/nls'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IConstructorSignature1, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; import { IEditorProgressService } from 'vs/platform/progress/common/progress'; @@ -1023,7 +1022,7 @@ export class DefaultPreferencesEditor extends BaseTextEditor { return options; } - override async setInput(input: DefaultPreferencesEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { + override async setInput(input: DefaultPreferencesEditorInput, options: ISettingsEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise { await super.setInput(input, options, context, token); const editorModel = await this.input!.resolve(); if (!editorModel) { From 5cc9ec944d815c975a5f61ef0191c90190f4832d Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 26 May 2021 07:49:17 +0200 Subject: [PATCH 108/140] sandbox - bring in iframe based webview service --- .../sandbox.simpleservices.ts | 19 ------------------- .../workbench.desktop.sandbox.main.ts | 2 ++ 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts index c27cd8e4f63..4f84e7b6ea4 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts @@ -12,7 +12,6 @@ import { IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnectio import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IExtensionService, NullExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { isWindows } from 'vs/base/common/platform'; -import { IWebviewService, Webview, WebviewContentOptions, WebviewElement, WebviewExtensionDescription, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { ITunnelProvider, ITunnelService, RemoteTunnel, TunnelProviderFeatures } from 'vs/platform/remote/common/tunnel'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { joinPath } from 'vs/base/common/resources'; @@ -264,24 +263,6 @@ registerSingleton(IExtensionService, SimpleExtensionService); //#endregion -//#region Webview - -class SimpleWebviewService implements IWebviewService { - declare readonly _serviceBrand: undefined; - - readonly activeWebview = undefined; - readonly webviews: Webview[] = []; - readonly onDidChangeActiveWebview = Event.None; - - createWebviewElement(id: string, options: WebviewOptions, contentOptions: WebviewContentOptions, extension: WebviewExtensionDescription | undefined): WebviewElement { throw new Error('Method not implemented.'); } - createWebviewOverlay(id: string, options: WebviewOptions, contentOptions: WebviewContentOptions, extension: WebviewExtensionDescription | undefined): WebviewOverlay { throw new Error('Method not implemented.'); } -} - -registerSingleton(IWebviewService, SimpleWebviewService); - -//#endregion - - //#region Tunnel class SimpleTunnelService implements ITunnelService { diff --git a/src/vs/workbench/workbench.desktop.sandbox.main.ts b/src/vs/workbench/workbench.desktop.sandbox.main.ts index 1d2f2a4150d..bd234a58591 100644 --- a/src/vs/workbench/workbench.desktop.sandbox.main.ts +++ b/src/vs/workbench/workbench.desktop.sandbox.main.ts @@ -39,5 +39,7 @@ import 'vs/workbench/electron-sandbox/desktop.main'; //#region --- workbench contributions +// Webview (using the iframe based solution) +import 'vs/workbench/contrib/webview/browser/webview.web.contribution'; //#endregion From fe1547c251baf95dc2b851849bdfea11d2070719 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 25 May 2021 23:01:41 -0700 Subject: [PATCH 109/140] Merge pull request #124621 from microsoft/roblou/diffNotificationMessage Don't rerender notification when content did not change --- src/vs/workbench/common/notifications.ts | 6 ++++- .../test/common/notifications.test.ts | 26 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index fb465bf963c..c718fbc18f9 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -619,13 +619,17 @@ export class NotificationViewItem extends Disposable implements INotificationVie } updateSeverity(severity: Severity): void { + if (severity === this._severity) { + return; + } + this._severity = severity; this._onDidChangeContent.fire({ kind: NotificationViewItemContentChangeKind.SEVERITY }); } updateMessage(input: NotificationMessage): void { const message = NotificationViewItem.parseNotificationMessage(input); - if (!message) { + if (!message || message.raw === this._message.raw) { return; } diff --git a/src/vs/workbench/test/common/notifications.test.ts b/src/vs/workbench/test/common/notifications.test.ts index 600c0e81579..12efcb72da5 100644 --- a/src/vs/workbench/test/common/notifications.test.ts +++ b/src/vs/workbench/test/common/notifications.test.ts @@ -10,6 +10,7 @@ import { INotification, Severity, NotificationsFilter } from 'vs/platform/notifi import { createErrorWithActions } from 'vs/base/common/errors'; import { NotificationService } from 'vs/workbench/services/notification/common/notificationService'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; +import { timeout } from 'vs/base/common/async'; suite('Notifications', () => { @@ -143,6 +144,23 @@ suite('Notifications', () => { assert.strictEqual(item11.silent, true); }); + test('Items - does not fire changed when message did not change (content, severity)', async () => { + const item1 = NotificationViewItem.create({ severity: Severity.Error, message: 'Error Message' })!; + + let fired = false; + item1.onDidChangeContent(() => { + fired = true; + }); + + item1.updateMessage('Error Message'); + await timeout(0); + assert.ok(!fired, 'Expected onDidChangeContent to not be fired'); + + item1.updateSeverity(Severity.Error); + await timeout(0); + assert.ok(!fired, 'Expected onDidChangeContent to not be fired'); + }); + test('Model', () => { const model = new NotificationsModel(); @@ -167,11 +185,11 @@ suite('Notifications', () => { assert.strictEqual(lastNotificationEvent.index, 0); assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.ADD); - item1Handle.updateMessage('Error Message'); + item1Handle.updateMessage('Different Error Message'); assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE); assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.MESSAGE); - item1Handle.updateSeverity(Severity.Error); + item1Handle.updateSeverity(Severity.Warning); assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.CHANGE); assert.strictEqual(lastNotificationEvent.detail, NotificationViewItemContentChangeKind.SEVERITY); @@ -205,8 +223,8 @@ suite('Notifications', () => { item1Handle.close(); assert.strictEqual(called, 1); assert.strictEqual(model.notifications.length, 2); - assert.strictEqual(lastNotificationEvent.item.severity, item1.severity); - assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), item1.message); + assert.strictEqual(lastNotificationEvent.item.severity, Severity.Warning); + assert.strictEqual(lastNotificationEvent.item.message.linkedText.toString(), 'Different Error Message'); assert.strictEqual(lastNotificationEvent.index, 2); assert.strictEqual(lastNotificationEvent.kind, NotificationChangeType.REMOVE); From d0884f4a1ec5800be0a3fed52418b574aa8e4e95 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 26 May 2021 08:24:55 +0200 Subject: [PATCH 110/140] webview - clear group listener when it gets disposed //cc @lramos15 --- .../browser/webviewPanel.contribution.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewPanel.contribution.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewPanel.contribution.ts index 9e92bad8fac..1f4c3d0d35b 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewPanel.contribution.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewPanel.contribution.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { Event } from 'vs/base/common/event'; +import { Disposable } from 'vs/base/common/lifecycle'; import { localize } from 'vs/nls'; import { registerAction2 } from 'vs/platform/actions/common/actions'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; @@ -28,26 +29,28 @@ import { IWebviewWorkbenchService, WebviewEditorService } from './webviewWorkben class WebviewPanelContribution extends Disposable implements IWorkbenchContribution { - private readonly _disposables = new DisposableStore(); constructor( @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService, ) { super(); + // Add all the initial groups to be listened to this.editorGroupService.whenReady.then(() => this.editorGroupService.groups.forEach(group => { this.registerGroupListener(group); })); // Additional groups added should also be listened to - this._register(this.editorGroupService.onDidAddGroup((group) => this.registerGroupListener(group))); - - this._register(this._disposables); + this._register(this.editorGroupService.onDidAddGroup(group => this.registerGroupListener(group))); } private registerGroupListener(group: IEditorGroup): void { const listener = group.onWillOpenEditor(e => this.onEditorOpening(e.editor, group)); - this._disposables.add(listener); + + Event.once(group.onWillDispose)(() => { + listener.dispose(); + }); } + private onEditorOpening( editor: IEditorInput, group: IEditorGroup @@ -74,7 +77,6 @@ class WebviewPanelContribution extends Disposable implements IWorkbenchContribut } previousGroup.closeEditor(editor); - } } @@ -87,7 +89,6 @@ Registry.as(EditorExtensions.EditorInputFactories). registerSingleton(IWebviewWorkbenchService, WebviewEditorService, true); - registerAction2(ShowWebViewEditorFindWidgetAction); registerAction2(HideWebViewEditorFindCommand); registerAction2(WebViewEditorFindNextCommand); From 5e146d257b55a4786bb3655f640d2b0b660aba97 Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Wed, 26 May 2021 08:28:28 +0200 Subject: [PATCH 111/140] Update classifier.json --- .github/classifier.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/classifier.json b/.github/classifier.json index 8e580003259..f463847c898 100644 --- a/.github/classifier.json +++ b/.github/classifier.json @@ -113,7 +113,7 @@ "php": {"assign": ["roblourens"]}, "portable-mode": {"assign": ["joaomoreno"]}, "proxy": {"assign": []}, - "quick-pick": {"assign": ["chrmarti"]}, + "quick-pick": {"assign": ["TylerLeonhardt"]}, "references-viewlet": {"assign": ["jrieken"]}, "release-notes": {"assign": []}, "remote": {"assign": []}, From 04f585a580af66c825ed8ce078130c34edb4defc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Fri, 21 May 2021 14:54:24 +0200 Subject: [PATCH 112/140] cleanup interfaces --- .../common/extensionGalleryService.ts | 119 +++++++++--------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index 572effc70a9..068a23e52db 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -25,48 +25,48 @@ import { optional } from 'vs/platform/instantiation/common/instantiation'; import { joinPath } from 'vs/base/common/resources'; interface IRawGalleryExtensionFile { - assetType: string; - source: string; + readonly assetType: string; + readonly source: string; } interface IRawGalleryExtensionProperty { - key: string; - value: string; + readonly key: string; + readonly value: string; } interface IRawGalleryExtensionVersion { - version: string; - lastUpdated: string; - assetUri: string; - fallbackAssetUri: string; - files: IRawGalleryExtensionFile[]; - properties?: IRawGalleryExtensionProperty[]; + readonly version: string; + readonly lastUpdated: string; + readonly assetUri: string; + readonly fallbackAssetUri: string; + readonly files: IRawGalleryExtensionFile[]; + readonly properties?: IRawGalleryExtensionProperty[]; } interface IRawGalleryExtensionStatistics { - statisticName: string; - value: number; + readonly statisticName: string; + readonly value: number; } interface IRawGalleryExtension { - extensionId: string; - extensionName: string; - displayName: string; - shortDescription: string; - publisher: { displayName: string, publisherId: string, publisherName: string; }; - versions: IRawGalleryExtensionVersion[]; - statistics: IRawGalleryExtensionStatistics[]; - flags: string; + readonly extensionId: string; + readonly extensionName: string; + readonly displayName: string; + readonly shortDescription: string; + readonly publisher: { displayName: string, publisherId: string, publisherName: string; }; + readonly versions: IRawGalleryExtensionVersion[]; + readonly statistics: IRawGalleryExtensionStatistics[]; + readonly flags: string; } interface IRawGalleryQueryResult { - results: { - extensions: IRawGalleryExtension[]; - resultMetadata: { - metadataType: string; - metadataItems: { - name: string; - count: number; + readonly results: { + readonly extensions: IRawGalleryExtension[]; + readonly resultMetadata: { + readonly metadataType: string; + readonly metadataItems: { + readonly name: string; + readonly count: number; }[]; }[] }[]; @@ -121,20 +121,20 @@ const PropertyType = { }; interface ICriterium { - filterType: FilterType; - value?: string; + readonly filterType: FilterType; + readonly value?: string; } const DefaultPageSize = 10; interface IQueryState { - pageNumber: number; - pageSize: number; - sortBy: SortBy; - sortOrder: SortOrder; - flags: Flags; - criteria: ICriterium[]; - assetTypes: string[]; + readonly pageNumber: number; + readonly pageSize: number; + readonly sortBy: SortBy; + readonly sortOrder: SortOrder; + readonly flags: Flags; + readonly criteria: ICriterium[]; + readonly assetTypes: string[]; } const DefaultQueryState: IQueryState = { @@ -148,32 +148,32 @@ const DefaultQueryState: IQueryState = { }; type GalleryServiceQueryClassification = { - filterTypes: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - sortBy: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - sortOrder: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - duration: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', 'isMeasurement': true }; - success: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - requestBodySize: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - responseBodySize?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - statusCode?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - errorCode?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; - count?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + readonly filterTypes: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + readonly sortBy: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + readonly sortOrder: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + readonly duration: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', 'isMeasurement': true }; + readonly success: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + readonly requestBodySize: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + readonly responseBodySize?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + readonly statusCode?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + readonly errorCode?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; + readonly count?: { classification: 'SystemMetaData', purpose: 'FeatureInsight' }; }; type QueryTelemetryData = { - filterTypes: string[]; - sortBy: string; - sortOrder: string; + readonly filterTypes: string[]; + readonly sortBy: string; + readonly sortOrder: string; }; type GalleryServiceQueryEvent = QueryTelemetryData & { - duration: number; - success: boolean; - requestBodySize: string; - responseBodySize?: string; - statusCode?: string; - errorCode?: string; - count?: string; + readonly duration: number; + readonly success: boolean; + readonly requestBodySize: string; + readonly responseBodySize?: string; + readonly statusCode?: string; + readonly errorCode?: string; + readonly count?: string; }; class Query { @@ -813,9 +813,10 @@ export class ExtensionGalleryService implements IExtensionGalleryService { return this.getLastValidExtensionVersionRecursively(extension, versions.slice(1)); } - version.properties = version.properties || []; - version.properties.push({ key: PropertyType.Engine, value: engine }); - return version; + return { + ...version, + properties: [...(version.properties || []), { key: PropertyType.Engine, value: engine }] + }; } async getExtensionsReport(): Promise { From 47d00215affbf8f1b13b602bac1a3fc9c7009204 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 26 May 2021 09:37:46 +0200 Subject: [PATCH 113/140] editors - cleanup untyped editor interfaces for text capabilities --- .../browser/services/codeEditorService.ts | 4 +- .../browser/standaloneCodeServiceImpl.ts | 4 +- .../browser/services/openerService.test.ts | 39 ++++---- src/vs/platform/editor/common/editor.ts | 62 ++++++++----- src/vs/workbench/browser/dnd.ts | 6 +- src/vs/workbench/browser/layout.ts | 10 +- .../browser/parts/editor/editorCommands.ts | 4 +- .../browser/parts/editor/editorDropTarget.ts | 14 ++- src/vs/workbench/common/editor.ts | 22 ++--- .../bulkEdit/browser/preview/bulkEditPane.ts | 4 +- .../files/browser/editors/fileEditorInput.ts | 4 +- .../contrib/files/browser/fileActions.ts | 9 +- .../contrib/files/browser/fileCommands.ts | 8 +- .../workbench/contrib/files/common/files.ts | 4 +- .../browser/diff/notebookDiffActions.ts | 18 ++-- .../notebook/browser/notebookBrowser.ts | 6 +- .../contrib/search/browser/replaceService.ts | 4 +- .../tasks/browser/abstractTaskService.ts | 4 +- .../userDataSync/browser/userDataSync.ts | 4 +- .../browser/userDataSyncMergesView.ts | 4 +- src/vs/workbench/electron-sandbox/window.ts | 6 +- .../services/editor/browser/editorService.ts | 92 ++++++++----------- .../services/editor/common/editorService.ts | 7 +- .../editor/test/browser/editorService.test.ts | 19 ++-- .../host/browser/browserHostService.ts | 4 +- .../common/untitledTextEditorInput.ts | 4 +- 26 files changed, 183 insertions(+), 183 deletions(-) diff --git a/src/vs/editor/browser/services/codeEditorService.ts b/src/vs/editor/browser/services/codeEditorService.ts index 8665de00275..826082df700 100644 --- a/src/vs/editor/browser/services/codeEditorService.ts +++ b/src/vs/editor/browser/services/codeEditorService.ts @@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/event'; import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { IDecorationRenderOptions } from 'vs/editor/common/editorCommon'; import { IModelDecorationOptions, ITextModel } from 'vs/editor/common/model'; -import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; @@ -52,5 +52,5 @@ export interface ICodeEditorService { getTransientModelProperties(model: ITextModel): [string, any][] | undefined; getActiveCodeEditor(): ICodeEditor | null; - openCodeEditor(input: IResourceEditorInput, source: ICodeEditor | null, sideBySide?: boolean): Promise; + openCodeEditor(input: ITextResourceEditorInput, source: ICodeEditor | null, sideBySide?: boolean): Promise; } diff --git a/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts b/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts index e14ce169335..8bc8c9d7c10 100644 --- a/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts +++ b/src/vs/editor/standalone/browser/standaloneCodeServiceImpl.ts @@ -12,7 +12,7 @@ import { IRange } from 'vs/editor/common/core/range'; import { ScrollType } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { IResourceEditorInput, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IThemeService } from 'vs/platform/theme/common/themeService'; export class StandaloneCodeEditorServiceImpl extends CodeEditorServiceImpl { @@ -59,7 +59,7 @@ export class StandaloneCodeEditorServiceImpl extends CodeEditorServiceImpl { return Promise.resolve(this.doOpenEditor(source, input)); } - private doOpenEditor(editor: ICodeEditor, input: IResourceEditorInput): ICodeEditor | null { + private doOpenEditor(editor: ICodeEditor, input: ITextResourceEditorInput): ICodeEditor | null { const model = this.findModel(editor, input.resource); if (!model) { if (input.resource) { diff --git a/src/vs/editor/test/browser/services/openerService.test.ts b/src/vs/editor/test/browser/services/openerService.test.ts index ffcb441ad89..fe11e474509 100644 --- a/src/vs/editor/test/browser/services/openerService.test.ts +++ b/src/vs/editor/test/browser/services/openerService.test.ts @@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri'; import { OpenerService } from 'vs/editor/browser/services/openerService'; import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices'; import { CommandsRegistry, ICommandService, NullCommandService } from 'vs/platform/commands/common/commands'; +import { ITextEditorOptions } from 'vs/platform/editor/common/editor'; import { matchesScheme } from 'vs/platform/opener/common/opener'; suite('OpenerService', function () { @@ -32,28 +33,28 @@ suite('OpenerService', function () { test('delegate to editorService, scheme:///fff', async function () { const openerService = new OpenerService(editorService, NullCommandService); await openerService.open(URI.parse('another:///somepath')); - assert.strictEqual(editorService.lastInput!.options!.selection, undefined); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection, undefined); }); test('delegate to editorService, scheme:///fff#L123', async function () { const openerService = new OpenerService(editorService, NullCommandService); await openerService.open(URI.parse('file:///somepath#L23')); - assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23); - assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 1); - assert.strictEqual(editorService.lastInput!.options!.selection!.endLineNumber, undefined); - assert.strictEqual(editorService.lastInput!.options!.selection!.endColumn, undefined); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 1); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endLineNumber, undefined); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endColumn, undefined); assert.strictEqual(editorService.lastInput!.resource.fragment, ''); await openerService.open(URI.parse('another:///somepath#L23')); - assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23); - assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 1); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 1); await openerService.open(URI.parse('another:///somepath#L23,45')); - assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23); - assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 45); - assert.strictEqual(editorService.lastInput!.options!.selection!.endLineNumber, undefined); - assert.strictEqual(editorService.lastInput!.options!.selection!.endColumn, undefined); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 45); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endLineNumber, undefined); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endColumn, undefined); assert.strictEqual(editorService.lastInput!.resource.fragment, ''); }); @@ -61,17 +62,17 @@ suite('OpenerService', function () { const openerService = new OpenerService(editorService, NullCommandService); await openerService.open(URI.parse('file:///somepath#23')); - assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23); - assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 1); - assert.strictEqual(editorService.lastInput!.options!.selection!.endLineNumber, undefined); - assert.strictEqual(editorService.lastInput!.options!.selection!.endColumn, undefined); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 1); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endLineNumber, undefined); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endColumn, undefined); assert.strictEqual(editorService.lastInput!.resource.fragment, ''); await openerService.open(URI.parse('file:///somepath#23,45')); - assert.strictEqual(editorService.lastInput!.options!.selection!.startLineNumber, 23); - assert.strictEqual(editorService.lastInput!.options!.selection!.startColumn, 45); - assert.strictEqual(editorService.lastInput!.options!.selection!.endLineNumber, undefined); - assert.strictEqual(editorService.lastInput!.options!.selection!.endColumn, undefined); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startLineNumber, 23); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.startColumn, 45); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endLineNumber, undefined); + assert.strictEqual((editorService.lastInput!.options as ITextEditorOptions)!.selection!.endColumn, undefined); assert.strictEqual(editorService.lastInput!.resource.fragment, ''); }); diff --git a/src/vs/platform/editor/common/editor.ts b/src/vs/platform/editor/common/editor.ts index 2f3866f2b0f..988855fc478 100644 --- a/src/vs/platform/editor/common/editor.ts +++ b/src/vs/platform/editor/common/editor.ts @@ -37,17 +37,17 @@ export interface IEditorModel { export interface IBaseResourceEditorInput { /** - * Optional options to use when opening the text input. + * Optional options to use when opening the input. */ - options?: ITextEditorOptions; + options?: IEditorOptions; /** - * Label to show for the diff editor + * Label to show for the input. */ readonly label?: string; /** - * Description to show for the diff editor + * Description to show for the input. */ readonly description?: string; @@ -70,6 +70,41 @@ export interface IBaseResourceEditorInput { readonly forceUntitled?: boolean; } +export interface IBaseTextResourceEditorInput extends IBaseResourceEditorInput { + + /** + * Optional options to use when opening the text input. + */ + options?: ITextEditorOptions; + + /** + * The encoding of the text input if known. + */ + readonly encoding?: string; + + /** + * The identifier of the language mode of the text input + * if known to use when displaying the contents. + */ + readonly mode?: string; +} + +export interface IResourceEditorInput extends IBaseResourceEditorInput { + + /** + * The resource URI of the resource to open. + */ + readonly resource: URI; +} + +export interface ITextResourceEditorInput extends IResourceEditorInput, IBaseTextResourceEditorInput { + + /** + * Optional options to use when opening the text input. + */ + options?: ITextEditorOptions; +} + /** * This identifier allows to uniquely identify an editor with a * resource and type identifier. @@ -87,25 +122,6 @@ export interface IResourceEditorInputIdentifier { readonly typeId: string; } -export interface IResourceEditorInput extends IBaseResourceEditorInput { - - /** - * The resource URI of the resource to open. - */ - readonly resource: URI; - - /** - * The encoding of the text input if known. - */ - readonly encoding?: string; - - /** - * The identifier of the language mode of the text input - * if known to use when displaying the contents. - */ - readonly mode?: string; -} - export enum EditorActivation { /** diff --git a/src/vs/workbench/browser/dnd.ts b/src/vs/workbench/browser/dnd.ts index b464dcd2a3c..bb2697230d0 100644 --- a/src/vs/workbench/browser/dnd.ts +++ b/src/vs/workbench/browser/dnd.ts @@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { bufferToReadable, VSBuffer } from 'vs/base/common/buffer'; import { FileAccess, Schemas } from 'vs/base/common/network'; -import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd'; import { DragMouseEvent } from 'vs/base/browser/mouseEvent'; import { normalizeDriveLetter } from 'vs/base/common/labels'; @@ -55,7 +55,7 @@ interface IDraggedResource { isExternal?: boolean; } -interface IDraggedEditor extends IResourceEditorInput { +interface IDraggedEditor extends ITextResourceEditorInput { contents?: string; isExternal?: boolean; } @@ -346,7 +346,7 @@ export function fillResourceDragTransfers(accessor: ServicesAccessor, resourcesO for (const resourceOrEditor of resourcesOrEditors) { // Extract resource editor from provided object or URI - let editor: IResourceEditorInput | undefined = undefined; + let editor: ITextResourceEditorInput | undefined = undefined; if (isEditorIdentifier(resourceOrEditor)) { editor = resourceOrEditor.editor.asResourceEditorInput(resourceOrEditor.groupId); } else { diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 0c8569dff0a..d713601925e 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -10,7 +10,7 @@ import { onDidChangeFullscreen, isFullscreen } from 'vs/base/browser/browser'; import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup'; import { Registry } from 'vs/platform/registry/common/platform'; import { isWindows, isLinux, isMacintosh, isWeb, isNative } from 'vs/base/common/platform'; -import { pathsToEditors } from 'vs/workbench/common/editor'; +import { IResourceDiffEditorInput, pathsToEditors } from 'vs/workbench/common/editor'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart'; import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart'; @@ -601,12 +601,14 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi // Files to diff is exclusive return pathsToEditors(initialFilesToOpen.filesToDiff, fileService).then(filesToDiff => { if (filesToDiff.length === 2) { - return [{ - leftResource: filesToDiff[0].resource, - rightResource: filesToDiff[1].resource, + const diffEditorInput: IResourceDiffEditorInput[] = [{ + leftEditor: { resource: filesToDiff[0].resource }, + rightEditor: { resource: filesToDiff[1].resource }, options: { pinned: true }, forceFile: true }]; + + return diffEditorInput; } // Otherwise: Open/Create files diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 44f83d3e69e..295aa1c366c 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -460,8 +460,8 @@ function registerOpenEditorAPICommands(): void { const [options, column] = mixinContext(context, optionsArg, columnArg); await editorService.openEditor({ - leftResource: URI.revive(leftResource), - rightResource: URI.revive(rightResource), + leftEditor: { resource: URI.revive(leftResource) }, + rightEditor: { resource: URI.revive(rightResource) }, label, options }, viewColumnToEditorGroup(editorGroupService, column)); diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index 4092e7396a5..10cecdf94a4 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -332,18 +332,16 @@ class DropOverlay extends Themable { proposedFilePath = joinPath(defaultFilePath, name); } - // Open as untitled text file with the provided contents - const untitledTextEditor = this.editorService.createEditorInput({ - resource: proposedFilePath, - forceUntitled: true, - contents: VSBuffer.wrap(new Uint8Array(event.target.result)).toString() - }); - if (!targetGroup) { targetGroup = ensureTargetGroup(); } - await this.editorService.openEditor(untitledTextEditor, undefined, targetGroup.id); + // Open as untitled text file with the provided contents + await this.editorService.openEditor({ + resource: proposedFilePath, + forceUntitled: true, + contents: VSBuffer.wrap(new Uint8Array(event.target.result)).toString() + }, targetGroup.id); } }; } diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index 86069b6bfd7..b11b7d6a3a9 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -9,7 +9,7 @@ import { assertIsDefined, isUndefinedOrNull } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { IEditor, IEditorViewState, IDiffEditor } from 'vs/editor/common/editorCommon'; -import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceEditorInput, IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceEditorInput, IResourceEditorInput, ITextResourceEditorInput, IBaseTextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IInstantiationService, IConstructorSignature0, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation'; import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -275,7 +275,7 @@ export interface IEditorInputSerializer { deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): IEditorInput | undefined; } -export interface IUntitledTextResourceEditorInput extends IBaseResourceEditorInput { +export interface IUntitledTextResourceEditorInput extends IBaseTextResourceEditorInput { /** * Optional resource. If the resource is not provided a new untitled file is created (e.g. Untitled-1). @@ -285,33 +285,23 @@ export interface IUntitledTextResourceEditorInput extends IBaseResourceEditorInp */ readonly resource?: URI; - /** - * Optional language of the untitled resource. - */ - readonly mode?: string; - /** * Optional contents of the untitled resource. */ readonly contents?: string; - - /** - * Optional encoding of the untitled resource. - */ - readonly encoding?: string; } export interface IResourceDiffEditorInput extends IBaseResourceEditorInput { /** - * The left hand side URI to open inside a diff editor. + * The left hand side editor to open inside a diff editor. */ - readonly leftResource: URI; + readonly leftEditor: IResourceEditorInput | ITextResourceEditorInput | IUntitledTextResourceEditorInput; /** - * The right hand side URI to open inside a diff editor. + * The right hand side editor to open inside a diff editor. */ - readonly rightResource: URI; + readonly rightEditor: IResourceEditorInput | ITextResourceEditorInput | IUntitledTextResourceEditorInput; } export const enum Verbosity { diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts index 6cf35182be6..2f0adb1d28c 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts @@ -353,8 +353,8 @@ export class BulkEditPane extends ViewPane { } this._editorService.openEditor({ - leftResource, - rightResource: previewUri, + leftEditor: { resource: leftResource }, + rightEditor: { resource: previewUri }, label, description: this._labelService.getUriLabel(dirname(leftResource), { relative: true }), options diff --git a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts index 547c9050b07..66b0b4344fd 100644 --- a/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts +++ b/src/vs/workbench/contrib/files/browser/editors/fileEditorInput.ts @@ -6,7 +6,7 @@ import { URI } from 'vs/base/common/uri'; import { IFileEditorInput, Verbosity, GroupIdentifier, IMoveResult, EditorInputCapabilities, IEditorDescriptor, IEditorPane } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; -import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { FileOperationError, FileOperationResult, FileSystemProviderCapabilities, IFileService } from 'vs/platform/files/common/files'; import { ITextFileService, TextFileEditorModelState, TextFileResolveReason, TextFileOperationError, TextFileOperationResult, ITextFileEditorModel, EncodingMode } from 'vs/workbench/services/textfile/common/textfiles'; @@ -360,7 +360,7 @@ export class FileEditorInput extends AbstractTextResourceEditorInput implements }; } - override asResourceEditorInput(group: GroupIdentifier): IResourceEditorInput | undefined { + override asResourceEditorInput(group: GroupIdentifier): ITextResourceEditorInput | undefined { return { resource: this.preferredResource, encoding: this.getEncoding(), diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index df99b2a38c8..f286d0f3c3a 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -454,8 +454,8 @@ export class GlobalCompareResourcesAction extends Action { const resource = (picks[0] as unknown as { resource: unknown }).resource; if (URI.isUri(resource) && this.textModelService.canHandleResource(resource)) { this.editorService.openEditor({ - leftResource: activeResource, - rightResource: resource, + leftEditor: { resource: activeResource }, + rightEditor: { resource: resource }, options: { pinned: true } }); } @@ -730,8 +730,9 @@ export class CompareWithClipboardAction extends Action { const editorLabel = nls.localize('clipboardComparisonLabel', "Clipboard ↔ {0}", name); await this.editorService.openEditor({ - leftResource: resource.with({ scheme }), - rightResource: resource, label: editorLabel, + leftEditor: { resource: resource.with({ scheme }) }, + rightEditor: { resource: resource }, + label: editorLabel, options: { pinned: true } }).finally(() => { dispose(this.registrationDisposal); diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index 2a378027973..56fd4af0e55 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -244,8 +244,8 @@ CommandsRegistry.registerCommand({ if (resources.length === 2) { return editorService.openEditor({ - leftResource: resources[0], - rightResource: resources[1], + leftEditor: { resource: resources[0] }, + rightEditor: { resource: resources[1] }, options: { pinned: true } }); } @@ -263,8 +263,8 @@ CommandsRegistry.registerCommand({ const rightResource = getResourceForCommand(resource, listService, editorService); if (globalResourceToCompare && rightResource) { editorService.openEditor({ - leftResource: globalResourceToCompare, - rightResource, + leftEditor: { resource: globalResourceToCompare }, + rightEditor: { resource: rightResource }, options: { pinned: true } }); } diff --git a/src/vs/workbench/contrib/files/common/files.ts b/src/vs/workbench/contrib/files/common/files.ts index 99ad007e77e..de57c784bdf 100644 --- a/src/vs/workbench/contrib/files/common/files.ts +++ b/src/vs/workbench/contrib/files/common/files.ts @@ -132,8 +132,8 @@ export class TextFileContentProvider extends Disposable implements ITextModelCon static async open(resource: URI, scheme: string, label: string, editorService: IEditorService, options?: ITextEditorOptions): Promise { await editorService.openEditor({ - leftResource: TextFileContentProvider.resourceToTextFile(scheme, resource), - rightResource: resource, + leftEditor: { resource: TextFileContentProvider.resourceToTextFile(scheme, resource) }, + rightEditor: { resource }, label, options }); diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts index ededf65643a..4c0dc00df13 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffActions.ts @@ -45,15 +45,17 @@ registerAction2(class extends Action2 { const activeEditor = editorService.activeEditorPane; if (activeEditor && activeEditor instanceof NotebookTextDiffEditor) { const diffEditorInput = activeEditor.input as NotebookDiffEditorInput; - const leftResource = diffEditorInput.originalResource; - const rightResource = diffEditorInput.resource; - const options = { - preserveFocus: false - }; - const label = diffEditorInput.textDiffName; - const input = editorService.createEditorInput({ leftResource, rightResource, label, options }); - await editorService.openEditor(input, { override: EditorOverride.DISABLED }, viewColumnToEditorGroup(editorGroupService, undefined)); + await editorService.openEditor( + { + leftEditor: { resource: diffEditorInput.originalResource }, + rightEditor: { resource: diffEditorInput.resource }, + label: diffEditorInput.textDiffName, + options: { + preserveFocus: false, + override: EditorOverride.DISABLED + } + }, viewColumnToEditorGroup(editorGroupService, undefined)); } } }); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index f08f9a00b7a..a4c34466eae 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -27,7 +27,7 @@ import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { IMenu } from 'vs/platform/actions/common/actions'; import { IEditorPane } from 'vs/workbench/common/editor'; -import { IEditorOptions, IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { ITextEditorOptions, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation'; import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets'; import { INotebookWebviewMessage } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView'; @@ -323,8 +323,8 @@ export interface INotebookDeltaCellStatusBarItems { items: INotebookCellStatusBarItem[]; } -export interface INotebookEditorOptions extends IEditorOptions { - readonly cellOptions?: IResourceEditorInput; +export interface INotebookEditorOptions extends ITextEditorOptions { + readonly cellOptions?: ITextResourceEditorInput; readonly cellSelections?: ICellRange[]; readonly isReadOnly?: boolean; } diff --git a/src/vs/workbench/contrib/search/browser/replaceService.ts b/src/vs/workbench/contrib/search/browser/replaceService.ts index e34e10c1bd7..ded6614d0c2 100644 --- a/src/vs/workbench/contrib/search/browser/replaceService.ts +++ b/src/vs/workbench/contrib/search/browser/replaceService.ts @@ -113,8 +113,8 @@ export class ReplaceService implements IReplaceService { const fileMatch = element instanceof Match ? element.parent() : element; const editor = await this.editorService.openEditor({ - leftResource: fileMatch.resource, - rightResource: toReplaceResource(fileMatch.resource), + leftEditor: { resource: fileMatch.resource }, + rightEditor: { resource: toReplaceResource(fileMatch.resource) }, label: nls.localize('fileReplaceChanges', "{0} ↔ {1} (Replace Preview)", fileMatch.name(), fileMatch.name()), description: this.labelService.getUriLabel(dirname(fileMatch.resource), { relative: true }), options: { diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 49d5b578354..cf3b107085d 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -3320,8 +3320,8 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer run: async () => { for (const upgrade of fileDiffs) { await this.editorService.openEditor({ - leftResource: upgrade[0], - rightResource: upgrade[1], + leftEditor: { resource: upgrade[0] }, + rightEditor: { resource: upgrade[1] } }); } } diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 9e443a31a49..e7f96b1e96c 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -684,8 +684,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo const leftResourceName = localize({ key: 'leftResourceName', comment: ['remote as in file in cloud'] }, "{0} (Remote)", basename(conflict.remoteResource)); const rightResourceName = localize('merges', "{0} (Merges)", basename(conflict.previewResource)); await this.editorService.openEditor({ - leftResource: conflict.remoteResource, - rightResource: conflict.previewResource, + leftEditor: { resource: conflict.remoteResource }, + rightEditor: { resource: conflict.previewResource }, label: localize('sideBySideLabels', "{0} ↔ {1}", leftResourceName, rightResourceName), description: localize('sideBySideDescription', "Settings Sync"), options: { diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncMergesView.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncMergesView.ts index cb0c35e2c0d..2797dcebc01 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncMergesView.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncMergesView.ts @@ -315,8 +315,8 @@ export class UserDataSyncMergesViewPane extends TreeViewPane { const rightResourceName = previewResource.mergeState === MergeState.Conflict ? localize('merges', "{0} (Merges)", basename(rightResource)) : localize({ key: 'rightResourceName', comment: ['local as in file in disk'] }, "{0} (Local)", basename(rightResource)); await this.editorService.openEditor({ - leftResource, - rightResource, + leftEditor: { resource: leftResource }, + rightEditor: { resource: rightResource }, label: localize('sideBySideLabels', "{0} ↔ {1}", leftResourceName, rightResourceName), description: localize('sideBySideDescription', "Settings Sync"), options: { diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts index 2035ba6adce..ca69b90ac30 100644 --- a/src/vs/workbench/electron-sandbox/window.ts +++ b/src/vs/workbench/electron-sandbox/window.ts @@ -673,7 +673,11 @@ export class NativeWindow extends Disposable { // In diffMode we open 2 resources as diff if (diffMode && resources.length === 2 && resources[0].resource && resources[1].resource) { - return this.editorService.openEditor({ leftResource: resources[0].resource, rightResource: resources[1].resource, options: { pinned: true } }); + return this.editorService.openEditor({ + leftEditor: { resource: resources[0].resource }, + rightEditor: { resource: resources[1].resource }, + options: { pinned: true } + }); } // Open resource(s) diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index d1b973738e9..d86a7f7c49e 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IResourceEditorInput, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier, ITextEditorOptions } from 'vs/platform/editor/common/editor'; +import { IResourceEditorInput, IEditorOptions, EditorActivation, EditorOverride, IResourceEditorInputIdentifier, ITextEditorOptions, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { SideBySideEditor, IEditorInput, IEditorPane, GroupIdentifier, IFileEditorInput, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, IEditorInputFactoryRegistry, EditorExtensions, IEditorInputWithOptions, isEditorInputWithOptions, IEditorIdentifier, IEditorCloseEvent, ITextEditorPane, ITextDiffEditorPane, IRevertOptions, SaveReason, EditorsOrder, isTextEditorPane, IWorkbenchEditorConfiguration, EditorResourceAccessor, IVisibleEditorPane, IEditorInputWithOptionsAndGroup, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; @@ -16,7 +16,7 @@ import { IFileService, FileOperationEvent, FileOperation, FileChangesEvent, File import { Schemas } from 'vs/base/common/network'; import { Event, Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; -import { basename, joinPath, isEqual } from 'vs/base/common/resources'; +import { basename, joinPath } from 'vs/base/common/resources'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { IEditorGroupsService, IEditorGroup, GroupsOrder, IEditorReplacement, GroupChangeKind, preferredSideBySideGroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IResourceEditorInputType, SIDE_GROUP, IResourceEditorReplacement, IEditorService, SIDE_GROUP_TYPE, ACTIVE_GROUP_TYPE, ISaveEditorsOptions, ISaveAllEditorsOptions, IRevertAllEditorsOptions, IBaseSaveRevertAllEditorOptions } from 'vs/workbench/services/editor/common/editorService'; @@ -34,8 +34,6 @@ import { Promises, timeout } from 'vs/base/common/async'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { indexOfPath } from 'vs/base/common/extpath'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; -import { IModelService } from 'vs/editor/common/services/modelService'; -import { ILogService } from 'vs/platform/log/common/log'; import { ContributedEditorPriority, DEFAULT_EDITOR_ASSOCIATION, IEditorOverrideService } from 'vs/workbench/services/editor/common/editorOverrideService'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IWorkspaceTrustRequestService, WorkspaceTrustUriResponse } from 'vs/platform/workspace/common/workspaceTrust'; @@ -77,7 +75,6 @@ export class EditorService extends Disposable implements EditorServiceImpl { @IConfigurationService private readonly configurationService: IConfigurationService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IUriIdentityService private readonly uriIdentityService: IUriIdentityService, - @ILogService private readonly logService: ILogService, @IEditorOverrideService private readonly editorOverrideService: IEditorOverrideService, @IWorkingCopyService private readonly workingCopyService: IWorkingCopyService, @IWorkspaceTrustRequestService private readonly workspaceTrustRequestService: IWorkspaceTrustRequestService, @@ -787,9 +784,16 @@ export class EditorService extends Disposable implements EditorServiceImpl { // Untyped editor else { const resourceDiffEditor = editor as IResourceDiffEditorInput; - if (URI.isUri(resourceDiffEditor.leftResource) && URI.isUri(resourceDiffEditor.rightResource)) { - resources.set(resourceDiffEditor.leftResource, true); - resources.set(resourceDiffEditor.rightResource, true); + if (resourceDiffEditor.leftEditor && resourceDiffEditor.rightEditor) { + const leftResourceEditor = resourceDiffEditor.leftEditor as IResourceEditorInput; + if (URI.isUri(leftResourceEditor.resource)) { + resources.set(leftResourceEditor.resource, true); + } + + const rightResourceEditor = resourceDiffEditor.rightEditor as IResourceEditorInput; + if (URI.isUri(rightResourceEditor.resource)) { + resources.set(rightResourceEditor.resource, true); + } } const resourceEditor = editor as IResourceEditorInput; @@ -808,7 +812,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { isOpened(editor: IResourceEditorInputIdentifier): boolean { return this.editorsObserver.hasEditor({ - resource: this.asCanonicalEditorResource(editor.resource), + resource: this.uriIdentityService.asCanonicalUri(editor.resource), typeId: editor.typeId }); } @@ -954,9 +958,9 @@ export class EditorService extends Disposable implements EditorServiceImpl { // Diff Editor Support const resourceDiffInput = input as IResourceDiffEditorInput; - if (resourceDiffInput.leftResource && resourceDiffInput.rightResource) { - const leftInput = this.createEditorInput({ resource: resourceDiffInput.leftResource, forceFile: resourceDiffInput.forceFile }); - const rightInput = this.createEditorInput({ resource: resourceDiffInput.rightResource, forceFile: resourceDiffInput.forceFile }); + if (resourceDiffInput.leftEditor && resourceDiffInput.rightEditor) { + const leftInput = this.createEditorInput({ ...resourceDiffInput.leftEditor, forceFile: resourceDiffInput.forceFile }); + const rightInput = this.createEditorInput({ ...resourceDiffInput.rightEditor, forceFile: resourceDiffInput.forceFile }); return this.instantiationService.createInstance(DiffEditorInput, resourceDiffInput.label, @@ -1003,31 +1007,31 @@ export class EditorService extends Disposable implements EditorServiceImpl { }) as EditorInput; } - // Resource Editor Support - const resourceEditorInput = input as IResourceEditorInput; - if (resourceEditorInput.resource instanceof URI) { + // Text Resource Editor Support + const textResourceEditorInput = input as ITextResourceEditorInput; + if (textResourceEditorInput.resource instanceof URI) { // Derive the label from the path if not provided explicitly - const label = resourceEditorInput.label || basename(resourceEditorInput.resource); + const label = textResourceEditorInput.label || basename(textResourceEditorInput.resource); // We keep track of the preferred resource this input is to be created // with but it may be different from the canonical resource (see below) - const preferredResource = resourceEditorInput.resource; + const preferredResource = textResourceEditorInput.resource; // From this moment on, only operate on the canonical resource // to ensure we reduce the chance of opening the same resource // with different resource forms (e.g. path casing on Windows) - const canonicalResource = this.asCanonicalEditorResource(preferredResource); + const canonicalResource = this.uriIdentityService.asCanonicalUri(preferredResource); return this.createOrGetCached(canonicalResource, () => { // File - if (resourceEditorInput.forceFile || this.fileService.canHandleResource(canonicalResource)) { - return this.fileEditorInputFactory.createFileEditorInput(canonicalResource, preferredResource, resourceEditorInput.label, resourceEditorInput.description, resourceEditorInput.encoding, resourceEditorInput.mode, this.instantiationService); + if (textResourceEditorInput.forceFile || this.fileService.canHandleResource(canonicalResource)) { + return this.fileEditorInputFactory.createFileEditorInput(canonicalResource, preferredResource, textResourceEditorInput.label, textResourceEditorInput.description, textResourceEditorInput.encoding, textResourceEditorInput.mode, this.instantiationService); } // Resource - return this.instantiationService.createInstance(TextResourceEditorInput, canonicalResource, resourceEditorInput.label, resourceEditorInput.description, resourceEditorInput.mode); + return this.instantiationService.createInstance(TextResourceEditorInput, canonicalResource, textResourceEditorInput.label, textResourceEditorInput.description, textResourceEditorInput.mode); }, cachedInput => { // Untitled @@ -1039,20 +1043,20 @@ export class EditorService extends Disposable implements EditorServiceImpl { else if (!(cachedInput instanceof TextResourceEditorInput)) { cachedInput.setPreferredResource(preferredResource); - if (resourceEditorInput.label) { - cachedInput.setPreferredName(resourceEditorInput.label); + if (textResourceEditorInput.label) { + cachedInput.setPreferredName(textResourceEditorInput.label); } - if (resourceEditorInput.description) { - cachedInput.setPreferredDescription(resourceEditorInput.description); + if (textResourceEditorInput.description) { + cachedInput.setPreferredDescription(textResourceEditorInput.description); } - if (resourceEditorInput.encoding) { - cachedInput.setPreferredEncoding(resourceEditorInput.encoding); + if (textResourceEditorInput.encoding) { + cachedInput.setPreferredEncoding(textResourceEditorInput.encoding); } - if (resourceEditorInput.mode) { - cachedInput.setPreferredMode(resourceEditorInput.mode); + if (textResourceEditorInput.mode) { + cachedInput.setPreferredMode(textResourceEditorInput.mode); } } @@ -1062,12 +1066,12 @@ export class EditorService extends Disposable implements EditorServiceImpl { cachedInput.setName(label); } - if (resourceEditorInput.description) { - cachedInput.setDescription(resourceEditorInput.description); + if (textResourceEditorInput.description) { + cachedInput.setDescription(textResourceEditorInput.description); } - if (resourceEditorInput.mode) { - cachedInput.setPreferredMode(resourceEditorInput.mode); + if (textResourceEditorInput.mode) { + cachedInput.setPreferredMode(textResourceEditorInput.mode); } } }) as EditorInput; @@ -1076,28 +1080,6 @@ export class EditorService extends Disposable implements EditorServiceImpl { throw new Error('Unknown input type'); } - private _modelService: IModelService | undefined = undefined; - private get modelService(): IModelService | undefined { - if (!this._modelService) { - this._modelService = this.instantiationService.invokeFunction(accessor => accessor.get(IModelService)); - } - - return this._modelService; - } - - private asCanonicalEditorResource(resource: URI): URI { - const canonicalResource: URI = this.uriIdentityService.asCanonicalUri(resource); - - // In the unlikely case that a model exists for the original resource but - // differs from the canonical resource, we print a warning as this means - // the model will not be able to be opened as editor. - if (!isEqual(resource, canonicalResource) && this.modelService?.getModel(resource)) { - this.logService.warn(`EditorService: a model exists for a resource that is not canonical: ${resource.toString(true)}`); - } - - return canonicalResource; - } - private createOrGetCached(resource: URI, factoryFn: () => CachedEditorInput, cachedFn?: (input: CachedEditorInput) => void): CachedEditorInput { // Return early if already cached diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index a1e447a2295..a8685ea1a47 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IResourceEditorInput, IEditorOptions, IResourceEditorInputIdentifier } from 'vs/platform/editor/common/editor'; +import { IResourceEditorInput, IEditorOptions, IResourceEditorInputIdentifier, ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { IEditorInput, IEditorPane, GroupIdentifier, IEditorInputWithOptions, IUntitledTextResourceEditorInput, IResourceDiffEditorInput, ITextEditorPane, ITextDiffEditorPane, IEditorIdentifier, ISaveOptions, IRevertOptions, EditorsOrder, IVisibleEditorPane, IEditorCloseEvent } from 'vs/workbench/common/editor'; import { Event } from 'vs/base/common/event'; import { IEditor, IDiffEditor } from 'vs/editor/common/editorCommon'; @@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri'; export const IEditorService = createDecorator('editorService'); -export type IResourceEditorInputType = IResourceEditorInput | IUntitledTextResourceEditorInput | IResourceDiffEditorInput; +export type IResourceEditorInputType = IResourceEditorInput | ITextResourceEditorInput | IUntitledTextResourceEditorInput | IResourceDiffEditorInput; export interface IResourceEditorReplacement { readonly editor: IResourceEditorInputType; @@ -158,7 +158,8 @@ export interface IEditorService { * opened to be active. */ openEditor(editor: IEditorInput, options?: IEditorOptions, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; - openEditor(editor: IResourceEditorInput | IUntitledTextResourceEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: IResourceEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; + openEditor(editor: ITextResourceEditorInput | IUntitledTextResourceEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; openEditor(editor: IResourceDiffEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE): Promise; /** diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index 8ce795464cb..65790d5137e 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -8,7 +8,7 @@ import { EditorActivation, EditorOverride } from 'vs/platform/editor/common/edit import { URI } from 'vs/base/common/uri'; import { Event } from 'vs/base/common/event'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; -import { EditorsOrder } from 'vs/workbench/common/editor'; +import { EditorsOrder, IResourceDiffEditorInput } from 'vs/workbench/common/editor'; import { workbenchInstantiationService, TestServiceAccessor, registerTestEditor, TestFileEditorInput, ITestInstantiationService, registerTestResourceEditor, registerTestSideBySideEditor, createEditorPart } from 'vs/workbench/test/browser/workbenchTestServices'; import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService'; @@ -281,7 +281,7 @@ suite('EditorService', () => { const [part, service, accessor] = await createEditorService(); const input = { resource: URI.parse('my://resource-openEditors') }; - const otherInput = { leftResource: URI.parse('my://resource2-openEditors'), rightResource: URI.parse('my://resource3-openEditors') }; + const otherInput: IResourceDiffEditorInput = { leftEditor: { resource: URI.parse('my://resource2-openEditors') }, rightEditor: { resource: URI.parse('my://resource3-openEditors') } }; const oldHandler = accessor.workspaceTrustRequestService.requestOpenUrisHandler; @@ -296,8 +296,8 @@ suite('EditorService', () => { assert.strictEqual(part.activeGroup.count, 0); assert.strictEqual(trustEditorUris.length, 3); assert.strictEqual(trustEditorUris.some(uri => uri.toString() === input.resource.toString()), true); - assert.strictEqual(trustEditorUris.some(uri => uri.toString() === otherInput.leftResource.toString()), true); - assert.strictEqual(trustEditorUris.some(uri => uri.toString() === otherInput.rightResource.toString()), true); + assert.strictEqual(trustEditorUris.some(uri => uri.toString() === otherInput.leftEditor.resource?.toString()), true); + assert.strictEqual(trustEditorUris.some(uri => uri.toString() === otherInput.rightEditor.resource?.toString()), true); } finally { accessor.workspaceTrustRequestService.requestOpenUrisHandler = oldHandler; } @@ -441,11 +441,14 @@ suite('EditorService', () => { assert(input instanceof TextResourceEditorInput); // Untyped Input (diff) - input = service.createEditorInput({ - leftResource: toResource.call(this, '/primary.html'), - rightResource: toResource.call(this, '/secondary.html') - }); + const resourceDiffInput = { + leftEditor: { resource: toResource.call(this, '/primary.html') }, + rightEditor: { resource: toResource.call(this, '/secondary.html') } + }; + input = service.createEditorInput(resourceDiffInput); assert(input instanceof DiffEditorInput); + assert.strictEqual(input.originalInput.resource?.toString(), resourceDiffInput.leftEditor.resource.toString()); + assert.strictEqual(input.modifiedInput.resource?.toString(), resourceDiffInput.rightEditor.resource.toString()); }); test('delegate', function (done) { diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts index 8506a81b357..b3396b2e222 100644 --- a/src/vs/workbench/services/host/browser/browserHostService.ts +++ b/src/vs/workbench/services/host/browser/browserHostService.ts @@ -256,8 +256,8 @@ export class BrowserHostService extends Disposable implements IHostService { // Same Window: open via editor service in current window if (this.shouldReuse(options, true /* file */)) { editorService.openEditor({ - leftResource: editors[0].resource, - rightResource: editors[1].resource, + leftEditor: { resource: editors[0].resource }, + rightEditor: { resource: editors[1].resource }, options: { pinned: true } }); } diff --git a/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts b/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts index 3f270151d8f..74351978f24 100644 --- a/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts +++ b/src/vs/workbench/services/untitled/common/untitledTextEditorInput.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IResourceEditorInput } from 'vs/platform/editor/common/editor'; +import { ITextResourceEditorInput } from 'vs/platform/editor/common/editor'; import { GroupIdentifier, Verbosity } from 'vs/workbench/common/editor'; import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; import { IUntitledTextEditorModel } from 'vs/workbench/services/untitled/common/untitledTextEditorModel'; @@ -116,7 +116,7 @@ export class UntitledTextEditorInput extends AbstractTextResourceEditorInput imp return this.model; } - override asResourceEditorInput(group: GroupIdentifier): IResourceEditorInput | undefined { + override asResourceEditorInput(group: GroupIdentifier): ITextResourceEditorInput | undefined { return { resource: this.model.resource, encoding: this.getEncoding(), From 44b470c99ffdbd76002cd98f1bdd8cc025d4f01f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 09:41:56 +0200 Subject: [PATCH 114/140] fixes #124576 --- src/vs/workbench/api/common/extHost.api.impl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 05e4c4a1d1d..dedcaf765ee 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -321,7 +321,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I return extHostUrls.createAppUri(uri); } - if (!matchesScheme(uri.scheme, Schemas.http) && !matchesScheme(uri.scheme, Schemas.https)) { + if (!matchesScheme(uri, Schemas.http) && !matchesScheme(uri, Schemas.https)) { checkProposedApiEnabled(extension); // https://github.com/microsoft/vscode/issues/124263 } From 14f61093f4312f7730135b9bc4bd97472e58ce04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 10:03:25 +0200 Subject: [PATCH 115/140] fixes #124507 --- src/vs/workbench/api/common/extHost.api.impl.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index dedcaf765ee..77717fcacea 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -316,7 +316,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I allowContributedOpeners: options?.allowContributedOpeners, }); }, - asExternalUri(uri: URI) { + async asExternalUri(uri: URI) { if (uri.scheme === initData.environment.appUriScheme) { return extHostUrls.createAppUri(uri); } @@ -325,7 +325,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I checkProposedApiEnabled(extension); // https://github.com/microsoft/vscode/issues/124263 } - return extHostWindow.asExternalUri(uri, { allowTunneling: !!initData.remote.authority }); + try { + return await extHostWindow.asExternalUri(uri, { allowTunneling: !!initData.remote.authority }); + } catch { + return uri; + } }, get remoteName() { return getRemoteName(initData.remote.authority); From c2cc9b11afea0b209321646b1e634ca50fdaec9d Mon Sep 17 00:00:00 2001 From: Melvin Date: Wed, 26 May 2021 08:05:39 +0000 Subject: [PATCH 116/140] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e38197ccbc7..09f399503e2 100644 --- a/README.md +++ b/README.md @@ -21,11 +21,11 @@ Visual Studio Code is updated monthly with new features and bug fixes. You can d ## Contributing -There are many ways in which you can participate in the project, for example: +There are many ways in which you can participate in this project, for example: * [Submit bugs and feature requests](https://github.com/microsoft/vscode/issues), and help us verify as they are checked in * Review [source code changes](https://github.com/microsoft/vscode/pulls) -* Review the [documentation](https://github.com/microsoft/vscode-docs) and make pull requests for anything from typos to new content +* Review the [documentation](https://github.com/microsoft/vscode-docs) and make pull requests for anything from typos to additional and new content If you are interested in fixing issues and contributing directly to the code base, please see the document [How to Contribute](https://github.com/microsoft/vscode/wiki/How-to-Contribute), which covers the following: From 18b6620bc39e1dcc9e1f57ea43c78c20584e589b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 10:07:00 +0200 Subject: [PATCH 117/140] fixes #123543 --- .../contrib/userDataSync/browser/userDataSyncMergesView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncMergesView.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncMergesView.ts index 2797dcebc01..83bea9244f7 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncMergesView.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncMergesView.ts @@ -419,7 +419,7 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio return editor.getContribution(AcceptChangesContribution.ID); } - public static readonly ID = 'editor.contrib.acceptChangesButton'; + public static readonly ID = 'editor.contrib.acceptChangesButton2'; private acceptChangesButton: FloatingClickWidget | undefined; From 98dc73a32965f2cb0592cb850fbfda5618f15420 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 26 May 2021 11:47:54 +0200 Subject: [PATCH 118/140] unnecessary space in in julia cgmanifest --- extensions/julia/cgmanifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/julia/cgmanifest.json b/extensions/julia/cgmanifest.json index 3b2f492cc6c..e2f4268ed2f 100644 --- a/extensions/julia/cgmanifest.json +++ b/extensions/julia/cgmanifest.json @@ -4,7 +4,7 @@ "component": { "type": "git", "git": { - "name": " JuliaEditorSupport/atom-language-julia", + "name": "JuliaEditorSupport/atom-language-julia", "repositoryUrl": "https://github.com/JuliaEditorSupport/atom-language-julia", "commitHash": "008e02c5ec9440fa9f0ea8a891712c7238f24706" } @@ -14,4 +14,4 @@ } ], "version": 1 -} \ No newline at end of file +} From 0a7a69f1908d72714820f89136b6082071701236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 13:30:43 +0200 Subject: [PATCH 119/140] fix build compilation --- .../common/installPlaywright.js | 2 +- .../azure-pipelines/common/publish-webview.js | 4 ++-- build/darwin/create-universal-app.js | 4 ++-- build/lib/builtInExtensionsCG.js | 2 +- build/lib/compilation.js | 2 +- build/lib/eslint/code-import-patterns.js | 4 ++-- build/lib/eslint/code-layering.js | 8 +++---- .../code-no-nls-in-standalone-editor.js | 4 ++-- build/lib/eslint/code-no-standalone-editor.js | 4 ++-- build/lib/eslint/code-translation-remind.js | 4 ++-- build/lib/extensions.js | 4 ++-- build/lib/i18n.js | 22 +++++++++---------- build/lib/layersChecker.js | 8 +++---- build/lib/nls.js | 6 ++--- build/lib/optimize.js | 4 ++-- build/lib/preLaunch.js | 2 +- build/lib/treeshaking.js | 7 ++++-- build/lib/treeshaking.ts | 10 ++++++--- 18 files changed, 54 insertions(+), 47 deletions(-) diff --git a/build/azure-pipelines/common/installPlaywright.js b/build/azure-pipelines/common/installPlaywright.js index 8321e71aab0..a0454fd69ab 100644 --- a/build/azure-pipelines/common/installPlaywright.js +++ b/build/azure-pipelines/common/installPlaywright.js @@ -9,6 +9,6 @@ const retry_1 = require("./retry"); const { installBrowsersWithProgressBar } = require('playwright/lib/install/installer'); const playwrightPath = path.dirname(require.resolve('playwright')); async function install() { - await retry_1.retry(() => installBrowsersWithProgressBar(playwrightPath)); + await (0, retry_1.retry)(() => installBrowsersWithProgressBar(playwrightPath)); } install(); diff --git a/build/azure-pipelines/common/publish-webview.js b/build/azure-pipelines/common/publish-webview.js index 27804624126..e7d6f67e42d 100644 --- a/build/azure-pipelines/common/publish-webview.js +++ b/build/azure-pipelines/common/publish-webview.js @@ -39,7 +39,7 @@ async function publish(commit, files) { .withFilter(new azure.ExponentialRetryPolicyFilter(20)); await assertContainer(blobService, commit); for (const file of files) { - const blobName = path_1.basename(file); + const blobName = (0, path_1.basename)(file); const blobExists = await doesBlobExist(blobService, commit, blobName); if (blobExists) { console.log(`Blob ${commit}, ${blobName} already exists, not publishing again.`); @@ -58,7 +58,7 @@ function main() { } const opts = minimist(process.argv.slice(2)); const [directory] = opts._; - const files = fileNames.map(fileName => path_1.join(directory, fileName)); + const files = fileNames.map(fileName => (0, path_1.join)(directory, fileName)); publish(commit, files).catch(err => { console.error(err); process.exit(1); diff --git a/build/darwin/create-universal-app.js b/build/darwin/create-universal-app.js index d455a5cef70..92609d0e6b1 100644 --- a/build/darwin/create-universal-app.js +++ b/build/darwin/create-universal-app.js @@ -23,7 +23,7 @@ async function main() { const outAppPath = path.join(buildDir, `VSCode-darwin-${arch}`, appName); const productJsonPath = path.resolve(outAppPath, 'Contents', 'Resources', 'app', 'product.json'); const infoPlistPath = path.resolve(outAppPath, 'Contents', 'Info.plist'); - await vscode_universal_1.makeUniversalApp({ + await (0, vscode_universal_1.makeUniversalApp)({ x64AppPath, arm64AppPath, x64AsarPath, @@ -33,7 +33,7 @@ async function main() { 'Credits.rtf', 'CodeResources', 'fsevents.node', - 'Info.plist', // TODO@deepak1556: regressed with 11.4.2 internal builds + 'Info.plist', '.npmrc' ], outAppPath, diff --git a/build/lib/builtInExtensionsCG.js b/build/lib/builtInExtensionsCG.js index 10bf38f8c8e..64b9064c8e9 100644 --- a/build/lib/builtInExtensionsCG.js +++ b/build/lib/builtInExtensionsCG.js @@ -25,7 +25,7 @@ async function downloadExtensionDetails(extension) { const promises = []; for (const fileName of contentFileNames) { promises.push(new Promise(resolve => { - got_1.default(`${repositoryContentBaseUrl}/${fileName}`) + (0, got_1.default)(`${repositoryContentBaseUrl}/${fileName}`) .then(response => { resolve({ fileName, body: response.rawBody }); }) diff --git a/build/lib/compilation.js b/build/lib/compilation.js index 6fecf3f9ae5..1b7c06fc3f9 100644 --- a/build/lib/compilation.js +++ b/build/lib/compilation.js @@ -17,7 +17,7 @@ const fancyLog = require("fancy-log"); const ansiColors = require("ansi-colors"); const os = require("os"); const watch = require('./watch'); -const reporter = reporter_1.createReporter(); +const reporter = (0, reporter_1.createReporter)(); function getTypeScriptCompilerOptions(src) { const rootDir = path.join(__dirname, `../../${src}`); let options = {}; diff --git a/build/lib/eslint/code-import-patterns.js b/build/lib/eslint/code-import-patterns.js index 0d508d1d00e..97dd154b1d3 100644 --- a/build/lib/eslint/code-import-patterns.js +++ b/build/lib/eslint/code-import-patterns.js @@ -21,7 +21,7 @@ module.exports = new class { const configs = context.options; for (const config of configs) { if (minimatch(context.getFilename(), config.target)) { - return utils_1.createImportRuleListener((node, value) => this._checkImport(context, config, node, value)); + return (0, utils_1.createImportRuleListener)((node, value) => this._checkImport(context, config, node, value)); } } return {}; @@ -29,7 +29,7 @@ module.exports = new class { _checkImport(context, config, node, path) { // resolve relative paths if (path[0] === '.') { - path = path_1.join(context.getFilename(), path); + path = (0, path_1.join)(context.getFilename(), path); } let restrictions; if (typeof config.restrictions === 'string') { diff --git a/build/lib/eslint/code-layering.js b/build/lib/eslint/code-layering.js index db591f789c7..bcb413d9db3 100644 --- a/build/lib/eslint/code-layering.js +++ b/build/lib/eslint/code-layering.js @@ -17,7 +17,7 @@ module.exports = new class { }; } create(context) { - const fileDirname = path_1.dirname(context.getFilename()); + const fileDirname = (0, path_1.dirname)(context.getFilename()); const parts = fileDirname.split(/\\|\//); const ruleArgs = context.options[0]; let config; @@ -39,11 +39,11 @@ module.exports = new class { // nothing return {}; } - return utils_1.createImportRuleListener((node, path) => { + return (0, utils_1.createImportRuleListener)((node, path) => { if (path[0] === '.') { - path = path_1.join(path_1.dirname(context.getFilename()), path); + path = (0, path_1.join)((0, path_1.dirname)(context.getFilename()), path); } - const parts = path_1.dirname(path).split(/\\|\//); + const parts = (0, path_1.dirname)(path).split(/\\|\//); for (let i = parts.length - 1; i >= 0; i--) { const part = parts[i]; if (config.allowed.has(part)) { diff --git a/build/lib/eslint/code-no-nls-in-standalone-editor.js b/build/lib/eslint/code-no-nls-in-standalone-editor.js index d8955507bed..36782a4b5bc 100644 --- a/build/lib/eslint/code-no-nls-in-standalone-editor.js +++ b/build/lib/eslint/code-no-nls-in-standalone-editor.js @@ -20,10 +20,10 @@ module.exports = new class NoNlsInStandaloneEditorRule { || /vs(\/|\\)editor(\/|\\)editor.api/.test(fileName) || /vs(\/|\\)editor(\/|\\)editor.main/.test(fileName) || /vs(\/|\\)editor(\/|\\)editor.worker/.test(fileName)) { - return utils_1.createImportRuleListener((node, path) => { + return (0, utils_1.createImportRuleListener)((node, path) => { // resolve relative paths if (path[0] === '.') { - path = path_1.join(context.getFilename(), path); + path = (0, path_1.join)(context.getFilename(), path); } if (/vs(\/|\\)nls/.test(path)) { context.report({ diff --git a/build/lib/eslint/code-no-standalone-editor.js b/build/lib/eslint/code-no-standalone-editor.js index d9d6bb55b87..c57bd560bcf 100644 --- a/build/lib/eslint/code-no-standalone-editor.js +++ b/build/lib/eslint/code-no-standalone-editor.js @@ -21,10 +21,10 @@ module.exports = new class NoNlsInStandaloneEditorRule { // the vs/editor folder is allowed to use the standalone editor return {}; } - return utils_1.createImportRuleListener((node, path) => { + return (0, utils_1.createImportRuleListener)((node, path) => { // resolve relative paths if (path[0] === '.') { - path = path_1.join(context.getFilename(), path); + path = (0, path_1.join)(context.getFilename(), path); } if (/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(path) || /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(path) diff --git a/build/lib/eslint/code-translation-remind.js b/build/lib/eslint/code-translation-remind.js index a276e7c0028..30b63429521 100644 --- a/build/lib/eslint/code-translation-remind.js +++ b/build/lib/eslint/code-translation-remind.js @@ -15,7 +15,7 @@ module.exports = new (_a = class TranslationRemind { }; } create(context) { - return utils_1.createImportRuleListener((node, path) => this._checkImport(context, node, path)); + return (0, utils_1.createImportRuleListener)((node, path) => this._checkImport(context, node, path)); } _checkImport(context, node, path) { if (path !== TranslationRemind.NLS_MODULE) { @@ -31,7 +31,7 @@ module.exports = new (_a = class TranslationRemind { let resourceDefined = false; let json; try { - json = fs_1.readFileSync('./build/lib/i18n.resources.json', 'utf8'); + json = (0, fs_1.readFileSync)('./build/lib/i18n.resources.json', 'utf8'); } catch (e) { console.error('[translation-remind rule]: File with resources to pull from Transifex was not found. Aborting translation resource check for newly defined workbench part/service.'); diff --git a/build/lib/extensions.js b/build/lib/extensions.js index b25c3713ea8..d8ecc37f4ce 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -143,7 +143,7 @@ function fromLocalWebpack(extensionPath, webpackConfigFileName) { console.error(packagedDependencies); result.emit('error', err); }); - return result.pipe(stats_1.createStatsStream(path.basename(extensionPath))); + return result.pipe((0, stats_1.createStatsStream)(path.basename(extensionPath))); } function fromLocalNormal(extensionPath) { const result = es.through(); @@ -161,7 +161,7 @@ function fromLocalNormal(extensionPath) { es.readArray(files).pipe(result); }) .catch(err => result.emit('error', err)); - return result.pipe(stats_1.createStatsStream(path.basename(extensionPath))); + return result.pipe((0, stats_1.createStatsStream)(path.basename(extensionPath))); } const baseHeaders = { 'X-Market-Client-Id': 'VSCode Build', diff --git a/build/lib/i18n.js b/build/lib/i18n.js index 50ec3f3f45a..e884fc832b2 100644 --- a/build/lib/i18n.js +++ b/build/lib/i18n.js @@ -463,7 +463,7 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) { }); } function processNlsFiles(opts) { - return event_stream_1.through(function (file) { + return (0, event_stream_1.through)(function (file) { let fileName = path.basename(file.path); if (fileName === 'nls.metadata.json') { let json = null; @@ -515,7 +515,7 @@ function getResource(sourceFile) { } exports.getResource = getResource; function createXlfFilesForCoreBundle() { - return event_stream_1.through(function (file) { + return (0, event_stream_1.through)(function (file) { const basename = path.basename(file.path); if (basename === 'nls.metadata.json') { if (file.isBuffer()) { @@ -566,7 +566,7 @@ function createXlfFilesForExtensions() { let counter = 0; let folderStreamEnded = false; let folderStreamEndEmitted = false; - return event_stream_1.through(function (extensionFolder) { + return (0, event_stream_1.through)(function (extensionFolder) { const folderStream = this; const stat = fs.statSync(extensionFolder.path); if (!stat.isDirectory()) { @@ -584,7 +584,7 @@ function createXlfFilesForExtensions() { } return _xlf; } - gulp.src([`.build/extensions/${extensionName}/package.nls.json`, `.build/extensions/${extensionName}/**/nls.metadata.json`], { allowEmpty: true }).pipe(event_stream_1.through(function (file) { + gulp.src([`.build/extensions/${extensionName}/package.nls.json`, `.build/extensions/${extensionName}/**/nls.metadata.json`], { allowEmpty: true }).pipe((0, event_stream_1.through)(function (file) { if (file.isBuffer()) { const buffer = file.contents; const basename = path.basename(file.path); @@ -643,7 +643,7 @@ function createXlfFilesForExtensions() { } exports.createXlfFilesForExtensions = createXlfFilesForExtensions; function createXlfFilesForIsl() { - return event_stream_1.through(function (file) { + return (0, event_stream_1.through)(function (file) { let projectName, resourceFile; if (path.basename(file.path) === 'Default.isl') { projectName = setupProject; @@ -697,7 +697,7 @@ exports.createXlfFilesForIsl = createXlfFilesForIsl; function pushXlfFiles(apiHostname, username, password) { let tryGetPromises = []; let updateCreatePromises = []; - return event_stream_1.through(function (file) { + return (0, event_stream_1.through)(function (file) { const project = path.dirname(file.relative); const fileName = path.basename(file.path); const slug = fileName.substr(0, fileName.length - '.xlf'.length); @@ -759,7 +759,7 @@ function getAllResources(project, apiHostname, username, password) { function findObsoleteResources(apiHostname, username, password) { let resourcesByProject = Object.create(null); resourcesByProject[extensionsProject] = [].concat(exports.externalExtensionsWithTranslations); // clone - return event_stream_1.through(function (file) { + return (0, event_stream_1.through)(function (file) { const project = path.dirname(file.relative); const fileName = path.basename(file.path); const slug = fileName.substr(0, fileName.length - '.xlf'.length); @@ -936,7 +936,7 @@ function pullXlfFiles(apiHostname, username, password, language, resources) { const credentials = `${username}:${password}`; let expectedTranslationsCount = resources.length; let translationsRetrieved = 0, called = false; - return event_stream_1.readable(function (_count, callback) { + return (0, event_stream_1.readable)(function (_count, callback) { // Mark end of stream when all resources were retrieved if (translationsRetrieved === expectedTranslationsCount) { return this.emit('end'); @@ -994,7 +994,7 @@ function retrieveResource(language, resource, apiHostname, credentials) { } function prepareI18nFiles() { let parsePromises = []; - return event_stream_1.through(function (xlf) { + return (0, event_stream_1.through)(function (xlf) { let stream = this; let parsePromise = XLF.parse(xlf.contents.toString()); parsePromises.push(parsePromise); @@ -1043,7 +1043,7 @@ function prepareI18nPackFiles(externalExtensions, resultingTranslationPaths, pse let mainPack = { version: i18nPackVersion, contents: {} }; let extensionsPacks = {}; let errors = []; - return event_stream_1.through(function (xlf) { + return (0, event_stream_1.through)(function (xlf) { let project = path.basename(path.dirname(xlf.relative)); let resource = path.basename(xlf.relative, '.xlf'); let contents = xlf.contents.toString(); @@ -1104,7 +1104,7 @@ function prepareI18nPackFiles(externalExtensions, resultingTranslationPaths, pse exports.prepareI18nPackFiles = prepareI18nPackFiles; function prepareIslFiles(language, innoSetupConfig) { let parsePromises = []; - return event_stream_1.through(function (xlf) { + return (0, event_stream_1.through)(function (xlf) { let stream = this; let parsePromise = XLF.parse(xlf.contents.toString()); parsePromises.push(parsePromise); diff --git a/build/lib/layersChecker.js b/build/lib/layersChecker.js index 147d038f50b..3b9bd6fb9f4 100644 --- a/build/lib/layersChecker.js +++ b/build/lib/layersChecker.js @@ -199,7 +199,7 @@ const RULES = [ ] } ]; -const TS_CONFIG_PATH = path_1.join(__dirname, '../../', 'src', 'tsconfig.json'); +const TS_CONFIG_PATH = (0, path_1.join)(__dirname, '../../', 'src', 'tsconfig.json'); let hasErrors = false; function checkFile(program, sourceFile, rule) { checkNode(sourceFile); @@ -250,8 +250,8 @@ function checkFile(program, sourceFile, rule) { } function createProgram(tsconfigPath) { const tsConfig = ts.readConfigFile(tsconfigPath, ts.sys.readFile); - const configHostParser = { fileExists: fs_1.existsSync, readDirectory: ts.sys.readDirectory, readFile: file => fs_1.readFileSync(file, 'utf8'), useCaseSensitiveFileNames: process.platform === 'linux' }; - const tsConfigParsed = ts.parseJsonConfigFileContent(tsConfig.config, configHostParser, path_1.resolve(path_1.dirname(tsconfigPath)), { noEmit: true }); + const configHostParser = { fileExists: fs_1.existsSync, readDirectory: ts.sys.readDirectory, readFile: file => (0, fs_1.readFileSync)(file, 'utf8'), useCaseSensitiveFileNames: process.platform === 'linux' }; + const tsConfigParsed = ts.parseJsonConfigFileContent(tsConfig.config, configHostParser, (0, path_1.resolve)((0, path_1.dirname)(tsconfigPath)), { noEmit: true }); const compilerHost = ts.createCompilerHost(tsConfigParsed.options, true); return ts.createProgram(tsConfigParsed.fileNames, tsConfigParsed.options, compilerHost); } @@ -261,7 +261,7 @@ function createProgram(tsconfigPath) { const program = createProgram(TS_CONFIG_PATH); for (const sourceFile of program.getSourceFiles()) { for (const rule of RULES) { - if (minimatch_1.match([sourceFile.fileName], rule.target).length > 0) { + if ((0, minimatch_1.match)([sourceFile.fileName], rule.target).length > 0) { if (!rule.skip) { checkFile(program, sourceFile, rule); } diff --git a/build/lib/nls.js b/build/lib/nls.js index 671a0afed43..8930b31e96c 100644 --- a/build/lib/nls.js +++ b/build/lib/nls.js @@ -53,8 +53,8 @@ define([], [${wrap + lines.map(l => indent + l).join(',\n') + wrap}]);`; * Returns a stream containing the patched JavaScript and source maps. */ function nls() { - const input = event_stream_1.through(); - const output = input.pipe(event_stream_1.through(function (f) { + const input = (0, event_stream_1.through)(); + const output = input.pipe((0, event_stream_1.through)(function (f) { if (!f.sourceMap) { return this.emit('error', new Error(`File ${f.relative} does not have sourcemaps.`)); } @@ -72,7 +72,7 @@ function nls() { } _nls.patchFiles(f, typescript).forEach(f => this.emit('data', f)); })); - return event_stream_1.duplex(input, output); + return (0, event_stream_1.duplex)(input, output); } exports.nls = nls; function isImportNode(ts, node) { diff --git a/build/lib/optimize.js b/build/lib/optimize.js index 1cfca357f7c..3a9cb487d04 100644 --- a/build/lib/optimize.js +++ b/build/lib/optimize.js @@ -96,7 +96,7 @@ function toConcatStream(src, bundledFileHeader, sources, dest, fileContentMapper return es.readArray(treatedSources) .pipe(useSourcemaps ? util.loadSourcemaps() : es.through()) .pipe(concat(dest)) - .pipe(stats_1.createStatsStream(dest)); + .pipe((0, stats_1.createStatsStream)(dest)); } function toBundleStream(src, bundledFileHeader, bundles, fileContentMapper) { return es.merge(bundles.map(function (bundle) { @@ -153,7 +153,7 @@ function optimizeTask(opts) { addComment: true, includeContent: true })) - .pipe(opts.languages && opts.languages.length ? i18n_1.processNlsFiles({ + .pipe(opts.languages && opts.languages.length ? (0, i18n_1.processNlsFiles)({ fileHeader: bundledFileHeader, languages: opts.languages }) : es.through()) diff --git a/build/lib/preLaunch.js b/build/lib/preLaunch.js index 1aecbe19048..b1ecd53b5d9 100644 --- a/build/lib/preLaunch.js +++ b/build/lib/preLaunch.js @@ -12,7 +12,7 @@ const yarn = process.platform === 'win32' ? 'yarn.cmd' : 'yarn'; const rootDir = path.resolve(__dirname, '..', '..'); function runProcess(command, args = []) { return new Promise((resolve, reject) => { - const child = child_process_1.spawn(command, args, { cwd: rootDir, stdio: 'inherit', env: process.env }); + const child = (0, child_process_1.spawn)(command, args, { cwd: rootDir, stdio: 'inherit', env: process.env }); child.on('exit', err => !err ? resolve() : process.exit(err !== null && err !== void 0 ? err : 1)); child.on('error', reject); }); diff --git a/build/lib/treeshaking.js b/build/lib/treeshaking.js index 3abe020882b..41cb33809b0 100644 --- a/build/lib/treeshaking.js +++ b/build/lib/treeshaking.js @@ -241,6 +241,9 @@ function nodeOrChildIsBlack(node) { } return false; } +function isSymbolWithDeclarations(symbol) { + return !!(symbol && symbol.declarations); +} function markNodes(ts, languageService, options) { const program = languageService.getProgram(); if (!program) { @@ -413,7 +416,7 @@ function markNodes(ts, languageService, options) { if (symbolImportNode) { setColor(symbolImportNode, 2 /* Black */); } - if (symbol && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) { + if (isSymbolWithDeclarations(symbol) && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) { for (let i = 0, len = symbol.declarations.length; i < len; i++) { const declaration = symbol.declarations[i]; if (ts.isSourceFile(declaration)) { @@ -686,7 +689,7 @@ function getRealNodeSymbol(ts, checker, node) { // get the aliased symbol instead. This allows for goto def on an import e.g. // import {A, B} from "mod"; // to jump to the implementation directly. - if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) { + if (symbol && symbol.flags & ts.SymbolFlags.Alias && symbol.declarations && shouldSkipAlias(node, symbol.declarations[0])) { const aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { // We should mark the import as visited diff --git a/build/lib/treeshaking.ts b/build/lib/treeshaking.ts index f941e9791a7..f24b31e26ac 100644 --- a/build/lib/treeshaking.ts +++ b/build/lib/treeshaking.ts @@ -323,6 +323,10 @@ function nodeOrChildIsBlack(node: ts.Node): boolean { return false; } +function isSymbolWithDeclarations(symbol: ts.Symbol | undefined | null): symbol is ts.Symbol & { declarations: ts.Declaration[] } { + return !!(symbol && symbol.declarations); +} + function markNodes(ts: typeof import('typescript'), languageService: ts.LanguageService, options: ITreeShakingOptions) { const program = languageService.getProgram(); if (!program) { @@ -530,7 +534,7 @@ function markNodes(ts: typeof import('typescript'), languageService: ts.Language setColor(symbolImportNode, NodeColor.Black); } - if (symbol && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) { + if (isSymbolWithDeclarations(symbol) && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) { for (let i = 0, len = symbol.declarations.length; i < len; i++) { const declaration = symbol.declarations[i]; if (ts.isSourceFile(declaration)) { @@ -595,7 +599,7 @@ function markNodes(ts: typeof import('typescript'), languageService: ts.Language } } -function nodeIsInItsOwnDeclaration(nodeSourceFile: ts.SourceFile, node: ts.Node, symbol: ts.Symbol): boolean { +function nodeIsInItsOwnDeclaration(nodeSourceFile: ts.SourceFile, node: ts.Node, symbol: ts.Symbol & { declarations: ts.Declaration[] }): boolean { for (let i = 0, len = symbol.declarations.length; i < len; i++) { const declaration = symbol.declarations[i]; const declarationSourceFile = declaration.getSourceFile(); @@ -838,7 +842,7 @@ function getRealNodeSymbol(ts: typeof import('typescript'), checker: ts.TypeChec // get the aliased symbol instead. This allows for goto def on an import e.g. // import {A, B} from "mod"; // to jump to the implementation directly. - if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) { + if (symbol && symbol.flags & ts.SymbolFlags.Alias && symbol.declarations && shouldSkipAlias(node, symbol.declarations[0])) { const aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { // We should mark the import as visited From 9cba86888c953fe4f665290462b2bd701f3cb971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 13:32:50 +0200 Subject: [PATCH 120/140] update node version in optimize --- build/lib/optimize.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts index c3c29e4a700..b613416cab2 100644 --- a/build/lib/optimize.ts +++ b/build/lib/optimize.ts @@ -254,7 +254,7 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => sourcemap: 'external', outdir: '.', platform: 'node', - target: ['node12.18'], + target: ['node14.16'], write: false }).then(res => { const jsFile = res.outputFiles.find(f => /\.js$/.test(f.path))!; From 0d44b63c1c1beb2b2c5c3b798d67e79f4cb34c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 14:05:25 +0200 Subject: [PATCH 121/140] fixes #124407 --- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 6eee9af184f..239fc2b35e8 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -56,7 +56,7 @@ import { SelectionClipboardContributionID } from 'vs/workbench/contrib/codeEdito import { ContextMenuController } from 'vs/editor/contrib/contextmenu/contextmenu'; import * as platform from 'vs/base/common/platform'; import { compare, format } from 'vs/base/common/strings'; -import { inputPlaceholderForeground, inputValidationInfoBorder, inputValidationWarningBorder, inputValidationErrorBorder, inputValidationInfoBackground, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningForeground, inputValidationErrorBackground, inputValidationErrorForeground, inputBackground, inputForeground, inputBorder, focusBorder, registerColor, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; +import { inputPlaceholderForeground, inputValidationInfoBorder, inputValidationWarningBorder, inputValidationErrorBorder, inputValidationInfoBackground, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningForeground, inputValidationErrorBackground, inputValidationErrorForeground, inputBackground, inputForeground, inputBorder, focusBorder, registerColor, contrastBorder, editorSelectionBackground, selectionBackground } from 'vs/platform/theme/common/colorRegistry'; import { SuggestController } from 'vs/editor/contrib/suggest/suggestController'; import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2'; import { Schemas } from 'vs/base/common/network'; @@ -2163,6 +2163,11 @@ registerThemingParticipant((theme, collector) => { { background-color: ${inputBackgroundColor} !important; }`); } + const selectionBackgroundColor = theme.getColor(selectionBackground) ?? theme.getColor(editorSelectionBackground); + if (selectionBackgroundColor) { + collector.addRule(`.scm-view .scm-editor-container .monaco-editor .focused .selected-text { background-color: ${selectionBackgroundColor}; }`); + } + const inputForegroundColor = theme.getColor(inputForeground); if (inputForegroundColor) { collector.addRule(`.scm-view .scm-editor-container .mtk1 { color: ${inputForegroundColor}; }`); From dff33d73244acced865a2643a62126409cb541a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 14:11:36 +0200 Subject: [PATCH 122/140] use actual object --- src/vs/base/common/process.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/common/process.ts b/src/vs/base/common/process.ts index 6c4b1f407d5..ec90453aa83 100644 --- a/src/vs/base/common/process.ts +++ b/src/vs/base/common/process.ts @@ -38,7 +38,7 @@ else { nextTick(callback: (...args: any[]) => void): void { return setImmediate(callback); }, // Unsupported - get env() { return Object.create(null); }, + get env() { return {}; }, cwd() { return '/'; } }; } From 0688745e82ef2bfa306a4614668b5d71a2671b58 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Wed, 26 May 2021 14:13:00 +0200 Subject: [PATCH 123/140] Color.Format.Css.format does not return null, so the return type can be made more strict. (#124568) --- src/vs/base/common/color.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/common/color.ts b/src/vs/base/common/color.ts index eb5fd3b079a..abfbad67c9e 100644 --- a/src/vs/base/common/color.ts +++ b/src/vs/base/common/color.ts @@ -523,7 +523,7 @@ export namespace Color { /** * The default format will use HEX if opaque and RGBA otherwise. */ - export function format(color: Color): string | null { + export function format(color: Color): string { if (color.isOpaque()) { return Color.Format.CSS.formatHex(color); } From 4cda850edf57f244260b7b534cbb8d7c3717f58a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 26 May 2021 14:22:08 +0200 Subject: [PATCH 124/140] disable welcome editor in smoke tests (fix #124674) --- test/smoke/src/areas/multiroot/multiroot.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/smoke/src/areas/multiroot/multiroot.test.ts b/test/smoke/src/areas/multiroot/multiroot.test.ts index 3c11cd5c553..077c46bf7ed 100644 --- a/test/smoke/src/areas/multiroot/multiroot.test.ts +++ b/test/smoke/src/areas/multiroot/multiroot.test.ts @@ -22,7 +22,10 @@ async function createWorkspaceFile(workspacePath: string): Promise { { path: toUri(path.join(workspacePath, 'public')) }, { path: toUri(path.join(workspacePath, 'routes')) }, { path: toUri(path.join(workspacePath, 'views')) } - ] + ], + settings: { + 'workbench.startupEditor': 'none' + } }; fs.writeFileSync(workspaceFilePath, JSON.stringify(workspace, null, '\t')); From a628237458fba554ea856cb53079935924bdcd17 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 26 May 2021 14:36:09 +0200 Subject: [PATCH 125/140] Web: "Open Folder" on empty workspace does nothing fixes #124494 --- src/vs/workbench/contrib/files/browser/explorerViewlet.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts index ebdde76ffdc..f752b8790e5 100644 --- a/src/vs/workbench/contrib/files/browser/explorerViewlet.ts +++ b/src/vs/workbench/contrib/files/browser/explorerViewlet.ts @@ -37,7 +37,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { WorkbenchStateContext, RemoteNameContext } from 'vs/workbench/browser/contextkeys'; import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; import { AddRootFolderAction, OpenFolderAction, OpenFileFolderAction } from 'vs/workbench/browser/actions/workspaceActions'; -import { isMacintosh } from 'vs/base/common/platform'; +import { isMacintosh, isWeb } from 'vs/base/common/platform'; import { Codicon } from 'vs/base/common/codicons'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; @@ -294,7 +294,7 @@ viewsRegistry.registerViewWelcomeContent(EmptyView.ID, { order: 1 }); -const commandId = isMacintosh ? OpenFileFolderAction.ID : OpenFolderAction.ID; +const commandId = (isMacintosh && !isWeb) ? OpenFileFolderAction.ID : OpenFolderAction.ID; viewsRegistry.registerViewWelcomeContent(EmptyView.ID, { content: localize({ key: 'remoteNoFolderHelp', comment: ['Please do not translate the word "commmand", it is part of our internal syntax which must not change'] }, "Connected to remote.\n[Open Folder](command:{0})", commandId), From 0a4bfb31c9027e231e89977d03846f53d2bac48c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 14:25:39 +0200 Subject: [PATCH 126/140] fix naming --- src/vs/base/browser/ui/splitview/paneview.ts | 4 ++-- src/vs/base/browser/ui/splitview/splitview.ts | 6 +++--- src/vs/workbench/browser/parts/views/viewPane.ts | 2 +- src/vs/workbench/browser/parts/views/viewPaneContainer.ts | 7 +++---- .../contrib/webviewView/browser/webviewViewPane.ts | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/vs/base/browser/ui/splitview/paneview.ts b/src/vs/base/browser/ui/splitview/paneview.ts index 0c190fc4f3a..a84c6f5837e 100644 --- a/src/vs/base/browser/ui/splitview/paneview.ts +++ b/src/vs/base/browser/ui/splitview/paneview.ts @@ -445,7 +445,7 @@ export class PaneView extends Disposable { orientation: Orientation; readonly onDidSashChange: Event; - readonly onScroll: Event; + readonly onDidScroll: Event; constructor(container: HTMLElement, options: IPaneViewOptions = {}) { super(); @@ -455,7 +455,7 @@ export class PaneView extends Disposable { this.element = append(container, $('.monaco-pane-view')); this.splitview = this._register(new SplitView(this.element, { orientation: this.orientation })); this.onDidSashChange = this.splitview.onDidSashChange; - this.onScroll = this.splitview.onScroll; + this.onDidScroll = this.splitview.onDidScroll; } addPane(pane: Pane, size: number, index = this.splitview.length): void { diff --git a/src/vs/base/browser/ui/splitview/splitview.ts b/src/vs/base/browser/ui/splitview/splitview.ts index d193d68b1cf..5996365a70f 100644 --- a/src/vs/base/browser/ui/splitview/splitview.ts +++ b/src/vs/base/browser/ui/splitview/splitview.ts @@ -237,7 +237,7 @@ export class SplitView extends Disposable { private _onDidSashReset = this._register(new Emitter()); readonly onDidSashReset = this._onDidSashReset.event; - readonly onScroll: Event; + readonly onDidScroll: Event; get length(): number { return this.viewItems.length; @@ -319,8 +319,8 @@ export class SplitView extends Disposable { horizontal: this.orientation === Orientation.HORIZONTAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden }, this.scrollable)); - this.onScroll = this.scrollableElement.onScroll; - this._register(this.onScroll(e => { + this.onDidScroll = this.scrollableElement.onScroll; + this._register(this.onDidScroll(e => { this.viewContainer.scrollTop = e.scrollTop; this.viewContainer.scrollLeft = e.scrollLeft; })); diff --git a/src/vs/workbench/browser/parts/views/viewPane.ts b/src/vs/workbench/browser/parts/views/viewPane.ts index d6b967b6a40..655410652bf 100644 --- a/src/vs/workbench/browser/parts/views/viewPane.ts +++ b/src/vs/workbench/browser/parts/views/viewPane.ts @@ -445,7 +445,7 @@ export abstract class ViewPane extends Pane implements IView { this.scrollableElement.scanDomNode(); } - onRootScroll() { + onDidScrollRoot() { // noop } diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index 8cc73ad857b..0ed15426be7 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -38,7 +38,6 @@ import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane'; import { CompositeMenuActions } from 'vs/workbench/browser/actions'; import { createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar'; -import { ScrollEvent } from 'vs/base/common/scrollable'; export const ViewsSubMenu = new MenuId('Views'); MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, { @@ -408,7 +407,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { options.orientation = this.orientation; this.paneview = this._register(new PaneView(parent, this.options)); this._register(this.paneview.onDidDrop(({ from, to }) => this.movePane(from as ViewPane, to as ViewPane))); - this._register(this.paneview.onScroll(e => this.onPaneScroll(e))); + this._register(this.paneview.onDidScroll(_ => this.onDidScrollPane())); this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, (e: MouseEvent) => this.showContextMenu(new StandardMouseEvent(e)))); this._menuActions = this._register(this.instantiationService.createInstance(ViewContainerMenuActions, this.paneview.element, this.viewContainer)); @@ -1066,9 +1065,9 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { return true; } - private onPaneScroll(e: ScrollEvent) { + private onDidScrollPane() { for (const pane of this.panes) { - pane.onRootScroll(); + pane.onDidScrollRoot(); } } diff --git a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts index 36734608452..84c82e7be02 100644 --- a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts +++ b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts @@ -219,7 +219,7 @@ export class WebviewViewPane extends ViewPane { return this.progressService.withProgress({ location: this.id, delay: 500 }, task); } - override onRootScroll() { + override onDidScrollRoot() { this.layoutWebview(); } From 0e3459b0b9facc5e7a1e95903955f870bc5a532c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 14:38:38 +0200 Subject: [PATCH 127/140] expose Grid.onDidScroll related to #116946 --- src/vs/base/browser/ui/grid/grid.ts | 9 +++++++-- src/vs/base/browser/ui/grid/gridview.ts | 24 ++++++++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/vs/base/browser/ui/grid/grid.ts b/src/vs/base/browser/ui/grid/grid.ts index 38bc8c53d9e..512d2d8a7ec 100644 --- a/src/vs/base/browser/ui/grid/grid.ts +++ b/src/vs/base/browser/ui/grid/grid.ts @@ -210,7 +210,9 @@ export class Grid extends Disposable { get minimumHeight(): number { return this.gridview.minimumHeight; } get maximumWidth(): number { return this.gridview.maximumWidth; } get maximumHeight(): number { return this.gridview.maximumHeight; } - get onDidChange(): Event<{ width: number; height: number; } | undefined> { return this.gridview.onDidChange; } + + readonly onDidChange: Event<{ width: number; height: number; } | undefined>; + readonly onDidScroll: Event; get boundarySashes(): IBoundarySashes { return this.gridview.boundarySashes; } set boundarySashes(boundarySashes: IBoundarySashes) { this.gridview.boundarySashes = boundarySashes; } @@ -232,8 +234,8 @@ export class Grid extends Disposable { } else { this.gridview = new GridView(options); } - this._register(this.gridview); + this._register(this.gridview); this._register(this.gridview.onDidSashReset(this.onDidSashReset, this)); const size: number | GridViewSizing = typeof options.firstViewVisibleCachedSize === 'number' @@ -243,6 +245,9 @@ export class Grid extends Disposable { if (!(view instanceof GridView)) { this._addView(view, size, [0]); } + + this.onDidChange = this.gridview.onDidChange; + this.onDidScroll = this.gridview.onDidScroll; } style(styles: IGridStyles): void { diff --git a/src/vs/base/browser/ui/grid/gridview.ts b/src/vs/base/browser/ui/grid/gridview.ts index 8ed7d712459..996b968ddc0 100644 --- a/src/vs/base/browser/ui/grid/gridview.ts +++ b/src/vs/base/browser/ui/grid/gridview.ts @@ -243,6 +243,10 @@ class BranchNode implements ISplitView, IDisposable { private readonly _onDidChange = new Emitter(); readonly onDidChange: Event = this._onDidChange.event; + private _onDidScroll = new Emitter(); + private onDidScrollDisposable: IDisposable = Disposable.None; + readonly onDidScroll: Event = this._onDidScroll.event; + private childrenChangeDisposable: IDisposable = Disposable.None; private readonly _onDidSashReset = new Emitter(); @@ -344,11 +348,7 @@ class BranchNode implements ISplitView, IDisposable { const onDidSashReset = Event.map(this.splitview.onDidSashReset, i => [i]); this.splitviewSashResetDisposable = onDidSashReset(this._onDidSashReset.fire, this._onDidSashReset); - const onDidChildrenChange = Event.map(Event.any(...this.children.map(c => c.onDidChange)), () => undefined); - this.childrenChangeDisposable = onDidChildrenChange(this._onDidChange.fire, this._onDidChange); - - const onDidChildrenSashReset = Event.any(...this.children.map((c, i) => Event.map(c.onDidSashReset, location => [i, ...location]))); - this.childrenSashResetDisposable = onDidChildrenSashReset(this._onDidSashReset.fire, this._onDidSashReset); + this.updateChildrenEvents(); } style(styles: IGridViewStyles): void { @@ -567,6 +567,11 @@ class BranchNode implements ISplitView, IDisposable { } private onDidChildrenChange(): void { + this.updateChildrenEvents(); + this._onDidChange.fire(undefined); + } + + private updateChildrenEvents(): void { const onDidChildrenChange = Event.map(Event.any(...this.children.map(c => c.onDidChange)), () => undefined); this.childrenChangeDisposable.dispose(); this.childrenChangeDisposable = onDidChildrenChange(this._onDidChange.fire, this._onDidChange); @@ -575,7 +580,9 @@ class BranchNode implements ISplitView, IDisposable { this.childrenSashResetDisposable.dispose(); this.childrenSashResetDisposable = onDidChildrenSashReset(this._onDidSashReset.fire, this._onDidSashReset); - this._onDidChange.fire(undefined); + const onDidScroll = Event.any(Event.signal(this.splitview.onDidScroll), ...this.children.map(c => c.onDidScroll)); + this.onDidScrollDisposable.dispose(); + this.onDidScrollDisposable = onDidScroll(this._onDidScroll.fire, this._onDidScroll); } trySet2x2(other: BranchNode): IDisposable { @@ -677,6 +684,7 @@ class LeafNode implements ISplitView, IDisposable { private absoluteOffset: number = 0; private absoluteOrthogonalOffset: number = 0; + readonly onDidScroll: Event = Event.None; readonly onDidSashReset: Event = Event.None; private _onDidLinkedWidthNodeChange = new Relay(); @@ -891,6 +899,7 @@ export class GridView implements IDisposable { this.element.appendChild(root.element); this.onDidSashResetRelay.input = root.onDidSashReset; this._onDidChange.input = Event.map(root.onDidChange, () => undefined); // TODO + this._onDidScroll.input = root.onDidScroll; } get orientation(): Orientation { @@ -916,6 +925,9 @@ export class GridView implements IDisposable { get maximumWidth(): number { return this.root.maximumHeight; } get maximumHeight(): number { return this.root.maximumHeight; } + private _onDidScroll = new Relay(); + readonly onDidScroll = this._onDidScroll.event; + private _onDidChange = new Relay(); readonly onDidChange = this._onDidChange.event; From c704e43d5dc8cdf6570ad61e5f06baa67e4cfa83 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 26 May 2021 14:43:02 +0200 Subject: [PATCH 128/140] Check that the /build/ folder compiles --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d08dac3c03b..faac7802508 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -244,6 +244,9 @@ jobs: - name: Run Valid Layers Checks run: yarn valid-layers-check + - name: Compile /build/ + run: yarn --cwd build compile + - name: Run Monaco Editor Checks run: yarn monaco-compile-check From d662cc5654926fdb0a0f9c48bae9aa4ca2f123d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 14:42:15 +0200 Subject: [PATCH 129/140] remove old license notification related to #119463 --- src/vs/workbench/contrib/update/browser/update.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/vs/workbench/contrib/update/browser/update.ts b/src/vs/workbench/contrib/update/browser/update.ts index 473dbf7f0d9..143c803d8b4 100644 --- a/src/vs/workbench/contrib/update/browser/update.ts +++ b/src/vs/workbench/contrib/update/browser/update.ts @@ -186,11 +186,6 @@ export class ProductContribution implements IWorkbenchContribution { }); } - // should we show the new license? - if (productService.licenseUrl && lastVersion && lastVersion.major < 1 && currentVersion && currentVersion.major >= 1) { - notificationService.info(nls.localize('licenseChanged', "Our license terms have changed, please click [here]({0}) to go through them.", productService.licenseUrl)); - } - storageService.store(ProductContribution.KEY, productService.version, StorageScope.GLOBAL, StorageTarget.MACHINE); }); } From a7ab347c2b3f4f5da76146d6b7db2e5c12aaca1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 26 May 2021 14:45:42 +0200 Subject: [PATCH 130/140] remove old notification --- .../contrib/update/browser/update.ts | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/src/vs/workbench/contrib/update/browser/update.ts b/src/vs/workbench/contrib/update/browser/update.ts index 143c803d8b4..f648957e6b6 100644 --- a/src/vs/workbench/contrib/update/browser/update.ts +++ b/src/vs/workbench/contrib/update/browser/update.ts @@ -255,10 +255,6 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu this.onUpdateDownloaded(state.update); break; - case StateType.Updating: - this.onUpdateUpdating(state.update); - break; - case StateType.Ready: this.onUpdateReady(state.update); break; @@ -367,23 +363,6 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu ); } - // windows fast updates - private onUpdateUpdating(update: IUpdate): void { - if (isWindows && this.productService.target === 'user') { - return; - } - - // windows fast updates (target === system) - this.notificationService.prompt( - severity.Info, - nls.localize('updateInstalling', "{0} {1} is being installed in the background; we'll let you know when it's done.", this.productService.nameLong, update.productVersion), - [], - { - neverShowAgain: { id: 'neverShowAgain:update/win32-fast-updates', isSecondary: true } - } - ); - } - // windows and mac private onUpdateReady(update: IUpdate): void { if (!(isWindows && this.productService.target !== 'user') && !this.shouldShowNotification()) { From 764d8fdc3dd26bf166588e918488781f79e62350 Mon Sep 17 00:00:00 2001 From: Wendell Hu Date: Wed, 26 May 2021 20:51:15 +0800 Subject: [PATCH 131/140] test: add test for event Relay (#119070) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: add test for event Relay * whitespace & syntax Co-authored-by: João Moreno --- src/vs/base/test/common/event.test.ts | 58 ++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/src/vs/base/test/common/event.test.ts b/src/vs/base/test/common/event.test.ts index 3fea2b43b4e..680c4aa2804 100644 --- a/src/vs/base/test/common/event.test.ts +++ b/src/vs/base/test/common/event.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { Event, Emitter, EventBufferer, EventMultiplexer, PauseableEmitter } from 'vs/base/common/event'; +import { Event, Emitter, EventBufferer, EventMultiplexer, PauseableEmitter, Relay } from 'vs/base/common/event'; import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { errorHandler, setUnexpectedErrorHandler } from 'vs/base/common/errors'; import { AsyncEmitter, IWaitUntil, timeout } from 'vs/base/common/async'; @@ -904,4 +904,60 @@ suite('Event utils', () => { const listener = emitter.event(() => undefined); listener.dispose(); // should not crash }); + + suite('Relay', () => { + test('should input work', () => { + const e1 = new Emitter(); + const e2 = new Emitter(); + const relay = new Relay(); + + const result: number[] = []; + const listener = (num: number) => result.push(num); + const subscription = relay.event(listener); + + e1.fire(1); + assert.deepStrictEqual(result, []); + + relay.input = e1.event; + e1.fire(2); + assert.deepStrictEqual(result, [2]); + + relay.input = e2.event; + e1.fire(3); + e2.fire(4); + assert.deepStrictEqual(result, [2, 4]); + + subscription.dispose(); + e1.fire(5); + e2.fire(6); + assert.deepStrictEqual(result, [2, 4]); + }); + + test('should Relay dispose work', () => { + const e1 = new Emitter(); + const e2 = new Emitter(); + const relay = new Relay(); + + const result: number[] = []; + const listener = (num: number) => result.push(num); + relay.event(listener); + + e1.fire(1); + assert.deepStrictEqual(result, []); + + relay.input = e1.event; + e1.fire(2); + assert.deepStrictEqual(result, [2]); + + relay.input = e2.event; + e1.fire(3); + e2.fire(4); + assert.deepStrictEqual(result, [2, 4]); + + relay.dispose(); + e1.fire(5); + e2.fire(6); + assert.deepStrictEqual(result, [2, 4]); + }); + }); }); From bfccdcb958130748419e6df1693c0f99d636dccf Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 26 May 2021 16:28:21 +0200 Subject: [PATCH 132/140] disable fullscreen on ios #106972 --- src/vs/platform/contextkey/common/contextkeys.ts | 3 ++- src/vs/workbench/browser/actions/windowActions.ts | 3 ++- src/vs/workbench/browser/contextkeys.ts | 3 ++- src/vs/workbench/browser/layout.ts | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/vs/platform/contextkey/common/contextkeys.ts b/src/vs/platform/contextkey/common/contextkeys.ts index d98aa5ee62c..4b40ea1d517 100644 --- a/src/vs/platform/contextkey/common/contextkeys.ts +++ b/src/vs/platform/contextkey/common/contextkeys.ts @@ -5,7 +5,7 @@ import { localize } from 'vs/nls'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { isMacintosh, isLinux, isWindows, isWeb } from 'vs/base/common/platform'; +import { isMacintosh, isLinux, isWindows, isWeb, isIOS } from 'vs/base/common/platform'; export const IsMacContext = new RawContextKey('isMac', isMacintosh, localize('isMac', "Whether the operating system is macOS")); export const IsLinuxContext = new RawContextKey('isLinux', isLinux, localize('isLinux', "Whether the operating system is Linux")); @@ -13,6 +13,7 @@ export const IsWindowsContext = new RawContextKey('isWindows', isWindow export const IsWebContext = new RawContextKey('isWeb', isWeb, localize('isWeb', "Whether the platform is a web browser")); export const IsMacNativeContext = new RawContextKey('isMacNative', isMacintosh && !isWeb, localize('isMacNative', "Whether the operating system is macOS on a non-browser platform")); +export const IsIOSContext = new RawContextKey('isIOS', isIOS, localize('isIOS', "Whether the operating system is IOS")); export const IsDevelopmentContext = new RawContextKey('isDevelopment', false, true); diff --git a/src/vs/workbench/browser/actions/windowActions.ts b/src/vs/workbench/browser/actions/windowActions.ts index 0ee503c57b6..08c85b251c2 100644 --- a/src/vs/workbench/browser/actions/windowActions.ts +++ b/src/vs/workbench/browser/actions/windowActions.ts @@ -9,7 +9,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { MenuRegistry, MenuId, Action2, registerAction2, IAction2Options } from 'vs/platform/actions/common/actions'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { IsFullscreenContext } from 'vs/workbench/browser/contextkeys'; -import { IsMacNativeContext, IsDevelopmentContext, IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; +import { IsMacNativeContext, IsDevelopmentContext, IsWebContext, IsIOSContext } from 'vs/platform/contextkey/common/contextkeys'; import { CATEGORIES } from 'vs/workbench/common/actions'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IQuickInputButton, IQuickInputService, IQuickPickSeparator, IKeyMods, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; @@ -285,6 +285,7 @@ class ToggleFullScreenAction extends Action2 { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_F } }, + precondition: IsIOSContext.toNegated(), toggled: IsFullscreenContext, menu: { id: MenuId.MenubarAppearanceMenu, diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index 847d044083f..baeaddc1e44 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -7,7 +7,7 @@ import { localize } from 'vs/nls'; import { Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; -import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext } from 'vs/platform/contextkey/common/contextkeys'; +import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext } from 'vs/platform/contextkey/common/contextkeys'; import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, EditorInputCapabilities } from 'vs/workbench/common/editor'; import { trackFocus, addDisposableListener, EventType, WebFileSystemAccess } from 'vs/base/browser/dom'; import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -93,6 +93,7 @@ export class WorkbenchContextKeysHandler extends Disposable { IsWebContext.bindTo(this.contextKeyService); IsMacNativeContext.bindTo(this.contextKeyService); + IsIOSContext.bindTo(this.contextKeyService); RemoteNameContext.bindTo(this.contextKeyService).set(getRemoteName(this.environmentService.remoteAuthority) || ''); diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index d713601925e..565d32342cb 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -9,7 +9,7 @@ import { EventType, addDisposableListener, getClientArea, Dimension, position, s import { onDidChangeFullscreen, isFullscreen } from 'vs/base/browser/browser'; import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup'; import { Registry } from 'vs/platform/registry/common/platform'; -import { isWindows, isLinux, isMacintosh, isWeb, isNative } from 'vs/base/common/platform'; +import { isWindows, isLinux, isMacintosh, isWeb, isNative, isIOS } from 'vs/base/common/platform'; import { IResourceDiffEditorInput, pathsToEditors } from 'vs/workbench/common/editor'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart'; @@ -1052,7 +1052,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi silentNotifications: boolean; } = this.configurationService.getValue('zenMode'); - toggleFullScreen = !this.state.fullscreen && config.fullScreen; + toggleFullScreen = !this.state.fullscreen && config.fullScreen && !isIOS; this.state.zenMode.transitionedToFullScreen = restoring ? config.fullScreen : toggleFullScreen; this.state.zenMode.transitionedToCenteredEditorLayout = !this.isEditorLayoutCentered() && config.centerLayout; From 6a7c700a12da93d8b6ae392bd8e5ecade03999db Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 26 May 2021 16:36:44 +0200 Subject: [PATCH 133/140] file working copies - do not throw from ctor anymore when schemes are unexpected //cc @joaomoreno --- .../services/workingCopy/common/storedFileWorkingCopy.ts | 4 ---- .../services/workingCopy/common/untitledFileWorkingCopy.ts | 5 ----- .../workingCopy/test/browser/storedFileWorkingCopy.test.ts | 4 ---- .../workingCopy/test/browser/untitledFileWorkingCopy.test.ts | 4 ---- 4 files changed, 17 deletions(-) diff --git a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts index 8a56b821263..b5a97afc967 100644 --- a/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts +++ b/src/vs/workbench/services/workingCopy/common/storedFileWorkingCopy.ts @@ -305,10 +305,6 @@ export class StoredFileWorkingCopy extend ) { super(resource, fileService); - if (!fileService.canHandleResource(this.resource)) { - throw new Error(`The file working copy resource ${this.resource.toString(true)} does not have an associated file system provider.`); - } - // Make known to working copy service this._register(workingCopyService.registerWorkingCopy(this)); } diff --git a/src/vs/workbench/services/workingCopy/common/untitledFileWorkingCopy.ts b/src/vs/workbench/services/workingCopy/common/untitledFileWorkingCopy.ts index de26fda357f..781cf2ebc0f 100644 --- a/src/vs/workbench/services/workingCopy/common/untitledFileWorkingCopy.ts +++ b/src/vs/workbench/services/workingCopy/common/untitledFileWorkingCopy.ts @@ -9,7 +9,6 @@ import { IWorkingCopyBackup, WorkingCopyCapabilities } from 'vs/workbench/servic import { IFileWorkingCopy, IFileWorkingCopyModel, IFileWorkingCopyModelFactory } from 'vs/workbench/services/workingCopy/common/fileWorkingCopy'; import { Disposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; -import { Schemas } from 'vs/base/common/network'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ISaveOptions } from 'vs/workbench/common/editor'; @@ -111,10 +110,6 @@ export class UntitledFileWorkingCopy ex ) { super(); - if (resource.scheme !== Schemas.untitled) { - throw new Error(`The untitled file working copy resource ${this.resource.toString(true)} is not using untitled as scheme.`); - } - // Make known to working copy service this._register(workingCopyService.registerWorkingCopy(this)); } diff --git a/src/vs/workbench/services/workingCopy/test/browser/storedFileWorkingCopy.test.ts b/src/vs/workbench/services/workingCopy/test/browser/storedFileWorkingCopy.test.ts index 37a28f22ecf..c135244e3ec 100644 --- a/src/vs/workbench/services/workingCopy/test/browser/storedFileWorkingCopy.test.ts +++ b/src/vs/workbench/services/workingCopy/test/browser/storedFileWorkingCopy.test.ts @@ -120,10 +120,6 @@ suite('StoredFileWorkingCopy', function () { assert.strictEqual(accessor.workingCopyService.workingCopies.length, 0); }); - test('requires good file system URI', async () => { - assert.throws(() => createWorkingCopy(URI.from({ scheme: 'unknown', path: 'somePath' }))); - }); - test('orphaned tracking', async () => { assert.strictEqual(workingCopy.hasState(StoredFileWorkingCopyState.ORPHAN), false); diff --git a/src/vs/workbench/services/workingCopy/test/browser/untitledFileWorkingCopy.test.ts b/src/vs/workbench/services/workingCopy/test/browser/untitledFileWorkingCopy.test.ts index 16219cd5a69..e34fd7dac9d 100644 --- a/src/vs/workbench/services/workingCopy/test/browser/untitledFileWorkingCopy.test.ts +++ b/src/vs/workbench/services/workingCopy/test/browser/untitledFileWorkingCopy.test.ts @@ -129,10 +129,6 @@ suite('UntitledFileWorkingCopy', () => { assert.strictEqual(accessor.workingCopyService.workingCopies.length, 0); }); - test('requires good untitled URI', async () => { - assert.throws(() => createWorkingCopy(URI.from({ scheme: 'unknown', path: 'somePath' }))); - }); - test('dirty', async () => { assert.strictEqual(workingCopy.isDirty(), false); From e6a1cc384371efcc2eddf3fc71bbd56481d1588e Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 26 May 2021 08:12:33 -0700 Subject: [PATCH 134/140] Update commands.json --- .github/commands.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/commands.json b/.github/commands.json index 65936b422a9..388a9c3dbb3 100644 --- a/.github/commands.json +++ b/.github/commands.json @@ -90,7 +90,7 @@ "@author" ], "action": "updateLabels", - "addLabel": "z-author-verified", + "addLabel": "verified", "removeLabel": "author-verification-requested", "requireLabel": "author-verification-requested", "disallowLabel": "unreleased" From 31a59b5970dc2f7d5202fd968212e1c5d26828ea Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 26 May 2021 17:20:59 +0200 Subject: [PATCH 135/140] bump distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7e3bd9ff769..2b7f683afbb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.57.0", - "distro": "f572cb079a417a61c1db45d011c3eefbbcf881f4", + "distro": "6990f0d636b76eeb248768293adc4cb00dfa7736", "author": { "name": "Microsoft Corporation" }, From 84bc432011c5b038b8996f1e9111bfeccef3144e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 26 May 2021 18:00:07 +0200 Subject: [PATCH 136/140] Add `IHoverPart.owner` --- .../contrib/hover/markdownHoverParticipant.ts | 7 +- .../contrib/hover/markerHoverParticipant.ts | 3 +- .../editor/contrib/hover/modesContentHover.ts | 79 +++++++++++-------- 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/vs/editor/contrib/hover/markdownHoverParticipant.ts b/src/vs/editor/contrib/hover/markdownHoverParticipant.ts index ec4442dbd5a..f312eda5a4d 100644 --- a/src/vs/editor/contrib/hover/markdownHoverParticipant.ts +++ b/src/vs/editor/contrib/hover/markdownHoverParticipant.ts @@ -25,6 +25,7 @@ const $ = dom.$; export class MarkdownHover implements IHoverPart { constructor( + public readonly owner: IEditorHoverParticipant, public readonly range: Range, public readonly contents: IMarkdownString[] ) { } @@ -47,7 +48,7 @@ export class MarkdownHoverParticipant implements IEditorHoverParticipant, public readonly range: Range, public readonly marker: IMarker, ) { } @@ -81,7 +82,7 @@ export class MarkerHoverParticipant implements IEditorHoverParticipant { computeSync(hoverRange: Range, lineDecorations: IModelDecoration[]): T[]; computeAsync?(range: Range, token: CancellationToken): Promise; + createLoadingMessage?(range: Range): T; renderHoverParts(hoverParts: T[], fragment: DocumentFragment): IDisposable; } @@ -76,8 +78,7 @@ class ModesContentComputer implements IHoverComputer { constructor( editor: ICodeEditor, - private readonly _markerHoverParticipant: IEditorHoverParticipant, - private readonly _markdownHoverParticipant: MarkdownHoverParticipant + private readonly _participants: readonly IEditorHoverParticipant[] ) { this._editor = editor; this._result = []; @@ -94,12 +95,22 @@ class ModesContentComputer implements IHoverComputer { } public async computeAsync(token: CancellationToken): Promise { - if (!this._editor.hasModel() || !this._range) { + const range = this._range; + + if (!this._editor.hasModel() || !range) { return Promise.resolve([]); } - const markdownHovers = await this._markdownHoverParticipant.computeAsync(this._range, token); - return markdownHovers.map(h => new HoverPartInfo(this._markdownHoverParticipant, h)); + const allResults = await Promise.all(this._participants.map(p => this._computeAsync(p, range, token))); + return flatten(allResults); + } + + private async _computeAsync(participant: IEditorHoverParticipant, range: Range, token: CancellationToken): Promise { + if (!participant.computeAsync) { + return []; + } + const parts = await participant.computeAsync(range, token); + return parts.map(part => new HoverPartInfo(participant, part)); } public computeSync(): HoverPartInfo[] { @@ -142,15 +153,18 @@ class ModesContentComputer implements IHoverComputer { } } - const markdownHovers = this._markdownHoverParticipant.computeSync(this._range, lineDecorations); - result = result.concat(markdownHovers.map(h => new HoverPartInfo(this._markdownHoverParticipant, h))); - - const markerHovers = this._markerHoverParticipant.computeSync(this._range, lineDecorations); - result = result.concat(markerHovers.map(h => new HoverPartInfo(this._markerHoverParticipant, h))); + for (const participant of this._participants) { + result = result.concat(this._computeSync(participant, this._range, lineDecorations)); + } return coalesce(result); } + private _computeSync(participant: IEditorHoverParticipant, range: Range, lineDecorations: IModelDecoration[]): HoverPartInfo[] { + const parts = participant.computeSync(range, lineDecorations); + return parts.map(part => new HoverPartInfo(participant, part)); + } + public onResult(result: HoverPartInfo[], isFromSynchronousComputation: boolean): void { // Always put synchronous messages before asynchronous ones if (isFromSynchronousComputation) { @@ -166,9 +180,12 @@ class ModesContentComputer implements IHoverComputer { public getResultWithLoadingMessage(): HoverPartInfo[] { if (this._range) { - const loadingMessage = new HoverPartInfo(this._markdownHoverParticipant, this._markdownHoverParticipant.createLoadingMessage(this._range)); - return this._result.slice(0).concat([loadingMessage]); - + for (const participant of this._participants) { + if (participant.createLoadingMessage) { + const loadingMessage = new HoverPartInfo(participant, participant.createLoadingMessage(this._range)); + return this._result.slice(0).concat([loadingMessage]); + } + } } return this._result.slice(0); } @@ -178,9 +195,6 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I static readonly ID = 'editor.contrib.modesContentHoverWidget'; - private readonly _markerHoverParticipant: IEditorHoverParticipant; - private readonly _markdownHoverParticipant: MarkdownHoverParticipant; - private readonly _hover: HoverWidget; private readonly _id: string; private readonly _editor: ICodeEditor; @@ -210,8 +224,8 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I ) { super(); - this._markerHoverParticipant = instantiationService.createInstance(MarkerHoverParticipant, editor, this); - this._markdownHoverParticipant = instantiationService.createInstance(MarkdownHoverParticipant, editor, this); + const markerHoverParticipant = instantiationService.createInstance(MarkerHoverParticipant, editor, this); + const markdownHoverParticipant = instantiationService.createInstance(MarkdownHoverParticipant, editor, this); this._hover = this._register(new HoverWidget()); this._id = ModesContentHoverWidget.ID; @@ -242,7 +256,7 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I this._messages = []; this._lastRange = null; - this._computer = new ModesContentComputer(this._editor, this._markerHoverParticipant, this._markdownHoverParticipant); + this._computer = new ModesContentComputer(this._editor, [markdownHoverParticipant, markerHoverParticipant]); this._highlightDecorations = []; this._isChangingDecorations = false; this._shouldFocus = false; @@ -480,8 +494,7 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I let containColorPicker = false; const disposables = new DisposableStore(); - const markerMessages: MarkerHover[] = []; - const markdownParts: MarkdownHover[] = []; + const hoverParts = new Map(); messages.forEach((_msg) => { const msg = _msg.data; if (!msg.range) { @@ -577,22 +590,18 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I this._renderDisposable = combinedDisposable(colorListener, colorChangeListener, widget, disposables); }); } else { - if (msg instanceof MarkerHover) { - markerMessages.push(msg); - } else { - if (msg instanceof MarkdownHover) { - markdownParts.push(msg); + if (msg.owner) { + if (!hoverParts.has(msg.owner)) { + hoverParts.set(msg.owner, []); } + const dest = hoverParts.get(msg.owner)!; + dest.push(msg); } } }); - if (markdownParts.length > 0) { - disposables.add(this._markdownHoverParticipant.renderHoverParts(markdownParts, fragment)); - } - - if (markerMessages.length) { - disposables.add(this._markerHoverParticipant.renderHoverParts(markerMessages, fragment)); + for (const [participant, participantHoverParts] of hoverParts) { + disposables.add(participant.renderHoverParts(participantHoverParts, fragment)); } this._renderDisposable = disposables; From 23e1f261dc82b17efee51f8b8642a8c44ec56b70 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 26 May 2021 18:04:23 +0200 Subject: [PATCH 137/140] Remove `HoverPartInfo` --- .../editor/contrib/hover/modesContentHover.ts | 64 ++++++++----------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index cc80ab62ffa..12ede0a1b13 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -63,17 +63,10 @@ class ColorHover implements IHoverPart { } } -class HoverPartInfo { - constructor( - public readonly owner: IEditorHoverParticipant | null, - public readonly data: IHoverPart - ) { } -} - -class ModesContentComputer implements IHoverComputer { +class ModesContentComputer implements IHoverComputer { private readonly _editor: ICodeEditor; - private _result: HoverPartInfo[]; + private _result: IHoverPart[]; private _range: Range | null; constructor( @@ -94,7 +87,7 @@ class ModesContentComputer implements IHoverComputer { this._result = []; } - public async computeAsync(token: CancellationToken): Promise { + public async computeAsync(token: CancellationToken): Promise { const range = this._range; if (!this._editor.hasModel() || !range) { @@ -105,15 +98,14 @@ class ModesContentComputer implements IHoverComputer { return flatten(allResults); } - private async _computeAsync(participant: IEditorHoverParticipant, range: Range, token: CancellationToken): Promise { + private async _computeAsync(participant: IEditorHoverParticipant, range: Range, token: CancellationToken): Promise { if (!participant.computeAsync) { return []; } - const parts = await participant.computeAsync(range, token); - return parts.map(part => new HoverPartInfo(participant, part)); + return participant.computeAsync(range, token); } - public computeSync(): HoverPartInfo[] { + public computeSync(): IHoverPart[] { if (!this._editor.hasModel() || !this._range) { return []; } @@ -141,31 +133,26 @@ class ModesContentComputer implements IHoverComputer { return true; }); - let result: HoverPartInfo[] = []; + let result: IHoverPart[] = []; const colorDetector = ColorDetector.get(this._editor); for (const d of lineDecorations) { const colorData = colorDetector.getColorData(d.range.getStartPosition()); if (colorData) { const { color, range } = colorData.colorInfo; - result.push(new HoverPartInfo(null, new ColorHover(Range.lift(range), color, colorData.provider))); + result.push(new ColorHover(Range.lift(range), color, colorData.provider)); break; } } for (const participant of this._participants) { - result = result.concat(this._computeSync(participant, this._range, lineDecorations)); + result = result.concat(participant.computeSync(this._range, lineDecorations)); } return coalesce(result); } - private _computeSync(participant: IEditorHoverParticipant, range: Range, lineDecorations: IModelDecoration[]): HoverPartInfo[] { - const parts = participant.computeSync(range, lineDecorations); - return parts.map(part => new HoverPartInfo(participant, part)); - } - - public onResult(result: HoverPartInfo[], isFromSynchronousComputation: boolean): void { + public onResult(result: IHoverPart[], isFromSynchronousComputation: boolean): void { // Always put synchronous messages before asynchronous ones if (isFromSynchronousComputation) { this._result = result.concat(this._result); @@ -174,15 +161,15 @@ class ModesContentComputer implements IHoverComputer { } } - public getResult(): HoverPartInfo[] { + public getResult(): IHoverPart[] { return this._result.slice(0); } - public getResultWithLoadingMessage(): HoverPartInfo[] { + public getResultWithLoadingMessage(): IHoverPart[] { if (this._range) { for (const participant of this._participants) { if (participant.createLoadingMessage) { - const loadingMessage = new HoverPartInfo(participant, participant.createLoadingMessage(this._range)); + const loadingMessage = participant.createLoadingMessage(this._range); return this._result.slice(0).concat([loadingMessage]); } } @@ -206,10 +193,10 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I // IContentWidget.allowEditorOverflow public readonly allowEditorOverflow = true; - private _messages: HoverPartInfo[]; + private _messages: IHoverPart[]; private _lastRange: Range | null; private readonly _computer: ModesContentComputer; - private readonly _hoverOperation: HoverOperation; + private readonly _hoverOperation: HoverOperation; private _highlightDecorations: string[]; private _isChangingDecorations: boolean; private _shouldFocus: boolean; @@ -286,7 +273,7 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I this._messages = this._messages.map(msg => { // If a color hover is visible, we need to update the message that // created it so that the color matches the last chosen color - if (msg.data instanceof ColorHover && !!this._lastRange?.intersectRanges(msg.data.range) && this._colorPicker?.model.color) { + if (msg instanceof ColorHover && !!this._lastRange?.intersectRanges(msg.range) && this._colorPicker?.model.color) { const color = this._colorPicker.model.color; const newColor = { red: color.rgba.r / 255, @@ -294,7 +281,7 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I blue: color.rgba.b / 255, alpha: color.rgba.a }; - return new HoverPartInfo(msg.owner, new ColorHover(msg.data.range, newColor, msg.data.provider)); + return new ColorHover(msg.range, newColor, msg.provider); } else { return msg; } @@ -407,10 +394,10 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I if (!this._showAtPosition || this._showAtPosition.lineNumber !== range.startLineNumber) { this.hide(); } else { - let filteredMessages: HoverPartInfo[] = []; + let filteredMessages: IHoverPart[] = []; for (let i = 0, len = this._messages.length; i < len; i++) { const msg = this._messages[i]; - const rng = msg.data.range; + const rng = msg.range; if (rng && rng.startColumn <= range.startColumn && rng.endColumn >= range.endColumn) { filteredMessages.push(msg); } @@ -470,7 +457,7 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I this._hover.onContentsChanged(); } - private _withResult(result: HoverPartInfo[], complete: boolean): void { + private _withResult(result: IHoverPart[], complete: boolean): void { this._messages = result; if (this._lastRange && this._messages.length > 0) { @@ -480,7 +467,7 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I } } - private _renderMessages(renderRange: Range, messages: HoverPartInfo[]): void { + private _renderMessages(renderRange: Range, messages: IHoverPart[]): void { if (this._renderDisposable) { this._renderDisposable.dispose(); this._renderDisposable = null; @@ -489,14 +476,13 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I // update column from which to show let renderColumn = Constants.MAX_SAFE_SMALL_INTEGER; - let highlightRange: Range | null = messages[0].data.range ? Range.lift(messages[0].data.range) : null; + let highlightRange: Range | null = messages[0].range ? Range.lift(messages[0].range) : null; let fragment = document.createDocumentFragment(); let containColorPicker = false; const disposables = new DisposableStore(); const hoverParts = new Map(); - messages.forEach((_msg) => { - const msg = _msg.data; + messages.forEach((msg) => { if (!msg.range) { return; } @@ -626,12 +612,12 @@ export class ModesContentHoverWidget extends Widget implements IContentWidget, I }); } -function hoverContentsEquals(first: HoverPartInfo[], second: HoverPartInfo[]): boolean { +function hoverContentsEquals(first: IHoverPart[], second: IHoverPart[]): boolean { if (first.length !== second.length) { return false; } for (let i = 0; i < first.length; i++) { - if (!first[i].data.equals(second[i].data)) { + if (!first[i].equals(second[i])) { return false; } } From 5eb64c54ca438dd49e1b407e2f03bdbfae0d64b8 Mon Sep 17 00:00:00 2001 From: Ashray Jha Date: Wed, 26 May 2021 21:35:35 +0530 Subject: [PATCH 138/140] Modified markdown preview nested list styling (#124445) * Modified markdown preview nested list styling * Added proper styling to the nested list * merge different rules into a single one --- extensions/markdown-language-features/media/markdown.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extensions/markdown-language-features/media/markdown.css b/extensions/markdown-language-features/media/markdown.css index d4bcb78e065..8ea239c7341 100644 --- a/extensions/markdown-language-features/media/markdown.css +++ b/extensions/markdown-language-features/media/markdown.css @@ -105,6 +105,9 @@ body.showEditorSelection li.code-line:hover:before { .vscode-high-contrast.showEditorSelection .code-line .code-line:hover:before { border-left: none; } +ul ul,ul ol,ol ul,ol ol{ + margin-bottom: 0; +} img { max-width: 100%; From 9464d14f31744c8ac43a09c2c71a044622e8370e Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 26 May 2021 09:15:00 -0700 Subject: [PATCH 139/140] Make notebook renderer activate potentially async (#124647) * Make notebook renderer activate potentially async - Allow activate to be `async` - Make `getRenderer` always return a promise instead of the api result directly * Add comment on why we use async --- .../notebook/emoji.ts | 7 +++++-- .../notebook/katex.ts | 9 ++++++--- .../browser/view/renderers/webviewPreloads.ts | 16 +++++++++------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/extensions/notebook-markdown-extensions/notebook/emoji.ts b/extensions/notebook-markdown-extensions/notebook/emoji.ts index b842750a03c..28557b47047 100644 --- a/extensions/notebook-markdown-extensions/notebook/emoji.ts +++ b/extensions/notebook-markdown-extensions/notebook/emoji.ts @@ -6,10 +6,13 @@ import type * as markdownIt from 'markdown-it'; const emoji = require('markdown-it-emoji'); -export function activate(ctx: { +export async function activate(ctx: { getRenderer: (id: string) => any }) { - const markdownItRenderer = ctx.getRenderer('markdownItRenderer'); + const markdownItRenderer = await ctx.getRenderer('markdownItRenderer'); + if (!markdownItRenderer) { + throw new Error('Could not load markdownItRenderer'); + } markdownItRenderer.extendMarkdownIt((md: markdownIt.MarkdownIt) => { return md.use(emoji); diff --git a/extensions/notebook-markdown-extensions/notebook/katex.ts b/extensions/notebook-markdown-extensions/notebook/katex.ts index ccb12569053..27d7be58be7 100644 --- a/extensions/notebook-markdown-extensions/notebook/katex.ts +++ b/extensions/notebook-markdown-extensions/notebook/katex.ts @@ -6,10 +6,13 @@ import type * as markdownIt from 'markdown-it'; const styleHref = import.meta.url.replace(/katex.js$/, 'katex.min.css'); -export function activate(ctx: { - getRenderer: (id: string) => any +export async function activate(ctx: { + getRenderer: (id: string) => Promise }) { - const markdownItRenderer = ctx.getRenderer('markdownItRenderer'); + const markdownItRenderer = await ctx.getRenderer('markdownItRenderer'); + if (!markdownItRenderer) { + throw new Error('Could not load markdownItRenderer'); + } const link = document.createElement('link'); link.rel = 'stylesheet'; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 8250b75e1f3..ff86aa25c5f 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -130,13 +130,13 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re interface RendererContext { getState(): T | undefined; setState(newState: T): void; - getRenderer(id: string): any | undefined; + getRenderer(id: string): Promise; postMessage?(message: unknown): void; onDidReceiveMessage?: Event; } interface ScriptModule { - activate: (ctx?: RendererContext) => any; + activate(ctx?: RendererContext): Promise | RendererApi | undefined | any; } const invokeSourceWithGlobals = (functionSrc: string, globals: { [name: string]: unknown }) => { @@ -844,7 +844,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re ) { } private _onMessageEvent = createEmitter(); - private _loadPromise: Promise | undefined; + private _loadPromise?: Promise; private _api: RendererApi | undefined; public get api() { return this._api; } @@ -869,7 +869,9 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re const state = vscode.getState(); return typeof state === 'object' && state ? state[id] as T : undefined; }, - getRenderer: (id: string) => renderers.getRenderer(id)?.api, + // TODO: This is async so that we can return a promise to the API in the future. + // Currently the API is always resolved before we call `createRendererContext`. + getRenderer: async (id: string) => renderers.getRenderer(id)?.api, }; if (messaging) { @@ -881,13 +883,13 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re } /** Inner function cached in the _loadPromise(). */ - private async _load() { + private async _load(): Promise { const module = await runRenderScript(this.data.entrypoint, this.data.id); if (!module) { return; } - const api = module.activate(this.createRendererContext()); + const api = await module.activate(this.createRendererContext()); this._api = api; // Squash any errors extends errors. They won't prevent the renderer @@ -902,7 +904,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re } const kernelPreloads = new class { - private readonly preloads = new Map>(); + private readonly preloads = new Map>(); /** * Returns a promise that resolves when the given preload is activated. From 7f21b1af48502bdf710e84f9fb7d90db09c24945 Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Wed, 26 May 2021 10:42:20 -0700 Subject: [PATCH 140/140] Revert "Allow extensions to create multiple sessions from the same provider (#124640)" (#124705) This reverts commit a18ea9c9ec25c59e599ba3c2eb668315546dd269. --- .../api/browser/mainThreadAuthentication.ts | 13 +- .../api/common/extHostAuthentication.ts | 5 +- .../browser/authenticationService.ts | 4 +- .../api/mainThreadAuthentication.test.ts | 136 ------------------ .../test/common/workbenchTestServices.ts | 19 --- 5 files changed, 14 insertions(+), 163 deletions(-) delete mode 100644 src/vs/workbench/test/browser/api/mainThreadAuthentication.test.ts diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index 401db52faa2..19e704dff86 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -183,15 +183,21 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu return choice === 0; } + private async setTrustedExtensionAndAccountPreference(providerId: string, accountName: string, extensionId: string, extensionName: string, sessionId: string): Promise { + this.authenticationService.updatedAllowedExtension(providerId, accountName, extensionId, extensionName, true); + this.storageService.store(`${extensionName}-${providerId}`, sessionId, StorageScope.GLOBAL, StorageTarget.MACHINE); + + } + private async selectSession(providerId: string, extensionId: string, extensionName: string, scopes: string[], potentialSessions: readonly modes.AuthenticationSession[], clearSessionPreference: boolean, silent: boolean): Promise { if (!potentialSessions.length) { throw new Error('No potential sessions found'); } if (clearSessionPreference) { - this.storageService.remove(`${extensionName}-${providerId}-${scopes.join('-')}`, StorageScope.GLOBAL); + this.storageService.remove(`${extensionName}-${providerId}`, StorageScope.GLOBAL); } else { - const existingSessionPreference = this.storageService.get(`${extensionName}-${providerId}-${scopes.join('-')}`, StorageScope.GLOBAL); + const existingSessionPreference = this.storageService.get(`${extensionName}-${providerId}`, StorageScope.GLOBAL); if (existingSessionPreference) { const matchingSession = potentialSessions.find(session => session.id === existingSessionPreference); if (matchingSession) { @@ -255,8 +261,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu } session = await this.authenticationService.createSession(providerId, scopes, true); - await this.authenticationService.updatedAllowedExtension(providerId, session.account.label, extensionId, extensionName, true); - this.storageService.store(`${extensionName}-${providerId}-${scopes.join('-')}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); + await this.setTrustedExtensionAndAccountPreference(providerId, session.account.label, extensionId, extensionName, session.id); } else { await this.authenticationService.requestNewSession(providerId, scopes, extensionId, extensionName); } diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index 14acdb4343c..c134a357403 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -68,8 +68,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { this._inFlightRequests.set(extensionId, inFlightRequests); try { - const s = await session; - return s; + await session; } finally { const requestIndex = inFlightRequests.findIndex(request => request.scopes === sortedScopes); if (requestIndex > -1) { @@ -77,6 +76,8 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { this._inFlightRequests.set(extensionId, inFlightRequests); } } + + return session; } } diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts index 1654f175077..b5da23219ea 100644 --- a/src/vs/workbench/services/authentication/browser/authenticationService.ts +++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts @@ -503,7 +503,7 @@ export class AuthenticationService extends Disposable implements IAuthentication this.updatedAllowedExtension(providerId, accountName, extensionId, extensionName, true); this.removeAccessRequest(providerId, extensionId); - this.storageService.store(`${extensionName}-${providerId}-${scopes.join('-')}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); + this.storageService.store(`${extensionName}-${providerId}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); quickPick.dispose(); resolve(session); @@ -638,7 +638,7 @@ export class AuthenticationService extends Disposable implements IAuthentication this.updatedAllowedExtension(providerId, session.account.label, extensionId, extensionName, true); // And also set it as the preferred account for the extension - storageService.store(`${extensionName}-${providerId}-${scopes.join('-')}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); + storageService.store(`${extensionName}-${providerId}`, session.id, StorageScope.GLOBAL, StorageTarget.MACHINE); } }); diff --git a/src/vs/workbench/test/browser/api/mainThreadAuthentication.test.ts b/src/vs/workbench/test/browser/api/mainThreadAuthentication.test.ts deleted file mode 100644 index e4bd24e47b9..00000000000 --- a/src/vs/workbench/test/browser/api/mainThreadAuthentication.test.ts +++ /dev/null @@ -1,136 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as assert from 'assert'; -import { AuthenticationProviderInformation } from 'vs/editor/common/modes'; -import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService'; -import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; -import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { INotificationService } from 'vs/platform/notification/common/notification'; -import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService'; -import { IQuickInputHideEvent, IQuickInputService, IQuickPickDidAcceptEvent } from 'vs/platform/quickinput/common/quickInput'; -import { IStorageService } from 'vs/platform/storage/common/storage'; -import { MainThreadAuthentication } from 'vs/workbench/api/browser/mainThreadAuthentication'; -import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol'; -import { IActivityService } from 'vs/workbench/services/activity/common/activity'; -import { AuthenticationService, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService'; -import { ExtensionHostKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { TestRemoteAgentService } from 'vs/workbench/services/remote/test/common/testServices'; -import { TestQuickInputService } from 'vs/workbench/test/browser/workbenchTestServices'; -import { TestActivityService, TestExtensionService, TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; - -function createSession(id: string = '1234', scope: string[] = []) { - return { - accessToken: '1234', - account: { - id: 'test@test.com', - label: 'Test Person' - }, - id: id, - scopes: scope - }; -} - -class AuthQuickPick { - private listener: ((e: IQuickPickDidAcceptEvent) => any) | undefined; - public items = []; - public get selectedItems(): string[] { - return this.items; - } - - onDidAccept(listener: (e: IQuickPickDidAcceptEvent) => any) { - this.listener = listener; - } - onDidHide(listener: (e: IQuickInputHideEvent) => any) { - - } - dispose() { - - } - show() { - this.listener!({ - inBackground: false - }); - } -} -class AuthTestQuickInputService extends TestQuickInputService { - override createQuickPick() { - return new AuthQuickPick(); - } -} - -suite('MainThreadAuthentication', () => { - let mainThreadAuthentication: MainThreadAuthentication; - suiteSetup(async () => { - // extHostContext: IExtHostContext, - const services = new ServiceCollection(); - const dialogService = new TestDialogService(); - const storageService = new TestStorageService(); - const quickInputService = new AuthTestQuickInputService(); - const extensionService = new TestExtensionService(); - - const activityService = new TestActivityService(); - const remoteAgentService = new TestRemoteAgentService(); - - services.set(IDialogService, dialogService); - services.set(IStorageService, storageService); - services.set(INotificationService, new TestNotificationService()); - services.set(IQuickInputService, quickInputService); - services.set(IExtensionService, extensionService); - services.set(IActivityService, activityService); - services.set(IRemoteAgentService, remoteAgentService); - - const instaService = new InstantiationService(services); - services.set(IAuthenticationService, instaService.createInstance(AuthenticationService)); - - mainThreadAuthentication = instaService.createInstance(MainThreadAuthentication, - new class implements IExtHostContext { - remoteAuthority = ''; - extensionHostKind = ExtensionHostKind.LocalProcess; - assertRegistered() { } - set(v: any): any { return null; } - getProxy(): any { - return { - $getSessions(id: string, scopes: string[]) { - return Promise.resolve([createSession(id, scopes)]); - }, - $createSession(id: string, scopes: string[]) { - return Promise.resolve(createSession(id, scopes)); - }, - $removeSession(id: string, sessionId: string) { return Promise.resolve(); }, - $onDidChangeAuthenticationSessions(id: string, label: string) { return Promise.resolve(); }, - $onDidChangeAuthenticationProviders(added: AuthenticationProviderInformation[], removed: AuthenticationProviderInformation[]) { return Promise.resolve(); }, - $setProviders(providers: AuthenticationProviderInformation[]) { return Promise.resolve(); } - }; - } - drain(): any { return null; } - }); - - await mainThreadAuthentication.$registerAuthenticationProvider('test', 'test provider', true); - }); - - suiteTeardown(() => { - mainThreadAuthentication.$unregisterAuthenticationProvider('test'); - }); - - test('Can get a session', async () => { - const session = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', { createIfNone: true, clearSessionPreference: false }); - assert.strictEqual(session?.id, 'test'); - assert.strictEqual(session?.scopes[0], 'foo'); - }); - - test('Can get multiple sessions (with different scopes) in one extension', async () => { - let session = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', { createIfNone: true, clearSessionPreference: false }); - session = await mainThreadAuthentication.$getSession('test', ['bar'], 'testextension', 'test extension', { createIfNone: true, clearSessionPreference: false }); - assert.strictEqual(session?.id, 'test'); - assert.strictEqual(session?.scopes[0], 'bar'); - - session = await mainThreadAuthentication.$getSession('test', ['foo'], 'testextension', 'test extension', { createIfNone: false, clearSessionPreference: false }); - assert.strictEqual(session?.id, 'test'); - assert.strictEqual(session?.scopes[0], 'foo'); - }); -}); diff --git a/src/vs/workbench/test/common/workbenchTestServices.ts b/src/vs/workbench/test/common/workbenchTestServices.ts index f4450ecfcd5..b2ddf026545 100644 --- a/src/vs/workbench/test/common/workbenchTestServices.ts +++ b/src/vs/workbench/test/common/workbenchTestServices.ts @@ -22,7 +22,6 @@ import { IFileStatWithMetadata } from 'vs/platform/files/common/files'; import { ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor'; import { CancellationToken } from 'vs/base/common/cancellation'; import product from 'vs/platform/product/common/product'; -import { IActivity, IActivityService } from 'vs/workbench/services/activity/common/activity'; export class TestTextResourcePropertiesService implements ITextResourcePropertiesService { @@ -215,21 +214,3 @@ export interface Ctor { export class TestExtensionService extends NullExtensionService { } export const TestProductService = { _serviceBrand: undefined, ...product }; - -export class TestActivityService implements IActivityService { - _serviceBrand: undefined; - showViewContainerActivity(viewContainerId: string, badge: IActivity): IDisposable { - return this; - } - showViewActivity(viewId: string, badge: IActivity): IDisposable { - return this; - } - showAccountsActivity(activity: IActivity): IDisposable { - return this; - } - showGlobalActivity(activity: IActivity): IDisposable { - return this; - } - - dispose() { } -}