Skip to content

Keep a DiffView hunk's collapse with that hunk, not its position [patch] - #632

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/482-diffview-collapse-per-hunk
Oct 14, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/482-diffview-collapse-per-hunk

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #482

What was wrong

DiffViewState stored collapsed hunks as a HashSet<int> of positions. That state lives as long as the widget's label, so:

  1. Collapse hunk 2 of file A, then select file B under the same label, and B's hunk 2 opens collapsed.
  2. Stage hunk 0 and re-read the diff. Every later hunk shifts down one index, so the collapse marker lands on a different hunk.

Change

This follows the issue's preferred fix. The collapse flag is now a Collapsed property on HunkLayout. LayoutFor already replaces a layout when a different hunk instance arrives at a position (!ReferenceEquals(layout.Hunk, hunk)), so:

  • a new hunk at an old position starts expanded;
  • the same hunk instance redrawn keeps its state.

IsCollapsed and ToggleCollapsed now take the hunk as well as the index. Both are internal, and DiffView's three call sites already have the hunk in scope. The HashSet<int> is gone.

The issue's optional suggestion was left out on purpose: the static States dictionary is still never evicted. It grows only per distinct label, and nothing in this PR adds to it.

Tests

DiffViewStateTests:

  • Collapse_ADifferentHunkAtTheSamePosition_StartsExpanded is the bug. Temporarily switching the state back to index-only storage makes it fail, and it passes with the fix.
  • Collapse_TheSameHunkAgain_StaysCollapsed covers the issue's second requested case.
  • Collapse_OtherPositions_AreUnaffected checks that collapsing one position leaves the others alone.
  • Collapse_ToggledTwice_ReturnsToExpanded is updated for the new signature.

Results:

  • ImGui.Widgets.Tests: 1126/1126 pass.
  • dotnet build ImGui.Widgets across all target frameworks: 0 warnings, 0 errors.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JrNRgZ65vSm9BQxYHcanRS


Generated by Claude Code

DiffViewState kept collapsed hunks as a set of indices that lived as long as the
widget's label. Selecting another file under the same label, or re-reading a diff after
staging a hunk, put new hunks at old positions and they opened collapsed. The flag now
lives on the per-hunk layout, which is already replaced when a different hunk instance
arrives at a position, so a new hunk starts expanded and a redrawn one keeps its state.

Fixes #482

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JrNRgZ65vSm9BQxYHcanRS
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DiffView keeps hunk collapse state by index, so a new diff under the same label opens with the wrong hunks collapsed

2 participants