Skip to content

Commit 4fc84b3

Browse files
committed
sketch for notebook kernel
1 parent f62bef3 commit 4fc84b3

12 files changed

Lines changed: 354 additions & 26 deletions

File tree

src/vs/vscode.proposed.d.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,17 +1835,36 @@ declare module 'vscode' {
18351835

18361836
export interface NotebookKernel {
18371837
label: string;
1838+
description?: string;
1839+
isPreferred?: boolean;
18381840
preloads?: Uri[];
18391841
executeCell(document: NotebookDocument, cell: NotebookCell, token: CancellationToken): Promise<void>;
18401842
executeAllCells(document: NotebookDocument, token: CancellationToken): Promise<void>;
18411843
}
18421844

1845+
export interface NotebookDocumentFilter {
1846+
viewType?: string;
1847+
filenamePattern?: GlobPattern;
1848+
excludeFileNamePattern?: GlobPattern;
1849+
}
1850+
1851+
export interface NotebookKernelProvider<T extends NotebookKernel = NotebookKernel> {
1852+
onDidChangeKernels?: Event<void>;
1853+
provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult<T[]>;
1854+
resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult<void>;
1855+
}
1856+
18431857
export namespace notebook {
18441858
export function registerNotebookContentProvider(
18451859
notebookType: string,
18461860
provider: NotebookContentProvider
18471861
): Disposable;
18481862

1863+
export function registerNotebookKernelProvider(
1864+
selector: NotebookDocumentFilter,
1865+
provider: NotebookKernelProvider
1866+
): Disposable;
1867+
18491868
export function registerNotebookKernel(
18501869
id: string,
18511870
selectors: GlobPattern[],
@@ -1882,6 +1901,9 @@ declare module 'vscode' {
18821901
* @param selector
18831902
*/
18841903
export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument;
1904+
1905+
export let activeNotebookKernel: NotebookKernel | undefined;
1906+
export const onDidChangeActiveNotebookKernel: Event<void>;
18851907
}
18861908

18871909
//#endregion

src/vs/workbench/api/browser/mainThreadNotebook.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx
1010
import { Disposable, IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
1111
import { URI, UriComponents } from 'vs/base/common/uri';
1212
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
13-
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';
13+
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';
1414
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1515
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
1616
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -22,6 +22,7 @@ import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
2222
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
2323
import { IUndoRedoService, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo';
2424
import { ITextModelService } from 'vs/editor/common/services/resolverService';
25+
import { Emitter } from 'vs/base/common/event';
2526

2627
export class MainThreadNotebookDocument extends Disposable {
2728
private _textModel: NotebookTextModel;
@@ -203,6 +204,7 @@ class DocumentAndEditorState {
203204
export class MainThreadNotebooks extends Disposable implements MainThreadNotebookShape {
204205
private readonly _notebookProviders = new Map<string, MainThreadNotebookController>();
205206
private readonly _notebookKernels = new Map<string, MainThreadNotebookKernel>();
207+
private readonly _notebookKernelProviders = new Map<number, { extension: NotebookExtensionDescription, emitter: Emitter<void>, provider: IDisposable }>();
206208
private readonly _notebookRenderers = new Map<string, MainThreadNotebookRenderer>();
207209
private readonly _proxy: ExtHostNotebookShape;
208210
private _toDisposeOnEditorRemove = new Map<string, IDisposable>();
@@ -455,6 +457,47 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
455457
return;
456458
}
457459

460+
async $registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise<void> {
461+
const emitter = new Emitter<void>();
462+
const that = this;
463+
const provider = this._notebookService.registerNotebookKernelProvider({
464+
onDidChangeKernels: emitter.event,
465+
selector: documentFilter,
466+
provideKernels: (uri: URI, token: CancellationToken) => {
467+
return that._proxy.$provideNotebookKernels(handle, uri, token);
468+
},
469+
resolveKernel: (editorId: string, uri: URI, kernelId: string, token: CancellationToken) => {
470+
return that._proxy.$resolveNotebookKernel(handle, editorId, uri, kernelId, token);
471+
},
472+
executeNotebook: (viewType: string, uri: URI, kernelId: string, handle: number | undefined, token: CancellationToken) => {
473+
return that._proxy.$executeNotebook2(kernelId, viewType, uri, handle, token);
474+
}
475+
});
476+
this._notebookKernelProviders.set(handle, {
477+
extension,
478+
emitter,
479+
provider
480+
});
481+
482+
return;
483+
}
484+
485+
async $unregisterNotebookKernelProvider(handle: number): Promise<void> {
486+
const entry = this._notebookKernelProviders.get(handle);
487+
488+
if (entry) {
489+
entry.emitter.dispose();
490+
entry.provider.dispose();
491+
this._notebookKernelProviders.delete(handle);
492+
}
493+
}
494+
495+
$onNotebookKernelChange(handle: number): void {
496+
const entry = this._notebookKernelProviders.get(handle);
497+
498+
entry?.emitter.fire();
499+
}
500+
458501
async $updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void> {
459502
let controller = this._notebookProviders.get(viewType);
460503

src/vs/workbench/api/common/extHost.api.impl.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
936936
checkProposedApiEnabled(extension);
937937
return extHostNotebook.onDidChangeVisibleNotebookEditors;
938938
},
939+
get activeNotebookKernel() {
940+
checkProposedApiEnabled(extension);
941+
return extHostNotebook.activeNotebookKernel;
942+
},
943+
get onDidChangeActiveNotebookKernel() {
944+
checkProposedApiEnabled(extension);
945+
return extHostNotebook.onDidChangeActiveNotebookKernel;
946+
},
939947
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider) => {
940948
checkProposedApiEnabled(extension);
941949
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider);
@@ -944,6 +952,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
944952
checkProposedApiEnabled(extension);
945953
return extHostNotebook.registerNotebookKernel(extension, id, selector, kernel);
946954
},
955+
registerNotebookKernelProvider: (selector: vscode.NotebookDocumentFilter, provider: vscode.NotebookKernelProvider) => {
956+
checkProposedApiEnabled(extension);
957+
return extHostNotebook.registerNotebookKernelProvider(extension, selector, provider);
958+
},
947959
registerNotebookOutputRenderer: (type: string, outputFilter: vscode.NotebookOutputSelector, renderer: vscode.NotebookOutputRenderer) => {
948960
checkProposedApiEnabled(extension);
949961
return extHostNotebook.registerNotebookOutputRenderer(type, extension, outputFilter, renderer);

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
5151
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
5252
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
5353
import { revive } from 'vs/base/common/marshalling';
54-
import { INotebookMimeTypeSelector, IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, IOutputRenderRequest, IOutputRenderResponse } from 'vs/workbench/contrib/notebook/common/notebookCommon';
54+
import { INotebookMimeTypeSelector, IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, IOutputRenderRequest, IOutputRenderResponse, INotebookDocumentFilter, INotebookKernelInfoDto2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
5555
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
5656
import { Dto } from 'vs/base/common/types';
5757
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
@@ -704,6 +704,9 @@ export interface MainThreadNotebookShape extends IDisposable {
704704
$registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, preloads: UriComponents[]): Promise<void>;
705705
$unregisterNotebookRenderer(id: string): Promise<void>;
706706
$registerNotebookKernel(extension: NotebookExtensionDescription, id: string, label: string, selectors: (string | IRelativePattern)[], preloads: UriComponents[]): Promise<void>;
707+
$registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise<void>;
708+
$unregisterNotebookKernelProvider(handle: number): Promise<void>;
709+
$onNotebookKernelChange(handle: number): void;
707710
$unregisterNotebookKernel(id: string): Promise<void>;
708711
$tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise<boolean>;
709712
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void>;
@@ -1611,6 +1614,8 @@ export interface INotebookDocumentsAndEditorsDelta {
16111614
export interface ExtHostNotebookShape {
16121615
$resolveNotebookData(viewType: string, uri: UriComponents, backupId?: string): Promise<NotebookDataDto | undefined>;
16131616
$resolveNotebookEditor(viewType: string, uri: UriComponents, editorId: string): Promise<void>;
1617+
$provideNotebookKernels(handle: number, uri: UriComponents, token: CancellationToken): Promise<INotebookKernelInfoDto2[]>;
1618+
$resolveNotebookKernel(handle: number, editorId: string, uri: UriComponents, kernelId: string, token: CancellationToken): Promise<void>;
16141619
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void>;
16151620
$executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
16161621
$saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean>;

src/vs/workbench/api/common/extHostNotebook.ts

Lines changed: 116 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import { Emitter, Event } from 'vs/base/common/event';
99
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
1010
import { ISplice } from 'vs/base/common/sequence';
1111
import { URI, UriComponents } from 'vs/base/common/uri';
12+
import * as UUID from 'vs/base/common/uuid';
1213
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
1314
import { CellKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData, INotebookDocumentsAndEditorsDelta } from 'vs/workbench/api/common/extHost.protocol';
1415
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
1516
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
16-
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, INotebookDisplayOrder, INotebookEditData, NotebookCellsChangedEvent, NotebookCellsSplice2, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto, IOutputRenderRequest, IOutputRenderResponse, IOutputRenderResponseOutputInfo, IOutputRenderResponseCellInfo, IRawOutput, CellOutputKind, IProcessedOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
17+
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, INotebookDisplayOrder, INotebookEditData, NotebookCellsChangedEvent, NotebookCellsSplice2, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto, IOutputRenderRequest, IOutputRenderResponse, IOutputRenderResponseOutputInfo, IOutputRenderResponseCellInfo, IRawOutput, CellOutputKind, IProcessedOutput, INotebookKernelInfoDto2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
1718
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
1819
import { CancellationToken } from 'vs/base/common/cancellation';
1920
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
@@ -24,7 +25,6 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa
2425
import { joinPath } from 'vs/base/common/resources';
2526
import { Schemas } from 'vs/base/common/network';
2627
import { hash } from 'vs/base/common/hash';
27-
import { generateUuid } from 'vs/base/common/uuid';
2828
import { Cache } from './cache';
2929

3030
interface IObservable<T> {
@@ -54,7 +54,7 @@ interface INotebookEventEmitter {
5454
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void;
5555
}
5656

57-
const addIdToOutput = (output: IRawOutput, id = generateUuid()): IProcessedOutput => output.outputKind === CellOutputKind.Rich
57+
const addIdToOutput = (output: IRawOutput, id = UUID.generateUuid()): IProcessedOutput => output.outputKind === CellOutputKind.Rich
5858
? ({ ...output, outputId: id }) : output;
5959

6060
export class ExtHostCell extends Disposable implements vscode.NotebookCell {
@@ -780,10 +780,74 @@ export interface ExtHostNotebookOutputRenderingHandler {
780780
findBestMatchedRenderer(mimeType: string): ExtHostNotebookOutputRenderer[];
781781
}
782782

783+
export class ExtHostNotebookKernelProviderAdapter extends Disposable {
784+
private _kernelToId = new Map<vscode.NotebookKernel, string>();
785+
private _idToKernel = new Map<string, vscode.NotebookKernel>();
786+
constructor(
787+
private readonly _proxy: MainThreadNotebookShape,
788+
private readonly _handle: number,
789+
private readonly _extension: IExtensionDescription,
790+
private readonly _provider: vscode.NotebookKernelProvider
791+
) {
792+
super();
793+
794+
if (this._provider.onDidChangeKernels) {
795+
this._register(this._provider.onDidChangeKernels(() => {
796+
this._proxy.$onNotebookKernelChange(this._handle);
797+
}));
798+
}
799+
}
800+
801+
async provideKernels(document: ExtHostNotebookDocument, token: vscode.CancellationToken): Promise<INotebookKernelInfoDto2[]> {
802+
const data = await this._provider.provideKernels(document, token) || [];
803+
804+
const newMap = new Map<vscode.NotebookKernel, string>();
805+
806+
const transformedData: INotebookKernelInfoDto2[] = data.map(kernel => {
807+
let id = this._kernelToId.get(kernel);
808+
if (id === undefined) {
809+
id = UUID.generateUuid();
810+
this._kernelToId.set(kernel, id);
811+
}
812+
813+
newMap.set(kernel, id);
814+
815+
return {
816+
id,
817+
label: kernel.label,
818+
extension: this._extension.identifier,
819+
description: kernel.description,
820+
isPreferred: kernel.isPreferred,
821+
preloads: kernel.preloads
822+
};
823+
});
824+
825+
this._kernelToId = newMap;
826+
827+
this._idToKernel.clear();
828+
this._kernelToId.forEach((value, key) => {
829+
this._idToKernel.set(value, key);
830+
});
831+
832+
return transformedData;
833+
}
834+
835+
async resolveNotebook(kernelId: string, document: ExtHostNotebookDocument, webview: vscode.NotebookCommunication, token: CancellationToken) {
836+
const kernel = this._idToKernel.get(kernelId);
837+
838+
if (kernel && this._provider.resolveKernel) {
839+
return this._provider.resolveKernel(kernel, document, webview, token);
840+
}
841+
}
842+
}
843+
783844
export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostNotebookOutputRenderingHandler {
845+
private static _notebookKernelProviderHandlePool: number = 0;
846+
784847
private readonly _proxy: MainThreadNotebookShape;
785848
private readonly _notebookContentProviders = new Map<string, { readonly provider: vscode.NotebookContentProvider, readonly extension: IExtensionDescription; }>();
786849
private readonly _notebookKernels = new Map<string, { readonly kernel: vscode.NotebookKernel, readonly extension: IExtensionDescription; }>();
850+
private readonly _notebookKernelProviders = new Map<number, ExtHostNotebookKernelProviderAdapter>();
787851
private readonly _documents = new Map<string, ExtHostNotebookDocument>();
788852
private readonly _unInitializedDocuments = new Map<string, ExtHostNotebookDocument>();
789853
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor }>();
@@ -820,6 +884,10 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
820884
private _onDidCloseNotebookDocument = new Emitter<vscode.NotebookDocument>();
821885
onDidCloseNotebookDocument: Event<vscode.NotebookDocument> = this._onDidCloseNotebookDocument.event;
822886
visibleNotebookEditors: ExtHostNotebookEditor[] = [];
887+
activeNotebookKernel?: vscode.NotebookKernel;
888+
889+
private _onDidChangeActiveNotebookKernel = new Emitter<void>();
890+
onDidChangeActiveNotebookKernel = this._onDidChangeActiveNotebookKernel.event;
823891
private _onDidChangeVisibleNotebookEditors = new Emitter<vscode.NotebookEditor[]>();
824892
onDidChangeVisibleNotebookEditors = this._onDidChangeVisibleNotebookEditors.event;
825893

@@ -998,6 +1066,51 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
9981066
});
9991067
}
10001068

1069+
registerNotebookKernelProvider(extension: IExtensionDescription, selector: vscode.NotebookDocumentFilter, provider: vscode.NotebookKernelProvider) {
1070+
const handle = ExtHostNotebookController._notebookKernelProviderHandlePool++;
1071+
const adapter = new ExtHostNotebookKernelProviderAdapter(this._proxy, handle, extension, provider);
1072+
this._notebookKernelProviders.set(handle, adapter);
1073+
this._proxy.$registerNotebookKernelProvider({ id: extension.identifier, location: extension.extensionLocation }, handle, selector);
1074+
1075+
return new extHostTypes.Disposable(() => {
1076+
adapter.dispose();
1077+
this._notebookKernelProviders.delete(handle);
1078+
this._proxy.$unregisterNotebookKernelProvider(handle);
1079+
});
1080+
}
1081+
1082+
private _withAdapter<T>(handle: number, uri: UriComponents, callback: (adapter: ExtHostNotebookKernelProviderAdapter, document: ExtHostNotebookDocument) => Promise<T>) {
1083+
const document = this._documents.get(URI.revive(uri).toString());
1084+
1085+
if (!document) {
1086+
return [];
1087+
}
1088+
1089+
const provider = this._notebookKernelProviders.get(handle);
1090+
1091+
if (!provider) {
1092+
return [];
1093+
}
1094+
1095+
return callback(provider, document);
1096+
}
1097+
1098+
async $provideNotebookKernels(handle: number, uri: UriComponents, token: CancellationToken): Promise<INotebookKernelInfoDto2[]> {
1099+
return this._withAdapter<INotebookKernelInfoDto2[]>(handle, uri, (adapter, document) => {
1100+
return adapter.provideKernels(document, token);
1101+
});
1102+
}
1103+
1104+
async $resolveNotebookKernel(handle: number, editorId: string, uri: UriComponents, kernelId: string, token: CancellationToken): Promise<void> {
1105+
await this._withAdapter<void>(handle, uri, async (adapter, document) => {
1106+
let webComm = this._webviewComm.get(editorId);
1107+
1108+
if (webComm) {
1109+
await adapter.resolveNotebook(kernelId, document, webComm.contentProviderComm, token);
1110+
}
1111+
});
1112+
}
1113+
10011114
registerNotebookKernel(extension: IExtensionDescription, id: string, selectors: vscode.GlobPattern[], kernel: vscode.NotebookKernel): vscode.Disposable {
10021115
if (this._notebookKernels.has(id)) {
10031116
throw new Error(`Notebook kernel for '${id}' already registered`);

0 commit comments

Comments
 (0)