editor: Disable gutter breakpoint and bookmark actions in unsaved buf… (#61310)

## Context

Closes #58818

Breakpoints and bookmarks are keyed by a buffer's absolute file path. In
an unsaved (untitled) buffer there is no worktree file, so both
`BreakpointStore::toggle_breakpoint` and
`BookmarkStore::toggle_bookmark` early-return and do nothing. The gutter
still offered the affordances, so clicking (or cmd-clicking) the gutter
hover button, or picking an entry from the gutter right-click menu,
silently did nothing.

Rather than support these actions on unsaved buffers, this hides them:
the gutter hover button and the gutter context menu are both suppressed
for buffers without a worktree file, matching the store-level
eligibility check (`project::File::from_dyn(...).is_some()`). The buffer
is resolved per row via `anchor_to_buffer_anchor`, so multibuffers with
a mix of saved and unsaved excerpts behave correctly.

Manual test after the changes :

[Screencast from 2026-07-19
18-46-26.webm](https://github.com/user-attachments/assets/d1fe6704-3843-49bb-bcd6-d84ecdd4f19d)


## How to Review

**`crates/editor/src/element/mouse.rs`**

In the gutter hover-button computation in `mouse_moved`, the existing
`anchor_to_buffer_anchor(...).is_some()` guard is tightened to also
require the resolved buffer to have a worktree file. When the row
belongs to an unsaved buffer the button state stays `None` and the
debounce task is never armed, so the add-breakpoint/add-bookmark button
no longer appears. This is the single writer of `gutter_hover_button`,
and it recomputes on every mouse move, so a buffer that later gets saved
picks up the button again immediately.

**`crates/editor/src/editor.rs`**

`set_gutter_context_menu` now binds the multibuffer snapshot once,
computes the effective anchor, and returns early when that anchor's
buffer is not file-backed, so no menu is opened. This is the shared
choke point for all three ways the menu can open (gutter background
right-click, breakpoint-marker right-click, bookmark-marker
right-click), so every store-backed entry (Set/Unset Breakpoint,
log/condition/hit-condition, Enable/Disable, Add/Remove Bookmark, Edit
Bookmark, Run to Cursor) and the file-meaningless Git Blame entry are
all suppressed together. `gutter_context_menu` itself is unchanged.

**`crates/editor/src/editor_tests.rs`**

Adds a shared `build_gutter_hover_test_editor(saved)` helper that builds
either a saved-file editor or an untitled-buffer editor (via
`Project::create_buffer`), plus small helpers that draw the window and
simulate a mouse move / right-click over row 0 of the gutter hitbox.
Four tests cover both surfaces on both buffer kinds:
`test_gutter_hover_button_shown_for_saved_buffer` /
`test_gutter_hover_button_hidden_for_unsaved_buffer` (asserting the
hover button state and its activation debounce), and
`test_gutter_context_menu_shown_for_saved_buffer` /
`test_gutter_context_menu_hidden_for_unsaved_buffer` (asserting
`mouse_context_menu` opens only for the saved buffer). The saved-buffer
tests act as positive controls so the negative tests cannot pass
vacuously.

## Self-Review Checklist

- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the UI/UX checklist
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Fixed the gutter offering breakpoint and bookmark actions in unsaved
buffers, where they could not take effect
502cbccb0bsaberoueslati committed on 7/22/2026, 8:28:46 AM· committed by GitHubparent8556974
3 files changedLine totals unavailable