mainThreadNotebook.ts 21.2 KB
Newer Older
R
rebornix 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
7
import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IExtHostContext, ExtHostNotebookShape, ExtHostContext, INotebookDocumentsAndEditorsDelta, INotebookModelAddedData } from '../common/extHost.protocol';
R
rebornix 已提交
8
import { Disposable, IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
R
rebornix 已提交
9
import { URI, UriComponents } from 'vs/base/common/uri';
10
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
11
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, INotebookKernelInfo, INotebookKernelInfoDto, INotebookTextModelBackup, IEditor, INotebookRendererInfo, IOutputRenderRequest, IOutputRenderResponse } from 'vs/workbench/contrib/notebook/common/notebookCommon';
R
rebornix 已提交
12
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
13
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
14 15
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
16
import { CancellationToken } from 'vs/base/common/cancellation';
R
rebornix 已提交
17
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
R
rebornix 已提交
18 19
import { IRelativePattern } from 'vs/base/common/glob';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
R
rebornix 已提交
20

21 22
export class MainThreadNotebookDocument extends Disposable {
	private _textModel: NotebookTextModel;
R
rebornix 已提交
23

24 25
	get textModel() {
		return this._textModel;
R
rebornix 已提交
26
	}
R
rebornix 已提交
27 28

	constructor(
R
rebornix 已提交
29
		private readonly _proxy: ExtHostNotebookShape,
R
rebornix 已提交
30
		public handle: number,
R
rebornix 已提交
31
		public viewType: string,
32 33
		public uri: URI,
		readonly notebookService: INotebookService
R
rebornix 已提交
34
	) {
R
rebornix 已提交
35
		super();
36
		this._textModel = new NotebookTextModel(handle, viewType, uri);
37
		this._register(this._textModel.onDidModelChangeProxy(e => {
R
rebornix 已提交
38
			this._proxy.$acceptModelChanged(this.uri, e);
39
			this._proxy.$acceptEditorPropertiesChanged(uri, { selections: { selections: this._textModel.selections }, metadata: null });
R
rebornix 已提交
40
		}));
R
rebornix 已提交
41 42
		this._register(this._textModel.onDidSelectionChange(e => {
			const selectionsChange = e ? { selections: e } : null;
R
rebornix 已提交
43
			this._proxy.$acceptEditorPropertiesChanged(uri, { selections: selectionsChange, metadata: null });
R
rebornix 已提交
44
		}));
R
rebornix 已提交
45
	}
R
rebornix 已提交
46

47 48 49
	async applyEdit(modelVersionId: number, edits: ICellEditOperation[]): Promise<boolean> {
		await this.notebookService.transformEditsOutputs(this.textModel, edits);
		return this._textModel.$applyEdit(modelVersionId, edits);
R
rebornix 已提交
50
	}
R
rebornix 已提交
51

52 53 54 55
	async spliceNotebookCellOutputs(cellHandle: number, splices: NotebookCellOutputsSplice[]) {
		await this.notebookService.transformSpliceOutputs(this.textModel, splices);
		this._textModel.$spliceNotebookCellOutputs(cellHandle, splices);
	}
R
rebornix 已提交
56
	dispose() {
57
		this._textModel.dispose();
R
rebornix 已提交
58 59
		super.dispose();
	}
R
rebornix 已提交
60 61
}

R
rebornix 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
class DocumentAndEditorState {
	static ofMaps<K, V>(before: Map<K, V>, after: Map<K, V>): { removed: V[], added: V[] } {
		const removed: V[] = [];
		const added: V[] = [];
		before.forEach((value, index) => {
			if (!after.has(index)) {
				removed.push(value);
			}
		});
		after.forEach((value, index) => {
			if (!before.has(index)) {
				added.push(value);
			}
		});
		return { removed, added };
	}

