Skip to content

Commit 32f29cf

Browse files
committed
transient outputs.
1 parent e88c040 commit 32f29cf

11 files changed

Lines changed: 70 additions & 27 deletions

File tree

src/vs/vscode.proposed.d.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1618,7 +1618,16 @@ declare module 'vscode' {
16181618
notebookType: string,
16191619
provider: NotebookContentProvider,
16201620
options?: {
1621-
transientMetadata?: { [K in keyof NotebookCellMetadata]?: boolean }
1621+
/**
1622+
* Controls if outputs change will trigger notebook document content change and if it will be used in the diff editor
1623+
* Default to false. If the content provider doesn't persisit the outputs in the file document, this should be set to true.
1624+
*/
1625+
transientOutputs: boolean;
1626+
/**
1627+
* Controls if a meetadata property change will trigger notebook document content change and if it will be used in the diff editor
1628+
* Default to false. If the content provider doesn't persisit a metadata property in the file document, it should be set to true.
1629+
*/
1630+
transientMetadata: { [K in keyof NotebookCellMetadata]?: boolean }
16221631
}
16231632
): Disposable;
16241633

src/vs/workbench/api/browser/mainThreadNotebook.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
375375
// }
376376
}
377377

378-
async $registerNotebookProvider(_extension: NotebookExtensionDescription, _viewType: string, _supportBackup: boolean, _kernel: INotebookKernelInfoDto | undefined, options: { transientMetadata: TransientMetadata }): Promise<void> {
378+
async $registerNotebookProvider(_extension: NotebookExtensionDescription, _viewType: string, _supportBackup: boolean, _kernel: INotebookKernelInfoDto | undefined, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise<void> {
379379
const controller: IMainNotebookController = {
380380
kernel: _kernel,
381381
supportBackup: _supportBackup,
@@ -388,7 +388,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
388388

389389
mainthreadTextModel.languages = data.languages;
390390
mainthreadTextModel.metadata = data.metadata;
391-
mainthreadTextModel.transientMetadata = options.transientMetadata;
391+
mainthreadTextModel.transientOptions = options;
392392

393393
const edits: ICellEditOperation[] = [
394394
{ editType: CellEditType.Delete, count: mainthreadTextModel.cells.length, index: 0 },
@@ -412,7 +412,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
412412

413413
textModel.languages = data.languages;
414414
textModel.metadata = data.metadata;
415-
textModel.transientMetadata = options.transientMetadata;
415+
textModel.transientOptions = options;
416416

417417
if (data.cells.length) {
418418
textModel.initialize(data!.cells);

src/vs/workbench/api/common/extHost.api.impl.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
951951
return extHostNotebook.onDidChangeActiveNotebookKernel;
952952
},
953953
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider, options?: {
954-
transientMetadata?: { [K in keyof vscode.NotebookCellMetadata]?: boolean }
954+
transientOutputs: boolean;
955+
transientMetadata: { [K in keyof vscode.NotebookCellMetadata]?: boolean }
955956
}) => {
956957
checkProposedApiEnabled(extension);
957958
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider, options);

src/vs/workbench/api/common/extHost.protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ export type NotebookCellOutputsSplice = [
715715
];
716716

717717
export interface MainThreadNotebookShape extends IDisposable {
718-
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, kernelInfoDto: INotebookKernelInfoDto | undefined, options: { transientMetadata: TransientMetadata }): Promise<void>;
718+
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, kernelInfoDto: INotebookKernelInfoDto | undefined, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise<void>;
719719
$onNotebookChange(viewType: string, resource: UriComponents): Promise<void>;
720720
$unregisterNotebookProvider(viewType: string): Promise<void>;
721721
$registerNotebookKernel(extension: NotebookExtensionDescription, id: string, label: string, selectors: (string | IRelativePattern)[], preloads: UriComponents[]): Promise<void>;

src/vs/workbench/api/common/extHostNotebook.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
955955
viewType: string,
956956
provider: vscode.NotebookContentProvider & { kernel?: vscode.NotebookKernel },
957957
options?: {
958-
transientMetadata?: { [K in keyof NotebookCellMetadata]?: boolean }
958+
transientOutputs: boolean;
959+
transientMetadata: { [K in keyof NotebookCellMetadata]?: boolean };
959960
}
960961
): vscode.Disposable {
961962

@@ -988,7 +989,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
988989

989990
const supportBackup = !!provider.backupNotebook;
990991

991-
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation, description: extension.description }, viewType, supportBackup, provider.kernel ? { id: viewType, label: provider.kernel.label, extensionLocation: extension.extensionLocation, preloads: provider.kernel.preloads } : undefined, { transientMetadata: options?.transientMetadata || {} });
992+
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation, description: extension.description }, viewType, supportBackup, provider.kernel ? { id: viewType, label: provider.kernel.label, extensionLocation: extension.extensionLocation, preloads: provider.kernel.preloads } : undefined, { transientOutputs: options?.transientOutputs || false, transientMetadata: options?.transientMetadata || {} });
992993

