Skip to content

Commit

Permalink
transient metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
rebornix committed Aug 26, 2020
1 parent 1fe5613 commit 7c986e9
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 33 deletions.
9 changes: 6 additions & 3 deletions src/vs/workbench/api/browser/mainThreadNotebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx
import { Disposable, IDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
import { NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, INotebookKernelInfo, INotebookKernelInfoDto, IEditor, INotebookDocumentFilter, DisplayOrderKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType, CellKind, INotebookKernelInfo, INotebookKernelInfoDto, IEditor, INotebookDocumentFilter, DisplayOrderKey, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
Expand Down Expand Up @@ -375,10 +375,11 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
// }
}

async $registerNotebookProvider(_extension: NotebookExtensionDescription, _viewType: string, _supportBackup: boolean, _kernel: INotebookKernelInfoDto | undefined): Promise<void> {
async $registerNotebookProvider(_extension: NotebookExtensionDescription, _viewType: string, _supportBackup: boolean, _kernel: INotebookKernelInfoDto | undefined, options: { transientMetadata: TransientMetadata }): Promise<void> {
const controller: IMainNotebookController = {
kernel: _kernel,
supportBackup: _supportBackup,
options: options,
reloadNotebook: async (mainthreadTextModel: NotebookTextModel) => {
const data = await this._proxy.$resolveNotebookData(_viewType, mainthreadTextModel.uri);
if (!data) {
Expand All @@ -387,6 +388,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo

mainthreadTextModel.languages = data.languages;
mainthreadTextModel.metadata = data.metadata;
mainthreadTextModel.transientMetadata = options.transientMetadata;

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

textModel.languages = data.languages;
textModel.metadata = data.metadata;
textModel.transientMetadata = options.transientMetadata;

if (data.cells.length) {
textModel.initialize(data!.cells);
Expand Down Expand Up @@ -551,7 +554,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
async $updateNotebookCellMetadata(viewType: string, resource: UriComponents, handle: number, metadata: NotebookCellMetadata): Promise<void> {
this.logService.debug('MainThreadNotebooks#updateNotebookCellMetadata', resource.path, handle, metadata);
const textModel = this._notebookService.getNotebookTextModel(URI.from(resource));
textModel?.updateNotebookCellMetadata(handle, metadata);
textModel?.changeCellMetadata(handle, metadata, true);
}

async $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[]): Promise<void> {
Expand Down
6 changes: 4 additions & 2 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -950,9 +950,11 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.onDidChangeActiveNotebookKernel;
},
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider) => {
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider, options?: {
transientMetadata?: { [K in keyof vscode.NotebookCellMetadata]?: boolean }
}) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider);
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider, options);
},
registerNotebookKernel: (id: string, selector: vscode.GlobPattern[], kernel: vscode.NotebookKernel) => {
checkProposedApiEnabled(extension);
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
import { revive } from 'vs/base/common/marshalling';
import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IProcessedOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto, INotebookKernelInfoDto, IMainCellDto, INotebookDocumentFilter, INotebookKernelInfoDto2, TransientMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { Dto } from 'vs/base/common/types';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
Expand Down Expand Up @@ -715,7 +715,7 @@ export type NotebookCellOutputsSplice = [
];

export interface MainThreadNotebookShape extends IDisposable {
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, kernelInfoDto: INotebookKernelInfoDto | undefined): Promise<void>;
$registerNotebookProvider(extension: NotebookExtensionDescription, viewType: string, supportBackup: boolean, kernelInfoDto: INotebookKernelInfoDto | undefined, options: { 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>;
Expand Down
5 changes: 4 additions & 1 deletion src/vs/workbench/api/common/extHostNotebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,9 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
extension: IExtensionDescription,
viewType: string,
provider: vscode.NotebookContentProvider & { kernel?: vscode.NotebookKernel },
options?: {
transientMetadata?: { [K in keyof NotebookCellMetadata]?: boolean }
}
): vscode.Disposable {

if (this._notebookContentProviders.has(viewType)) {
Expand Down Expand Up @@ -985,7 +988,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);
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 || {} });

return new extHostTypes.Disposable(() => {
listener.dispose();
Expand Down
10 changes: 5 additions & 5 deletions src/vs/workbench/contrib/notebook/browser/contrib/coreActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1292,7 +1292,7 @@ registerAction2(class extends NotebookCellAction {

editor.viewModel.notebookDocument.clearCellOutput(context.cell.handle);
if (context.cell.metadata && context.cell.metadata?.runState !== NotebookCellRunState.Running) {
context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, {
context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, {
runState: NotebookCellRunState.Idle,
runStartTime: undefined,
lastRunDuration: undefined,
Expand Down Expand Up @@ -1562,7 +1562,7 @@ registerAction2(class extends NotebookCellAction {
}

async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { inputCollapsed: true });
context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { inputCollapsed: true });
}
});

Expand All @@ -1585,7 +1585,7 @@ registerAction2(class extends NotebookCellAction {
}

async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { inputCollapsed: false });
context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { inputCollapsed: false });
}
});

Expand All @@ -1608,7 +1608,7 @@ registerAction2(class extends NotebookCellAction {
}

async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { outputCollapsed: true });
context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { outputCollapsed: true });
}
});

