From 2de06d768bf22db70691a83404c5fb263fdbe149 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 16 Mar 2021 13:19:33 +0100 Subject: [PATCH] add INotebookSerializer interfaces and wire up IPC calls --- .../api/browser/mainThreadNotebook.ts | 22 ++++++++- .../workbench/api/common/extHost.protocol.ts | 11 ++++- .../workbench/api/common/extHostNotebook.ts | 46 ++++++++++++++++++- .../api/common/extHostTypeConverters.ts | 10 ++++ .../notebook/browser/notebookServiceImpl.ts | 7 ++- .../notebook/common/notebookService.ts | 11 ++++- 6 files changed, 100 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index a7f288c9d44..df7172f32fc 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -24,7 +24,7 @@ import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/no import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService'; -import { ICellEditOperation, ICellRange, IMainCellDto, INotebookDecorationRenderOptions, INotebookDocumentFilter, INotebookExclusiveDocumentFilter, INotebookKernel, NotebookCellsChangeType, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ICellEditOperation, ICellRange, IMainCellDto, INotebookDecorationRenderOptions, INotebookDocumentFilter, INotebookExclusiveDocumentFilter, INotebookKernel, NotebookCellsChangeType, NotebookDataDto, TransientMetadata, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService'; import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -107,6 +107,7 @@ export class MainThreadNotebooks implements MainThreadNotebookShape { private readonly _proxy: ExtHostNotebookShape; private readonly _notebookProviders = new Map(); + private readonly _notebookSerializer = new Map(); private readonly _notebookKernelProviders = new Map, provider: IDisposable }>(); private readonly _editorEventListenersMapping = new Map(); private readonly _documentEventListenersMapping = new ResourceMap(); @@ -147,6 +148,7 @@ export class MainThreadNotebooks implements MainThreadNotebookShape { item.emitter.dispose(); item.provider.dispose(); } + dispose(this._notebookSerializer.values()); dispose(this._editorEventListenersMapping.values()); dispose(this._documentEventListenersMapping.values()); dispose(this._cellStatusBarEntries.values()); @@ -452,6 +454,24 @@ export class MainThreadNotebooks implements MainThreadNotebookShape { } } + $registerNotebookSerializer(handle: number, viewType: string, options: TransientOptions): void { + const registration = this._notebookService.registerNotebookSerializer(viewType, { + options, + dataToNotebook: (data: Uint8Array): Promise => { + return this._proxy.$dataToNotebook(handle, data); + }, + notebookToData: (data: NotebookDataDto): Promise => { + return this._proxy.$notebookToData(handle, data); + } + }); + this._notebookSerializer.set(handle, registration); + } + + $unregisterNotebookSerializer(handle: number): void { + this._notebookSerializer.get(handle)?.dispose(); + this._notebookSerializer.delete(handle); + } + async $registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise { const emitter = new Emitter(); const that = this; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index aaa24b06bd7..8aa6666e1fc 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -50,7 +50,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService'; import { TunnelCreationOptions, TunnelProviderFeatures, TunnelOptions, ProvidedPortAttributes } 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 { NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEventDto, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, TransientMetadata, INotebookCellStatusBarEntry, ICellRange, INotebookDecorationRenderOptions, INotebookExclusiveDocumentFilter, IOutputDto } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEventDto, NotebookDataDto, IMainCellDto, INotebookDocumentFilter, TransientMetadata, INotebookCellStatusBarEntry, ICellRange, INotebookDecorationRenderOptions, INotebookExclusiveDocumentFilter, IOutputDto, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy'; import { Dto } from 'vs/base/common/types'; import { DebugConfigurationProviderTriggerKind, WorkspaceTrustState } from 'vs/workbench/api/common/extHostTypes'; @@ -836,6 +836,10 @@ export interface MainThreadNotebookShape extends IDisposable { }): Promise; $updateNotebookProviderOptions(viewType: string, options?: { transientOutputs: boolean; transientMetadata: TransientMetadata; }): Promise; $unregisterNotebookProvider(viewType: string): Promise; + + $registerNotebookSerializer(handle: number, viewType: string, options: TransientOptions): void; + $unregisterNotebookSerializer(handle: number): void; + $registerNotebookKernelProvider(extension: NotebookExtensionDescription, handle: number, documentFilter: INotebookDocumentFilter): Promise; $unregisterNotebookKernelProvider(handle: number): Promise; $onNotebookKernelChange(handle: number, uri: UriComponents | undefined): void; @@ -1863,10 +1867,15 @@ export interface ExtHostNotebookShape { $executeNotebookKernelFromProvider(handle: number, uri: UriComponents, kernelId: string, cellHandle: number | undefined): Promise; $cancelNotebookKernelFromProvider(handle: number, uri: UriComponents, kernelId: string, cellHandle: number | undefined): Promise; $onDidReceiveMessage(editorId: string, rendererId: string | undefined, message: unknown): void; + $openNotebook(viewType: string, uri: UriComponents, backupId: string | undefined, token: CancellationToken, untitledDocumentData?: VSBuffer): Promise; $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise; $saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise; $backupNotebook(viewType: string, uri: UriComponents, cancellation: CancellationToken): Promise; + + $dataToNotebook(handle: number, data: Uint8Array): Promise; + $notebookToData(handle: number, data: NotebookDataDto): Promise; + $acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEventDto, isDirty: boolean): void; $acceptDirtyStateChanged(uriComponents: UriComponents, isDirty: boolean): void; $acceptModelSaved(uriComponents: UriComponents): void; diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 15dc624965a..6c14865fd1d 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -5,7 +5,7 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; import { Emitter, Event } from 'vs/base/common/event'; -import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { URI, UriComponents } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; @@ -17,7 +17,7 @@ import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePa import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters'; import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview'; -import { CellStatusbarAlignment, CellUri, INotebookCellStatusBarEntry, INotebookExclusiveDocumentFilter, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookCellsChangeType, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellStatusbarAlignment, CellUri, INotebookCellStatusBarEntry, INotebookExclusiveDocumentFilter, NotebookCellMetadata, NotebookCellsChangedEventDto, NotebookCellsChangeType, NotebookDataDto, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import * as vscode from 'vscode'; import { ResourceMap } from 'vs/base/common/map'; import { ExtHostCell, ExtHostNotebookDocument } from './extHostNotebookDocument'; @@ -209,6 +209,11 @@ export class NotebookEditorDecorationType { } } +export interface NotebookSerializer { + dataToNotebook(data: Uint8Array): vscode.NotebookData | Thenable; + notebookToData(data: vscode.NotebookData): Uint8Array | Thenable; +} + type NotebookContentProviderData = { readonly provider: vscode.NotebookContentProvider; readonly extension: IExtensionDescription; @@ -496,6 +501,43 @@ export class ExtHostNotebookController implements ExtHostNotebookShape { }); } + // --- serialize/deserialize + + private _handlePool = 0; + private readonly _notebookSerializer = new Map(); + + registerNotebookSerializer(extension: IExtensionDescription, viewType: string, serializer: NotebookSerializer, options: TransientOptions): vscode.Disposable { + const handle = this._handlePool++; + this._notebookSerializer.set(handle, serializer); + this._proxy.$registerNotebookSerializer(handle, viewType, options); + return toDisposable(() => { + this._proxy.$unregisterNotebookSerializer(handle); + }); + } + + async $dataToNotebook(handle: number, bytes: Uint8Array): Promise { + const serializer = this._notebookSerializer.get(handle); + if (!serializer) { + throw new Error('NO serializer found'); + } + const data = await serializer.dataToNotebook(bytes); + return { + metadata: typeConverters.NotebookDocumentMetadata.from(data.metadata), + cells: data.cells.map(typeConverters.NotebookCellData.from), + }; + } + + async $notebookToData(handle: number, data: NotebookDataDto): Promise { + const serializer = this._notebookSerializer.get(handle); + if (!serializer) { + throw new Error('NO serializer found'); + } + return await serializer.notebookToData({ + metadata: typeConverters.NotebookDocumentMetadata.to(data.metadata), + cells: data.cells.map(typeConverters.NotebookCellData.to) + }); + } + // --- open, save, saveAs, backup async $openNotebook(viewType: string, uri: UriComponents, backupId: string | undefined, token: CancellationToken, untitledDocumentData?: VSBuffer): Promise { diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index fe2aec8f49a..a0012a4aae1 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1469,6 +1469,16 @@ export namespace NotebookCellData { outputs: data.outputs ? data.outputs.map(NotebookCellOutput.from) : [] }; } + + export function to(data: notebooks.ICellDto2): vscode.NotebookCellData { + return { + kind: NotebookCellKind.to(data.cellKind), + language: data.language, + source: data.source, + metadata: data.metadata ? NotebookCellMetadata.to(data.metadata) : new types.NotebookCellMetadata(), + outputs: data.outputs ? data.outputs.map(NotebookCellOutput.to) : [] + }; + } } export namespace NotebookCellOutputItem { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 805c8fc2879..ead74eef874 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -31,7 +31,7 @@ import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, DisplayOrderKey import { NotebookMarkdownRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookMarkdownRenderer'; import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer'; import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider'; -import { IMainNotebookController, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; +import { IMainNotebookController, INotebookSerializer, INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { Extensions as EditorExtensions, IEditorTypesHandler, IEditorType, IEditorAssociationsRegistry } from 'vs/workbench/browser/editor'; @@ -465,6 +465,11 @@ export class NotebookService extends Disposable implements INotebookService, IEd }); } + registerNotebookSerializer(viewType: string, serializer: INotebookSerializer): IDisposable { + + return Disposable.None; + } + registerNotebookKernelProvider(provider: INotebookKernelProvider): IDisposable { const d = this._notebookKernelProviderInfoStore.add(provider); const kernelChangeEventListener = provider.onDidChangeKernels((e) => { diff --git a/src/vs/workbench/contrib/notebook/common/notebookService.ts b/src/vs/workbench/contrib/notebook/common/notebookService.ts index e76d9b486ea..fab3431d46d 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookService.ts @@ -8,7 +8,7 @@ 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, INotebookKernelProvider, INotebookKernel, TransientMetadata, NotebookDataDto, TransientOptions, INotebookExclusiveDocumentFilter, IOrderedMimeType, IOutputDto, INotebookMarkdownRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookTextModel, INotebookRendererInfo, INotebookKernelProvider, INotebookKernel, NotebookDataDto, TransientOptions, INotebookExclusiveDocumentFilter, IOrderedMimeType, IOutputDto, INotebookMarkdownRendererInfo } 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'; @@ -22,7 +22,7 @@ export const INotebookService = createDecorator('notebookServi export interface IMainNotebookController { viewOptions?: { displayName: string; filenamePattern: (string | IRelativePattern | INotebookExclusiveDocumentFilter)[]; exclusive: boolean; }; - options: { transientOutputs: boolean; transientMetadata: TransientMetadata; }; + options: TransientOptions; resolveNotebookEditor(viewType: string, uri: URI, editorId: string): Promise; onDidReceiveMessage(editorId: string, rendererType: string | undefined, message: any): void; @@ -32,6 +32,11 @@ export interface IMainNotebookController { backup(uri: URI, token: CancellationToken): Promise; } +export interface INotebookSerializer { + options: TransientOptions; + dataToNotebook(data: Uint8Array): Promise + notebookToData(data: NotebookDataDto): Promise; +} export interface INotebookRawData { data: NotebookDataDto; @@ -47,7 +52,9 @@ export interface INotebookService { onNotebookDocumentSaved: Event; onDidChangeKernels: Event; onDidChangeNotebookActiveKernel: Event<{ uri: URI, providerHandle: number | undefined, kernelFriendlyId: string | undefined; }>; + registerNotebookController(viewType: string, extensionData: NotebookExtensionDescription, controller: IMainNotebookController): IDisposable; + registerNotebookSerializer(viewType: string, serializer: INotebookSerializer): IDisposable; getMimeTypeInfo(textModel: NotebookTextModel, output: IOutputDto): readonly IOrderedMimeType[];