Change:
Monaco Editor Repro  To verify bug-fix: Click on "Compare with latest dev" and notice that the alignment is correct in the dev version. (edited by Type: <bBug</b! This is a diff for a file that has been removed and regenerated using . Line 202 on the left should not be marked as deleted and there should not be an empty line on the right under line 201. This also causes the diff from this point to be misaligned: ! ! Last screenshot also shows how diff becomes even more misaligned if the same bug appears again later in the diff. This is not open-source project, so can't point to a commit with this change on github, but the same happened in my other projects when I regenerated by removing it and reinstalling deps. VS Code version: Code 1.86.1 (, 2024-02-07T09:07:19.849Z) OS version: Linux x64 6.1.0-17-amd64 Modes: <details<summarySystem Info</summary </detailsExtensions disabled<details<summaryA/B Experiments</summary</details<!-- generated by issue reporter --
This also happens when there aren't many changes to the file: !
Thanks for reporting! Can you reproduce this issue?
I still can with latest version !
Created a repro repo: There are two commits. Open diff between them in vscode to see the bug. Easier to notice with ! enabled
Played with playground bisect for fun, and since I did I can as well post the results: !
Probably it broke with
I'm not familiar with vscode source code, so the fix doesn't make much sense to me. Could you explain why the bug would happen only for some changes and not all of them? Unless it's hard to explain. I'm very interested what was the cause here.
The bug fix is just this: ! Which I think was an oversight when I combined and into (and then later only modify and not and ). This code looks at words in both sides and checks how many equal parts they have. If more than 1/3 of a word changed, the entire word is marked as changed. The bug here was that in your specific case, the word was extended in a wrong way. Even worse, the modified side was extended into the next line, whereas the original side wasn't. This caused the misalignment (and assertion failure). The function is quite tricky.
Thank you!

Discussion:
import { DynamicProgrammingDiffing } from 'vs/editor/common/diff/defaultLinesDiffComputer/algorithms/dynamicProgrammingDiffing'; import { MyersDiffAlgorithm } from 'vs/editor/common/diff/defaultLinesDiffComputer/algorithms/myersDiffAlgorithm'; import { computeMovedLines } from 'vs/editor/common/diff/defaultLinesDiffComputer/computeMovedLines'; <del> import { extendDiffsToEntireWordIfAppropriate, optimizeSequenceDiffs, removeVeryShortMatchingLinesBetweenDiffs, removeVeryShortMatchingTextBetweenLongDiffs, removeShortMatches } from 'vs/editor/common/diff/defaultLinesDiffComputer/heuristicSequenceOptimizations'; </del> <ins> import { extendDiffsToEntireWordIfAppropriate, optimizeSequenceDiffs, removeShortMatches, removeVeryShortMatchingLinesBetweenDiffs, removeVeryShortMatchingTextBetweenLongDiffs } from 'vs/editor/common/diff/defaultLinesDiffComputer/heuristicSequenceOptimizations'; import { LineSequence } from 'vs/editor/common/diff/defaultLinesDiffComputer/lineSequence'; import { LinesSliceCharSequence } from 'vs/editor/common/diff/defaultLinesDiffComputer/linesSliceCharSequence'; </ins> import { ILinesDiffComputer, ILinesDiffComputerOptions, LinesDiff, MovedText } from 'vs/editor/common/diff/linesDiffComputer'; import { DetailedLineRangeMapping, RangeMapping } from '../rangeMapping'; <del> import { LinesSliceCharSequence } from 'vs/editor/common/diff/defaultLinesDiffComputer/linesSliceCharSequence'; import { LineSequence } from 'vs/editor/common/diff/defaultLinesDiffComputer/lineSequence'; </del> export class DefaultLinesDiffComputer implements ILinesDiffComputer { private readonly dynamicProgrammingDiffing = new DynamicProgrammingDiffing();

} assertFn(() => { <del> if (!dontAssertStartLine) { if (changes.length > 0 && changes[0].original.startLineNumber !== changes[0].modified.startLineNumber) { </del> <ins> if (!dontAssertStartLine && changes.length > 0) { if (changes[0].modified.startLineNumber !== changes[0].original.startLineNumber) { return false; } if (modifiedLines.length - changes[changes.length - 1].modified.endLineNumberExclusive !== originalLines.length - changes[changes.length - 1].original.endLineNumberExclusive) { </ins> return false; } }