993994
return new extHostTypes.Disposable(() => {
994995
listener.dispose();

src/vs/workbench/contrib/notebook/browser/diff/cellComponents.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ abstract class AbstractCellRenderer extends Disposable {
261261
{
262262
updateInfoRendering: this.updateOutputRendering.bind(this),
263263
checkIfModified: (cell) => {
264-
return cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []);
264+
return !this.notebookEditor.textModel!.transientOptions.transientOutputs && cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []);
265265
},
266266
getFoldingState: (cell) => {
267267
return this.cell.outputFoldingState;
@@ -324,7 +324,7 @@ abstract class AbstractCellRenderer extends Disposable {
324324
protected _getFormatedMetadataJSON(metadata: NotebookCellMetadata, language?: string) {
325325
let filteredMetadata: { [key: string]: any } = {};
326326
if (this.notebookEditor.textModel) {
327-
const transientMetadata = this.notebookEditor.textModel!.transientMetadata;
327+
const transientMetadata = this.notebookEditor.textModel!.transientOptions.transientMetadata;
328328

329329
const keys = new Set([...Object.keys(metadata)]);
330330
for (let key of keys) {
@@ -421,7 +421,7 @@ abstract class AbstractCellRenderer extends Disposable {
421421
}
422422

423423
private _buildOutputEditor() {
424-
if (this.cell.type === 'modified') {
424+
if (this.cell.type === 'modified' && !this.notebookEditor.textModel!.transientOptions.transientOutputs) {
425425
const originalOutputsSource = this._getFormatedOutputJSON(this.cell.original?.outputs || []);
426426
const modifiedOutputsSource = this._getFormatedOutputJSON(this.cell.modified?.outputs || []);
427427
if (originalOutputsSource !== modifiedOutputsSource) {
@@ -465,9 +465,11 @@ abstract class AbstractCellRenderer extends Disposable {
465465

466466
const mode = this.modeService.create('json');
467467
const originaloutputSource = this._getFormatedOutputJSON(
468-
this.cell.type === 'insert'
469-
? this.cell.modified!.outputs || []
470-
: this.cell.original!.outputs || []);
468+
this.notebookEditor.textModel!.transientOptions
469+
? []
470+
: this.cell.type === 'insert'
471+
? this.cell.modified!.outputs || []
472+
: this.cell.original!.outputs || []);
471473
const outputModel = this.modelService.createModel(originaloutputSource, mode, undefined, true);
472474
this._outputEditor.setModel(outputModel);
473475

src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { Emitter, Event } from 'vs/base/common/event';
7-
import { ICell, IProcessedOutput, NotebookCellOutputsSplice, CellKind, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
7+
import { ICell, IProcessedOutput, NotebookCellOutputsSplice, CellKind, NotebookCellMetadata, NotebookDocumentMetadata, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
88
import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder';
99
import { URI } from 'vs/base/common/uri';
1010
import * as model from 'vs/editor/common/model';
@@ -85,6 +85,7 @@ export class NotebookCellTextModel extends Disposable implements ICell {
8585
public cellKind: CellKind,
8686
outputs: IProcessedOutput[],
8787
metadata: NotebookCellMetadata | undefined,
88+
public readonly transientOptions: TransientOptions,
8889
private readonly _modelService: ITextModelService
8990
) {
9091
super();
@@ -108,11 +109,25 @@ export class NotebookCellTextModel extends Disposable implements ICell {
108109
}
109110

110111
// TODO, raw outputs
111-
this._hash = hash([hash(this.getValue()), this._metadata, this._outputs]);
112-
// this._hash = hash(this.getValue());
112+
this._hash = hash([hash(this.getValue()), this._getPersisentMetadata, this.transientOptions.transientOutputs ? [] : this._outputs]);
113113
return this._hash;
114114
}
115115

116+
private _getPersisentMetadata() {
117+
let filteredMetadata: { [key: string]: any } = {};
118+
const transientMetadata = this.transientOptions.transientMetadata;
119+
120+
const keys = new Set([...Object.keys(this.metadata)]);
121+
for (let key of keys) {
122+
if (!(transientMetadata[key as keyof NotebookCellMetadata])
123+
) {
124+
filteredMetadata[key] = this.metadata[key as keyof NotebookCellMetadata];
125+
}
126+
}
127+
128+
return filteredMetadata;
129+
}
130+
116131
getTextLength(): number {
117132
return this.textBuffer.getLength();
118133
}

src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event';
88
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
99
import { URI } from 'vs/base/common/uri';
1010
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
11-
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellTextModelSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, NotebookCellsChangedEvent, CellKind, IProcessedOutput, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, IMainCellDto, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
11+
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookCellTextModelSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, NotebookCellsChangedEvent, CellKind, IProcessedOutput, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, IMainCellDto, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
1212
import { ITextSnapshot } from 'vs/editor/common/model';
1313
import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
1414
import { InsertCellEdit, DeleteCellEdit, MoveCellEdit, SpliceCellsEdit, CellMetadataEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit';
@@ -128,7 +128,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
128128
cells: NotebookCellTextModel[];
129129
languages: string[] = [];
130130
metadata: NotebookDocumentMetadata = notebookDocumentMetadataDefaults;
131-
transientMetadata: TransientMetadata = {};
131+
transientOptions: TransientOptions = { transientMetadata: {}, transientOutputs: false };
132132
private _isUntitled: boolean | undefined = undefined;
133133
private _versionId = 0;
134134

@@ -187,7 +187,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
187187
) {
188188
const cellHandle = this._cellhandlePool++;
189189
const cellUri = CellUri.generate(this.uri, cellHandle);
190-
return new NotebookCellTextModel(cellUri, cellHandle, source, language, cellKind, outputs || [], metadata || {}, this._modelService);
190+
return new NotebookCellTextModel(cellUri, cellHandle, source, language, cellKind, outputs || [], metadata || {}, this.transientOptions, this._modelService);
191191
}
192192

193193
initialize(cells: ICellDto2[]) {
@@ -197,7 +197,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
197197
const mainCells = cells.map(cell => {
198198
const cellHandle = this._cellhandlePool++;
199199
const cellUri = CellUri.generate(this.uri, cellHandle);
200-
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this._modelService);
200+
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this.transientOptions, this._modelService);
201201
});
202202

203203
this._isUntitled = false;
@@ -245,7 +245,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
245245
const mainCells = edit.cells.map(cell => {
246246
const cellHandle = this._cellhandlePool++;
247247
const cellUri = CellUri.generate(this.uri, cellHandle);
248-
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this._modelService);
248+
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this.transientOptions, this._modelService);
249249
});
250250
this.insertNewCell(edit.index, mainCells, false);
251251
break;
@@ -473,6 +473,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
473473
spliceNotebookCellOutputs(cellHandle: number, splices: NotebookCellOutputsSplice[]): void {
474474
const cell = this._mapping.get(cellHandle);
475475
cell?.spliceNotebookCellOutputs(splices);
476+
477+
if (!this.transientOptions.transientOutputs) {
478+
this._increaseVersionId();
479+
this.setDirty(true);
480+
this._onDidChangeContent.fire();
481+
}
476482
}
477483

478484
clearCellOutput(handle: number) {
@@ -497,13 +503,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
497503
}
498504
}
499505

500-
private _compareCellMetadata(a: NotebookCellMetadata, b: NotebookCellMetadata) {
506+
private _isCellMetadataChanged(a: NotebookCellMetadata, b: NotebookCellMetadata) {
501507
const keys = new Set([...Object.keys(a || {}), ...Object.keys(b || {})]);
502508
for (let key of keys) {
503509
if (
504510
(a[key as keyof NotebookCellMetadata] !== b[key as keyof NotebookCellMetadata])
505511
&&
506-
!(this.transientMetadata[key as keyof NotebookCellMetadata])
512+
!(this.transientOptions.transientMetadata[key as keyof NotebookCellMetadata])
507513
) {
508514
return true;
509515
}
@@ -519,7 +525,11 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
519525
return;
520526
}
521527

522-
const triggerDirtyChange = this._compareCellMetadata(cell.metadata, metadata);
528+
if (!this._isCellMetadataChanged(cell.metadata, metadata)) {
529+
return;
530+
}
531+
532+
const triggerDirtyChange = this._isCellMetadataChanged(cell.metadata, metadata);
523533

524534
if (triggerDirtyChange) {
525535
if (pushUndoStop) {

src/vs/workbench/contrib/notebook/common/notebookCommon.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ export interface NotebookCellMetadata {
105105

106106
export type TransientMetadata = { [K in keyof NotebookCellMetadata]?: boolean };
107107

108+
export interface TransientOptions {
109+
transientOutputs: boolean;
110+
transientMetadata: TransientMetadata;
111+
}
112+
108113
export interface INotebookDisplayOrder {
109114
defaultOrder: string[];
110115
userOrder?: string[];

src/vs/workbench/contrib/notebook/common/notebookService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const INotebookService = createDecorator<INotebookService>('notebookServi
2424
export interface IMainNotebookController {
2525
kernel: INotebookKernelInfoDto | undefined;
2626
supportBackup: boolean;
27-
options: { transientMetadata: TransientMetadata };
27+
options: { transientOutputs: boolean; transientMetadata: TransientMetadata; };
2828
createNotebook(textModel: NotebookTextModel, editorId?: string, backupId?: string): Promise<void>;
2929
reloadNotebook(mainthreadTextModel: NotebookTextModel): Promise<void>;
3030
resolveNotebookEditor(viewType: string, uri: URI, editorId: string): Promise<void>;

0 commit comments

Comments
 (0)