extHostNotebook.ts 37.3 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 * as vscode from 'vscode';
R
rebornix 已提交
7 8
import { readonly } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
R
rebornix 已提交
9
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
10
import { ISplice } from 'vs/base/common/sequence';
11 12
import { URI, UriComponents } from 'vs/base/common/uri';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
13
import { CellKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData, INotebookDocumentsAndEditorsDelta } from 'vs/workbench/api/common/extHost.protocol';
14
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
15
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
16
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, INotebookDisplayOrder, INotebookEditData, NotebookCellsChangedEvent, NotebookCellsSplice2, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto, IOutputRenderRequest, IOutputRenderResponse, IOutputRenderResponseOutputInfo, IOutputRenderResponseCellInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon';
R
rebornix 已提交
17
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
18
import { CancellationToken } from 'vs/base/common/cancellation';
19 20
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
import { NotImplementedProxy } from 'vs/base/common/types';
R
rebornix 已提交
21
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
R
rebornix 已提交
22
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

interface IObservable<T> {
	proxy: T;
	onDidChange: Event<void>;
}

function getObservable<T extends Object>(obj: T): IObservable<T> {
	const onDidChange = new Emitter<void>();
	const proxy = new Proxy(obj, {
		set(target: T, p: PropertyKey, value: any, _receiver: any): boolean {
			target[p as keyof T] = value;
			onDidChange.fire();
			return true;
		}
	});

	return {
		proxy,
		onDidChange: onDidChange.event
	};
}
R
rebornix 已提交
44

R
rebornix 已提交
45 46
interface INotebookEventEmitter {
	emitModelChange(events: vscode.NotebookCellsChangeEvent): void;
47
	emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void;
R
rebornix 已提交
48 49 50
	emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void;
}

51
export class ExtHostCell extends Disposable implements vscode.NotebookCell {
R
rebornix 已提交
52

53
	// private originalSource: string[];
R
rebornix 已提交
54
	private _outputs: any[];
55 56
	private _onDidChangeOutputs = new Emitter<ISplice<vscode.CellOutput>[]>();
	onDidChangeOutputs: Event<ISplice<vscode.CellOutput>[]> = this._onDidChangeOutputs.event;
57 58
	// private _textDocument: vscode.TextDocument | undefined;
	// private _initalVersion: number = -1;
59
	private _outputMapping = new Set<vscode.CellOutput>();
60 61 62
	private _metadata: vscode.NotebookCellMetadata;

	private _metadataChangeListener: IDisposable;
R
rebornix 已提交
63

64 65 66 67 68 69
	private _documentData: ExtHostDocumentData;

	get document(): vscode.TextDocument {
		return this._documentData.document;
	}

R
rebornix 已提交
70
	get source() {
71 72
		// todo@jrieken remove this
		return this._documentData.getText();
R
rebornix 已提交
73 74
	}

R
rebornix 已提交
75
	constructor(
76 77
		private readonly viewType: string,
		private readonly documentUri: URI,
78 79
		readonly handle: number,
		readonly uri: URI,
80
		content: string,
R
rebornix 已提交
81
		public readonly cellKind: CellKind,
R
rebornix 已提交
82
		public language: string,
R
rebornix 已提交
83
		outputs: any[],
84
		_metadata: vscode.NotebookCellMetadata | undefined,
85
		private _proxy: MainThreadNotebookShape,
R
rebornix 已提交
86
	) {
87
		super();
88 89 90 91 92 93 94
		this._documentData = new ExtHostDocumentData(
			new class extends NotImplementedProxy<MainThreadDocumentsShape>('document') { },
			uri,
			content.split(/\r|\n|\r\n/g), '\n',
			language, 0, false
		);

R
rebornix 已提交
95
		this._outputs = outputs;
96

97
		const observableMetadata = getObservable(_metadata || {});
98 99 100 101
		this._metadata = observableMetadata.proxy;
		this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
			this.updateMetadata();
		}));
R
rebornix 已提交
102 103 104 105 106 107
	}

	get outputs() {
		return this._outputs;
	}

R
rebornix 已提交
108
	set outputs(newOutputs: vscode.CellOutput[]) {
109
		let diffs = diff<vscode.CellOutput>(this._outputs || [], newOutputs || [], (a) => {
110 111 112 113 114 115 116 117 118 119 120 121 122
			return this._outputMapping.has(a);
		});

		diffs.forEach(diff => {
			for (let i = diff.start; i < diff.start + diff.deleteCount; i++) {
				this._outputMapping.delete(this._outputs[i]);
			}

			diff.toInsert.forEach(output => {
				this._outputMapping.add(output);
			});
		});

R
rebornix 已提交
123
		this._outputs = newOutputs;
124
		this._onDidChangeOutputs.fire(diffs);
R
rebornix 已提交
125 126
	}

127 128 129 130
	get metadata() {
		return this._metadata;
	}

R
rebornix 已提交
131
	set metadata(newMetadata: vscode.NotebookCellMetadata) {
132
		// Don't apply metadata defaults here, 'undefined' means 'inherit from document metadata'
133
		this._metadataChangeListener.dispose();
134
		const observableMetadata = getObservable(newMetadata);
135 136 137 138 139 140 141
		this._metadata = observableMetadata.proxy;
		this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
			this.updateMetadata();
		}));

		this.updateMetadata();
	}
142

143 144
	private updateMetadata(): Promise<void> {
		return this._proxy.$updateNotebookCellMetadata(this.viewType, this.documentUri, this.handle, this._metadata);
145 146
	}

147 148 149
	attachTextDocument(document: ExtHostDocumentData) {
		this._documentData = document;
		// this._initalVersion = this._documentData.version;
R
rebornix 已提交
150 151
	}

R
rebornix 已提交
152
	detachTextDocument() {
153
		// no-op? keep stale document until new comes along?
R
rebornix 已提交
154

155 156 157 158 159
		// if (this._textDocument && this._textDocument.version !== this._initalVersion) {
		// 	this.originalSource = this._textDocument.getText().split(/\r|\n|\r\n/g);
		// }
		// this._textDocument = undefined;
		// this._initalVersion = -1;
R
rebornix 已提交
160 161 162
	}
}

R
rebornix 已提交
163
export class ExtHostNotebookDocument extends Disposable implements vscode.NotebookDocument {
R
rebornix 已提交
164
	private static _handlePool: number = 0;
R
rebornix 已提交
165 166 167 168
	readonly handle = ExtHostNotebookDocument._handlePool++;

