mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 09:08:48 +01:00
transient outputs.
This commit is contained in:
Vendored
+10
-1
@@ -1618,7 +1618,16 @@ declare module 'vscode' {
|
||||
notebookType: string,
|
||||
provider: NotebookContentProvider,
|
||||
options?: {
|
||||
transientMetadata?: { [K in keyof NotebookCellMetadata]?: boolean }
|
||||
/**
|
||||
* Controls if outputs change will trigger notebook document content change and if it will be used in the diff editor
|
||||
* Default to false. If the content provider doesn't persisit the outputs in the file document, this should be set to true.
|
||||
*/
|
||||
transientOutputs: boolean;
|
||||
/**
|
||||
* Controls if a meetadata property change will trigger notebook document content change and if it will be used in the diff editor
|
||||
* Default to false. If the content provider doesn't persisit a metadata property in the file document, it should be set to true.
|
||||
*/
|
||||
transientMetadata: { [K in keyof NotebookCellMetadata]?: boolean }
|
||||
}
|
||||
): Disposable;
|
||||
|
||||
|
||||
@@ -375,7 +375,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
// }
|
||||
}
|
||||
|
||||
async $registerNotebookProvider(_extension: NotebookExtensionDescription, _viewType: string, _supportBackup: boolean, _kernel: INotebookKernelInfoDto | undefined, options: { transientMetadata: TransientMetadata }): Promise<void> {
|
||||
async $registerNotebookProvider(_extension: NotebookExtensionDescription, _viewType: string, _supportBackup: boolean, _kernel: INotebookKernelInfoDto | undefined, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise<void> {
|
||||
const controller: IMainNotebookController = {
|
||||
kernel: _kernel,
|
||||
supportBackup: _supportBackup,
|
||||
@@ -388,7 +388,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
|
||||
mainthreadTextModel.languages = data.languages;
|
||||
mainthreadTextModel.metadata = data.metadata;
|
||||
mainthreadTextModel.transientMetadata = options.transientMetadata;
|
||||
mainthreadTextModel.transientOptions = options;
|
||||
|
||||
const edits: ICellEditOperation[] = [
|
||||
{ editType: CellEditType.Delete, count: mainthreadTextModel.cells.length, index: 0 },
|
||||
@@ -412,7 +412,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
|
||||
textModel.languages = data.languages;
|
||||
textModel.metadata = data.metadata;
|
||||
textModel.transientMetadata = options.transientMetadata;
|
||||
textModel.transientOptions = options;
|
||||
|
||||
if (data.cells.length) {
|
||||
textModel.initialize(data!.cells);
|
||||
|
||||
@@ -951,7 +951,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostNotebook.onDidChangeActiveNotebookKernel;
|
||||
},
|
||||
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider, options?: {
|
||||
transientMetadata?: { [K in keyof vscode.NotebookCellMetadata]?: boolean }
|
||||
transientOutputs: boolean;
|
||||
transientMetadata: { [K in keyof vscode.NotebookCellMetadata]?: boolean }
|
||||
}) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider, options);
|
||||
|
||||
@@ -715,7 +715,7 @@ export type NotebookCellOutputsSplice = [
|
||||
];
|
||||
|
||||
export interface MainThreadNotebookShape extends IDisposable {
|
||||
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, kernelInfoDto: INotebookKernelInfoDto | undefined, options: { transientMetadata: TransientMetadata }): Promise<void>;
|
||||
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, kernelInfoDto: INotebookKernelInfoDto | undefined, options: { transientOutputs: boolean; transientMetadata: TransientMetadata }): Promise<void>;
|
||||
$onNotebookChange(viewType: string, resource: UriComponents): Promise<void>;
|
||||
$unregisterNotebookProvider(viewType: string): Promise<void>;
|
||||
$registerNotebookKernel(extension: NotebookExtensionDescription, id: string, label: string, selectors: (string | IRelativePattern)[], preloads: UriComponents[]): Promise<void>;
|
||||
|
||||
@@ -955,7 +955,8 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
viewType: string,
|
||||
provider: vscode.NotebookContentProvider & { kernel?: vscode.NotebookKernel },
|
||||
options?: {
|
||||
transientMetadata?: { [K in keyof NotebookCellMetadata]?: boolean }
|
||||
transientOutputs: boolean;
|
||||
transientMetadata: { [K in keyof NotebookCellMetadata]?: boolean };
|
||||
}
|
||||
): vscode.Disposable {
|
||||
|
||||
@@ -988,7 +989,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
|
||||
const supportBackup = !!provider.backupNotebook;
|
||||
|
||||
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 || {} });
|
||||
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 || {} });
|
||||
|
||||
return new extHostTypes.Disposable(() => {
|
||||
listener.dispose();
|
||||
|
||||
@@ -261,7 +261,7 @@ abstract class AbstractCellRenderer extends Disposable {
|
||||
{
|
||||
updateInfoRendering: this.updateOutputRendering.bind(this),
|
||||
checkIfModified: (cell) => {
|
||||
return cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []);
|
||||
return !this.notebookEditor.textModel!.transientOptions.transientOutputs && cell.type === 'modified' && hash(cell.original?.outputs ?? []) !== hash(cell.modified?.outputs ?? []);
|
||||
},
|
||||
getFoldingState: (cell) => {
|
||||
return this.cell.outputFoldingState;
|
||||
@@ -324,7 +324,7 @@ abstract class AbstractCellRenderer extends Disposable {
|
||||
protected _getFormatedMetadataJSON(metadata: NotebookCellMetadata, language?: string) {
|
||||
let filteredMetadata: { [key: string]: any } = {};
|
||||
if (this.notebookEditor.textModel) {
|
||||
const transientMetadata = this.notebookEditor.textModel!.transientMetadata;
|
||||
const transientMetadata = this.notebookEditor.textModel!.transientOptions.transientMetadata;
|
||||
|
||||
const keys = new Set([...Object.keys(metadata)]);
|
||||
for (let key of keys) {
|
||||
@@ -421,7 +421,7 @@ abstract class AbstractCellRenderer extends Disposable {
|
||||
}
|
||||
|
||||
private _buildOutputEditor() {
|
||||
if (this.cell.type === 'modified') {
|
||||
if (this.cell.type === 'modified' && !this.notebookEditor.textModel!.transientOptions.transientOutputs) {
|
||||
const originalOutputsSource = this._getFormatedOutputJSON(this.cell.original?.outputs || []);
|
||||
const modifiedOutputsSource = this._getFormatedOutputJSON(this.cell.modified?.outputs || []);
|
||||
if (originalOutputsSource !== modifiedOutputsSource) {
|
||||
@@ -465,7 +465,9 @@ abstract class AbstractCellRenderer extends Disposable {
|
||||
|
||||
const mode = this.modeService.create('json');
|
||||
const originaloutputSource = this._getFormatedOutputJSON(
|
||||
this.cell.type === 'insert'
|
||||
this.notebookEditor.textModel!.transientOptions
|
||||
? []
|
||||
: this.cell.type === 'insert'
|
||||
? this.cell.modified!.outputs || []
|
||||
: this.cell.original!.outputs || []);
|
||||
const outputModel = this.modelService.createModel(originaloutputSource, mode, undefined, true);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { ICell, IProcessedOutput, NotebookCellOutputsSplice, CellKind, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICell, IProcessedOutput, NotebookCellOutputsSplice, CellKind, NotebookCellMetadata, NotebookDocumentMetadata, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { PieceTreeTextBufferBuilder } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as model from 'vs/editor/common/model';
|
||||
@@ -85,6 +85,7 @@ export class NotebookCellTextModel extends Disposable implements ICell {
|
||||
public cellKind: CellKind,
|
||||
outputs: IProcessedOutput[],
|
||||
metadata: NotebookCellMetadata | undefined,
|
||||
public readonly transientOptions: TransientOptions,
|
||||
private readonly _modelService: ITextModelService
|
||||
) {
|
||||
super();
|
||||
@@ -108,11 +109,25 @@ export class NotebookCellTextModel extends Disposable implements ICell {
|
||||
}
|
||||
|
||||
// TODO, raw outputs
|
||||
this._hash = hash([hash(this.getValue()), this._metadata, this._outputs]);
|
||||
// this._hash = hash(this.getValue());
|
||||
this._hash = hash([hash(this.getValue()), this._getPersisentMetadata, this.transientOptions.transientOutputs ? [] : this._outputs]);
|
||||
return this._hash;
|
||||
}
|
||||
|
||||
private _getPersisentMetadata() {
|
||||
let filteredMetadata: { [key: string]: any } = {};
|
||||
const transientMetadata = this.transientOptions.transientMetadata;
|
||||
|
||||
const keys = new Set([...Object.keys(this.metadata)]);
|
||||
for (let key of keys) {
|
||||
if (!(transientMetadata[key as keyof NotebookCellMetadata])
|
||||
) {
|
||||
filteredMetadata[key] = this.metadata[key as keyof NotebookCellMetadata];
|
||||
}
|
||||
}
|
||||
|
||||
return filteredMetadata;
|
||||
}
|
||||
|
||||
getTextLength(): number {
|
||||
return this.textBuffer.getLength();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
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';
|
||||
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';
|
||||
import { ITextSnapshot } from 'vs/editor/common/model';
|
||||
import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
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
|
||||
cells: NotebookCellTextModel[];
|
||||
languages: string[] = [];
|
||||
metadata: NotebookDocumentMetadata = notebookDocumentMetadataDefaults;
|
||||
transientMetadata: TransientMetadata = {};
|
||||
transientOptions: TransientOptions = { transientMetadata: {}, transientOutputs: false };
|
||||
private _isUntitled: boolean | undefined = undefined;
|
||||
private _versionId = 0;
|
||||
|
||||
@@ -187,7 +187,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
|
||||
) {
|
||||
const cellHandle = this._cellhandlePool++;
|
||||
const cellUri = CellUri.generate(this.uri, cellHandle);
|
||||
return new NotebookCellTextModel(cellUri, cellHandle, source, language, cellKind, outputs || [], metadata || {}, this._modelService);
|
||||
return new NotebookCellTextModel(cellUri, cellHandle, source, language, cellKind, outputs || [], metadata || {}, this.transientOptions, this._modelService);
|
||||
}
|
||||
|
||||
initialize(cells: ICellDto2[]) {
|
||||
@@ -197,7 +197,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
|
||||
const mainCells = cells.map(cell => {
|
||||
const cellHandle = this._cellhandlePool++;
|
||||
const cellUri = CellUri.generate(this.uri, cellHandle);
|
||||
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this._modelService);
|
||||
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this.transientOptions, this._modelService);
|
||||
});
|
||||
|
||||
this._isUntitled = false;
|
||||
@@ -245,7 +245,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
|
||||
const mainCells = edit.cells.map(cell => {
|
||||
const cellHandle = this._cellhandlePool++;
|
||||
const cellUri = CellUri.generate(this.uri, cellHandle);
|
||||
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this._modelService);
|
||||
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this.transientOptions, this._modelService);
|
||||
});
|
||||
this.insertNewCell(edit.index, mainCells, false);
|
||||
break;
|
||||
@@ -473,6 +473,12 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
|
||||
spliceNotebookCellOutputs(cellHandle: number, splices: NotebookCellOutputsSplice[]): void {
|
||||
const cell = this._mapping.get(cellHandle);
|
||||
cell?.spliceNotebookCellOutputs(splices);
|
||||
|
||||
if (!this.transientOptions.transientOutputs) {
|
||||
this._increaseVersionId();
|
||||
this.setDirty(true);
|
||||
this._onDidChangeContent.fire();
|
||||
}
|
||||
}
|
||||
|
||||
clearCellOutput(handle: number) {
|
||||
@@ -497,13 +503,13 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
|
||||
}
|
||||
}
|
||||
|
||||
private _compareCellMetadata(a: NotebookCellMetadata, b: NotebookCellMetadata) {
|
||||
private _isCellMetadataChanged(a: NotebookCellMetadata, b: NotebookCellMetadata) {
|
||||
const keys = new Set([...Object.keys(a || {}), ...Object.keys(b || {})]);
|
||||
for (let key of keys) {
|
||||
if (
|
||||
(a[key as keyof NotebookCellMetadata] !== b[key as keyof NotebookCellMetadata])
|
||||
&&
|
||||
!(this.transientMetadata[key as keyof NotebookCellMetadata])
|
||||
!(this.transientOptions.transientMetadata[key as keyof NotebookCellMetadata])
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@@ -519,7 +525,11 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
|
||||
return;
|
||||
}
|
||||
|
||||
const triggerDirtyChange = this._compareCellMetadata(cell.metadata, metadata);
|
||||
if (!this._isCellMetadataChanged(cell.metadata, metadata)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const triggerDirtyChange = this._isCellMetadataChanged(cell.metadata, metadata);
|
||||
|
||||
if (triggerDirtyChange) {
|
||||
if (pushUndoStop) {
|
||||
|
||||
@@ -105,6 +105,11 @@ export interface NotebookCellMetadata {
|
||||
|
||||
export type TransientMetadata = { [K in keyof NotebookCellMetadata]?: boolean };
|
||||
|
||||
export interface TransientOptions {
|
||||
transientOutputs: boolean;
|
||||
transientMetadata: TransientMetadata;
|
||||
}
|
||||
|
||||
export interface INotebookDisplayOrder {
|
||||
defaultOrder: string[];
|
||||
userOrder?: string[];
|
||||
|
||||
@@ -24,7 +24,7 @@ export const INotebookService = createDecorator<INotebookService>('notebookServi
|
||||
export interface IMainNotebookController {
|
||||
kernel: INotebookKernelInfoDto | undefined;
|
||||
supportBackup: boolean;
|
||||
options: { transientMetadata: TransientMetadata };
|
||||
options: { transientOutputs: boolean; transientMetadata: TransientMetadata; };
|
||||
createNotebook(textModel: NotebookTextModel, editorId?: string, backupId?: string): Promise<void>;
|
||||
reloadNotebook(mainthreadTextModel: NotebookTextModel): Promise<void>;
|
||||
resolveNotebookEditor(viewType: string, uri: URI, editorId: string): Promise<void>;
|
||||
|
||||
@@ -45,7 +45,7 @@ export class TestCell extends NotebookCellTextModel {
|
||||
outputs: IProcessedOutput[],
|
||||
modelService: ITextModelService
|
||||
) {
|
||||
super(CellUri.generate(URI.parse('test:///fake/notebook'), handle), handle, source, language, cellKind, outputs, undefined, modelService);
|
||||
super(CellUri.generate(URI.parse('test:///fake/notebook'), handle), handle, source, language, cellKind, outputs, undefined, { transientMetadata: {}, transientOutputs: false }, modelService);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user