mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-26 11:38:51 +01:00
move/copy onDidSaveNotebookDocument-event into workspace, add onDidChangeNotebookDocument-event which fires for any notebook change: metadata, structure, cell output, cell metadata
This commit is contained in:
@@ -882,6 +882,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
}
|
||||
return extHostNotebook.getNotebookDocument(uri).apiNotebook;
|
||||
},
|
||||
onDidSaveNotebookDocument(listener, thisArg, disposables) {
|
||||
checkProposedApiEnabled(extension, 'notebookDocumentEvents');
|
||||
return extHostNotebookDocuments.onDidSaveNotebookDocument(listener, thisArg, disposables);
|
||||
},
|
||||
onDidChangeNotebookDocument(listener, thisArg, disposables) {
|
||||
checkProposedApiEnabled(extension, 'notebookDocumentEvents');
|
||||
return extHostNotebookDocuments.onDidChangeNotebookDocument(listener, thisArg, disposables);
|
||||
},
|
||||
get onDidOpenNotebookDocument(): Event<vscode.NotebookDocument> {
|
||||
return extHostNotebook.onDidOpenNotebookDocument;
|
||||
},
|
||||
|
||||
@@ -2005,7 +2005,7 @@ export type NotebookCellsChangedEventDto = {
|
||||
};
|
||||
|
||||
export interface ExtHostNotebookDocumentsShape {
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: SerializableObjectWithBuffers<NotebookCellsChangedEventDto>, isDirty: boolean): void;
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: SerializableObjectWithBuffers<NotebookCellsChangedEventDto>, isDirty: boolean, newMetadata?: notebookCommon.NotebookDocumentMetadata): void;
|
||||
$acceptDirtyStateChanged(uriComponents: UriComponents, isDirty: boolean): void;
|
||||
$acceptModelSaved(uriComponents: UriComponents): void;
|
||||
$acceptDocumentPropertiesChanged(uriComponents: UriComponents, data: INotebookDocumentPropertiesChangeData): void;
|
||||
|
||||
@@ -10,12 +10,25 @@ import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { ExtHostDocumentsAndEditors, IExtHostModelAddedData } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import * as extHostTypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { NotebookRange } from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as notebookCommon from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
class RawContentChangeEvent {
|
||||
|
||||
constructor(readonly start: number, readonly deletedCount: number, readonly deletedItems: vscode.NotebookCell[], readonly items: ExtHostCell[]) { }
|
||||
|
||||
constructor(readonly start: number, readonly deletedCount: number, readonly deletedItems: vscode.NotebookCell[], readonly items: ExtHostCell[]) {
|
||||
|
||||
}
|
||||
|
||||
asApiEvent(): vscode.NotebookDocumentContentChange {
|
||||
return {
|
||||
range: new NotebookRange(this.start, this.start + this.deletedCount),
|
||||
addedCells: this.items.map(cell => cell.apiCell),
|
||||
removedCells: this.deletedItems,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
static asApiEvents(events: RawContentChangeEvent[]): readonly vscode.NotebookCellsChangeData[] {
|
||||
return events.map(event => {
|
||||
@@ -157,7 +170,7 @@ export class ExtHostNotebookDocument {
|
||||
) {
|
||||
this._notebookType = data.viewType;
|
||||
this._metadata = Object.freeze(data.metadata ?? Object.create(null));
|
||||
this._spliceNotebookCells([[0, 0, data.cells]], true /* init -> no event*/);
|
||||
this._spliceNotebookCells([[0, 0, data.cells]], true /* init -> no event*/, undefined);
|
||||
this._versionId = data.versionId;
|
||||
}
|
||||
|
||||
@@ -213,29 +226,67 @@ export class ExtHostNotebookDocument {
|
||||
this._isDirty = isDirty;
|
||||
}
|
||||
|
||||
acceptModelChanged(event: extHostProtocol.NotebookCellsChangedEventDto, isDirty: boolean): void {
|
||||
acceptModelChanged(event: extHostProtocol.NotebookCellsChangedEventDto, isDirty: boolean, newMetadata: notebookCommon.NotebookDocumentMetadata | undefined): vscode.NotebookDocumentChangeEvent {
|
||||
this._versionId = event.versionId;
|
||||
this._isDirty = isDirty;
|
||||
this.acceptDocumentPropertiesChanged({ metadata: newMetadata });
|
||||
|
||||
|
||||
const result = {
|
||||
notebook: this.apiNotebook,
|
||||
metadata: newMetadata,
|
||||
cellChanges: <vscode.NotebookDocumentContentCellChange[]>[],
|
||||
contentChanges: <vscode.NotebookDocumentContentChange[]>[],
|
||||
};
|
||||
const cellOutputChanges = new Set<ExtHostCell>();
|
||||
const cellMetadataChanges = new Set<ExtHostCell>();
|
||||
|
||||
// -- apply change and populate content changes
|
||||
|
||||
for (const rawEvent of event.rawEvents) {
|
||||
if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ModelChange) {
|
||||
this._spliceNotebookCells(rawEvent.changes, false);
|
||||
this._spliceNotebookCells(rawEvent.changes, false, result.contentChanges);
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.Move) {
|
||||
this._moveCell(rawEvent.index, rawEvent.newIdx);
|
||||
this._moveCell(rawEvent.index, rawEvent.newIdx, result.contentChanges);
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.Output) {
|
||||
this._setCellOutputs(rawEvent.index, rawEvent.outputs);
|
||||
cellOutputChanges.add(this._cells[rawEvent.index]);
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.OutputItem) {
|
||||
this._setCellOutputItems(rawEvent.index, rawEvent.outputId, rawEvent.append, rawEvent.outputItems);
|
||||
cellOutputChanges.add(this._cells[rawEvent.index]);
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeLanguage) {
|
||||
this._changeCellLanguage(rawEvent.index, rawEvent.language);
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMime) {
|
||||
this._changeCellMime(rawEvent.index, rawEvent.mime);
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellMetadata) {
|
||||
this._changeCellMetadata(rawEvent.index, rawEvent.metadata);
|
||||
cellMetadataChanges.add(this._cells[rawEvent.index]);
|
||||
} else if (rawEvent.kind === notebookCommon.NotebookCellsChangeType.ChangeCellInternalMetadata) {
|
||||
this._changeCellInternalMetadata(rawEvent.index, rawEvent.internalMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
// -- populate cell changes
|
||||
|
||||
for (const cell of cellOutputChanges) {
|
||||
result.cellChanges.push({
|
||||
cell: cell.apiCell,
|
||||
outputs: cell.apiCell.outputs,
|
||||
metadata: cellMetadataChanges.has(cell) ? cell.apiCell.metadata : undefined,
|
||||
executionSummary: undefined
|
||||
});
|
||||
cellMetadataChanges.delete(cell);
|
||||
}
|
||||
for (const cell of cellMetadataChanges) {
|
||||
result.cellChanges.push({
|
||||
cell: cell.apiCell,
|
||||
metadata: cell.apiCell.metadata,
|
||||
outputs: undefined,
|
||||
executionSummary: undefined
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private _validateIndex(index: number): number {
|
||||
@@ -277,7 +328,7 @@ export class ExtHostNotebookDocument {
|
||||
return this._proxy.$trySaveNotebook(this.uri);
|
||||
}
|
||||
|
||||
private _spliceNotebookCells(splices: notebookCommon.NotebookCellTextModelSplice<extHostProtocol.NotebookCellDto>[], initialization: boolean): void {
|
||||
private _spliceNotebookCells(splices: notebookCommon.NotebookCellTextModelSplice<extHostProtocol.NotebookCellDto>[], initialization: boolean, bucket: vscode.NotebookDocumentContentChange[] | undefined): void {
|
||||
if (this._disposed) {
|
||||
return;
|
||||
}
|
||||
@@ -303,7 +354,6 @@ export class ExtHostNotebookDocument {
|
||||
removedCellDocuments.push(cell.uri);
|
||||
changeEvent.deletedItems.push(cell.apiCell);
|
||||
}
|
||||
|
||||
contentChangeEvents.push(changeEvent);
|
||||
});
|
||||
|
||||
@@ -312,6 +362,12 @@ export class ExtHostNotebookDocument {
|
||||
removedDocuments: removedCellDocuments
|
||||
});
|
||||
|
||||
if (bucket) {
|
||||
for (let changeEvent of contentChangeEvents) {
|
||||
bucket.push(changeEvent.asApiEvent());
|
||||
}
|
||||
}
|
||||
|
||||
if (!initialization) {
|
||||
this._emitter.emitModelChange(deepFreeze({
|
||||
document: this.apiNotebook,
|
||||
@@ -320,13 +376,16 @@ export class ExtHostNotebookDocument {
|
||||
}
|
||||
}
|
||||
|
||||
private _moveCell(index: number, newIdx: number): void {
|
||||
private _moveCell(index: number, newIdx: number, bucket: vscode.NotebookDocumentContentChange[]): void {
|
||||
const cells = this._cells.splice(index, 1);
|
||||
this._cells.splice(newIdx, 0, ...cells);
|
||||
const changes = [
|
||||
new RawContentChangeEvent(index, 1, cells.map(c => c.apiCell), []),
|
||||
new RawContentChangeEvent(newIdx, 0, [], cells)
|
||||
];
|
||||
for (const change of changes) {
|
||||
bucket.push(change.asApiEvent());
|
||||
}
|
||||
this._emitter.emitModelChange(deepFreeze({
|
||||
document: this.apiNotebook,
|
||||
changes: RawContentChangeEvent.asApiEvents(changes)
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { deepFreeze } from 'vs/base/common/objects';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostNotebookController } from 'vs/workbench/api/common/extHostNotebook';
|
||||
import { NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { SerializableObjectWithBuffers } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import type * as vscode from 'vscode';
|
||||
|
||||
@@ -16,17 +18,21 @@ export class ExtHostNotebookDocuments implements extHostProtocol.ExtHostNotebook
|
||||
private readonly _onDidChangeNotebookDocumentMetadata = new Emitter<vscode.NotebookDocumentMetadataChangeEvent>();
|
||||
readonly onDidChangeNotebookDocumentMetadata = this._onDidChangeNotebookDocumentMetadata.event;
|
||||
|
||||
private _onDidSaveNotebookDocument = new Emitter<vscode.NotebookDocument>();
|
||||
private readonly _onDidSaveNotebookDocument = new Emitter<vscode.NotebookDocument>();
|
||||
readonly onDidSaveNotebookDocument = this._onDidSaveNotebookDocument.event;
|
||||
|
||||
private readonly _onDidChangeNotebookDocument = new Emitter<vscode.NotebookDocumentChangeEvent>();
|
||||
readonly onDidChangeNotebookDocument = this._onDidChangeNotebookDocument.event;
|
||||
|
||||
constructor(
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
private readonly _notebooksAndEditors: ExtHostNotebookController,
|
||||
) { }
|
||||
|
||||
$acceptModelChanged(uri: UriComponents, event: SerializableObjectWithBuffers<extHostProtocol.NotebookCellsChangedEventDto>, isDirty: boolean): void {
|
||||
$acceptModelChanged(uri: UriComponents, event: SerializableObjectWithBuffers<extHostProtocol.NotebookCellsChangedEventDto>, isDirty: boolean, newMetadata?: NotebookDocumentMetadata): void {
|
||||
const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri));
|
||||
document.acceptModelChanged(event.value, isDirty);
|
||||
const e = document.acceptModelChanged(event.value, isDirty, newMetadata);
|
||||
this._onDidChangeNotebookDocument.fire(deepFreeze(e));
|
||||
}
|
||||
|
||||
$acceptDirtyStateChanged(uri: UriComponents, isDirty: boolean): void {
|
||||
|
||||
Reference in New Issue
Block a user