	private _cells: ExtHostCell[] = [];

R
rebornix 已提交
169 170
	private _cellDisposableMapping = new Map<number, DisposableStore>();

R
rebornix 已提交
171 172 173 174
	get cells() {
		return this._cells;
	}

R
rebornix 已提交
175 176 177 178 179
	private _languages: string[] = [];

	get languages() {
		return this._languages = [];
	}
R
rebornix 已提交
180

R
rebornix 已提交
181 182 183
	set languages(newLanguages: string[]) {
		this._languages = newLanguages;
		this._proxy.$updateNotebookLanguages(this.viewType, this.uri, this._languages);
R
rebornix 已提交
184
	}
R
rebornix 已提交
185

186 187
	private _metadata: Required<vscode.NotebookDocumentMetadata> = notebookDocumentMetadataDefaults;
	private _metadataChangeListener: IDisposable;
R
rebornix 已提交
188 189 190 191 192

	get metadata() {
		return this._metadata;
	}

193 194 195 196 197 198
	set metadata(newMetadata: Required<vscode.NotebookDocumentMetadata>) {
		this._metadataChangeListener.dispose();
		newMetadata = {
			...notebookDocumentMetadataDefaults,
			...newMetadata
		};
R
rebornix 已提交
199 200 201 202
		if (this._metadataChangeListener) {
			this._metadataChangeListener.dispose();
		}

203 204 205 206 207
		const observableMetadata = getObservable(newMetadata);
		this._metadata = observableMetadata.proxy;
		this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
			this.updateMetadata();
		}));
R
rebornix 已提交
208 209

		this.updateMetadata();
R
rebornix 已提交
210 211
	}

R
rebornix 已提交
212
	private _displayOrder: string[] = [];
R
rebornix 已提交
213 214 215 216 217

	get displayOrder() {
		return this._displayOrder;
	}

R
rebornix 已提交
218
	set displayOrder(newOrder: string[]) {
R
rebornix 已提交
219 220 221
		this._displayOrder = newOrder;
	}

R
rebornix 已提交
222 223 224 225 226 227
	private _versionId = 0;

	get versionId() {
		return this._versionId;
	}

228 229
	private _disposed = false;

R
rebornix 已提交
230
	constructor(
R
rebornix 已提交
231
		private readonly _proxy: MainThreadNotebookShape,
R
rebornix 已提交
232
		private _documentsAndEditors: ExtHostDocumentsAndEditors,
233
		private _emitter: INotebookEventEmitter,
R
rebornix 已提交
234
		public viewType: string,
R
rebornix 已提交
235 236
		public uri: URI,
		public renderingHandler: ExtHostNotebookOutputRenderingHandler
R
rebornix 已提交
237
	) {
R
rebornix 已提交
238
		super();
239 240 241 242 243 244 245 246 247 248

		const observableMetadata = getObservable(notebookDocumentMetadataDefaults);
		this._metadata = observableMetadata.proxy;
		this._metadataChangeListener = this._register(observableMetadata.onDidChange(() => {
			this.updateMetadata();
		}));
	}

	private updateMetadata() {
		this._proxy.$updateNotebookMetadata(this.viewType, this.uri, this._metadata);
R
rebornix 已提交
249
	}
R
rebornix 已提交
250

R
rebornix 已提交
251
	dispose() {
252
		this._disposed = true;
R
rebornix 已提交
253
		super.dispose();
R
rebornix 已提交
254 255
		this._cellDisposableMapping.forEach(cell => cell.dispose());
	}
R
rebornix 已提交
256

R
rebornix 已提交
257
	get fileName() { return this.uri.fsPath; }
R
rebornix 已提交
258

R
rebornix 已提交
259 260
	get isDirty() { return false; }

261
	accpetModelChanged(event: NotebookCellsChangedEvent): void {
R
rebornix 已提交
262
		this._versionId = event.versionId;
R
rebornix 已提交
263
		if (event.kind === NotebookCellsChangeType.ModelChange) {
264
			this.$spliceNotebookCells(event.changes);
R
rebornix 已提交
265
		} else if (event.kind === NotebookCellsChangeType.Move) {
266
			this.$moveCell(event.index, event.newIdx);
R
rebornix 已提交
267
		} else if (event.kind === NotebookCellsChangeType.CellClearOutput) {
268
			this.$clearCellOutputs(event.index);
R
rebornix 已提交
269
		} else if (event.kind === NotebookCellsChangeType.CellsClearOutput) {
270
			this.$clearAllCellOutputs();
271
		} else if (event.kind === NotebookCellsChangeType.ChangeLanguage) {
272
			this.$changeCellLanguage(event.index, event.language);
R
rebornix 已提交
273
		}
R
rebornix 已提交
274
	}
275

276
	private $spliceNotebookCells(splices: NotebookCellsSplice2[]): void {
277
		if (this._disposed) {
R
rebornix 已提交
278
			return;
279 280
		}

281
		let contentChangeEvents: vscode.NotebookCellsChangeData[] = [];
R
rebornix 已提交
282

283 284 285 286 287
		splices.reverse().forEach(splice => {
			let cellDtos = splice[2];
			let newCells = cellDtos.map(cell => {
				const extCell = new ExtHostCell(this.viewType, this.uri, cell.handle, URI.revive(cell.uri), cell.source.join('\n'), cell.cellKind, cell.language, cell.outputs, cell.metadata, this._proxy);
				const documentData = this._documentsAndEditors.getDocument(URI.revive(cell.uri));
288

289 290 291
				if (documentData) {
					extCell.attachTextDocument(documentData);
				}
R
rebornix 已提交
292

293 294 295
				if (!this._cellDisposableMapping.has(extCell.handle)) {
					this._cellDisposableMapping.set(extCell.handle, new DisposableStore());
				}
296

297
				let store = this._cellDisposableMapping.get(extCell.handle)!;
R
rebornix 已提交
298

299 300 301
				store.add(extCell.onDidChangeOutputs((diffs) => {
					this.eventuallyUpdateCellOutputs(extCell, diffs);
				}));
R
rebornix 已提交
302

303 304
				return extCell;
			});
305

306 307 308
			for (let j = splice[0]; j < splice[0] + splice[1]; j++) {
				this._cellDisposableMapping.get(this.cells[j].handle)?.dispose();
				this._cellDisposableMapping.delete(this.cells[j].handle);
R
rebornix 已提交
309

310
			}
311

312
			this.cells.splice(splice[0], splice[1], ...newCells);
R
rebornix 已提交
313

314 315 316 317 318
			const event: vscode.NotebookCellsChangeData = {
				start: splice[0],
				deletedCount: splice[1],
				items: newCells
			};
R
rebornix 已提交
319

320 321
			contentChangeEvents.push(event);
		});
R
rebornix 已提交
322

323
		this._emitter.emitModelChange({
R
rebornix 已提交
324 325 326
			document: this,
			changes: contentChangeEvents
		});
R
rebornix 已提交
327
	}
