Skip to content

DiffViewer: inline-editor scrolls to wrong line on hunk navigation #26

@geevensingh

Description

@geevensingh

Problem

DiffPaneView.OnHunkNavigationRequested (DiffViewer/Views/DiffPaneView.xaml.cs:454-464) scrolls the inline editor to the wrong line when the user navigates via F7/F8 (or any code path that raises HunkNavigationRequested).

private void OnHunkNavigationRequested(object? sender, HunkNavigationEventArgs e)
{
    ScrollEditorToLine(LeftEditor, e.LeftLine);
    ScrollEditorToLine(RightEditor, e.RightLine);
    // Inline mode: the line numbers above are blob-relative, but the
    // inline editor's own line numbering is hunk-prefix-based. The
    // simplest approximation: scroll to the new-side line + 1 (header).
    ScrollEditorToLine(InlineEditor, e.RightLine);   // ← bug
}

The comment correctly notes that the inline document interleaves hunk-header lines, so blob-relative line numbers don't translate 1:1. But the actual call passes e.RightLine (the new-side blob line) to the inline editor unchanged. The further down in the file, the larger the offset error.

Why this is fixable cleanly

MapNewLineToInline(int newLine) already exists in the same file (DiffViewer/Views/DiffPaneView.xaml.cs:501-509) and does exactly the inverse lookup needed:

private int MapNewLineToInline(int newLine)
{
    if (_vm?.InlineLineToSourceLines is not { Count: > 0 } map) return newLine;
    for (int i = 0; i < map.Count; i++)
    {
        if (map[i].NewLine is int n && n >= newLine) return i + 1;
    }
    ...
}

It's already used by OnScrollRequested (DiffViewer/Views/DiffPaneView.xaml.cs:479+) for the overview-bar click path.

Suggested fix

- ScrollEditorToLine(InlineEditor, e.RightLine);
+ ScrollEditorToLine(InlineEditor, MapNewLineToInline(e.RightLine));

For deletions (a hunk where NewLine is null on the inline doc side because it's a pure removal), consider falling back to a MapOldLineToInline lookup or to the hunk-header line — e.RightLine will be 0 / the line after the deletion, which still won't be ideal.

Test coverage

Add a test that:

  1. Builds a diff with multiple hunks (e.g., a hunk near line 5 and another near line 50).
  2. Switches to inline mode.
  3. Calls JumpToHunk(1) (the second hunk).
  4. Asserts the inline editor's current vertical scroll line corresponds to the inline-doc line that maps back to the hunk's NewStartLine, not the raw NewStartLine.

This is harder to test because it requires WPF layout — but at minimum the helper math (MapNewLineToInline for known fixtures of InlineLineToSourceLines) can be unit-tested.

Citations

  • DiffViewer/Views/DiffPaneView.xaml.cs:454-464 — buggy handler
  • DiffViewer/Views/DiffPaneView.xaml.cs:479-492OnScrollRequested, the correct pattern
  • DiffViewer/Views/DiffPaneView.xaml.cs:501-509MapNewLineToInline helper that should be used
  • DiffViewer/Rendering/InlineDiffBuilder.cs — produces InlineLineToSourceLines

Severity

Medium-High. User-visible incorrectness in inline mode; the more interesting (further-down) hunks land off-screen.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions