Merge pull request #117069 from microsoft/roblou/refactorKernel
Move kernel/execution code out of NotebookEditorWidget for testability
This commit is contained in:
commit
c159b34535
|
@ -48,12 +48,6 @@ async function saveAllFilesAndCloseAll(resource: vscode.Uri | undefined) {
|
|||
await documentClosed;
|
||||
}
|
||||
|
||||
async function updateCellMetadata(uri: vscode.Uri, cell: vscode.NotebookCell, newMetadata: vscode.NotebookCellMetadata) {
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCellMetadata(uri, cell.index, newMetadata);
|
||||
await vscode.workspace.applyEdit(edit);
|
||||
}
|
||||
|
||||
async function updateNotebookMetadata(uri: vscode.Uri, newMetadata: vscode.NotebookDocumentMetadata) {
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookMetadata(uri, newMetadata);
|
||||
|
@ -489,7 +483,7 @@ suite('Notebook API tests', function () {
|
|||
const version = vscode.window.activeNotebookEditor!.document.version;
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
editBuilder.replaceCells(1, 0, [{ cellKind: vscode.NotebookCellKind.Code, language: 'javascript', source: 'test 2', outputs: [], metadata: undefined }]);
|
||||
editBuilder.replaceCellMetadata(0, new vscode.NotebookCellMetadata().with({ runnable: false }));
|
||||
editBuilder.replaceCellMetadata(0, new vscode.NotebookCellMetadata().with({ breakpointMargin: false }));
|
||||
});
|
||||
|
||||
await cellsChangeEvent;
|
||||
|
@ -507,18 +501,18 @@ suite('Notebook API tests', function () {
|
|||
const version = vscode.window.activeNotebookEditor!.document.version;
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
editBuilder.replaceCells(1, 0, [{ cellKind: vscode.NotebookCellKind.Code, language: 'javascript', source: 'test 2', outputs: [], metadata: undefined }]);
|
||||
editBuilder.replaceCellMetadata(0, new vscode.NotebookCellMetadata().with({ runnable: false }));
|
||||
editBuilder.replaceCellMetadata(0, new vscode.NotebookCellMetadata().with({ breakpointMargin: false }));
|
||||
});
|
||||
|
||||
await cellsChangeEvent;
|
||||
await cellMetadataChangeEvent;
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cells.length, 3);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cells[0]?.metadata?.runnable, false);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cells[0]?.metadata?.breakpointMargin, false);
|
||||
assert.strictEqual(version + 1, vscode.window.activeNotebookEditor!.document.version);
|
||||
|
||||
await vscode.commands.executeCommand('undo');
|
||||
assert.strictEqual(version + 2, vscode.window.activeNotebookEditor!.document.version);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cells[0]?.metadata?.runnable, undefined);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cells[0]?.metadata?.breakpointMargin, undefined);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cells.length, 2);
|
||||
|
||||
await saveAllFilesAndCloseAll(resource);
|
||||
|
@ -686,35 +680,6 @@ suite('Notebook API tests', function () {
|
|||
await saveFileAndCloseAll(resource);
|
||||
});
|
||||
|
||||
|
||||
test('cell runnable metadata is respected', async () => {
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
|
||||
await vscode.commands.executeCommand('notebook.focusTop');
|
||||
const cell = editor.document.cells[0];
|
||||
assert.strictEqual(cell.outputs.length, 0);
|
||||
|
||||
let metadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
await updateCellMetadata(resource, cell, cell.metadata.with({ runnable: false }));
|
||||
await metadataChangeEvent;
|
||||
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
assert.strictEqual(cell.outputs.length, 0, 'should not execute'); // not runnable, didn't work
|
||||
|
||||
metadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebook.onDidChangeCellMetadata);
|
||||
await updateCellMetadata(resource, cell, cell.metadata.with({ runnable: true }));
|
||||
await metadataChangeEvent;
|
||||
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
|
||||
await vscode.commands.executeCommand('workbench.action.files.save');
|
||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||
});
|
||||
|
||||
test('document runnable metadata is respected', async () => {
|
||||
const resource = await createRandomFile('', undefined, '.vsctestnb');
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
|
|
@ -28,3 +28,14 @@ export function testRepeat(n: number, description: string, callback: (this: any)
|
|||
test(`${description} (iteration ${i})`, callback);
|
||||
}
|
||||
}
|
||||
|
||||
export async function assertThrowsAsync(block: () => any, message: string | Error = 'Missing expected exception'): Promise<void> {
|
||||
try {
|
||||
await block();
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const err = message instanceof Error ? message : new Error(message);
|
||||
throw err;
|
||||
}
|
||||
|
|
|
@ -142,6 +142,7 @@ export class MenuId {
|
|||
static readonly NotebookCellInsert = new MenuId('NotebookCellInsert');
|
||||
static readonly NotebookCellBetween = new MenuId('NotebookCellBetween');
|
||||
static readonly NotebookCellListTop = new MenuId('NotebookCellTop');
|
||||
static readonly NotebookCellExecute = new MenuId('NotebookCellExecute');
|
||||
static readonly NotebookDiffCellInputTitle = new MenuId('NotebookDiffCellInputTitle');
|
||||
static readonly NotebookDiffCellMetadataTitle = new MenuId('NotebookDiffCellMetadataTitle');
|
||||
static readonly NotebookDiffCellOutputsTitle = new MenuId('NotebookDiffCellOutputsTitle');
|
||||
|
|
65
src/vs/platform/quickinput/test/testQuickInputService.ts
Normal file
65
src/vs/platform/quickinput/test/testQuickInputService.ts
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import * as Types from 'vs/base/common/types';
|
||||
import { IInputBox, IInputOptions, IPickOptions, IQuickInputButton, IQuickInputService, IQuickNavigateConfiguration, IQuickPick, IQuickPickItem, Omit, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
|
||||
|
||||
export class TestQuickInputService implements IQuickInputService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
readonly onShow = Event.None;
|
||||
readonly onHide = Event.None;
|
||||
|
||||
readonly quickAccess = undefined!;
|
||||
|
||||
public pick<T extends IQuickPickItem>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: true }, token?: CancellationToken): Promise<T[]>;
|
||||
public pick<T extends IQuickPickItem>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: false }, token?: CancellationToken): Promise<T>;
|
||||
public pick<T extends IQuickPickItem>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: Omit<IPickOptions<T>, 'canPickMany'>, token?: CancellationToken): Promise<T | undefined> {
|
||||
if (Types.isArray(picks)) {
|
||||
return Promise.resolve(<any>{ label: 'selectedPick', description: 'pick description', value: 'selectedPick' });
|
||||
} else {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
public input(options?: IInputOptions, token?: CancellationToken): Promise<string> {
|
||||
return Promise.resolve(options ? 'resolved' + options.prompt : 'resolved');
|
||||
}
|
||||
|
||||
backButton!: IQuickInputButton;
|
||||
|
||||
createQuickPick<T extends IQuickPickItem>(): IQuickPick<T> {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
createInputBox(): IInputBox {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
toggle(): void {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
navigate(next: boolean, quickNavigate?: IQuickNavigateConfiguration): void {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
accept(): Promise<void> {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
back(): Promise<void> {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
cancel(): Promise<void> {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
}
|
8
src/vs/vscode.proposed.d.ts
vendored
8
src/vs/vscode.proposed.d.ts
vendored
|
@ -1118,16 +1118,15 @@ declare module 'vscode' {
|
|||
readonly statusMessage?: string;
|
||||
|
||||
// run related API, will be removed
|
||||
readonly runnable?: boolean;
|
||||
readonly hasExecutionOrder?: boolean;
|
||||
readonly executionOrder?: number;
|
||||
readonly runState?: NotebookCellRunState;
|
||||
readonly runStartTime?: number;
|
||||
readonly lastRunDuration?: number;
|
||||
|
||||
constructor(editable?: boolean, breakpointMargin?: boolean, runnable?: boolean, hasExecutionOrder?: boolean, executionOrder?: number, runState?: NotebookCellRunState, runStartTime?: number, statusMessage?: string, lastRunDuration?: number, inputCollapsed?: boolean, outputCollapsed?: boolean, custom?: Record<string, any>)
|
||||
constructor(editable?: boolean, breakpointMargin?: boolean, hasExecutionOrder?: boolean, executionOrder?: number, runState?: NotebookCellRunState, runStartTime?: number, statusMessage?: string, lastRunDuration?: number, inputCollapsed?: boolean, outputCollapsed?: boolean, custom?: Record<string, any>)
|
||||
|
||||
with(change: { editable?: boolean | null, breakpointMargin?: boolean | null, runnable?: boolean | null, hasExecutionOrder?: boolean | null, executionOrder?: number | null, runState?: NotebookCellRunState | null, runStartTime?: number | null, statusMessage?: string | null, lastRunDuration?: number | null, inputCollapsed?: boolean | null, outputCollapsed?: boolean | null, custom?: Record<string, any> | null, }): NotebookCellMetadata;
|
||||
with(change: { editable?: boolean | null, breakpointMargin?: boolean | null, hasExecutionOrder?: boolean | null, executionOrder?: number | null, runState?: NotebookCellRunState | null, runStartTime?: number | null, statusMessage?: string | null, lastRunDuration?: number | null, inputCollapsed?: boolean | null, outputCollapsed?: boolean | null, custom?: Record<string, any> | null, }): NotebookCellMetadata;
|
||||
}
|
||||
|
||||
// todo@API support ids https://github.com/jupyter/enhancement-proposals/blob/master/62-cell-id/cell-id.md
|
||||
|
@ -1174,10 +1173,9 @@ declare module 'vscode' {
|
|||
// todo@API infer from kernel
|
||||
// todo@API remove
|
||||
readonly runnable: boolean;
|
||||
readonly cellRunnable: boolean;
|
||||
readonly runState: NotebookRunState;
|
||||
|
||||
constructor(editable?: boolean, runnable?: boolean, cellEditable?: boolean, cellRunnable?: boolean, cellHasExecutionOrder?: boolean, displayOrder?: GlobPattern[], custom?: { [key: string]: any; }, runState?: NotebookRunState, trusted?: boolean);
|
||||
constructor(editable?: boolean, runnable?: boolean, cellEditable?: boolean, cellHasExecutionOrder?: boolean, displayOrder?: GlobPattern[], custom?: { [key: string]: any; }, runState?: NotebookRunState, trusted?: boolean);
|
||||
|
||||
with(change: { editable?: boolean | null, runnable?: boolean | null, cellEditable?: boolean | null, cellRunnable?: boolean | null, cellHasExecutionOrder?: boolean | null, displayOrder?: GlobPattern[] | null, custom?: { [key: string]: any; } | null, runState?: NotebookRunState | null, trusted?: boolean | null, }): NotebookDocumentMetadata
|
||||
}
|
||||
|
|
|
@ -1419,7 +1419,7 @@ export namespace NotebookCellRange {
|
|||
export namespace NotebookCellMetadata {
|
||||
|
||||
export function to(data: notebooks.NotebookCellMetadata): types.NotebookCellMetadata {
|
||||
return new types.NotebookCellMetadata(data.editable, data.breakpointMargin, data.runnable, data.hasExecutionOrder, data.executionOrder, data.runState, data.runStartTime, data.statusMessage, data.lastRunDuration, data.inputCollapsed, data.outputCollapsed, data.custom);
|
||||
return new types.NotebookCellMetadata(data.editable, data.breakpointMargin, data.hasExecutionOrder, data.executionOrder, data.runState, data.runStartTime, data.statusMessage, data.lastRunDuration, data.inputCollapsed, data.outputCollapsed, data.custom);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1430,7 +1430,7 @@ export namespace NotebookDocumentMetadata {
|
|||
}
|
||||
|
||||
export function to(data: notebooks.NotebookDocumentMetadata): types.NotebookDocumentMetadata {
|
||||
return new types.NotebookDocumentMetadata(data.editable, data.runnable, data.cellEditable, data.cellRunnable, data.cellHasExecutionOrder, data.displayOrder, data.custom, data.runState, data.trusted);
|
||||
return new types.NotebookDocumentMetadata(data.editable, data.runnable, data.cellEditable, data.cellHasExecutionOrder, data.displayOrder, data.custom, data.runState, data.trusted);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2924,7 +2924,6 @@ export class NotebookCellMetadata {
|
|||
constructor(
|
||||
readonly editable?: boolean,
|
||||
readonly breakpointMargin?: boolean,
|
||||
readonly runnable?: boolean,
|
||||
readonly hasExecutionOrder?: boolean,
|
||||
readonly executionOrder?: number,
|
||||
readonly runState?: NotebookCellRunState,
|
||||
|
@ -2939,7 +2938,6 @@ export class NotebookCellMetadata {
|
|||
with(change: {
|
||||
editable?: boolean | null,
|
||||
breakpointMargin?: boolean | null,
|
||||
runnable?: boolean | null,
|
||||
hasExecutionOrder?: boolean | null,
|
||||
executionOrder?: number | null,
|
||||
runState?: NotebookCellRunState | null,
|
||||
|
@ -2951,7 +2949,7 @@ export class NotebookCellMetadata {
|
|||
custom?: Record<string, any> | null,
|
||||
}): NotebookCellMetadata {
|
||||
|
||||
let { editable, breakpointMargin, runnable, hasExecutionOrder, executionOrder, runState, runStartTime, statusMessage, lastRunDuration, inputCollapsed, outputCollapsed, custom } = change;
|
||||
let { editable, breakpointMargin, hasExecutionOrder, executionOrder, runState, runStartTime, statusMessage, lastRunDuration, inputCollapsed, outputCollapsed, custom } = change;
|
||||
|
||||
if (editable === undefined) {
|
||||
editable = this.editable;
|
||||
|
@ -2963,11 +2961,6 @@ export class NotebookCellMetadata {
|
|||
} else if (breakpointMargin === null) {
|
||||
breakpointMargin = undefined;
|
||||
}
|
||||
if (runnable === undefined) {
|
||||
runnable = this.runnable;
|
||||
} else if (runnable === null) {
|
||||
runnable = undefined;
|
||||
}
|
||||
if (hasExecutionOrder === undefined) {
|
||||
hasExecutionOrder = this.hasExecutionOrder;
|
||||
} else if (hasExecutionOrder === null) {
|
||||
|
@ -3016,7 +3009,6 @@ export class NotebookCellMetadata {
|
|||
|
||||
if (editable === this.editable &&
|
||||
breakpointMargin === this.breakpointMargin &&
|
||||
runnable === this.runnable &&
|
||||
hasExecutionOrder === this.hasExecutionOrder &&
|
||||
executionOrder === this.executionOrder &&
|
||||
runState === this.runState &&
|
||||
|
@ -3033,7 +3025,6 @@ export class NotebookCellMetadata {
|
|||
return new NotebookCellMetadata(
|
||||
editable,
|
||||
breakpointMargin,
|
||||
runnable,
|
||||
hasExecutionOrder,
|
||||
executionOrder,
|
||||
runState,
|
||||
|
@ -3053,7 +3044,6 @@ export class NotebookDocumentMetadata {
|
|||
readonly editable: boolean = true,
|
||||
readonly runnable: boolean = true,
|
||||
readonly cellEditable: boolean = true,
|
||||
readonly cellRunnable: boolean = true,
|
||||
readonly cellHasExecutionOrder: boolean = true,
|
||||
readonly displayOrder: vscode.GlobPattern[] = NOTEBOOK_DISPLAY_ORDER,
|
||||
readonly custom: { [key: string]: any; } = {},
|
||||
|
@ -3065,7 +3055,6 @@ export class NotebookDocumentMetadata {
|
|||
editable?: boolean | null,
|
||||
runnable?: boolean | null,
|
||||
cellEditable?: boolean | null,
|
||||
cellRunnable?: boolean | null,
|
||||
cellHasExecutionOrder?: boolean | null,
|
||||
displayOrder?: vscode.GlobPattern[] | null,
|
||||
custom?: { [key: string]: any; } | null,
|
||||
|
@ -3073,7 +3062,7 @@ export class NotebookDocumentMetadata {
|
|||
trusted?: boolean | null,
|
||||
}): NotebookDocumentMetadata {
|
||||
|
||||
let { editable, runnable, cellEditable, cellRunnable, cellHasExecutionOrder, displayOrder, custom, runState, trusted } = change;
|
||||
let { editable, runnable, cellEditable, cellHasExecutionOrder, displayOrder, custom, runState, trusted } = change;
|
||||
|
||||
if (editable === undefined) {
|
||||
editable = this.editable;
|
||||
|
@ -3090,11 +3079,6 @@ export class NotebookDocumentMetadata {
|
|||
} else if (cellEditable === null) {
|
||||
cellEditable = undefined;
|
||||
}
|
||||
if (cellRunnable === undefined) {
|
||||
cellRunnable = this.cellRunnable;
|
||||
} else if (cellRunnable === null) {
|
||||
cellRunnable = undefined;
|
||||
}
|
||||
if (cellHasExecutionOrder === undefined) {
|
||||
cellHasExecutionOrder = this.cellHasExecutionOrder;
|
||||
} else if (cellHasExecutionOrder === null) {
|
||||
|
@ -3124,7 +3108,6 @@ export class NotebookDocumentMetadata {
|
|||
if (editable === this.editable &&
|
||||
runnable === this.runnable &&
|
||||
cellEditable === this.cellEditable &&
|
||||
cellRunnable === this.cellRunnable &&
|
||||
cellHasExecutionOrder === this.cellHasExecutionOrder &&
|
||||
displayOrder === this.displayOrder &&
|
||||
custom === this.custom &&
|
||||
|
@ -3139,7 +3122,6 @@ export class NotebookDocumentMetadata {
|
|||
editable,
|
||||
runnable,
|
||||
cellEditable,
|
||||
cellRunnable,
|
||||
cellHasExecutionOrder,
|
||||
displayOrder,
|
||||
custom,
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as glob from 'vs/base/common/glob';
|
||||
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
|
@ -20,20 +22,18 @@ import { InputFocusedContext, InputFocusedContextKey } from 'vs/platform/context
|
|||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { CATEGORIES } from 'vs/workbench/common/actions';
|
||||
import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, IActiveNotebookEditor, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { EditorsOrder } from 'vs/workbench/common/editor';
|
||||
import { BaseCellRenderTemplate, CellEditState, CellFocusMode, EXECUTE_CELL_COMMAND_ID, EXPAND_CELL_CONTENT_COMMAND_ID, IActiveNotebookEditor, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_RUN_STATE, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
|
||||
import { INotebookEditorWidgetService } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidgetService';
|
||||
import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { CellEditType, CellKind, ICellEditOperation, ICellRange, INotebookDocumentFilter, isDocumentExcludePattern, NotebookCellMetadata, NotebookCellRunState, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
|
||||
import { EditorsOrder } from 'vs/workbench/common/editor';
|
||||
import { INotebookEditorWidgetService } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidgetService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions';
|
||||
|
||||
// Notebook Commands
|
||||
const EXECUTE_NOTEBOOK_COMMAND_ID = 'notebook.execute';
|
||||
|
@ -228,11 +228,17 @@ export function getWidgetFromUri(accessor: ServicesAccessor, uri: URI) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const executeCellCondition = ContextKeyExpr.or(
|
||||
ContextKeyExpr.and(
|
||||
ContextKeyExpr.equals(NOTEBOOK_CELL_RUN_STATE.key, NotebookCellRunState[NotebookCellRunState.Idle]),
|
||||
ContextKeyExpr.greater(NOTEBOOK_KERNEL_COUNT.key, 0)),
|
||||
NOTEBOOK_CELL_TYPE.isEqualTo('markdown'));
|
||||
|
||||
registerAction2(class ExecuteCell extends NotebookCellAction<ICellRange> {
|
||||
constructor() {
|
||||
super({
|
||||
id: EXECUTE_CELL_COMMAND_ID,
|
||||
precondition: ContextKeyExpr.or(ContextKeyExpr.greater(NOTEBOOK_KERNEL_COUNT.key, 0), NOTEBOOK_CELL_TYPE.isEqualTo('markdown')),
|
||||
precondition: executeCellCondition,
|
||||
title: localize('notebookActions.execute', "Execute Cell"),
|
||||
keybinding: {
|
||||
when: NOTEBOOK_CELL_LIST_FOCUSED,
|
||||
|
@ -242,6 +248,11 @@ registerAction2(class ExecuteCell extends NotebookCellAction<ICellRange> {
|
|||
},
|
||||
weight: EDITOR_WIDGET_ACTION_WEIGHT
|
||||
},
|
||||
menu: {
|
||||
id: MenuId.NotebookCellExecute,
|
||||
when: executeCellCondition,
|
||||
group: 'inline'
|
||||
},
|
||||
description: {
|
||||
description: localize('notebookActions.execute', "Execute Cell"),
|
||||
args: [
|
||||
|
@ -325,8 +336,14 @@ registerAction2(class StopExecuteCell extends NotebookCellAction<ICellRange> {
|
|||
constructor() {
|
||||
super({
|
||||
id: CANCEL_CELL_COMMAND_ID,
|
||||
precondition: ContextKeyExpr.equals(NOTEBOOK_CELL_RUN_STATE.key, NotebookCellRunState[NotebookCellRunState.Running]),
|
||||
title: localize('notebookActions.cancel', "Stop Cell Execution"),
|
||||
icon: icons.stopIcon,
|
||||
menu: {
|
||||
id: MenuId.NotebookCellExecute,
|
||||
when: ContextKeyExpr.equals(NOTEBOOK_CELL_RUN_STATE.key, NotebookCellRunState[NotebookCellRunState.Running]),
|
||||
group: 'inline'
|
||||
},
|
||||
description: {
|
||||
description: localize('notebookActions.cancel', "Stop Cell Execution"),
|
||||
args: [
|
||||
|
@ -397,42 +414,6 @@ registerAction2(class StopExecuteCell extends NotebookCellAction<ICellRange> {
|
|||
}
|
||||
});
|
||||
|
||||
export class ExecuteCellAction extends MenuItemAction {
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@ICommandService commandService: ICommandService
|
||||
) {
|
||||
super(
|
||||
{
|
||||
id: EXECUTE_CELL_COMMAND_ID,
|
||||
title: localize('notebookActions.executeCell', "Execute Cell"),
|
||||
icon: icons.executeIcon
|
||||
},
|
||||
undefined,
|
||||
{ shouldForwardArgs: true },
|
||||
contextKeyService,
|
||||
commandService);
|
||||
}
|
||||
}
|
||||
|
||||
export class CancelCellAction extends MenuItemAction {
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@ICommandService commandService: ICommandService
|
||||
) {
|
||||
super(
|
||||
{
|
||||
id: CANCEL_CELL_COMMAND_ID,
|
||||
title: localize('notebookActions.CancelCell', "Cancel Execution"),
|
||||
icon: icons.stopIcon
|
||||
},
|
||||
undefined,
|
||||
{ shouldForwardArgs: true },
|
||||
contextKeyService,
|
||||
commandService);
|
||||
}
|
||||
}
|
||||
|
||||
export class DeleteCellAction extends MenuItemAction {
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
|
@ -455,7 +436,7 @@ registerAction2(class ExecuteCellSelectBelow extends NotebookCellAction {
|
|||
constructor() {
|
||||
super({
|
||||
id: EXECUTE_CELL_SELECT_BELOW,
|
||||
precondition: ContextKeyExpr.or(ContextKeyExpr.greater(NOTEBOOK_KERNEL_COUNT.key, 0), NOTEBOOK_CELL_TYPE.isEqualTo('markdown')),
|
||||
precondition: executeCellCondition,
|
||||
title: localize('notebookActions.executeAndSelectBelow', "Execute Notebook Cell and Select Below"),
|
||||
keybinding: {
|
||||
when: NOTEBOOK_CELL_LIST_FOCUSED,
|
||||
|
@ -492,7 +473,7 @@ registerAction2(class ExecuteCellInsertBelow extends NotebookCellAction {
|
|||
constructor() {
|
||||
super({
|
||||
id: EXECUTE_CELL_INSERT_BELOW,
|
||||
precondition: ContextKeyExpr.or(ContextKeyExpr.greater(NOTEBOOK_KERNEL_COUNT.key, 0), NOTEBOOK_CELL_TYPE.isEqualTo('markdown')),
|
||||
precondition: executeCellCondition,
|
||||
title: localize('notebookActions.executeAndInsertBelow', "Execute Notebook Cell and Insert Below"),
|
||||
keybinding: {
|
||||
when: NOTEBOOK_CELL_LIST_FOCUSED,
|
||||
|
@ -1261,7 +1242,6 @@ registerAction2(class extends NotebookAction {
|
|||
outputs: cell.outputs,
|
||||
metadata: {
|
||||
editable: cell.metadata?.editable,
|
||||
runnable: cell.metadata?.runnable,
|
||||
breakpointMargin: cell.metadata?.breakpointMargin,
|
||||
hasExecutionOrder: cell.metadata?.hasExecutionOrder,
|
||||
inputCollapsed: cell.metadata?.inputCollapsed,
|
||||
|
@ -1319,7 +1299,6 @@ registerAction2(class extends NotebookCellAction {
|
|||
outputs: cell.outputs,
|
||||
metadata: {
|
||||
editable: cell.metadata?.editable,
|
||||
runnable: cell.metadata?.runnable,
|
||||
breakpointMargin: cell.metadata?.breakpointMargin,
|
||||
hasExecutionOrder: cell.metadata?.hasExecutionOrder,
|
||||
inputCollapsed: cell.metadata?.inputCollapsed,
|
||||
|
|
|
@ -21,8 +21,8 @@ suite('Notebook Folding', () => {
|
|||
const undoRedoService = instantiationService.stub(IUndoRedoService, () => { });
|
||||
instantiationService.spy(IUndoRedoService, 'pushElement');
|
||||
|
||||
test('Folding based on markdown cells', function () {
|
||||
withTestNotebook(
|
||||
test('Folding based on markdown cells', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -50,8 +50,8 @@ suite('Notebook Folding', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('Top level header in a cell wins', function () {
|
||||
withTestNotebook(
|
||||
test('Top level header in a cell wins', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -84,8 +84,8 @@ suite('Notebook Folding', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('Folding', function () {
|
||||
withTestNotebook(
|
||||
test('Folding', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -109,7 +109,7 @@ suite('Notebook Folding', () => {
|
|||
}
|
||||
);
|
||||
|
||||
withTestNotebook(
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -134,7 +134,7 @@ suite('Notebook Folding', () => {
|
|||
}
|
||||
);
|
||||
|
||||
withTestNotebook(
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -160,8 +160,8 @@ suite('Notebook Folding', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('Nested Folding', function () {
|
||||
withTestNotebook(
|
||||
test('Nested Folding', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -217,8 +217,8 @@ suite('Notebook Folding', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('Folding Memento', function () {
|
||||
withTestNotebook(
|
||||
test('Folding Memento', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -249,7 +249,7 @@ suite('Notebook Folding', () => {
|
|||
}
|
||||
);
|
||||
|
||||
withTestNotebook(
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -284,7 +284,7 @@ suite('Notebook Folding', () => {
|
|||
}
|
||||
);
|
||||
|
||||
withTestNotebook(
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -320,8 +320,8 @@ suite('Notebook Folding', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('View Index', function () {
|
||||
withTestNotebook(
|
||||
test('View Index', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -360,7 +360,7 @@ suite('Notebook Folding', () => {
|
|||
}
|
||||
);
|
||||
|
||||
withTestNotebook(
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
|
|
@ -394,7 +394,6 @@ abstract class AbstractElementRenderer extends Disposable {
|
|||
case 'hasExecutionOrder':
|
||||
case 'inputCollapsed':
|
||||
case 'outputCollapsed':
|
||||
case 'runnable':
|
||||
// boolean
|
||||
if (typeof newMetadataObj[key] === 'boolean') {
|
||||
result[key] = newMetadataObj[key];
|
||||
|
|
|
@ -488,9 +488,9 @@
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .runnable .run-button-container .monaco-toolbar,
|
||||
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused .runnable .run-button-container .monaco-toolbar,
|
||||
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.cell-output-hover .runnable .run-button-container .monaco-toolbar {
|
||||
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .run-button-container .monaco-toolbar,
|
||||
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused .run-button-container .monaco-toolbar,
|
||||
.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.cell-output-hover .run-button-container .monaco-toolbar {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
|
|
|
@ -658,10 +658,6 @@ class RegisterSchemasContribution extends Disposable implements IWorkbenchContri
|
|||
type: 'boolean',
|
||||
description: `Controls whether a cell's editor is editable/readonly`
|
||||
},
|
||||
['runnable']: {
|
||||
type: 'boolean',
|
||||
description: 'Controls if the cell is executable'
|
||||
},
|
||||
['breakpointMargin']: {
|
||||
type: 'boolean',
|
||||
description: 'Controls if the cell has a margin to support the breakpoint UI'
|
||||
|
|
|
@ -56,9 +56,8 @@ export const NOTEBOOK_CELL_TYPE = new RawContextKey<string>('notebookCellType',
|
|||
export const NOTEBOOK_CELL_EDITABLE = new RawContextKey<boolean>('notebookCellEditable', false); // bool
|
||||
export const NOTEBOOK_CELL_FOCUSED = new RawContextKey<boolean>('notebookCellFocused', false); // bool
|
||||
export const NOTEBOOK_CELL_EDITOR_FOCUSED = new RawContextKey<boolean>('notebookCellEditorFocused', false); // bool
|
||||
export const NOTEBOOK_CELL_RUNNABLE = new RawContextKey<boolean>('notebookCellRunnable', false); // bool
|
||||
export const NOTEBOOK_CELL_MARKDOWN_EDIT_MODE = new RawContextKey<boolean>('notebookCellMarkdownEditMode', false); // bool
|
||||
export const NOTEBOOK_CELL_RUN_STATE = new RawContextKey<string>('notebookCellRunState', undefined); // idle, running
|
||||
export const NOTEBOOK_CELL_RUN_STATE = new RawContextKey<string>('notebookCellRunState', undefined); // Idle, Running
|
||||
export const NOTEBOOK_CELL_HAS_OUTPUTS = new RawContextKey<boolean>('notebookCellHasOutputs', false); // bool
|
||||
export const NOTEBOOK_CELL_INPUT_COLLAPSED = new RawContextKey<boolean>('notebookCellInputIsCollapsed', false); // bool
|
||||
export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey<boolean>('notebookCellOutputIsCollapsed', false); // bool
|
||||
|
|
|
@ -0,0 +1,445 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { Memento } from 'vs/workbench/common/memento';
|
||||
import { ICellViewModel, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_KERNEL_COUNT } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { configureKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { NotebookKernelProviderAssociation, NotebookKernelProviderAssociations, notebookKernelProviderAssociationsSettingId } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation';
|
||||
import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { CellKind, INotebookKernel, NotebookCellRunState, NotebookRunState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
|
||||
|
||||
const NotebookEditorActiveKernelCache = 'workbench.editor.notebook.activeKernel';
|
||||
|
||||
export interface IKernelManagerDelegate {
|
||||
viewModel: NotebookViewModel | undefined;
|
||||
getId(): string;
|
||||
getContributedNotebookProviders(resource?: URI): readonly NotebookProviderInfo[];
|
||||
getContributedNotebookProvider(viewType: string): NotebookProviderInfo | undefined;
|
||||
getNotebookKernels(viewType: string, resource: URI, token: CancellationToken): Promise<INotebookKernel[]>;
|
||||
loadKernelPreloads(extensionLocation: URI, kernel: INotebookKernel): Promise<void>;
|
||||
}
|
||||
|
||||
export class NotebookEditorKernelManager extends Disposable {
|
||||
private _isDisposed: boolean = false;
|
||||
|
||||
private _activeKernelExecuted: boolean = false;
|
||||
private _activeKernel: INotebookKernel | undefined = undefined;
|
||||
private readonly _onDidChangeKernel = this._register(new Emitter<void>());
|
||||
readonly onDidChangeKernel: Event<void> = this._onDidChangeKernel.event;
|
||||
private readonly _onDidChangeAvailableKernels = this._register(new Emitter<void>());
|
||||
readonly onDidChangeAvailableKernels: Event<void> = this._onDidChangeAvailableKernels.event;
|
||||
|
||||
private _contributedKernelsComputePromise: CancelablePromise<INotebookKernel[]> | null = null;
|
||||
private _initialKernelComputationDone: boolean = false;
|
||||
|
||||
private readonly _editorRunnable: IContextKey<boolean>;
|
||||
private readonly _notebookExecuting: IContextKey<boolean>;
|
||||
private readonly _notebookHasMultipleKernels: IContextKey<boolean>;
|
||||
private readonly _notebookKernelCount: IContextKey<number>;
|
||||
|
||||
get activeKernel() {
|
||||
return this._activeKernel;
|
||||
}
|
||||
|
||||
set activeKernel(kernel: INotebookKernel | undefined) {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._delegate.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._activeKernel === kernel) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._activeKernel = kernel;
|
||||
this._activeKernelResolvePromise = undefined;
|
||||
|
||||
const memento = this._activeKernelMemento.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||
memento[this._delegate.viewModel.viewType] = this._activeKernel?.friendlyId;
|
||||
this._activeKernelMemento.saveMemento();
|
||||
this._onDidChangeKernel.fire();
|
||||
if (this._activeKernel) {
|
||||
this._delegate.loadKernelPreloads(this._activeKernel.extensionLocation, this._activeKernel);
|
||||
}
|
||||
}
|
||||
|
||||
private _activeKernelResolvePromise: Promise<void> | undefined = undefined;
|
||||
|
||||
private _multipleKernelsAvailable: boolean = false;
|
||||
|
||||
get multipleKernelsAvailable() {
|
||||
return this._multipleKernelsAvailable;
|
||||
}
|
||||
|
||||
set multipleKernelsAvailable(state: boolean) {
|
||||
this._multipleKernelsAvailable = state;
|
||||
this._onDidChangeAvailableKernels.fire();
|
||||
}
|
||||
|
||||
private readonly _activeKernelMemento: Memento;
|
||||
|
||||
constructor(
|
||||
private readonly _delegate: IKernelManagerDelegate,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IQuickInputService private readonly _quickInputService: IQuickInputService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,) {
|
||||
super();
|
||||
|
||||
this._activeKernelMemento = new Memento(NotebookEditorActiveKernelCache, storageService);
|
||||
|
||||
this._editorRunnable = NOTEBOOK_EDITOR_RUNNABLE.bindTo(contextKeyService);
|
||||
this._notebookExecuting = NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK.bindTo(contextKeyService);
|
||||
this._notebookHasMultipleKernels = NOTEBOOK_HAS_MULTIPLE_KERNELS.bindTo(contextKeyService);
|
||||
this._notebookKernelCount = NOTEBOOK_KERNEL_COUNT.bindTo(contextKeyService);
|
||||
}
|
||||
|
||||
public async setKernels(tokenSource: CancellationTokenSource) {
|
||||
if (!this._delegate.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._activeKernel !== undefined && this._activeKernelExecuted) {
|
||||
// kernel already executed, we should not change it automatically
|
||||
return;
|
||||
}
|
||||
|
||||
const provider = this._delegate.getContributedNotebookProvider(this._delegate.viewModel.viewType) || this._delegate.getContributedNotebookProviders(this._delegate.viewModel.uri)[0];
|
||||
const availableKernels = await this.beginComputeContributedKernels();
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._notebookKernelCount.set(availableKernels.length);
|
||||
if (availableKernels.length > 1) {
|
||||
this._notebookHasMultipleKernels.set(true);
|
||||
this.multipleKernelsAvailable = true;
|
||||
} else {
|
||||
this._notebookHasMultipleKernels.set(false);
|
||||
this.multipleKernelsAvailable = false;
|
||||
}
|
||||
|
||||
const activeKernelStillExist = [...availableKernels].find(kernel => kernel.friendlyId === this.activeKernel?.friendlyId && this.activeKernel?.friendlyId !== undefined);
|
||||
|
||||
if (activeKernelStillExist) {
|
||||
// the kernel still exist, we don't want to modify the selection otherwise user's temporary preference is lost
|
||||
return;
|
||||
}
|
||||
|
||||
if (availableKernels.length) {
|
||||
return this._setKernelsFromProviders(provider, availableKernels, tokenSource);
|
||||
}
|
||||
|
||||
this._initialKernelComputationDone = true;
|
||||
|
||||
tokenSource.dispose();
|
||||
}
|
||||
|
||||
async beginComputeContributedKernels() {
|
||||
if (this._contributedKernelsComputePromise) {
|
||||
return this._contributedKernelsComputePromise;
|
||||
}
|
||||
|
||||
this._contributedKernelsComputePromise = createCancelablePromise(token => {
|
||||
return this._delegate.getNotebookKernels(this._delegate.viewModel!.viewType, this._delegate.viewModel!.uri, token);
|
||||
});
|
||||
|
||||
const result = await this._contributedKernelsComputePromise;
|
||||
this._initialKernelComputationDone = true;
|
||||
this._contributedKernelsComputePromise = null;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
updateForMetadata(): void {
|
||||
if (!this._delegate.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
const notebookMetadata = this._delegate.viewModel.metadata;
|
||||
this._editorRunnable.set(this._delegate.viewModel.runnable);
|
||||
this._notebookExecuting.set(notebookMetadata.runState === NotebookRunState.Running);
|
||||
}
|
||||
|
||||
private async _setKernelsFromProviders(provider: NotebookProviderInfo, kernels: INotebookKernel[], tokenSource: CancellationTokenSource) {
|
||||
const rawAssociations = this._configurationService.getValue<NotebookKernelProviderAssociations>(notebookKernelProviderAssociationsSettingId) || [];
|
||||
const userSetKernelProvider = rawAssociations.filter(e => e.viewType === this._delegate.viewModel?.viewType)[0]?.kernelProvider;
|
||||
const memento = this._activeKernelMemento.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||
|
||||
if (userSetKernelProvider) {
|
||||
const filteredKernels = kernels.filter(kernel => kernel.extension.value === userSetKernelProvider);
|
||||
|
||||
if (filteredKernels.length) {
|
||||
const cachedKernelId = memento[provider.id];
|
||||
this.activeKernel =
|
||||
filteredKernels.find(kernel => kernel.isPreferred)
|
||||
|| filteredKernels.find(kernel => kernel.friendlyId === cachedKernelId)
|
||||
|| filteredKernels[0];
|
||||
} else {
|
||||
this.activeKernel = undefined;
|
||||
}
|
||||
|
||||
if (this.activeKernel) {
|
||||
await this._delegate.loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._activeKernelResolvePromise = this.activeKernel.resolve(this._delegate.viewModel!.uri, this._delegate.getId(), tokenSource.token);
|
||||
await this._activeKernelResolvePromise;
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memento[provider.id] = this._activeKernel?.friendlyId;
|
||||
this._activeKernelMemento.saveMemento();
|
||||
|
||||
tokenSource.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
// choose a preferred kernel
|
||||
const kernelsFromSameExtension = kernels.filter(kernel => kernel.extension.value === provider.providerExtensionId);
|
||||
if (kernelsFromSameExtension.length) {
|
||||
const cachedKernelId = memento[provider.id];
|
||||
|
||||
const preferedKernel = kernelsFromSameExtension.find(kernel => kernel.isPreferred)
|
||||
|| kernelsFromSameExtension.find(kernel => kernel.friendlyId === cachedKernelId)
|
||||
|| kernelsFromSameExtension[0];
|
||||
this.activeKernel = preferedKernel;
|
||||
if (this.activeKernel) {
|
||||
await this._delegate.loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
}
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
await preferedKernel.resolve(this._delegate.viewModel!.uri, this._delegate.getId(), tokenSource.token);
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
memento[provider.id] = this._activeKernel?.friendlyId;
|
||||
this._activeKernelMemento.saveMemento();
|
||||
tokenSource.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
// the provider doesn't have a builtin kernel, choose a kernel
|
||||
this.activeKernel = kernels[0];
|
||||
if (this.activeKernel) {
|
||||
await this._delegate.loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.activeKernel.resolve(this._delegate.viewModel!.uri, this._delegate.getId(), tokenSource.token);
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tokenSource.dispose();
|
||||
}
|
||||
|
||||
private async _ensureActiveKernel() {
|
||||
if (this._activeKernel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._activeKernelResolvePromise) {
|
||||
await this._activeKernelResolvePromise;
|
||||
|
||||
if (this._activeKernel) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!this._initialKernelComputationDone) {
|
||||
await this.setKernels(new CancellationTokenSource());
|
||||
|
||||
if (this._activeKernel) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// pick active kernel
|
||||
|
||||
const picker = this._quickInputService.createQuickPick<(IQuickPickItem & { run(): void; kernelProviderId?: string })>();
|
||||
picker.placeholder = nls.localize('notebook.runCell.selectKernel', "Select a notebook kernel to run this notebook");
|
||||
picker.matchOnDetail = true;
|
||||
|
||||
const tokenSource = new CancellationTokenSource();
|
||||
const availableKernels = await this.beginComputeContributedKernels();
|
||||
const picks: QuickPickInput<IQuickPickItem & { run(): void; kernelProviderId?: string; }>[] = availableKernels.map((a) => {
|
||||
return {
|
||||
id: a.friendlyId,
|
||||
label: a.label,
|
||||
picked: false,
|
||||
description:
|
||||
a.description
|
||||
? a.description
|
||||
: a.extension.value,
|
||||
detail: a.detail,
|
||||
kernelProviderId: a.extension.value,
|
||||
run: async () => {
|
||||
this.activeKernel = a;
|
||||
this._activeKernelResolvePromise = this.activeKernel.resolve(this._delegate.viewModel!.uri, this._delegate.getId(), tokenSource.token);
|
||||
},
|
||||
buttons: [{
|
||||
iconClass: ThemeIcon.asClassName(configureKernelIcon),
|
||||
tooltip: nls.localize('notebook.promptKernel.setDefaultTooltip', "Set as default kernel provider for '{0}'", this._delegate.viewModel!.viewType)
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
picker.items = picks;
|
||||
picker.busy = false;
|
||||
|
||||
const pickedItem = await new Promise<(IQuickPickItem & { run(): void; kernelProviderId?: string; }) | undefined>(resolve => {
|
||||
picker.onDidAccept(() => {
|
||||
resolve(picker.selectedItems.length === 1 ? picker.selectedItems[0] : undefined);
|
||||
picker.dispose();
|
||||
});
|
||||
|
||||
picker.onDidTriggerItemButton(e => {
|
||||
const pick = e.item;
|
||||
const id = pick.id;
|
||||
resolve(pick); // open the view
|
||||
picker.dispose();
|
||||
|
||||
// And persist the setting
|
||||
if (pick && id && pick.kernelProviderId) {
|
||||
const newAssociation: NotebookKernelProviderAssociation = { viewType: this._delegate.viewModel!.viewType, kernelProvider: pick.kernelProviderId };
|
||||
const currentAssociations = [...this._configurationService.getValue<NotebookKernelProviderAssociations>(notebookKernelProviderAssociationsSettingId)];
|
||||
|
||||
// First try updating existing association
|
||||
for (let i = 0; i < currentAssociations.length; ++i) {
|
||||
const existing = currentAssociations[i];
|
||||
if (existing.viewType === newAssociation.viewType) {
|
||||
currentAssociations.splice(i, 1, newAssociation);
|
||||
this._configurationService.updateValue(notebookKernelProviderAssociationsSettingId, currentAssociations);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, create a new one
|
||||
currentAssociations.unshift(newAssociation);
|
||||
this._configurationService.updateValue(notebookKernelProviderAssociationsSettingId, currentAssociations);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
tokenSource.dispose();
|
||||
|
||||
if (pickedItem) {
|
||||
await pickedItem.run();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
async cancelNotebookExecution(): Promise<void> {
|
||||
if (!this._delegate.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._delegate.viewModel.metadata.runState !== NotebookRunState.Running) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._ensureActiveKernel();
|
||||
await this._activeKernel?.cancelNotebookCell!(this._delegate.viewModel.uri, undefined);
|
||||
}
|
||||
|
||||
async executeNotebook(): Promise<void> {
|
||||
if (!this._delegate.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._delegate.viewModel.runnable) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._ensureActiveKernel();
|
||||
this._activeKernelExecuted = true;
|
||||
await this._activeKernel?.executeNotebookCell!(this._delegate.viewModel.uri, undefined);
|
||||
}
|
||||
|
||||
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 !== NotebookCellRunState.Running) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._ensureActiveKernel();
|
||||
await this._activeKernel?.cancelNotebookCell!(this._delegate.viewModel.uri, cell.handle);
|
||||
}
|
||||
|
||||
async executeNotebookCell(cell: ICellViewModel): Promise<void> {
|
||||
if (!this._delegate.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.canExecuteCell(cell)) {
|
||||
throw new Error('Cell is not executable: ' + cell.uri);
|
||||
}
|
||||
|
||||
await this._ensureActiveKernel();
|
||||
this._activeKernelExecuted = true;
|
||||
await this._activeKernel?.executeNotebookCell!(this._delegate.viewModel.uri, cell.handle);
|
||||
}
|
||||
|
||||
private canExecuteCell(cell: ICellViewModel): boolean {
|
||||
if (!this.activeKernel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cell.cellKind !== CellKind.Code) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.activeKernel.supportedLanguages) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.activeKernel.supportedLanguages.includes(cell.language)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -5,17 +5,18 @@
|
|||
|
||||
import { getPixelRatio, getZoomLevel } from 'vs/base/browser/browser';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
|
||||
import { IAction, Separator } from 'vs/base/common/actions';
|
||||
import { CancelablePromise, createCancelablePromise, SequencerByKey } from 'vs/base/common/async';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { SequencerByKey } from 'vs/base/common/async';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { combinedDisposable, Disposable, DisposableStore, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { extname } from 'vs/base/common/resources';
|
||||
import { ScrollEvent } from 'vs/base/common/scrollable';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import 'vs/css!./media/notebook';
|
||||
|
@ -24,6 +25,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
|||
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { IContentDecorationRenderOptions, IEditor, isThemeColor } from 'vs/editor/common/editorCommon';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
@ -32,45 +34,40 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
|
|||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { contrastBorder, diffInserted, diffRemoved, editorBackground, errorForeground, focusBorder, foreground, listInactiveSelectionBackground, registerColor, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground, textPreformatForeground, transparent } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IColorTheme, IThemeService, registerThemingParticipant, ThemeColor, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { EditorMemento } from 'vs/workbench/browser/parts/editor/editorPane';
|
||||
import { IEditorMemento } from 'vs/workbench/common/editor';
|
||||
import { Memento, MementoObject } from 'vs/workbench/common/memento';
|
||||
import { PANEL_BORDER } from 'vs/workbench/common/theme';
|
||||
import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugColors';
|
||||
import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_OUTPUT_PADDING, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, MARKDOWN_CELL_BOTTOM_MARGIN, MARKDOWN_CELL_TOP_MARGIN, SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
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_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellOutputViewModel, ICellViewModel, ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IFocusNotebookCellOptions, IGenericCellViewModel, IInsetRenderOutput, INotebookCellList, INotebookCellOutputLayoutInfo, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions';
|
||||
import { NotebookKernelProviderAssociation, NotebookKernelProviderAssociations, notebookKernelProviderAssociationsSettingId } from 'vs/workbench/contrib/notebook/browser/notebookKernelAssociation';
|
||||
import { IKernelManagerDelegate, NotebookEditorKernelManager } from 'vs/workbench/contrib/notebook/browser/notebookEditorKernelManager';
|
||||
import { errorStateIcon, successStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList';
|
||||
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
|
||||
import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
|
||||
import { CellContextKeyManager } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys';
|
||||
import { CodeCellRenderer, ListTopCellToolbar, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
|
||||
import { CellDragAndDropController } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellDnd';
|
||||
import { CodeCellRenderer, ListTopCellToolbar, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
|
||||
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
|
||||
import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CellKind, CellToolbarLocKey, ICellRange, INotebookDecorationRenderOptions, INotebookKernel, NotebookCellRunState, NotebookRunState, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellKind, CellToolbarLocKey, ICellRange, INotebookDecorationRenderOptions, INotebookKernel, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator';
|
||||
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { configureKernelIcon, errorStateIcon, successStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugColors';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { extname } from 'vs/base/common/resources';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
const NotebookEditorActiveKernelCache = 'workbench.editor.notebook.activeKernel';
|
||||
|
||||
export class NotebookEditorWidget extends Disposable implements INotebookEditor {
|
||||
static readonly ID: string = 'workbench.editor.notebook';
|
||||
private static readonly EDITOR_MEMENTOS = new Map<string, EditorMemento<unknown>>();
|
||||
|
@ -95,16 +92,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
private readonly _editorFocus: IContextKey<boolean>;
|
||||
private readonly _outputFocus: IContextKey<boolean>;
|
||||
private readonly _editorEditable: IContextKey<boolean>;
|
||||
private readonly _editorRunnable: IContextKey<boolean>;
|
||||
private readonly _notebookExecuting: IContextKey<boolean>;
|
||||
private readonly _notebookHasMultipleKernels: IContextKey<boolean>;
|
||||
private readonly _notebookKernelCount: IContextKey<number>;
|
||||
|
||||
private _outputRenderer: OutputRenderer;
|
||||
protected readonly _contributions = new Map<string, INotebookEditorContribution>();
|
||||
private _scrollBeyondLastLine: boolean;
|
||||
private readonly _memento: Memento;
|
||||
private readonly _activeKernelMemento: Memento;
|
||||
private readonly _onDidFocusEmitter = this._register(new Emitter<void>());
|
||||
public readonly onDidFocus = this._onDidFocusEmitter.event;
|
||||
private readonly _onWillScroll = this._register(new Emitter<ScrollEvent>());
|
||||
|
@ -118,6 +110,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
this._list.scrollTop = top;
|
||||
}
|
||||
|
||||
private _kernelManger: NotebookEditorKernelManager;
|
||||
private _cellContextKeyManager: CellContextKeyManager | null = null;
|
||||
private _isVisible = false;
|
||||
private readonly _uuid = generateUuid();
|
||||
|
@ -152,57 +145,29 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
return this._notebookViewModel?.notebookDocument;
|
||||
}
|
||||
|
||||
private _activeKernelExecuted: boolean = false;
|
||||
private _activeKernel: INotebookKernel | undefined = undefined;
|
||||
private readonly _onDidChangeKernel = this._register(new Emitter<void>());
|
||||
readonly onDidChangeKernel: Event<void> = this._onDidChangeKernel.event;
|
||||
private readonly _onDidChangeAvailableKernels = this._register(new Emitter<void>());
|
||||
readonly onDidChangeAvailableKernels: Event<void> = this._onDidChangeAvailableKernels.event;
|
||||
|
||||
private _contributedKernelsComputePromise: CancelablePromise<INotebookKernel[]> | null = null;
|
||||
private _initialKernelComputationDone: boolean = false;
|
||||
get onDidChangeKernel(): Event<void> {
|
||||
return this._kernelManger.onDidChangeKernel;
|
||||
}
|
||||
get onDidChangeAvailableKernels(): Event<void> {
|
||||
return this._kernelManger.onDidChangeAvailableKernels;
|
||||
}
|
||||
|
||||
get activeKernel() {
|
||||
return this._activeKernel;
|
||||
return this._kernelManger.activeKernel;
|
||||
}
|
||||
|
||||
set activeKernel(kernel: INotebookKernel | undefined) {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._activeKernel === kernel) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._activeKernel = kernel;
|
||||
this._activeKernelResolvePromise = undefined;
|
||||
|
||||
const memento = this._activeKernelMemento.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||
memento[this.viewModel.viewType] = this._activeKernel?.friendlyId;
|
||||
this._activeKernelMemento.saveMemento();
|
||||
this._onDidChangeKernel.fire();
|
||||
if (this._activeKernel) {
|
||||
this._loadKernelPreloads(this._activeKernel.extensionLocation, this._activeKernel);
|
||||
}
|
||||
this._kernelManger.activeKernel = kernel;
|
||||
}
|
||||
|
||||
private _activeKernelResolvePromise: Promise<void> | undefined = undefined;
|
||||
|
||||
private _currentKernelTokenSource: CancellationTokenSource | undefined = undefined;
|
||||
private _multipleKernelsAvailable: boolean = false;
|
||||
|
||||
get multipleKernelsAvailable() {
|
||||
return this._multipleKernelsAvailable;
|
||||
return this._kernelManger.multipleKernelsAvailable;
|
||||
}
|
||||
|
||||
set multipleKernelsAvailable(state: boolean) {
|
||||
this._multipleKernelsAvailable = state;
|
||||
this._onDidChangeAvailableKernels.fire();
|
||||
this._kernelManger.multipleKernelsAvailable = state;
|
||||
}
|
||||
|
||||
private readonly _onDidChangeActiveEditor = this._register(new Emitter<this>());
|
||||
|
@ -258,7 +223,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
@ILayoutService private readonly layoutService: ILayoutService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
|
@ -270,8 +234,23 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
this.scopedContextKeyService = contextKeyService.createScoped(this._overlayContainer);
|
||||
this.instantiationService = instantiationService.createChild(new ServiceCollection([IContextKeyService, this.scopedContextKeyService]));
|
||||
|
||||
const that = this;
|
||||
this._kernelManger = instantiationService.createInstance(NotebookEditorKernelManager, <IKernelManagerDelegate>{
|
||||
getId() { return that.getId(); },
|
||||
loadKernelPreloads: that._loadKernelPreloads.bind(that),
|
||||
get viewModel() { return that.viewModel; },
|
||||
getContributedNotebookProviders(resource?: URI) {
|
||||
return that.notebookService.getContributedNotebookProviders(resource);
|
||||
},
|
||||
getContributedNotebookProvider(viewType: string): NotebookProviderInfo | undefined {
|
||||
return that.notebookService.getContributedNotebookProvider(viewType);
|
||||
},
|
||||
getNotebookKernels(viewType: string, resource: URI, token: CancellationToken): Promise<INotebookKernel[]> {
|
||||
return that.notebookService.getNotebookKernels(viewType, resource, token);
|
||||
}
|
||||
});
|
||||
|
||||
this._memento = new Memento(NotebookEditorWidget.ID, storageService);
|
||||
this._activeKernelMemento = new Memento(NotebookEditorActiveKernelCache, storageService);
|
||||
|
||||
this._outputRenderer = new OutputRenderer(this, this.instantiationService);
|
||||
this._scrollBeyondLastLine = this.configurationService.getValue<boolean>('editor.scrollBeyondLastLine');
|
||||
|
@ -304,10 +283,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
this._editorFocus = NOTEBOOK_EDITOR_FOCUSED.bindTo(this.scopedContextKeyService);
|
||||
this._outputFocus = NOTEBOOK_OUTPUT_FOCUSED.bindTo(this.scopedContextKeyService);
|
||||
this._editorEditable = NOTEBOOK_EDITOR_EDITABLE.bindTo(this.scopedContextKeyService);
|
||||
this._editorRunnable = NOTEBOOK_EDITOR_RUNNABLE.bindTo(this.scopedContextKeyService);
|
||||
this._notebookExecuting = NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK.bindTo(this.scopedContextKeyService);
|
||||
this._notebookHasMultipleKernels = NOTEBOOK_HAS_MULTIPLE_KERNELS.bindTo(this.scopedContextKeyService);
|
||||
this._notebookKernelCount = NOTEBOOK_KERNEL_COUNT.bindTo(this.scopedContextKeyService);
|
||||
|
||||
let contributions: INotebookEditorContributionDescription[];
|
||||
if (Array.isArray(this.creationOptions.contributions)) {
|
||||
|
@ -777,24 +752,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
this._webview?.element.remove();
|
||||
this._webview = null;
|
||||
this._list.clear();
|
||||
this._activeKernel = undefined;
|
||||
this._activeKernelExecuted = false;
|
||||
}
|
||||
|
||||
async beginComputeContributedKernels() {
|
||||
if (this._contributedKernelsComputePromise) {
|
||||
return this._contributedKernelsComputePromise;
|
||||
}
|
||||
|
||||
this._contributedKernelsComputePromise = createCancelablePromise(token => {
|
||||
return this.notebookService.getNotebookKernels(this.viewModel!.viewType, this.viewModel!.uri, token);
|
||||
});
|
||||
|
||||
const result = await this._contributedKernelsComputePromise;
|
||||
this._initialKernelComputationDone = true;
|
||||
this._contributedKernelsComputePromise = null;
|
||||
|
||||
return result;
|
||||
return this._kernelManger.beginComputeContributedKernels();
|
||||
}
|
||||
|
||||
private async _setKernels(tokenSource: CancellationTokenSource) {
|
||||
|
@ -802,127 +763,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
return;
|
||||
}
|
||||
|
||||
if (this._activeKernel !== undefined && this._activeKernelExecuted) {
|
||||
// kernel already executed, we should not change it automatically
|
||||
return;
|
||||
}
|
||||
|
||||
const provider = this.notebookService.getContributedNotebookProvider(this.viewModel.viewType) || this.notebookService.getContributedNotebookProviders(this.viewModel.uri)[0];
|
||||
const availableKernels = await this.beginComputeContributedKernels();
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._notebookKernelCount.set(availableKernels.length);
|
||||
if (availableKernels.length > 1) {
|
||||
this._notebookHasMultipleKernels.set(true);
|
||||
this.multipleKernelsAvailable = true;
|
||||
} else {
|
||||
this._notebookHasMultipleKernels.set(false);
|
||||
this.multipleKernelsAvailable = false;
|
||||
}
|
||||
|
||||
const activeKernelStillExist = [...availableKernels].find(kernel => kernel.friendlyId === this.activeKernel?.friendlyId && this.activeKernel?.friendlyId !== undefined);
|
||||
|
||||
if (activeKernelStillExist) {
|
||||
// the kernel still exist, we don't want to modify the selection otherwise user's temporary preference is lost
|
||||
return;
|
||||
}
|
||||
|
||||
if (availableKernels.length) {
|
||||
return this._setKernelsFromProviders(provider, availableKernels, tokenSource);
|
||||
}
|
||||
|
||||
this._initialKernelComputationDone = true;
|
||||
|
||||
tokenSource.dispose();
|
||||
}
|
||||
|
||||
private async _setKernelsFromProviders(provider: NotebookProviderInfo, kernels: INotebookKernel[], tokenSource: CancellationTokenSource) {
|
||||
const rawAssociations = this.configurationService.getValue<NotebookKernelProviderAssociations>(notebookKernelProviderAssociationsSettingId) || [];
|
||||
const userSetKernelProvider = rawAssociations.filter(e => e.viewType === this.viewModel?.viewType)[0]?.kernelProvider;
|
||||
const memento = this._activeKernelMemento.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||
|
||||
if (userSetKernelProvider) {
|
||||
const filteredKernels = kernels.filter(kernel => kernel.extension.value === userSetKernelProvider);
|
||||
|
||||
if (filteredKernels.length) {
|
||||
const cachedKernelId = memento[provider.id];
|
||||
this.activeKernel =
|
||||
filteredKernels.find(kernel => kernel.isPreferred)
|
||||
|| filteredKernels.find(kernel => kernel.friendlyId === cachedKernelId)
|
||||
|| filteredKernels[0];
|
||||
} else {
|
||||
this.activeKernel = undefined;
|
||||
}
|
||||
|
||||
if (this.activeKernel) {
|
||||
await this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._activeKernelResolvePromise = this.activeKernel.resolve(this.viewModel!.uri, this.getId(), tokenSource.token);
|
||||
await this._activeKernelResolvePromise;
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
memento[provider.id] = this._activeKernel?.friendlyId;
|
||||
this._activeKernelMemento.saveMemento();
|
||||
|
||||
tokenSource.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
// choose a preferred kernel
|
||||
const kernelsFromSameExtension = kernels.filter(kernel => kernel.extension.value === provider.providerExtensionId);
|
||||
if (kernelsFromSameExtension.length) {
|
||||
const cachedKernelId = memento[provider.id];
|
||||
|
||||
const preferedKernel = kernelsFromSameExtension.find(kernel => kernel.isPreferred)
|
||||
|| kernelsFromSameExtension.find(kernel => kernel.friendlyId === cachedKernelId)
|
||||
|| kernelsFromSameExtension[0];
|
||||
this.activeKernel = preferedKernel;
|
||||
if (this.activeKernel) {
|
||||
await this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
}
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
await preferedKernel.resolve(this.viewModel!.uri, this.getId(), tokenSource.token);
|
||||
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
memento[provider.id] = this._activeKernel?.friendlyId;
|
||||
this._activeKernelMemento.saveMemento();
|
||||
tokenSource.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
// the provider doesn't have a builtin kernel, choose a kernel
|
||||
this.activeKernel = kernels[0];
|
||||
if (this.activeKernel) {
|
||||
await this._loadKernelPreloads(this.activeKernel.extensionLocation, this.activeKernel);
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.activeKernel.resolve(this.viewModel!.uri, this.getId(), tokenSource.token);
|
||||
if (tokenSource.token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tokenSource.dispose();
|
||||
this._kernelManger.setKernels(tokenSource);
|
||||
}
|
||||
|
||||
private async _loadKernelPreloads(extensionLocation: URI, kernel: INotebookKernel) {
|
||||
|
@ -939,11 +780,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
|
||||
const notebookMetadata = this.viewModel.metadata;
|
||||
this._editorEditable.set(!!notebookMetadata?.editable);
|
||||
this._editorRunnable.set(this.viewModel.runnable);
|
||||
this._overflowContainer.classList.toggle('notebook-editor-editable', !!notebookMetadata?.editable);
|
||||
this.getDomNode().classList.toggle('notebook-editor-editable', !!notebookMetadata?.editable);
|
||||
|
||||
this._notebookExecuting.set(notebookMetadata.runState === NotebookRunState.Running);
|
||||
this._kernelManger.updateForMetadata();
|
||||
}
|
||||
|
||||
private async _resolveWebview(): Promise<BackLayerWebView<ICommonCellInfo> | null> {
|
||||
|
@ -1498,7 +1338,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
const nextIndex = ui ? this.viewModel.getNextVisibleCellIndex(index) : index + 1;
|
||||
let language;
|
||||
if (type === CellKind.Code) {
|
||||
const supportedLanguages = this._activeKernel?.supportedLanguages ?? this.modeService.getRegisteredModes();
|
||||
const supportedLanguages = this._kernelManger.activeKernel?.supportedLanguages ?? this.modeService.getRegisteredModes();
|
||||
const defaultLanguage = supportedLanguages[0] || 'plaintext';
|
||||
if (cell?.cellKind === CellKind.Code) {
|
||||
language = cell.language;
|
||||
|
@ -1726,152 +1566,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
return undefined;
|
||||
}
|
||||
|
||||
private async _ensureActiveKernel() {
|
||||
if (this._activeKernel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._activeKernelResolvePromise) {
|
||||
await this._activeKernelResolvePromise;
|
||||
|
||||
if (this._activeKernel) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!this._initialKernelComputationDone) {
|
||||
await this._setKernels(new CancellationTokenSource());
|
||||
|
||||
if (this._activeKernel) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// pick active kernel
|
||||
|
||||
const picker = this.quickInputService.createQuickPick<(IQuickPickItem & { run(): void; kernelProviderId?: string })>();
|
||||
picker.placeholder = nls.localize('notebook.runCell.selectKernel', "Select a notebook kernel to run this notebook");
|
||||
picker.matchOnDetail = true;
|
||||
|
||||
const tokenSource = new CancellationTokenSource();
|
||||
const availableKernels = await this.beginComputeContributedKernels();
|
||||
const picks: QuickPickInput<IQuickPickItem & { run(): void; kernelProviderId?: string; }>[] = availableKernels.map((a) => {
|
||||
return {
|
||||
id: a.friendlyId,
|
||||
label: a.label,
|
||||
picked: false,
|
||||
description:
|
||||
a.description
|
||||
? a.description
|
||||
: a.extension.value,
|
||||
detail: a.detail,
|
||||
kernelProviderId: a.extension.value,
|
||||
run: async () => {
|
||||
this.activeKernel = a;
|
||||
this._activeKernelResolvePromise = this.activeKernel.resolve(this.viewModel!.uri, this.getId(), tokenSource.token);
|
||||
},
|
||||
buttons: [{
|
||||
iconClass: ThemeIcon.asClassName(configureKernelIcon),
|
||||
tooltip: nls.localize('notebook.promptKernel.setDefaultTooltip', "Set as default kernel provider for '{0}'", this.viewModel!.viewType)
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
picker.items = picks;
|
||||
picker.busy = false;
|
||||
|
||||
const pickedItem = await new Promise<(IQuickPickItem & { run(): void; kernelProviderId?: string; }) | undefined>(resolve => {
|
||||
picker.onDidAccept(() => {
|
||||
resolve(picker.selectedItems.length === 1 ? picker.selectedItems[0] : undefined);
|
||||
picker.dispose();
|
||||
});
|
||||
|
||||
picker.onDidTriggerItemButton(e => {
|
||||
const pick = e.item;
|
||||
const id = pick.id;
|
||||
resolve(pick); // open the view
|
||||
picker.dispose();
|
||||
|
||||
// And persist the setting
|
||||
if (pick && id && pick.kernelProviderId) {
|
||||
const newAssociation: NotebookKernelProviderAssociation = { viewType: this.viewModel!.viewType, kernelProvider: pick.kernelProviderId };
|
||||
const currentAssociations = [...this.configurationService.getValue<NotebookKernelProviderAssociations>(notebookKernelProviderAssociationsSettingId)];
|
||||
|
||||
// First try updating existing association
|
||||
for (let i = 0; i < currentAssociations.length; ++i) {
|
||||
const existing = currentAssociations[i];
|
||||
if (existing.viewType === newAssociation.viewType) {
|
||||
currentAssociations.splice(i, 1, newAssociation);
|
||||
this.configurationService.updateValue(notebookKernelProviderAssociationsSettingId, currentAssociations);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, create a new one
|
||||
currentAssociations.unshift(newAssociation);
|
||||
this.configurationService.updateValue(notebookKernelProviderAssociationsSettingId, currentAssociations);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
tokenSource.dispose();
|
||||
|
||||
if (pickedItem) {
|
||||
await pickedItem.run();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
async cancelNotebookExecution(): Promise<void> {
|
||||
if (!this.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.viewModel.metadata.runState !== NotebookRunState.Running) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._ensureActiveKernel();
|
||||
await this._activeKernel?.cancelNotebookCell!(this.viewModel.uri, undefined);
|
||||
return this._kernelManger.cancelNotebookExecution();
|
||||
}
|
||||
|
||||
async executeNotebook(): Promise<void> {
|
||||
if (!this.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.viewModel.runnable) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._ensureActiveKernel();
|
||||
this._activeKernelExecuted = true;
|
||||
await this._activeKernel?.executeNotebookCell!(this.viewModel.uri, undefined);
|
||||
return this._kernelManger.executeNotebook();
|
||||
}
|
||||
|
||||
async cancelNotebookCellExecution(cell: ICellViewModel): Promise<void> {
|
||||
if (!this.viewModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cell.cellKind !== CellKind.Code) {
|
||||
return;
|
||||
}
|
||||
|
||||
const metadata = cell.getEvaluatedMetadata(this.viewModel.metadata);
|
||||
if (!metadata.runnable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (metadata.runState !== NotebookCellRunState.Running) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._ensureActiveKernel();
|
||||
await this._activeKernel?.cancelNotebookCell!(this.viewModel.uri, cell.handle);
|
||||
return this._kernelManger.cancelNotebookCellExecution(cell);
|
||||
}
|
||||
|
||||
async executeNotebookCell(cell: ICellViewModel): Promise<void> {
|
||||
|
@ -1879,18 +1583,13 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO@roblourens, don't use the "execute" command for this
|
||||
if (cell.cellKind === CellKind.Markdown) {
|
||||
this.focusNotebookCell(cell, 'container');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cell.getEvaluatedMetadata(this.viewModel.metadata).runnable) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._ensureActiveKernel();
|
||||
this._activeKernelExecuted = true;
|
||||
await this._activeKernel?.executeNotebookCell!(this.viewModel.uri, cell.handle);
|
||||
return this._kernelManger.executeNotebookCell(cell);
|
||||
}
|
||||
|
||||
focusNotebookCell(cell: ICellViewModel, focusItem: 'editor' | 'container' | 'output', options?: IFocusNotebookCellOptions) {
|
||||
|
|
|
@ -520,7 +520,6 @@ export class NotebookService extends Disposable implements INotebookService, IEd
|
|||
const cloneMetadata = (cell: NotebookCellTextModel) => {
|
||||
return {
|
||||
editable: cell.metadata?.editable,
|
||||
runnable: cell.metadata?.runnable,
|
||||
breakpointMargin: cell.metadata?.breakpointMargin,
|
||||
hasExecutionOrder: cell.metadata?.hasExecutionOrder,
|
||||
inputCollapsed: cell.metadata?.inputCollapsed,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { INotebookTextModel, NotebookCellRunState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NOTEBOOK_CELL_TYPE, NOTEBOOK_VIEW_TYPE, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_RUNNABLE, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_RUN_STATE, NOTEBOOK_CELL_HAS_OUTPUTS, CellViewModelStateChangeEvent, CellEditState, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_FOCUSED, INotebookEditor, NOTEBOOK_CELL_EDITOR_FOCUSED, CellFocusMode } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { NOTEBOOK_CELL_TYPE, NOTEBOOK_VIEW_TYPE, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_RUN_STATE, NOTEBOOK_CELL_HAS_OUTPUTS, CellViewModelStateChangeEvent, CellEditState, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_FOCUSED, INotebookEditor, NOTEBOOK_CELL_EDITOR_FOCUSED, CellFocusMode } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
|
@ -15,7 +15,6 @@ export class CellContextKeyManager extends Disposable {
|
|||
private cellType!: IContextKey<string>;
|
||||
private viewType!: IContextKey<string>;
|
||||
private cellEditable!: IContextKey<boolean>;
|
||||
private cellRunnable!: IContextKey<boolean>;
|
||||
private cellFocused!: IContextKey<boolean>;
|
||||
private cellEditorFocused!: IContextKey<boolean>;
|
||||
private cellRunState!: IContextKey<string>;
|
||||
|
@ -41,7 +40,6 @@ export class CellContextKeyManager extends Disposable {
|
|||
this.cellEditable = NOTEBOOK_CELL_EDITABLE.bindTo(this.contextKeyService);
|
||||
this.cellFocused = NOTEBOOK_CELL_FOCUSED.bindTo(this.contextKeyService);
|
||||
this.cellEditorFocused = NOTEBOOK_CELL_EDITOR_FOCUSED.bindTo(this.contextKeyService);
|
||||
this.cellRunnable = NOTEBOOK_CELL_RUNNABLE.bindTo(this.contextKeyService);
|
||||
this.markdownEditMode = NOTEBOOK_CELL_MARKDOWN_EDIT_MODE.bindTo(this.contextKeyService);
|
||||
this.cellRunState = NOTEBOOK_CELL_RUN_STATE.bindTo(this.contextKeyService);
|
||||
this.cellHasOutputs = NOTEBOOK_CELL_HAS_OUTPUTS.bindTo(this.contextKeyService);
|
||||
|
@ -116,7 +114,6 @@ export class CellContextKeyManager extends Disposable {
|
|||
private updateForMetadata() {
|
||||
const metadata = this.element.getEvaluatedMetadata(this.notebookTextModel.metadata);
|
||||
this.cellEditable.set(!!metadata.editable);
|
||||
this.cellRunnable.set(!!metadata.runnable);
|
||||
|
||||
const runState = metadata.runState ?? NotebookCellRunState.Idle;
|
||||
this.cellRunState.set(NotebookCellRunState[runState]);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
||||
// TODO@roblourens Is this class overkill now?
|
||||
export class CellMenus {
|
||||
constructor(
|
||||
@IMenuService private readonly menuService: IMenuService,
|
||||
|
@ -23,10 +24,12 @@ export class CellMenus {
|
|||
return this.getMenu(MenuId.NotebookCellListTop, contextKeyService);
|
||||
}
|
||||
|
||||
getCellExecuteMenu(contextKeyService: IContextKeyService): IMenu {
|
||||
return this.getMenu(MenuId.NotebookCellExecute, contextKeyService);
|
||||
}
|
||||
|
||||
private getMenu(menuId: MenuId, contextKeyService: IContextKeyService): IMenu {
|
||||
const menu = this.menuService.createMenu(menuId, contextKeyService);
|
||||
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
import { getPixelRatio, getZoomLevel } from 'vs/base/browser/browser';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels';
|
||||
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
|
@ -36,13 +36,13 @@ import { ServiceCollection } from 'vs/platform/instantiation/common/serviceColle
|
|||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { BOTTOM_CELL_TOOLBAR_GAP, CELL_BOTTOM_MARGIN, CELL_TOP_MARGIN, EDITOR_BOTTOM_PADDING, EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CancelCellAction, DeleteCellAction, ExecuteCellAction, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
|
||||
import { DeleteCellAction, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
|
||||
import { BaseCellRenderTemplate, CellEditState, CodeCellRenderTemplate, EditorTopPaddingChangeEvent, EXPAND_CELL_CONTENT_COMMAND_ID, getEditorTopPadding, ICellViewModel, INotebookEditor, isCodeCellRenderTemplate, MarkdownCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellContextKeyManager } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys';
|
||||
import { CellDragAndDropController, DRAGGING_CLASS } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellDnd';
|
||||
import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus';
|
||||
import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
|
||||
import { CodeCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/codeCell';
|
||||
import { CellDragAndDropController, DRAGGING_CLASS } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellDnd';
|
||||
import { StatefulMarkdownCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/markdownCell';
|
||||
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
|
@ -244,7 +244,7 @@ abstract class AbstractCellRenderer {
|
|||
return toolbar;
|
||||
}
|
||||
|
||||
private getCellToolbarActions(menu: IMenu, alwaysFillSecondaryActions: boolean): { primary: IAction[], secondary: IAction[] } {
|
||||
protected getCellToolbarActions(menu: IMenu, alwaysFillSecondaryActions: boolean): { primary: IAction[], secondary: IAction[] } {
|
||||
const primary: IAction[] = [];
|
||||
const secondary: IAction[] = [];
|
||||
const result = { primary, secondary };
|
||||
|
@ -742,8 +742,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
|||
|
||||
const cellContainer = DOM.append(container, $('.cell.code'));
|
||||
const runButtonContainer = DOM.append(cellContainer, $('.run-button-container'));
|
||||
const runToolbar = disposables.add(this.createToolbar(runButtonContainer));
|
||||
|
||||
const runToolbar = disposables.add(this.setupRunToolbar(runButtonContainer, contextKeyService, disposables));
|
||||
const executionOrderLabel = DOM.append(cellContainer, $('div.execution-count-label'));
|
||||
|
||||
const editorPart = DOM.append(cellContainer, $('.cell-editor-part'));
|
||||
|
@ -772,7 +772,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
|||
|
||||
const statusBar = disposables.add(this.instantiationService.createInstance(CellEditorStatusBar, editorPart));
|
||||
const timer = new TimerRenderer(statusBar.durationContainer);
|
||||
const cellRunState = new RunStateRenderer(statusBar.cellRunStatusContainer, runToolbar, this.instantiationService);
|
||||
const cellRunState = new RunStateRenderer(statusBar.cellRunStatusContainer);
|
||||
|
||||
const outputContainer = DOM.append(container, $('.output'));
|
||||
const outputShowMoreContainer = DOM.append(container, $('.output-show-more-container'));
|
||||
|
@ -834,6 +834,20 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
|||
return templateData;
|
||||
}
|
||||
|
||||
private setupRunToolbar(runButtonContainer: HTMLElement, contextKeyService: IContextKeyService, disposables: DisposableStore): ToolBar {
|
||||
const runToolbar = this.createToolbar(runButtonContainer);
|
||||
const runMenu = this.cellMenus.getCellExecuteMenu(contextKeyService);
|
||||
const update = () => {
|
||||
const actions = this.getCellToolbarActions(runMenu, false);
|
||||
runToolbar.setActions(actions.primary, actions.secondary);
|
||||
};
|
||||
disposables.add(runMenu.onDidChange(() => {
|
||||
update();
|
||||
}));
|
||||
update();
|
||||
return runToolbar;
|
||||
}
|
||||
|
||||
private updateForOutputs(element: CodeCellViewModel, templateData: CodeCellRenderTemplate): void {
|
||||
if (element.outputsViewModels.length) {
|
||||
DOM.show(templateData.focusSinkElement);
|
||||
|
@ -848,7 +862,6 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
|||
}
|
||||
|
||||
const metadata = element.getEvaluatedMetadata(this.notebookEditor.viewModel.notebookDocument.metadata);
|
||||
templateData.container.classList.toggle('runnable', !!metadata.runnable);
|
||||
this.updateExecutionOrder(metadata, templateData);
|
||||
templateData.statusBar.cellStatusMessageContainer.textContent = metadata?.statusMessage || '';
|
||||
|
||||
|
@ -1062,7 +1075,7 @@ export class RunStateRenderer {
|
|||
private spinnerTimer: any | undefined;
|
||||
private pendingNewState: NotebookCellRunState | undefined;
|
||||
|
||||
constructor(private readonly element: HTMLElement, private readonly runToolbar: ToolBar, private readonly instantiationService: IInstantiationService) {
|
||||
constructor(private readonly element: HTMLElement) {
|
||||
DOM.hide(element);
|
||||
}
|
||||
|
||||
|
@ -1079,12 +1092,6 @@ export class RunStateRenderer {
|
|||
return;
|
||||
}
|
||||
|
||||
if (runState === NotebookCellRunState.Running) {
|
||||
this.runToolbar.setActions([this.instantiationService.createInstance(CancelCellAction)]);
|
||||
} else {
|
||||
this.runToolbar.setActions([this.instantiationService.createInstance(ExecuteCellAction)]);
|
||||
}
|
||||
|
||||
if (runState === NotebookCellRunState.Success) {
|
||||
DOM.reset(this.element, renderIcon(successStateIcon));
|
||||
} else if (runState === NotebookCellRunState.Error) {
|
||||
|
|
|
@ -229,7 +229,6 @@ export class CodeCell extends Disposable {
|
|||
const updatePlaceholder = () => {
|
||||
if (this.notebookEditor.viewModel
|
||||
&& this.notebookEditor.getActiveCell() === this.viewCell
|
||||
&& viewCell.getEvaluatedMetadata(this.notebookEditor.viewModel.metadata).runnable
|
||||
&& viewCell.metadata.runState === undefined
|
||||
&& viewCell.metadata.lastRunDuration === undefined
|
||||
) {
|
||||
|
|
|
@ -453,9 +453,6 @@ export abstract class BaseCellViewModel extends Disposable {
|
|||
const editable = this.metadata?.editable ??
|
||||
documentMetadata.cellEditable;
|
||||
|
||||
const runnable = (this.metadata?.runnable ??
|
||||
documentMetadata.cellRunnable) && !!documentMetadata.trusted;
|
||||
|
||||
const hasExecutionOrder = this.metadata?.hasExecutionOrder ??
|
||||
documentMetadata.cellHasExecutionOrder;
|
||||
|
||||
|
@ -463,7 +460,6 @@ export abstract class BaseCellViewModel extends Disposable {
|
|||
...(this.metadata || {}),
|
||||
...{
|
||||
editable,
|
||||
runnable,
|
||||
hasExecutionOrder
|
||||
}
|
||||
};
|
||||
|
|
|
@ -153,9 +153,6 @@ export class NotebookCellTextModel extends Disposable implements ICell {
|
|||
const editable = this.metadata?.editable ??
|
||||
documentMetadata.cellEditable;
|
||||
|
||||
const runnable = this.metadata?.runnable ??
|
||||
documentMetadata.cellRunnable;
|
||||
|
||||
const hasExecutionOrder = this.metadata?.hasExecutionOrder ??
|
||||
documentMetadata.cellHasExecutionOrder;
|
||||
|
||||
|
@ -163,7 +160,6 @@ export class NotebookCellTextModel extends Disposable implements ICell {
|
|||
...(this.metadata || {}),
|
||||
...{
|
||||
editable,
|
||||
runnable,
|
||||
hasExecutionOrder
|
||||
}
|
||||
};
|
||||
|
|
|
@ -62,7 +62,6 @@ export const notebookDocumentMetadataDefaults: Required<NotebookDocumentMetadata
|
|||
editable: true,
|
||||
runnable: true,
|
||||
cellEditable: true,
|
||||
cellRunnable: true,
|
||||
cellHasExecutionOrder: true,
|
||||
displayOrder: NOTEBOOK_DISPLAY_ORDER,
|
||||
custom: {},
|
||||
|
@ -74,7 +73,6 @@ export interface NotebookDocumentMetadata {
|
|||
editable: boolean;
|
||||
runnable: boolean;
|
||||
cellEditable: boolean;
|
||||
cellRunnable: boolean;
|
||||
cellHasExecutionOrder: boolean;
|
||||
displayOrder?: (string | glob.IRelativePattern)[];
|
||||
custom?: { [key: string]: unknown };
|
||||
|
@ -91,7 +89,6 @@ export enum NotebookCellRunState {
|
|||
|
||||
export interface NotebookCellMetadata {
|
||||
editable?: boolean;
|
||||
runnable?: boolean;
|
||||
breakpointMargin?: boolean;
|
||||
hasExecutionOrder?: boolean;
|
||||
executionOrder?: number;
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as sinon from 'sinon';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { assertThrowsAsync } from 'vs/base/test/common/utils';
|
||||
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
|
||||
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 { TestQuickInputService } from 'vs/platform/quickinput/test/testQuickInputService';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { NOTEBOOK_KERNEL_COUNT } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
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, 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';
|
||||
|
||||
suite('NotebookEditorKernelManager', () => {
|
||||
const instantiationService = setupInstantiationService();
|
||||
instantiationService.stub(IStorageService, new TestStorageService());
|
||||
instantiationService.stub(IContextKeyService, new MockContextKeyService());
|
||||
instantiationService.stub(IQuickInputService, new TestQuickInputService());
|
||||
|
||||
const bulkEditService = instantiationService.get(IBulkEditService);
|
||||
const undoRedoService = instantiationService.get(IUndoRedoService);
|
||||
const loadKernelPreloads = async () => { };
|
||||
|
||||
async function withTestNotebook(cells: [string, string, CellKind, IOutputDto[], NotebookCellMetadata][], callback: (viewModel: NotebookViewModel, textModel: NotebookTextModel) => void | Promise<void>) {
|
||||
return _withTestNotebook(instantiationService, bulkEditService, undoRedoService, cells, (_editor, viewModel, textModel) => callback(viewModel, textModel));
|
||||
}
|
||||
|
||||
test('ctor', () => {
|
||||
instantiationService.createInstance(NotebookEditorKernelManager, {});
|
||||
const contextKeyService = instantiationService.get(IContextKeyService);
|
||||
|
||||
assert.strictEqual(contextKeyService.getContextKeyValue(NOTEBOOK_KERNEL_COUNT.key), 0);
|
||||
});
|
||||
|
||||
test('cell is not runnable when no kernel is selected', async () => {
|
||||
await withTestNotebook(
|
||||
[],
|
||||
async (viewModel) => {
|
||||
const kernelManager: NotebookEditorKernelManager = instantiationService.createInstance(NotebookEditorKernelManager, { viewModel, loadKernelPreloads });
|
||||
|
||||
const cell = viewModel.createCell(1, 'var c = 3', 'javascript', CellKind.Code, {}, [], true, true);
|
||||
await assertThrowsAsync(async () => await kernelManager.executeNotebookCell(cell));
|
||||
});
|
||||
});
|
||||
|
||||
test('cell is not runnable when kernel does not support the language', async () => {
|
||||
await withTestNotebook(
|
||||
[],
|
||||
async (viewModel) => {
|
||||
const kernelManager: NotebookEditorKernelManager = instantiationService.createInstance(NotebookEditorKernelManager, { viewModel, loadKernelPreloads });
|
||||
kernelManager.activeKernel = new TestNotebookKernel({ languages: ['testlang'] });
|
||||
|
||||
const cell = viewModel.createCell(1, 'var c = 3', 'javascript', CellKind.Code, {}, [], true, true);
|
||||
await assertThrowsAsync(async () => await kernelManager.executeNotebookCell(cell));
|
||||
});
|
||||
});
|
||||
|
||||
test('cell is runnable when kernel does support the language', async () => {
|
||||
await withTestNotebook(
|
||||
[],
|
||||
async (viewModel) => {
|
||||
const kernelManager: NotebookEditorKernelManager = instantiationService.createInstance(NotebookEditorKernelManager, { viewModel, loadKernelPreloads });
|
||||
const kernel = new TestNotebookKernel({ languages: ['javascript'] });
|
||||
const executeSpy = sinon.spy();
|
||||
kernel.executeNotebookCell = executeSpy;
|
||||
kernelManager.activeKernel = kernel;
|
||||
|
||||
const cell = viewModel.createCell(0, 'var c = 3', 'javascript', CellKind.Code, {}, [], true, true);
|
||||
await kernelManager.executeNotebookCell(cell);
|
||||
assert.strictEqual(executeSpy.calledOnce, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
class TestNotebookKernel implements INotebookKernel {
|
||||
id?: string | undefined;
|
||||
friendlyId: string = '';
|
||||
label: string = '';
|
||||
extension: ExtensionIdentifier = new ExtensionIdentifier('test');
|
||||
extensionLocation: URI = URI.file('/test');
|
||||
providerHandle?: number | undefined;
|
||||
description?: string | undefined;
|
||||
detail?: string | undefined;
|
||||
isPreferred?: boolean | undefined;
|
||||
preloads?: URI[] | undefined;
|
||||
supportedLanguages?: string[] | undefined;
|
||||
async resolve(uri: URI, editorId: string, token: CancellationToken): Promise<void> { }
|
||||
executeNotebookCell(uri: URI, handle: number | undefined): Promise<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
cancelNotebookCell(uri: URI, handle: number | undefined): Promise<void> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
constructor(opts?: { languages?: string[] }) {
|
||||
this.supportedLanguages = opts?.languages;
|
||||
}
|
||||
}
|
|
@ -17,8 +17,8 @@ suite('NotebookTextModel', () => {
|
|||
const undoRedoService = instantiationService.stub(IUndoRedoService, () => { });
|
||||
instantiationService.spy(IUndoRedoService, 'pushElement');
|
||||
|
||||
test('insert', function () {
|
||||
withTestNotebook(
|
||||
test('insert', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -42,8 +42,8 @@ suite('NotebookTextModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('multiple inserts at same position', function () {
|
||||
withTestNotebook(
|
||||
test('multiple inserts at same position', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -67,8 +67,8 @@ suite('NotebookTextModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('delete', function () {
|
||||
withTestNotebook(
|
||||
test('delete', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -90,8 +90,8 @@ suite('NotebookTextModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('delete + insert', function () {
|
||||
withTestNotebook(
|
||||
test('delete + insert', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -115,8 +115,8 @@ suite('NotebookTextModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('delete + insert at same position', function () {
|
||||
withTestNotebook(
|
||||
test('delete + insert at same position', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -140,8 +140,8 @@ suite('NotebookTextModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('(replace) delete + insert at same position', function () {
|
||||
withTestNotebook(
|
||||
test('(replace) delete + insert at same position', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -164,8 +164,8 @@ suite('NotebookTextModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('output', function () {
|
||||
withTestNotebook(
|
||||
test('output', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -239,8 +239,8 @@ suite('NotebookTextModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('metadata', function () {
|
||||
withTestNotebook(
|
||||
test('metadata', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -279,8 +279,8 @@ suite('NotebookTextModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('multiple inserts in one edit', function () {
|
||||
withTestNotebook(
|
||||
test('multiple inserts in one edit', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
@ -316,8 +316,8 @@ suite('NotebookTextModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('insert and metadata change in one edit', function () {
|
||||
withTestNotebook(
|
||||
test('insert and metadata change in one edit', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
|
|
|
@ -19,21 +19,21 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
|||
suite('NotebookViewModel', () => {
|
||||
const instantiationService = setupInstantiationService();
|
||||
const textModelService = instantiationService.get(ITextModelService);
|
||||
const blukEditService = instantiationService.get(IBulkEditService);
|
||||
const bulkEditService = instantiationService.get(IBulkEditService);
|
||||
const undoRedoService = instantiationService.get(IUndoRedoService);
|
||||
|
||||
test('ctor', function () {
|
||||
const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], notebookDocumentMetadataDefaults, { transientMetadata: {}, transientOutputs: false }, undoRedoService, textModelService);
|
||||
const model = new NotebookEditorTestModel(notebook);
|
||||
const eventDispatcher = new NotebookEventDispatcher();
|
||||
const viewModel = new NotebookViewModel('notebook', model.notebook, eventDispatcher, null, instantiationService, blukEditService, undoRedoService);
|
||||
const viewModel = new NotebookViewModel('notebook', model.notebook, eventDispatcher, null, instantiationService, bulkEditService, undoRedoService);
|
||||
assert.equal(viewModel.viewType, 'notebook');
|
||||
});
|
||||
|
||||
test('insert/delete', function () {
|
||||
withTestNotebook(
|
||||
test('insert/delete', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
bulkEditService,
|
||||
undoRedoService,
|
||||
[
|
||||
['var a = 1;', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
|
@ -56,10 +56,10 @@ suite('NotebookViewModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('move cells down', function () {
|
||||
withTestNotebook(
|
||||
test('move cells down', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
bulkEditService,
|
||||
undoRedoService,
|
||||
[
|
||||
['//a', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
|
@ -87,10 +87,10 @@ suite('NotebookViewModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('move cells up', function () {
|
||||
withTestNotebook(
|
||||
test('move cells up', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
bulkEditService,
|
||||
undoRedoService,
|
||||
[
|
||||
['//a', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
|
@ -112,10 +112,10 @@ suite('NotebookViewModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('index', function () {
|
||||
withTestNotebook(
|
||||
test('index', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
bulkEditService,
|
||||
undoRedoService,
|
||||
[
|
||||
['var a = 1;', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
|
@ -141,90 +141,79 @@ suite('NotebookViewModel', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('metadata', function () {
|
||||
withTestNotebook(
|
||||
test('metadata', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
bulkEditService,
|
||||
undoRedoService,
|
||||
[
|
||||
['var a = 1;', 'javascript', CellKind.Code, [], {}],
|
||||
['var b = 2;', 'javascript', CellKind.Code, [], { editable: true, runnable: true }],
|
||||
['var c = 3;', 'javascript', CellKind.Code, [], { editable: true, runnable: false }],
|
||||
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false, runnable: true }],
|
||||
['var e = 5;', 'javascript', CellKind.Code, [], { editable: false, runnable: false }],
|
||||
['var b = 2;', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
['var c = 3;', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false }],
|
||||
['var e = 5;', 'javascript', CellKind.Code, [], { editable: false }],
|
||||
],
|
||||
(editor, viewModel) => {
|
||||
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: true, cellEditable: true, cellHasExecutionOrder: true, trusted: true };
|
||||
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellEditable: true, cellHasExecutionOrder: true, trusted: true };
|
||||
|
||||
const defaults = { hasExecutionOrder: true };
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: true,
|
||||
runnable: true,
|
||||
...defaults
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[1].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: true,
|
||||
runnable: true,
|
||||
...defaults
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[2].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: true,
|
||||
runnable: false,
|
||||
...defaults
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[3].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: false,
|
||||
runnable: true,
|
||||
...defaults
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[4].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: false,
|
||||
runnable: false,
|
||||
...defaults
|
||||
});
|
||||
|
||||
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: true, cellHasExecutionOrder: true, trusted: true };
|
||||
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellEditable: true, cellHasExecutionOrder: true, trusted: true };
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: true,
|
||||
runnable: false,
|
||||
...defaults
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[1].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: true,
|
||||
runnable: true,
|
||||
...defaults
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[2].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: true,
|
||||
runnable: false,
|
||||
...defaults
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[3].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: false,
|
||||
runnable: true,
|
||||
...defaults
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[4].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: false,
|
||||
runnable: false,
|
||||
...defaults
|
||||
});
|
||||
|
||||
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellRunnable: false, cellEditable: false, cellHasExecutionOrder: true, trusted: true };
|
||||
viewModel.notebookDocument.metadata = { editable: true, runnable: true, cellEditable: false, cellHasExecutionOrder: true, trusted: true };
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), <NotebookCellMetadata>{
|
||||
editable: false,
|
||||
runnable: false,
|
||||
...defaults
|
||||
});
|
||||
}
|
||||
|
@ -262,17 +251,17 @@ suite('NotebookViewModel Decorations', () => {
|
|||
const blukEditService = instantiationService.get(IBulkEditService);
|
||||
const undoRedoService = instantiationService.get(IUndoRedoService);
|
||||
|
||||
test('tracking range', function () {
|
||||
withTestNotebook(
|
||||
test('tracking range', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
[
|
||||
['var a = 1;', 'javascript', CellKind.Code, [], {}],
|
||||
['var b = 2;', 'javascript', CellKind.Code, [], { editable: true, runnable: true }],
|
||||
['var c = 3;', 'javascript', CellKind.Code, [], { editable: true, runnable: false }],
|
||||
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false, runnable: true }],
|
||||
['var e = 5;', 'javascript', CellKind.Code, [], { editable: false, runnable: false }],
|
||||
['var b = 2;', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
['var c = 3;', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false }],
|
||||
['var e = 5;', 'javascript', CellKind.Code, [], { editable: false }],
|
||||
],
|
||||
(editor, viewModel) => {
|
||||
const trackedId = viewModel.setTrackedRange('test', { start: 1, end: 2 }, TrackedRangeStickiness.GrowsOnlyWhenTypingAfter);
|
||||
|
@ -320,19 +309,19 @@ suite('NotebookViewModel Decorations', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('tracking range 2', function () {
|
||||
withTestNotebook(
|
||||
test('tracking range 2', async function () {
|
||||
await withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
[
|
||||
['var a = 1;', 'javascript', CellKind.Code, [], {}],
|
||||
['var b = 2;', 'javascript', CellKind.Code, [], { editable: true, runnable: true }],
|
||||
['var c = 3;', 'javascript', CellKind.Code, [], { editable: true, runnable: false }],
|
||||
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false, runnable: true }],
|
||||
['var e = 5;', 'javascript', CellKind.Code, [], { editable: false, runnable: false }],
|
||||
['var e = 6;', 'javascript', CellKind.Code, [], { editable: false, runnable: false }],
|
||||
['var e = 7;', 'javascript', CellKind.Code, [], { editable: false, runnable: false }],
|
||||
['var b = 2;', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
['var c = 3;', 'javascript', CellKind.Code, [], { editable: true }],
|
||||
['var d = 4;', 'javascript', CellKind.Code, [], { editable: false }],
|
||||
['var e = 5;', 'javascript', CellKind.Code, [], { editable: false }],
|
||||
['var e = 6;', 'javascript', CellKind.Code, [], { editable: false }],
|
||||
['var e = 7;', 'javascript', CellKind.Code, [], { editable: false }],
|
||||
],
|
||||
(editor, viewModel) => {
|
||||
const trackedId = viewModel.setTrackedRange('test', { start: 1, end: 3 }, TrackedRangeStickiness.GrowsOnlyWhenTypingAfter);
|
||||
|
@ -359,7 +348,7 @@ suite('NotebookViewModel Decorations', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('reduce range', function () {
|
||||
test('reduce range', async function () {
|
||||
assert.deepEqual(reduceCellRanges([
|
||||
{ start: 0, end: 1 },
|
||||
{ start: 1, end: 2 },
|
||||
|
@ -378,7 +367,7 @@ suite('NotebookViewModel Decorations', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('diff hidden ranges', function () {
|
||||
test('diff hidden ranges', async function () {
|
||||
assert.deepEqual(getVisibleCells<number>([1, 2, 3, 4, 5], []), [1, 2, 3, 4, 5]);
|
||||
|
||||
assert.deepEqual(
|
||||
|
@ -420,7 +409,7 @@ suite('NotebookViewModel Decorations', () => {
|
|||
}), [{ start: 1, deleteCount: 1, toInsert: [2, 6] }]);
|
||||
});
|
||||
|
||||
test('hidden ranges', function () {
|
||||
test('hidden ranges', async function () {
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -456,7 +456,8 @@ export function setupInstantiationService() {
|
|||
return instantiationService;
|
||||
}
|
||||
|
||||
export function withTestNotebook(instantiationService: TestInstantiationService, blukEditService: IBulkEditService, undoRedoService: IUndoRedoService, cells: [string, string, CellKind, IOutputDto[], NotebookCellMetadata][], callback: (editor: TestNotebookEditor, viewModel: NotebookViewModel, textModel: NotebookTextModel) => void) {
|
||||
// TODO await all usages
|
||||
export async function withTestNotebook(instantiationService: TestInstantiationService, blukEditService: IBulkEditService, undoRedoService: IUndoRedoService, cells: [string, string, CellKind, IOutputDto[], NotebookCellMetadata][], callback: (editor: TestNotebookEditor, viewModel: NotebookViewModel, textModel: NotebookTextModel) => void | Promise<void>) {
|
||||
const textModelService = instantiationService.get(ITextModelService);
|
||||
|
||||
const viewType = 'notebook';
|
||||
|
@ -474,7 +475,7 @@ export function withTestNotebook(instantiationService: TestInstantiationService,
|
|||
const eventDispatcher = new NotebookEventDispatcher();
|
||||
const viewModel = new NotebookViewModel(viewType, model.notebook, eventDispatcher, null, instantiationService, blukEditService, undoRedoService);
|
||||
|
||||
callback(editor, viewModel, notebook);
|
||||
await callback(editor, viewModel, notebook);
|
||||
|
||||
viewModel.dispose();
|
||||
return;
|
||||
|
|
|
@ -4,29 +4,27 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { normalize } from 'vs/base/common/path';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { URI as uri } from 'vs/base/common/uri';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
import { BaseConfigurationResolverService } from 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
|
||||
import { Workspace, IWorkspaceFolder, IWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { TestEditorService, TestProductService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { TestWorkbenchConfiguration } from 'vs/workbench/test/electron-browser/workbenchTestServices';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IQuickInputService, IQuickPickItem, QuickPickInput, IPickOptions, Omit, IInputOptions, IQuickInputButton, IQuickPick, IInputBox, IQuickNavigateConfiguration } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import * as Types from 'vs/base/common/types';
|
||||
import { EditorType } from 'vs/editor/common/editorCommon';
|
||||
import { normalize } from 'vs/base/common/path';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { URI as uri } from 'vs/base/common/uri';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
import { NativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService';
|
||||
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace';
|
||||
import { EditorType } from 'vs/editor/common/editorCommon';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { IFormatterChangeEvent, ILabelService, ResourceLabelFormatter } from 'vs/platform/label/common/label';
|
||||
import { TestQuickInputService } from 'vs/platform/quickinput/test/testQuickInputService';
|
||||
import { IWorkspace, IWorkspaceFolder, Workspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace';
|
||||
import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { BaseConfigurationResolverService } from 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
import { NativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService';
|
||||
import { TestEditorService, TestProductService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { TestWorkbenchConfiguration } from 'vs/workbench/test/electron-browser/workbenchTestServices';
|
||||
|
||||
const mockLineNumber = 10;
|
||||
class TestEditorServiceWithActiveEditor extends TestEditorService {
|
||||
|
@ -66,13 +64,13 @@ suite('Configuration Resolver Service', () => {
|
|||
let editorService: TestEditorServiceWithActiveEditor;
|
||||
let containingWorkspace: Workspace;
|
||||
let workspace: IWorkspaceFolder;
|
||||
let quickInputService: MockQuickInputService;
|
||||
let quickInputService: TestQuickInputService;
|
||||
let labelService: MockLabelService;
|
||||
|
||||
setup(() => {
|
||||
mockCommandService = new MockCommandService();
|
||||
editorService = new TestEditorServiceWithActiveEditor();
|
||||
quickInputService = new MockQuickInputService();
|
||||
quickInputService = new TestQuickInputService();
|
||||
environmentService = new MockWorkbenchEnvironmentService(envVariables);
|
||||
labelService = new MockLabelService();
|
||||
containingWorkspace = testWorkspace(uri.parse('file:///VSCode/workspaceLocation'));
|
||||
|
@ -648,63 +646,6 @@ class MockCommandService implements ICommandService {
|
|||
}
|
||||
}
|
||||
|
||||
class MockQuickInputService implements IQuickInputService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
readonly onShow = Event.None;
|
||||
readonly onHide = Event.None;
|
||||
|
||||
readonly quickAccess = undefined!;
|
||||
|
||||
public pick<T extends IQuickPickItem>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: true }, token?: CancellationToken): Promise<T[]>;
|
||||
public pick<T extends IQuickPickItem>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: false }, token?: CancellationToken): Promise<T>;
|
||||
public pick<T extends IQuickPickItem>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: Omit<IPickOptions<T>, 'canPickMany'>, token?: CancellationToken): Promise<T | undefined> {
|
||||
if (Types.isArray(picks)) {
|
||||
return Promise.resolve(<any>{ label: 'selectedPick', description: 'pick description', value: 'selectedPick' });
|
||||
} else {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
public input(options?: IInputOptions, token?: CancellationToken): Promise<string> {
|
||||
return Promise.resolve(options ? 'resolved' + options.prompt : 'resolved');
|
||||
}
|
||||
|
||||
backButton!: IQuickInputButton;
|
||||
|
||||
createQuickPick<T extends IQuickPickItem>(): IQuickPick<T> {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
createInputBox(): IInputBox {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
toggle(): void {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
navigate(next: boolean, quickNavigate?: IQuickNavigateConfiguration): void {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
accept(): Promise<void> {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
back(): Promise<void> {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
|
||||
cancel(): Promise<void> {
|
||||
throw new Error('not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
class MockLabelService implements ILabelService {
|
||||
_serviceBrand: undefined;
|
||||
getUriLabel(resource: uri, options?: { relative?: boolean | undefined; noPrefix?: boolean | undefined; endWithSeparator?: boolean | undefined; }): string {
|
||||
|
|
|
@ -653,7 +653,6 @@ suite('ExtHostTypes', function () {
|
|||
const obj = new types.NotebookDocumentMetadata();
|
||||
assert.strictEqual(obj.cellEditable, notebookDocumentMetadataDefaults.cellEditable);
|
||||
assert.strictEqual(obj.cellHasExecutionOrder, notebookDocumentMetadataDefaults.cellHasExecutionOrder);
|
||||
assert.strictEqual(obj.cellRunnable, notebookDocumentMetadataDefaults.cellRunnable);
|
||||
assert.deepStrictEqual(obj.custom, notebookDocumentMetadataDefaults.custom);
|
||||
assert.deepStrictEqual(obj.displayOrder, notebookDocumentMetadataDefaults.displayOrder);
|
||||
assert.strictEqual(obj.editable, notebookDocumentMetadataDefaults.editable);
|
||||
|
|
Loading…
Reference in a new issue