R
rebornix 已提交
328

329
	private $moveCell(index: number, newIdx: number): void {
R
rebornix 已提交
330 331
		const cells = this.cells.splice(index, 1);
		this.cells.splice(newIdx, 0, ...cells);
332 333 334 335 336 337 338 339 340 341 342 343 344
		const changes: vscode.NotebookCellsChangeData[] = [{
			start: index,
			deletedCount: 1,
			items: []
		}, {
			start: newIdx,
			deletedCount: 0,
			items: cells
		}];
		this._emitter.emitModelChange({
			document: this,
			changes
		});
R
rebornix 已提交
345 346
	}

347
	private $clearCellOutputs(index: number): void {
R
rebornix 已提交
348 349
		const cell = this.cells[index];
		cell.outputs = [];
350 351
		const event: vscode.NotebookCellOutputsChangeEvent = { document: this, cells: [cell] };
		this._emitter.emitCellOutputsChange(event);
R
rebornix 已提交
352 353
	}

354 355 356 357 358 359 360 361 362 363
	private $clearAllCellOutputs(): void {
		const modifedCells: vscode.NotebookCell[] = [];
		this.cells.forEach(cell => {
			if (cell.outputs.length !== 0) {
				cell.outputs = [];
				modifedCells.push(cell);
			}
		});
		const event: vscode.NotebookCellOutputsChangeEvent = { document: this, cells: modifedCells };
		this._emitter.emitCellOutputsChange(event);
R
rebornix 已提交
364 365
	}

366
	private $changeCellLanguage(index: number, language: string): void {
367 368
		const cell = this.cells[index];
		cell.language = language;
R
rebornix 已提交
369
		const event: vscode.NotebookCellLanguageChangeEvent = { document: this, cell, language };
370
		this._emitter.emitCellLanguageChange(event);
371 372
	}

373
	async eventuallyUpdateCellOutputs(cell: ExtHostCell, diffs: ISplice<vscode.CellOutput>[]) {
374 375 376
		let renderers = new Set<number>();
		let outputDtos: NotebookCellOutputsSplice[] = diffs.map(diff => {
			let outputs = diff.toInsert;
377
			return [diff.start, diff.deleteCount, outputs];
378 379
		});

380 381 382 383 384
		await this._proxy.$spliceNotebookCellOutputs(this.viewType, this.uri, cell.handle, outputDtos, Array.from(renderers));
		this._emitter.emitCellOutputsChange({
			document: this,
			cells: [cell]
		});
385 386
	}

R
rebornix 已提交
387
	getCell(cellHandle: number) {
R
rebornix 已提交
388 389
		return this.cells.find(cell => cell.handle === cellHandle);
	}
R
rebornix 已提交
390

391 392 393 394
	getCell2(cellUri: UriComponents) {
		return this.cells.find(cell => cell.uri.fragment === cellUri.fragment);
	}

395 396
	attachCellTextDocument(textDocument: ExtHostDocumentData) {
		let cell = this.cells.find(cell => cell.uri.toString() === textDocument.document.uri.toString());
R
rebornix 已提交
397 398 399 400 401
		if (cell) {
			cell.attachTextDocument(textDocument);
		}
	}

402 403
	detachCellTextDocument(textDocument: ExtHostDocumentData) {
		let cell = this.cells.find(cell => cell.uri.toString() === textDocument.document.uri.toString());
R
rebornix 已提交
404
		if (cell) {
R
rebornix 已提交
405
			cell.detachTextDocument();
R
rebornix 已提交
406 407
		}
	}
R
rebornix 已提交
408 409
}

R
rebornix 已提交
410
export class NotebookEditorCellEditBuilder implements vscode.NotebookEditorCellEdit {
R
rebornix 已提交
411 412 413
	private _finalized: boolean = false;
	private readonly _documentVersionId: number;
	private _collectedEdits: ICellEditOperation[] = [];
R
rebornix 已提交
414
	private _renderers = new Set<number>();
R
rebornix 已提交
415 416 417 418

	constructor(
		readonly editor: ExtHostNotebookEditor
	) {
R
rebornix 已提交
419
		this._documentVersionId = editor.document.versionId;
R
rebornix 已提交
420 421 422 423 424 425
	}

	finalize(): INotebookEditData {
		this._finalized = true;
		return {
			documentVersionId: this._documentVersionId,
R
rebornix 已提交
426 427
			edits: this._collectedEdits,
			renderers: Array.from(this._renderers)
R
rebornix 已提交
428 429 430 431 432 433 434 435 436
		};
	}

	private _throwIfFinalized() {
		if (this._finalized) {
			throw new Error('Edit is only valid while callback runs');
		}
	}

R
rebornix 已提交
437
	insert(index: number, content: string | string[], language: string, type: CellKind, outputs: vscode.CellOutput[], metadata: vscode.NotebookCellMetadata | undefined): void {
R
rebornix 已提交
438 439
		this._throwIfFinalized();

R
rebornix 已提交
440
		const sourceArr = Array.isArray(content) ? content : content.split(/\r|\n|\r\n/g);
R
rebornix 已提交
441
		let cell = {
R
rebornix 已提交
442
			source: sourceArr,
R
rebornix 已提交
443
			language,
R
rebornix 已提交
444
			cellKind: type,
445
			outputs: outputs,
R
rebornix 已提交
446
			metadata
R
rebornix 已提交
447 448 449 450 451 452
		};

		this._collectedEdits.push({
			editType: CellEditType.Insert,
			index,
			cells: [cell]
R
rebornix 已提交
453 454 455 456 457 458 459 460
		});
	}

	delete(index: number): void {
		this._throwIfFinalized();

		this._collectedEdits.push({
			editType: CellEditType.Delete,
461 462
			index,
			count: 1
R
rebornix 已提交
463 464 465 466
		});
	}
}

