未验证 提交 5abb87f9 编写于 作者: P Peng Lyu 提交者: GitHub

Merge pull request #102735 from rebornix/rebornix/multi-kernel

Multi kernel support in Notebook
......@@ -125,7 +125,7 @@ suite('Notebook API tests', () => {
await firstEditorClose;
});
test('editor open/close event', async function () {
test('editor open/close event 2', async function () {
const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
let count = 0;
const disposables: vscode.Disposable[] = [];
......
......@@ -1823,17 +1823,36 @@ declare module 'vscode' {
export interface NotebookKernel {
label: string;
description?: string;
isPreferred?: boolean;
preloads?: Uri[];
executeCell(document: NotebookDocument, cell: NotebookCell, token: CancellationToken): Promise<void>;
executeAllCells(document: NotebookDocument, token: CancellationToken): Promise<void>;
}
export interface NotebookDocumentFilter {
viewType?: string;
filenamePattern?: GlobPattern;
excludeFileNamePattern?: GlobPattern;
}
export interface NotebookKernelProvider<T extends NotebookKernel = NotebookKernel> {
onDidChangeKernels?: Event<void>;
provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult<T[]>;
resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult<void>;
}
export namespace notebook {
export function registerNotebookContentProvider(
notebookType: string,
provider: NotebookContentProvider
): Disposable;
export function registerNotebookKernelProvider(
selector: NotebookDocumentFilter,
provider: NotebookKernelProvider
): Disposable;
export function registerNotebookKernel(
id: string,
selectors: GlobPattern[],
......@@ -1870,6 +1889,9 @@ declare module 'vscode' {
* @param selector
*/
export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument;
export let activeNotebookKernel: NotebookKernel | undefined;
export const onDidChangeActiveNotebookKernel: Event<void>;
}
//#endregion
......
......@@ -10,7 +10,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx
import { Disposable, IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, INotebookKernelInfo, INotebookKernelInfoDto, INotebookTextModelBackup, IEditor, INotebookRendererInfo, IOutputRenderRequest, IOutputRenderResponse } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, INotebookKernelInfo, INotebookKernelInfoDto, INotebookTextModelBackup, IEditor, INotebookRendererInfo, IOutputRenderRequest, IOutputRenderResponse, INotebookDocumentFilter } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
......@@ -22,6 +22,7 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IUndoRedoService, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { Emitter } from 'vs/base/common/event';
export class MainThreadNotebookDocument extends Disposable {
private _textModel: NotebookTextModel;
......@@ -204,6 +205,7 @@ class DocumentAndEditorState {
export class MainThreadNotebooks extends Disposable implements MainThreadNotebookShape {
private readonly _notebookProviders = new Map<string, MainThreadNotebookController>();
private readonly _notebookKernels = new Map<string, MainThreadNotebookKernel>();
private readonly _notebookKernelProviders = new Map<number, { extension: NotebookExtensionDescription, emitter: Emitter<void>, provider: IDisposable }>();
private readonly _notebookRenderers = new Map<string, MainThreadNotebookRenderer>();
private readonly _proxy: ExtHostNotebookShape;
private _toDisposeOnEditorRemove = new Map<string, IDisposable>();
......@@ -456,6 +458,47 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
return;
}
async $registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise<void> {
const emitter = new Emitter<void>();
const that = this;
const provider = this._notebookService.registerNotebookKernelProvider({
onDidChangeKernels: emitter.event,
selector: documentFilter,
provideKernels: (uri: URI, token: CancellationToken) => {
return that._proxy.$provideNotebookKernels(handle, uri, token);
},
resolveKernel: (editorId: string, uri: URI, kernelId: string, token: CancellationToken) => {
return that._proxy.$resolveNotebookKernel(handle, editorId, uri, kernelId, token);
},
executeNotebook: (uri: URI, kernelId: string, cellHandle: number | undefined, token: CancellationToken) => {
return that._proxy.$executeNotebookKernelFromProvider(handle, uri, kernelId, cellHandle, token);
}
});
this._notebookKernelProviders.set(handle, {
extension,
emitter,
provider
});
return;
}
async $unregisterNotebookKernelProvider(handle: number): Promise<void> {
const entry = this._notebookKernelProviders.get(handle);
if (entry) {
entry.emitter.dispose();
entry.provider.dispose();
this._notebookKernelProviders.delete(handle);
}
}
$onNotebookKernelChange(handle: number): void {
const entry = this._notebookKernelProviders.get(handle);
entry?.emitter.fire();
}
async $updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void> {
let controller = this._notebookProviders.get(viewType);
......@@ -485,8 +528,8 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
await controller?.spliceNotebookCellOutputs(resource, cellHandle, splices, renderers);
}
async executeNotebook(viewType: string, uri: URI, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
return this._proxy.$executeNotebook(viewType, uri, undefined, useAttachedKernel, token);
async executeNotebookByAttachedKernel(viewType: string, uri: URI, token: CancellationToken): Promise<void> {
return this._proxy.$executeNotebookByAttachedKernel(viewType, uri, undefined, token);
}
async $postMessage(editorId: string, forRendererId: string | undefined, value: any): Promise<boolean> {
......@@ -651,8 +694,8 @@ export class MainThreadNotebookController implements IMainNotebookController {
await mainthreadNotebook?.spliceNotebookCellOutputs(cellHandle, splices);
}
async executeNotebook(viewType: string, uri: URI, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
return this._mainThreadNotebook.executeNotebook(viewType, uri, useAttachedKernel, token);
async executeNotebookByAttachedKernel(viewType: string, uri: URI, token: CancellationToken): Promise<void> {
return this._mainThreadNotebook.executeNotebookByAttachedKernel(viewType, uri, token);
}
onDidReceiveMessage(editorId: string, rendererType: string | undefined, message: unknown): void {
......@@ -699,8 +742,8 @@ export class MainThreadNotebookController implements IMainNotebookController {
document?.textModel.updateNotebookCellMetadata(handle, metadata);
}
async executeNotebookCell(uri: URI, handle: number, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
return this._proxy.$executeNotebook(this._viewType, uri, handle, useAttachedKernel, token);
async executeNotebookCell(uri: URI, handle: number, token: CancellationToken): Promise<void> {
return this._proxy.$executeNotebookByAttachedKernel(this._viewType, uri, handle, token);
}
async save(uri: URI, token: CancellationToken): Promise<boolean> {
......
......@@ -933,6 +933,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeVisibleNotebookEditors;
},
get activeNotebookKernel() {
checkProposedApiEnabled(extension);
return extHostNotebook.activeNotebookKernel;
},
get onDidChangeActiveNotebookKernel() {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeActiveNotebookKernel;
},
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider);
......@@ -941,6 +949,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookKernel(extension, id, selector, kernel);
},
registerNotebookKernelProvider: (selector: vscode.NotebookDocumentFilter, provider: vscode.NotebookKernelProvider) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookKernelProvider(extension, selector, provider);
},
registerNotebookOutputRenderer: (type: string, outputFilter: vscode.NotebookOutputSelector, renderer: vscode.NotebookOutputRenderer) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookOutputRenderer(type, extension, outputFilter, renderer);
......
......@@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
import { revive } from 'vs/base/common/marshalling';
import { INotebookMimeTypeSelector, IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, IOutputRenderRequest, IOutputRenderResponse } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookMimeTypeSelector, IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, IOutputRenderRequest, IOutputRenderResponse, INotebookDocumentFilter, INotebookKernelInfoDto2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { Dto } from 'vs/base/common/types';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
......@@ -704,6 +704,9 @@ export interface MainThreadNotebookShape extends IDisposable {
$registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, preloads: UriComponents[]): Promise<void>;
$unregisterNotebookRenderer(id: string): Promise<void>;
$registerNotebookKernel(extension: NotebookExtensionDescription, id: string, label: string, selectors: (string | IRelativePattern)[], preloads: UriComponents[]): Promise<void>;
$registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise<void>;
$unregisterNotebookKernelProvider(handle: number): Promise<void>;
$onNotebookKernelChange(handle: number): void;
$unregisterNotebookKernel(id: string): Promise<void>;
$tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise<boolean>;
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void>;
......@@ -1611,7 +1614,10 @@ export interface INotebookDocumentsAndEditorsDelta {
export interface ExtHostNotebookShape {
$resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise<NotebookDataDto | undefined>;
$resolveNotebookEditor(viewType: string, uri: UriComponents, editorId: string): Promise<void>;
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void>;
$provideNotebookKernels(handle: number, uri: UriComponents, token: CancellationToken): Promise<INotebookKernelInfoDto2[]>;
$resolveNotebookKernel(handle: number, editorId: string, uri: UriComponents, kernelId: string, token: CancellationToken): Promise<void>;
$executeNotebookByAttachedKernel(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
$executeNotebookKernelFromProvider(handle: number, uri: UriComponents, kernelId: string, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
$executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
$saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean>;
$saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean>;
......
......@@ -9,11 +9,12 @@ import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { ISplice } from 'vs/base/common/sequence';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as UUID from 'vs/base/common/uuid';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { CellKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData, INotebookDocumentsAndEditorsDelta } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { CellEditType, diff, ICellEditOperation, ICellInsertEdit, INotebookDisplayOrder, INotebookEditData, NotebookCellsChangedEvent, NotebookCellsSplice2, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto, IOutputRenderRequest, IOutputRenderResponse, IOutputRenderResponseOutputInfo, IOutputRenderResponseCellInfo, IRawOutput, CellOutputKind, IProcessedOutput, IMainCellDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellEditType, diff, ICellEditOperation, ICellInsertEdit, INotebookDisplayOrder, INotebookEditData, NotebookCellsChangedEvent, NotebookCellsSplice2, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto, IOutputRenderRequest, IOutputRenderResponse, IOutputRenderResponseOutputInfo, IOutputRenderResponseCellInfo, IRawOutput, CellOutputKind, IProcessedOutput, INotebookKernelInfoDto2, IMainCellDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
......@@ -24,7 +25,6 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa
import { joinPath } from 'vs/base/common/resources';
import { Schemas } from 'vs/base/common/network';
import { hash } from 'vs/base/common/hash';
import { generateUuid } from 'vs/base/common/uuid';
import { Cache } from './cache';
interface IObservable<T> {
......@@ -54,7 +54,7 @@ interface INotebookEventEmitter {
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void;
}
const addIdToOutput = (output: IRawOutput, id = generateUuid()): IProcessedOutput => output.outputKind === CellOutputKind.Rich
const addIdToOutput = (output: IRawOutput, id = UUID.generateUuid()): IProcessedOutput => output.outputKind === CellOutputKind.Rich
? ({ ...output, outputId: id }) : output;
class DettachedCellDocumentData extends ExtHostDocumentData {
......@@ -152,7 +152,7 @@ export class ExtHostCell extends Disposable implements vscode.NotebookCell {
start: diff.start,
toInsert: diff.toInsert.map((output): IProcessedOutput => {
if (output.outputKind === CellOutputKind.Rich) {
const uuid = generateUuid();
const uuid = UUID.generateUuid();
this._outputMapping.set(output, uuid);
return { ...output, outputId: uuid };
}
......@@ -745,10 +745,89 @@ export interface ExtHostNotebookOutputRenderingHandler {
findBestMatchedRenderer(mimeType: string): ExtHostNotebookOutputRenderer[];
}
export class ExtHostNotebookKernelProviderAdapter extends Disposable {
private _kernelToId = new Map<vscode.NotebookKernel, string>();
private _idToKernel = new Map<string, vscode.NotebookKernel>();
constructor(
private readonly _proxy: MainThreadNotebookShape,
private readonly _handle: number,
private readonly _extension: IExtensionDescription,
private readonly _provider: vscode.NotebookKernelProvider
) {
super();
if (this._provider.onDidChangeKernels) {
this._register(this._provider.onDidChangeKernels(() => {
this._proxy.$onNotebookKernelChange(this._handle);
}));
}
}
async provideKernels(document: ExtHostNotebookDocument, token: vscode.CancellationToken): Promise<INotebookKernelInfoDto2[]> {
const data = await this._provider.provideKernels(document, token) || [];
const newMap = new Map<vscode.NotebookKernel, string>();
const transformedData: INotebookKernelInfoDto2[] = data.map(kernel => {
let id = this._kernelToId.get(kernel);
if (id === undefined) {
id = UUID.generateUuid();
this._kernelToId.set(kernel, id);
}
newMap.set(kernel, id);
return {
id,
label: kernel.label,
extension: this._extension.identifier,
extensionLocation: this._extension.extensionLocation,
description: kernel.description,
isPreferred: kernel.isPreferred,
preloads: kernel.preloads
};
});
this._kernelToId = newMap;
this._idToKernel.clear();
this._kernelToId.forEach((value, key) => {
this._idToKernel.set(value, key);
});
return transformedData;
}
async resolveNotebook(kernelId: string, document: ExtHostNotebookDocument, webview: vscode.NotebookCommunication, token: CancellationToken) {
const kernel = this._idToKernel.get(kernelId);
if (kernel && this._provider.resolveKernel) {
return this._provider.resolveKernel(kernel, document, webview, token);
}
}
async executeNotebook(kernelId: string, document: ExtHostNotebookDocument, cell: ExtHostCell | undefined, token: CancellationToken) {
const kernel = this._idToKernel.get(kernelId);
if (!kernel) {
return;
}
if (cell) {
return kernel.executeCell(document, cell, token);
} else {
return kernel.executeAllCells(document, token);
}
}
}
export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostNotebookOutputRenderingHandler {
private static _notebookKernelProviderHandlePool: number = 0;
private readonly _proxy: MainThreadNotebookShape;
private readonly _notebookContentProviders = new Map<string, { readonly provider: vscode.NotebookContentProvider, readonly extension: IExtensionDescription; }>();
private readonly _notebookKernels = new Map<string, { readonly kernel: vscode.NotebookKernel, readonly extension: IExtensionDescription; }>();
private readonly _notebookKernelProviders = new Map<number, ExtHostNotebookKernelProviderAdapter>();
private readonly _documents = new Map<string, ExtHostNotebookDocument>();
private readonly _unInitializedDocuments = new Map<string, ExtHostNotebookDocument>();
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor }>();
......@@ -785,6 +864,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
private _onDidCloseNotebookDocument = new Emitter<vscode.NotebookDocument>();
onDidCloseNotebookDocument: Event<vscode.NotebookDocument> = this._onDidCloseNotebookDocument.event;
visibleNotebookEditors: ExtHostNotebookEditor[] = [];
activeNotebookKernel?: vscode.NotebookKernel;
private _onDidChangeActiveNotebookKernel = new Emitter<void>();
onDidChangeActiveNotebookKernel = this._onDidChangeActiveNotebookKernel.event;
private _onDidChangeVisibleNotebookEditors = new Emitter<vscode.NotebookEditor[]>();
onDidChangeVisibleNotebookEditors = this._onDidChangeVisibleNotebookEditors.event;
......@@ -963,6 +1046,55 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
});
}
registerNotebookKernelProvider(extension: IExtensionDescription, selector: vscode.NotebookDocumentFilter, provider: vscode.NotebookKernelProvider) {
const handle = ExtHostNotebookController._notebookKernelProviderHandlePool++;
const adapter = new ExtHostNotebookKernelProviderAdapter(this._proxy, handle, extension, provider);
this._notebookKernelProviders.set(handle, adapter);
this._proxy.$registerNotebookKernelProvider({ id: extension.identifier, location: extension.extensionLocation }, handle, {
viewType: selector.viewType,
filenamePattern: selector.filenamePattern ? typeConverters.GlobPattern.from(selector.filenamePattern) : undefined,
excludeFileNamePattern: selector.excludeFileNamePattern ? typeConverters.GlobPattern.from(selector.excludeFileNamePattern) : undefined,
});
return new extHostTypes.Disposable(() => {
adapter.dispose();
this._notebookKernelProviders.delete(handle);
this._proxy.$unregisterNotebookKernelProvider(handle);
});
}
private _withAdapter<T>(handle: number, uri: UriComponents, callback: (adapter: ExtHostNotebookKernelProviderAdapter, document: ExtHostNotebookDocument) => Promise<T>) {
const document = this._documents.get(URI.revive(uri).toString());
if (!document) {
return [];
}
const provider = this._notebookKernelProviders.get(handle);
if (!provider) {
return [];
}
return callback(provider, document);
}
async $provideNotebookKernels(handle: number, uri: UriComponents, token: CancellationToken): Promise<INotebookKernelInfoDto2[]> {
return this._withAdapter<INotebookKernelInfoDto2[]>(handle, uri, (adapter, document) => {
return adapter.provideKernels(document, token);
});
}
async $resolveNotebookKernel(handle: number, editorId: string, uri: UriComponents, kernelId: string, token: CancellationToken): Promise<void> {
await this._withAdapter<void>(handle, uri, async (adapter, document) => {
let webComm = this._webviewComm.get(editorId);
if (webComm) {
await adapter.resolveNotebook(kernelId, document, webComm.contentProviderComm, token);
}
});
}
registerNotebookKernel(extension: IExtensionDescription, id: string, selectors: vscode.GlobPattern[], kernel: vscode.NotebookKernel): vscode.Disposable {
if (this._notebookKernels.has(id)) {
throw new Error(`Notebook kernel for '${id}' already registered`);
......@@ -1066,7 +1198,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
}
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
async $executeNotebookByAttachedKernel(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
let document = this._documents.get(URI.revive(uri).toString());
if (!document) {
......@@ -1077,7 +1209,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
const cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
const provider = this._notebookContentProviders.get(viewType)!.provider;
if (provider.kernel && useAttachedKernel) {
if (provider.kernel) {
if (cell) {
return provider.kernel.executeCell(document, cell, token);
} else {
......@@ -1087,6 +1219,14 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
}
async $executeNotebookKernelFromProvider(handle: number, uri: UriComponents, kernelId: string, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
await this._withAdapter(handle, uri, async (adapter, document) => {
let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
return adapter.executeNotebook(kernelId, document, cell, token);
});
}
async $executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
let document = this._documents.get(URI.revive(uri).toString());
......
......@@ -4,13 +4,21 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { Registry } from 'vs/platform/registry/common/platform';
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { INotebookActionContext, NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
import { INotebookEditor, NOTEBOOK_HAS_MULTIPLE_KERNELS, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { INotebookActionContext, NOTEBOOK_ACTIONS_CATEGORY, getActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
import { INotebookEditor, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { INotebookKernelInfo2, INotebookKernelInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/common/statusbar';
registerAction2(class extends Action2 {
......@@ -21,12 +29,6 @@ registerAction2(class extends Action2 {
title: { value: nls.localize('notebookActions.selectKernel', "Select Notebook Kernel"), original: 'Select Notebook Kernel' },
precondition: NOTEBOOK_IS_ACTIVE_EDITOR,
icon: { id: 'codicon/server-environment' },
menu: {
id: MenuId.EditorTitle,
when: NOTEBOOK_HAS_MULTIPLE_KERNELS,
group: 'navigation',
order: -2,
},
f1: true
});
}
......@@ -43,17 +45,25 @@ registerAction2(class extends Action2 {
const editor = editorService.activeEditorPane?.getControl() as INotebookEditor;
const activeKernel = editor.activeKernel;
const tokenSource = new CancellationTokenSource();
const availableKernels2 = await notebookService.getContributedNotebookKernels2(editor.viewModel!.viewType, editor.viewModel!.uri, tokenSource.token);
const availableKernels = notebookService.getContributedNotebookKernels(editor.viewModel!.viewType, editor.viewModel!.uri);
const picks: QuickPickInput<IQuickPickItem & { run(): void; }>[] = availableKernels.map((a) => {
const picks: QuickPickInput<IQuickPickItem & { run(): void; }>[] = [...availableKernels2, ...availableKernels].map((a) => {
return {
id: a.id,
label: a.label,
picked: a.id === activeKernel?.id,
description: a.extension.value + (a.id === activeKernel?.id
? nls.localize('currentActiveKernel', " (Currently Active)")
: ''),
run: () => {
description:
(a as INotebookKernelInfo2).description
? (a as INotebookKernelInfo2).description
: a.extension.value + (a.id === activeKernel?.id
? nls.localize('currentActiveKernel', " (Currently Active)")
: ''),
run: async () => {
editor.activeKernel = a;
if ((a as any).resolve) {
(a as INotebookKernelInfo2).resolve(editor.uri!, editor.getId(), tokenSource.token);
}
}
};
});
......@@ -75,7 +85,58 @@ registerAction2(class extends Action2 {
}
const action = await quickInputService.pick(picks, { placeHolder: nls.localize('pickAction', "Select Action"), matchOnDetail: true });
tokenSource.dispose();
return action?.run();
}
});
export class KernelStatus extends Disposable implements IWorkbenchContribution {
private _editorDisposable = new DisposableStore();
private readonly kernelInfoElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
constructor(
@IEditorService private readonly _editorService: IEditorService,
@INotebookService private readonly _notebookService: INotebookService,
@IStatusbarService private readonly _statusbarService: IStatusbarService,
) {
super();
this.registerListeners();
}
registerListeners() {
this._register(this._editorService.onDidActiveEditorChange(() => this.updateStatusbar()));
this._register(this._notebookService.onDidChangeActiveEditor(() => this.updateStatusbar()));
this._register(this._notebookService.onDidChangeKernels(() => this.updateStatusbar()));
}
updateStatusbar() {
this._editorDisposable.clear();
const activeEditor = getActiveNotebookEditor(this._editorService);
if (activeEditor && activeEditor.multipleKernelsAvailable) {
this.showKernelStatus(activeEditor.activeKernel);
this._editorDisposable.add(activeEditor.onDidChangeKernel(() => {
if (activeEditor.multipleKernelsAvailable) {
this.showKernelStatus(activeEditor.activeKernel);
} else {
this.kernelInfoElement.clear();
}
}));
} else {
this.kernelInfoElement.clear();
}
}
showKernelStatus(kernel: INotebookKernelInfo | INotebookKernelInfo2 | undefined) {
this.kernelInfoElement.value = this._statusbarService.addEntry({
text: kernel ? kernel.label : 'Choose Kernel',
ariaLabel: kernel ? kernel.label : 'Choose Kernel',
tooltip: nls.localize('chooseActiveKernel', "Choose kernel for current notebook"),
command: 'notebook.selectKernel',
}, 'notebook.selectKernel', nls.localize('notebook.selectKernel', "Choose kernel for current notebook"), StatusbarAlignment.RIGHT, 100);
}
}
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(KernelStatus, LifecyclePhase.Ready);
......@@ -23,7 +23,7 @@ import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/outpu
import { CellLanguageStatusBarItem, TimerRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { CellKind, IProcessedOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata, INotebookKernelInfo, IEditor } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellKind, IProcessedOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata, INotebookKernelInfo, IEditor, INotebookKernelInfo2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { IMenu } from 'vs/platform/actions/common/actions';
......@@ -172,7 +172,8 @@ export interface INotebookEditor extends IEditor {
readonly onDidChangeModel: Event<NotebookTextModel | undefined>;
readonly onDidFocusEditorWidget: Event<void>;
isNotebookEditor: boolean;
activeKernel: INotebookKernelInfo | undefined;
activeKernel: INotebookKernelInfo | INotebookKernelInfo2 | undefined;
multipleKernelsAvailable: boolean;
readonly onDidChangeKernel: Event<void>;
isDisposed: boolean;
......
......@@ -37,7 +37,7 @@ import { CellDragAndDropController, CodeCellRenderer, MarkdownCellRenderer, Note
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind, IProcessedOutput, INotebookKernelInfo, INotebookKernelInfoDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellKind, IProcessedOutput, INotebookKernelInfo, INotebookKernelInfoDto, INotebookKernelInfo2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
......@@ -132,7 +132,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
return this._notebookViewModel?.notebookDocument;
}
private _activeKernel: INotebookKernelInfo | undefined = undefined;
private _activeKernel: INotebookKernelInfo | INotebookKernelInfo2 | undefined = undefined;
private readonly _onDidChangeKernel = this._register(new Emitter<void>());
readonly onDidChangeKernel: Event<void> = this._onDidChangeKernel.event;
......@@ -140,7 +140,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
return this._activeKernel;
}
set activeKernel(kernel: INotebookKernelInfo | undefined) {
set activeKernel(kernel: INotebookKernelInfo | INotebookKernelInfo2 | undefined) {
if (this._isDisposed) {
return;
}
......@@ -149,6 +149,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this._onDidChangeKernel.fire();
}
private _currentKernelTokenSource: CancellationTokenSource | undefined = undefined;
multipleKernelsAvailable: boolean = false;
private readonly _onDidChangeActiveEditor = this._register(new Emitter<this>());
readonly onDidChangeActiveEditor: Event<this> = this._onDidChangeActiveEditor.event;
......@@ -197,6 +200,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this.notebookService.addNotebookEditor(this);
}
/**
* EditorId
*/
public getId(): string {
return this._uuid;
}
......@@ -476,11 +482,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
// clear state
this._dndController?.clearGlobalDragState();
this._setKernels(textModel);
this._currentKernelTokenSource = new CancellationTokenSource();
this._localStore.add(this._currentKernelTokenSource);
await this._setKernels(textModel, this._currentKernelTokenSource);
this._localStore.add(this.notebookService.onDidChangeKernels(() => {
this._localStore.add(this.notebookService.onDidChangeKernels(async () => {
if (this.activeKernel === undefined) {
this._setKernels(textModel);
this._currentKernelTokenSource?.cancel();
this._currentKernelTokenSource = new CancellationTokenSource();
await this._setKernels(textModel, this._currentKernelTokenSource);
}
}));
......@@ -552,16 +562,20 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this._list?.clear();
}
private _setKernels(textModel: NotebookTextModel) {
private async _setKernels(textModel: NotebookTextModel, tokenSource: CancellationTokenSource) {
const provider = this.notebookService.getContributedNotebookProviders(this.viewModel!.uri)[0];
const availableKernels2 = await this.notebookService.getContributedNotebookKernels2(textModel.viewType, textModel.uri, tokenSource.token);
const availableKernels = this.notebookService.getContributedNotebookKernels(textModel.viewType, textModel.uri);
if (provider.kernel && availableKernels.length > 0) {
if (provider.kernel && (availableKernels.length + availableKernels2.length) > 0) {
this._notebookHasMultipleKernels!.set(true);
} else if (availableKernels.length > 1) {
this.multipleKernelsAvailable = true;
} else if ((availableKernels.length + availableKernels2.length) > 1) {
this._notebookHasMultipleKernels!.set(true);
this.multipleKernelsAvailable = true;
} else {
this._notebookHasMultipleKernels!.set(false);
this.multipleKernelsAvailable = false;
}
if (provider && provider.kernel) {
......@@ -570,6 +584,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
return;
}
// choose a preferred kernel
const kernelsFromSameExtension = availableKernels2.filter(kernel => kernel.extension.value === provider.providerId);
if (kernelsFromSameExtension.length) {
const preferedKernel = kernelsFromSameExtension.find(kernel => kernel.isPreferred) || kernelsFromSameExtension[0];
this.activeKernel = preferedKernel;
await preferedKernel.resolve(this.viewModel!.uri, this.getId(), tokenSource.token);
return;
}
// the provider doesn't have a builtin kernel, choose a kernel
this.activeKernel = availableKernels[0];
if (this.activeKernel) {
......@@ -1138,11 +1162,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
const notebookUri = this._notebookViewModel!.uri;
if (this._activeKernel) {
await this.notebookService.executeNotebook2(this._notebookViewModel!.viewType, this._notebookViewModel!.uri, this._activeKernel.id, tokenSource.token);
// TODO@rebornix temp any cast, should be removed once we remove legacy kernel support
if ((this._activeKernel as INotebookKernelInfo2).executeNotebookCell) {
await (this._activeKernel as INotebookKernelInfo2).executeNotebookCell!(this._notebookViewModel!.uri, undefined, tokenSource.token);
} else {
await this.notebookService.executeNotebook2(this._notebookViewModel!.viewType, this._notebookViewModel!.uri, this._activeKernel.id, tokenSource.token);
}
} else if (provider.kernel) {
return await this.notebookService.executeNotebook(viewType, notebookUri, true, tokenSource.token);
} else {
return await this.notebookService.executeNotebook(viewType, notebookUri, false, tokenSource.token);
return await this.notebookService.executeNotebook(viewType, notebookUri, tokenSource.token);
}
}
......@@ -1190,11 +1217,15 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
const notebookUri = this._notebookViewModel!.uri;
if (this._activeKernel) {
return await this.notebookService.executeNotebookCell2(viewType, notebookUri, cell.handle, this._activeKernel.id, tokenSource.token);
// TODO@rebornix temp any cast, should be removed once we remove legacy kernel support
if ((this._activeKernel as INotebookKernelInfo2).executeNotebookCell) {
await (this._activeKernel as INotebookKernelInfo2).executeNotebookCell!(this._notebookViewModel!.uri, cell.handle, tokenSource.token);
} else {
return await this.notebookService.executeNotebookCell2(viewType, notebookUri, cell.handle, this._activeKernel.id, tokenSource.token);
}
} else if (provider.kernel) {
return await this.notebookService.executeNotebookCell(viewType, notebookUri, cell.handle, true, tokenSource.token);
} else {
return await this.notebookService.executeNotebookCell(viewType, notebookUri, cell.handle, false, tokenSource.token);
return await this.notebookService.executeNotebookCell(viewType, notebookUri, cell.handle, tokenSource.token);
}
}
} finally {
......
......@@ -4,13 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { Disposable, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { notebookProviderExtensionPoint, notebookRendererExtensionPoint, INotebookEditorContribution } from 'vs/workbench/contrib/notebook/browser/extensionPoint';
import { NotebookProviderInfo, NotebookEditorDescriptor } from 'vs/workbench/contrib/notebook/common/notebookProvider';
import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.protocol';
import { Emitter, Event } from 'vs/base/common/event';
import { INotebookTextModel, INotebookRendererInfo, NotebookDocumentMetadata, ICellDto2, INotebookKernelInfo, CellOutputKind, ITransformedDisplayOutputDto, IDisplayOutput, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes, IOrderedMimeType, mimeTypeSupportedByCore, IOutputRenderRequestOutputInfo, IOutputRenderRequestCellInfo, NotebookCellOutputsSplice, ICellEditOperation, CellEditType, ICellInsertEdit, IOutputRenderResponse, IProcessedOutput, BUILTIN_RENDERER_ID, NotebookEditorPriority } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookTextModel, INotebookRendererInfo, NotebookDocumentMetadata, ICellDto2, INotebookKernelInfo, CellOutputKind, ITransformedDisplayOutputDto, IDisplayOutput, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes, IOrderedMimeType, mimeTypeSupportedByCore, IOutputRenderRequestOutputInfo, IOutputRenderRequestCellInfo, NotebookCellOutputsSplice, ICellEditOperation, CellEditType, ICellInsertEdit, IOutputRenderResponse, IProcessedOutput, BUILTIN_RENDERER_ID, NotebookEditorPriority, INotebookKernelProvider, notebookDocumentFilterMatch, INotebookKernelInfo2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer';
import { Iterable } from 'vs/base/common/iterator';
......@@ -28,6 +28,7 @@ import { Memento } from 'vs/workbench/common/memento';
import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { generateUuid } from 'vs/base/common/uuid';
import { flatten } from 'vs/base/common/arrays';
function MODEL_ID(resource: URI): string {
return resource.toString();
......@@ -74,6 +75,7 @@ export class NotebookProviderInfoStore extends Disposable {
displayName: notebookContribution.displayName,
selector: notebookContribution.selector || [],
priority: this._convertPriority(notebookContribution.priority),
providerId: extension.description.identifier.value,
providerDisplayName: extension.description.isBuiltin ? nls.localize('builtinProviderDisplayName', "Built-in") : extension.description.displayName || extension.description.identifier.value,
providerExtensionLocation: extension.description.extensionLocation
}));
......@@ -193,6 +195,7 @@ export class NotebookService extends Disposable implements INotebookService, ICu
private _lastClipboardIsCopy: boolean = true;
private _displayOrder: { userOrder: string[], defaultOrder: string[] } = Object.create(null);
private readonly _notebookKernelProviders: INotebookKernelProvider[] = [];
constructor(
@IExtensionService private readonly _extensionService: IExtensionService,
......@@ -297,6 +300,50 @@ export class NotebookService extends Disposable implements INotebookService, ICu
this._onDidChangeKernels.fire();
}
registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable {
this._notebookKernelProviders.push(provider);
const kernelChangeEventListener = provider.onDidChangeKernels(() => {
this._onDidChangeKernels.fire();
});
return toDisposable(() => {
kernelChangeEventListener.dispose();
let idx = this._notebookKernelProviders.indexOf(provider);
if (idx >= 0) {
this._notebookKernelProviders.splice(idx, 1);
}
});
}
async getContributedNotebookKernels2(viewType: string, resource: URI, token: CancellationToken): Promise<INotebookKernelInfo2[]> {
const filteredProvider = this._notebookKernelProviders.filter(provider => notebookDocumentFilterMatch(provider.selector, viewType, resource));
const result = new Array<INotebookKernelInfo2[]>(filteredProvider.length);
const promises = filteredProvider.map(async (provider, index) => {
const data = await provider.provideKernels(resource, token);
result[index] = data.map(dto => {
return {
extension: dto.extension,
extensionLocation: dto.extensionLocation,
id: dto.id,
label: dto.label,
description: dto.description,
isPreferred: dto.isPreferred,
preloads: dto.preloads,
resolve: async (uri: URI, editorId: string, token: CancellationToken) => {
return provider.resolveKernel(editorId, uri, dto.id, token);
},
executeNotebookCell: async (uri: URI, handle: number | undefined, token: CancellationToken) => {
return provider.executeNotebook(uri, dto.id, handle, token);
}
};
});
});
await Promise.all(promises);
return flatten(result);
}
getContributedNotebookKernels(viewType: string, resource: URI): INotebookKernelInfo[] {
let kernelInfos: INotebookKernelInfo[] = [];
this._notebookKernels.forEach(kernel => {
......@@ -630,20 +677,20 @@ export class NotebookService extends Disposable implements INotebookService, ICu
return this.notebookRenderersInfoStore.getContributedRenderer(mimeType);
}
async executeNotebook(viewType: string, uri: URI, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
async executeNotebook(viewType: string, uri: URI, token: CancellationToken): Promise<void> {
let provider = this._notebookProviders.get(viewType);
if (provider) {
return provider.controller.executeNotebook(viewType, uri, useAttachedKernel, token);
return provider.controller.executeNotebookByAttachedKernel(viewType, uri, token);
}
return;
}
async executeNotebookCell(viewType: string, uri: URI, handle: number, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
async executeNotebookCell(viewType: string, uri: URI, handle: number, token: CancellationToken): Promise<void> {
const provider = this._notebookProviders.get(viewType);
if (provider) {
await provider.controller.executeNotebookCell(uri, handle, useAttachedKernel, token);
await provider.controller.executeNotebookCell(uri, handle, token);
}
}
......
......@@ -14,10 +14,10 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { GlobPattern } from 'vs/workbench/api/common/extHost.protocol';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Schemas } from 'vs/base/common/network';
import { IRevertOptions } from 'vs/workbench/common/editor';
import { basename } from 'vs/base/common/path';
export enum CellKind {
Markdown = 1,
......@@ -69,7 +69,7 @@ export interface NotebookDocumentMetadata {
cellEditable: boolean;
cellRunnable: boolean;
cellHasExecutionOrder: boolean;
displayOrder?: GlobPattern[];
displayOrder?: (string | glob.IRelativePattern)[];
custom?: { [key: string]: unknown };
}
......@@ -608,3 +608,53 @@ export interface INotebookSearchOptions {
caseSensitive?: boolean
wordSeparators?: string;
}
export interface INotebookDocumentFilter {
viewType?: string;
filenamePattern?: string | glob.IRelativePattern;
excludeFileNamePattern?: string | glob.IRelativePattern;
}
//TODO@rebornix test
export function notebookDocumentFilterMatch(filter: INotebookDocumentFilter, viewType: string, resource: URI): boolean {
if (filter.viewType === viewType) {
return true;
}
if (filter.filenamePattern) {
if (glob.match(filter.filenamePattern, basename(resource.fsPath).toLowerCase())) {
if (filter.excludeFileNamePattern) {
if (glob.match(filter.excludeFileNamePattern, basename(resource.fsPath).toLowerCase())) {
// should exclude
return false;
}
}
return true;
}
}
return false;
}
export interface INotebookKernelInfoDto2 {
id: string;
label: string;
extension: ExtensionIdentifier;
extensionLocation: URI;
description?: string;
isPreferred?: boolean;
preloads?: UriComponents[];
}
export interface INotebookKernelInfo2 extends INotebookKernelInfoDto2 {
resolve(uri: URI, editorId: string, token: CancellationToken): Promise<void>;
executeNotebookCell?(uri: URI, handle: number | undefined, token: CancellationToken): Promise<void>;
}
export interface INotebookKernelProvider {
selector: INotebookDocumentFilter;
onDidChangeKernels: Event<void>;
provideKernels(uri: URI, token: CancellationToken): Promise<INotebookKernelInfoDto2[]>;
resolveKernel(editorId: string, uri: UriComponents, kernelId: string, token: CancellationToken): Promise<void>;
executeNotebook(uri: URI, kernelId: string, handle: number | undefined, token: CancellationToken): Promise<void>;
}
......@@ -18,6 +18,7 @@ export interface NotebookEditorDescriptor {
readonly displayName: string;
readonly selector: readonly NotebookSelector[];
readonly priority: NotebookEditorPriority;
readonly providerId?: string;
readonly providerDisplayName: string;
readonly providerExtensionLocation: URI;
kernel?: INotebookKernelInfoDto;
......@@ -29,6 +30,8 @@ export class NotebookProviderInfo implements NotebookEditorDescriptor {
readonly displayName: string;
readonly selector: readonly NotebookSelector[];
readonly priority: NotebookEditorPriority;
// it's optional as the memento might not have it
readonly providerId?: string;
readonly providerDisplayName: string;
readonly providerExtensionLocation: URI;
kernel?: INotebookKernelInfoDto;
......@@ -38,6 +41,7 @@ export class NotebookProviderInfo implements NotebookEditorDescriptor {
this.displayName = descriptor.displayName;
this.selector = descriptor.selector;
this.priority = descriptor.priority;
this.providerId = descriptor.providerId;
this.providerDisplayName = descriptor.providerDisplayName;
this.providerExtensionLocation = descriptor.providerExtensionLocation;
}
......
......@@ -8,10 +8,14 @@ import { URI } from 'vs/base/common/uri';
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.protocol';
import { Event } from 'vs/base/common/event';
import { INotebookTextModel, INotebookRendererInfo, NotebookDocumentMetadata, ICellDto2, INotebookKernelInfo, INotebookKernelInfoDto, INotebookTextModelBackup, IEditor, ICellEditOperation, NotebookCellOutputsSplice, IOrderedMimeType, IProcessedOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import {
INotebookTextModel, INotebookRendererInfo, NotebookDocumentMetadata, ICellDto2, INotebookKernelInfo, INotebookKernelInfoDto, INotebookTextModelBackup,
IEditor, ICellEditOperation, NotebookCellOutputsSplice, IOrderedMimeType, IProcessedOutput, INotebookKernelProvider, INotebookKernelInfo2
} from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CancellationToken } from 'vs/base/common/cancellation';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { IDisposable } from 'vs/base/common/lifecycle';
export const INotebookService = createDecorator<INotebookService>('notebookService');
......@@ -20,9 +24,9 @@ export interface IMainNotebookController {
kernel: INotebookKernelInfoDto | undefined;
createNotebook(viewType: string, uri: URI, backup: INotebookTextModelBackup | undefined, forceReload: boolean, editorId?: string, backupId?: string): Promise<NotebookTextModel | undefined>;
resolveNotebookEditor(viewType: string, uri: URI, editorId: string): Promise<void>;
executeNotebook(viewType: string, uri: URI, useAttachedKernel: boolean, token: CancellationToken): Promise<void>;
executeNotebookByAttachedKernel(viewType: string, uri: URI, token: CancellationToken): Promise<void>;
onDidReceiveMessage(editorId: string, rendererType: string | undefined, message: any): void;
executeNotebookCell(uri: URI, handle: number, useAttachedKernel: boolean, token: CancellationToken): Promise<void>;
executeNotebookCell(uri: URI, handle: number, token: CancellationToken): Promise<void>;
removeNotebookDocument(notebook: INotebookTextModel): Promise<void>;
save(uri: URI, token: CancellationToken): Promise<boolean>;
saveAs(uri: URI, target: URI, token: CancellationToken): Promise<boolean>;
......@@ -48,12 +52,14 @@ export interface INotebookService {
transformSingleOutput(textModel: NotebookTextModel, output: IProcessedOutput, rendererId: string, mimeType: string): Promise<IOrderedMimeType | undefined>;
registerNotebookKernel(kernel: INotebookKernelInfo): void;
unregisterNotebookKernel(id: string): void;
registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable;
getContributedNotebookKernels(viewType: string, resource: URI): readonly INotebookKernelInfo[];
getContributedNotebookKernels2(viewType: string, resource: URI, token: CancellationToken): Promise<INotebookKernelInfo2[]>;
getRendererInfo(id: string): INotebookRendererInfo | undefined;
resolveNotebook(viewType: string, uri: URI, forceReload: boolean, editorId?: string, backupId?: string): Promise<NotebookTextModel | undefined>;
createNotebookFromBackup(viewType: string, uri: URI, metadata: NotebookDocumentMetadata, languages: string[], cells: ICellDto2[], editorId?: string): Promise<NotebookTextModel | undefined>;
executeNotebook(viewType: string, uri: URI, useAttachedKernel: boolean, token: CancellationToken): Promise<void>;
executeNotebookCell(viewType: string, uri: URI, handle: number, useAttachedKernel: boolean, token: CancellationToken): Promise<void>;
executeNotebook(viewType: string, uri: URI, token: CancellationToken): Promise<void>;
executeNotebookCell(viewType: string, uri: URI, handle: number, token: CancellationToken): Promise<void>;
executeNotebook2(viewType: string, uri: URI, kernelId: string, token: CancellationToken): Promise<void>;
executeNotebookCell2(viewType: string, uri: URI, handle: number, kernelId: string, token: CancellationToken): Promise<void>;
getContributedNotebookProviders(resource: URI): readonly NotebookProviderInfo[];
......
......@@ -62,6 +62,8 @@ export class TestNotebookEditor implements INotebookEditor {
constructor(
) { }
multipleKernelsAvailable: boolean = false;
uri?: URI | undefined;
textModel?: NotebookTextModel | undefined;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册