Skip to content

Commit b9c163f

Browse files
committed
asWebUri.
1 parent 48539ee commit b9c163f

17 files changed

Lines changed: 222 additions & 137 deletions

extensions/vscode-notebook-tests/src/notebook.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,3 +345,15 @@ suite('regression', () => {
345345
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');
346346
});
347347
});
348+
349+
suite('webview resource uri', () => {
350+
test('asWebviewUri', async function () {
351+
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
352+
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
353+
354+
await waitFor(500);
355+
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
356+
const uri = vscode.notebook.activeNotebookEditor!.asWebviewUri(vscode.Uri.parse('./hello.png'));
357+
assert.equal(uri.scheme, 'vscode-resource');
358+
});
359+
});

src/vs/vscode.proposed.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,11 @@ declare module 'vscode' {
17321732
*/
17331733
postMessage(message: any): Thenable<boolean>;
17341734

1735+
/**
1736+
* Convert a uri for the local file system to one that can be used inside outputs webview.
1737+
*/
1738+
asWebviewUri(localResource: Uri): Uri;
1739+
17351740
edit(callback: (editBuilder: NotebookEditorCellEdit) => void): Thenable<boolean>;
17361741
}
17371742

@@ -1794,6 +1799,8 @@ declare module 'vscode' {
17941799
// revert?(document: NotebookDocument, cancellation: CancellationToken): Thenable<void>;
17951800
// backup?(document: NotebookDocument, cancellation: CancellationToken): Thenable<CustomDocumentBackup>;
17961801

1802+
kernel?: NotebookKernel;
1803+
17971804
/**
17981805
* Responsible for filling in outputs for the cell
17991806
*/

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

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
1717
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
1818
import { IRelativePattern } from 'vs/base/common/glob';
1919
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
20+
import { generateUuid } from 'vs/base/common/uuid';
2021

2122
export class MainThreadNotebookDocument extends Disposable {
2223
private _textModel: NotebookTextModel;
@@ -29,10 +30,11 @@ export class MainThreadNotebookDocument extends Disposable {
2930
private readonly _proxy: ExtHostNotebookShape,
3031
public handle: number,
3132
public viewType: string,
32-
public uri: URI
33+
public uri: URI,
34+
public webviewId: string,
3335
) {
3436
super();
35-
this._textModel = new NotebookTextModel(handle, viewType, uri);
37+
this._textModel = new NotebookTextModel(handle, viewType, uri, webviewId);
3638
this._register(this._textModel.onDidModelChange(e => {
3739
this._proxy.$acceptModelChanged(this.uri, e);
3840
}));
@@ -121,8 +123,8 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
121123
this._notebookService.unregisterNotebookRenderer(handle);
122124
}
123125

124-
async $registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string): Promise<void> {
125-
let controller = new MainThreadNotebookController(this._proxy, this, viewType);
126+
async $registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, hasKernelSupport: boolean): Promise<void> {
127+
let controller = new MainThreadNotebookController(this._proxy, this, viewType, hasKernelSupport);
126128
this._notebookProviders.set(viewType, controller);
127129
this._notebookService.registerNotebookController(viewType, extension, controller);
128130
return;
@@ -176,8 +178,8 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
176178
controller?.spliceNotebookCellOutputs(resource, cellHandle, splices, renderers);
177179
}
178180

179-
async executeNotebook(viewType: string, uri: URI, token: CancellationToken): Promise<void> {
180-
return this._proxy.$executeNotebook(viewType, uri, undefined, token);
181+
async executeNotebook(viewType: string, uri: URI, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
182+
return this._proxy.$executeNotebook(viewType, uri, undefined, useAttachedKernel, token);
181183
}
182184

183185
async $postMessage(handle: number, value: any): Promise<boolean> {
@@ -203,7 +205,8 @@ export class MainThreadNotebookController implements IMainNotebookController {
203205
constructor(
204206
private readonly _proxy: ExtHostNotebookShape,
205207
private _mainThreadNotebook: MainThreadNotebooks,
206-
private _viewType: string
208+
private _viewType: string,
209+
readonly hasKernelSupport: boolean
207210
) {
208211
}
209212

@@ -227,7 +230,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
227230
return mainthreadNotebook.textModel;
228231
}
229232

230-
let document = new MainThreadNotebookDocument(this._proxy, MainThreadNotebookController.documentHandle++, viewType, uri);
233+
let document = new MainThreadNotebookDocument(this._proxy, MainThreadNotebookController.documentHandle++, viewType, uri, generateUuid());
231234
await this.createNotebookDocument(document);
232235

233236
if (forBackup) {
@@ -272,8 +275,8 @@ export class MainThreadNotebookController implements IMainNotebookController {
272275
mainthreadNotebook?.textModel.$spliceNotebookCellOutputs(cellHandle, splices);
273276
}
274277

275-
async executeNotebook(viewType: string, uri: URI, token: CancellationToken): Promise<void> {
276-
return this._mainThreadNotebook.executeNotebook(viewType, uri, token);
278+
async executeNotebook(viewType: string, uri: URI, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
279+
return this._mainThreadNotebook.executeNotebook(viewType, uri, useAttachedKernel, token);
277280
}
278281

279282
onDidReceiveMessage(uri: UriComponents, message: any): void {
@@ -287,6 +290,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
287290
addedDocuments: [{
288291
viewType: document.viewType,
289292
handle: document.handle,
293+
webviewId: document.webviewId,
290294
uri: document.uri,
291295
metadata: document.textModel.metadata
292296
}]
@@ -327,8 +331,8 @@ export class MainThreadNotebookController implements IMainNotebookController {
327331
document?.textModel.updateRenderers(renderers);
328332
}
329333

330-
async executeNotebookCell(uri: URI, handle: number, token: CancellationToken): Promise<void> {
331-
return this._proxy.$executeNotebook(this._viewType, uri, handle, token);
334+
async executeNotebookCell(uri: URI, handle: number, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
335+
return this._proxy.$executeNotebook(this._viewType, uri, handle, useAttachedKernel, token);
332336
}
333337

334338
async save(uri: URI, token: CancellationToken): Promise<boolean> {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
134134
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
135135
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
136136
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol));
137-
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors));
137+
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, initData.environment));
138138
const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol));
139139
const extHostAuthentication = rpcProtocol.set(ExtHostContext.ExtHostAuthentication, new ExtHostAuthentication(rpcProtocol));
140140
const extHostTimeline = rpcProtocol.set(ExtHostContext.ExtHostTimeline, new ExtHostTimeline(rpcProtocol, extHostCommands));

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ export type NotebookCellOutputsSplice = [
689689
];
690690