R
rebornix 已提交
467
export class ExtHostNotebookEditor extends Disposable implements vscode.NotebookEditor {
R
rebornix 已提交
468
	private _viewColumn: vscode.ViewColumn | undefined;
R
rebornix 已提交
469 470

	selection?: ExtHostCell = undefined;
R
rebornix 已提交
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493

	private _active: boolean = false;
	get active(): boolean {
		return this._active;
	}

	set active(_state: boolean) {
		throw readonly('active');
	}

	private _visible: boolean = false;
	get visible(): boolean {
		return this._visible;
	}

	set visible(_state: boolean) {
		throw readonly('visible');
	}

	_acceptVisibility(value: boolean) {
		this._visible = value;
	}

R
rebornix 已提交
494
	_acceptActive(value: boolean) {
R
rebornix 已提交
495 496 497
		this._active = value;
	}

R
rebornix 已提交
498 499
	private _onDidDispose = new Emitter<void>();
	readonly onDidDispose: Event<void> = this._onDidDispose.event;
500
	onDidReceiveMessage: vscode.Event<any> = this._onDidReceiveMessage.event;
R
rebornix 已提交
501 502

	constructor(
503
		private readonly viewType: string,
R
rebornix 已提交
504 505
		readonly id: string,
		public uri: URI,
506 507
		private _proxy: MainThreadNotebookShape,
		private _onDidReceiveMessage: Emitter<any>,
R
rebornix 已提交
508
		private _webviewInitData: WebviewInitData,
R
rebornix 已提交
509
		public document: ExtHostNotebookDocument,
R
rebornix 已提交
510
		private _documentsAndEditors: ExtHostDocumentsAndEditors
R
rebornix 已提交
511
	) {
R
rebornix 已提交
512 513
		super();
		this._register(this._documentsAndEditors.onDidAddDocuments(documents => {
514 515
			for (const documentData of documents) {
				let data = CellUri.parse(documentData.document.uri);
J
Johannes Rieken 已提交
516 517
				if (data) {
					if (this.document.uri.toString() === data.notebook.toString()) {
518
						document.attachCellTextDocument(documentData);
R
rebornix 已提交
519 520 521
					}
				}
			}
R
rebornix 已提交
522
		}));
R
rebornix 已提交
523

R
rebornix 已提交
524
		this._register(this._documentsAndEditors.onDidRemoveDocuments(documents => {
525 526
			for (const documentData of documents) {
				let data = CellUri.parse(documentData.document.uri);
J
Johannes Rieken 已提交
527 528
				if (data) {
					if (this.document.uri.toString() === data.notebook.toString()) {
529
						document.detachCellTextDocument(documentData);
R
rebornix 已提交
530 531 532
					}
				}
			}
R
rebornix 已提交
533 534 535
		}));
	}

R
rebornix 已提交
536 537
	edit(callback: (editBuilder: NotebookEditorCellEditBuilder) => void): Thenable<boolean> {
		const edit = new NotebookEditorCellEditBuilder(this);
R
rebornix 已提交
538 539 540 541
		callback(edit);
		return this._applyEdit(edit);
	}

R
rebornix 已提交
542
	private _applyEdit(editBuilder: NotebookEditorCellEditBuilder): Promise<boolean> {
R
rebornix 已提交
543 544 545 546 547 548 549
		const editData = editBuilder.finalize();

		// return when there is nothing to do
		if (editData.edits.length === 0) {
			return Promise.resolve(true);
		}

R
rebornix 已提交
550 551 552 553 554 555 556 557 558 559 560 561 562 563
		let compressedEdits: ICellEditOperation[] = [];
		let compressedEditsIndex = -1;

		for (let i = 0; i < editData.edits.length; i++) {
			if (compressedEditsIndex < 0) {
				compressedEdits.push(editData.edits[i]);
				compressedEditsIndex++;
				continue;
			}

			let prevIndex = compressedEditsIndex;
			let prev = compressedEdits[prevIndex];

			if (prev.editType === CellEditType.Insert && editData.edits[i].editType === CellEditType.Insert) {
564
				if (prev.index === editData.edits[i].index) {
R
rebornix 已提交
565 566 567 568 569
					prev.cells.push(...(editData.edits[i] as ICellInsertEdit).cells);
					continue;
				}
			}

570 571 572 573 574 575 576
			if (prev.editType === CellEditType.Delete && editData.edits[i].editType === CellEditType.Delete) {
				if (prev.index === editData.edits[i].index) {
					prev.count += (editData.edits[i] as ICellDeleteEdit).count;
					continue;
				}
			}

R
rebornix 已提交
577 578 579
			compressedEdits.push(editData.edits[i]);
			compressedEditsIndex++;
		}
R
rebornix 已提交
580

R
rebornix 已提交
581
		return this._proxy.$tryApplyEdits(this.viewType, this.uri, editData.documentVersionId, compressedEdits, editData.renderers);
R
rebornix 已提交
582 583 584 585 586 587 588 589
	}

	get viewColumn(): vscode.ViewColumn | undefined {
		return this._viewColumn;
	}

	set viewColumn(value) {
		throw readonly('viewColumn');
R
rebornix 已提交
590
	}
591 592 593 594 595

	async postMessage(message: any): Promise<boolean> {
		return this._proxy.$postMessage(this.document.handle, message);
	}

R
rebornix 已提交
596
	asWebviewUri(localResource: vscode.Uri): vscode.Uri {
597
		return asWebviewUri(this._webviewInitData, this.id, localResource);
R
rebornix 已提交
598
	}
R
rebornix 已提交
599 600 601 602
	dispose() {
		this._onDidDispose.fire();
		super.dispose();
	}
R
rebornix 已提交
603 604
}

R
rebornix 已提交
605
export class ExtHostNotebookOutputRenderer {
R
rebornix 已提交
606 607 608
	private static _handlePool: number = 0;
	readonly handle = ExtHostNotebookOutputRenderer._handlePool++;

R
rebornix 已提交
609
	constructor(
R
rebornix 已提交
610 611 612
		public type: string,
		public filter: vscode.NotebookOutputSelector,
		public renderer: vscode.NotebookOutputRenderer
R
rebornix 已提交
613 614 615 616
	) {

	}

R
rebornix 已提交
617 618 619
	matches(mimeType: string): boolean {
		if (this.filter.subTypes) {
			if (this.filter.subTypes.indexOf(mimeType) >= 0) {
R
rebornix 已提交
620 621 622 623 624 625
				return true;
			}
		}
		return false;
	}

R
rebornix 已提交
626
	render(document: ExtHostNotebookDocument, output: vscode.CellDisplayOutput, mimeType: string): string {
R
rebornix 已提交
627
		let html = this.renderer.render(document, output, mimeType);
R
rebornix 已提交
628

629
		return html;
R
rebornix 已提交
630 631 632 633
	}
}

