提交 4fc84b3a 编写于 作者: R rebornix

sketch for notebook kernel

上级 f62bef3b
......@@ -1835,17 +1835,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[],
......@@ -1882,6 +1901,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;
......@@ -203,6 +204,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>();
......@@ -455,6 +457,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: (viewType: string, uri: URI, kernelId: string, handle: number | undefined, token: CancellationToken) => {
return that._proxy.$executeNotebook2(kernelId, viewType, uri, handle, 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);
......
......@@ -936,6 +936,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);
......@@ -944,6 +952,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,6 +1614,8 @@ 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>;
$provideNotebookKernels(handle: number, uri: UriComponents, token: CancellationToken): Promise<INotebookKernelInfoDto2[]>;
$resolveNotebookKernel(handle: number, editorId: string, uri: UriComponents, kernelId: string, token: CancellationToken): Promise<void>;
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, 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>;
......
......@@ -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, 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';
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';
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;
export class ExtHostCell extends Disposable implements vscode.NotebookCell {
......@@ -780,10 +780,74 @@ 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,
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);
}
}
}
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 }>();
......@@ -820,6 +884,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;
......@@ -998,6 +1066,51 @@ 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, selector);
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`);
......
......@@ -11,6 +11,8 @@ import { INotebookCellActionContext, NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbe
import { INotebookEditor, NOTEBOOK_HAS_MULTIPLE_KERNELS, 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 { INotebookKernelInfoDto2, INotebookKernelInfo2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
registerAction2(class extends Action2 {
......@@ -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 INotebookKernelInfoDto2).description
? (a as INotebookKernelInfoDto2).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());
}
}
};
});
......
......@@ -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, INotebookKernelInfoDto2 } 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';
......@@ -171,7 +171,7 @@ export interface INotebookEditor extends IEditor {
readonly onDidChangeModel: Event<NotebookTextModel | undefined>;
readonly onDidFocusEditorWidget: Event<void>;
isNotebookEditor: boolean;
activeKernel: INotebookKernelInfo | undefined;
activeKernel: INotebookKernelInfo | INotebookKernelInfoDto2 | undefined;
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, INotebookKernelInfoDto2, 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 | INotebookKernelInfoDto2 | 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 | INotebookKernelInfoDto2 | undefined) {
if (this._isDisposed) {
return;
}
......@@ -197,6 +197,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this.notebookService.addNotebookEditor(this);
}
/**
* EditorId
*/
public getId(): string {
return this._uuid;
}
......@@ -472,11 +475,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
// clear state
this._dndController?.clearGlobalDragState();
this._setKernels(textModel);
await this._setKernels(textModel);
this._localStore.add(this.notebookService.onDidChangeKernels(() => {
this._localStore.add(this.notebookService.onDidChangeKernels(async () => {
if (this.activeKernel === undefined) {
this._setKernels(textModel);
await this._setKernels(textModel);
}
}));
......@@ -548,13 +551,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this._list?.clear();
}
private _setKernels(textModel: NotebookTextModel) {
private async _setKernels(textModel: NotebookTextModel) {
const provider = this.notebookService.getContributedNotebookProviders(this.viewModel!.uri)[0];
const tokenSource = new CancellationTokenSource();
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) {
} else if ((availableKernels.length + availableKernels2.length) > 1) {
this._notebookHasMultipleKernels!.set(true);
} else {
this._notebookHasMultipleKernels!.set(false);
......@@ -566,6 +572,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 this.notebookService.resolveNotebookKernel(this.viewModel!.viewType, this.viewModel!.uri, this.getId(), preferedKernel.id);
return;
}
// the provider doesn't have a builtin kernel, choose a kernel
this.activeKernel = availableKernels[0];
if (this.activeKernel) {
......@@ -1134,7 +1150,12 @@ 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 any).executeNotebook) {
await (this._activeKernel as INotebookKernelInfo2).executeNotebook(this._notebookViewModel!.viewType, 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 {
......
......@@ -4,18 +4,18 @@
*--------------------------------------------------------------------------------------------*/
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, INotebookKernelInfoDto2, 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';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CancellationToken } from 'vs/base/common/cancellation';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IEditorService, ICustomEditorViewTypesHandler, ICustomEditorInfo } from 'vs/workbench/services/editor/common/editorService';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
......@@ -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,47 @@ export class NotebookService extends Disposable implements INotebookService, ICu
this._onDidChangeKernels.fire();
}
registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable {
this._notebookKernelProviders.push(provider);
return toDisposable(() => {
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) => {
const tokenSource = new CancellationTokenSource();
return provider.resolveKernel(editorId, uri, dto.id, tokenSource.token);
},
executeNotebook: async (viewType: string, uri: URI, handle: number | undefined, token: CancellationToken) => {
return provider.executeNotebook(viewType, 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 => {
......
......@@ -18,6 +18,7 @@ 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,
......@@ -607,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): Promise<void>;
executeNotebook(viewType: string, 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(viewType: string, 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,11 @@ 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, INotebookKernelInfoDto2 } 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');
......@@ -48,7 +49,9 @@ 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<INotebookKernelInfoDto2[]>;
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>;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册