	static compute(before: DocumentAndEditorState | undefined, after: DocumentAndEditorState): INotebookDocumentsAndEditorsDelta {
		if (!before) {
			const apiEditors = [];
			for (let id in after.textEditors) {
				const editor = after.textEditors.get(id)!;
				apiEditors.push({ id, documentUri: editor.uri!, selections: editor!.textModel!.selections });
			}

			return {
				addedDocuments: [],
				addedEditors: apiEditors
			};
		}
		// const documentDelta = delta.ofSets(before.documents, after.documents);
		const editorDelta = DocumentAndEditorState.ofMaps(before.textEditors, after.textEditors);
		const addedAPIEditors = editorDelta.added.map(add => ({
			id: add.getId(),
			documentUri: add.uri!,
			selections: add.textModel!.selections
		}));

		const removedAPIEditors = editorDelta.removed.map(removed => removed.getId());

		// const oldActiveEditor = before.activeEditor !== after.activeEditor ? before.activeEditor : undefined;
		const newActiveEditor = before.activeEditor !== after.activeEditor ? after.activeEditor : undefined;

		return {
			addedEditors: addedAPIEditors,
			removedEditors: removedAPIEditors,
			newActiveEditor: newActiveEditor
		};
	}

	constructor(
		readonly documents: Set<URI>,
		readonly textEditors: Map<string, IEditor>,
		readonly activeEditor: string | null | undefined,
	) {
		//
	}
}

R
rebornix 已提交
121 122 123
@extHostNamedCustomer(MainContext.MainThreadNotebook)
export class MainThreadNotebooks extends Disposable implements MainThreadNotebookShape {
	private readonly _notebookProviders = new Map<string, MainThreadNotebookController>();
R
rebornix 已提交
124
	private readonly _notebookKernels = new Map<string, MainThreadNotebookKernel>();
125
	private readonly _notebookRenderers = new Map<string, MainThreadNotebookRenderer>();
R
rebornix 已提交
126
	private readonly _proxy: ExtHostNotebookShape;
R
rebornix 已提交
127 128
	private _toDisposeOnEditorRemove = new Map<string, IDisposable>();
	private _currentState?: DocumentAndEditorState;
R
rebornix 已提交
129 130 131

	constructor(
		extHostContext: IExtHostContext,
R
rebornix 已提交
132
		@INotebookService private _notebookService: INotebookService,
133 134
		@IConfigurationService private readonly configurationService: IConfigurationService,
		@IEditorService private readonly editorService: IEditorService,
R
rebornix 已提交
135
		@IAccessibilityService private readonly accessibilityService: IAccessibilityService
136

R
rebornix 已提交
137 138 139
	) {
		super();
		this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostNotebook);
R
rebornix 已提交
140 141 142
		this.registerListeners();
	}

R
rebornix 已提交
143 144 145 146 147 148 149 150
	async $tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise<boolean> {
		let controller = this._notebookProviders.get(viewType);

		if (controller) {
			return controller.tryApplyEdits(resource, modelVersionId, edits, renderers);
		}

		return false;
R
rebornix 已提交
151 152
	}

R
rebornix 已提交
153
	registerListeners() {
R
rebornix 已提交
154 155 156 157
		this._notebookService.listNotebookEditors().forEach((e) => {
			this._addNotebookEditor(e);
		});

R
rebornix 已提交
158
		this._register(this._notebookService.onDidChangeActiveEditor(e => {
R
rebornix 已提交
159
			this._proxy.$acceptDocumentAndEditorsDelta({
R
rebornix 已提交
160
				newActiveEditor: e
R
rebornix 已提交
161
			});
R
rebornix 已提交
162
		}));
R
rebornix 已提交
163

R
rebornix 已提交
164 165 166 167 168 169
		this._register(this._notebookService.onDidChangeVisibleEditors(e => {
			this._proxy.$acceptDocumentAndEditorsDelta({
				visibleEditors: e
			});
		}));

R
rebornix 已提交
170 171 172 173
		this._register(this._notebookService.onNotebookEditorAdd(editor => {
			this._addNotebookEditor(editor);
		}));

174 175 176

		this._register(this._notebookService.onNotebookDocumentRemove(() => {
			this._updateState();
R
rebornix 已提交
177 178
		}));

R
rebornix 已提交
179 180 181 182 183 184 185
		const updateOrder = () => {
			let userOrder = this.configurationService.getValue<string[]>('notebook.displayOrder');
			this._proxy.$acceptDisplayOrder({
				defaultOrder: this.accessibilityService.isScreenReaderOptimized() ? ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER : NOTEBOOK_DISPLAY_ORDER,
				userOrder: userOrder
			});
		};
R
rebornix 已提交
186

R
rebornix 已提交
187
		updateOrder();
R
rebornix 已提交
188

R
rebornix 已提交
189 190 191
		this._register(this.configurationService.onDidChangeConfiguration(e => {
			if (e.affectedKeys.indexOf('notebook.displayOrder') >= 0) {
				updateOrder();
R
rebornix 已提交
192
			}
R
rebornix 已提交
193 194 195 196 197
		}));

		this._register(this.accessibilityService.onDidChangeScreenReaderOptimized(() => {
			updateOrder();
		}));
R
rebornix 已提交
198 199 200 201

		const activeEditorPane = this.editorService.activeEditorPane as any | undefined;
		const notebookEditor = activeEditorPane?.isNotebookEditor ? activeEditorPane.getControl() : undefined;
		this._updateState(notebookEditor);
R
rebornix 已提交
202 203
	}