export interface ExtHostNotebookOutputRenderingHandler {
R
rebornix 已提交
634
	outputDisplayOrder: INotebookDisplayOrder | undefined;
R
rebornix 已提交
635
	findBestMatchedRenderer(mimeType: string): ExtHostNotebookOutputRenderer[];
R
rebornix 已提交
636 637 638
}

export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostNotebookOutputRenderingHandler {
R
rebornix 已提交
639
	private readonly _proxy: MainThreadNotebookShape;
R
rebornix 已提交
640
	private readonly _notebookContentProviders = new Map<string, { readonly provider: vscode.NotebookContentProvider, readonly extension: IExtensionDescription; }>();
R
rebornix 已提交
641
	private readonly _notebookKernels = new Map<string, { readonly kernel: vscode.NotebookKernel, readonly extension: IExtensionDescription; }>();
R
rebornix 已提交
642
	private readonly _documents = new Map<string, ExtHostNotebookDocument>();
R
rebornix 已提交
643
	private readonly _unInitializedDocuments = new Map<string, ExtHostNotebookDocument>();
R
rebornix 已提交
644
	private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; }>();
645
	private readonly _notebookOutputRenderers = new Map<string, ExtHostNotebookOutputRenderer>();
R
rebornix 已提交
646 647
	private readonly _onDidChangeNotebookCells = new Emitter<vscode.NotebookCellsChangeEvent>();
	readonly onDidChangeNotebookCells = this._onDidChangeNotebookCells.event;
648 649
	private readonly _onDidChangeCellOutputs = new Emitter<vscode.NotebookCellOutputsChangeEvent>();
	readonly onDidChangeCellOutputs = this._onDidChangeCellOutputs.event;
R
rebornix 已提交
650 651
	private readonly _onDidChangeCellLanguage = new Emitter<vscode.NotebookCellLanguageChangeEvent>();
	readonly onDidChangeCellLanguage = this._onDidChangeCellLanguage.event;
R
rebornix 已提交
652 653
	private readonly _onDidChangeActiveNotebookEditor = new Emitter<vscode.NotebookEditor | undefined>();
	readonly onDidChangeActiveNotebookEditor = this._onDidChangeActiveNotebookEditor.event;
654

R
rebornix 已提交
655
	private _outputDisplayOrder: INotebookDisplayOrder | undefined;
R
rebornix 已提交
656

R
rebornix 已提交
657
	get outputDisplayOrder(): INotebookDisplayOrder | undefined {
R
rebornix 已提交
658
		return this._outputDisplayOrder;
R
rebornix 已提交
659 660
	}

R
rebornix 已提交
661 662 663 664 665 666
	private _activeNotebookDocument: ExtHostNotebookDocument | undefined;

	get activeNotebookDocument() {
		return this._activeNotebookDocument;
	}

R
rebornix 已提交
667 668 669 670 671 672
	private _activeNotebookEditor: ExtHostNotebookEditor | undefined;

	get activeNotebookEditor() {
		return this._activeNotebookEditor;
	}

R
rebornix 已提交
673 674
	private _onDidOpenNotebookDocument = new Emitter<vscode.NotebookDocument>();
	onDidOpenNotebookDocument: Event<vscode.NotebookDocument> = this._onDidOpenNotebookDocument.event;
R
rebornix 已提交
675 676
	private _onDidCloseNotebookDocument = new Emitter<vscode.NotebookDocument>();
	onDidCloseNotebookDocument: Event<vscode.NotebookDocument> = this._onDidCloseNotebookDocument.event;
R
rebornix 已提交
677 678 679
	visibleNotebookEditors: ExtHostNotebookEditor[] = [];
	private _onDidChangeVisibleNotebookEditors = new Emitter<vscode.NotebookEditor[]>();
	onDidChangeVisibleNotebookEditors = this._onDidChangeVisibleNotebookEditors.event;
R
rebornix 已提交
680

R
rebornix 已提交
681
	constructor(mainContext: IMainContext, commands: ExtHostCommands, private _documentsAndEditors: ExtHostDocumentsAndEditors, private readonly _webviewInitData: WebviewInitData) {
R
rebornix 已提交
682
		this._proxy = mainContext.getProxy(MainContext.MainThreadNotebook);
683 684 685 686 687 688 689 690

		commands.registerArgumentProcessor({
			processArgument: arg => {
				if (arg && arg.$mid === 12) {
					const documentHandle = arg.notebookEditor?.notebookHandle;
					const cellHandle = arg.cell.handle;

					for (let value of this._editors) {
691 692
						if (value[1].editor.document.handle === documentHandle) {
							const cell = value[1].editor.document.getCell(cellHandle);
693 694 695 696 697 698
							if (cell) {
								return cell;
							}
						}
					}
				}
B
Benjamin Pasero 已提交
699
				return arg;
700 701
			}
		});
R
rebornix 已提交
702 703
	}

