Path: blob/main/src/vs/workbench/contrib/notebook/common/notebookDiff.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { IDiffChange } from '../../../../base/common/diff/diff.js';6import { CellKind, INotebookDiffResult } from './notebookCommon.js';78export type CellDiffInfo = {9originalCellIndex: number;10modifiedCellIndex: number;11type: 'unchanged' | 'modified';12} |13{14originalCellIndex: number;15type: 'delete';16} |17{18modifiedCellIndex: number;19type: 'insert';20};2122interface ICell {23cellKind: CellKind;24getHashValue(): number;25equal(cell: ICell): boolean;26}27// interface INotebookDiffResult {28// cellsDiff: IDiffResult;29// metadataChanged: boolean;30// }3132export function computeDiff(originalModel: { readonly cells: readonly ICell[] }, modifiedModel: { readonly cells: readonly ICell[] }, diffResult: INotebookDiffResult) {33const cellChanges = diffResult.cellsDiff.changes;34const cellDiffInfo: CellDiffInfo[] = [];35let originalCellIndex = 0;36let modifiedCellIndex = 0;3738let firstChangeIndex = -1;3940for (let i = 0; i < cellChanges.length; i++) {41const change = cellChanges[i];42// common cells4344for (let j = 0; j < change.originalStart - originalCellIndex; j++) {45const originalCell = originalModel.cells[originalCellIndex + j];46const modifiedCell = modifiedModel.cells[modifiedCellIndex + j];47if (originalCell.getHashValue() === modifiedCell.getHashValue()) {48cellDiffInfo.push({49originalCellIndex: originalCellIndex + j,50modifiedCellIndex: modifiedCellIndex + j,51type: 'unchanged'52});53} else {54if (firstChangeIndex === -1) {55firstChangeIndex = cellDiffInfo.length;56}57cellDiffInfo.push({58originalCellIndex: originalCellIndex + j,59modifiedCellIndex: modifiedCellIndex + j,60type: 'modified'61});62}63}6465const modifiedLCS = computeModifiedLCS(change, originalModel, modifiedModel);66if (modifiedLCS.length && firstChangeIndex === -1) {67firstChangeIndex = cellDiffInfo.length;68}6970cellDiffInfo.push(...modifiedLCS);71originalCellIndex = change.originalStart + change.originalLength;72modifiedCellIndex = change.modifiedStart + change.modifiedLength;73}7475for (let i = originalCellIndex; i < originalModel.cells.length; i++) {76cellDiffInfo.push({77originalCellIndex: i,78modifiedCellIndex: i - originalCellIndex + modifiedCellIndex,79type: 'unchanged'80});81}8283return {84cellDiffInfo,85firstChangeIndex86};87}8889function computeModifiedLCS(change: IDiffChange, originalModel: { readonly cells: readonly ICell[] }, modifiedModel: { readonly cells: readonly ICell[] }) {90const result: CellDiffInfo[] = [];91// modified cells92const modifiedLen = Math.min(change.originalLength, change.modifiedLength);9394for (let j = 0; j < modifiedLen; j++) {95const originalCell = originalModel.cells[change.originalStart + j];96const modifiedCell = modifiedModel.cells[change.modifiedStart + j];97if (originalCell.cellKind !== modifiedCell.cellKind) {98result.push({99originalCellIndex: change.originalStart + j,100type: 'delete'101});102result.push({103modifiedCellIndex: change.modifiedStart + j,104type: 'insert'105});106} else {107const isTheSame = originalCell.equal(modifiedCell);108result.push({109originalCellIndex: change.originalStart + j,110modifiedCellIndex: change.modifiedStart + j,111type: isTheSame ? 'unchanged' : 'modified'112});113}114}115116for (let j = modifiedLen; j < change.originalLength; j++) {117// deletion118result.push({119originalCellIndex: change.originalStart + j,120type: 'delete'121});122}123124for (let j = modifiedLen; j < change.modifiedLength; j++) {125result.push({126modifiedCellIndex: change.modifiedStart + j,127type: 'insert'128});129}130131return result;132}133134135