204
	async addNotebookDocument(data: INotebookModelAddedData) {
205
		this._updateState();
206 207
	}

R
rebornix 已提交
208 209 210
	private _addNotebookEditor(e: IEditor) {
		this._toDisposeOnEditorRemove.set(e.getId(), combinedDisposable(
			e.onDidChangeModel(() => this._updateState()),
R
rebornix 已提交
211 212 213
			e.onDidFocusEditorWidget(() => {
				this._updateState(e);
			}),
R
rebornix 已提交
214 215
		));

R
rebornix 已提交
216 217 218
		const activeEditorPane = this.editorService.activeEditorPane as any | undefined;
		const notebookEditor = activeEditorPane?.isNotebookEditor ? activeEditorPane.getControl() : undefined;
		this._updateState(notebookEditor);
R
rebornix 已提交
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
	}

	private _removeNotebookEditor(e: IEditor) {
		const sub = this._toDisposeOnEditorRemove.get(e.getId());
		if (sub) {
			this._toDisposeOnEditorRemove.delete(e.getId());
			sub.dispose();
			this._updateState();
		}
	}

	private async _updateState(focusedNotebookEditor?: IEditor) {
		const documents = new Set<URI>();
		this._notebookService.listNotebookDocuments().forEach(document => {
			documents.add(document.uri);
		});

		const editors = new Map<string, IEditor>();
		let activeEditor: string | null = null;

		for (const editor of this._notebookService.listNotebookEditors()) {
			if (editor.hasModel()) {
				editors.set(editor.getId(), editor);
				if (editor.hasFocus()) {
					activeEditor = editor.getId();
				}
			}
		}

R
rebornix 已提交
248 249 250 251
		if (!activeEditor && focusedNotebookEditor) {
			activeEditor = focusedNotebookEditor.getId();
		}

R
rebornix 已提交
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
		// editors always have view model attached, which means there is already a document in exthost.
		const newState = new DocumentAndEditorState(documents, editors, activeEditor);
		const delta = DocumentAndEditorState.compute(this._currentState, newState);
		// const isEmptyChange = (!delta.addedDocuments || delta.addedDocuments.length === 0)
		// 	&& (!delta.removedDocuments || delta.removedDocuments.length === 0)
		// 	&& (!delta.addedEditors || delta.addedEditors.length === 0)
		// 	&& (!delta.removedEditors || delta.removedEditors.length === 0)
		// 	&& (delta.newActiveEditor === undefined)

		// if (!isEmptyChange) {
		this._currentState = newState;
		await this._proxy.$acceptDocumentAndEditorsDelta(delta);
		// }
	}

267 268 269 270
	async $registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, preloads: UriComponents[]): Promise<void> {
		const renderer = new MainThreadNotebookRenderer(this._proxy, type, extension.id, URI.revive(extension.location), selectors, preloads.map(uri => URI.revive(uri)));
		this._notebookRenderers.set(type, renderer);
		this._notebookService.registerNotebookRenderer(type, renderer);
R
rebornix 已提交
271 272
	}

273 274
	async $unregisterNotebookRenderer(id: string): Promise<void> {
		this._notebookService.unregisterNotebookRenderer(id);
R
rebornix 已提交
275 276
	}

R
rebornix 已提交
277
	async $registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, kernel: INotebookKernelInfoDto | undefined): Promise<void> {
278
		let controller = new MainThreadNotebookController(this._proxy, this, viewType, kernel, this._notebookService);
R
rebornix 已提交
279
		this._notebookProviders.set(viewType, controller);
R
rebornix 已提交
280
		this._notebookService.registerNotebookController(viewType, extension, controller);
R
rebornix 已提交
281
		return;
R
rebornix 已提交
282 283
	}