R
rebornix 已提交
704
	registerNotebookOutputRenderer(
R
rebornix 已提交
705
		type: string,
R
rebornix 已提交
706
		extension: IExtensionDescription,
R
rebornix 已提交
707
		filter: vscode.NotebookOutputSelector,
R
rebornix 已提交
708
		renderer: vscode.NotebookOutputRenderer
R
rebornix 已提交
709
	): vscode.Disposable {
710 711 712 713
		if (this._notebookKernels.has(type)) {
			throw new Error(`Notebook renderer for '${type}' already registered`);
		}

R
rebornix 已提交
714
		let extHostRenderer = new ExtHostNotebookOutputRenderer(type, filter, renderer);
715 716
		this._notebookOutputRenderers.set(extHostRenderer.type, extHostRenderer);
		this._proxy.$registerNotebookRenderer({ id: extension.identifier, location: extension.extensionLocation }, type, filter, renderer.preloads || []);
R
rebornix 已提交
717
		return new extHostTypes.Disposable(() => {
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
			this._notebookOutputRenderers.delete(extHostRenderer.type);
			this._proxy.$unregisterNotebookRenderer(extHostRenderer.type);
		});
	}

	async $renderOutputs(uriComponents: UriComponents, id: string, request: IOutputRenderRequest<UriComponents>): Promise<IOutputRenderResponse<UriComponents> | undefined> {
		if (!this._notebookOutputRenderers.has(id)) {
			throw new Error(`Notebook renderer for '${id}' is not registered`);
		}

		const document = this._documents.get(URI.revive(uriComponents).toString());

		if (!document) {
			return;
		}

		const renderer = this._notebookOutputRenderers.get(id)!;
		const cellsResponse: IOutputRenderResponseCellInfo<UriComponents>[] = request.items.map(cellInfo => {
			const cell = document.getCell2(cellInfo.key);
			const outputResponse: IOutputRenderResponseOutputInfo[] = cellInfo.outputs.map(output => {
				return {
					index: output.index,
					mimeType: output.mimeType,
					handlerId: id,
					transformedOutput: renderer.render(document, cell!.outputs[output.index] as vscode.CellDisplayOutput, output.mimeType)
				};
			});

			return {
				key: cellInfo.key,
				outputs: outputResponse
			};
		});

		return { items: cellsResponse };
	}

	/**
	 * The request carry the raw data for outputs so we don't look up in the existing document
	 */
	async $renderOutputs2<T>(uriComponents: UriComponents, id: string, request: IOutputRenderRequest<T>): Promise<IOutputRenderResponse<T> | undefined> {
		if (!this._notebookOutputRenderers.has(id)) {
			throw new Error(`Notebook renderer for '${id}' is not registered`);
		}

		const document = this._documents.get(URI.revive(uriComponents).toString());

		if (!document) {
			return;
		}

		const renderer = this._notebookOutputRenderers.get(id)!;
		const cellsResponse: IOutputRenderResponseCellInfo<T>[] = request.items.map(cellInfo => {
			const outputResponse: IOutputRenderResponseOutputInfo[] = cellInfo.outputs.map(output => {
				return {
					index: output.index,
					mimeType: output.mimeType,
					handlerId: id,
					transformedOutput: renderer.render(document, output.output! as vscode.CellDisplayOutput, output.mimeType)
				};
			});

			return {
				key: cellInfo.key,
				outputs: outputResponse
			};
R
rebornix 已提交
784
		});
785 786

		return { items: cellsResponse };
R
rebornix 已提交
787 788
	}

R
rebornix 已提交
789 790
	findBestMatchedRenderer(mimeType: string): ExtHostNotebookOutputRenderer[] {
		let matches: ExtHostNotebookOutputRenderer[] = [];
R
rebornix 已提交
791
		for (let renderer of this._notebookOutputRenderers) {
R
rebornix 已提交
792
			if (renderer[1].matches(mimeType)) {
R
rebornix 已提交
793
				matches.push(renderer[1]);
R
rebornix 已提交
794 795 796
			}
		}

R
rebornix 已提交
797
		return matches;
R
rebornix 已提交
798 799
	}

R
rebornix 已提交
800 801 802 803 804 805
	registerNotebookContentProvider(
		extension: IExtensionDescription,
		viewType: string,
		provider: vscode.NotebookContentProvider,
	): vscode.Disposable {

R
rebornix 已提交
806
		if (this._notebookContentProviders.has(viewType)) {
R
rebornix 已提交
807 808 809
			throw new Error(`Notebook provider for '${viewType}' already registered`);
		}

R
rebornix 已提交
810 811 812
		// if ((<any>provider).executeCell) {
		// 	throw new Error('NotebookContentKernel.executeCell is removed, please use vscode.notebook.registerNotebookKernel instead.');
		// }
R
rebornix 已提交
813

R
rebornix 已提交
814
		this._notebookContentProviders.set(viewType, { extension, provider });
R
rebornix 已提交
815
		this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType, provider.kernel ? { id: viewType, label: provider.kernel.label, extensionLocation: extension.extensionLocation, preloads: provider.kernel.preloads } : undefined);
R
rebornix 已提交
816
		return new extHostTypes.Disposable(() => {
R
rebornix 已提交
817 818 819 820 821
			this._notebookContentProviders.delete(viewType);
			this._proxy.$unregisterNotebookProvider(viewType);
		});
	}

R
rebornix 已提交
822 823 824 825 826 827 828 829
	registerNotebookKernel(extension: IExtensionDescription, id: string, selectors: vscode.GlobPattern[], kernel: vscode.NotebookKernel): vscode.Disposable {
		if (this._notebookKernels.has(id)) {
			throw new Error(`Notebook kernel for '${id}' already registered`);
		}

		this._notebookKernels.set(id, { kernel, extension });
		const transformedSelectors = selectors.map(selector => typeConverters.GlobPattern.from(selector));

R
rebornix 已提交
830
		this._proxy.$registerNotebookKernel({ id: extension.identifier, location: extension.extensionLocation }, id, kernel.label, transformedSelectors, kernel.preloads || []);
R
rebornix 已提交
831
		return new extHostTypes.Disposable(() => {
R
rebornix 已提交
832 833 834 835 836
			this._notebookKernels.delete(id);
			this._proxy.$unregisterNotebookKernel(id);
		});
	}

R
rebornix 已提交
837
	async $resolveNotebookData(viewType: string, uri: UriComponents): Promise<NotebookDataDto | undefined> {
R
rebornix 已提交
838 839 840 841 842 843 844
		const provider = this._notebookContentProviders.get(viewType);
		const revivedUri = URI.revive(uri);

		if (provider) {
			let document = this._documents.get(URI.revive(uri).toString());

			if (!document) {
845 846 847 848 849 850 851 852 853 854 855 856
				const that = this;
				document = this._unInitializedDocuments.get(revivedUri.toString()) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, {
					emitModelChange(event: vscode.NotebookCellsChangeEvent): void {
						that._onDidChangeNotebookCells.fire(event);
					},
					emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void {
						that._onDidChangeCellOutputs.fire(event);
					},
					emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void {
						that._onDidChangeCellLanguage.fire(event);
					}
				}, viewType, revivedUri, this);
R
rebornix 已提交
857 858
				this._unInitializedDocuments.set(revivedUri.toString(), document);
			}
R
rebornix 已提交
859 860 861 862 863 864 865 866

			const rawCells = await provider.provider.openNotebook(URI.revive(uri));
			const dto = {
				metadata: {
					...notebookDocumentMetadataDefaults,
					...rawCells.metadata
				},
				languages: rawCells.languages,
867
				cells: rawCells.cells,
R
rebornix 已提交
868 869 870 871 872 873 874 875
			};

			return dto;
		}

		return;
	}