691691
export interface MainThreadNotebookShape extends IDisposable {
692-
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string): Promise<void>;
692+
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, hasKernelSupport: boolean): Promise<void>;
693693
$unregisterNotebookProvider(viewType: string): Promise<void>;
694694
$registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, handle: number, preloads: UriComponents[]): Promise<void>;
695695
$unregisterNotebookRenderer(handle: number): Promise<void>;
@@ -1545,6 +1545,7 @@ export interface INotebookEditorPropertiesChangeData {
15451545
export interface INotebookModelAddedData {
15461546
uri: UriComponents;
15471547
handle: number;
1548+
webviewId: string;
15481549
// versionId: number;
15491550
viewType: string;
15501551
metadata?: NotebookDocumentMetadata;
@@ -1560,7 +1561,7 @@ export interface INotebookDocumentsAndEditorsDelta {
15601561

15611562
export interface ExtHostNotebookShape {
15621563
$resolveNotebookData(viewType: string, uri: UriComponents): Promise<NotebookDataDto | undefined>;
1563-
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
1564+
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void>;
15641565
$executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
15651566
$saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean>;
15661567
$saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean>;

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

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
1919
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
2020
import { NotImplementedProxy } from 'vs/base/common/types';
2121
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
22+
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
2223

2324
interface IObservable<T> {
2425
proxy: T;
@@ -498,6 +499,8 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
498499
public uri: URI,
499500
private _proxy: MainThreadNotebookShape,
500501
private _onDidReceiveMessage: Emitter<any>,
502+
private _webviewId: string,
503+
private _webviewInitData: WebviewInitData,
501504
public document: ExtHostNotebookDocument,
502505
private _documentsAndEditors: ExtHostDocumentsAndEditors
503506
) {
@@ -585,6 +588,9 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
585588
return this._proxy.$postMessage(this.document.handle, message);
586589
}
587590

591+
asWebviewUri(localResource: vscode.Uri): vscode.Uri {
592+
return asWebviewUri(this._webviewInitData, this._webviewId, localResource);
593+
}
588594
}
589595

590596
export class ExtHostNotebookOutputRenderer {
@@ -656,7 +662,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
656662
private _onDidCloseNotebookDocument = new Emitter<vscode.NotebookDocument>();
657663
onDidCloseNotebookDocument: Event<vscode.NotebookDocument> = this._onDidCloseNotebookDocument.event;
658664

659-
constructor(mainContext: IMainContext, commands: ExtHostCommands, private _documentsAndEditors: ExtHostDocumentsAndEditors) {
665+
constructor(mainContext: IMainContext, commands: ExtHostCommands, private _documentsAndEditors: ExtHostDocumentsAndEditors, private readonly _webviewInitData: WebviewInitData) {
660666
this._proxy = mainContext.getProxy(MainContext.MainThreadNotebook);
661667

662668
commands.registerArgumentProcessor({
@@ -716,7 +722,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
716722
}
717723

718724
this._notebookContentProviders.set(viewType, { extension, provider });
719-
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType);
725+
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType, !!provider.kernel);
720726
return new VSCodeDisposable(() => {
721727
this._notebookContentProviders.delete(viewType);
722728
this._proxy.$unregisterNotebookProvider(viewType);
@@ -833,17 +839,26 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
833839
};
834840
}
835841

836-
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
842+
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
837843
let document = this._documents.get(URI.revive(uri).toString());
838844

839845
if (!document) {
840846
return;
841847
}
842848

843849
if (this._notebookContentProviders.has(viewType)) {
844-
let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
850+
const cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
851+
const provider = this._notebookContentProviders.get(viewType)!.provider;
845852

846-
return this._notebookContentProviders.get(viewType)!.provider.executeCell(document, cell, token);
853+
if (provider.kernel && useAttachedKernel) {
854+
if (cell) {
855+
return provider.kernel.executeCell(document, cell, token);
856+
} else {
857+
return provider.kernel.executeAllCells(document, token);
858+
}
859+
} else {
860+
return provider.executeCell(document, cell, token);
861+
}
847862
}
848863
}
849864

@@ -1004,6 +1019,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
10041019
revivedUri,
10051020
this._proxy,
10061021
onDidReceiveMessage,
1022+
modelData.webviewId,
1023+
this._webviewInitData,
10071024
document,
10081025
this._documentsAndEditors
10091026
);

src/vs/workbench/contrib/notebook/browser/contrib/status/editorStatus.ts

Lines changed: 24 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,76 +3,16 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { INotebookEditor, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
6+
import { INotebookEditor, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_HAS_MULTIPLE_KERNELS } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
77
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
88
import { IQuickInputService, QuickPickInput, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
99
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
1010
import * as nls from 'vs/nls';
11-
import { registerAction2, Action2 } from 'vs/platform/actions/common/actions';
11+
import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/actions';
1212
import { NOTEBOOK_ACTIONS_CATEGORY, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
1313
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
1414
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
1515

16-
// export class NotebookEditorStatus extends Disposable implements IWorkbenchContribution {
17-
// private _localStore: DisposableStore = new DisposableStore();
18-
// private kernelInfoElement = this._register(new MutableDisposable<IStatusbarEntryAccessor>());
19-
20-
// constructor(
21-
// @IEditorService private readonly editorService: IEditorService,
22-
// @IStatusbarService private readonly statusbarService: IStatusbarService,
23-
// ) {
24-
// super();
25-
// this.registerListeners();
26-
// }
27-
28-
// private registerListeners(): void {
29-
// this._register(this.editorService.onDidActiveEditorChange(() => this.updateStatusBar()));
30-
// this.updateStatusBar();
31-
// }
32-
33-
// private async updateStatusBar(): Promise<void> {
34-
// this._localStore.clear();
35-
36-
// const activeEditorPane = this.editorService.activeEditorPane as any | undefined;
37-
// if (!activeEditorPane?.isNotebookEditor) {
38-
// this.kernelInfoElement.clear();
39-
// return;
40-
// }
41-
// const editor = activeEditorPane.getControl() as INotebookEditor;
42-
// this._localStore.add(editor.onDidChangeKernel(() => {
43-
// this.updateKernelInfo(editor.activeKernel);
44-
// }));
45-
46-
// this.updateKernelInfo(editor.activeKernel);
47-
// }
48-
49-
// private updateKernelInfo(kernelInfo: INotebookKernelInfo | undefined) {
50-
// if (!kernelInfo) {
51-
// this.kernelInfoElement.clear();
52-
// return;
53-
// }
54-
55-
// const props: IStatusbarEntry = {
56-
// text: kernelInfo.label,
57-
// ariaLabel: kernelInfo.label,
58-
// tooltip: nls.localize('selectKernel', "Select Notebook Kernel"),
59-
// command: 'notebook.selectKernel'
60-
// };
61-
62-
// this.updateElement(this.kernelInfoElement, props, 'status.notebook.kernel', nls.localize('selectKernel', "Select Notebook Kernel"), StatusbarAlignment.RIGHT, 50);
63-
// }
64-
65-
// private updateElement(element: MutableDisposable<IStatusbarEntryAccessor>, props: IStatusbarEntry, id: string, name: string, alignment: StatusbarAlignment, priority: number) {
66-
// if (!element.value) {
67-
// element.value = this.statusbarService.addEntry(props, id, name, alignment, priority);
68-
// } else {
69-
// element.value.update(props);
70-
// }
71-
// }
72-
// }
73-
74-
// Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NotebookEditorStatus, LifecyclePhase.Eventually);
75-
7616

7717
registerAction2(class extends Action2 {
7818
constructor() {
@@ -82,12 +22,12 @@ registerAction2(class extends Action2 {
8222
title: nls.localize('notebookActions.selectKernel', "Select Notebook Kernel"),
8323
precondition: ContextKeyExpr.and(NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_EDITOR_FOCUSED),
8424
icon: { id: 'codicon/server-environment' },
85-
// menu: {
86-
// id: MenuId.EditorTitle,
87-
// // when: ContextKeyExpr.and(ContextKeyEqualsExpr.create('view', that.id), that.refreshContextKey),
88-
// group: 'navigation',
89-
// order: -2,
90-
// },
25+
menu: {
26+
id: MenuId.EditorTitle,
27+
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_HAS_MULTIPLE_KERNELS),
28+
group: 'navigation',
29+
order: -2,
30+
},
9131
f1: true
9232
});
9333
}
@@ -119,6 +59,22 @@ registerAction2(class extends Action2 {
11959
};
12060
});
12161

62+
const provider = notebookService.getContributedNotebookProviders(editor.viewModel!.uri)[0];
63+
64+
if (provider.hasKernelSupport) {
65+
picks.unshift({
66+
id: provider.id,
67+
label: provider.displayName,
68+
picked: !activeKernel, // no active kernel, the builtin kernel of the provider is used
69+
description: activeKernel === undefined
70+
? nls.localize('currentActiveBuiltinKernel', " (Currently Active)")
71+
: '',
72+
run: () => {
73+
editor.activeKernel = undefined;
74+
}
75+
});
76+
}
77+
12278
const action = await quickInputService.pick(picks, { placeHolder: nls.localize('pickAction', "Select Action"), matchOnDetail: true });
12379
return action?.run();
12480

src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ export const NOTEBOOK_CELL_MARKDOWN_EDIT_MODE = new RawContextKey<boolean>('note
4747
export const NOTEBOOK_CELL_RUN_STATE = new RawContextKey<string>('notebookCellRunState', undefined); // idle, running
4848
export const NOTEBOOK_CELL_HAS_OUTPUTS = new RawContextKey<boolean>('notebookCellHasOutputs', false); // bool
4949

50+
// Kernels
51+
52+
export const NOTEBOOK_HAS_MULTIPLE_KERNELS = new RawContextKey<boolean>('notebookHasMultipleKernels', false);
53+
5054
export interface NotebookLayoutInfo {
5155
width: number;
5256
height: number;

0 commit comments

Comments
 (0)