284 285 286 287 288 289 290
	async $onNotebookChange(viewType: string, uri: UriComponents): Promise<void> {
		let controller = this._notebookProviders.get(viewType);
		if (controller) {
			controller.handleNotebookChange(uri);
		}
	}

R
rebornix 已提交
291
	async $unregisterNotebookProvider(viewType: string): Promise<void> {
R
rebornix 已提交
292 293
		this._notebookProviders.delete(viewType);
		this._notebookService.unregisterNotebookProvider(viewType);
R
rebornix 已提交
294 295 296
		return;
	}

R
rebornix 已提交
297 298
	async $registerNotebookKernel(extension: NotebookExtensionDescription, id: string, label: string, selectors: (string | IRelativePattern)[], preloads: UriComponents[]): Promise<void> {
		const kernel = new MainThreadNotebookKernel(this._proxy, id, label, selectors, extension.id, URI.revive(extension.location), preloads.map(preload => URI.revive(preload)));
R
rebornix 已提交
299 300 301 302 303 304 305 306 307 308 309
		this._notebookKernels.set(id, kernel);
		this._notebookService.registerNotebookKernel(kernel);
		return;
	}

	async $unregisterNotebookKernel(id: string): Promise<void> {
		this._notebookKernels.delete(id);
		this._notebookService.unregisterNotebookKernel(id);
		return;
	}

R
rebornix 已提交
310
	async $updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void> {
R
rebornix 已提交
311 312 313
		let controller = this._notebookProviders.get(viewType);

		if (controller) {
R
rebornix 已提交
314
			controller.updateLanguages(resource, languages);
R
rebornix 已提交
315 316
		}
	}
R
rebornix 已提交
317

R
rebornix 已提交
318
	async $updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise<void> {
R
rebornix 已提交
319 320 321 322 323 324 325
		let controller = this._notebookProviders.get(viewType);

		if (controller) {
			controller.updateNotebookMetadata(resource, metadata);
		}
	}

326 327 328 329 330 331 332 333
	async $updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata): Promise<void> {
		let controller = this._notebookProviders.get(viewType);

		if (controller) {
			controller.updateNotebookCellMetadata(resource, handle, metadata);
		}
	}

334
	async $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise<void> {
335
		let controller = this._notebookProviders.get(viewType);
336
		await controller?.spliceNotebookCellOutputs(resource, cellHandle, splices, renderers);
337 338
	}

R
rebornix 已提交
339 340
	async executeNotebook(viewType: string, uri: URI, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
		return this._proxy.$executeNotebook(viewType, uri, undefined, useAttachedKernel, token);
R
rebornix 已提交
341
	}
342 343 344 345 346

	async $postMessage(handle: number, value: any): Promise<boolean> {

		const activeEditorPane = this.editorService.activeEditorPane as any | undefined;
		if (activeEditorPane?.isNotebookEditor) {
R
rebornix 已提交
347
			const notebookEditor = (activeEditorPane.getControl() as INotebookEditor);
348 349 350 351 352 353 354 355 356

			if (notebookEditor.viewModel?.handle === handle) {
				notebookEditor.postMessage(value);
				return true;
			}
		}

		return false;
	}
R
rebornix 已提交
357 358 359
}

export class MainThreadNotebookController implements IMainNotebookController {
R
rebornix 已提交
360
	private _mapping: Map<string, MainThreadNotebookDocument> = new Map();
R
rebornix 已提交
361
	static documentHandle: number = 0;
R
rebornix 已提交
362 363

