notebook tests for notebook content change events.

This commit is contained in:
rebornix 2020-05-19 14:46:14 -07:00
parent 345f02dad4
commit cc151dd103
6 changed files with 226 additions and 130 deletions

View file

@ -811,8 +811,7 @@
"trigger",
"unregister",
"write",
"move",
"clear"
"move"
]
}
]

View file

@ -8,25 +8,161 @@ import * as assert from 'assert';
import * as vscode from 'vscode';
import { join } from 'path';
function waitFor(ms: number): Promise<void> {
let resolveFunc: () => void;
export function once<T>(event: vscode.Event<T>): vscode.Event<T> {
return (listener: any, thisArgs = null, disposables?: any) => {
// we need this, in case the event fires during the listener call
let didFire = false;
let result: vscode.Disposable;
result = event(e => {
if (didFire) {
return;
} else if (result) {
result.dispose();
} else {
didFire = true;
}
const promise = new Promise<void>(resolve => {
resolveFunc = resolve;
});
setTimeout(() => {
resolveFunc!();
}, ms);
return listener.call(thisArgs, e);
}, null, disposables);
return promise;
if (didFire) {
result.dispose();
}
return result;
};
}
async function getEventOncePromise<T>(event: vscode.Event<T>): Promise<T> {
return new Promise<T>((resolve, _reject) => {
once(event)((result: T) => resolve(result));
});
}
suite('API tests', () => {
test('document open/close event', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
const firstDocumentOpen = getEventOncePromise(vscode.notebook.onDidOpenNotebookDocument);
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await firstDocumentOpen;
const firstDocumentClose = getEventOncePromise(vscode.notebook.onDidCloseNotebookDocument);
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
await firstDocumentClose;
});
test('shared document in notebook editors', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
let counter = 0;
const disposables: vscode.Disposable[] = [];
disposables.push(vscode.notebook.onDidOpenNotebookDocument(() => {
counter++;
}));
disposables.push(vscode.notebook.onDidCloseNotebookDocument(() => {
counter--;
}));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
assert.equal(counter, 1);
await vscode.commands.executeCommand('workbench.action.splitEditor');
assert.equal(counter, 1);
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
assert.equal(counter, 0);
disposables.forEach(d => d.dispose());
});
test('editor open/close event', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
const firstEditorOpen = getEventOncePromise(vscode.notebook.onDidChangeVisibleNotebookEditors);
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await firstEditorOpen;
const firstEditorClose = getEventOncePromise(vscode.notebook.onDidChangeVisibleNotebookEditors);
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
await firstEditorClose;
});
test('editor open/close event', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
let count = 0;
const disposables: vscode.Disposable[] = [];
disposables.push(vscode.notebook.onDidChangeVisibleNotebookEditors(() => {
count = vscode.notebook.visibleNotebookEditors.length;
}));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
assert.equal(count, 1);
await vscode.commands.executeCommand('workbench.action.splitEditor');
assert.equal(count, 2);
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
assert.equal(count, 0);
});
test('editor editing event', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
const cellsChangeEvent = getEventOncePromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
const cellChangeEventRet = await cellsChangeEvent;
assert.equal(cellChangeEventRet.document, vscode.notebook.activeNotebookEditor?.document);
assert.equal(cellChangeEventRet.changes.length, 1);
assert.deepEqual(cellChangeEventRet.changes[0], {
start: 1,
deletedCount: 0,
items: [
vscode.notebook.activeNotebookEditor!.document.cells[1]
]
});
const moveCellEvent = getEventOncePromise<vscode.NotebookCellMoveEvent>(vscode.notebook.onDidMoveNotebookCell);
await vscode.commands.executeCommand('notebook.cell.moveUp');
const moveCellEventRet = await moveCellEvent;
assert.deepEqual(moveCellEventRet, {
document: vscode.notebook.activeNotebookEditor!.document,
index: 1,
newIndex: 0
});
const cellOutputChange = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
await vscode.commands.executeCommand('notebook.cell.execute');
const cellOutputsAddedRet = await cellOutputChange;
assert.deepEqual(cellOutputsAddedRet, {
document: vscode.notebook.activeNotebookEditor!.document,
cells: [vscode.notebook.activeNotebookEditor!.document.cells[0]]
});
assert.equal(cellOutputsAddedRet.cells[0].outputs.length, 1);
const cellOutputClear = getEventOncePromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
await vscode.commands.executeCommand('notebook.cell.clearOutputs');
const cellOutputsCleardRet = await cellOutputClear;
assert.deepEqual(cellOutputsCleardRet, {
document: vscode.notebook.activeNotebookEditor!.document,
cells: [vscode.notebook.activeNotebookEditor!.document.cells[0]]
});
assert.equal(cellOutputsAddedRet.cells[0].outputs.length, 0);
// const cellChangeLanguage = getEventOncePromise<vscode.NotebookCellLanguageChangeEvent>(vscode.notebook.onDidChangeCellLanguage);
// await vscode.commands.executeCommand('notebook.cell.changeToMarkdown');
// const cellChangeLanguageRet = await cellChangeLanguage;
// assert.deepEqual(cellChangeLanguageRet, {
// document: vscode.notebook.activeNotebookEditor!.document,
// cells: vscode.notebook.activeNotebookEditor!.document.cells[0],
// language: 'markdown'
// });
await vscode.commands.executeCommand('workbench.action.files.save');
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
});
});
suite('notebook workflow', () => {
test('notebook open', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, 'test');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');
@ -48,8 +184,6 @@ suite('notebook workflow', () => {
test('notebook cell actions', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, 'test');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');
@ -119,8 +253,6 @@ suite('notebook workflow', () => {
test('move cells will not recreate cells in ExtHost', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
await vscode.commands.executeCommand('notebook.focusTop');
@ -139,8 +271,6 @@ suite('notebook workflow', () => {
// const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
// await waitFor(500);
// assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
// const editor = vscode.notebook.activeNotebookEditor!;
@ -164,9 +294,6 @@ suite('notebook workflow', () => {
test('cell runnable metadata is respected', async () => {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
const editor = vscode.notebook.activeNotebookEditor!;
@ -188,9 +315,6 @@ suite('notebook workflow', () => {
test('document runnable metadata is respected', async () => {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
const editor = vscode.notebook.activeNotebookEditor!;
@ -213,8 +337,6 @@ suite('notebook dirty state', () => {
test('notebook open', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, 'test');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');
@ -235,8 +357,6 @@ suite('notebook dirty state', () => {
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true);
assert.equal(vscode.notebook.activeNotebookEditor?.selection !== undefined, true);
assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells[1], vscode.notebook.activeNotebookEditor?.selection);
@ -251,8 +371,6 @@ suite('notebook undo redo', () => {
test('notebook open', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, 'test');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');
@ -296,8 +414,6 @@ suite('notebook working copy', () => {
test('notebook revert on close', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, '');
@ -307,8 +423,6 @@ suite('notebook working copy', () => {
// close active editor from command will revert the file
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true);
assert.equal(vscode.notebook.activeNotebookEditor?.selection !== undefined, true);
assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells[0], vscode.notebook.activeNotebookEditor?.selection);
@ -321,8 +435,6 @@ suite('notebook working copy', () => {
test('notebook revert', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, '');
@ -342,8 +454,6 @@ suite('notebook working copy', () => {
test('multiple tabs: dirty + clean', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, '');
@ -352,7 +462,6 @@ suite('notebook working copy', () => {
const secondResource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './second.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
await waitFor(500);
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
// make sure that the previous dirty editor is still restored in the extension host and no data loss
@ -369,8 +478,6 @@ suite('notebook working copy', () => {
test('multiple tabs: two dirty tabs and switching', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, '');
@ -379,7 +486,6 @@ suite('notebook working copy', () => {
const secondResource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './second.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', secondResource, 'notebookCoreTest');
await waitFor(500);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, '');
@ -407,8 +513,6 @@ suite('notebook working copy', () => {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
const firstNotebookEditor = vscode.notebook.activeNotebookEditor;
assert.equal(firstNotebookEditor !== undefined, true, 'notebook first');
assert.equal(firstNotebookEditor!.selection?.source, 'test');
@ -433,8 +537,6 @@ suite('metadata', () => {
test('custom metadata should be supported', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
assert.equal(vscode.notebook.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false);
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.metadata.custom!['testCellMetadata'] as number, 123);
@ -446,8 +548,6 @@ suite('metadata', () => {
test('custom metadata should be supported', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
assert.equal(vscode.notebook.activeNotebookEditor!.document.metadata.custom!['testMetadata'] as boolean, false);
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.metadata.custom!['testCellMetadata'] as number, 123);
@ -464,8 +564,6 @@ suite('regression', () => {
test('microsoft/vscode-github-issue-notebooks#26. Insert template cell in the new empty document', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './empty.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.source, '');
assert.equal(vscode.notebook.activeNotebookEditor!.selection?.language, 'typescript');
@ -476,8 +574,6 @@ suite('regression', () => {
test('#97830, #97764. Support switch to other editor types', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './empty.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
await vscode.commands.executeCommand('default:type', { text: 'var abc = 0;' });
@ -496,15 +592,11 @@ suite('regression', () => {
test('#96105 - dirty editors', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './empty.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'default');
await waitFor(500);
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
await vscode.commands.executeCommand('default:type', { text: 'var abc = 0;' });
// now it's dirty, open the resource with notebook editor should open a new one
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.notEqual(vscode.notebook.activeNotebookEditor, undefined, 'notebook first');
assert.notEqual(vscode.window.activeTextEditor, undefined);
@ -518,10 +610,9 @@ suite('webview resource uri', () => {
test('asWebviewUri', async function () {
const resource = vscode.Uri.parse(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
await waitFor(500);
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
const uri = vscode.notebook.activeNotebookEditor!.asWebviewUri(vscode.Uri.parse('./hello.png'));
assert.equal(uri.scheme, 'vscode-webview-resource');
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
});
});

View file

@ -1801,7 +1801,7 @@ declare module 'vscode' {
}
export interface NotebookCellsChange {
export interface NotebookCellsChangeData {
readonly start: number;
readonly deletedCount: number;
readonly items: NotebookCell[];
@ -1813,7 +1813,7 @@ declare module 'vscode' {
* The affected document.
*/
readonly document: NotebookDocument;
readonly changes: ReadonlyArray<NotebookCellsChange>;
readonly changes: ReadonlyArray<NotebookCellsChangeData>;
}
export interface NotebookCellMoveEvent {
@ -1826,21 +1826,13 @@ declare module 'vscode' {
readonly newIndex: number;
}
export interface NotebookCellOutputsClearEvent {
/**
* The affected document.
*/
readonly document: NotebookDocument;
readonly cell: NotebookCell;
}
export interface NotebookAllCellsOutputsClearEvent {
export interface NotebookCellOutputsChangeEvent {
/**
* The affected document.
*/
readonly document: NotebookDocument;
readonly cells: NotebookCell[];
}
export interface NotebookCellLanguageChangeEvent {
@ -1929,8 +1921,7 @@ declare module 'vscode' {
export const onDidChangeNotebookCells: Event<NotebookCellsChangeEvent>;
export const onDidMoveNotebookCell: Event<NotebookCellMoveEvent>;
export const onDidClearCellOutputs: Event<NotebookCellOutputsClearEvent>;
export const onDidClearAllCellsOutputs: Event<NotebookAllCellsOutputsClearEvent>;
export const onDidChangeCellOutputs: Event<NotebookCellOutputsChangeEvent>;
export const onDidChangeCellLanguage: Event<NotebookCellLanguageChangeEvent>;
/**
* Create a document that is the concatenation of all notebook cells. By default all code-cells are included

View file

@ -952,13 +952,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.onDidMoveNotebookCell(listener, thisArgs, disposables);
},
onDidClearCellOutputs(listener, thisArgs?, disposables?) {
onDidChangeCellOutputs(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidClearCellOutputs(listener, thisArgs, disposables);
},
onDidClearAllCellsOutputs(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidClearAllCellsOutputs(listener, thisArgs, disposables);
return extHostNotebook.onDidChangeCellOutputs(listener, thisArgs, disposables);
},
onDidChangeCellLanguage(listener, thisArgs?, disposables?) {
checkProposedApiEnabled(extension);

View file

@ -45,8 +45,7 @@ function getObservable<T extends Object>(obj: T): IObservable<T> {
interface INotebookEventEmitter {
emitModelChange(events: vscode.NotebookCellsChangeEvent): void;
emitMoveChange(event: vscode.NotebookCellMoveEvent): void;
emitCellOutputsClear(event: vscode.NotebookCellOutputsClearEvent): void;
emitAllCellsOutputsClearEvent(event: vscode.NotebookAllCellsOutputsClearEvent): void;
emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void;
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void;
}
@ -232,6 +231,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
constructor(
private readonly _proxy: MainThreadNotebookShape,
private _documentsAndEditors: ExtHostDocumentsAndEditors,
private _emitter: INotebookEventEmitter,
public viewType: string,
public uri: URI,
public renderingHandler: ExtHostNotebookOutputRenderingHandler
@ -259,22 +259,22 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
get isDirty() { return false; }
accpetModelChanged(event: NotebookCellsChangedEvent, emitter?: INotebookEventEmitter): void {
accpetModelChanged(event: NotebookCellsChangedEvent): void {
this._versionId = event.versionId;
if (event.kind === NotebookCellsChangeType.ModelChange) {
this.$spliceNotebookCells(event.changes, emitter);
this.$spliceNotebookCells(event.changes);
} else if (event.kind === NotebookCellsChangeType.Move) {
this.$moveCell(event.index, event.newIdx, emitter);
this.$moveCell(event.index, event.newIdx);
} else if (event.kind === NotebookCellsChangeType.CellClearOutput) {
this.$clearCellOutputs(event.index, emitter);
this.$clearCellOutputs(event.index);
} else if (event.kind === NotebookCellsChangeType.CellsClearOutput) {
this.$clearAllCellOutputs(emitter);
this.$clearAllCellOutputs();
} else if (event.kind === NotebookCellsChangeType.ChangeLanguage) {
this.$changeCellLanguage(event.index, event.language, emitter);
this.$changeCellLanguage(event.index, event.language);
}
}
private $spliceNotebookCells(splices: NotebookCellsSplice2[], emitter?: INotebookEventEmitter): void {
private $spliceNotebookCells(splices: NotebookCellsSplice2[]): void {
if (this._disposed) {
return;
}
@ -283,7 +283,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
return;
}
let contentChangeEvents: vscode.NotebookCellsChange[] = [];
let contentChangeEvents: vscode.NotebookCellsChangeData[] = [];
splices.reverse().forEach(splice => {
let cellDtos = splice[2];
@ -316,7 +316,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
this.cells.splice(splice[0], splice[1], ...newCells);
const event: vscode.NotebookCellsChange = {
const event: vscode.NotebookCellsChangeData = {
start: splice[0],
deletedCount: splice[1],
items: newCells
@ -325,40 +325,46 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
contentChangeEvents.push(event);
});
emitter?.emitModelChange({
this._emitter.emitModelChange({
document: this,
changes: contentChangeEvents
});
}
private $moveCell(index: number, newIdx: number, emitter?: INotebookEventEmitter): void {
private $moveCell(index: number, newIdx: number): void {
const cells = this.cells.splice(index, 1);
this.cells.splice(newIdx, 0, ...cells);
const event: vscode.NotebookCellMoveEvent = { document: this, index, newIndex: newIdx };
emitter?.emitMoveChange(event);
this._emitter.emitMoveChange(event);
}
private $clearCellOutputs(index: number, emitter?: INotebookEventEmitter): void {
private $clearCellOutputs(index: number): void {
const cell = this.cells[index];
cell.outputs = [];
const event: vscode.NotebookCellOutputsClearEvent = { document: this, cell };
emitter?.emitCellOutputsClear(event);
const event: vscode.NotebookCellOutputsChangeEvent = { document: this, cells: [cell] };
this._emitter.emitCellOutputsChange(event);
}
private $clearAllCellOutputs(emitter?: INotebookEventEmitter): void {
this.cells.forEach(cell => cell.outputs = []);
const event: vscode.NotebookAllCellsOutputsClearEvent = { document: this };
emitter?.emitAllCellsOutputsClearEvent(event);
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);
}
private $changeCellLanguage(index: number, language: string, emitter?: INotebookEventEmitter): void {
private $changeCellLanguage(index: number, language: string): void {
const cell = this.cells[index];
cell.language = language;
const event: vscode.NotebookCellLanguageChangeEvent = { document: this, cell, language };
emitter?.emitCellLanguageChange(event);
this._emitter.emitCellLanguageChange(event);
}
eventuallyUpdateCellOutputs(cell: ExtHostCell, diffs: ISplice<vscode.CellOutput>[]) {
async eventuallyUpdateCellOutputs(cell: ExtHostCell, diffs: ISplice<vscode.CellOutput>[]) {
let renderers = new Set<number>();
let outputDtos: NotebookCellOutputsSplice[] = diffs.map(diff => {
let outputs = diff.toInsert;
@ -379,7 +385,11 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
return [diff.start, diff.deleteCount, transformedOutputs];
});
this._proxy.$spliceNotebookCellOutputs(this.viewType, this.uri, cell.handle, outputDtos, Array.from(renderers));
await this._proxy.$spliceNotebookCellOutputs(this.viewType, this.uri, cell.handle, outputDtos, Array.from(renderers));
this._emitter.emitCellOutputsChange({
document: this,
cells: [cell]
});
}
transformMimeTypes(output: vscode.CellDisplayOutput): ITransformedDisplayOutputDto {
@ -674,10 +684,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
readonly onDidChangeNotebookCells = this._onDidChangeNotebookCells.event;
private readonly _onDidMoveNotebookCell = new Emitter<vscode.NotebookCellMoveEvent>();
readonly onDidMoveNotebookCell = this._onDidMoveNotebookCell.event;
private readonly _onDidClearCellOutputs = new Emitter<vscode.NotebookCellOutputsClearEvent>();
readonly onDidClearCellOutputs = this._onDidClearCellOutputs.event;
private readonly _onDidClearAllCellsOutputs = new Emitter<vscode.NotebookAllCellsOutputsClearEvent>();
readonly onDidClearAllCellsOutputs = this._onDidClearAllCellsOutputs.event;
private readonly _onDidChangeCellOutputs = new Emitter<vscode.NotebookCellOutputsChangeEvent>();
readonly onDidChangeCellOutputs = this._onDidChangeCellOutputs.event;
private readonly _onDidChangeCellLanguage = new Emitter<vscode.NotebookCellLanguageChangeEvent>();
readonly onDidChangeCellLanguage = this._onDidChangeCellLanguage.event;
@ -797,7 +805,21 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
let document = this._documents.get(URI.revive(uri).toString());
if (!document) {
document = this._unInitializedDocuments.get(revivedUri.toString()) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, revivedUri, this);
const that = this;
document = this._unInitializedDocuments.get(revivedUri.toString()) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, {
emitModelChange(event: vscode.NotebookCellsChangeEvent): void {
that._onDidChangeNotebookCells.fire(event);
},
emitMoveChange(event: vscode.NotebookCellMoveEvent): void {
that._onDidMoveNotebookCell.fire(event);
},
emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void {
that._onDidChangeCellOutputs.fire(event);
},
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void {
that._onDidChangeCellLanguage.fire(event);
}
}, viewType, revivedUri, this);
this._unInitializedDocuments.set(revivedUri.toString(), document);
}
@ -1003,24 +1025,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
const document = this._documents.get(URI.revive(uriComponents).toString());
if (document) {
const that = this;
document.accpetModelChanged(event, {
emitModelChange(event: vscode.NotebookCellsChangeEvent): void {
that._onDidChangeNotebookCells.fire(event);
},
emitMoveChange(event: vscode.NotebookCellMoveEvent): void {
that._onDidMoveNotebookCell.fire(event);
},
emitCellOutputsClear(event: vscode.NotebookCellOutputsClearEvent): void {
that._onDidClearCellOutputs.fire(event);
},
emitAllCellsOutputsClearEvent(event: vscode.NotebookAllCellsOutputsClearEvent): void {
that._onDidClearAllCellsOutputs.fire(event);
},
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void {
that._onDidChangeCellLanguage.fire(event);
}
});
document.accpetModelChanged(event);
}
}
@ -1111,7 +1116,22 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
const revivedUriStr = revivedUri.toString();
const viewType = modelData.viewType;
if (!this._documents.has(revivedUriStr)) {
let document = this._unInitializedDocuments.get(revivedUriStr) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, revivedUri, this);
const that = this;
let document = this._unInitializedDocuments.get(revivedUriStr) ?? new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, {
emitModelChange(event: vscode.NotebookCellsChangeEvent): void {
that._onDidChangeNotebookCells.fire(event);
},
emitMoveChange(event: vscode.NotebookCellMoveEvent): void {
that._onDidMoveNotebookCell.fire(event);
},
emitCellOutputsChange(event: vscode.NotebookCellOutputsChangeEvent): void {
that._onDidChangeCellOutputs.fire(event);
},
emitCellLanguageChange(event: vscode.NotebookCellLanguageChangeEvent): void {
that._onDidChangeCellLanguage.fire(event);
}
}, viewType, revivedUri, this);
this._unInitializedDocuments.delete(revivedUriStr);
if (modelData.metadata) {
document.metadata = {

View file

@ -54,8 +54,7 @@ export class ExtHostNotebookConcatDocument implements vscode.NotebookConcatTextD
this._disposables.add(extHostNotebooks.onDidMoveNotebookCell(e => documentChange(e.document)));
this._disposables.add(extHostNotebooks.onDidChangeCellLanguage(e => documentChange(e.document)));
this._disposables.add(extHostNotebooks.onDidClearAllCellsOutputs(e => documentChange(e.document)));
this._disposables.add(extHostNotebooks.onDidClearCellOutputs(e => documentChange(e.document)));
this._disposables.add(extHostNotebooks.onDidChangeCellOutputs(e => documentChange(e.document)));
this._disposables.add(extHostNotebooks.onDidChangeNotebookCells(e => documentChange(e.document)));
}