diff --git a/src/vs/workbench/api/browser/mainThreadNotebookKernels.ts b/src/vs/workbench/api/browser/mainThreadNotebookKernels.ts index 2cdf7d8b3ff..d6de28127b3 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebookKernels.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebookKernels.ts @@ -11,7 +11,7 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService'; -import { ICellRange, INotebookKernel, INotebookKernelChangeEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookKernel, INotebookKernelChangeEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { NotebookSelector } from 'vs/workbench/contrib/notebook/common/notebookSelector'; import { ExtHostContext, ExtHostNotebookKernelsShape, IExtHostContext, INotebookKernelDto2, MainContext, MainThreadNotebookKernelsShape } from '../common/extHost.protocol'; @@ -90,8 +90,8 @@ abstract class MainThreadKernel implements INotebookKernel { this._onDidChange.fire(event); } - abstract executeNotebookCellsRequest(uri: URI, ranges: ICellRange[]): Promise; - abstract cancelNotebookCellExecution(uri: URI, ranges: ICellRange[]): Promise; + abstract executeNotebookCellsRequest(uri: URI, cellHandles: number[]): Promise; + abstract cancelNotebookCellExecution(uri: URI, cellHandles: number[]): Promise; } @extHostNamedCustomer(MainContext.MainThreadNotebookKernels) @@ -186,11 +186,11 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape async $addKernel(handle: number, data: INotebookKernelDto2): Promise { const that = this; const kernel = new class extends MainThreadKernel { - async executeNotebookCellsRequest(uri: URI, ranges: ICellRange[]): Promise { - await that._proxy.$executeCells(handle, uri, ranges); + async executeNotebookCellsRequest(uri: URI, handles: number[]): Promise { + await that._proxy.$executeCells(handle, uri, handles); } - async cancelNotebookCellExecution(uri: URI, ranges: ICellRange[]): Promise { - await that._proxy.$cancelCells(handle, uri, ranges); + async cancelNotebookCellExecution(uri: URI, handles: number[]): Promise { + await that._proxy.$cancelCells(handle, uri, handles); } }(data); const registration = this._notebookKernelService.registerKernel(kernel); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 88d86a09baa..4b495f61980 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1953,8 +1953,8 @@ export interface ExtHostNotebookEditorsShape { export interface ExtHostNotebookKernelsShape { $acceptSelection(handle: number, uri: UriComponents, value: boolean): void; - $executeCells(handle: number, uri: UriComponents, ranges: ICellRange[]): Promise; - $cancelCells(handle: number, uri: UriComponents, ranges: ICellRange[]): Promise; + $executeCells(handle: number, uri: UriComponents, handles: number[]): Promise; + $cancelCells(handle: number, uri: UriComponents, handles: number[]): Promise; $acceptRendererMessage(handle: number, editorId: string, message: any): void; } diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index e866d3038c9..dc2c4fc32e4 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -635,17 +635,17 @@ export class ExtHostNotebookController implements ExtHostNotebookShape { createNotebookCellExecution(docUri: vscode.Uri, index: number, kernelId: string): vscode.NotebookCellExecutionTask | undefined { const document = this.lookupNotebookDocument(docUri); if (!document) { - throw new Error(`Invalid cell uri / index: ${docUri}, ${index} `); + throw new Error(`Invalid uri: ${docUri} `); } const cell = document.getCellFromIndex(index); if (!cell) { - throw new Error(`Invalid cell uri / index: ${docUri}, ${index} `); + throw new Error(`Invalid cell index: ${docUri}, ${index} `); } // TODO@roblou also validate kernelId, once kernel has moved from editor to document if (this._activeExecutions.has(cell.uri)) { - return; + throw new Error(`duplicate execution for ${cell.uri}`); } const execution = new NotebookCellExecutionTask(docUri, document, cell, this._notebookDocumentsProxy); diff --git a/src/vs/workbench/api/common/extHostNotebookKernels.ts b/src/vs/workbench/api/common/extHostNotebookKernels.ts index 597385f8cad..b874b90e189 100644 --- a/src/vs/workbench/api/common/extHostNotebookKernels.ts +++ b/src/vs/workbench/api/common/extHostNotebookKernels.ts @@ -10,7 +10,6 @@ import * as vscode from 'vscode'; import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook'; import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { URI, UriComponents } from 'vs/base/common/uri'; -import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService'; @@ -199,7 +198,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { } } - async $executeCells(handle: number, uri: UriComponents, ranges: ICellRange[]): Promise { + async $executeCells(handle: number, uri: UriComponents, handles: number[]): Promise { const obj = this._kernelData.get(handle); if (!obj) { // extension can dispose kernels in the meantime @@ -211,8 +210,11 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { } const cells: vscode.NotebookCell[] = []; - for (let range of ranges) { - cells.push(...document.notebookDocument.getCells(extHostTypeConverters.NotebookRange.to(range))); + for (let cellHandle of handles) { + const cell = document.getCell(cellHandle); + if (cell) { + cells.push(cell.cell); + } } try { @@ -223,7 +225,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { } } - async $cancelCells(handle: number, uri: UriComponents, ranges: ICellRange[]): Promise { + async $cancelCells(handle: number, uri: UriComponents, handles: number[]): Promise { const obj = this._kernelData.get(handle); if (!obj) { // extension can dispose kernels in the meantime @@ -238,12 +240,10 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape { } // we do both? interrupt and cancellation or should we be selective? - for (const range of ranges) { - for (let i = range.start; i < range.end; i++) { - const cell = document.getCellFromIndex(i); - if (cell) { - this._extHostNotebook.cancelOneNotebookCellExecution(cell); - } + for (let cellHandle of handles) { + const cell = document.getCell(cellHandle); + if (cell) { + this._extHostNotebook.cancelOneNotebookCellExecution(cell); } } } diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 8dd364d65cd..86271f2dcfc 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3101,7 +3101,8 @@ export class NotebookCellData { } static isNotebookCellData(value: unknown): value is vscode.NotebookCellData { - return value instanceof NotebookCellData; + // return value instanceof NotebookCellData; + return true; } kind: NotebookCellKind; diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts index 45ed6a12b41..d3e8ae0afe5 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts @@ -31,6 +31,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions'; import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { Iterable } from 'vs/base/common/iterator'; // Notebook Commands const EXECUTE_NOTEBOOK_COMMAND_ID = 'notebook.execute'; @@ -427,7 +428,7 @@ registerAction2(class CancelExecuteCell extends NotebookCellAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { - return context.notebookEditor.cancelNotebookCellExecution(context.cell); + return context.notebookEditor.cancelNotebookCells(Iterable.single(context.cell)); } }); @@ -569,7 +570,7 @@ registerAction2(class extends NotebookAction { group?.pinEditor(editor.editor); } - return context.notebookEditor.executeNotebook(); + return context.notebookEditor.executeNotebookCells(); } }); @@ -611,7 +612,7 @@ registerAction2(class CancelNotebook extends NotebookAction { } async runWithContext(accessor: ServicesAccessor, context: INotebookActionContext): Promise { - return context.notebookEditor.cancelNotebookExecution(); + return context.notebookEditor.cancelNotebookCells(); } }); @@ -695,7 +696,7 @@ async function runCell(accessor: ServicesAccessor, context: INotebookCellActionC context.notebookEditor.focusNotebookCell(context.cell, 'container'); return; } else { - return context.notebookEditor.executeNotebookCell(context.cell); + return context.notebookEditor.executeNotebookCells(Iterable.single(context.cell)); } } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 6980ce5bf33..204449f9e72 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -453,24 +453,14 @@ export interface INotebookEditor extends ICommonNotebookEditor { readonly activeKernel: INotebookKernel | undefined; /** - * Execute the given notebook cell + * Execute the given notebook cells */ - executeNotebookCell(cell: ICellViewModel): Promise; + executeNotebookCells(cells?: Iterable): Promise /** - * Cancel the cell execution + * Cancel the given notebook cells */ - cancelNotebookCellExecution(cell: ICellViewModel): void; - - /** - * Executes all notebook cells in order - */ - executeNotebook(): Promise; - - /** - * Cancel the notebook execution - */ - cancelNotebookExecution(): void; + cancelNotebookCells(cells?: Iterable): Promise /** * Get current active cell diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorKernelManager.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorKernelManager.ts index fbab10d46c8..6f33a760505 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorKernelManager.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorKernelManager.ts @@ -4,114 +4,60 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable } from 'vs/base/common/lifecycle'; -import { ICellViewModel, getRanges } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { cellIndexesToRanges, CellKind, INotebookKernel, NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellKind, INotebookKernel, INotebookTextModel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { ICommandService } from 'vs/platform/commands/common/commands'; - - -export interface IKernelManagerDelegate { - activeKernel: INotebookKernel | undefined; - viewModel: NotebookViewModel | undefined; -} +import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; export class NotebookEditorKernelManager extends Disposable { constructor( - private readonly _delegate: IKernelManagerDelegate, @ICommandService private readonly _commandService: ICommandService, + @INotebookKernelService private readonly _notebookKernelService: INotebookKernelService, ) { super(); } - private async _ensureActiveKernel(): Promise { - if (!this._delegate.activeKernel) { + getActiveKernel(notebook: INotebookTextModel): INotebookKernel | undefined { + return this._notebookKernelService.getBoundKernel(notebook) ?? this._notebookKernelService.getMatchingKernels(notebook)[0]; + } + + async executeNotebookCells(notebook: INotebookTextModel, cells: Iterable): Promise { + if (!notebook.metadata.trusted) { + return; + } + + let kernel = this.getActiveKernel(notebook); + if (!kernel) { await this._commandService.executeCommand('notebook.selectKernel'); + kernel = this.getActiveKernel(notebook); + } + + if (!kernel) { + return; + } + + const cellHandles: number[] = []; + for (const cell of cells) { + if (cell.cellKind !== CellKind.Code) { + continue; + } + if (!kernel.supportedLanguages.includes(cell.language)) { + continue; + } + cellHandles.push(cell.handle); + } + + if (cellHandles.length > 0) { + this._notebookKernelService.updateNotebookKernelBinding(notebook, kernel); + await kernel.executeNotebookCellsRequest(notebook.uri, cellHandles); } } - async cancelNotebookExecution(): Promise { - if (!this._delegate.viewModel) { - return; + async cancelNotebookCells(notebook: INotebookTextModel, cells: Iterable): Promise { + let kernel = this._notebookKernelService.getBoundKernel(notebook); + if (kernel) { + await kernel.cancelNotebookCellExecution(notebook.uri, Array.from(cells, cell => cell.handle)); } - await this._ensureActiveKernel(); - await this._delegate.activeKernel?.cancelNotebookCellExecution!(this._delegate.viewModel.uri, [{ start: 0, end: this._delegate.viewModel.length }]); - } - - async executeNotebook(): Promise { - if (!this._delegate.viewModel) { - return; - } - await this._ensureActiveKernel(); - if (!this.canExecuteNotebook()) { - return; - } - const codeCellRanges = getRanges(this._delegate.viewModel.viewCells, cell => this.canExecuteCell(cell)); - if (codeCellRanges.length > 0) { - await this._delegate.activeKernel?.executeNotebookCellsRequest(this._delegate.viewModel.uri, codeCellRanges); - } - } - - async cancelNotebookCellExecution(cell: ICellViewModel): Promise { - if (!this._delegate.viewModel) { - return; - } - - if (cell.cellKind !== CellKind.Code) { - return; - } - - const metadata = cell.getEvaluatedMetadata(this._delegate.viewModel.metadata); - if (metadata.runState === NotebookCellExecutionState.Idle) { - return; - } - - await this._ensureActiveKernel(); - - const idx = this._delegate.viewModel.getCellIndex(cell); - const ranges = cellIndexesToRanges([idx]); - await this._delegate.activeKernel?.cancelNotebookCellExecution!(this._delegate.viewModel.uri, ranges); - } - - async executeNotebookCell(cell: ICellViewModel): Promise { - if (!this._delegate.viewModel) { - return; - } - await this._ensureActiveKernel(); - if (!this.canExecuteCell(cell)) { - throw new Error('Cell is not executable: ' + cell.uri); - } - const idx = this._delegate.viewModel.getCellIndex(cell); - const range = cellIndexesToRanges([idx]); - await this._delegate.activeKernel?.executeNotebookCellsRequest(this._delegate.viewModel.uri, range); - } - - private canExecuteNotebook(): boolean { - if (!this._delegate.activeKernel) { - return false; - } - if (!this._delegate.viewModel?.trusted) { - return false; - } - return true; - } - - private canExecuteCell(cell: ICellViewModel): boolean { - if (!this._delegate.viewModel?.trusted) { - return false; - } - if (!this._delegate.activeKernel) { - return false; - } - if (cell.cellKind !== CellKind.Code) { - return false; - } - if (!this._delegate.activeKernel.supportedLanguages) { - return true; - } - if (this._delegate.activeKernel.supportedLanguages.includes(cell.language)) { - return true; - } - return false; } } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 1bf1481762a..61f9490d67a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -46,7 +46,7 @@ import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN 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 } 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 { IKernelManagerDelegate, NotebookEditorKernelManager } from 'vs/workbench/contrib/notebook/browser/notebookEditorKernelManager'; +import { NotebookEditorKernelManager } from 'vs/workbench/contrib/notebook/browser/notebookEditorKernelManager'; import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService'; import { errorStateIcon, successStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList'; @@ -312,7 +312,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor @IStorageService storageService: IStorageService, @IAccessibilityService accessibilityService: IAccessibilityService, @INotebookEditorService private readonly notebookEditorService: INotebookEditorService, - @INotebookKernelService private readonly notebookKernelService: INotebookKernelService, + @INotebookKernelService notebookKernelService: INotebookKernelService, @IEditorService private readonly editorService: IEditorService, @IConfigurationService private readonly configurationService: IConfigurationService, @IContextKeyService contextKeyService: IContextKeyService, @@ -336,11 +336,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this._register(instantiationService.createInstance(NotebookEditorContextKeys, this)); - const that = this; - this._kernelManger = instantiationService.createInstance(NotebookEditorKernelManager, { - get viewModel() { return that.viewModel; }, - get activeKernel() { return that.activeKernel; } - }); + this._kernelManger = instantiationService.createInstance(NotebookEditorKernelManager); this._register(notebookKernelService.onDidChangeNotebookKernelBinding(e => { if (isEqual(e.notebook, this.viewModel?.uri)) { this._loadKernelPreloads(); @@ -1668,33 +1664,27 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor } get activeKernel() { - if (!this.viewModel) { - return undefined; - } - let boundKernel = this.notebookKernelService.getBoundKernel(this.viewModel.notebookDocument); - if (boundKernel) { - return boundKernel; - } - return this.notebookKernelService.getMatchingKernels(this.viewModel.notebookDocument)[0]; + return this.viewModel && this._kernelManger.getActiveKernel(this.viewModel.notebookDocument); } - async cancelNotebookExecution(): Promise { - return this._kernelManger.cancelNotebookExecution(); - } - - async executeNotebook(): Promise { - return this._kernelManger.executeNotebook(); - } - - async cancelNotebookCellExecution(cell: ICellViewModel): Promise { - return this._kernelManger.cancelNotebookCellExecution(cell); - } - - async executeNotebookCell(cell: ICellViewModel): Promise { - if (!this.viewModel) { + async cancelNotebookCells(cells?: Iterable): Promise { + if (!this.hasModel()) { return; } - return this._kernelManger.executeNotebookCell(cell); + if (!cells) { + cells = this.viewModel.viewCells; + } + return this._kernelManger.cancelNotebookCells(this.viewModel.notebookDocument, cells); + } + + async executeNotebookCells(cells?: Iterable): Promise { + if (!this.hasModel()) { + return; + } + if (!cells) { + cells = this.viewModel.viewCells; + } + return this._kernelManger.executeNotebookCells(this.viewModel.notebookDocument, cells); } //#endregion diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 5078796b945..5675dbff036 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -789,12 +789,12 @@ export interface INotebookKernel { description?: string; detail?: string; isPreferred?: boolean; - supportedLanguages?: string[] + supportedLanguages: string[] implementsInterrupt?: boolean; implementsExecutionOrder?: boolean; - executeNotebookCellsRequest(uri: URI, ranges: ICellRange[]): Promise; - cancelNotebookCellExecution(uri: URI, ranges: ICellRange[]): Promise; + executeNotebookCellsRequest(uri: URI, cellHandles: number[]): Promise; + cancelNotebookCellExecution(uri: URI, cellHandles: number[]): Promise; } export interface INotebookCellStatusBarItemProvider { diff --git a/src/vs/workbench/contrib/notebook/test/notebookEditorKernelManager.test.ts b/src/vs/workbench/contrib/notebook/test/notebookEditorKernelManager.test.ts index bef81f6b33a..77ce161a014 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookEditorKernelManager.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookEditorKernelManager.test.ts @@ -7,25 +7,22 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; import { URI } from 'vs/base/common/uri'; import { assertThrowsAsync } from 'vs/base/test/common/utils'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; -import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; -import { IStorageService } from 'vs/platform/storage/common/storage'; import { NotebookEditorKernelManager } from 'vs/workbench/contrib/notebook/browser/notebookEditorKernelManager'; import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; -import { CellKind, ICellRange, INotebookKernel, IOutputDto, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, INotebookKernel, IOutputDto, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { setupInstantiationService, withTestNotebook as _withTestNotebook } from 'vs/workbench/contrib/notebook/test/testNotebookEditor'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; -import { TestQuickInputService } from 'vs/workbench/test/browser/workbenchTestServices'; import { Event } from 'vs/base/common/event'; +import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { NotebookKernelService } from 'vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl'; +import { NullLogService } from 'vs/platform/log/common/log'; suite('NotebookEditorKernelManager', () => { const instantiationService = setupInstantiationService(); - instantiationService.stub(IStorageService, new TestStorageService()); - instantiationService.stub(IContextKeyService, new MockContextKeyService()); - instantiationService.stub(IQuickInputService, new TestQuickInputService()); + const kernelService = new NotebookKernelService(new TestStorageService(), new NullLogService()); + instantiationService.set(INotebookKernelService, kernelService); async function withTestNotebook(cells: [string, string, CellKind, IOutputDto[], NotebookCellMetadata][], callback: (viewModel: NotebookViewModel, textModel: NotebookTextModel) => void | Promise) { return _withTestNotebook(cells, (editor) => callback(editor.viewModel, editor.viewModel.notebookDocument)); @@ -53,13 +50,12 @@ suite('NotebookEditorKernelManager', () => { await withTestNotebook( [], async (viewModel) => { - const kernelManager = instantiationService.createInstance(NotebookEditorKernelManager, { - activeKernel: new TestNotebookKernel({ languages: ['testlang'] }), - viewModel - }); + const d = kernelService.registerKernel(new TestNotebookKernel({ languages: ['testlang'] })); + const kernelManager = instantiationService.createInstance(NotebookEditorKernelManager); const cell = viewModel.createCell(1, 'var c = 3', 'javascript', CellKind.Code, {}, [], true); await assertThrowsAsync(async () => await kernelManager.executeNotebookCell(cell)); + d.dispose(); }); }); @@ -68,16 +64,15 @@ suite('NotebookEditorKernelManager', () => { [], async (viewModel) => { const kernel = new TestNotebookKernel({ languages: ['javascript'] }); - const kernelManager: NotebookEditorKernelManager = instantiationService.createInstance(NotebookEditorKernelManager, { - activeKernel: kernel, - viewModel - }); + const d = kernelService.registerKernel(kernel); + const kernelManager = instantiationService.createInstance(NotebookEditorKernelManager); const executeSpy = sinon.spy(); kernel.executeNotebookCellsRequest = executeSpy; const cell = viewModel.createCell(0, 'var c = 3', 'javascript', CellKind.Code, {}, [], true); - await kernelManager.executeNotebookCell(cell); + await kernelManager.executeNotebookCells(viewModel.notebookDocument, [cell]); assert.strictEqual(executeSpy.calledOnce, true); + d.dispose(); }); }); }); @@ -94,15 +89,15 @@ class TestNotebookKernel implements INotebookKernel { isPreferred?: boolean | undefined; preloadUris: URI[] = []; preloadProvides: string[] = []; - supportedLanguages?: string[] | undefined; - executeNotebookCellsRequest(uri: URI, ranges: ICellRange[]): Promise { + supportedLanguages: string[] = []; + executeNotebookCellsRequest(): Promise { throw new Error('Method not implemented.'); } cancelNotebookCellExecution(): Promise { throw new Error('Method not implemented.'); } - constructor(opts?: { languages?: string[] }) { - this.supportedLanguages = opts?.languages; + constructor(opts?: { languages: string[] }) { + this.supportedLanguages = opts?.languages ?? ['text/plain']; } }