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));
}
}