mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-17 09:35:37 -05:00
Remove API compatibility layer for VS Code notebook extensions (#21225)
This commit is contained in:
@@ -15,13 +15,9 @@ import { LocalContentManager } from 'sql/workbench/services/notebook/common/loca
|
||||
import { Deferred } from 'sql/base/common/promise';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import type { FutureInternal } from 'sql/workbench/services/notebook/browser/interfaces';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { INotebookProviderRegistry, NotebookProviderRegistryId } from 'sql/workbench/services/notebook/common/notebookRegistry';
|
||||
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
||||
import { SqlExtHostContext, SqlMainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
|
||||
const notebookRegistry = Registry.as<INotebookProviderRegistry>(NotebookProviderRegistryId);
|
||||
|
||||
@extHostNamedCustomer(SqlMainContext.MainThreadNotebook)
|
||||
export class MainThreadNotebook extends Disposable implements MainThreadNotebookShape {
|
||||
|
||||
@@ -101,14 +97,6 @@ export class MainThreadNotebook extends Disposable implements MainThreadNotebook
|
||||
future.onDone(done);
|
||||
}
|
||||
}
|
||||
|
||||
public $updateProviderKernels(providerId: string, languages: azdata.nb.IStandardKernel[]): void {
|
||||
notebookRegistry.updateProviderKernels(providerId, languages);
|
||||
}
|
||||
|
||||
public $updateKernelLanguages(providerId: string, kernelName: string, languages: string[]): void {
|
||||
notebookRegistry.updateKernelLanguages(providerId, kernelName, languages);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
|
||||
|
||||
@@ -345,14 +345,6 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to create a new notebook with the specified provider and contents. Used for VS Code extension compatibility.
|
||||
*/
|
||||
async $tryCreateNotebookDocument(providerId: string, contents?: azdata.nb.INotebookContents): Promise<UriComponents> {
|
||||
let input = await this._notebookService.createNotebookInputFromContents(providerId, contents);
|
||||
return input.resource;
|
||||
}
|
||||
|
||||
$tryShowNotebookDocument(resource: UriComponents, options: INotebookShowOptions): Promise<string> {
|
||||
// Append a numbered suffix if an untitled notebook is already open with the same path
|
||||
if (resource.scheme === Schemas.untitled) {
|
||||
|
||||
@@ -13,11 +13,6 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
|
||||
import { ExtHostNotebookShape, MainThreadNotebookShape } from 'sql/workbench/api/common/sqlExtHost.protocol';
|
||||
import { IExecuteManagerDetails, INotebookSessionDetails, INotebookKernelDetails, INotebookFutureDetails, FutureMessageType, ISerializationManagerDetails } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import { VSCodeSerializationProvider } from 'sql/workbench/api/common/notebooks/vscodeSerializationProvider';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ADSNotebookController } from 'sql/workbench/api/common/notebooks/adsNotebookController';
|
||||
import { VSCodeExecuteProvider } from 'sql/workbench/api/common/notebooks/vscodeExecuteProvider';
|
||||
import { ExtHostNotebookDocumentsAndEditors } from 'sql/workbench/api/common/extHostNotebookDocumentsAndEditors';
|
||||
import { SqlMainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
|
||||
type Adapter = azdata.nb.NotebookSerializationProvider | azdata.nb.SerializationManager | azdata.nb.NotebookExecuteProvider | azdata.nb.ExecuteManager | azdata.nb.ISession | azdata.nb.IKernel | azdata.nb.IFuture;
|
||||
@@ -29,7 +24,7 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
private _adapters = new Map<number, Adapter>();
|
||||
|
||||
// Notebook URI to manager lookup.
|
||||
constructor(_mainContext: IMainContext, private _extHostNotebookDocumentsAndEditors: ExtHostNotebookDocumentsAndEditors) {
|
||||
constructor(_mainContext: IMainContext) {
|
||||
this._proxy = _mainContext.getProxy(SqlMainContext.MainThreadNotebook);
|
||||
}
|
||||
|
||||
@@ -174,10 +169,6 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
}
|
||||
|
||||
$requestExecute(kernelId: number, content: azdata.nb.IExecuteRequest, disposeOnDone?: boolean): Thenable<INotebookFutureDetails> {
|
||||
// Revive request's URIs to restore functions
|
||||
content.notebookUri = URI.revive(content.notebookUri);
|
||||
content.cellUri = URI.revive(content.cellUri);
|
||||
|
||||
let kernel = this._getAdapter<azdata.nb.IKernel>(kernelId);
|
||||
let future = kernel.requestExecute(content, disposeOnDone);
|
||||
let futureId = this._addNewAdapter(future);
|
||||
@@ -258,35 +249,6 @@ export class ExtHostNotebook implements ExtHostNotebookShape {
|
||||
this._proxy.$registerSerializationProvider(provider.providerId, handle);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
registerNotebookSerializer(notebookType: string, serializer: vscode.NotebookSerializer, options?: vscode.NotebookDocumentContentOptions, registration?: vscode.NotebookRegistrationData): vscode.Disposable {
|
||||
let serializationProvider = new VSCodeSerializationProvider(notebookType, serializer);
|
||||
return this.registerSerializationProvider(serializationProvider);
|
||||
}
|
||||
|
||||
createNotebookController(
|
||||
extension: IExtensionDescription,
|
||||
id: string,
|
||||
viewType: string,
|
||||
label: string,
|
||||
getDocHandler: (notebookUri: URI) => azdata.nb.NotebookDocument,
|
||||
execHandler?: (cells: vscode.NotebookCell[], notebook: vscode.NotebookDocument, controller: vscode.NotebookController) => void | Thenable<void>,
|
||||
rendererScripts?: vscode.NotebookRendererScript[]
|
||||
): vscode.NotebookController {
|
||||
let languagesHandler = (languages: string[]) => this._proxy.$updateKernelLanguages(viewType, viewType, languages);
|
||||
let controller = new ADSNotebookController(extension, id, viewType, label, this._extHostNotebookDocumentsAndEditors, languagesHandler, getDocHandler, execHandler, extension.enabledApiProposals ? rendererScripts : undefined);
|
||||
let newKernel: azdata.nb.IStandardKernel = {
|
||||
name: viewType,
|
||||
displayName: controller.label,
|
||||
connectionProviderIds: [],
|
||||
supportedLanguages: [] // These will get set later from the controller
|
||||
};
|
||||
this._proxy.$updateProviderKernels(viewType, [newKernel]);
|
||||
|
||||
let executeProvider = new VSCodeExecuteProvider(controller);
|
||||
this.registerExecuteProvider(executeProvider);
|
||||
return controller;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region private methods
|
||||
|
||||
@@ -21,9 +21,6 @@ import {
|
||||
} from 'sql/workbench/api/common/sqlExtHost.protocol';
|
||||
import { ExtHostNotebookDocumentData } from 'sql/workbench/api/common/extHostNotebookDocumentData';
|
||||
import { ExtHostNotebookEditor } from 'sql/workbench/api/common/extHostNotebookEditor';
|
||||
import { VSCodeNotebookDocument } from 'sql/workbench/api/common/notebooks/vscodeNotebookDocument';
|
||||
import { VSCodeNotebookEditor } from 'sql/workbench/api/common/notebooks/vscodeNotebookEditor';
|
||||
import { docNotFoundForUriError } from 'sql/base/common/locConstants';
|
||||
import { SqlMainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
|
||||
type Adapter = azdata.nb.NavigationProvider;
|
||||
@@ -52,37 +49,12 @@ export class ExtHostNotebookDocumentsAndEditors implements ExtHostNotebookDocume
|
||||
readonly onDidCloseNotebookDocument: Event<azdata.nb.NotebookDocument> = this._onDidCloseNotebook.event;
|
||||
readonly onDidChangeNotebookCell: Event<azdata.nb.NotebookCellChangeEvent> = this._onDidChangeNotebookCell.event;
|
||||
|
||||
private readonly _onDidChangeVisibleVSCodeEditors = new Emitter<vscode.NotebookEditor[]>();
|
||||
private readonly _onDidChangeActiveVSCodeEditor = new Emitter<vscode.NotebookEditor>();
|
||||
private readonly _onDidOpenVSCodeNotebook = new Emitter<vscode.NotebookDocument>();
|
||||
private readonly _onDidCloseVSCodeNotebook = new Emitter<vscode.NotebookDocument>();
|
||||
private readonly _onDidSaveVSCodeNotebook = new Emitter<vscode.NotebookDocument>();
|
||||
private readonly _onDidChangeVSCodeExecutionState = new Emitter<vscode.NotebookCellExecutionStateChangeEvent>();
|
||||
private readonly _onDidChangeVSCodeEditorSelection = new Emitter<vscode.NotebookEditorSelectionChangeEvent>();
|
||||
private readonly _onDidChangeVSCodeEditorRanges = new Emitter<vscode.NotebookEditorVisibleRangesChangeEvent>();
|
||||
private readonly _onDidChangeVSCodeNotebookDocument = new Emitter<vscode.NotebookDocumentChangeEvent>();
|
||||
|
||||
readonly onDidChangeVisibleVSCodeEditors: Event<vscode.NotebookEditor[]> = this._onDidChangeVisibleVSCodeEditors.event;
|
||||
readonly onDidChangeActiveVSCodeEditor: Event<vscode.NotebookEditor> = this._onDidChangeActiveVSCodeEditor.event;
|
||||
readonly onDidOpenVSCodeNotebookDocument: Event<vscode.NotebookDocument> = this._onDidOpenVSCodeNotebook.event;
|
||||
readonly onDidCloseVSCodeNotebookDocument: Event<vscode.NotebookDocument> = this._onDidCloseVSCodeNotebook.event;
|
||||
readonly onDidSaveVSCodeNotebookDocument: Event<vscode.NotebookDocument> = this._onDidSaveVSCodeNotebook.event;
|
||||
readonly onDidChangeVSCodeExecutionState: Event<vscode.NotebookCellExecutionStateChangeEvent> = this._onDidChangeVSCodeExecutionState.event;
|
||||
readonly onDidChangeVSCodeEditorSelection: Event<vscode.NotebookEditorSelectionChangeEvent> = this._onDidChangeVSCodeEditorSelection.event;
|
||||
readonly onDidChangeVSCodeEditorRanges: Event<vscode.NotebookEditorVisibleRangesChangeEvent> = this._onDidChangeVSCodeEditorRanges.event;
|
||||
readonly onDidChangeVSCodeNotebookDocument: Event<vscode.NotebookDocumentChangeEvent> = this._onDidChangeVSCodeNotebookDocument.event;
|
||||
|
||||
constructor(
|
||||
private readonly _mainContext: IMainContext,
|
||||
) {
|
||||
if (this._mainContext) {
|
||||
this._proxy = this._mainContext.getProxy(SqlMainContext.MainThreadNotebookDocumentsAndEditors);
|
||||
}
|
||||
|
||||
this.onDidChangeVisibleNotebookEditors(editors => this._onDidChangeVisibleVSCodeEditors.fire(editors.map(editor => new VSCodeNotebookEditor(editor))));
|
||||
this.onDidChangeActiveNotebookEditor(editor => this._onDidChangeActiveVSCodeEditor.fire(new VSCodeNotebookEditor(editor)));
|
||||
this.onDidOpenNotebookDocument(notebook => this._onDidOpenVSCodeNotebook.fire(new VSCodeNotebookDocument(notebook)));
|
||||
this.onDidCloseNotebookDocument(notebook => this._onDidCloseVSCodeNotebook.fire(new VSCodeNotebookDocument(notebook)));
|
||||
}
|
||||
|
||||
dispose() {
|
||||
@@ -218,43 +190,6 @@ export class ExtHostNotebookDocumentsAndEditors implements ExtHostNotebookDocume
|
||||
//#endregion
|
||||
|
||||
//#region Extension accessible methods
|
||||
/**
|
||||
* Attempts to create a new notebook with the specified provider and contents. Used for VS Code extension compatibility.
|
||||
*/
|
||||
async createNotebookDocument(providerId: string, contents?: azdata.nb.INotebookContents): Promise<URI> {
|
||||
let uriComps = await this._proxy.$tryCreateNotebookDocument(providerId, contents);
|
||||
let uri = URI.revive(uriComps);
|
||||
let notebookCells = contents?.cells?.map<azdata.nb.NotebookCell>(cellContents => {
|
||||
return {
|
||||
contents: cellContents,
|
||||
uri: undefined
|
||||
};
|
||||
});
|
||||
|
||||
let documentData = new ExtHostNotebookDocumentData(
|
||||
this._proxy,
|
||||
uri,
|
||||
providerId,
|
||||
false,
|
||||
notebookCells ?? []
|
||||
);
|
||||
this._documents.set(uri.toString(), documentData);
|
||||
this._onDidOpenNotebook.fire(documentData.document);
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to open an existing notebook. Used for VS Code extension compatibility.
|
||||
*/
|
||||
async openNotebookDocument(uri: vscode.Uri): Promise<azdata.nb.NotebookDocument> {
|
||||
let docData = this._documents.get(uri.toString());
|
||||
if (!docData) {
|
||||
throw new Error(docNotFoundForUriError);
|
||||
}
|
||||
return docData.document;
|
||||
}
|
||||
|
||||
showNotebookDocument(uri: vscode.Uri, showOptions: azdata.nb.NotebookShowOptions): Thenable<azdata.nb.NotebookEditor> {
|
||||
return this.doShowNotebookDocument(uri, showOptions);
|
||||
}
|
||||
|
||||
@@ -1,279 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import type * as azdata from 'azdata';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { INotebookKernelDto2 } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { Deferred } from 'sql/base/common/promise';
|
||||
import { ExtHostNotebookDocumentsAndEditors } from 'sql/workbench/api/common/extHostNotebookDocumentsAndEditors';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { NotebookCellExecutionTaskState } from 'vs/workbench/api/common/extHostNotebookKernels';
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
import { convertToADSCellOutput } from 'sql/workbench/api/common/notebooks/notebookUtils';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
|
||||
type SelectionChangedEvent = { selected: boolean, notebook: vscode.NotebookDocument; };
|
||||
type MessageReceivedEvent = { editor: vscode.NotebookEditor, message: any; };
|
||||
type ExecutionHandler = (cells: vscode.NotebookCell[], notebook: vscode.NotebookDocument, controller: vscode.NotebookController) => void | Thenable<void>;
|
||||
type LanguagesHandler = (languages: string[]) => void;
|
||||
type InterruptHandler = (notebook: vscode.NotebookDocument) => void | Promise<void>;
|
||||
type GetDocHandler = (notebookUri: URI) => azdata.nb.NotebookDocument;
|
||||
|
||||
/**
|
||||
* A VS Code Notebook Controller that is used as part of converting VS Code notebook extension APIs into ADS equivalents.
|
||||
*/
|
||||
export class ADSNotebookController implements vscode.NotebookController {
|
||||
private readonly _kernelData: INotebookKernelDto2;
|
||||
private _interruptHandler: (notebook: vscode.NotebookDocument) => void | Promise<void>;
|
||||
|
||||
private readonly _onDidChangeSelection = new Emitter<SelectionChangedEvent>();
|
||||
private readonly _onDidReceiveMessage = new Emitter<MessageReceivedEvent>();
|
||||
|
||||
private readonly _languagesAdded = new Deferred<void>();
|
||||
private readonly _executionHandlerAdded = new Deferred<void>();
|
||||
|
||||
private readonly _execMap: Map<string, ADSNotebookCellExecution> = new Map();
|
||||
|
||||
constructor(
|
||||
private _extension: IExtensionDescription,
|
||||
private _id: string,
|
||||
private _viewType: string,
|
||||
private _label: string,
|
||||
private _extHostNotebookDocumentsAndEditors: ExtHostNotebookDocumentsAndEditors,
|
||||
private _languagesHandler: LanguagesHandler,
|
||||
private _getDocHandler: GetDocHandler,
|
||||
private _execHandler?: ExecutionHandler,
|
||||
preloads?: vscode.NotebookRendererScript[]
|
||||
) {
|
||||
this._kernelData = {
|
||||
id: `${this._extension.identifier.value}/${this._id}`,
|
||||
notebookType: this._viewType,
|
||||
extensionId: this._extension.identifier,
|
||||
extensionLocation: this._extension.extensionLocation,
|
||||
label: this._label || this._extension.identifier.value,
|
||||
preloads: preloads ? preloads.map(extHostTypeConverters.NotebookRendererScript.from) : []
|
||||
};
|
||||
if (this._execHandler) {
|
||||
this._executionHandlerAdded.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
public get languagesAdded(): Promise<void> {
|
||||
return this._languagesAdded.promise;
|
||||
}
|
||||
|
||||
public get executionHandlerAdded(): Promise<void> {
|
||||
return this._executionHandlerAdded.promise;
|
||||
}
|
||||
|
||||
public get id(): string { return this._id; }
|
||||
|
||||
public get notebookType(): string { return this._viewType; }
|
||||
|
||||
public get onDidChangeSelectedNotebooks(): Event<SelectionChangedEvent> {
|
||||
return this._onDidChangeSelection.event;
|
||||
}
|
||||
|
||||
public get onDidReceiveMessage(): Event<MessageReceivedEvent> {
|
||||
return this._onDidReceiveMessage.event;
|
||||
}
|
||||
|
||||
public get label(): string {
|
||||
return this._kernelData.label;
|
||||
}
|
||||
|
||||
public set label(value: string) {
|
||||
this._kernelData.label = value ?? this._extension.displayName ?? this._extension.name;
|
||||
}
|
||||
|
||||
public get detail(): string {
|
||||
return this._kernelData.detail ?? '';
|
||||
}
|
||||
|
||||
public set detail(value: string) {
|
||||
this._kernelData.detail = value;
|
||||
}
|
||||
|
||||
public get description(): string {
|
||||
return this._kernelData.description ?? '';
|
||||
}
|
||||
|
||||
public set description(value: string) {
|
||||
this._kernelData.description = value;
|
||||
}
|
||||
|
||||
public get supportedLanguages(): string[] | undefined {
|
||||
return this._kernelData.supportedLanguages;
|
||||
}
|
||||
|
||||
public set supportedLanguages(value: string[]) {
|
||||
this._kernelData.supportedLanguages = value;
|
||||
this._languagesHandler(value);
|
||||
this._languagesAdded.resolve();
|
||||
}
|
||||
|
||||
public get supportsExecutionOrder(): boolean {
|
||||
return this._kernelData.supportsExecutionOrder ?? false;
|
||||
}
|
||||
|
||||
public set supportsExecutionOrder(value: boolean) {
|
||||
this._kernelData.supportsExecutionOrder = value;
|
||||
}
|
||||
|
||||
public get rendererScripts(): vscode.NotebookRendererScript[] {
|
||||
return this._kernelData.preloads ? this._kernelData.preloads.map(extHostTypeConverters.NotebookRendererScript.to) : [];
|
||||
}
|
||||
|
||||
public get executeHandler(): ExecutionHandler {
|
||||
return this._execHandler;
|
||||
}
|
||||
|
||||
public set executeHandler(value: ExecutionHandler) {
|
||||
this._execHandler = value;
|
||||
this._executionHandlerAdded.resolve();
|
||||
}
|
||||
|
||||
public get interruptHandler(): InterruptHandler {
|
||||
return this._interruptHandler;
|
||||
}
|
||||
|
||||
public set interruptHandler(value: InterruptHandler) {
|
||||
this._interruptHandler = value;
|
||||
this._kernelData.supportsInterrupt = Boolean(value);
|
||||
}
|
||||
|
||||
public getCellExecution(cellUri: URI): ADSNotebookCellExecution | undefined {
|
||||
return this._execMap.get(cellUri.toString());
|
||||
}
|
||||
|
||||
public removeCellExecution(cellUri: URI): void {
|
||||
this._execMap.delete(cellUri.toString());
|
||||
}
|
||||
|
||||
public getNotebookDocument(notebookUri: URI): azdata.nb.NotebookDocument {
|
||||
return this._getDocHandler(notebookUri);
|
||||
}
|
||||
|
||||
public createNotebookCellExecution(cell: vscode.NotebookCell): vscode.NotebookCellExecution {
|
||||
let exec = new ADSNotebookCellExecution(cell, this._extHostNotebookDocumentsAndEditors);
|
||||
this._execMap.set(cell.document.uri.toString(), exec);
|
||||
return exec;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public updateNotebookAffinity(notebook: vscode.NotebookDocument, affinity: vscode.NotebookControllerAffinity): void {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public postMessage(message: any, editor?: vscode.NotebookEditor): Thenable<boolean> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
public asWebviewUri(localResource: vscode.Uri): vscode.Uri {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
class ADSNotebookCellExecution implements vscode.NotebookCellExecution {
|
||||
private _executionOrder: number;
|
||||
private _state = NotebookCellExecutionTaskState.Init;
|
||||
private _cancellationSource = new CancellationTokenSource();
|
||||
constructor(private readonly _cell: vscode.NotebookCell, private readonly _extHostNotebookDocumentsAndEditors: ExtHostNotebookDocumentsAndEditors) {
|
||||
this._executionOrder = this._cell.executionSummary?.executionOrder ?? -1;
|
||||
}
|
||||
|
||||
public get cell(): vscode.NotebookCell {
|
||||
return this._cell;
|
||||
}
|
||||
|
||||
public get tokenSource(): vscode.CancellationTokenSource {
|
||||
return this._cancellationSource;
|
||||
}
|
||||
|
||||
public get token(): vscode.CancellationToken {
|
||||
return this._cancellationSource.token;
|
||||
}
|
||||
|
||||
public get executionOrder(): number {
|
||||
return this._executionOrder;
|
||||
}
|
||||
|
||||
public set executionOrder(order: number) {
|
||||
this._executionOrder = order;
|
||||
}
|
||||
|
||||
public start(startTime?: number): void {
|
||||
this._state = NotebookCellExecutionTaskState.Started;
|
||||
}
|
||||
|
||||
public end(success: boolean, endTime?: number): void {
|
||||
this._state = NotebookCellExecutionTaskState.Resolved;
|
||||
}
|
||||
|
||||
public async clearOutput(cell?: vscode.NotebookCell): Promise<void> {
|
||||
this.verifyStateForOutput();
|
||||
const targetCell = typeof cell === 'number' ? this._cell.notebook.cellAt(cell) : (cell ?? this._cell);
|
||||
const editor = this._extHostNotebookDocumentsAndEditors.getEditor(URI.from(targetCell.notebook.uri).toString());
|
||||
await editor.clearOutput(editor.document.cells[targetCell.index]);
|
||||
}
|
||||
|
||||
public async replaceOutput(out: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell): Promise<void> {
|
||||
this.verifyStateForOutput();
|
||||
return this.updateOutputs(out, cell, false);
|
||||
}
|
||||
|
||||
public async appendOutput(out: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell?: vscode.NotebookCell): Promise<void> {
|
||||
this.verifyStateForOutput();
|
||||
return this.updateOutputs(out, cell, true);
|
||||
}
|
||||
|
||||
public async replaceOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput): Promise<void> {
|
||||
this.verifyStateForOutput();
|
||||
return this.updateOutputItems(items, output, false);
|
||||
}
|
||||
|
||||
public async appendOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput): Promise<void> {
|
||||
this.verifyStateForOutput();
|
||||
return this.updateOutputItems(items, output, true);
|
||||
}
|
||||
|
||||
private async updateOutputs(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], cell: vscode.NotebookCell | number | undefined, append: boolean): Promise<void> {
|
||||
this.verifyStateForOutput();
|
||||
const targetCell = typeof cell === 'number' ? this._cell.notebook.cellAt(cell) : (cell ?? this._cell);
|
||||
const editor = this._extHostNotebookDocumentsAndEditors.getEditor(URI.from(targetCell.notebook.uri).toString());
|
||||
await editor.edit(builder => {
|
||||
const adsOutputs = convertToADSCellOutput(outputs);
|
||||
builder.updateCell(targetCell.index, { outputs: adsOutputs }, append);
|
||||
});
|
||||
}
|
||||
|
||||
private async updateOutputItems(items: vscode.NotebookCellOutputItem | vscode.NotebookCellOutputItem[], output: vscode.NotebookCellOutput, append: boolean): Promise<void> {
|
||||
this.verifyStateForOutput();
|
||||
const editor = this._extHostNotebookDocumentsAndEditors.getEditor(URI.from(this._cell.notebook.uri).toString());
|
||||
await editor.edit(builder => {
|
||||
const adsOutput = convertToADSCellOutput({ id: output.id, items: asArray(items) }, undefined);
|
||||
builder.updateCellOutput(this._cell.index, { outputs: adsOutput }, append);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the execution is in a state where it's valid to modify the output (currently executing).
|
||||
*/
|
||||
private verifyStateForOutput() {
|
||||
if (this._state === NotebookCellExecutionTaskState.Init) {
|
||||
throw new Error('Must call start before modifying cell output');
|
||||
}
|
||||
|
||||
if (this._state === NotebookCellExecutionTaskState.Resolved) {
|
||||
throw new Error('Cannot modify cell output after calling end');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import type * as azdata from 'azdata';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CellTypes, MimeTypes, OutputTypes } from 'sql/workbench/services/notebook/common/contracts';
|
||||
import { NBFORMAT, NBFORMAT_MINOR } from 'sql/workbench/common/constants';
|
||||
import { NotebookCellKind } from 'vs/workbench/api/common/extHostTypes';
|
||||
|
||||
const DotnetInteractiveJupyterKernelPrefix = '.net-';
|
||||
export const DotnetInteractiveLanguagePrefix = 'dotnet-interactive.';
|
||||
export const DotnetInteractiveDisplayName = '.NET Interactive';
|
||||
|
||||
export function convertToVSCodeNotebookCell(cellKind: azdata.nb.CellType, cellIndex: number, cellUri: URI, docUri: URI, cellLanguage: string, cellSource?: string | string[]): vscode.NotebookCell {
|
||||
// We only use this notebook field for .NET Interactive's intellisense, which only uses the notebook's URI
|
||||
let notebook = <vscode.NotebookDocument>{
|
||||
uri: docUri
|
||||
};
|
||||
return <vscode.NotebookCell>{
|
||||
kind: cellKind === CellTypes.Code ? NotebookCellKind.Code : NotebookCellKind.Markup,
|
||||
index: cellIndex,
|
||||
document: <vscode.TextDocument>{
|
||||
uri: cellUri,
|
||||
languageId: cellLanguage,
|
||||
getText: () => Array.isArray(cellSource) ? cellSource.join('') : (cellSource ?? ''),
|
||||
notebook: notebook
|
||||
},
|
||||
notebook: notebook,
|
||||
outputs: [],
|
||||
metadata: {},
|
||||
mime: undefined,
|
||||
executionSummary: undefined
|
||||
};
|
||||
}
|
||||
|
||||
export function convertToADSCellOutput(outputs: vscode.NotebookCellOutput | vscode.NotebookCellOutput[], executionOrder?: number): azdata.nb.IDisplayResult[] {
|
||||
return asArray(outputs).map(output => {
|
||||
let outputData = {};
|
||||
for (let item of output.items) {
|
||||
outputData[item.mime] = VSBuffer.wrap(item.data).toString();
|
||||
}
|
||||
return {
|
||||
output_type: OutputTypes.ExecuteResult,
|
||||
data: outputData,
|
||||
execution_count: executionOrder,
|
||||
metadata: output.metadata,
|
||||
id: output.id
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function convertToVSCodeCellOutput(output: azdata.nb.ICellOutput): vscode.NotebookCellOutput {
|
||||
let convertedOutputItems: vscode.NotebookCellOutputItem[];
|
||||
switch (output.output_type) {
|
||||
case OutputTypes.ExecuteResult:
|
||||
case OutputTypes.DisplayData:
|
||||
case OutputTypes.UpdateDisplayData:
|
||||
let displayOutput = output as azdata.nb.IDisplayResult;
|
||||
convertedOutputItems = Object.keys(displayOutput.data).map<vscode.NotebookCellOutputItem>(key => {
|
||||
return {
|
||||
mime: key,
|
||||
data: VSBuffer.fromString(displayOutput.data[key]).buffer
|
||||
};
|
||||
});
|
||||
break;
|
||||
case OutputTypes.Stream:
|
||||
let streamOutput = output as azdata.nb.IStreamResult;
|
||||
convertedOutputItems = [{
|
||||
mime: MimeTypes.HTML,
|
||||
data: VSBuffer.fromString(Array.isArray(streamOutput.text) ? streamOutput.text.join('') : streamOutput.text).buffer
|
||||
}];
|
||||
break;
|
||||
case OutputTypes.Error:
|
||||
let errorOutput = output as azdata.nb.IErrorResult;
|
||||
let errorString = errorOutput.ename + ': ' + errorOutput.evalue + (errorOutput.traceback ? '\n' + errorOutput.traceback?.join('\n') : '');
|
||||
convertedOutputItems = [{
|
||||
mime: MimeTypes.HTML,
|
||||
data: VSBuffer.fromString(errorString).buffer
|
||||
}];
|
||||
break;
|
||||
}
|
||||
return {
|
||||
items: convertedOutputItems,
|
||||
metadata: output.metadata,
|
||||
id: output.id
|
||||
};
|
||||
}
|
||||
|
||||
export function convertToADSNotebookContents(notebookData: vscode.NotebookData | undefined): azdata.nb.INotebookContents {
|
||||
let result = {
|
||||
cells: notebookData?.cells?.map<azdata.nb.ICellContents>(cell => {
|
||||
let executionOrder = cell.executionSummary?.executionOrder;
|
||||
let convertedCell: azdata.nb.ICellContents = {
|
||||
cell_type: cell.kind === NotebookCellKind.Code ? CellTypes.Code : CellTypes.Markdown,
|
||||
source: cell.value,
|
||||
execution_count: executionOrder,
|
||||
outputs: cell.outputs ? convertToADSCellOutput(cell.outputs, executionOrder) : undefined
|
||||
};
|
||||
convertedCell.metadata = cell.metadata?.custom?.metadata ?? {};
|
||||
if (!convertedCell.metadata.language) {
|
||||
convertedCell.metadata.language = cell.languageId;
|
||||
}
|
||||
return convertedCell;
|
||||
}),
|
||||
metadata: notebookData?.metadata?.custom?.metadata ?? {},
|
||||
nbformat: notebookData?.metadata?.custom?.nbformat ?? NBFORMAT,
|
||||
nbformat_minor: notebookData?.metadata?.custom?.nbformat_minor ?? NBFORMAT_MINOR
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function convertToVSCodeNotebookData(notebook: azdata.nb.INotebookContents): vscode.NotebookData {
|
||||
let result: vscode.NotebookData = {
|
||||
cells: notebook.cells?.map<vscode.NotebookCellData>(cell => {
|
||||
return {
|
||||
kind: cell.cell_type === CellTypes.Code ? NotebookCellKind.Code : NotebookCellKind.Markup,
|
||||
value: Array.isArray(cell.source) ? cell.source.join('') : cell.source,
|
||||
languageId: cell.metadata?.language ?? notebook.metadata.language_info?.name,
|
||||
outputs: cell.outputs?.map<vscode.NotebookCellOutput>(output => convertToVSCodeCellOutput(output)),
|
||||
executionSummary: {
|
||||
executionOrder: cell.execution_count
|
||||
},
|
||||
metadata: {
|
||||
custom: {
|
||||
metadata: cell.metadata
|
||||
}
|
||||
}
|
||||
};
|
||||
}),
|
||||
metadata: {
|
||||
custom: {
|
||||
metadata: notebook.metadata,
|
||||
nbformat: notebook.nbformat,
|
||||
nbformat_minor: notebook.nbformat_minor
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
// #region .NET Interactive Kernel Metadata Conversion
|
||||
|
||||
/*
|
||||
Since ADS relies on notebook kernelSpecs for provider metadata in a lot of places, we have to convert
|
||||
a .NET Interactive notebook's Jupyter kernelSpec to an internal representation so that it matches up with
|
||||
the contributed .NET Interactive notebook provider from the Jupyter extension. When saving a notebook, we
|
||||
then need to restore the original kernelSpec state so that it will work with other notebook apps like
|
||||
VS Code. VS Code does something similar by shifting a Jupyter notebook's original metadata over to a new
|
||||
"custom" field, which is then shifted back when saving the notebook.
|
||||
|
||||
This is an example of an internal kernel representation we use to get compatibility working (C#, in this case):
|
||||
kernelSpec: {
|
||||
name: 'jupyter-notebook', // Matches the name of the notebook provider from the Jupyter extension
|
||||
language: 'dotnet-interactive.csharp', // Matches the contributed languages from the .NET Interactive extension
|
||||
display_name: '.NET Interactive' // The kernel name we need to show in our dropdown to match VS Code's kernel dropdown
|
||||
}
|
||||
|
||||
This is how that C# kernel spec would need to be saved to work in VS Code:
|
||||
kernelSpec: {
|
||||
name: '.net-csharp',
|
||||
language: 'C#',
|
||||
display_name: '.NET (C#)'
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Stores equivalent external kernel metadata in a newly created .NET Interactive notebook, which is used as the default metadata when saving the notebook. This is so that ADS notebooks are still usable in other apps.
|
||||
* @param kernelSpec The notebook kernel metadata to be modified.
|
||||
*/
|
||||
export function addExternalInteractiveKernelMetadata(kernelSpec: azdata.nb.IKernelSpec): void {
|
||||
if (kernelSpec.name === 'jupyter-notebook' && kernelSpec.display_name === DotnetInteractiveDisplayName && kernelSpec.language) {
|
||||
let language = kernelSpec.language.replace(DotnetInteractiveLanguagePrefix, '');
|
||||
let displayLanguage: string;
|
||||
switch (language) {
|
||||
case 'csharp':
|
||||
displayLanguage = 'C#';
|
||||
break;
|
||||
case 'fsharp':
|
||||
displayLanguage = 'F#';
|
||||
break;
|
||||
case 'pwsh':
|
||||
displayLanguage = 'PowerShell';
|
||||
break;
|
||||
default:
|
||||
displayLanguage = language;
|
||||
}
|
||||
if (!kernelSpec.oldName) {
|
||||
kernelSpec.oldName = `${DotnetInteractiveJupyterKernelPrefix}${language}`;
|
||||
}
|
||||
if (!kernelSpec.oldDisplayName) {
|
||||
kernelSpec.oldDisplayName = `.NET (${displayLanguage})`;
|
||||
}
|
||||
if (!kernelSpec.oldLanguage) {
|
||||
kernelSpec.oldLanguage = displayLanguage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a .NET Interactive notebook's metadata to an internal representation needed for VS Code notebook compatibility. This metadata is then restored when saving the notebook.
|
||||
* @param metadata The notebook metadata to be modified.
|
||||
*/
|
||||
export function convertToInternalInteractiveKernelMetadata(metadata: azdata.nb.INotebookMetadata | undefined): void {
|
||||
if (metadata?.kernelspec?.name?.startsWith(DotnetInteractiveJupyterKernelPrefix)) {
|
||||
metadata.kernelspec.oldDisplayName = metadata.kernelspec.display_name;
|
||||
metadata.kernelspec.display_name = DotnetInteractiveDisplayName;
|
||||
|
||||
let kernelName = metadata.kernelspec.name;
|
||||
let baseLanguageName = kernelName.replace(DotnetInteractiveJupyterKernelPrefix, '');
|
||||
if (baseLanguageName === 'powershell') {
|
||||
baseLanguageName = 'pwsh';
|
||||
}
|
||||
let languageName = `${DotnetInteractiveLanguagePrefix}${baseLanguageName}`;
|
||||
|
||||
metadata.kernelspec.oldLanguage = metadata.kernelspec.language;
|
||||
metadata.kernelspec.language = languageName;
|
||||
|
||||
metadata.language_info.oldName = metadata.language_info.name;
|
||||
metadata.language_info.name = languageName;
|
||||
}
|
||||
}
|
||||
|
||||
// #endregion
|
||||
@@ -1,347 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import type * as azdata from 'azdata';
|
||||
import { ADSNotebookController } from 'sql/workbench/api/common/notebooks/adsNotebookController';
|
||||
import * as nls from 'vs/nls';
|
||||
import { addExternalInteractiveKernelMetadata, convertToVSCodeNotebookCell } from 'sql/workbench/api/common/notebooks/notebookUtils';
|
||||
import { CellTypes } from 'sql/workbench/services/notebook/common/contracts';
|
||||
import { VSCodeNotebookDocument } from 'sql/workbench/api/common/notebooks/vscodeNotebookDocument';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { notebookMultipleRequestsError } from 'sql/workbench/common/constants';
|
||||
|
||||
class VSCodeFuture implements azdata.nb.IFuture {
|
||||
private _inProgress = true;
|
||||
|
||||
constructor(private readonly _executeCompletion: Promise<void>) {
|
||||
}
|
||||
|
||||
dispose() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
public get inProgress(): boolean {
|
||||
return this._inProgress;
|
||||
}
|
||||
|
||||
public set inProgress(value: boolean) {
|
||||
this._inProgress = value;
|
||||
}
|
||||
|
||||
public get msg(): azdata.nb.IMessage | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public get done(): Thenable<azdata.nb.IShellMessage | undefined> {
|
||||
return this._executeCompletion.then(() => {
|
||||
return undefined;
|
||||
}).finally(() => {
|
||||
this._inProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
setReplyHandler(handler: azdata.nb.MessageHandler<azdata.nb.IShellMessage>): void {
|
||||
// No-op
|
||||
}
|
||||
|
||||
setStdInHandler(handler: azdata.nb.MessageHandler<azdata.nb.IStdinMessage>): void {
|
||||
// No-op
|
||||
}
|
||||
|
||||
setIOPubHandler(handler: azdata.nb.MessageHandler<azdata.nb.IIOPubMessage>): void {
|
||||
// No-op
|
||||
}
|
||||
|
||||
registerMessageHook(hook: (msg: azdata.nb.IIOPubMessage) => boolean | Thenable<boolean>): void {
|
||||
// No-op
|
||||
}
|
||||
|
||||
removeMessageHook(hook: (msg: azdata.nb.IIOPubMessage) => boolean | Thenable<boolean>): void {
|
||||
// No-op
|
||||
}
|
||||
|
||||
sendInputReply(content: azdata.nb.IInputReply): void {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
|
||||
class VSCodeKernel implements azdata.nb.IKernel {
|
||||
protected static kernelId = 0;
|
||||
private readonly _id: string;
|
||||
private readonly _name: string;
|
||||
private readonly _info: azdata.nb.IInfoReply;
|
||||
private readonly _kernelSpec: azdata.nb.IKernelSpec;
|
||||
private _activeRequest: azdata.nb.IExecuteRequest;
|
||||
|
||||
constructor(private readonly _controller: ADSNotebookController, private readonly _options: azdata.nb.ISessionOptions) {
|
||||
this._id = this._options.kernelId ?? (VSCodeKernel.kernelId++).toString();
|
||||
this._kernelSpec = this._options.kernelSpec ?? {
|
||||
name: this._controller.notebookType,
|
||||
display_name: this._controller.label,
|
||||
};
|
||||
if (!this._kernelSpec.language) {
|
||||
this._kernelSpec.language = this._controller.supportedLanguages[0];
|
||||
this._kernelSpec.supportedLanguages = this._controller.supportedLanguages;
|
||||
}
|
||||
|
||||
// Store external kernel names for .NET Interactive kernels for when notebook gets saved, so that notebook is usable outside of ADS
|
||||
addExternalInteractiveKernelMetadata(this._kernelSpec);
|
||||
|
||||
this._name = this._kernelSpec.name;
|
||||
this._info = {
|
||||
protocol_version: '',
|
||||
implementation: '',
|
||||
implementation_version: '',
|
||||
language_info: {
|
||||
name: this._kernelSpec.language,
|
||||
oldName: this._kernelSpec.oldLanguage
|
||||
},
|
||||
banner: '',
|
||||
help_links: [{
|
||||
text: '',
|
||||
url: ''
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
public get id(): string {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
public get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
public get supportsIntellisense(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
public get requiresConnection(): boolean | undefined {
|
||||
return false;
|
||||
}
|
||||
|
||||
public get isReady(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
public get ready(): Thenable<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public get info(): azdata.nb.IInfoReply | null {
|
||||
return this._info;
|
||||
}
|
||||
|
||||
public get spec(): azdata.nb.IKernelSpec {
|
||||
return this._kernelSpec;
|
||||
}
|
||||
|
||||
getSpec(): Thenable<azdata.nb.IKernelSpec> {
|
||||
return Promise.resolve(this.spec);
|
||||
}
|
||||
|
||||
private cleanUpActiveExecution(cellUri: URI) {
|
||||
this._activeRequest = undefined;
|
||||
this._controller.removeCellExecution(cellUri);
|
||||
}
|
||||
|
||||
requestExecute(content: azdata.nb.IExecuteRequest, disposeOnDone?: boolean): azdata.nb.IFuture {
|
||||
if (this._activeRequest) {
|
||||
throw new Error(notebookMultipleRequestsError);
|
||||
}
|
||||
let executePromise: Promise<void>;
|
||||
if (this._controller.executeHandler) {
|
||||
let cell = convertToVSCodeNotebookCell(CellTypes.Code, content.cellIndex, content.cellUri, content.notebookUri, content.language ?? this._kernelSpec.language, content.code);
|
||||
this._activeRequest = content;
|
||||
executePromise = Promise.resolve(this._controller.executeHandler([cell], cell.notebook, this._controller)).then(() => this.cleanUpActiveExecution(content.cellUri));
|
||||
} else {
|
||||
executePromise = Promise.resolve();
|
||||
}
|
||||
|
||||
return new VSCodeFuture(executePromise);
|
||||
}
|
||||
|
||||
requestComplete(content: azdata.nb.ICompleteRequest): Thenable<azdata.nb.ICompleteReplyMsg> {
|
||||
let response: Partial<azdata.nb.ICompleteReplyMsg> = {};
|
||||
return Promise.resolve(response as azdata.nb.ICompleteReplyMsg);
|
||||
}
|
||||
|
||||
public async interrupt(): Promise<void> {
|
||||
if (this._activeRequest) {
|
||||
if (this._controller.interruptHandler) {
|
||||
let doc = this._controller.getNotebookDocument(this._activeRequest.notebookUri);
|
||||
await this._controller.interruptHandler.call(this._controller, new VSCodeNotebookDocument(doc));
|
||||
} else {
|
||||
let exec = this._controller.getCellExecution(this._activeRequest.cellUri);
|
||||
exec?.tokenSource.cancel();
|
||||
}
|
||||
this.cleanUpActiveExecution(this._activeRequest.cellUri);
|
||||
}
|
||||
}
|
||||
|
||||
public async restart(): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
class VSCodeSession implements azdata.nb.ISession {
|
||||
private _kernel: VSCodeKernel;
|
||||
private _defaultKernelLoaded = false;
|
||||
constructor(controller: ADSNotebookController, private readonly _options: azdata.nb.ISessionOptions) {
|
||||
this._kernel = new VSCodeKernel(controller, this._options);
|
||||
}
|
||||
|
||||
public set defaultKernelLoaded(value) {
|
||||
this._defaultKernelLoaded = value;
|
||||
}
|
||||
|
||||
public get defaultKernelLoaded(): boolean {
|
||||
return this._defaultKernelLoaded;
|
||||
}
|
||||
|
||||
public get canChangeKernels(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
public get id(): string {
|
||||
return this._options.kernelId || this._kernel ? this._kernel.id : '';
|
||||
}
|
||||
|
||||
public get path(): string {
|
||||
return this._options.path;
|
||||
}
|
||||
|
||||
public get name(): string {
|
||||
return this._options.name || '';
|
||||
}
|
||||
|
||||
public get type(): string {
|
||||
return this._options.type || '';
|
||||
}
|
||||
|
||||
public get status(): azdata.nb.KernelStatus {
|
||||
return 'connected';
|
||||
}
|
||||
|
||||
public get vsKernel(): VSCodeKernel {
|
||||
return this._kernel;
|
||||
}
|
||||
|
||||
public get kernel(): azdata.nb.IKernel {
|
||||
return this.vsKernel;
|
||||
}
|
||||
|
||||
changeKernel(kernelInfo: azdata.nb.IKernelSpec): Thenable<azdata.nb.IKernel> {
|
||||
return Promise.resolve(this._kernel);
|
||||
}
|
||||
|
||||
configureKernel(kernelInfo: azdata.nb.IKernelSpec): Thenable<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
configureConnection(connection: azdata.IConnectionProfile): Thenable<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
class VSCodeSessionManager implements azdata.nb.SessionManager {
|
||||
private _sessions: VSCodeSession[] = [];
|
||||
|
||||
constructor(private readonly _controller: ADSNotebookController) {
|
||||
}
|
||||
|
||||
public get isReady(): boolean {
|
||||
return this._controller.supportedLanguages?.length > 0 && this._controller.executeHandler !== undefined;
|
||||
}
|
||||
|
||||
public get ready(): Thenable<void> {
|
||||
return Promise.all([this._controller.languagesAdded, this._controller.executionHandlerAdded]).then();
|
||||
}
|
||||
|
||||
public get specs(): azdata.nb.IAllKernels {
|
||||
// Have to return the default kernel here, since the manager specs are accessed before kernels get added
|
||||
let defaultKernel: azdata.nb.IKernelSpec = {
|
||||
name: this._controller.notebookType,
|
||||
language: this._controller.supportedLanguages[0],
|
||||
display_name: this._controller.label,
|
||||
supportedLanguages: this._controller.supportedLanguages ?? []
|
||||
};
|
||||
return {
|
||||
defaultKernel: defaultKernel.name,
|
||||
kernels: [defaultKernel]
|
||||
};
|
||||
}
|
||||
|
||||
public async startNew(options: azdata.nb.ISessionOptions): Promise<azdata.nb.ISession> {
|
||||
if (!this.isReady) {
|
||||
return Promise.reject(new Error(nls.localize('errorStartBeforeReady', "Cannot start a session, the manager is not yet initialized")));
|
||||
}
|
||||
let session = new VSCodeSession(this._controller, options);
|
||||
let index = this._sessions.findIndex(session => session.path === options.path);
|
||||
if (index > -1) {
|
||||
this._sessions.splice(index);
|
||||
}
|
||||
this._sessions.push(session);
|
||||
return Promise.resolve(session);
|
||||
}
|
||||
|
||||
public shutdown(id: string): Thenable<void> {
|
||||
let index = this._sessions.findIndex(session => session.id === id);
|
||||
if (index > -1) {
|
||||
this._sessions.splice(index);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public shutdownAll(): Thenable<void> {
|
||||
return Promise.all(this._sessions.map(session => {
|
||||
return this.shutdown(session.id);
|
||||
})).then();
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
|
||||
class VSCodeExecuteManager implements azdata.nb.ExecuteManager {
|
||||
public readonly providerId: string;
|
||||
private readonly _sessionManager: azdata.nb.SessionManager;
|
||||
|
||||
constructor(controller: ADSNotebookController) {
|
||||
this.providerId = controller.notebookType;
|
||||
this._sessionManager = new VSCodeSessionManager(controller);
|
||||
}
|
||||
|
||||
public get sessionManager(): azdata.nb.SessionManager {
|
||||
return this._sessionManager;
|
||||
}
|
||||
|
||||
public get serverManager(): azdata.nb.ServerManager | undefined {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Notebook Execute Provider that is used to convert VS Code notebook extension APIs into ADS equivalents.
|
||||
*/
|
||||
export class VSCodeExecuteProvider implements azdata.nb.NotebookExecuteProvider {
|
||||
public readonly providerId: string;
|
||||
private readonly _executeManager: azdata.nb.ExecuteManager;
|
||||
|
||||
constructor(controller: ADSNotebookController) {
|
||||
this._executeManager = new VSCodeExecuteManager(controller);
|
||||
this.providerId = controller.notebookType;
|
||||
}
|
||||
|
||||
public getExecuteManager(notebookUri: vscode.Uri): Thenable<azdata.nb.ExecuteManager> {
|
||||
return Promise.resolve(this._executeManager);
|
||||
}
|
||||
|
||||
public handleNotebookClosed(notebookUri: vscode.Uri): void {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import type * as azdata from 'azdata';
|
||||
import { convertToVSCodeNotebookCell } from 'sql/workbench/api/common/notebooks/notebookUtils';
|
||||
|
||||
export class VSCodeNotebookDocument implements vscode.NotebookDocument {
|
||||
private readonly _convertedCells: vscode.NotebookCell[];
|
||||
|
||||
constructor(private readonly _notebookDoc: azdata.nb.NotebookDocument) {
|
||||
this._convertedCells = this._notebookDoc.cells?.map((cell, index) => convertToVSCodeNotebookCell(cell.contents.cell_type, index, cell.uri, this._notebookDoc.uri, cell.contents.metadata?.language, cell.contents.source));
|
||||
}
|
||||
|
||||
public get uri() { return this._notebookDoc.uri; }
|
||||
|
||||
public get version() { return undefined; }
|
||||
|
||||
public get notebookType() { return this._notebookDoc.providerId; }
|
||||
|
||||
public get isDirty() { return this._notebookDoc.isDirty; }
|
||||
|
||||
public get isUntitled() { return this._notebookDoc.isUntitled; }
|
||||
|
||||
public get isClosed() { return this._notebookDoc.isClosed; }
|
||||
|
||||
public get metadata() { return {}; }
|
||||
|
||||
public get cellCount() { return this._notebookDoc.cells?.length; }
|
||||
|
||||
cellAt(index: number): vscode.NotebookCell {
|
||||
if (this._notebookDoc.cells) {
|
||||
if (index < 0) {
|
||||
index = 0;
|
||||
} else if (index >= this._notebookDoc.cells.length) {
|
||||
index = this._convertedCells.length - 1;
|
||||
}
|
||||
return this._convertedCells[index];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getCells(range?: vscode.NotebookRange): vscode.NotebookCell[] {
|
||||
let cells: vscode.NotebookCell[] = [];
|
||||
if (range) {
|
||||
cells = this._convertedCells?.slice(range.start, range.end);
|
||||
} else {
|
||||
cells = this._convertedCells;
|
||||
}
|
||||
return cells;
|
||||
}
|
||||
|
||||
save(): Thenable<boolean> {
|
||||
return this._notebookDoc.save();
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import type * as azdata from 'azdata';
|
||||
import { VSCodeNotebookDocument } from 'sql/workbench/api/common/notebooks/vscodeNotebookDocument';
|
||||
import { functionalityNotSupportedError } from 'sql/base/common/locConstants';
|
||||
|
||||
export class VSCodeNotebookEditor implements vscode.NotebookEditor {
|
||||
private readonly _document: vscode.NotebookDocument;
|
||||
|
||||
constructor(editor: azdata.nb.NotebookEditor) {
|
||||
if (editor) {
|
||||
this._document = new VSCodeNotebookDocument(editor.document);
|
||||
}
|
||||
}
|
||||
|
||||
public get document(): vscode.NotebookDocument {
|
||||
return this._document;
|
||||
}
|
||||
|
||||
public get selections(): vscode.NotebookRange[] {
|
||||
throw new Error(functionalityNotSupportedError);
|
||||
}
|
||||
|
||||
public get visibleRanges(): vscode.NotebookRange[] {
|
||||
throw new Error(functionalityNotSupportedError);
|
||||
}
|
||||
|
||||
public get viewColumn(): vscode.ViewColumn | undefined {
|
||||
throw new Error(functionalityNotSupportedError);
|
||||
}
|
||||
|
||||
public revealRange(range: vscode.NotebookRange, revealType?: vscode.NotebookEditorRevealType): void {
|
||||
throw new Error(functionalityNotSupportedError);
|
||||
}
|
||||
|
||||
public edit(callback: (editBuilder: vscode.NotebookEditorEdit) => void): Promise<boolean> {
|
||||
return Promise.reject(functionalityNotSupportedError);
|
||||
}
|
||||
|
||||
public setDecorations(decorationType: vscode.NotebookEditorDecorationType, range: vscode.NotebookRange): void {
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import type * as azdata from 'azdata';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { convertToADSNotebookContents, convertToVSCodeNotebookData } from 'sql/workbench/api/common/notebooks/notebookUtils';
|
||||
|
||||
export class VSCodeContentManager implements azdata.nb.ContentManager {
|
||||
constructor(private readonly _serializer: vscode.NotebookSerializer) {
|
||||
}
|
||||
|
||||
public async deserializeNotebook(contents: string): Promise<azdata.nb.INotebookContents> {
|
||||
let buffer = VSBuffer.fromString(contents);
|
||||
let notebookData = await this._serializer.deserializeNotebook(buffer.buffer, CancellationToken.None);
|
||||
return convertToADSNotebookContents(notebookData);
|
||||
}
|
||||
|
||||
public async serializeNotebook(notebook: azdata.nb.INotebookContents): Promise<string> {
|
||||
let notebookData = convertToVSCodeNotebookData(notebook);
|
||||
let bytes = await this._serializer.serializeNotebook(notebookData, CancellationToken.None);
|
||||
let buffer = VSBuffer.wrap(bytes);
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class VSCodeSerializationManager implements azdata.nb.SerializationManager {
|
||||
private _manager: VSCodeContentManager;
|
||||
|
||||
constructor(serializer: vscode.NotebookSerializer) {
|
||||
this._manager = new VSCodeContentManager(serializer);
|
||||
}
|
||||
|
||||
public get contentManager(): azdata.nb.ContentManager {
|
||||
return this._manager;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Notebook Serialization Provider that is used to convert VS Code notebook extension APIs into ADS equivalents.
|
||||
*/
|
||||
export class VSCodeSerializationProvider implements azdata.nb.NotebookSerializationProvider {
|
||||
private _manager: VSCodeSerializationManager;
|
||||
|
||||
constructor(public readonly providerId: string, serializer: vscode.NotebookSerializer) {
|
||||
this._manager = new VSCodeSerializationManager(serializer);
|
||||
}
|
||||
|
||||
public getSerializationManager(notebookUri: vscode.Uri): Thenable<azdata.nb.SerializationManager> {
|
||||
return Promise.resolve(this._manager);
|
||||
}
|
||||
}
|
||||
@@ -53,18 +53,16 @@ export interface IExtensionApiFactory {
|
||||
|
||||
export interface IAdsExtensionApiFactory {
|
||||
azdata: IAzdataExtensionApiFactory;
|
||||
extHostNotebook: ExtHostNotebook;
|
||||
extHostNotebookDocumentsAndEditors: ExtHostNotebookDocumentsAndEditors;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method instantiates and returns the extension API surface
|
||||
*/
|
||||
export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): IExtensionApiFactory {
|
||||
const { azdata, extHostNotebook, extHostNotebookDocumentsAndEditors } = createAdsApiFactory(accessor);
|
||||
const { azdata } = createAdsApiFactory(accessor);
|
||||
return {
|
||||
azdata,
|
||||
vscode: vsApiFactory(accessor, extHostNotebook, extHostNotebookDocumentsAndEditors)
|
||||
vscode: vsApiFactory(accessor)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -99,7 +97,7 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp
|
||||
const extHostModelViewDialog = rpcProtocol.set(SqlExtHostContext.ExtHostModelViewDialog, new ExtHostModelViewDialog(rpcProtocol, extHostModelView, extHostBackgroundTaskManagement));
|
||||
const extHostQueryEditor = rpcProtocol.set(SqlExtHostContext.ExtHostQueryEditor, new ExtHostQueryEditor(rpcProtocol));
|
||||
const extHostNotebookDocumentsAndEditors = rpcProtocol.set(SqlExtHostContext.ExtHostNotebookDocumentsAndEditors, new ExtHostNotebookDocumentsAndEditors(rpcProtocol));
|
||||
const extHostNotebook = rpcProtocol.set(SqlExtHostContext.ExtHostNotebook, new ExtHostNotebook(rpcProtocol, extHostNotebookDocumentsAndEditors));
|
||||
const extHostNotebook = rpcProtocol.set(SqlExtHostContext.ExtHostNotebook, new ExtHostNotebook(rpcProtocol));
|
||||
const extHostExtensionManagement = rpcProtocol.set(SqlExtHostContext.ExtHostExtensionManagement, new ExtHostExtensionManagement(rpcProtocol));
|
||||
const extHostWorkspace = rpcProtocol.set(SqlExtHostContext.ExtHostWorkspace, new ExtHostWorkspace(rpcProtocol));
|
||||
return {
|
||||
@@ -670,8 +668,6 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp
|
||||
executionPlan: executionPlan,
|
||||
env
|
||||
};
|
||||
},
|
||||
extHostNotebook: extHostNotebook,
|
||||
extHostNotebookDocumentsAndEditors: extHostNotebookDocumentsAndEditors
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -935,8 +935,6 @@ export interface MainThreadNotebookShape extends IDisposable {
|
||||
$unregisterExecuteProvider(handle: number): void;
|
||||
$onFutureMessage(futureId: number, type: FutureMessageType, payload: azdata.nb.IMessage): void;
|
||||
$onFutureDone(futureId: number, done: INotebookFutureDone): void;
|
||||
$updateProviderKernels(providerId: string, languages: azdata.nb.IStandardKernel[]): void;
|
||||
$updateKernelLanguages(providerId: string, kernelName: string, languages: string[]): void;
|
||||
}
|
||||
|
||||
export interface INotebookDocumentsAndEditorsDelta {
|
||||
@@ -991,7 +989,6 @@ export interface ExtHostNotebookDocumentsAndEditorsShape {
|
||||
export interface MainThreadNotebookDocumentsAndEditorsShape extends IDisposable {
|
||||
$trySetTrusted(_uri: UriComponents, isTrusted: boolean): Thenable<boolean>;
|
||||
$trySaveDocument(uri: UriComponents): Thenable<boolean>;
|
||||
$tryCreateNotebookDocument(providerId: string, contents?: azdata.nb.INotebookContents): Promise<UriComponents>;
|
||||
$tryShowNotebookDocument(resource: UriComponents, options: INotebookShowOptions): Promise<string>;
|
||||
$tryApplyEdits(id: string, modelVersionId: number, edits: INotebookEditOperation[], opts: IUndoStopOptions): Promise<boolean>;
|
||||
$runCell(id: string, cellUri: UriComponents): Promise<boolean>;
|
||||
|
||||
@@ -561,12 +561,6 @@ export interface ICellMetadata {
|
||||
tags?: string[] | undefined;
|
||||
azdata_cell_guid?: string | undefined;
|
||||
connection_name?: string;
|
||||
/**
|
||||
* .NET Interactive metadata. This is only required for compatibility with the .NET Interactive extension.
|
||||
*/
|
||||
dotnet_interactive?: {
|
||||
language: string;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ISerializationManagerDetails {
|
||||
|
||||
Reference in New Issue
Block a user