diff --git a/extensions/vscode-notebook-tests/src/notebook.test.ts b/extensions/vscode-notebook-tests/src/notebook.test.ts index 077815ad16d..4b4efea03e6 100644 --- a/extensions/vscode-notebook-tests/src/notebook.test.ts +++ b/extensions/vscode-notebook-tests/src/notebook.test.ts @@ -278,6 +278,23 @@ suite('API tests', () => { await vscode.commands.executeCommand('workbench.action.files.save'); await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); }); + + test('initialzation should not emit cell change events.', async function () { + const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb')); + + let count = 0; + const disposables: vscode.Disposable[] = []; + disposables.push(vscode.notebook.onDidChangeNotebookCells(() => { + count++; + })); + + await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); + assert.equal(count, 0); + + disposables.forEach(d => d.dispose()); + await vscode.commands.executeCommand('workbench.action.files.save'); + await vscode.commands.executeCommand('workbench.action.closeActiveEditor'); + }); }); suite('notebook workflow', () => { diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index d908d6c0fb0..a82dd202a82 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -476,14 +476,16 @@ export class MainThreadNotebookController implements IMainNotebookController { document.textModel.metadata = backup.metadata; document.textModel.languages = backup.languages; + // restored from backup, update the text model without emitting any event to exthost document.textModel.$applyEdit(document.textModel.versionId, [ { editType: CellEditType.Insert, index: 0, cells: backup.cells || [] } - ]); + ], false); + // create document in ext host with cells data await this._mainThreadNotebook.addNotebookDocument({ viewType: document.viewType, handle: document.handle, diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index 0d6daa6086a..a725b04b779 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -263,8 +263,10 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo accpetModelChanged(event: NotebookCellsChangedEvent): void { this._versionId = event.versionId; - if (event.kind === NotebookCellsChangeType.ModelChange) { - this.$spliceNotebookCells(event.changes); + if (event.kind === NotebookCellsChangeType.Initialize) { + this.$spliceNotebookCells(event.changes, true); + } if (event.kind === NotebookCellsChangeType.ModelChange) { + this.$spliceNotebookCells(event.changes, false); } else if (event.kind === NotebookCellsChangeType.Move) { this.$moveCell(event.index, event.newIdx); } else if (event.kind === NotebookCellsChangeType.CellClearOutput) { @@ -276,7 +278,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo } } - private $spliceNotebookCells(splices: NotebookCellsSplice2[]): void { + private $spliceNotebookCells(splices: NotebookCellsSplice2[], initialization: boolean): void { if (this._disposed) { return; } @@ -323,10 +325,12 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo contentChangeEvents.push(event); }); - this._emitter.emitModelChange({ - document: this, - changes: contentChangeEvents - }); + if (!initialization) { + this._emitter.emitModelChange({ + document: this, + changes: contentChangeEvents + }); + } } private $moveCell(index: number, newIdx: number): void { @@ -1105,7 +1109,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN } document.accpetModelChanged({ - kind: NotebookCellsChangeType.ModelChange, + kind: NotebookCellsChangeType.Initialize, versionId: modelData.versionId, changes: [[ 0, diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index 305d80a87bd..c47e6d922fb 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -134,10 +134,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel const cellUri = CellUri.generate(this.uri, cellHandle); return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata); }); - this.insertNewCell(0, mainCells); + this.insertNewCell(0, mainCells, false); } - $applyEdit(modelVersionId: number, rawEdits: ICellEditOperation[]): boolean { + $applyEdit(modelVersionId: number, rawEdits: ICellEditOperation[], emitToExtHost: boolean = true): boolean { if (modelVersionId !== this._versionId) { return false; } @@ -198,19 +198,21 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel return [diff.start, diff.deleteCount, diff.toInsert] as [number, number, NotebookCellTextModel[]]; }); - this._onDidModelChangeProxy.fire({ - kind: NotebookCellsChangeType.ModelChange, - versionId: this._versionId, - changes: diffs.map(diff => [diff[0], diff[1], diff[2].map(cell => ({ - handle: cell.handle, - uri: cell.uri, - source: cell.textBuffer.getLinesContent(), - language: cell.language, - cellKind: cell.cellKind, - outputs: cell.outputs, - metadata: cell.metadata - }))] as [number, number, IMainCellDto[]]) - }); + if (emitToExtHost) { + this._onDidModelChangeProxy.fire({ + kind: NotebookCellsChangeType.ModelChange, + versionId: this._versionId, + changes: diffs.map(diff => [diff[0], diff[1], diff[2].map(cell => ({ + handle: cell.handle, + uri: cell.uri, + source: cell.textBuffer.getLinesContent(), + language: cell.language, + cellKind: cell.cellKind, + outputs: cell.outputs, + metadata: cell.metadata + }))] as [number, number, IMainCellDto[]]) + }); + } this._onDidChangeCells.fire(diffs); return true; diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 7dce654a3f2..c67e219b28a 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -300,7 +300,14 @@ export enum NotebookCellsChangeType { Move = 2, CellClearOutput = 3, CellsClearOutput = 4, - ChangeLanguage = 5 + ChangeLanguage = 5, + Initialize = 6 +} + +export interface NotebookCellsInitializeEvent { + readonly kind: NotebookCellsChangeType.Initialize; + readonly changes: NotebookCellsSplice2[]; + readonly versionId: number; } export interface NotebookCellsModelChangedEvent { @@ -334,7 +341,7 @@ export interface NotebookCellsChangeLanguageEvent { readonly language: string; } -export type NotebookCellsChangedEvent = NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookCellClearOutputEvent | NotebookCellsClearOutputEvent | NotebookCellsChangeLanguageEvent; +export type NotebookCellsChangedEvent = NotebookCellsInitializeEvent | NotebookCellsModelChangedEvent | NotebookCellsModelMoveEvent | NotebookCellClearOutputEvent | NotebookCellsClearOutputEvent | NotebookCellsChangeLanguageEvent; export enum CellEditType { Insert = 1, Delete = 2