	constructor(
R
rebornix 已提交
364 365
		private readonly _proxy: ExtHostNotebookShape,
		private _mainThreadNotebook: MainThreadNotebooks,
R
rebornix 已提交
366
		private _viewType: string,
367 368 369
		readonly kernel: INotebookKernelInfoDto | undefined,
		readonly notebookService: INotebookService,

R
rebornix 已提交
370 371 372
	) {
	}

373
	async createNotebook(viewType: string, uri: URI, backup: INotebookTextModelBackup | undefined, forceReload: boolean, editorId?: string): Promise<NotebookTextModel | undefined> {
R
rebornix 已提交
374 375 376
		let mainthreadNotebook = this._mapping.get(URI.from(uri).toString());

		if (mainthreadNotebook) {
R
revert.  
rebornix 已提交
377 378 379 380 381 382 383 384
			if (forceReload) {
				const data = await this._proxy.$resolveNotebookData(viewType, uri);
				if (!data) {
					return;
				}

				mainthreadNotebook.textModel.languages = data.languages;
				mainthreadNotebook.textModel.metadata = data.metadata;
385
				mainthreadNotebook.textModel.$applyEdit(mainthreadNotebook.textModel.versionId, [
R
revert.  
rebornix 已提交
386 387 388 389
					{ editType: CellEditType.Delete, count: mainthreadNotebook.textModel.cells.length, index: 0 },
					{ editType: CellEditType.Insert, index: 0, cells: data.cells }
				]);
			}
R
rebornix 已提交
390 391 392
			return mainthreadNotebook.textModel;
		}

393
		let document = new MainThreadNotebookDocument(this._proxy, MainThreadNotebookController.documentHandle++, viewType, uri, this.notebookService);
R
rebornix 已提交
394 395 396 397 398 399 400
		this._mapping.set(document.uri.toString(), document);

		if (backup) {
			// trigger events
			document.textModel.metadata = backup.metadata;
			document.textModel.languages = backup.languages;

401
			document.textModel.$applyEdit(document.textModel.versionId, [
R
rebornix 已提交
402 403 404
				{
					editType: CellEditType.Insert,
					index: 0,
405
					cells: backup.cells || []
R
rebornix 已提交
406 407 408
				}
			]);

409
			await this._mainThreadNotebook.addNotebookDocument({
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
				viewType: document.viewType,
				handle: document.handle,
				uri: document.uri,
				metadata: document.textModel.metadata,
				versionId: document.textModel.versionId,
				cells: document.textModel.cells.map(cell => ({
					handle: cell.handle,
					uri: cell.uri,
					source: cell.textBuffer.getLinesContent(),
					language: cell.language,
					cellKind: cell.cellKind,
					outputs: cell.outputs,
					metadata: cell.metadata
				})),
				attachedEditor: editorId ? {
					id: editorId,
					selections: document.textModel.selections
				} : undefined
R
rebornix 已提交
428
			});
R
rebornix 已提交
429 430 431 432 433 434 435 436 437 438 439 440

			return document.textModel;
		}

		// open notebook document
		const data = await this._proxy.$resolveNotebookData(viewType, uri);
		if (!data) {
			return;
		}

		document.textModel.languages = data.languages;
		document.textModel.metadata = data.metadata;
441 442 443 444 445 446 447

		if (data.cells.length) {
			document.textModel.initialize(data!.cells);
		} else {
			const mainCell = document.textModel.createCellTextModel([''], document.textModel.languages.length ? document.textModel.languages[0] : '', CellKind.Code, [], undefined);
			document.textModel.insertTemplateCell(mainCell);
		}
R
rebornix 已提交
448

449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
		await this._mainThreadNotebook.addNotebookDocument({
			viewType: document.viewType,
			handle: document.handle,
			uri: document.uri,
			metadata: document.textModel.metadata,
			versionId: document.textModel.versionId,
			cells: document.textModel.cells.map(cell => ({
				handle: cell.handle,
				uri: cell.uri,
				source: cell.textBuffer.getLinesContent(),
				language: cell.language,
				cellKind: cell.cellKind,
				outputs: cell.outputs,
				metadata: cell.metadata
			})),
			attachedEditor: editorId ? {
				id: editorId,
				selections: document.textModel.selections
			} : undefined
R
rebornix 已提交
468 469
		});

R
rebornix 已提交
470 471
		this._proxy.$acceptEditorPropertiesChanged(uri, { selections: null, metadata: document.textModel.metadata });

R
rebornix 已提交
472 473 474
		return document.textModel;
	}

R
rebornix 已提交
475
	async tryApplyEdits(resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise<boolean> {
476
		let mainthreadNotebook = this._mapping.get(URI.from(resource).toString());
R
rebornix 已提交
477 478

		if (mainthreadNotebook) {
479
			return await mainthreadNotebook.applyEdit(modelVersionId, edits);
R
rebornix 已提交
480 481 482
		}

		return false;
483 484
	}

485
	async spliceNotebookCellOutputs(resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise<void> {
486
		let mainthreadNotebook = this._mapping.get(URI.from(resource).toString());
487
		await mainthreadNotebook?.spliceNotebookCellOutputs(cellHandle, splices);
488 489
	}

R
rebornix 已提交
490 491
	async executeNotebook(viewType: string, uri: URI, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
		return this._mainThreadNotebook.executeNotebook(viewType, uri, useAttachedKernel, token);
R
rebornix 已提交
492 493
	}

494 495
	onDidReceiveMessage(editorId: string, message: any): void {
		this._proxy.$onDidReceiveMessage(editorId, message);
496 497
	}

R
rebornix 已提交
498 499 500 501 502 503 504 505 506 507 508 509 510
	async removeNotebookDocument(notebook: INotebookTextModel): Promise<void> {
		let document = this._mapping.get(URI.from(notebook.uri).toString());

		if (!document) {
			return;
		}

		await this._proxy.$acceptDocumentAndEditorsDelta({ removedDocuments: [notebook.uri] });
		document.dispose();
		this._mapping.delete(URI.from(notebook.uri).toString());
	}

	// Methods for ExtHost
R
rebornix 已提交
511

512 513 514 515 516
	handleNotebookChange(resource: UriComponents) {
		let document = this._mapping.get(URI.from(resource).toString());
		document?.textModel.handleUnknownChange();
	}

R
rebornix 已提交
517 518
	updateLanguages(resource: UriComponents, languages: string[]) {
		let document = this._mapping.get(URI.from(resource).toString());
519
		document?.textModel.updateLanguages(languages);
R
rebornix 已提交
520 521
	}

R
rebornix 已提交
522
	updateNotebookMetadata(resource: UriComponents, metadata: NotebookDocumentMetadata) {
R
rebornix 已提交
523 524 525 526
		let document = this._mapping.get(URI.from(resource).toString());
		document?.textModel.updateNotebookMetadata(metadata);
	}

527 528 529 530 531
	updateNotebookCellMetadata(resource: UriComponents, handle: number, metadata: NotebookCellMetadata) {
		let document = this._mapping.get(URI.from(resource).toString());
		document?.textModel.updateNotebookCellMetadata(handle, metadata);
	}

R
rebornix 已提交
532 533
	async executeNotebookCell(uri: URI, handle: number, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
		return this._proxy.$executeNotebook(this._viewType, uri, handle, useAttachedKernel, token);
534 535
	}

R
rebornix 已提交
536 537
	async save(uri: URI, token: CancellationToken): Promise<boolean> {
		return this._proxy.$saveNotebook(this._viewType, uri, token);
538
	}
R
saveAs  
rebornix 已提交
539 540 541 542 543

	async saveAs(uri: URI, target: URI, token: CancellationToken): Promise<boolean> {
		return this._proxy.$saveNotebookAs(this._viewType, uri, target, token);

	}
R
rebornix 已提交
544
}
R
rebornix 已提交
545 546 547 548 549

export class MainThreadNotebookKernel implements INotebookKernelInfo {
	constructor(
		private readonly _proxy: ExtHostNotebookShape,
		readonly id: string,
R
rebornix 已提交
550
		readonly label: string,
R
rebornix 已提交
551 552 553 554 555 556 557 558 559 560 561
		readonly selectors: (string | IRelativePattern)[],
		readonly extension: ExtensionIdentifier,
		readonly extensionLocation: URI,
		readonly preloads: URI[]
	) {
	}

	async executeNotebook(viewType: string, uri: URI, handle: number | undefined, token: CancellationToken): Promise<void> {
		return this._proxy.$executeNotebook2(this.id, viewType, uri, handle, token);
	}
}
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582

export class MainThreadNotebookRenderer implements INotebookRendererInfo {
	constructor(
		private readonly _proxy: ExtHostNotebookShape,
		readonly id: string,
		readonly extensionId: ExtensionIdentifier,
		readonly extensionLocation: URI,
		readonly selectors: INotebookMimeTypeSelector,
		readonly preloads: URI[]
	) {

	}

	render(uri: URI, request: IOutputRenderRequest<UriComponents>): Promise<IOutputRenderResponse<UriComponents> | undefined> {
		return this._proxy.$renderOutputs(uri, this.id, request);
	}

	render2<T>(uri: URI, request: IOutputRenderRequest<T>): Promise<IOutputRenderResponse<T> | undefined> {
		return this._proxy.$renderOutputs2(uri, this.id, request);
	}
}