private cellStructureChanged()

in client/src/common/proposed.notebooks.ts [341:411]


	private cellStructureChanged(notebookDocument: vscode.NotebookDocument, syncInfo: SyncInfo | undefined = this.notebookSyncInfo.get(notebookDocument.uri.toString())): void {
		if (syncInfo === undefined) {
			// The notebook has not been synced. Could be it never matched or some
			// cells didn't match. So check if it would match now.
			const cells = this.getMatchingCells(notebookDocument);
			if (cells === undefined) {
				return;
			}
			this.didOpen(notebookDocument, cells, syncInfo);
		} else {
			// It is synced. Could be no cells match anymore. If this is the
			// case we close the notebook document. Otherwise we send a change event.
			const cells = this.getMatchingCells(notebookDocument);
			if (cells === undefined) {
				this.didClose(notebookDocument, syncInfo);
				return;
			}
			const oldCells = syncInfo.cells;
			const newCells = Converter.c2p.asNotebookCells(cells, this.client.code2ProtocolConverter);
			// meta data changes are reported using a different event. So we can ignore comparing the meta data which
			// has a positive impact on performance.
			const diff = NotebookCell.computeDiff(syncInfo.cells, newCells, false);
			if (diff === undefined) {
				return;
			}

			const deletedCells: Set<string> = diff.deleteCount === 0
				? new Set()
				: new Set(oldCells.slice(diff.start, diff.start + diff.deleteCount).map(cell => cell.document));
			const insertedCells: Set<string> = diff.cells === undefined
				? new Set()
				: new Set(diff.cells.map(cell => cell.document));

			// Remove the onces that got deleted and inserted again.
			for (const key of Array.from(deletedCells.values())) {
				if (insertedCells.has(key)) {
					deletedCells.delete(key);
					insertedCells.delete(key);
				}
			}

			const didOpen: Required<proto.Proposed.NotebookDocumentChangeEvent>['cellStructure']['didOpen'] = [];
			const didClose: Required<proto.Proposed.NotebookDocumentChangeEvent>['cellStructure']['didClose'] = [];
			if (deletedCells.size > 0 || insertedCells.size > 0) {
				const codeCells: Map<string, vscode.NotebookCell> = new Map(cells.map(cell => [this.client.code2ProtocolConverter.asUri(cell.document.uri), cell]));
				for (const document of insertedCells.values()) {
					const cell = codeCells.get(document);
					if (cell !== undefined) {
						didOpen.push(this.client.code2ProtocolConverter.asTextDocumentItem(cell.document));
					}
				}
				for (const document of deletedCells.values()) {
					didClose.push({ uri: document });
				}
			}

			this.client.sendNotification(proto.Proposed.DidChangeNotebookDocumentNotification.type, {
				notebookDocument: Converter.c2p.asVersionedNotebookDocumentIdentifier(notebookDocument, this.client.code2ProtocolConverter),
				change: {
					cellStructure: {
						array: diff,
						didClose: didClose.length > 0 ? didClose : undefined,
						didOpen: didOpen.length > 0 ? didOpen : undefined
					}
				}
			}).catch((error) => {
				this.client.error('Sending DidChangeNotebookDocumentNotification failed', error);
			});
			this.notebookSyncInfo.set(notebookDocument.uri.toString(), SyncInfo.create(newCells, cells));
		}
	}