execute by cell-handle, kernel manager has only execute/cancel cells, also "fix" isNotebookCellData fyi @rebornix

This commit is contained in:
Johannes Rieken
2021-04-20 14:39:19 +02:00
parent 0b46219a2d
commit b2b45e1005
11 changed files with 114 additions and 191 deletions
@@ -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<void>;
abstract cancelNotebookCellExecution(uri: URI, ranges: ICellRange[]): Promise<void>;
abstract executeNotebookCellsRequest(uri: URI, cellHandles: number[]): Promise<void>;
abstract cancelNotebookCellExecution(uri: URI, cellHandles: number[]): Promise<void>;
}
@extHostNamedCustomer(MainContext.MainThreadNotebookKernels)
@@ -186,11 +186,11 @@ export class MainThreadNotebookKernels implements MainThreadNotebookKernelsShape
async $addKernel(handle: number, data: INotebookKernelDto2): Promise<void> {
const that = this;
const kernel = new class extends MainThreadKernel {
async executeNotebookCellsRequest(uri: URI, ranges: ICellRange[]): Promise<void> {
await that._proxy.$executeCells(handle, uri, ranges);
async executeNotebookCellsRequest(uri: URI, handles: number[]): Promise<void> {
await that._proxy.$executeCells(handle, uri, handles);
}
async cancelNotebookCellExecution(uri: URI, ranges: ICellRange[]): Promise<void> {
await that._proxy.$cancelCells(handle, uri, ranges);
async cancelNotebookCellExecution(uri: URI, handles: number[]): Promise<void> {
await that._proxy.$cancelCells(handle, uri, handles);
}
}(data);
const registration = this._notebookKernelService.registerKernel(kernel);
@@ -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<void>;
$cancelCells(handle: number, uri: UriComponents, ranges: ICellRange[]): Promise<void>;
$executeCells(handle: number, uri: UriComponents, handles: number[]): Promise<void>;
$cancelCells(handle: number, uri: UriComponents, handles: number[]): Promise<void>;
$acceptRendererMessage(handle: number, editorId: string, message: any): void;
}
@@ -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);
@@ -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<void> {
async $executeCells(handle: number, uri: UriComponents, handles: number[]): Promise<void> {
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<void> {
async $cancelCells(handle: number, uri: UriComponents, handles: number[]): Promise<void> {
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);
}
}
}
+2 -1
View File
@@ -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;
@@ -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<ICellRange> {
}
async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
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<void> {
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));
}
}
@@ -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<void>;
executeNotebookCells(cells?: Iterable<ICellViewModel>): Promise<void>
/**
* Cancel the cell execution
* Cancel the given notebook cells
*/
cancelNotebookCellExecution(cell: ICellViewModel): void;
/**
* Executes all notebook cells in order
*/
executeNotebook(): Promise<void>;
/**
* Cancel the notebook execution
*/
cancelNotebookExecution(): void;
cancelNotebookCells(cells?: Iterable<ICellViewModel>): Promise<void>
/**
* Get current active cell
@@ -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<void> {
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<ICellViewModel>): Promise<void> {
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<void> {
if (!this._delegate.viewModel) {
return;
async cancelNotebookCells(notebook: INotebookTextModel, cells: Iterable<ICellViewModel>): Promise<void> {
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<void> {
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<void> {
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<void> {
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;
}
}
@@ -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, <IKernelManagerDelegate>{
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<void> {
return this._kernelManger.cancelNotebookExecution();
}
async executeNotebook(): Promise<void> {
return this._kernelManger.executeNotebook();
}
async cancelNotebookCellExecution(cell: ICellViewModel): Promise<void> {
return this._kernelManger.cancelNotebookCellExecution(cell);
}
async executeNotebookCell(cell: ICellViewModel): Promise<void> {
if (!this.viewModel) {
async cancelNotebookCells(cells?: Iterable<ICellViewModel>): Promise<void> {
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<ICellViewModel>): Promise<void> {
if (!this.hasModel()) {
return;
}
if (!cells) {
cells = this.viewModel.viewCells;
}
return this._kernelManger.executeNotebookCells(this.viewModel.notebookDocument, cells);
}
//#endregion
@@ -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<void>;
cancelNotebookCellExecution(uri: URI, ranges: ICellRange[]): Promise<void>;
executeNotebookCellsRequest(uri: URI, cellHandles: number[]): Promise<void>;
cancelNotebookCellExecution(uri: URI, cellHandles: number[]): Promise<void>;
}
export interface INotebookCellStatusBarItemProvider {
@@ -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<void>) {
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<void> {
supportedLanguages: string[] = [];
executeNotebookCellsRequest(): Promise<void> {
throw new Error('Method not implemented.');
}
cancelNotebookCellExecution(): Promise<void> {
throw new Error('Method not implemented.');
}
constructor(opts?: { languages?: string[] }) {
this.supportedLanguages = opts?.languages;
constructor(opts?: { languages: string[] }) {
this.supportedLanguages = opts?.languages ?? ['text/plain'];
}
}