提交 32f29cfd 编写于 作者: R rebornix

transient outputs.

上级 e88c040d
......@@ -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,9 +465,11 @@ abstract class AbstractCellRenderer extends Disposable {
const mode = this.modeService.create('json');
const originaloutputSource = this._getFormatedOutputJSON(
this.cell.type === 'insert'
? this.cell.modified!.outputs || []
: this.cell.original!.outputs || []);
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);
this._outputEditor.setModel(outputModel);
......
......@@ -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);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册