Expand All @@ -1631,7 +1631,7 @@ registerAction2(class extends NotebookCellAction {
}

async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
context.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(context.cell.handle, { outputCollapsed: false });
context.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(context.cell.handle, { outputCollapsed: false });
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,9 @@ abstract class AbstractCellRenderer {
}

if (templateData.currentRenderedCell.metadata?.inputCollapsed) {
this.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(templateData.currentRenderedCell.handle, { inputCollapsed: false });
this.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(templateData.currentRenderedCell.handle, { inputCollapsed: false });
} else if (templateData.currentRenderedCell.metadata?.outputCollapsed) {
this.notebookEditor.viewModel!.notebookDocument.changeCellMetadata(templateData.currentRenderedCell.handle, { outputCollapsed: false });
this.notebookEditor.viewModel!.notebookDocument.deltaCellMetadata(templateData.currentRenderedCell.handle, { outputCollapsed: false });
}
}));
}
Expand Down
32 changes: 32 additions & 0 deletions src/vs/workbench/contrib/notebook/common/model/cellEdit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { IResourceUndoRedoElement, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo';
import { URI } from 'vs/base/common/uri';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';

/**
* It should not modify Undo/Redo stack
Expand All @@ -14,6 +15,7 @@ export interface ITextCellEditingDelegate {
insertCell?(index: number, cell: NotebookCellTextModel): void;
deleteCell?(index: number): void;
moveCell?(fromIndex: number, length: number, toIndex: number, beforeSelections: number[] | undefined, endSelections: number[] | undefined): void;
updateCellMetadata?(index: number, newMetadata: NotebookCellMetadata | undefined): void;
emitSelections(selections: number[]): void;
}

Expand Down Expand Up @@ -183,3 +185,33 @@ export class SpliceCellsEdit implements IResourceUndoRedoElement {
}
}
}

export class CellMetadataEdit implements IResourceUndoRedoElement {
type: UndoRedoElementType.Resource = UndoRedoElementType.Resource;
label: string = 'Update Cell Metadata';
constructor(
public resource: URI,
readonly index: number,
readonly oldMetadata: NotebookCellMetadata | undefined,
readonly newMetadata: NotebookCellMetadata | undefined,
private editingDelegate: ITextCellEditingDelegate,
) {

}

undo(): void {
if (!this.editingDelegate.updateCellMetadata) {
return;
}

this.editingDelegate.updateCellMetadata(this.index, this.oldMetadata);
}

redo(): void | Promise<void> {
if (!this.editingDelegate.updateCellMetadata) {
return;
}

this.editingDelegate.updateCellMetadata(this.index, this.newMetadata);
}
}
110 changes: 93 additions & 17 deletions src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ 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 } from 'vs/workbench/contrib/notebook/common/notebookCommon';
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 { ITextSnapshot } from 'vs/editor/common/model';
import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
import { InsertCellEdit, DeleteCellEdit, MoveCellEdit, SpliceCellsEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit';
import { InsertCellEdit, DeleteCellEdit, MoveCellEdit, SpliceCellsEdit, CellMetadataEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit';
import { ITextModelService } from 'vs/editor/common/services/resolverService';

export class NotebookTextModelSnapshot implements ITextSnapshot {
Expand Down Expand Up @@ -128,6 +128,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
cells: NotebookCellTextModel[];
languages: string[] = [];
metadata: NotebookDocumentMetadata = notebookDocumentMetadataDefaults;
transientMetadata: TransientMetadata = {};
private _isUntitled: boolean | undefined = undefined;
private _versionId = 0;

Expand Down Expand Up @@ -259,7 +260,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
break;
case CellEditType.Metadata:
this.assertIndex(edit.index);
this.changeCellMetadata(this.cells[edit.index].handle, edit.metadata);
this.deltaCellMetadata(this.cells[edit.index].handle, edit.metadata);
break;
}
}
Expand Down Expand Up @@ -342,14 +343,6 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
this._onDidChangeMetadata.fire(this.metadata);
}

updateNotebookCellMetadata(handle: number, metadata: NotebookCellMetadata) {
const cell = this.cells.find(cell => cell.handle === handle);

if (cell) {
cell.metadata = metadata;
}
}

insertTemplateCell(cell: NotebookCellTextModel) {
if (this.cells.length > 0 || this._isUntitled !== undefined) {
return;
Expand Down Expand Up @@ -504,16 +497,99 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
}
}

changeCellMetadata(handle: number, newMetadata: NotebookCellMetadata) {
private _compareCellMetadata(a: NotebookCellMetadata | undefined, b: NotebookCellMetadata | undefined) {
if (a?.editable !== b?.editable && !this.transientMetadata.editable) {
return true;
}

if (a?.runnable !== b?.runnable && !this.transientMetadata.runnable) {
return true;
}

if (a?.breakpointMargin !== b?.breakpointMargin && !this.transientMetadata.breakpointMargin) {
return true;
}

if (a?.hasExecutionOrder !== b?.hasExecutionOrder && !this.transientMetadata.hasExecutionOrder) {
return true;
}

if (a?.executionOrder !== b?.executionOrder && !this.transientMetadata.executionOrder) {
return true;
}

if (a?.statusMessage !== b?.statusMessage && !this.transientMetadata.statusMessage) {
return true;
}

if (a?.runState !== b?.runState && !this.transientMetadata.runState) {
return true;
}

if (a?.runStartTime !== b?.runStartTime && !this.transientMetadata.runStartTime) {
return true;
}

if (a?.lastRunDuration !== b?.lastRunDuration && !this.transientMetadata.lastRunDuration) {
return true;
}

if (a?.inputCollapsed !== b?.inputCollapsed && !this.transientMetadata.inputCollapsed) {
return true;
}

if (a?.outputCollapsed !== b?.outputCollapsed && !this.transientMetadata.outputCollapsed) {
return true;
}

if (a?.custom !== b?.custom && !this.transientMetadata.custom) {
return true;
}

return false;
}

changeCellMetadata(handle: number, metadata: NotebookCellMetadata | undefined, pushUndoStop: boolean) {
const cell = this.cells.find(cell => cell.handle === handle);

if (!cell) {
return;
}

const triggerDirtyChange = this._compareCellMetadata(cell.metadata, metadata);

if (triggerDirtyChange) {
if (pushUndoStop) {
const index = this.cells.indexOf(cell);
this._operationManager.pushEditOperation(new CellMetadataEdit(this.uri, index, Object.freeze(cell.metadata), Object.freeze(metadata), {
updateCellMetadata: (index, newMetadata) => {
const cell = this.cells[index];
if (!cell) {
return;
}
this.changeCellMetadata(cell.handle, newMetadata, false);
},
emitSelections: this._emitSelectionsDelegate.bind(this)
}));
}
cell.metadata = metadata;
this.setDirty(true);
this._onDidChangeContent.fire();
} else {
cell.metadata = metadata;
}

this._increaseVersionId();
this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata });
}

deltaCellMetadata(handle: number, newMetadata: NotebookCellMetadata) {
const cell = this._mapping.get(handle);
if (cell) {
cell.metadata = {
this.changeCellMetadata(handle, {
...cell.metadata,
...newMetadata
};

this._increaseVersionId();
this._onDidModelChangeProxy.fire({ kind: NotebookCellsChangeType.ChangeMetadata, versionId: this._versionId, index: this.cells.indexOf(cell), metadata: cell.metadata });
}, true);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/contrib/notebook/common/notebookCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ export interface NotebookCellMetadata {
custom?: { [key: string]: unknown };
}

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

export interface INotebookDisplayOrder {
defaultOrder: string[];
userOrder?: string[];
Expand Down
Loading

0 comments on commit 7c986e9

Please sign in to comment.