From 86a881805966f2d206760b789e7468faa360a5d7 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 19 Jan 2021 09:31:42 -0800 Subject: [PATCH 01/10] multi selection in notebook --- src/vs/vscode.proposed.d.ts | 4 ++-- src/vs/workbench/api/common/extHostNotebook.ts | 6 ++---- .../api/common/extHostNotebookEditor.ts | 2 +- .../notebook/browser/notebookEditorWidget.ts | 17 ++++++++++++++++- .../notebook/browser/view/notebookCellList.ts | 16 ++++++++++++++-- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 0c4b9fd83a0..d9a1d264ec9 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1319,7 +1319,7 @@ declare module 'vscode' { /** * The primary selected cell on this notebook editor. */ - readonly selection?: NotebookCell; + readonly selection?: NotebookCell[]; /** @@ -1443,7 +1443,7 @@ declare module 'vscode' { export interface NotebookEditorSelectionChangeEvent { readonly notebookEditor: NotebookEditor; - readonly selection?: NotebookCell; + readonly selection?: NotebookCell[]; } export interface NotebookEditorVisibleRangesChangeEvent { diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 298548f294a..02cdd7a8971 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -651,8 +651,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN if (data.selections) { if (data.selections.selections.length) { - const firstCell = data.selections.selections[0]; - editor.editor.selection = editor.editor.notebookData.getCell(firstCell)?.cell; + editor.editor.selection = data.selections.selections.map(cellHandle => editor?.editor.notebookData.getCell(cellHandle)?.cell).filter(selection => selection !== undefined) as vscode.NotebookCell[]; } else { editor.editor.selection = undefined; } @@ -695,8 +694,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN ); if (selections.length) { - const firstCell = selections[0]; - editor.selection = editor.notebookData.getCell(firstCell)?.cell; + editor.selection = selections.map(cellHandle => editor.notebookData.getCell(cellHandle)?.cell).filter(selection => selection !== undefined) as vscode.NotebookCell[]; } else { editor.selection = undefined; } diff --git a/src/vs/workbench/api/common/extHostNotebookEditor.ts b/src/vs/workbench/api/common/extHostNotebookEditor.ts index 60e3af8a293..4ce123b6ed7 100644 --- a/src/vs/workbench/api/common/extHostNotebookEditor.ts +++ b/src/vs/workbench/api/common/extHostNotebookEditor.ts @@ -91,7 +91,7 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit { export class ExtHostNotebookEditor extends Disposable implements vscode.NotebookEditor { //TODO@rebornix noop setter? - selection?: vscode.NotebookCell; + selection?: vscode.NotebookCell[]; private _visibleRanges: vscode.NotebookCellRange[] = []; private _viewColumn?: vscode.ViewColumn; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index f4b6b12199a..f654fe47410 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -472,7 +472,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor horizontalScrolling: false, keyboardSupport: false, mouseSupport: true, - multipleSelectionSupport: false, + multipleSelectionSupport: true, enableKeyboardNavigation: true, additionalScrollHeight: 0, transformOptimization: false, //(isMacintosh && isNative) || getTitleBarStyle(this.configurationService, this.environmentService) === 'native', @@ -2109,6 +2109,13 @@ export const focusedCellBackground = registerColor('notebook.focusedCellBackgrou hc: null }, nls.localize('focusedCellBackground', "The background color of a cell when the cell is focused.")); +export const selectedCellBackground = registerColor('notebook.selectedCellBackground', { + dark: null, + light: null, + hc: null +}, nls.localize('selectedCellBackground', "The background color of a cell when the cell is selected.")); + + export const cellHoverBackground = registerColor('notebook.cellHoverBackground', { dark: transparent(focusedCellBackground, .5), light: transparent(focusedCellBackground, .7), @@ -2240,6 +2247,14 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.notebookOverlay .code-cell-row.focused .cell-collapsed-part { background-color: ${focusedCellBackgroundColor} !important; }`); } + const selectedCellBackgroundColor = theme.getColor(selectedCellBackground); + if (selectedCellBackground) { + collector.addRule(`.notebookOverlay .monaco-list.selection-multiple .markdown-cell-row.selected { background-color: ${selectedCellBackgroundColor} !important; }`); + collector.addRule(`.notebookOverlay .monaco-list.selection-multiple .code-cell-row.selected { background-color: ${selectedCellBackgroundColor} !important; }`); + collector.addRule(`.notebookOverlay .monaco-list.selection-multiple .markdown-cell-row.selected .cell-focus-indicator-bottom { background-color: ${selectedCellBackgroundColor} !important; }`); + collector.addRule(`.notebookOverlay .monaco-list.selection-multiple .code-cell-row.selected .cell-focus-indicator-bottom { background-color: ${selectedCellBackgroundColor} !important; }`); + } + const cellHoverBackgroundColor = theme.getColor(cellHoverBackground); if (cellHoverBackgroundColor) { collector.addRule(`.notebookOverlay .code-cell-row:not(.focused):hover .cell-focus-indicator, diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index 8d0c6a5422a..d41f0ce579b 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -368,7 +368,7 @@ export class NotebookCellList extends WorkbenchList implements ID const viewSelections = model.selectionHandles.map(handle => { return model.getCellByHandle(handle); }).filter(cell => !!cell).map(cell => this._getViewIndexUpperBound(cell!)); - this.setFocus(viewSelections, undefined, true); + this.setSelection(viewSelections, undefined, true); })); const hiddenRanges = model.getHiddenRanges(); @@ -592,6 +592,18 @@ export class NotebookCellList extends WorkbenchList implements ID } setFocus(indexes: number[], browserEvent?: UIEvent, ignoreTextModelUpdate?: boolean): void { + // if (!indexes.length) { + // return; + // } + + // if (this._viewModel && !ignoreTextModelUpdate) { + // this._viewModel.selectionHandles = indexes.map(index => this.element(index)).map(cell => cell.handle); + // } + + super.setFocus(indexes, browserEvent); + } + + setSelection(indexes: number[], browserEvent?: UIEvent | undefined, ignoreTextModelUpdate?: boolean) { if (!indexes.length) { return; } @@ -600,7 +612,7 @@ export class NotebookCellList extends WorkbenchList implements ID this._viewModel.selectionHandles = indexes.map(index => this.element(index)).map(cell => cell.handle); } - super.setFocus(indexes, browserEvent); + super.setSelection(indexes, browserEvent); } revealElementsInView(range: ICellRange) { From b2600b23d5b3661b7c7d1376657deaefbcc69a4d Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 19 Jan 2021 13:15:59 -0800 Subject: [PATCH 02/10] Cut keyboard shortcut support mutli selection --- .../notebook/browser/notebookBrowser.ts | 1 + .../notebook/browser/notebookEditorWidget.ts | 8 ++++ .../notebook/browser/notebookServiceImpl.ts | 39 +++++++++++++------ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index b5ed5c132a1..e10e88813f6 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -348,6 +348,7 @@ export interface INotebookEditor extends IEditor, ICommonNotebookEditor { getOverflowContainerDomNode(): HTMLElement; getInnerWebview(): Webview | undefined; getSelectionHandles(): number[]; + getSelectionViewModels(): ICellViewModel[]; /** * Focus the notebook editor cell list diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index f654fe47410..27c48747a51 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -297,6 +297,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor return this.viewModel?.selectionHandles || []; } + getSelectionViewModels(): ICellViewModel[] { + if (!this.viewModel) { + return []; + } + + return this.viewModel.selectionHandles.map(handle => this.viewModel!.getCellByHandle(handle)) as ICellViewModel[]; + } + hasModel(): this is IActiveNotebookEditor { return !!this._notebookViewModel; } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 6209a04e5d1..f778fc5c65e 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -27,12 +27,12 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.protocol'; import { Memento } from 'vs/workbench/common/memento'; import { INotebookEditorContribution, notebookProviderExtensionPoint, notebookRendererExtensionPoint } from 'vs/workbench/contrib/notebook/browser/extensionPoint'; -import { CellEditState, getActiveNotebookEditor, INotebookEditor, NotebookEditorOptions, updateEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, getActiveNotebookEditor, ICellViewModel, INotebookEditor, NotebookEditorOptions, updateEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookKernelProviderAssociationRegistry, NotebookViewTypesExtensionRegistry, updateNotebookKernelProvideAssociationSchema } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; -import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellKind, CellOutputKind, DisplayOrderKey, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, RENDERER_NOT_AVAILABLE, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellEditType, CellKind, CellOutputKind, DisplayOrderKey, ICellEditOperation, IDisplayOutput, INotebookDecorationRenderOptions, INotebookKernelInfo2, INotebookKernelProvider, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, ITransformedDisplayOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, notebookDocumentFilterMatch, NotebookEditorPriority, NOTEBOOK_DISPLAY_ORDER, RENDERER_NOT_AVAILABLE, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer'; import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider'; import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; @@ -437,8 +437,8 @@ export class NotebookService extends Disposable implements INotebookService, ICu return false; } - const { editor, activeCell } = getContext(); - if (!editor || !activeCell) { + const { editor } = getContext(); + if (!editor) { return false; } @@ -449,8 +449,14 @@ export class NotebookService extends Disposable implements INotebookService, ICu const clipboardService = accessor.get(IClipboardService); const notebookService = accessor.get(INotebookService); - clipboardService.writeText(activeCell.getText()); - notebookService.setToCopy([activeCell.model], true); + const selectedCells = editor.getSelectionViewModels(); + + if (!selectedCells.length) { + return false; + } + + clipboardService.writeText(selectedCells.map(cell => cell.getText()).join('\n')); + notebookService.setToCopy(selectedCells.map(cell => cell.model), true); return true; })); @@ -573,8 +579,8 @@ export class NotebookService extends Disposable implements INotebookService, ICu return false; } - const { editor, activeCell } = getContext(); - if (!editor || !activeCell) { + const { editor } = getContext(); + if (!editor) { return false; } @@ -590,9 +596,20 @@ export class NotebookService extends Disposable implements INotebookService, ICu const clipboardService = accessor.get(IClipboardService); const notebookService = accessor.get(INotebookService); - clipboardService.writeText(activeCell.getText()); - viewModel.deleteCell(viewModel.getCellIndex(activeCell), true); - notebookService.setToCopy([activeCell.model], false); + const selectedCells = editor.getSelectionViewModels(); + + if (!selectedCells.length) { + return false; + } + + clipboardService.writeText(selectedCells.map(cell => cell.getText()).join('\n')); + + const edits: ICellEditOperation[] = selectedCells.map(cell => [cell, viewModel.getCellIndex(cell)] as [ICellViewModel, number]).sort((a, b) => b[1] - a[1]).map(value => { + return { editType: CellEditType.Replace, index: value[1], count: 1, cells: [] }; + }); + + viewModel.notebookDocument.applyEdits(viewModel.notebookDocument.versionId, edits, true, editor.getSelectionHandles(), () => { return undefined; }, undefined, true); + notebookService.setToCopy(selectedCells.map(cell => cell.model), false); return true; }); From 5e948799db01fe50cba54d65c04877019dfef52b Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 19 Jan 2021 14:49:16 -0800 Subject: [PATCH 03/10] fix build --- .../src/notebook.test.ts | 128 +++++++++--------- .../notebook/test/testNotebookEditor.ts | 3 + 2 files changed, 67 insertions(+), 64 deletions(-) diff --git a/extensions/vscode-notebook-tests/src/notebook.test.ts b/extensions/vscode-notebook-tests/src/notebook.test.ts index bd36c596958..5ab0b046bb0 100644 --- a/extensions/vscode-notebook-tests/src/notebook.test.ts +++ b/extensions/vscode-notebook-tests/src/notebook.test.ts @@ -312,7 +312,7 @@ suite('Notebook API tests', () => { await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); await vscode.commands.executeCommand('notebook.focusTop'); - const activeCell = vscode.window.activeNotebookEditor!.selection; + const activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0); const moveChange = getEventOncePromise(vscode.notebook.onDidChangeNotebookCells); await vscode.commands.executeCommand('notebook.cell.moveDown'); @@ -720,14 +720,14 @@ suite('notebook workflow', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0]?.document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0]?.language, 'typescript'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); - const activeCell = vscode.window.activeNotebookEditor!.selection; + const activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.notEqual(vscode.window.activeNotebookEditor!.selection, undefined); assert.equal(activeCell!.document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); @@ -742,16 +742,16 @@ suite('notebook workflow', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); // ---- insert cell below and focus ---- // await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); // ---- insert cell above and focus ---- // await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); - let activeCell = vscode.window.activeNotebookEditor!.selection; + let activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.notEqual(vscode.window.activeNotebookEditor!.selection, undefined); assert.equal(activeCell!.document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); @@ -759,21 +759,21 @@ suite('notebook workflow', () => { // ---- focus bottom ---- // await vscode.commands.executeCommand('notebook.focusBottom'); - activeCell = vscode.window.activeNotebookEditor!.selection; + activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 2); // ---- focus top and then copy down ---- // await vscode.commands.executeCommand('notebook.focusTop'); - activeCell = vscode.window.activeNotebookEditor!.selection; + activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0); await vscode.commands.executeCommand('notebook.cell.copyDown'); - activeCell = vscode.window.activeNotebookEditor!.selection; + activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1); assert.equal(activeCell?.document.getText(), 'test'); await vscode.commands.executeCommand('notebook.cell.delete'); - activeCell = vscode.window.activeNotebookEditor!.selection; + activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1); assert.equal(activeCell?.document.getText(), ''); @@ -785,15 +785,15 @@ suite('notebook workflow', () => { assert.equal(vscode.window.activeNotebookEditor!.document.cells[1].document.getText(), 'test'); assert.equal(vscode.window.activeNotebookEditor!.document.cells[2].document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells[3].document.getText(), ''); - activeCell = vscode.window.activeNotebookEditor!.selection; + activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0); // ---- move up and down ---- // await vscode.commands.executeCommand('notebook.cell.moveDown'); - assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection!), 1, - `first move down, active cell ${vscode.window.activeNotebookEditor!.selection!.uri.toString()}, ${vscode.window.activeNotebookEditor!.selection!.document.getText()}`); + assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection![0]), 1, + `first move down, active cell ${vscode.window.activeNotebookEditor!.selection![0].uri.toString()}, ${vscode.window.activeNotebookEditor!.selection![0].document.getText()}`); // await vscode.commands.executeCommand('notebook.cell.moveDown'); // activeCell = vscode.window.activeNotebookEditor!.selection; @@ -816,20 +816,20 @@ suite('notebook workflow', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); const cellsChangeEvent = getEventOncePromise(vscode.notebook.onDidChangeNotebookCells); await vscode.commands.executeCommand('notebook.cell.joinAbove'); await cellsChangeEvent; - assert.deepEqual(vscode.window.activeNotebookEditor!.selection?.document.getText().split(/\r\n|\r|\n/), ['test', 'var abc = 0;']); + assert.deepEqual(vscode.window.activeNotebookEditor!.selection![0].document.getText().split(/\r\n|\r|\n/), ['test', 'var abc = 0;']); await vscode.commands.executeCommand('workbench.action.files.save'); await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); @@ -843,7 +843,7 @@ suite('notebook workflow', () => { await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); await vscode.commands.executeCommand('notebook.focusTop'); - const activeCell = vscode.window.activeNotebookEditor!.selection; + const activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0); await vscode.commands.executeCommand('notebook.cell.moveDown'); await vscode.commands.executeCommand('notebook.cell.moveDown'); @@ -1045,14 +1045,14 @@ suite('notebook dirty state', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); - const activeCell = vscode.window.activeNotebookEditor!.selection; + const activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.notEqual(vscode.window.activeNotebookEditor!.selection, undefined); assert.equal(activeCell!.document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); @@ -1064,7 +1064,7 @@ suite('notebook dirty state', () => { assert.equal(vscode.window.activeNotebookEditor !== undefined, true); assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[1], vscode.window.activeNotebookEditor?.selection); - assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'var abc = 0;'); await saveFileAndCloseAll(resource); }); @@ -1076,14 +1076,14 @@ suite('notebook undo redo', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); - const activeCell = vscode.window.activeNotebookEditor!.selection; + const activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.notEqual(vscode.window.activeNotebookEditor!.selection, undefined); assert.equal(activeCell!.document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); @@ -1092,24 +1092,24 @@ suite('notebook undo redo', () => { // modify the second cell, delete it const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); await vscode.commands.executeCommand('notebook.cell.delete'); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 2); - assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection!), 1); + assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection![0]), 1); // undo should bring back the deleted cell, and revert to previous content and selection await vscode.commands.executeCommand('undo'); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); - assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection!), 1); - assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection![0]), 1); + assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'var abc = 0;'); // redo // await vscode.commands.executeCommand('notebook.redo'); // assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 2); // assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection!), 1); - // assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'test'); + // assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'test'); await saveFileAndCloseAll(resource); }); @@ -1184,7 +1184,7 @@ suite('notebook working copy', () => { // const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); // await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); // await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - // assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + // assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); // await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); // await vscode.commands.executeCommand('default:type', { text: 'var abc = 0;' }); @@ -1195,7 +1195,7 @@ suite('notebook working copy', () => { // assert.equal(vscode.window.activeNotebookEditor !== undefined, true); // assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); // assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[0], vscode.window.activeNotebookEditor?.selection); - // assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'test'); + // assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'test'); // await vscode.commands.executeCommand('workbench.action.files.save'); // await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); @@ -1205,7 +1205,7 @@ suite('notebook working copy', () => { // const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); // await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); // await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - // assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + // assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); // await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); // await vscode.commands.executeCommand('default:type', { text: 'var abc = 0;' }); @@ -1215,7 +1215,7 @@ suite('notebook working copy', () => { // assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); // assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[0], vscode.window.activeNotebookEditor?.selection); // assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells.length, 1); - // assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'test'); + // assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'test'); // await vscode.commands.executeCommand('workbench.action.files.saveAll'); // await vscode.commands.executeCommand('workbench.action.closeAllEditors'); @@ -1226,11 +1226,11 @@ suite('notebook working copy', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); const secondResource = await createRandomFile('', undefined, 'second', '.vsctestnb'); @@ -1242,7 +1242,7 @@ suite('notebook working copy', () => { assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[1], vscode.window.activeNotebookEditor?.selection); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells.length, 3); - assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'var abc = 0;'); await saveFileAndCloseAll(resource); }); @@ -1252,17 +1252,17 @@ suite('notebook working copy', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); const secondResource = await createRandomFile('', undefined, 'second', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); // switch to the first editor await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); @@ -1270,7 +1270,7 @@ suite('notebook working copy', () => { assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[1], vscode.window.activeNotebookEditor?.selection); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells.length, 3); - assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'var abc = 0;'); // switch to the second editor await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest'); @@ -1278,7 +1278,7 @@ suite('notebook working copy', () => { assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[1], vscode.window.activeNotebookEditor?.selection); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells.length, 2); - assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), ''); await saveAllFilesAndCloseAll(secondResource); // await vscode.commands.executeCommand('workbench.action.files.saveAll'); @@ -1292,14 +1292,14 @@ suite('notebook working copy', () => { await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); const firstNotebookEditor = vscode.window.activeNotebookEditor; assert.equal(firstNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(firstNotebookEditor!.selection?.document.getText(), 'test'); - assert.equal(firstNotebookEditor!.selection?.language, 'typescript'); + assert.equal(firstNotebookEditor!.selection![0].document.getText(), 'test'); + assert.equal(firstNotebookEditor!.selection![0].language, 'typescript'); await splitEditor(); const secondNotebookEditor = vscode.window.activeNotebookEditor; assert.equal(secondNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(secondNotebookEditor!.selection?.document.getText(), 'test'); - assert.equal(secondNotebookEditor!.selection?.language, 'typescript'); + assert.equal(secondNotebookEditor!.selection![0].document.getText(), 'test'); + assert.equal(secondNotebookEditor!.selection![0].language, 'typescript'); assert.notEqual(firstNotebookEditor, secondNotebookEditor); assert.equal(firstNotebookEditor?.document, secondNotebookEditor?.document, 'split notebook editors share the same document'); @@ -1319,8 +1319,8 @@ suite('metadata', () => { await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); assert.equal(vscode.window.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false); - assert.equal(vscode.window.activeNotebookEditor!.selection?.metadata.custom!['testCellMetadata'] as number, 123); - assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].metadata.custom!['testCellMetadata'] as number, 123); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); await saveFileAndCloseAll(resource); }); @@ -1333,8 +1333,8 @@ suite('metadata', () => { await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); assert.equal(vscode.window.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false); - assert.equal(vscode.window.activeNotebookEditor!.selection?.metadata.custom!['testCellMetadata'] as number, 123); - assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].metadata.custom!['testCellMetadata'] as number, 123); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); // TODO see #101462 // await vscode.commands.executeCommand('notebook.cell.copyDown'); @@ -1351,8 +1351,8 @@ suite('regression', () => { // assertInitalState(); // await vscode.commands.executeCommand('workbench.action.files.newUntitledFile', { "viewType": "notebookCoreTest" }); // assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - // assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); - // assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); + // assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + // assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); // await vscode.commands.executeCommand('workbench.action.closeAllEditors'); // }); @@ -1398,12 +1398,12 @@ suite('regression', () => { await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'var abc = 0;'); - assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); await vscode.commands.executeCommand('vscode.openWith', resource, 'default'); assert.equal(vscode.window.activeTextEditor?.document.uri.path, resource.path); @@ -1441,17 +1441,17 @@ suite('regression', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); - let activeCell = vscode.window.activeNotebookEditor!.selection; + let activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.equal(activeCell?.document.getText(), 'test'); await vscode.commands.executeCommand('notebook.cell.copyDown'); await vscode.commands.executeCommand('notebook.cell.edit'); - activeCell = vscode.window.activeNotebookEditor!.selection; + activeCell = vscode.window.activeNotebookEditor!.selection![0]; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1); assert.equal(activeCell?.document.getText(), 'test'); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 2); diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 1878693e84a..66a3e285653 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -66,6 +66,9 @@ export class TestNotebookEditor implements INotebookEditor { constructor( ) { } + getSelectionViewModels(): ICellViewModel[] { + throw new Error('Method not implemented.'); + } revealCellRangeInView(range: ICellRange): void { throw new Error('Method not implemented.'); } From 6794401b7c85271fdfa254e45a8dc980499fdf58 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 26 Jan 2021 08:15:15 -0800 Subject: [PATCH 04/10] minimal changes --- .../src/notebook.test.ts | 128 +++++++++--------- src/vs/vscode.proposed.d.ts | 4 +- .../workbench/api/common/extHostNotebook.ts | 6 +- .../api/common/extHostNotebookEditor.ts | 2 +- 4 files changed, 71 insertions(+), 69 deletions(-) diff --git a/extensions/vscode-notebook-tests/src/notebook.test.ts b/extensions/vscode-notebook-tests/src/notebook.test.ts index 5ab0b046bb0..bd36c596958 100644 --- a/extensions/vscode-notebook-tests/src/notebook.test.ts +++ b/extensions/vscode-notebook-tests/src/notebook.test.ts @@ -312,7 +312,7 @@ suite('Notebook API tests', () => { await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); await vscode.commands.executeCommand('notebook.focusTop'); - const activeCell = vscode.window.activeNotebookEditor!.selection![0]; + const activeCell = vscode.window.activeNotebookEditor!.selection; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0); const moveChange = getEventOncePromise(vscode.notebook.onDidChangeNotebookCells); await vscode.commands.executeCommand('notebook.cell.moveDown'); @@ -720,14 +720,14 @@ suite('notebook workflow', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0]?.document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0]?.language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); - const activeCell = vscode.window.activeNotebookEditor!.selection![0]; + const activeCell = vscode.window.activeNotebookEditor!.selection; assert.notEqual(vscode.window.activeNotebookEditor!.selection, undefined); assert.equal(activeCell!.document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); @@ -742,16 +742,16 @@ suite('notebook workflow', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); // ---- insert cell below and focus ---- // await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); // ---- insert cell above and focus ---- // await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); - let activeCell = vscode.window.activeNotebookEditor!.selection![0]; + let activeCell = vscode.window.activeNotebookEditor!.selection; assert.notEqual(vscode.window.activeNotebookEditor!.selection, undefined); assert.equal(activeCell!.document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); @@ -759,21 +759,21 @@ suite('notebook workflow', () => { // ---- focus bottom ---- // await vscode.commands.executeCommand('notebook.focusBottom'); - activeCell = vscode.window.activeNotebookEditor!.selection![0]; + activeCell = vscode.window.activeNotebookEditor!.selection; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 2); // ---- focus top and then copy down ---- // await vscode.commands.executeCommand('notebook.focusTop'); - activeCell = vscode.window.activeNotebookEditor!.selection![0]; + activeCell = vscode.window.activeNotebookEditor!.selection; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0); await vscode.commands.executeCommand('notebook.cell.copyDown'); - activeCell = vscode.window.activeNotebookEditor!.selection![0]; + activeCell = vscode.window.activeNotebookEditor!.selection; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1); assert.equal(activeCell?.document.getText(), 'test'); await vscode.commands.executeCommand('notebook.cell.delete'); - activeCell = vscode.window.activeNotebookEditor!.selection![0]; + activeCell = vscode.window.activeNotebookEditor!.selection; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1); assert.equal(activeCell?.document.getText(), ''); @@ -785,15 +785,15 @@ suite('notebook workflow', () => { assert.equal(vscode.window.activeNotebookEditor!.document.cells[1].document.getText(), 'test'); assert.equal(vscode.window.activeNotebookEditor!.document.cells[2].document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells[3].document.getText(), ''); - activeCell = vscode.window.activeNotebookEditor!.selection![0]; + activeCell = vscode.window.activeNotebookEditor!.selection; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0); // ---- move up and down ---- // await vscode.commands.executeCommand('notebook.cell.moveDown'); - assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection![0]), 1, - `first move down, active cell ${vscode.window.activeNotebookEditor!.selection![0].uri.toString()}, ${vscode.window.activeNotebookEditor!.selection![0].document.getText()}`); + assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection!), 1, + `first move down, active cell ${vscode.window.activeNotebookEditor!.selection!.uri.toString()}, ${vscode.window.activeNotebookEditor!.selection!.document.getText()}`); // await vscode.commands.executeCommand('notebook.cell.moveDown'); // activeCell = vscode.window.activeNotebookEditor!.selection; @@ -816,20 +816,20 @@ suite('notebook workflow', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); const cellsChangeEvent = getEventOncePromise(vscode.notebook.onDidChangeNotebookCells); await vscode.commands.executeCommand('notebook.cell.joinAbove'); await cellsChangeEvent; - assert.deepEqual(vscode.window.activeNotebookEditor!.selection![0].document.getText().split(/\r\n|\r|\n/), ['test', 'var abc = 0;']); + assert.deepEqual(vscode.window.activeNotebookEditor!.selection?.document.getText().split(/\r\n|\r|\n/), ['test', 'var abc = 0;']); await vscode.commands.executeCommand('workbench.action.files.save'); await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); @@ -843,7 +843,7 @@ suite('notebook workflow', () => { await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); await vscode.commands.executeCommand('notebook.focusTop'); - const activeCell = vscode.window.activeNotebookEditor!.selection![0]; + const activeCell = vscode.window.activeNotebookEditor!.selection; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 0); await vscode.commands.executeCommand('notebook.cell.moveDown'); await vscode.commands.executeCommand('notebook.cell.moveDown'); @@ -1045,14 +1045,14 @@ suite('notebook dirty state', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); - const activeCell = vscode.window.activeNotebookEditor!.selection![0]; + const activeCell = vscode.window.activeNotebookEditor!.selection; assert.notEqual(vscode.window.activeNotebookEditor!.selection, undefined); assert.equal(activeCell!.document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); @@ -1064,7 +1064,7 @@ suite('notebook dirty state', () => { assert.equal(vscode.window.activeNotebookEditor !== undefined, true); assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[1], vscode.window.activeNotebookEditor?.selection); - assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;'); await saveFileAndCloseAll(resource); }); @@ -1076,14 +1076,14 @@ suite('notebook undo redo', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'test'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'test'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); - const activeCell = vscode.window.activeNotebookEditor!.selection![0]; + const activeCell = vscode.window.activeNotebookEditor!.selection; assert.notEqual(vscode.window.activeNotebookEditor!.selection, undefined); assert.equal(activeCell!.document.getText(), ''); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); @@ -1092,24 +1092,24 @@ suite('notebook undo redo', () => { // modify the second cell, delete it const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); await vscode.commands.executeCommand('notebook.cell.delete'); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 2); - assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection![0]), 1); + assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection!), 1); // undo should bring back the deleted cell, and revert to previous content and selection await vscode.commands.executeCommand('undo'); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 3); - assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection![0]), 1); - assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection!), 1); + assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;'); // redo // await vscode.commands.executeCommand('notebook.redo'); // assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 2); // assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(vscode.window.activeNotebookEditor!.selection!), 1); - // assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'test'); + // assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'test'); await saveFileAndCloseAll(resource); }); @@ -1184,7 +1184,7 @@ suite('notebook working copy', () => { // const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); // await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); // await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - // assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + // assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); // await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); // await vscode.commands.executeCommand('default:type', { text: 'var abc = 0;' }); @@ -1195,7 +1195,7 @@ suite('notebook working copy', () => { // assert.equal(vscode.window.activeNotebookEditor !== undefined, true); // assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); // assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[0], vscode.window.activeNotebookEditor?.selection); - // assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'test'); + // assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'test'); // await vscode.commands.executeCommand('workbench.action.files.save'); // await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); @@ -1205,7 +1205,7 @@ suite('notebook working copy', () => { // const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); // await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); // await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - // assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + // assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); // await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); // await vscode.commands.executeCommand('default:type', { text: 'var abc = 0;' }); @@ -1215,7 +1215,7 @@ suite('notebook working copy', () => { // assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); // assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[0], vscode.window.activeNotebookEditor?.selection); // assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells.length, 1); - // assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'test'); + // assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'test'); // await vscode.commands.executeCommand('workbench.action.files.saveAll'); // await vscode.commands.executeCommand('workbench.action.closeAllEditors'); @@ -1226,11 +1226,11 @@ suite('notebook working copy', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); const secondResource = await createRandomFile('', undefined, 'second', '.vsctestnb'); @@ -1242,7 +1242,7 @@ suite('notebook working copy', () => { assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[1], vscode.window.activeNotebookEditor?.selection); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells.length, 3); - assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;'); await saveFileAndCloseAll(resource); }); @@ -1252,17 +1252,17 @@ suite('notebook working copy', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); const secondResource = await createRandomFile('', undefined, 'second', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); // switch to the first editor await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); @@ -1270,7 +1270,7 @@ suite('notebook working copy', () => { assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[1], vscode.window.activeNotebookEditor?.selection); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells.length, 3); - assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), 'var abc = 0;'); // switch to the second editor await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest'); @@ -1278,7 +1278,7 @@ suite('notebook working copy', () => { assert.equal(vscode.window.activeNotebookEditor?.selection !== undefined, true); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells[1], vscode.window.activeNotebookEditor?.selection); assert.deepEqual(vscode.window.activeNotebookEditor?.document.cells.length, 2); - assert.equal(vscode.window.activeNotebookEditor?.selection![0].document.getText(), ''); + assert.equal(vscode.window.activeNotebookEditor?.selection?.document.getText(), ''); await saveAllFilesAndCloseAll(secondResource); // await vscode.commands.executeCommand('workbench.action.files.saveAll'); @@ -1292,14 +1292,14 @@ suite('notebook working copy', () => { await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); const firstNotebookEditor = vscode.window.activeNotebookEditor; assert.equal(firstNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(firstNotebookEditor!.selection![0].document.getText(), 'test'); - assert.equal(firstNotebookEditor!.selection![0].language, 'typescript'); + assert.equal(firstNotebookEditor!.selection?.document.getText(), 'test'); + assert.equal(firstNotebookEditor!.selection?.language, 'typescript'); await splitEditor(); const secondNotebookEditor = vscode.window.activeNotebookEditor; assert.equal(secondNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(secondNotebookEditor!.selection![0].document.getText(), 'test'); - assert.equal(secondNotebookEditor!.selection![0].language, 'typescript'); + assert.equal(secondNotebookEditor!.selection?.document.getText(), 'test'); + assert.equal(secondNotebookEditor!.selection?.language, 'typescript'); assert.notEqual(firstNotebookEditor, secondNotebookEditor); assert.equal(firstNotebookEditor?.document, secondNotebookEditor?.document, 'split notebook editors share the same document'); @@ -1319,8 +1319,8 @@ suite('metadata', () => { await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); assert.equal(vscode.window.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].metadata.custom!['testCellMetadata'] as number, 123); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.metadata.custom!['testCellMetadata'] as number, 123); + assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); await saveFileAndCloseAll(resource); }); @@ -1333,8 +1333,8 @@ suite('metadata', () => { await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); assert.equal(vscode.window.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].metadata.custom!['testCellMetadata'] as number, 123); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.metadata.custom!['testCellMetadata'] as number, 123); + assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); // TODO see #101462 // await vscode.commands.executeCommand('notebook.cell.copyDown'); @@ -1351,8 +1351,8 @@ suite('regression', () => { // assertInitalState(); // await vscode.commands.executeCommand('workbench.action.files.newUntitledFile', { "viewType": "notebookCoreTest" }); // assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - // assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), ''); - // assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); + // assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), ''); + // assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); // await vscode.commands.executeCommand('workbench.action.closeAllEditors'); // }); @@ -1398,12 +1398,12 @@ suite('regression', () => { await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow'); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); assert.equal(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].document.getText(), 'var abc = 0;'); - assert.equal(vscode.window.activeNotebookEditor!.selection![0].language, 'typescript'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.document.getText(), 'var abc = 0;'); + assert.equal(vscode.window.activeNotebookEditor!.selection?.language, 'typescript'); await vscode.commands.executeCommand('vscode.openWith', resource, 'default'); assert.equal(vscode.window.activeTextEditor?.document.uri.path, resource.path); @@ -1441,17 +1441,17 @@ suite('regression', () => { const resource = await createRandomFile('', undefined, 'first', '.vsctestnb'); await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); - let activeCell = vscode.window.activeNotebookEditor!.selection![0]; + let activeCell = vscode.window.activeNotebookEditor!.selection; assert.equal(activeCell?.document.getText(), 'test'); await vscode.commands.executeCommand('notebook.cell.copyDown'); await vscode.commands.executeCommand('notebook.cell.edit'); - activeCell = vscode.window.activeNotebookEditor!.selection![0]; + activeCell = vscode.window.activeNotebookEditor!.selection; assert.equal(vscode.window.activeNotebookEditor!.document.cells.indexOf(activeCell!), 1); assert.equal(activeCell?.document.getText(), 'test'); const edit = new vscode.WorkspaceEdit(); - edit.insert(vscode.window.activeNotebookEditor!.selection![0].uri, new vscode.Position(0, 0), 'var abc = 0;'); + edit.insert(vscode.window.activeNotebookEditor!.selection!.uri, new vscode.Position(0, 0), 'var abc = 0;'); await vscode.workspace.applyEdit(edit); assert.equal(vscode.window.activeNotebookEditor!.document.cells.length, 2); diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index d9a1d264ec9..0c4b9fd83a0 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1319,7 +1319,7 @@ declare module 'vscode' { /** * The primary selected cell on this notebook editor. */ - readonly selection?: NotebookCell[]; + readonly selection?: NotebookCell; /** @@ -1443,7 +1443,7 @@ declare module 'vscode' { export interface NotebookEditorSelectionChangeEvent { readonly notebookEditor: NotebookEditor; - readonly selection?: NotebookCell[]; + readonly selection?: NotebookCell; } export interface NotebookEditorVisibleRangesChangeEvent { diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 02cdd7a8971..298548f294a 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -651,7 +651,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN if (data.selections) { if (data.selections.selections.length) { - editor.editor.selection = data.selections.selections.map(cellHandle => editor?.editor.notebookData.getCell(cellHandle)?.cell).filter(selection => selection !== undefined) as vscode.NotebookCell[]; + const firstCell = data.selections.selections[0]; + editor.editor.selection = editor.editor.notebookData.getCell(firstCell)?.cell; } else { editor.editor.selection = undefined; } @@ -694,7 +695,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN ); if (selections.length) { - editor.selection = selections.map(cellHandle => editor.notebookData.getCell(cellHandle)?.cell).filter(selection => selection !== undefined) as vscode.NotebookCell[]; + const firstCell = selections[0]; + editor.selection = editor.notebookData.getCell(firstCell)?.cell; } else { editor.selection = undefined; } diff --git a/src/vs/workbench/api/common/extHostNotebookEditor.ts b/src/vs/workbench/api/common/extHostNotebookEditor.ts index 4ce123b6ed7..60e3af8a293 100644 --- a/src/vs/workbench/api/common/extHostNotebookEditor.ts +++ b/src/vs/workbench/api/common/extHostNotebookEditor.ts @@ -91,7 +91,7 @@ class NotebookEditorCellEditBuilder implements vscode.NotebookEditorEdit { export class ExtHostNotebookEditor extends Disposable implements vscode.NotebookEditor { //TODO@rebornix noop setter? - selection?: vscode.NotebookCell[]; + selection?: vscode.NotebookCell; private _visibleRanges: vscode.NotebookCellRange[] = []; private _viewColumn?: vscode.ViewColumn; From f96b651052aa3fc6acfcd71037089d32d6096423 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 1 Feb 2021 20:58:23 -0800 Subject: [PATCH 05/10] we should only use comm object to communicate. --- src/vs/vscode.proposed.d.ts | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 8f0ead3ada8..0bf85818c51 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1235,32 +1235,6 @@ declare module 'vscode' { // @rebornix REMOVE/REplace NotebookCommunication // todo@API fishy? notebooks are public objects, there should be a "global" events for this readonly onDidDispose: Event; - - /** - * Fired when the output hosting webview posts a message. - */ - // @rebornix REMOVE - // todo@API notebook editors are public -> ANY extension can listen to these event - readonly onDidReceiveMessage: Event; - /** - * Post a message to the output hosting webview. - * - * Messages are only delivered if the editor is live. - * - * @param message Body of the message. This must be a string or other json serializable object. - */ - // @rebornix REMOVE - // todo@API notebook editors are public -> ANY extension can send messages - postMessage(message: any): Thenable; - - /** - * Convert a uri for the local file system to one that can be used inside outputs webview. - */ - // @rebornix REMOVE - // todo@API unsure about that, how do you this when executing a cell without having an editor - asWebviewUri(localResource: Uri): Uri; - - } export interface NotebookOutputSelector { From d45a8915d277d2c2b2603e882e6077c2ce3f1cae Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 1 Feb 2021 21:01:38 -0800 Subject: [PATCH 06/10] transient metadata should be used to control the content change and dirty state. --- src/vs/vscode.proposed.d.ts | 47 ------------------------------------- 1 file changed, 47 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 0bf85818c51..3982275b308 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1328,48 +1328,6 @@ declare module 'vscode' { readonly metadata: NotebookDocumentMetadata; } - interface NotebookDocumentContentChangeEvent { - - /** - * The document that the edit is for. - */ - readonly document: NotebookDocument; - } - - // @rebornix p2, remove - // todo@API is this still needed? With transient metadata have we everything covered? - interface NotebookDocumentEditEvent { - - /** - * The document that the edit is for. - */ - readonly document: NotebookDocument; - - /** - * Undo the edit operation. - * - * This is invoked by VS Code when the user undoes this edit. To implement `undo`, your - * extension should restore the document and editor to the state they were in just before this - * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. - */ - undo(): Thenable | void; - - /** - * Redo the edit operation. - * - * This is invoked by VS Code when the user redoes this edit. To implement `redo`, your - * extension should restore the document and editor to the state they were in just after this - * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. - */ - redo(): Thenable | void; - - /** - * Display name describing the edit. - * - * This will be shown to users in the UI for undo/redo operations. - */ - readonly label?: string; - } /** * Communication object passed to the {@link NotebookContentProvider} and @@ -1596,11 +1554,6 @@ declare module 'vscode' { export interface NotebookContentProvider { readonly options?: NotebookDocumentContentOptions; readonly onDidChangeNotebookContentOptions?: Event; - - // @rebornix - // todo@API should be removed - readonly onDidChangeNotebook: Event; - /** * Content providers should always use [file system providers](#FileSystemProvider) to * resolve the raw content for `uri` as the resouce is not necessarily a file on disk. From c4f273e3dfe4d8281c6047665c212cd5a577dae2 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 2 Feb 2021 09:39:10 -0800 Subject: [PATCH 07/10] fix tests. --- extensions/vscode-notebook-tests/src/notebook.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/vscode-notebook-tests/src/notebook.test.ts b/extensions/vscode-notebook-tests/src/notebook.test.ts index bd36c596958..cb252a20b71 100644 --- a/extensions/vscode-notebook-tests/src/notebook.test.ts +++ b/extensions/vscode-notebook-tests/src/notebook.test.ts @@ -1303,7 +1303,7 @@ suite('notebook working copy', () => { assert.notEqual(firstNotebookEditor, secondNotebookEditor); assert.equal(firstNotebookEditor?.document, secondNotebookEditor?.document, 'split notebook editors share the same document'); - assert.notEqual(firstNotebookEditor?.asWebviewUri(vscode.Uri.file('./hello.png')), secondNotebookEditor?.asWebviewUri(vscode.Uri.file('./hello.png'))); + // assert.notEqual(firstNotebookEditor?.asWebviewUri(vscode.Uri.file('./hello.png')), secondNotebookEditor?.asWebviewUri(vscode.Uri.file('./hello.png'))); await saveAllFilesAndCloseAll(resource); From 5ec17aba95e7958eb902266bc0a7c64d99b4335f Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 2 Feb 2021 11:21:54 -0800 Subject: [PATCH 08/10] fix build in exthostnotebook --- .../workbench/api/common/extHostNotebook.ts | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 298548f294a..434d48581ce 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -321,23 +321,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN this._notebookContentProviders.set(viewType, { extension, provider }); const listeners: vscode.Disposable[] = []; - listeners.push(provider.onDidChangeNotebook - ? provider.onDidChangeNotebook(e => { - const document = this._documents.get(URI.revive(e.document.uri)); - - if (!document) { - throw new Error(`Notebook document ${e.document.uri.toString()} not found`); - } - - if (isEditEvent(e)) { - const editId = document.addEdit(e); - this._proxy.$onUndoableContentChange(e.document.uri, viewType, editId, e.label); - } else { - this._proxy.$onContentChange(e.document.uri, viewType); - } - }) - : Disposable.None); - listeners.push(provider.onDidChangeNotebookContentOptions ? provider.onDidChangeNotebookContentOptions(() => { this._proxy.$updateNotebookProviderOptions(viewType, provider.options); @@ -892,11 +875,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN } } -function isEditEvent(e: vscode.NotebookDocumentEditEvent | vscode.NotebookDocumentContentChangeEvent): e is vscode.NotebookDocumentEditEvent { - return typeof (e as vscode.NotebookDocumentEditEvent).undo === 'function' - && typeof (e as vscode.NotebookDocumentEditEvent).redo === 'function'; -} - export class NotebookCellStatusBarItemInternal extends Disposable { private static NEXT_ID = 0; From 16d84195625dd2e26e0e7dbb3ec566c799b35e19 Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 2 Feb 2021 11:32:29 -0800 Subject: [PATCH 09/10] smoke test --- .../src/notebookSmokeTestMain.ts | 1 - .../src/notebookTestMain.ts | 34 +------------------ 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/extensions/vscode-notebook-tests/src/notebookSmokeTestMain.ts b/extensions/vscode-notebook-tests/src/notebookSmokeTestMain.ts index 10ab61306dc..bf3f05e35aa 100644 --- a/extensions/vscode-notebook-tests/src/notebookSmokeTestMain.ts +++ b/extensions/vscode-notebook-tests/src/notebookSmokeTestMain.ts @@ -21,7 +21,6 @@ export function smokeTestActivate(context: vscode.ExtensionContext): any { })); context.subscriptions.push(vscode.notebook.registerNotebookContentProvider('notebookSmokeTest', { - onDidChangeNotebook: new vscode.EventEmitter().event, openNotebook: async (_resource: vscode.Uri) => { const dto: vscode.NotebookData = { languages: ['typescript'], diff --git a/extensions/vscode-notebook-tests/src/notebookTestMain.ts b/extensions/vscode-notebook-tests/src/notebookTestMain.ts index c02749acd39..9b2b91a012a 100644 --- a/extensions/vscode-notebook-tests/src/notebookTestMain.ts +++ b/extensions/vscode-notebook-tests/src/notebookTestMain.ts @@ -9,10 +9,7 @@ import { smokeTestActivate } from './notebookSmokeTestMain'; export function activate(context: vscode.ExtensionContext): any { smokeTestActivate(context); - const _onDidChangeNotebook = new vscode.EventEmitter(); - context.subscriptions.push(_onDidChangeNotebook); context.subscriptions.push(vscode.notebook.registerNotebookContentProvider('notebookCoreTest', { - onDidChangeNotebook: _onDidChangeNotebook.event, openNotebook: async (_resource: vscode.Uri) => { if (/.*empty\-.*\.vsctestnb$/.test(_resource.path)) { return { @@ -91,7 +88,7 @@ export function activate(context: vscode.ExtensionContext): any { return; } - const previousOutputs = cell.outputs; + // const previousOutputs = cell.outputs; const newOutputs: vscode.CellOutput[] = [{ outputKind: vscode.CellOutputKind.Rich, data: { @@ -100,20 +97,6 @@ export function activate(context: vscode.ExtensionContext): any { }]; cell.outputs = newOutputs; - - _onDidChangeNotebook.fire({ - document: document, - undo: () => { - if (cell) { - cell.outputs = previousOutputs; - } - }, - redo: () => { - if (cell) { - cell.outputs = newOutputs; - } - } - }); return; }, cancelCellExecution: async (_document: vscode.NotebookDocument, _cell: vscode.NotebookCell) => { } @@ -151,7 +134,6 @@ export function activate(context: vscode.ExtensionContext): any { return; } - const previousOutputs = cell.outputs; const newOutputs: vscode.CellOutput[] = [{ outputKind: vscode.CellOutputKind.Rich, data: { @@ -160,20 +142,6 @@ export function activate(context: vscode.ExtensionContext): any { }]; cell.outputs = newOutputs; - - _onDidChangeNotebook.fire({ - document: document, - undo: () => { - if (cell) { - cell.outputs = previousOutputs; - } - }, - redo: () => { - if (cell) { - cell.outputs = newOutputs; - } - } - }); return; }, cancelCellExecution: async (_document: vscode.NotebookDocument, _cell: vscode.NotebookCell) => { } From 04abcc03381c96f5014881dbfdd626803757ad5d Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 2 Feb 2021 11:44:47 -0800 Subject: [PATCH 10/10] yarn watchd does not detect interface change again. --- .../api/browser/mainThreadNotebook.ts | 17 --------- .../workbench/api/common/extHost.protocol.ts | 4 --- .../workbench/api/common/extHostNotebook.ts | 20 ----------- .../api/common/extHostNotebookDocument.ts | 36 ------------------- 4 files changed, 77 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index 0b4b7f3f55d..fcde89ecbb4 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -10,7 +10,6 @@ import { Emitter } from 'vs/base/common/event'; import { IRelativePattern } from 'vs/base/common/glob'; import { combinedDisposable, Disposable, DisposableStore, dispose, IDisposable, IReference } from 'vs/base/common/lifecycle'; import { ResourceMap } from 'vs/base/common/map'; -import { Schemas } from 'vs/base/common/network'; import { IExtUri } from 'vs/base/common/resources'; import { URI, UriComponents } from 'vs/base/common/uri'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; @@ -31,7 +30,6 @@ import { IEditorGroup, IEditorGroupsService, preferredSideBySideGroupDirection } import { openEditorWith } from 'vs/workbench/services/editor/common/editorOpenWith'; import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; -import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { ExtHostContext, ExtHostNotebookShape, IExtHostContext, INotebookCellStatusBarEntryDto, INotebookDocumentsAndEditorsDelta, INotebookDocumentShowOptions, INotebookModelAddedData, MainContext, MainThreadNotebookShape, NotebookEditorRevealType, NotebookExtensionDescription } from '../common/extHost.protocol'; class DocumentAndEditorState { @@ -131,7 +129,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo @IAccessibilityService private readonly accessibilityService: IAccessibilityService, @ILogService private readonly logService: ILogService, @INotebookCellStatusBarService private readonly cellStatusBarService: INotebookCellStatusBarService, - @IWorkingCopyService private readonly _workingCopyService: IWorkingCopyService, @INotebookEditorModelResolverService private readonly _notebookModelResolverService: INotebookEditorModelResolverService, @IUriIdentityService private readonly _uriIdentityService: IUriIdentityService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @@ -605,20 +602,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo return false; } - $onUndoableContentChange(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void { - const textModel = this._notebookService.getNotebookTextModel(URI.from(resource)); - - if (textModel) { - textModel.handleUnknownUndoableEdit(label, () => { - const isDirty = this._workingCopyService.isDirty(textModel.uri.with({ scheme: Schemas.vscodeNotebook })); - return this._proxy.$undoNotebook(textModel.viewType, textModel.uri, editId, isDirty); - }, () => { - const isDirty = this._workingCopyService.isDirty(textModel.uri.with({ scheme: Schemas.vscodeNotebook })); - return this._proxy.$redoNotebook(textModel.viewType, textModel.uri, editId, isDirty); - }); - } - } - $onContentChange(resource: UriComponents, viewType: string): void { const textModel = this._notebookService.getNotebookTextModel(URI.from(resource)); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 65987a19419..ebda6d1a322 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -809,7 +809,6 @@ export interface MainThreadNotebookShape extends IDisposable { $registerNotebookEditorDecorationType(key: string, options: INotebookDecorationRenderOptions): void; $removeNotebookEditorDecorationType(key: string): void; $trySetDecorations(id: string, range: ICellRange, decorationKey: string): void; - $onUndoableContentChange(resource: UriComponents, viewType: string, editId: number, label: string | undefined): void; $onContentChange(resource: UriComponents, viewType: string): void; } @@ -1805,9 +1804,6 @@ export interface ExtHostNotebookShape { $acceptEditorPropertiesChanged(id: string, data: INotebookEditorPropertiesChangeData): void; $acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void; $acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): void; - $undoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise; - $redoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise; - } export interface ExtHostStorageShape { diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 434d48581ce..a77e61aac27 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -527,26 +527,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN return false; } - async $undoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise { - const document = this._documents.get(URI.revive(uri)); - if (!document) { - return; - } - - document.undo(editId, isDirty); - - } - - async $redoNotebook(viewType: string, uri: UriComponents, editId: number, isDirty: boolean): Promise { - const document = this._documents.get(URI.revive(uri)); - if (!document) { - return; - } - - document.redo(editId, isDirty); - } - - async $backup(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise { const document = this._documents.get(URI.revive(uri)); const provider = this._notebookContentProviders.get(viewType); diff --git a/src/vs/workbench/api/common/extHostNotebookDocument.ts b/src/vs/workbench/api/common/extHostNotebookDocument.ts index 85f9083bacd..d5708a31d9c 100644 --- a/src/vs/workbench/api/common/extHostNotebookDocument.ts +++ b/src/vs/workbench/api/common/extHostNotebookDocument.ts @@ -15,7 +15,6 @@ import { CellKind, INotebookDocumentPropertiesChangeData, IWorkspaceCellEditDto, import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { CellEditType, CellOutputKind, diff, IMainCellDto, IProcessedOutput, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookCellsChangeType, NotebookCellsSplice2, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import * as vscode from 'vscode'; -import { Cache } from './cache'; interface IObservable { @@ -231,8 +230,6 @@ export class ExtHostNotebookDocument extends Disposable { private _disposed = false; private _languages: string[] = []; - private readonly _edits = new Cache('notebook documents'); - constructor( private readonly _proxy: MainThreadNotebookShape, private readonly _documentsAndEditors: ExtHostDocumentsAndEditors, @@ -496,37 +493,4 @@ export class ExtHostNotebookDocument extends Disposable { getCellIndex(cell: ExtHostCell): number { return this._cells.indexOf(cell); } - - addEdit(item: vscode.NotebookDocumentEditEvent): number { - return this._edits.add([item]); - } - - async undo(editId: number, isDirty: boolean): Promise { - await this.getEdit(editId).undo(); - // if (!isDirty) { - // this.disposeBackup(); - // } - } - - async redo(editId: number, isDirty: boolean): Promise { - await this.getEdit(editId).redo(); - // if (!isDirty) { - // this.disposeBackup(); - // } - } - - private getEdit(editId: number): vscode.NotebookDocumentEditEvent { - const edit = this._edits.get(editId, 0); - if (!edit) { - throw new Error('No edit found'); - } - - return edit; - } - - disposeEdits(editIds: number[]): void { - for (const id of editIds) { - this._edits.delete(id); - } - } }