Skip to content

Commit

Permalink
Show metadata diff when output value is the same.
Browse files Browse the repository at this point in the history
  • Loading branch information
rebornix committed Mar 4, 2022
1 parent aadc433 commit e4669da
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 9 deletions.
65 changes: 61 additions & 4 deletions src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { DiffElementViewModelBase, getFormattedMetadataJSON, getFormattedOutputJSON, OUTPUT_EDITOR_HEIGHT_MAGIC, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
import { DiffElementViewModelBase, getFormattedMetadataJSON, getFormattedOutputJSON, OutputComparison, outputEqual, OUTPUT_EDITOR_HEIGHT_MAGIC, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor, NOTEBOOK_DIFF_CELL_INPUT, NOTEBOOK_DIFF_CELL_PROPERTY, NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser';
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
Expand Down Expand Up @@ -286,12 +286,13 @@ abstract class AbstractElementRenderer extends Disposable {
protected _outputViewContainer?: HTMLElement;
protected _outputLeftContainer?: HTMLElement;
protected _outputRightContainer?: HTMLElement;
protected _outputMetadataContainer?: HTMLElement;
protected _outputEmptyElement?: HTMLElement;
protected _outputLeftView?: OutputContainer;
protected _outputRightView?: OutputContainer;
protected _outputEditorDisposeStore!: DisposableStore;
protected _outputEditor?: CodeEditorWidget | DiffEditorWidget;

protected _outputMetadataEditor?: DiffEditorWidget;

protected _diffEditorContainer!: HTMLElement;
protected _diagonalFill?: HTMLElement;
Expand Down Expand Up @@ -1398,8 +1399,16 @@ export class ModifiedElement extends AbstractElementRenderer {

this._outputLeftContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-left'));
this._outputRightContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-right'));
this._outputMetadataContainer = DOM.append(this._outputViewContainer!, DOM.$('.output-view-container-metadata'));

const outputModified = this.cell.checkIfOutputsModified();
const outputMetadataChangeOnly = outputModified
&& outputModified.kind === OutputComparison.Metadata
&& this.cell.original!.outputs.length === 1
&& this.cell.modified!.outputs.length === 1
&& outputEqual(this.cell.original!.outputs[0], this.cell.modified!.outputs[0]) === OutputComparison.Metadata;

if (this.cell.checkIfOutputsModified()) {
if (outputModified && !outputMetadataChangeOnly) {
const originalOutputRenderListener = this.notebookEditor.onDidDynamicOutputRendered(e => {
if (e.cell.uri.toString() === this.cell.original.uri.toString()) {
this.notebookEditor.deltaCellOutputContainerClassNames(DiffSide.Original, this.cell.original.id, ['nb-cellDeleted'], []);
Expand All @@ -1425,7 +1434,48 @@ export class ModifiedElement extends AbstractElementRenderer {
this._outputRightView = this.instantiationService.createInstance(OutputContainer, this.notebookEditor, this.notebookEditor.textModel!, this.cell, this.cell.modified!, DiffSide.Modified, this._outputRightContainer!);
this._outputRightView.render();
this._register(this._outputRightView);
this._decorate();

if (outputModified && !outputMetadataChangeOnly) {
this._decorate();
}

if (outputMetadataChangeOnly) {

this._outputMetadataContainer.style.top = `${this.cell.layoutInfo.rawOutputHeight}px`;
// single output, metadata change, let's render a diff editor for metadata
this._outputMetadataEditor = this.instantiationService.createInstance(DiffEditorWidget, this._outputMetadataContainer!, {
...fixedDiffEditorOptions,
overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode(),
readOnly: true,
ignoreTrimWhitespace: false,
automaticLayout: false,
dimension: {
height: OUTPUT_EDITOR_HEIGHT_MAGIC,
width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), false, true)
}
}, {
originalEditor: getOptimizedNestedCodeEditorWidgetOptions(),
modifiedEditor: getOptimizedNestedCodeEditorWidgetOptions()
});
this._register(this._outputMetadataEditor);
const originalOutputMetadataSource = JSON.stringify(this.cell.original!.outputs[0].metadata ?? {}, undefined, '\t');
const modifiedOutputMetadataSource = JSON.stringify(this.cell.modified!.outputs[0].metadata ?? {}, undefined, '\t');

const mode = this.languageService.createById('json');
const originalModel = this.modelService.createModel(originalOutputMetadataSource, mode, undefined, true);
const modifiedModel = this.modelService.createModel(modifiedOutputMetadataSource, mode, undefined, true);

this._outputMetadataEditor.setModel({
original: originalModel,
modified: modifiedModel
});

this.cell.outputMetadataHeight = this._outputMetadataEditor.getContentHeight();

this._register(this._outputMetadataEditor.onDidContentSizeChange((e) => {
this.cell.outputMetadataHeight = e.contentHeight;
}));
}
}

this._outputViewContainer.style.display = 'block';
Expand All @@ -1444,6 +1494,7 @@ export class ModifiedElement extends AbstractElementRenderer {

this._outputLeftView?.showOutputs();
this._outputRightView?.showOutputs();
this._outputMetadataEditor?.layout();
this._decorate();
}
}
Expand Down Expand Up @@ -1572,6 +1623,12 @@ export class ModifiedElement extends AbstractElementRenderer {
this._outputEditorContainer.style.height = `${this.cell.layoutInfo.outputTotalHeight}px`;
this._outputEditor?.layout();
}

if (this._outputMetadataContainer) {
this._outputMetadataContainer.style.height = `${this.cell.layoutInfo.outputMetadataHeight}px`;
this._outputMetadataContainer.style.top = `${this.cell.layoutInfo.outputTotalHeight - this.cell.layoutInfo.outputMetadataHeight}px`;
this._outputMetadataEditor?.layout();
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ export abstract class DiffElementViewModelBase extends Disposable {
throw new Error('Use Cell.layoutInfo.outputStatusHeight');
}

set outputMetadataHeight(height: number) {
this._layout({ outputMetadataHeight: height });
}

get outputMetadataHeight() {
throw new Error('Use Cell.layoutInfo.outputStatusHeight');
}

set editorHeight(height: number) {
this._layout({ editorHeight: height });
}
Expand Down Expand Up @@ -129,6 +137,7 @@ export abstract class DiffElementViewModelBase extends Disposable {
rawOutputHeight: 0,
outputTotalHeight: 0,
outputStatusHeight: 25,
outputMetadataHeight: 0,
bodyMargin: 32,
totalHeight: 82,
layoutState: CellLayoutState.Uninitialized
Expand All @@ -155,7 +164,8 @@ export abstract class DiffElementViewModelBase extends Disposable {
const rawOutputHeight = delta.rawOutputHeight !== undefined ? delta.rawOutputHeight : this._layoutInfo.rawOutputHeight;
const outputStatusHeight = delta.outputStatusHeight !== undefined ? delta.outputStatusHeight : this._layoutInfo.outputStatusHeight;
const bodyMargin = delta.bodyMargin !== undefined ? delta.bodyMargin : this._layoutInfo.bodyMargin;
const outputHeight = (delta.recomputeOutput || delta.rawOutputHeight !== undefined) ? this._getOutputTotalHeight(rawOutputHeight) : this._layoutInfo.outputTotalHeight;
const outputMetadataHeight = delta.outputMetadataHeight !== undefined ? delta.outputMetadataHeight : this._layoutInfo.outputMetadataHeight;
const outputHeight = (delta.recomputeOutput || delta.rawOutputHeight !== undefined || delta.outputMetadataHeight !== undefined) ? this._getOutputTotalHeight(rawOutputHeight, outputMetadataHeight) : this._layoutInfo.outputTotalHeight;

const totalHeight = editorHeight
+ editorMargin
Expand All @@ -175,6 +185,7 @@ export abstract class DiffElementViewModelBase extends Disposable {
outputStatusHeight: outputStatusHeight,
bodyMargin: bodyMargin,
rawOutputHeight: rawOutputHeight,
outputMetadataHeight: outputMetadataHeight,
totalHeight: totalHeight,
layoutState: CellLayoutState.Measured
};
Expand Down Expand Up @@ -213,6 +224,10 @@ export abstract class DiffElementViewModelBase extends Disposable {
changeEvent.bodyMargin = true;
}

if (newLayout.outputMetadataHeight !== this._layoutInfo.outputMetadataHeight) {
changeEvent.outputMetadataHeight = true;
}

if (newLayout.totalHeight !== this._layoutInfo.totalHeight) {
changeEvent.totalHeight = true;
}
Expand All @@ -237,6 +252,7 @@ export abstract class DiffElementViewModelBase extends Disposable {
+ this._layoutInfo.metadataStatusHeight
+ this._layoutInfo.outputTotalHeight
+ this._layoutInfo.outputStatusHeight
+ this._layoutInfo.outputMetadataHeight
+ this._layoutInfo.bodyMargin;

return totalHeight;
Expand All @@ -253,7 +269,7 @@ export abstract class DiffElementViewModelBase extends Disposable {
+ verticalScrollbarHeight;
}

private _getOutputTotalHeight(rawOutputHeight: number) {
private _getOutputTotalHeight(rawOutputHeight: number, metadataHeight: number) {
if (this.outputFoldingState === PropertyFoldingState.Collapsed) {
return 0;
}
Expand All @@ -263,7 +279,7 @@ export abstract class DiffElementViewModelBase extends Disposable {
// single line;
return 24;
}
return this.getRichOutputTotalHeight();
return this.getRichOutputTotalHeight() + metadataHeight;
} else {
return rawOutputHeight;
}
Expand Down Expand Up @@ -386,7 +402,8 @@ export class SideBySideDiffElementViewModel extends DiffElementViewModelBase {
}

return {
reason: ret === OutputComparison.Metadata ? 'Output metadata is changed' : undefined
reason: ret === OutputComparison.Metadata ? 'Output metadata is changed' : undefined,
kind: ret
};
}

Expand Down Expand Up @@ -553,12 +570,40 @@ export class SingleSideDiffElementViewModel extends DiffElementViewModelBase {
}
}

const enum OutputComparison {
export const enum OutputComparison {
Unchanged = 0,
Metadata = 1,
Other = 2
}

export function outputEqual(a: ICellOutput, b: ICellOutput): OutputComparison {
if (hash(a.metadata) === hash(b.metadata)) {
return OutputComparison.Other;
}

// metadata not equal
for (let j = 0; j < a.outputs.length; j++) {
const aOutputItem = a.outputs[j];
const bOutputItem = b.outputs[j];

if (aOutputItem.mime !== bOutputItem.mime) {
return OutputComparison.Other;
}

if (aOutputItem.data.buffer.length !== bOutputItem.data.buffer.length) {
return OutputComparison.Other;
}

for (let k = 0; k < aOutputItem.data.buffer.length; k++) {
if (aOutputItem.data.buffer[k] !== bOutputItem.data.buffer[k]) {
return OutputComparison.Other;
}
}
}

return OutputComparison.Metadata;
}

function outputsEqual(original: ICellOutput[], modified: ICellOutput[]) {
if (original.length !== modified.length) {
return OutputComparison.Other;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,10 @@
color: inherit;
}

.monaco-workbench .notebook-text-diff-editor .output-view-container .output-view-container-metadata {
position: relative;
}

/* Diff decorations */

.notebook-text-diff-editor .cell-body .codicon-diff-remove,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export interface IDiffElementLayoutInfo {
metadataHeight: number;
metadataStatusHeight: number;
rawOutputHeight: number;
outputMetadataHeight: number;
outputTotalHeight: number;
outputStatusHeight: number;
bodyMargin: number;
Expand Down

0 comments on commit e4669da

Please sign in to comment.