R
rebornix 已提交
876
	async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, useAttachedKernel: boolean, token: CancellationToken): Promise<void> {
R
rebornix 已提交
877
		let document = this._documents.get(URI.revive(uri).toString());
R
rebornix 已提交
878

R
rebornix 已提交
879
		if (!document) {
R
rebornix 已提交
880
			return;
R
rebornix 已提交
881
		}
R
rebornix 已提交
882

R
rebornix 已提交
883
		if (this._notebookContentProviders.has(viewType)) {
R
rebornix 已提交
884 885
			const cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
			const provider = this._notebookContentProviders.get(viewType)!.provider;
R
rebornix 已提交
886

R
rebornix 已提交
887 888 889 890 891 892 893
			if (provider.kernel && useAttachedKernel) {
				if (cell) {
					return provider.kernel.executeCell(document, cell, token);
				} else {
					return provider.kernel.executeAllCells(document, token);
				}
			}
R
rebornix 已提交
894
		}
R
rebornix 已提交
895 896
	}

R
rebornix 已提交
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
	async $executeNotebook2(kernelId: string, viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
		let document = this._documents.get(URI.revive(uri).toString());

		if (!document || document.viewType !== viewType) {
			return;
		}

		let kernelInfo = this._notebookKernels.get(kernelId);

		if (!kernelInfo) {
			return;
		}

		let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;

		if (cell) {
			return kernelInfo.kernel.executeCell(document, cell, token);
		} else {
			return kernelInfo.kernel.executeAllCells(document, token);
		}
	}

R
rebornix 已提交
919
	async $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean> {
R
rebornix 已提交
920
		let document = this._documents.get(URI.revive(uri).toString());
R
rebornix 已提交
921 922 923 924 925 926
		if (!document) {
			return false;
		}

		if (this._notebookContentProviders.has(viewType)) {
			try {
R
rebornix 已提交
927
				await this._notebookContentProviders.get(viewType)!.provider.saveNotebook(document, token);
R
rebornix 已提交
928 929 930 931 932 933 934
			} catch (e) {
				return false;
			}

			return true;
		}

R
saveAs  
rebornix 已提交
935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
		return false;
	}

	async $saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean> {
		let document = this._documents.get(URI.revive(uri).toString());
		if (!document) {
			return false;
		}

		if (this._notebookContentProviders.has(viewType)) {
			try {
				await this._notebookContentProviders.get(viewType)!.provider.saveNotebookAs(URI.revive(target), document, token);
			} catch (e) {
				return false;
			}
R
rebornix 已提交
950

R
rebornix 已提交
951
			return true;
R
rebornix 已提交
952 953 954 955 956
		}

		return false;
	}

R
rebornix 已提交
957
	$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void {
R
rebornix 已提交
958
		this._outputDisplayOrder = displayOrder;
R
rebornix 已提交
959
	}
960

R
rebornix 已提交
961 962 963 964 965 966 967 968 969 970 971 972 973
	// TODO: remove document - editor one on one mapping
	private _getEditorFromURI(uriComponents: UriComponents) {
		const uriStr = URI.revive(uriComponents).toString();
		let editor: { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; } | undefined;
		this._editors.forEach(e => {
			if (e.editor.uri.toString() === uriStr) {
				editor = e;
			}
		});

		return editor;
	}

974 975
	$onDidReceiveMessage(editorId: string, message: any): void {
		let editor = this._editors.get(editorId);
976 977 978 979 980

		if (editor) {
			editor.onDidReceiveMessage.fire(message);
		}
	}
R
rebornix 已提交
981 982

	$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void {
R
rebornix 已提交
983
		const document = this._documents.get(URI.revive(uriComponents).toString());
R
rebornix 已提交
984

R
rebornix 已提交
985
		if (document) {
986
			document.accpetModelChanged(event);
R
rebornix 已提交
987 988
		}
	}
R
rebornix 已提交
989 990

	$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void {
R
rebornix 已提交
991
		let editor = this._getEditorFromURI(uriComponents);
R
rebornix 已提交
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006

		if (!editor) {
			return;
		}

		if (data.selections) {
			const cells = editor.editor.document.cells;

			if (data.selections.selections.length) {
				const firstCell = data.selections.selections[0];
				editor.editor.selection = cells.find(cell => cell.handle === firstCell);
			} else {
				editor.editor.selection = undefined;
			}
		}
R
rebornix 已提交
1007 1008 1009 1010 1011 1012 1013

		if (data.metadata) {
			editor.editor.document.metadata = {
				...notebookDocumentMetadataDefaults,
				...data.metadata
			};
		}
R
rebornix 已提交
1014
	}
R
rebornix 已提交
1015

1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
	private _createExtHostEditor(document: ExtHostNotebookDocument, editorId: string, selections: number[]) {
		const onDidReceiveMessage = new Emitter<any>();
		const revivedUri = document.uri;

		let editor = new ExtHostNotebookEditor(
			document.viewType,
			editorId,
			revivedUri,
			this._proxy,
			onDidReceiveMessage,
			this._webviewInitData,
			document,
			this._documentsAndEditors
		);

		const cells = editor.document.cells;

		if (selections.length) {
			const firstCell = selections[0];
			editor.selection = cells.find(cell => cell.handle === firstCell);
		} else {
			editor.selection = undefined;
		}

		this._editors.get(editorId)?.editor.dispose();

		this._editors.set(editorId, { editor, onDidReceiveMessage });
	}

