Skip to content

Commit c0ab600

Browse files
authored
Move notebook diffing helpers into separate file (microsoft#242384)
1 parent 14db919 commit c0ab600

File tree

6 files changed

+142
-96
lines changed

6 files changed

+142
-96
lines changed

src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingModifiedNotebookEntry.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,13 @@ import { IFilesConfigurationService } from '../../../../services/filesConfigurat
4343
import { SnapshotContext } from '../../../../services/workingCopy/common/fileWorkingCopy.js';
4444
import { NotebookTextDiffEditor } from '../../../notebook/browser/diff/notebookDiffEditor.js';
4545
import { INotebookTextDiffEditor } from '../../../notebook/browser/diff/notebookDiffEditorBrowser.js';
46-
import { CellDiffInfo, computeDiff } from '../../../notebook/browser/diff/notebookDiffViewModel.js';
46+
import { CellDiffInfo } from '../../../notebook/browser/diff/notebookDiffViewModel.js';
4747
import { CellEditState, getNotebookEditorFromEditorPane } from '../../../notebook/browser/notebookBrowser.js';
4848
import { INotebookEditorService } from '../../../notebook/browser/services/notebookEditorService.js';
4949
import { NotebookCellTextModel } from '../../../notebook/common/model/notebookCellTextModel.js';
5050
import { NotebookTextModel } from '../../../notebook/common/model/notebookTextModel.js';
5151
import { CellEditType, ICellDto2, ICellEditOperation, ICellReplaceEdit, IResolvedNotebookEditorModel, NotebookSetting, NotebookTextModelChangedEvent, TransientOptions } from '../../../notebook/common/notebookCommon.js';
52+
import { computeDiff } from '../../../notebook/common/notebookDiff.js';
5253
import { INotebookEditorModelResolverService } from '../../../notebook/common/notebookEditorModelResolverService.js';
5354
import { INotebookLoggingService } from '../../../notebook/common/notebookLoggingService.js';
5455
import { INotebookService } from '../../../notebook/common/notebookService.js';

src/vs/workbench/contrib/notebook/browser/contrib/chatEdit/notebookSynchronizer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { INotebookService } from '../../../common/notebookService.js';
1010
import { bufferToStream, streamToBuffer, VSBuffer } from '../../../../../../base/common/buffer.js';
1111
import { NotebookTextModel } from '../../../common/model/notebookTextModel.js';
1212
import { raceCancellation, ThrottledDelayer } from '../../../../../../base/common/async.js';
13-
import { CellDiffInfo, computeDiff, prettyChanges } from '../../diff/notebookDiffViewModel.js';
13+
import { CellDiffInfo, prettyChanges } from '../../diff/notebookDiffViewModel.js';
1414
import { CancellationToken, CancellationTokenSource } from '../../../../../../base/common/cancellation.js';
1515
import { INotebookEditorWorkerService } from '../../../common/services/notebookWorkerService.js';
1616
import { CellEditType, ICellDto2, ICellEditOperation, ICellReplaceEdit, NotebookData, NotebookSetting } from '../../../common/notebookCommon.js';
@@ -31,6 +31,7 @@ import { INotebookEditorService } from '../../services/notebookEditorService.js'
3131
import { CellEditState } from '../../notebookBrowser.js';
3232
import { IModelService } from '../../../../../../editor/common/services/model.js';
3333
import { ChatEditingModifiedDocumentEntry } from '../../../../chat/browser/chatEditing/chatEditingModifiedDocumentEntry.js';
34+
import { computeDiff } from '../../../common/notebookDiff.js';
3435

3536

3637
export const INotebookModelSynchronizerFactory = createDecorator<INotebookModelSynchronizerFactory>('INotebookModelSynchronizerFactory');

src/vs/workbench/contrib/notebook/browser/diff/inlineDiff/notebookInlineDiff.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import { IInstantiationService } from '../../../../../../platform/instantiation/
1010
import { NotebookCellTextModel } from '../../../common/model/notebookCellTextModel.js';
1111
import { NotebookTextModel } from '../../../common/model/notebookTextModel.js';
1212
import { INotebookEditorWorkerService } from '../../../common/services/notebookWorkerService.js';
13-
import { CellDiffInfo, computeDiff } from '../notebookDiffViewModel.js';
13+
import { CellDiffInfo } from '../notebookDiffViewModel.js';
1414
import { INotebookEditorContribution, INotebookEditor } from '../../notebookBrowser.js';
1515
import { registerNotebookContribution } from '../../notebookEditorExtensions.js';
1616
import { NotebookCellDiffDecorator } from './notebookCellDiffDecorator.js';
1717
import { NotebookDeletedCellDecorator } from './notebookDeletedCellDecorator.js';
1818
import { NotebookInsertedCellDecorator } from './notebookInsertedCellDecorator.js';
1919
import { INotebookLoggingService } from '../../../common/notebookLoggingService.js';
20+
import { computeDiff } from '../../../common/notebookDiff.js';
2021

2122
export class NotebookInlineDiffDecorationContribution extends Disposable implements INotebookEditorContribution {
2223
static ID: string = 'workbench.notebook.inlineDiffDecoration';

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

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

66
import { CancellationToken } from '../../../../../base/common/cancellation.js';
7-
import { IDiffResult, IDiffChange } from '../../../../../base/common/diff/diff.js';
7+
import { IDiffResult } from '../../../../../base/common/diff/diff.js';
88
import { Emitter, type IValueWithChangeEvent } from '../../../../../base/common/event.js';
99
import { Disposable, DisposableStore, dispose } from '../../../../../base/common/lifecycle.js';
1010
import { Schemas } from '../../../../../base/common/network.js';
@@ -17,11 +17,12 @@ import { DiffElementCellViewModelBase, DiffElementPlaceholderViewModel, IDiffEle
1717
import { NotebookDiffEditorEventDispatcher } from './eventDispatcher.js';
1818
import { INotebookDiffViewModel, INotebookDiffViewModelUpdateEvent, NOTEBOOK_DIFF_ITEM_DIFF_STATE, NOTEBOOK_DIFF_ITEM_KIND } from './notebookDiffEditorBrowser.js';
1919
import { NotebookTextModel } from '../../common/model/notebookTextModel.js';
20-
import { CellUri, INotebookDiffEditorModel, INotebookDiffResult } from '../../common/notebookCommon.js';
20+
import { CellUri, INotebookDiffEditorModel } from '../../common/notebookCommon.js';
2121
import { INotebookService } from '../../common/notebookService.js';
2222
import { INotebookEditorWorkerService } from '../../common/services/notebookWorkerService.js';
2323
import { IDiffEditorHeightCalculatorService } from './editorHeightCalculator.js';
2424
import { raceCancellation } from '../../../../../base/common/async.js';
25+
import { computeDiff } from '../../common/notebookDiff.js';
2526

2627
export class NotebookDiffViewModel extends Disposable implements INotebookDiffViewModel, IValueWithChangeEvent<readonly MultiDiffEditorItem[]> {
2728
private readonly placeholderAndRelatedCells = new Map<DiffElementPlaceholderViewModel, DiffElementCellViewModelBase[]>();
@@ -415,62 +416,7 @@ export type CellDiffInfo = {
415416
modifiedCellIndex: number;
416417
type: 'insert';
417418
};
418-
export function computeDiff(originalModel: NotebookTextModel, modifiedModel: NotebookTextModel, diffResult: INotebookDiffResult) {
419-
const cellChanges = diffResult.cellsDiff.changes;
420-
const cellDiffInfo: CellDiffInfo[] = [];
421-
let originalCellIndex = 0;
422-
let modifiedCellIndex = 0;
423-
424-
let firstChangeIndex = -1;
425-
426-
for (let i = 0; i < cellChanges.length; i++) {
427-
const change = cellChanges[i];
428-
// common cells
429-
430-
for (let j = 0; j < change.originalStart - originalCellIndex; j++) {
431-
const originalCell = originalModel.cells[originalCellIndex + j];
432-
const modifiedCell = modifiedModel.cells[modifiedCellIndex + j];
433-
if (originalCell.getHashValue() === modifiedCell.getHashValue()) {
434-
cellDiffInfo.push({
435-
originalCellIndex: originalCellIndex + j,
436-
modifiedCellIndex: modifiedCellIndex + j,
437-
type: 'unchanged'
438-
});
439-
} else {
440-
if (firstChangeIndex === -1) {
441-
firstChangeIndex = cellDiffInfo.length;
442-
}
443-
cellDiffInfo.push({
444-
originalCellIndex: originalCellIndex + j,
445-
modifiedCellIndex: modifiedCellIndex + j,
446-
type: 'modified'
447-
});
448-
}
449-
}
450419

451-
const modifiedLCS = computeModifiedLCS(change, originalModel, modifiedModel);
452-
if (modifiedLCS.length && firstChangeIndex === -1) {
453-
firstChangeIndex = cellDiffInfo.length;
454-
}
455-
456-
cellDiffInfo.push(...modifiedLCS);
457-
originalCellIndex = change.originalStart + change.originalLength;
458-
modifiedCellIndex = change.modifiedStart + change.modifiedLength;
459-
}
460-
461-
for (let i = originalCellIndex; i < originalModel.cells.length; i++) {
462-
cellDiffInfo.push({
463-
originalCellIndex: i,
464-
modifiedCellIndex: i - originalCellIndex + modifiedCellIndex,
465-
type: 'unchanged'
466-
});
467-
}
468-
469-
return {
470-
cellDiffInfo,
471-
firstChangeIndex
472-
};
473-
}
474420
function isEqual(cellDiffInfo: CellDiffInfo[], viewModels: IDiffElementViewModelBase[], model: INotebookDiffEditorModel) {
475421
if (cellDiffInfo.length !== viewModels.length) {
476422
return false;
@@ -510,40 +456,6 @@ function isEqual(cellDiffInfo: CellDiffInfo[], viewModels: IDiffElementViewModel
510456

511457
return true;
512458
}
513-
514-
function computeModifiedLCS(change: IDiffChange, originalModel: NotebookTextModel, modifiedModel: NotebookTextModel) {
515-
const result: CellDiffInfo[] = [];
516-
// modified cells
517-
const modifiedLen = Math.min(change.originalLength, change.modifiedLength);
518-
519-
for (let j = 0; j < modifiedLen; j++) {
520-
const isTheSame = originalModel.cells[change.originalStart + j].equal(modifiedModel.cells[change.modifiedStart + j]);
521-
result.push({
522-
originalCellIndex: change.originalStart + j,
523-
modifiedCellIndex: change.modifiedStart + j,
524-
type: isTheSame ? 'unchanged' : 'modified'
525-
});
526-
}
527-
528-
for (let j = modifiedLen; j < change.originalLength; j++) {
529-
// deletion
530-
result.push({
531-
originalCellIndex: change.originalStart + j,
532-
type: 'delete'
533-
});
534-
}
535-
536-
for (let j = modifiedLen; j < change.modifiedLength; j++) {
537-
result.push({
538-
modifiedCellIndex: change.modifiedStart + j,
539-
type: 'insert'
540-
});
541-
}
542-
543-
return result;
544-
}
545-
546-
547459
export abstract class NotebookMultiDiffEditorItem extends MultiDiffEditorItem {
548460
constructor(
549461
originalUri: URI | undefined,

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import { ISplice } from '../../../../base/common/sequence.js';
1919
import { ThemeColor } from '../../../../base/common/themables.js';
2020
import { URI, UriComponents } from '../../../../base/common/uri.js';
2121
import { Range } from '../../../../editor/common/core/range.js';
22-
import { ILineChange } from '../../../../editor/common/diff/legacyLinesDiffComputer.js';
2322
import * as editorCommon from '../../../../editor/common/editorCommon.js';
2423
import { Command, WorkspaceEditMetadata } from '../../../../editor/common/languages.js';
2524
import { IReadonlyTextBuffer, ITextModel } from '../../../../editor/common/model.js';
@@ -960,7 +959,6 @@ export interface INotebookCellStatusBarItemProvider {
960959
export interface INotebookDiffResult {
961960
cellsDiff: IDiffResult;
962961
metadataChanged: boolean;
963-
linesDiff?: { originalCellhandle: number; modifiedCellhandle: number; lineChanges: ILineChange[] }[];
964962
}
965963

966964
export interface INotebookCellStatusBarItem {
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { IDiffChange } from '../../../../base/common/diff/diff.js';
7+
import { CellKind, INotebookDiffResult } from './notebookCommon.js';
8+
9+
export type CellDiffInfo = {
10+
originalCellIndex: number;
11+
modifiedCellIndex: number;
12+
type: 'unchanged' | 'modified';
13+
} |
14+
{
15+
originalCellIndex: number;
16+
type: 'delete';
17+
} |
18+
{
19+
modifiedCellIndex: number;
20+
type: 'insert';
21+
};
22+
23+
interface ICell {
24+
cellKind: CellKind;
25+
getHashValue(): number;
26+
equal(cell: ICell): boolean;
27+
}
28+
// interface INotebookDiffResult {
29+
// cellsDiff: IDiffResult;
30+
// metadataChanged: boolean;
31+
// }
32+
33+
export function computeDiff(originalModel: { readonly cells: readonly ICell[] }, modifiedModel: { readonly cells: readonly ICell[] }, diffResult: INotebookDiffResult) {
34+
const cellChanges = diffResult.cellsDiff.changes;
35+
const cellDiffInfo: CellDiffInfo[] = [];
36+
let originalCellIndex = 0;
37+
let modifiedCellIndex = 0;
38+
39+
let firstChangeIndex = -1;
40+
41+
for (let i = 0; i < cellChanges.length; i++) {
42+
const change = cellChanges[i];
43+
// common cells
44+
45+
for (let j = 0; j < change.originalStart - originalCellIndex; j++) {
46+
const originalCell = originalModel.cells[originalCellIndex + j];
47+
const modifiedCell = modifiedModel.cells[modifiedCellIndex + j];
48+
if (originalCell.getHashValue() === modifiedCell.getHashValue()) {
49+
cellDiffInfo.push({
50+
originalCellIndex: originalCellIndex + j,
51+
modifiedCellIndex: modifiedCellIndex + j,
52+
type: 'unchanged'
53+
});
54+
} else {
55+
if (firstChangeIndex === -1) {
56+
firstChangeIndex = cellDiffInfo.length;
57+
}
58+
cellDiffInfo.push({
59+
originalCellIndex: originalCellIndex + j,
60+
modifiedCellIndex: modifiedCellIndex + j,
61+
type: 'modified'
62+
});
63+
}
64+
}
65+
66+
const modifiedLCS = computeModifiedLCS(change, originalModel, modifiedModel);
67+
if (modifiedLCS.length && firstChangeIndex === -1) {
68+
firstChangeIndex = cellDiffInfo.length;
69+
}
70+
71+
cellDiffInfo.push(...modifiedLCS);
72+
originalCellIndex = change.originalStart + change.originalLength;
73+
modifiedCellIndex = change.modifiedStart + change.modifiedLength;
74+
}
75+
76+
for (let i = originalCellIndex; i < originalModel.cells.length; i++) {
77+
cellDiffInfo.push({
78+
originalCellIndex: i,
79+
modifiedCellIndex: i - originalCellIndex + modifiedCellIndex,
80+
type: 'unchanged'
81+
});
82+
}
83+
84+
return {
85+
cellDiffInfo,
86+
firstChangeIndex
87+
};
88+
}
89+
90+
function computeModifiedLCS(change: IDiffChange, originalModel: { readonly cells: readonly ICell[] }, modifiedModel: { readonly cells: readonly ICell[] }) {
91+
const result: CellDiffInfo[] = [];
92+
// modified cells
93+
const modifiedLen = Math.min(change.originalLength, change.modifiedLength);
94+
95+
for (let j = 0; j < modifiedLen; j++) {
96+
const originalCell = originalModel.cells[change.originalStart + j];
97+
const modifiedCell = modifiedModel.cells[change.modifiedStart + j];
98+
if (originalCell.cellKind !== modifiedCell.cellKind) {
99+
result.push({
100+
originalCellIndex: change.originalStart + j,
101+
type: 'delete'
102+
});
103+
result.push({
104+
modifiedCellIndex: change.modifiedStart + j,
105+
type: 'insert'
106+
});
107+
} else {
108+
const isTheSame = originalCell.equal(modifiedCell);
109+
result.push({
110+
originalCellIndex: change.originalStart + j,
111+
modifiedCellIndex: change.modifiedStart + j,
112+
type: isTheSame ? 'unchanged' : 'modified'
113+
});
114+
}
115+
}
116+
117+
for (let j = modifiedLen; j < change.originalLength; j++) {
118+
// deletion
119+
result.push({
120+
originalCellIndex: change.originalStart + j,
121+
type: 'delete'
122+
});
123+
}
124+
125+
for (let j = modifiedLen; j < change.modifiedLength; j++) {
126+
result.push({
127+
modifiedCellIndex: change.modifiedStart + j,
128+
type: 'insert'
129+
});
130+
}
131+
132+
return result;
133+
}

0 commit comments

Comments
 (0)