R
rebornix 已提交
1045
	async $acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta) {
1046 1047
		let editorChanged = false;

R
rebornix 已提交
1048 1049
		if (delta.removedDocuments) {
			delta.removedDocuments.forEach((uri) => {
1050 1051 1052
				const revivedUri = URI.revive(uri);
				const revivedUriStr = revivedUri.toString();
				let document = this._documents.get(revivedUriStr);
R
rebornix 已提交
1053 1054 1055

				if (document) {
					document.dispose();
1056
					this._documents.delete(revivedUriStr);
R
rebornix 已提交
1057 1058 1059
					this._onDidCloseNotebookDocument.fire(document);
				}

1060 1061 1062 1063 1064
				[...this._editors.values()].forEach((e) => {
					if (e.editor.uri.toString() === revivedUriStr) {
						e.editor.dispose();
						e.onDidReceiveMessage.dispose();
						this._editors.delete(e.editor.id);
R
rebornix 已提交
1065
						editorChanged = true;
1066 1067
					}
				});
R
rebornix 已提交
1068 1069 1070 1071 1072 1073
			});
		}

		if (delta.addedDocuments) {
			delta.addedDocuments.forEach(modelData => {
				const revivedUri = URI.revive(modelData.uri);
R
rebornix 已提交
1074
				const revivedUriStr = revivedUri.toString();
R
rebornix 已提交
1075
				const viewType = modelData.viewType;
R
rebornix 已提交
1076
				if (!this._documents.has(revivedUriStr)) {
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
					const that = this;
					let document = this._unInitializedDocuments.get(revivedUriStr) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, {
						emitModelChange(event: vscode.NotebookCellsChangeEvent): void {
							that._onDidChangeNotebookCells.fire(event);
						},
						emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void {
							that._onDidChangeCellOutputs.fire(event);
						},
						emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void {
							that._onDidChangeCellLanguage.fire(event);
						}
					}, viewType, revivedUri, this);

R
rebornix 已提交
1090
					this._unInitializedDocuments.delete(revivedUriStr);
R
rebornix 已提交
1091 1092 1093 1094 1095 1096 1097
					if (modelData.metadata) {
						document.metadata = {
							...notebookDocumentMetadataDefaults,
							...modelData.metadata
						};
					}

R
rebornix 已提交
1098 1099 1100
					document.accpetModelChanged({
						kind: NotebookCellsChangeType.ModelChange,
						versionId: modelData.versionId,
1101
						changes: [[
1102 1103 1104
							0,
							0,
							modelData.cells
1105
						]]
R
rebornix 已提交
1106 1107
					});

1108
					this._documents.get(revivedUriStr)?.dispose();
R
rebornix 已提交
1109
					this._documents.set(revivedUriStr, document);
1110 1111 1112 1113 1114 1115

					// create editor if populated
					if (modelData.attachedEditor) {
						this._createExtHostEditor(document, modelData.attachedEditor.id, modelData.attachedEditor.selections);
						editorChanged = true;
					}
R
rebornix 已提交
1116 1117
				}

R
rebornix 已提交
1118
				const document = this._documents.get(revivedUriStr)!;
R
rebornix 已提交
1119 1120 1121
				this._onDidOpenNotebookDocument.fire(document);
			});
		}
R
rebornix 已提交
1122

R
rebornix 已提交
1123 1124
		if (delta.addedEditors) {
			delta.addedEditors.forEach(editorModelData => {
1125 1126 1127 1128
				if (this._editors.has(editorModelData.id)) {
					return;
				}

R
rebornix 已提交
1129 1130 1131 1132
				const revivedUri = URI.revive(editorModelData.documentUri);
				const document = this._documents.get(revivedUri.toString());

				if (document) {
1133
					this._createExtHostEditor(document, editorModelData.id, editorModelData.selections);
R
rebornix 已提交
1134 1135 1136 1137 1138
					editorChanged = true;
				}
			});
		}

1139 1140
		const removedEditors: { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; }[] = [];

R
rebornix 已提交
1141 1142 1143
		if (delta.removedEditors) {
			delta.removedEditors.forEach(editorid => {
				const editor = this._editors.get(editorid);
R
rebornix 已提交
1144

R
rebornix 已提交
1145 1146 1147 1148
				if (editor) {
					editorChanged = true;
					this._editors.delete(editorid);

1149 1150 1151 1152 1153 1154
					if (this.activeNotebookEditor?.id === editor.editor.id) {
						this._activeNotebookEditor = undefined;
						this._activeNotebookDocument = undefined;
					}

					removedEditors.push(editor);
R
rebornix 已提交
1155
				}
R
rebornix 已提交
1156 1157 1158
			});
		}

R
rebornix 已提交
1159
		if (editorChanged) {
1160 1161 1162 1163
			removedEditors.forEach(e => {
				e.editor.dispose();
				e.onDidReceiveMessage.dispose();
			});
R
rebornix 已提交
1164 1165
		}

R
rebornix 已提交
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
		if (delta.visibleEditors) {
			this.visibleNotebookEditors = delta.visibleEditors.map(id => this._editors.get(id)?.editor).filter(editor => !!editor) as ExtHostNotebookEditor[];
			const visibleEditorsSet = new Set<string>();
			this.visibleNotebookEditors.forEach(editor => visibleEditorsSet.add(editor.id));

			[...this._editors.values()].forEach((e) => {
				const newValue = visibleEditorsSet.has(e.editor.id);
				e.editor._acceptVisibility(newValue);
			});

			this.visibleNotebookEditors = [...this._editors.values()].map(e => e.editor).filter(e => e.visible);
			this._onDidChangeVisibleNotebookEditors.fire(this.visibleNotebookEditors);
		}

R
rebornix 已提交
1180 1181 1182
		if (delta.newActiveEditor !== undefined) {
			if (delta.newActiveEditor) {
				this._activeNotebookEditor = this._editors.get(delta.newActiveEditor)?.editor;
R
rebornix 已提交
1183
				this._activeNotebookEditor?._acceptActive(true);
1184
				this._activeNotebookDocument = this._activeNotebookEditor ? this._documents.get(this._activeNotebookEditor!.uri.toString()) : undefined;
R
rebornix 已提交
1185 1186 1187 1188
			} else {
				this._activeNotebookEditor = undefined;
				this._activeNotebookDocument = undefined;
			}
R
rebornix 已提交
1189 1190

			this._onDidChangeActiveNotebookEditor.fire(this._activeNotebookEditor);
R
rebornix 已提交
1191
		}
R
rebornix 已提交
1192

R
rebornix 已提交
1193 1194
		[...this._editors.values()].forEach((e) => {
			if (e.editor !== this.activeNotebookEditor) {
R
rebornix 已提交
1195
				e.editor._acceptActive(false);
R
rebornix 已提交
1196 1197
			}
		});
R
rebornix 已提交
1198
	}
R
rebornix 已提交
1199
}