context_server's Cargo.toml requested http_client's test-support
feature from its normal [dependencies], not just for its own tests.
Because Cargo unifies features per package across a build, this
activated http_client/test-support for every build that links
context_server at all, including a plain release build of the zed
binary itself: cargo tree -p zed -e normal,features showed the
feature resolved with no dev-dependency involved.
The only user of that feature in context_server was
http_client::FakeHttpClient, used exclusively inside #[cfg(test)]
modules in oauth.rs and transport/http.rs. Moving the feature request
to [dev-dependencies] (matching the existing gpui/test-support entry)
keeps those tests building while dropping test-support from every
non-test build, including benchmarks' resolved feature graph, which
previously had a single test-support occurrence traced to exactly
this edge.
Also extended script/check-gpui-bench-feature-isolation with a check
that scans benchmarks' entire resolved feature graph for the literal
test-support feature name, so any future direct or transitive
dependency reintroducing it fails loudly. While adding that check,
found and fixed a latent bug affecting every existing check in the
script: echo "${output}" | grep --quiet PATTERN races under
set -o pipefail, since grep --quiet exits after its first match
without draining stdin, which can SIGPIPE echo before it finishes
writing large output and turn a real match into a false negative (or,
for a negated check, a false positive). Replaced every instance with
grep --quiet PATTERN <<< "${output}", which does not pipe at all.
markdown_renderer was the last direct test-support edge in crates/benchmarks. language now exposes rust_lang_for_benchmarks behind its own narrow benchmarks feature, and markdown_renderer builds its registry with the always-available LanguageRegistry::new. display_map.rs, which had been getting gpui::TestAppContext/TestDispatcher for free through this same edge (language/test-support -> settings/test-support -> gpui/test-support, unified across benchmarks' whole build), now builds its Criterion harness from gpui::bench_platform/BenchAppContext instead. script/check-gpui-bench-feature-isolation is extended to prove all of it.
Adds a narrow `benchmarks` feature to `multi_buffer`, gating
`MultiBuffer::build_simple_for_benchmarks`/`build_random_for_benchmarks` as
production-faithful equivalents of `build_simple`/`build_random` that do not
require any crate's test-support. `display_map`/`editor_render` now call the
new functions instead, and `benchmarks` requests `multi_buffer/benchmarks`
instead of `multi_buffer/test-support`.
`build_random_for_benchmarks` is a dedicated duplicate of
`randomly_edit_excerpts`, substituting a vendored `BenchmarkRandomCharIter`
for `util::RandomCharIter` (the only test-support-only dependency it has),
guarded against drift by a new parity test asserting byte-identical output
against `build_random` for the same rng sequence.
Extends script/check-gpui-bench-feature-isolation to prove the direct
benchmarks -> multi_buffer/test-support edge is gone and that multi_buffer's
benchmarks feature itself resolves no test-support.
`crates/benchmarks/Cargo.toml` requested `settings`'s `test-support` feature directly so `display_map.rs`, `editor_render.rs`, and `markdown_renderer.rs` could each call `SettingsStore::test` to build the global `SettingsStore` they render against. `test-support` is a much wider surface than that one call needs: it also enables `gpui/test-support` and `fs/test-support`, and (per `settings`'s own crate) exposes settings-file mutation APIs meant for interactive tests, not benchmarks. This removes that direct edge by giving `settings` a narrow `benchmarks` feature that exposes exactly the initializer these three benchmarks need, with the same settings content as before.
`settings::src::settings_file.rs` already built its `test_settings()` content (default settings overridden with a deterministic monospace font, `empty-theme`, and `format_on_save: on`) entirely from production APIs (`default_settings()`, `parse_json_with_comments`, `util::merge_non_null_json_value_into`); the only reason it needed `test-support` was the `#[cfg(...)]` gate on the function itself. I extracted that body into a private `deterministic_font_and_theme_settings()` helper and added a sibling `benchmark_settings()` accessor that calls the same helper, gated on `feature = "benchmarks"` instead. `SettingsStore` gets a matching `SettingsStore::benchmarks(cx)` constructor next to `SettingsStore::test`, built the same way from `benchmark_settings()`. `settings`'s new `benchmarks = []` feature enables nothing else, so it cannot re-enable `gpui/test-support` or `fs/test-support` transitively, and it exposes no mutation API (`update_user_settings` stays gated to `test`/`test-support` only).
Because `benchmark_settings()` and `test_settings()` call the exact same helper function, their content is guaranteed byte-identical rather than merely intended to match, so switching `display_map`/`editor_render`/`markdown_renderer` over does not change the font, size, or theme fallback those benchmarks measure. I confirmed this is a true no-op for the theme in particular: `empty-theme` is never registered under the `LoadThemes::JustBase` these benchmarks use, so `theme_settings::configured_theme` already fell back silently to the same default theme it would use for any unrecognized name; only the font settings (Courier/Courier New at 14px) are load-bearing, and those are now sourced identically to before. `crates/settings/src/settings_store.rs` gains a `#[cfg(feature = "benchmarks")]` test, `test_benchmark_settings_match_test_settings`, that asserts the string equality directly and reads back `buffer_font_family`/`buffer_font_size`/`ui_font_family`/`ui_font_size`/`theme` from a real `SettingsStore::benchmarks(cx)` to confirm the representative settings a rendering benchmark reads still resolve as expected.
`crates/benchmarks/Cargo.toml` now requests `settings`'s `benchmarks` feature instead of `test-support`, and the three bench files call `SettingsStore::benchmarks(cx)` instead of `SettingsStore::test(cx)` — their only change. `cargo tree -p benchmarks --edges features --invert settings` before this change showed `benchmarks` as a direct dependent of `settings feature "test-support"`; after this change that direct edge is gone, and `benchmarks` instead is a direct dependent of `settings feature "benchmarks"`.
`settings/test-support` is not fully gone from `benchmarks`' resolved graph, and cannot be in this scope: `language/test-support` (needed directly by `markdown_renderer.rs`'s `LanguageRegistry::test`/`language::rust_lang`, with no production equivalent) enables `settings/test-support` itself, so it still resolves transitively through `language`. This is the same shape as the existing `theme`/`util` debt this script already tracked, so I folded `settings` into that same loop (`for foundational_crate in theme util settings`) instead of inventing a new check shape, and updated its comments to describe `language`/`multi_buffer` as the remaining crates keeping `test-support` populated in the graph. I also added a second, positive assertion that `benchmarks` still resolves `settings feature "benchmarks"`, so a future edit can't silently drop that feature request and have these three benchmarks start reading unrelated plain-default settings without any isolation check catching it. `edit_file_tool_benchmarks` (the sibling package `edit_file_tool.rs` lives in, added in #63048) is unchanged and explicitly excluded from all of this: it still needs `settings/test-support` for `SettingsStore::update_user_settings`, which has no production-capable equivalent for mutating already-loaded settings content, and the script's existing sanity check for that package's continued existence is untouched.
Testing performed:
- `cargo tree -p settings --no-default-features --features benchmarks -e no-dev --edges features`: no `test-support` edge anywhere, confirming the `benchmarks` feature alone enables nothing test-only.
- `cargo tree -p benchmarks --edges features --invert settings` before/after: the direct `test-support` edge from `benchmarks` is gone; only the transitive edge through `language feature "test-support"` remains. A direct edge to `settings feature "benchmarks"` is now present instead.
- `cargo check -p settings --no-default-features --features benchmarks`: compiles cleanly standalone.
- `cargo test -p settings --lib` (default features) and `cargo test -p settings --features benchmarks --lib`: 32 and 33 tests pass respectively, including the new `test_benchmark_settings_match_test_settings`.
- `cargo check -p benchmarks --benches` and `cargo check -p edit_file_tool_benchmarks --benches`: both compile cleanly.
- `cargo bench -p benchmarks --bench display_map/--bench editor_render/--bench markdown_renderer -- --test` (quick mode): all cases across all three targets report Success, including the headless-renderer-backed `editor_render`/`markdown_render` cases.
- `script/check-gpui-bench-feature-isolation`: passes; manually confirmed it fails (correctly) when `settings`'s Cargo.toml entry is reverted to `test-support` and separately when its `benchmarks` feature request is dropped entirely.
- `script/shellcheck-scripts` and `cargo fmt --check` (whole repo) both pass.
- `./script/clippy -p settings -p benchmarks -p edit_file_tool_benchmarks` (release, all features, deny warnings) passes, including `cargo shear --locked --deny-warnings`.
Remaining debt, tracked honestly rather than hidden: `language` and `multi_buffer` still request `test-support` directly (for `LanguageRegistry::test`/`language::rust_lang` and `MultiBuffer::build_simple`/`build_random`, none of which have a production equivalent), which keeps `settings/test-support` and `gpui/test-support` resolved transitively in `benchmarks`' graph regardless of this change. `edit_file_tool_benchmarks` is unaffected and continues to depend on `test-support` from `agent`, `editor`, `language`, `language_model`, `lsp`, `project`, and `settings` for its fake-project agent-tool harness, as documented since #63048.
Release Notes:
- N/A
crates/benchmarks/Cargo.toml requested test-support directly from seven
application crates (agent, editor, language, language_model, lsp, project,
settings) so its edit_file_tool.rs bench could drive the agent's edit-file
tool through TestAppContext, FakeFs, FakeLspAdapter, FakeLanguageModel, and
Project::test. Because Cargo unifies features per package, those test-only
builds applied to the whole benchmarks package, including display_map.rs,
editor_render.rs, and markdown_renderer.rs, which render production code
paths and have no inherent need for most of that test-only surface.
This moves edit_file_tool.rs into a new sibling package,
edit_file_tool_benchmarks (crates/edit_file_tool_benchmarks), with its own
Cargo.toml requesting exactly the dependencies and test-support features
that one benchmark needs. It reuses benchmarks::bench_utils (for
random_rust_file/rust_identifier/rust_file_line_count) via a plain
workspace dependency on benchmarks rather than duplicating that generator,
since bench_utils itself needs no test-support feature. The bench file's
content, name, and behavior are unchanged; only its package changed, so
`cargo bench -p edit_file_tool_benchmarks --bench edit_file_tool` replaces
`cargo bench -p benchmarks --bench edit_file_tool`.
With edit_file_tool.rs gone, crates/benchmarks/Cargo.toml drops its direct
test-support edges to agent, editor, language_model, and project entirely:
`cargo tree -p benchmarks --edges features --invert <crate>` now shows none
of those four anywhere in the graph, not merely as a direct edge (agent and
language_model aren't dependencies of benchmarks at all any more).
Two edges do not go away, and this is a real finding, not an oversight:
- settings/test-support remains, because display_map.rs, editor_render.rs,
and markdown_renderer.rs all call SettingsStore::test directly to build a
global settings store for their benchmarks, independent of
edit_file_tool. This also keeps gpui/test-support resolved (settings'
test-support feature enables it directly), which is what display_map.rs's
direct use of TestAppContext/TestDispatcher relies on.
- language/test-support remains, because markdown_renderer.rs calls
LanguageRegistry::test and language::rust_lang directly to build a
language registry for its Markdown benchmark, also independent of
edit_file_tool. language's test-support feature enables lsp/test-support,
so lsp/test-support still resolves transitively too, despite benchmarks
no longer depending on lsp directly at all.
- multi_buffer/test-support is now a new *direct* edge (it used to resolve
only transitively through editor's test-support): display_map.rs and
editor_render.rs call MultiBuffer::build_simple/build_random, which are
only compiled under multi_buffer's own test-support feature, with no
production equivalent.
None of this is edit_file_tool-specific, so moving that one benchmark out
cannot remove it without changing what display_map/editor_render/
markdown_renderer actually exercise (e.g. swapping SettingsStore::test for
settings::init would change the settings values feeding those benchmarks).
That is out of scope here.
script/check-gpui-bench-feature-isolation gains a check that walks the whole
resolved graph (not just a direct edge, since nothing else in benchmarks has
a legitimate reason to reach test-support through any of them) for agent,
editor, language_model, and project, confirming they are fully absent from
benchmarks' test-support surface now that edit_file_tool moved out. The
existing theme/util direct-edge check gains updated comments reflecting
that language, multi_buffer, and settings are the crates still populating
the graph, and the script gains a sanity check that
edit_file_tool_benchmarks still exists and resolves, documenting rather than
hiding its continued test-support dependency.
Validation performed:
- `cargo check -p benchmarks -p edit_file_tool_benchmarks --benches`: both
packages compile cleanly together.
- `cargo bench --offline -- --test` (quick mode) for all four bench
targets: display_map, editor_render, and markdown_renderer under
benchmarks, and edit_file_tool under edit_file_tool_benchmarks. All cases
report Success with the same benchmark names/groups as before the split.
- `cargo tree -p benchmarks --edges features` before/after comparison
confirms agent, editor, language_model, and project are gone from the
graph entirely, while language, multi_buffer, and settings remain for the
reasons above.
- `script/check-gpui-bench-feature-isolation` passes; manually confirmed it
fails (correctly) when a test-support edge to agent is reintroduced.
- `cargo shear --locked`: no unused dependencies in either package.
- `cargo fmt --check` (whole repo) and `./script/clippy -p benchmarks -p
edit_file_tool_benchmarks` (deny warnings) both pass.
- `bash script/shellcheck-scripts` and `bash script/check-licenses` both
pass for the modified/new files.
Remaining test-support debt, tracked honestly rather than hidden:
edit_file_tool_benchmarks still depends on test-support from agent, editor,
language, language_model, lsp, project, and settings, unchanged from before
this split. This PR only isolates that dependency to its own package so it
stops contaminating the three production-rendering benchmarks; giving
edit_file_tool_benchmarks a production-capable harness (or accepting it as
a permanently test-shaped benchmark) is future work.
Release Notes:
- N/A
crates/benchmarks/Cargo.toml requested test-support directly from eight
application crates (agent, editor, language, language_model, lsp, project,
settings, theme, util) to build fixtures its benches exercise. This trims
two of those: theme and util no longer need a direct test-support edge from
benchmarks.
theme needed no test-only API at all. The two benchmark-visible calls
(theme::LoadThemes::JustBase and theme_settings::init) are both plain
production APIs; theme's test-support feature only gates
ThemeRegistry::register_test_themes/register_test_icon_themes, which no
bench uses. Declaring theme's test-support in benchmarks' manifest was
already a no-op edge.
util needed exactly one test-only API: util::RandomCharIter, a synthetic
multi-byte-aware text generator used by the display_map and editor_render
benches to build random buffer contents. It has no production analogue (it
exists purely to generate adversarial test/benchmark input), so rather than
inventing a production-capable substitute, this vendors an equivalent
generator into benchmarks::bench_utils::RandomCharIter, matching the
existing precedent of benchmarks::bench_utils::random_rust_file for
markdown_renderer. Both benches now import it from there instead of util.
settings, agent, editor, language, language_model, lsp, and project remain
untouched and cannot be trimmed further in this scope:
- edit_file_tool.rs (the one bench target this PR leaves alone) calls
SettingsStore::update_user_settings, which only exists under
cfg(any(test, feature = "test-support")) with no production equivalent for
mutating already-loaded settings content, plus TestAppContext, FakeFs,
FakeLspAdapter, FakeLanguageModel, and Project::test: a deeply test-double
harness for benchmarking the agent's edit-file tool against a fake
project. None of that has a narrow production-capable substitute; building
one is the "larger architectural change" out of scope for this PR.
- Because edit_file_tool.rs stays in the same benchmarks package as the
other three bench targets, Cargo's feature unification means settings
(and by extension agent/language/language_model/lsp/project) stay enabled
with test-support for the whole package regardless of what the other three
targets need on their own.
- theme and util's test-support features still resolve elsewhere in the
benchmarks dependency graph after this change, because editor's own
test-support feature (needed for edit_file_tool.rs, editor_render.rs, and
display_map.rs, and out of scope here) requires theme/test-support and
util/test-support directly, independent of anything benchmarks itself
requests. This PR only removes the edge it controls: benchmarks' own
direct request.
Before this change, `cargo tree -p benchmarks --edges features --invert
theme` (and the `util` equivalent) showed a direct
`[dev-dependencies] -> benchmarks` edge into each crate's `test-support`
feature, alongside the pre-existing indirect edge through `editor`. After
this change, only the indirect edge through `editor` remains; benchmarks
itself no longer requests either crate's `test-support`.
script/check-gpui-bench-feature-isolation gains a check for this: for
`theme` and `util`, it walks `cargo tree -p benchmarks --edges features
--invert <crate>` and fails if `benchmarks` appears as a direct dependent of
that crate's `test-support` feature. Unlike the existing gpui/gpui_platform
checks in this script, it can't assert `test-support`'s total absence from
the graph, since `editor`/`project` (out of scope) keep it resolved
regardless; it specifically targets the one edge this change controls.
Validation performed:
- `cargo check -p benchmarks --benches`: clean, no warnings.
- `cargo build -p benchmarks --benches` and `--release`: all four bench
targets (display_map, edit_file_tool, editor_render, markdown_renderer)
compile.
- `cargo bench -p benchmarks --bench display_map` and `--bench
editor_render` (quick mode): both run successfully, including the
"unicode" display_map case that exercises multi-byte text from the
vendored RandomCharIter.
- `cargo tree` before/after comparison for `benchmarks` against `theme` and
`util` confirms the direct edge is gone.
- `script/check-gpui-bench-feature-isolation` passes; manually confirmed it
fails (correctly) against the prior Cargo.toml.
- `cargo fmt --check` (whole repo) and `./script/clippy -p benchmarks
--benches` (deny warnings) both pass.
Remaining edges out of scope, in one place: `crates/benchmarks/Cargo.toml`
still requests test-support directly from agent, editor, language,
language_model, lsp, project, and settings. All of them are load-bearing for
edit_file_tool.rs's fake-project agent-tool harness (or, for settings,
blocked by that same target's use of a genuinely test-only settings-mutation
API), which would need a larger, separate rework to give it a
production-capable path.
Release Notes:
- N/A
This mirrors the prior gpui-level fix (#63039, "gpui: Stop bench
feature from pulling in test-support") one layer down, in the platform
split crates that back gpui on macOS.
`crates/benchmarks` previously requested `gpui_platform`'s
`test-support` feature just to reach `current_headless_renderer()`, the
real Metal-backed headless renderer used by `#[gpui::bench]` consumers
to render scenes without a window. That feature also enables
`gpui_platform`'s and `gpui_macos`'s and `gpui_apple`'s interactive
test-double code, none of which a benchmark should compile alongside
its production code.
Each platform crate now exposes a narrower `bench` feature alongside
its existing `test-support` feature:
- `gpui_apple`: `bench = ["gpui/bench"]` gates the same headless Metal
renderer APIs (`MetalHeadlessRenderer`, `render_scene`,
`render_scene_to_image`, and their supporting state) under
`cfg(any(test, feature = "test-support", feature = "bench"))` instead
of only `cfg(any(test, feature = "test-support"))`.
- `gpui_macos`: `bench = ["gpui/bench", "gpui_apple/bench"]` re-exports
`MetalHeadlessRenderer` under the same widened cfg.
- `gpui_platform`: `bench = ["gpui/bench", "gpui_macos/bench"]` gates
`current_headless_renderer()` under
`cfg(any(feature = "test-support", feature = "bench"))` instead of
only `cfg(feature = "test-support")`.
`crates/benchmarks` now depends on `gpui_platform` with `["bench",
"font-kit"]` instead of `["test-support", "font-kit"]`.
`script/check-gpui-bench-feature-isolation` gains a macOS-only check
that walks `cargo tree --invert` for `benchmarks` against
`gpui_platform`, `gpui_macos`, and `gpui_apple` and fails if any of
them still resolve `test-support`, the same shape as the existing
gpui-level check.
Before this change, `cargo tree -p benchmarks --edges features
--invert gpui_platform` (and the `gpui_macos`/`gpui_apple` equivalents)
showed a `test-support` edge from `benchmarks`. After this change, the
same commands show only `bench` edges; `test-support` no longer
appears for any of the three platform crates.
Validation performed on this stack:
- `cargo check -p gpui_apple --no-default-features --features bench`,
same for `gpui_macos` and `gpui_platform`, all bench-only (no
test-support), all pass.
- All four `benchmarks` bench targets compile.
- `cargo tree` before/after comparison for `benchmarks` against each
platform crate confirms the `test-support` edge is gone and replaced
by `bench`.
- `script/check-gpui-bench-feature-isolation` passes, including the new
macOS-only platform-crate loop.
- `gpui_apple` and `gpui_macos` test suites pass.
- `gpui_platform`'s test failure is pre-existing and reproduces on the
base branch, unrelated to this change.
- `cargo fmt --check` and targeted `clippy` pass for the touched
crates.
Remaining edges out of scope: `crates/benchmarks/Cargo.toml` still
requests `test-support` from several application crates (`agent`,
`editor`, `language`, `language_model`, `lsp`, `project`, `settings`,
`theme`, `util`) to build fixtures and harnesses those benchmarks
exercise. Those are unrelated to the gpui platform split this change
addresses and are left untouched.
Release Notes:
- N/A
Enabling gpui's `bench` feature previously enabled `test-support` too,
so every `#[gpui::bench]` consumer transitively compiled gpui's
interactive test-double APIs (fake platform prompts, screen capture
simulation, proptest, etc.) alongside its production code. That defeats
the point of a benchmark: it can silently depend on behavior that only
exists for tests and would never ship.
`bench` still needs a handful of pieces that used to arrive bundled
inside `test-support`: a real multithreaded dispatcher
(`ThreadedDispatcher`), a window backed by a real headless GPU renderer
(`TestPlatform`/`TestWindow`/`PlatformHeadlessRenderer`), and the sprite
atlas plumbing those use. Those are moved onto their own
`cfg(any(test, feature = "test-support", feature = "bench"))` gates so
`bench` can use them without pulling in `test-support` as a whole.
The remaining interactive-only surface of `TestPlatform` (multiple-choice
prompts, path-selection dialogs, and their simulate/inspect helpers) stays
behind `test`/`test-support` only, since benchmarks have no API to answer
a prompt; `bench`-only builds get a minimal stub that resolves such a
prompt as immediately cancelled instead of leaving it pending.
crates/benchmarks continues to compile unchanged: it separately requests
`test-support` on `gpui_platform` (for its own real headless Metal
renderer lookup), so gpui's feature graph still unifies to
`bench + test-support` there today. That's a distinct dependency edge
this change doesn't touch: `gpui_platform`, `gpui_macos`, and `gpui_apple`
each gate their own headless-renderer glue behind their own test-support
feature, and giving `#[gpui::bench]` a real end-to-end path that needs no
crate's test-support would mean mirroring this same split there.
Added script/check-gpui-bench-feature-isolation, which walks gpui's
resolved feature graph with only `bench` enabled and fails if
`test-support` reappears in it.
Release Notes:
- N/A
# Objective
- Make it easy to switch Git features between showing uncommitted
changes and all changes on the current branch.
## Solution
- Add `git::ToggleDiffBase`, which toggles the user setting between
`head` and `default_branch`.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Git: Added an action to toggle the diff base between HEAD and the
default branch.
This PR adds some validation for the extension manifest.
Mostly,
- it tests that name and description are set and non-empty
- the authors-list is non-empty
- the repository URL is actually a parseable URL and reachable with a
200 code
Release Notes:
- N/A
Language model transport errors currently retain only a provider display
name after an HTTP request fails. Downstream clients therefore cannot
tell users which configured endpoint was unreachable without parsing the
source error or hard-coding provider names.
Make the request hostname a required part of
`LanguageModelCompletionError::HttpSend` and preserve it through the
Anthropic, OpenAI-compatible, OpenRouter, Vercel AI Gateway, and Zed
Cloud transports. Each transport captures the parsed hostname from the
request URI before sending it, using the configured base URL as the
defensive fallback. This supports production, development, and custom
endpoints without string matching.
Tests exercise transport failures through the real request paths and
verify hostnames for Anthropic, ChatGPT Subscription, generic
OpenAI-compatible providers, and Zed Cloud.
Testing:
- `cargo fmt --check`
- `cargo nextest run -p anthropic -p open_ai -p open_router -p
language_models_cloud -p language_models` — 209 tests passed
- `cargo check -p agent -p agent_ui --all-targets`
- `git diff --check`
- `./script/clippy -p language_model_core -p anthropic -p open_ai -p
open_router -p language_models_cloud -p language_models` — clippy
passed; the script subsequently failed in the repository-wide `cargo
shear --deny-warnings` step on 203 pre-existing target and doctest
configuration warnings
Release Notes:
- Improved language model connection errors to identify the unreachable
host.
# Objective
Ensure that the bindings displayed in the Git Panel's context menu do
not change between the first and subsequent frames.
## Solution
Git panel context menus could briefly display bindings from the generic
`GitPanel` context before switching to the more specific `ChangesList`
bindings. This was especially noticeable with Vim mode enabled, where
"Stage All" changed from `ctrl-cmd-y` to `shift-x`.
Since `GitPanel::dispatch_context` relies on
`FocusHandle::contains_focused` to be `true` in order to add the `menu`
and `ChangesList` contexts it could fail on the first frame the context
menu is shown, as the menu's focus handle is absent from the previous
frame's dispatch tree when first focused.
The simplest fix in this case is to fallback to
`GitPanel::context_menu::is_some()` in case
`GitPanel::focus_handle::contains_focused` returns `false`.
## Testing
Tested both manually as well as updated an existing test to ensure that,
when the context menu is first focused, both the `menu` and
`ChangesList` context are still present, even if no frame is rendered.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
<details>
<summary>Before</summary>
Notice how the "Stage All" binding changes from `ctrl-cmd-y` (macOS) to
`shift-x` (vim).
https://github.com/user-attachments/assets/1d2e2de5-dce4-422c-8d63-4bcd93375431
</details>
<details>
<summary>After</summary>
https://github.com/user-attachments/assets/79e74c3f-8358-4e7c-8eb9-74fa36adde67
</details>
## Future Work
It's still possible for the bug to show up the first time the very first
time the context menu is actually opened, if the Git Panel was not
previously focused, that is, using `right-click` on the Git Panel while
the editor was focused, for example. I suspect this has to do with how
`Window::highest_precedence_binding_for_action_in` also relies on the
previous frame's dispatch tree, at which point the `GitPanel` was not
yet available in the context.
---
Release Notes:
- Fixed issue where the bindings shown in the Git Panel's context menu
would change after the first frame.
# Objective
Read-only marked files in zed could still be affected by format on save
feature. This PR fixes that.
FIXES#62899
## Solution
These changes add an early return on Editor's `Item::save`
implementation so neither formatting nor the write to disk occurs.
## Testing
I've tested by reproducing the issue in the original ticket.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed read-only files being formatted and saved when `format_on_save`
is enabled
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
This PR updates the language extension docs for syntax-based rules,
line-based rules, and context-aware alignment. It is a follow-up to
#33370.
Release Notes:
- N/A
Closes#55345.
Wayland is the only platform whose frame ticks are conditional: a
wl_surface frame callback only arrives after a commit the compositor
goes on to repaint.
GPUI assumed unconditional ticks (any previously our Wayland backend
faked them), so an idle fullscreen window
stopped receiving callbacks and froze until external damage arrived.
This PR makes the Wayland render loop demand-driven, instead parking
when there's nothing to draw, and stops Zed committing empty frames on
every tick as the artificial heartbeat from the compositor.
---
Release Notes:
- Fixed the UI freezing in fullscreen on some Wayland compositors
- Fixed idle windows waking at the display's refresh rate on Wayland
---------
Co-authored-by: Philipp Schaffrath <philipp.schaffrath@gmail.com>
Co-authored-by: Daan De Meyer <daan@amutable.com>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
- Notify the author when their PR has been in draft state with no new
commits for three weeks
- Close the draft PRs that didn't get updated after one more week
- Re-try the cla-bot check on PRs that are still unsigned after a week
- Close the PRs that are still unsigned after the re-try
## Testing
It works on my machine™
```
python script/github-pr-cleanup.py --dry-run
Checking 713 open pull requests
Dry-run mode: no comments or closures will be made
PR #60885: asking the CLA bot to check again
Would comment on PR #60885:
@cla-bot check
PR #61625: asking the CLA bot to check again
Would comment on PR #61625:
@cla-bot check
PR #57239: warning about a stale draft
Would comment on PR #57239:
<!-- zed-community-automation:stale-draft-warning -->
This pull request has remained in draft without new commits for three weeks.
If it remains a draft without new commits for another week, it will be closed
automatically.
PR #57241: warning about a stale draft
Would comment on PR #57241:
<!-- zed-community-automation:stale-draft-warning -->
This pull request has remained in draft without new commits for three weeks.
If it remains a draft without new commits for another week, it will be closed
automatically.
PR #61461: warning about a stale draft
Would comment on PR #61461:
<!-- zed-community-automation:stale-draft-warning -->
This pull request has remained in draft without new commits for three weeks.
If it remains a draft without new commits for another week, it will be closed
automatically.
PR #61722: warning about a stale draft
Would comment on PR #61722:
<!-- zed-community-automation:stale-draft-warning -->
This pull request has remained in draft without new commits for three weeks.
If it remains a draft without new commits for another week, it will be closed
automatically.
PR #61808: warning about a stale draft
Would comment on PR #61808:
<!-- zed-community-automation:stale-draft-warning -->
This pull request has remained in draft without new commits for three weeks.
If it remains a draft without new commits for another week, it will be closed
automatically.
PR #61809: warning about a stale draft
Would comment on PR #61809:
<!-- zed-community-automation:stale-draft-warning -->
This pull request has remained in draft without new commits for three weeks.
If it remains a draft without new commits for another week, it will be closed
automatically.
Cleanup complete: 0 unsigned PR closures, 6 draft warnings, 0 draft closures
```
Release Notes:
- N/A
# Objective
- Prefer using `Duration` instead of integers when dealing with spans of
time. This prevents confusing different units of time and comparing
arbitrary integers with durations.
- Remove `_ms`/`_secs` suffixes from variables which are `Duration`,
since their unit is inside of the type.
- Initialize large integer constants using `Duration`, which has more
descriptive constructors, while maintaining the resulting integer type.
Release Notes:
- N/A or Added/Fixed/Improved ...
Anthropic now returns distinct error types for billing failures, request
conflicts, and gateway timeouts. Because the Anthropic client did not
recognize these values, they fell through to
`LanguageModelCompletionError::Other`, losing their structured status
and causing callers to apply generic handling.
Recognize the documented `billing_error`, `conflict_error`, and
`timeout_error` codes. Billing failures now become `PaymentRequired`,
conflicts preserve their HTTP 409 status and provider message, and
timeouts become typed upstream HTTP 504 failures. End-to-end tests
exercise each mapping through the HTTP response parsing path.
Testing:
- `cargo fmt --check`
- `cargo nextest run -p anthropic`
- `./script/clippy -p anthropic`
- `git diff --check`
Release Notes:
- Fixed handling of Anthropic billing, conflict, and timeout errors.
# Objective
Make it easy to conditionally enable the gpui inspector, with a goal of
eventually turning it on in nightly.
## Solution
The new `zed/inspector` flag (and supporting flags in other crates)
enables the relevant inspector features in `gpui`, `ui`, and
`inspector_ui` to be able to display the gpui inspector.
## Testing
- Enabling the inspector adds about 5mb to the binary, and for context
the zed binary is > 400mb at this time.
- Observationally, the inspector doesn't affect performance in a
meaningful way, but I did not run profiling.
```
# release with inspector (inspector on)
cargo run --release --features inspector
# release without inspector (inspector off)
cargo run --release
# dev build with debug assertions (inspector on)
cargo run
```
then trigger `dev::ToggleInspector`.
- linux: `ctrl-alt-i`
- windows: `shift-alt-i`
- macos: `cmd-alt-i`
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- N/A
---------
Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
This PR adds a 'clear' button to the search field in the Settings
window. The button becomes visible only when the field contains text.
Clicking the button clears the search field, which also resets the
navigation list.
Empty:
<img width="213" height="41" alt="image"
src="https://github.com/user-attachments/assets/03f97367-1036-453f-816a-5cbad219951c"
/>
With a search term:
<img width="213" height="38" alt="image"
src="https://github.com/user-attachments/assets/518047f4-c397-4a34-bb2f-147fcf37dc69"
/>
There are similar UIs, like the macOS and Windows System Settings
windows, and even Zed's 'Help' menu filter (on macOS), where the field
acts as a 'live filter', updating results on each keystroke, and the
'clear' action is more convenient than backspacing.
The first commit adds the button and the 'on click' functionality. If
the Zed team approves this change, I would also like to use the `escape`
key to clear the field. I have done some work on this, but there are
several issues and I would like some feedback before committing the
appropriate changes:
1. The `escape` binding to clear the field could arguably be built-in
(not user-configurable) since it's the standard key for this type of
action, and it may not make sense to allow other key combinations since
this field accepts keyboard input. Would the team approve a built-in key
binding, or must it be bound to a user-configurable `Action`?
2. For the Settings Window, `escape` is currently bound to the
`CloseWindow` Action by default. If the search field is focused,
pressing the `escape` key should clear the field, but not close the
window.
- If a new `Action` is used to clear the field (containing text), the
binding to that `Action` can have a more specific context
(`SettingsWindow > NavigationMenu && search`) than the `Action` on the
window (`SettingsWindow > NavigationMenu`), so the window won't close …
but if the field is *already empty*, should `escape` close the window
(and is there a way to re-enable the `CloseWindow` action in that case)?
- If a `KeyDownEvent` listener for `escape` is used to clear the field,
the `CloseWindow` Action still closes the window – is there a way to
cancel the `CloseWindow` Action in this case?
3. There is at least one other location with a similar 'live filter'
field, namely the Filter field in the Keymap Editor, where this same
functionality could be implemented. (I could update that too if this PR
is approved). Are there other similar instances in Zed? This 'clear
filter' UX should be consistent in all those locations.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
(I could not find an existing issue or discussion about this feature.)
Release Notes:
- Added a 'clear' button to the search field in the Settings window,
which clears the field and resets the navigation list.
---------
Co-authored-by: MrSubidubi <finn@zed.dev>
Makes `ztracing` spans work on the web, by mapping them to browser
`performance` APIs.
Since calling into JS from wasm has fairly high overhead, we instead
have a dedicated reporter task that threads send timing information to.
This approach significantly decreases the performance overhead of the
span-capturing thread (which is usually the performance sensitive one),
at the expense of:
- erasing thread information for spans in the browser devtools
- potentially dropping events if the bounded queue becomes full
The first issue can be mitigated by some slightly more sophisticated
capturing, along with a fixup script, which will come in a later PR
---
Release Notes:
- N/A or Added/Fixed/Improved ...
# Objective
Add configurable inline completion debounce timeout
Fixes/implements #23159
## Solution
I initially wanted to make a global setting for this, but it would
conflict with hardcoded debounces in codestral (150ms) and copilot
(75ms) which I assume are there for a reason.
So I ended up using the same mechanism used for the hardcoded debounce
in Codestral (`DEBOUNCE_TIMEOUT`) and Copilot
(`COPILOT_DEBOUNCE_TIMEOUT`)
and made it accessible and configurable for all providers.
Also fixed a bug with `DelayMs` `Display` trait adding "ms" into the
input field which then fails to parse something like "150ms" as a `u64`
by implementing `FromStr` which strips the "ms" suffix if present.
So now both "1000" and "1000ms" are parsed correctly and apply.
If the parsing fix is not relevant enough I can open a separate issue +
PR for that (and the inconsistent use and therefore display of
`Option<u64>` vs `Option<DelayMs>` in other ms input fields).
## Testing
#### Did you test these changes? If so, how?
Added a separate test which passes
`test_refresh_prediction_from_buffer_honors_debounce_duration`
Manually tested with openapi compatible prediction
All other tests in affected crates pass (`cargo test -p settings_content
-p settings_ui -p editor -p edit_prediction -p language
`)
#### How can other people (reviewers) test your changes? Is there
anything specific they need to know?
Open provider settings and adjust debounce, then see how long it takes
for a prediction to render.
#### If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
Tested on Fedora 43 KDE, but it shouldn't matter as none of the affected
code is platform specific.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
https://github.com/user-attachments/assets/14efa628-765e-4c2a-ac44-01aaa3657097
---
Release Notes:
- Added configurable inline completion debounce timeout, fixes#23159
---------
Co-authored-by: Ben Kunkle <ben@zed.dev>
Closes https://github.com/zed-industries/zed/issues/62801
# Objective
Fix issue https://github.com/flathub/dev.zed.Zed/issues/395 (reported
against the flathub package, but as described in it, it was introduced
by https://github.com/zed-industries/zed/pull/57440 ).
The symptom was that when running `flatpak run dev.zed.Zed <project
path>` (or some alias), then you'd get two "files" opened `--zed` and
`zed-editor`, with `zed-editor` also being added to the Zed project list
in the open window, which was quite annoying.
## Solution
- The flatpak CLI launcher, which self-launches with potential extra
arguments, now puts those arguments first rather than last.
## Testing
- A simple unit test targets the helper function that adds the arguments
- It also verifies that the parsed args come out as expected
## Self-Review Checklist:
- [ x ] I've reviewed my own diff for quality, security, and reliability
- [ x ] Unsafe blocks (if any) have justifying comments
- [ x ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ x ] Tests cover the new/changed behavior
- [ x ] Performance impact has been considered and is acceptable
Note: I believe that other bullets than self-review and tests are not
relevant, as there is no unsafe, no expected performance impact, and no
UI changes.
---
Release Notes:
- Fixed an issue where Flatpak CLI launches would open
unrelated/nonexistent files due to a bug in argument construction
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
# Objective
Closes#52429Closes#56735Closes#62495Closes#62878
Reverts #13071
This PR fixes Zed windows sometimes remaining blank when first opened on
X11.
The issue remained very inconsistent across WMs and conditions to
reproduce and was finally consistently reproducable on my dwm build with
no compositor and on i3 with no compositor after removing the workaround
earlier added, which made it occur in i3 but not on my dwm build because
it was more aggressive with it's EWMH policy. It happened only on
opening a newer repo not opened the last time.
While running foreground work, a synchronous X11 request can read events
from the socket and place them in x11rb's internal event queue, calloop
monitors the underlying socket rather than this internal queue, so if
the socket is empty when the foreground work finishes, these events may
remain unprocessed until unrelated X11 activity occurs.
window is mapped -> events are buffered by x11rb
-> X11 socket is no longer readable
-> calloop does not wake
-> MapNotify is not processed
-> refresh loop does not start
-> window remains blank
This explains why the problem was inconsistent and differed between
window managers. Later focus, scrolling (on any window), exposure, or
other X11 activity could make the connection readable again and
incidentally process the older events.
My earlier PR #61162 fixed the related case where an already processed
`Expose` event could wait indefinitely for a stopped refresh loop. It
did not fix this initial-window case because the relevant events had not
reached Zed's event handler yet, which was again not perfectly
reproducable and lead me to assume was fixed.
## Solution
Process any X11 events buffered by x11rb after each foreground runnable
completes:
foreground work completes
-> buffered X11 events are processed
-> MapNotify starts the refresh loop
-> initial window contents are displayed
This also removes the unconditional
[`SetInputFocus`](https://tronche.com/gui/x/xlib/input/XSetInputFocus.html)
added in #13071. That call frequently masked the issue by generating
additional X11 activity, but also bypassed the window manager's focus
policy despite Zed already sending the standard `_NET_ACTIVE_WINDOW`
request.
With the event queue handled correctly, Zed no longer needs to force
focus to make the initial frame appear.
## Testing
Repeatedly opened fresh and existing workspaces under dwm while another
application retained focus with a new-project being opened everytime (at
least not the previous one).
Before this change, fresh windows could remain blank until later X11
activity occurred. After this change, they render immediately without
focusing, scrolling, resizing, or switching workspaces.
Also verified that window activation is left to the window manager
through `_NET_ACTIVE_WINDOW`.
## Self-Review Checklist:
* [x] I've reviewed my own diff for quality, security, and reliability
* [x] Unsafe blocks (if any) have justifying comments
* [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
* [ ] Tests cover the new/changed behavior
* [x] Performance impact has been considered and is acceptable
Release Notes:
* Fixed Zed windows sometimes remaining blank when first opened on X11
* Fixed Zed overriding window-manager focus policies when activating
windows
# Objective
Closes#52822
When hovering over the LSP status tooltip for a running language server,
the binary path is displayed. Currently, this tooltip shows
`LanguageServerBinary.path`. However, many language servers are executed
through runtimes such as Node or Python. For example, Zed-managed
`Basedpyright` produces a `LanguageServerBinary` like:
```Rust
LanguageServerBinary {
path: "/usr/bin/node",
arguments: [
"/home/xin/.local/share/zed/languages/basedpyright/node_modules/basedpyright/langserver.index.js",
"--stdio",
],
env: ...
}
```
In this case, only `"/usr/bin/node"` is displayed, which doesn't convey
useful information about the actual language server script being
executed.
## Solution
There was a PR #53076 in which I was involved, and the solution there
was to populate every language server adapter with a special marker for
the path to be shown in the tooltip. That solution is accurate, but in
order to make this solution work for extension-provided servers, the
final diff became huge for a simple fix.
So here, as commented in
https://github.com/zed-industries/zed/pull/53076#pullrequestreview-4204849892,
a guess is performed by a newly introduced function
`tooltip_for_server_binary()` to get the real path to be shown. It may
have some edge cases, but works for current cases and is simple to
implement.
## Testing
Added new unit tests, built and tested locally, with the comparision
attached in the Showcase section.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
For the mentioned `Basedpyright` language server case, the comparision
is shown below:
| Before | After |
|:--:|:--:|
| <img width="431" height="187" alt="before"
src="https://github.com/user-attachments/assets/0611f2fe-687b-4d67-ba78-380d89ed0212"
/> | <img width="582" height="185" alt="after"
src="https://github.com/user-attachments/assets/6ad08720-ac53-4b2d-a72c-3febb441e2f1"
/> |
---
Release Notes:
- Improved the LSP status tooltip to display the target script path for
runtime-managed language servers
# Objective
When a worktree has no enclosing git repository, the `global-gitignore`
check falls back to matching the raw, unbounded absolute path. This lets
an ancestor directory outside the worktree, or the worktree's own root
name, incorrectly match a bare global-ignore pattern (e.g. a global
entry like `tmp` or `*.com`) and mark the entire worktree as ignored,
which silently breaks project search and greys out every file in the
project panel.
Fixes#62126Fixes#48887
## Solution
- In `Snapshot::ignore_stack_for_abs_path`, when no containing
repository is found, fall back to the worktree's own root as the
boundary for `IgnoreStack.repo_root`, instead of leaving it `None`.
- This reuses the existing repo-root-relative matching logic in
`IgnoreStack::is_abs_path_ignored` (already correct for the
git-repository case since #61689) without needing any changes to
`ignore.rs` itself: ancestors outside the worktree now correctly fail
the prefix check and are treated as not ignored, while the global
gitignore still applies to files and directories within the worktree.
## Testing
- Added `test_global_gitignore_without_repository` in
`crates/worktree/tests/integration/worktree_tests.rs`, covering both
variants in one worktree: an ancestor directory outside a non-git
worktree matching a global pattern, and the worktree's own root name
matching one, while also confirming a file that matches the pattern from
within the worktree is still ignored.
- Verified the new test fails without the fix (reproducing both #62126
and #48887) and passes with it.
- Ran the full `worktree` integration test suite (`cargo test -p
worktree --test integration`); all tests pass.
- Not tested on Windows or macOS, only Linux.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] Tests cover the changed behavior
---
Release Notes:
- Fixed global gitignore entries incorrectly matching directories
outside the opened project and marking the entire project as ignored
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
Fixes https://github.com/zed-industries/zed/issues/62780
When formatting changed-only regions, we have received formatting
changes that are larger than the regions submitted.
Previous code merged only adjacent hunks in a single response, without
merging anything else, e.g. multiple responses' ranges that overlapped.
Release Notes:
- Fixed overlapping range format results duplicating the text
The inline assistant's streaming-tool path waited for the first
`rewrite_section` output, but treated any other completion event as
terminal. Responses API providers can emit `ReasoningDetails`,
`Thinking`, and other metadata before the tool call. This stopped the
stream early and marked generation as done without applying a
replacement.
EOF was not handled explicitly. Parse errors, provider errors,
incomplete tool calls, and truncated responses could also be reported as
successful completions.
Continue consuming informational events until a supported tool call
arrives. Track the rewrite tool call's streaming state, reject a second
`rewrite_section` call instead of concatenating unrelated outputs,
accept `failure_message` only after its input is complete, and reject a
`rewrite_section` arriving after a failure message (and vice versa).
Stop, EOF, malformed tool input, and stream errors now surface as
`CodegenStatus::Error` instead of silently completing. A completed tool
call followed by `Stop(MaxTokens)` or `Stop(Refusal)` is also an error:
the OpenAI Responses mapper flushes truncated tool calls as complete
before emitting the stop reason, so the stop reason must be checked even
when the tool input parsed. Completed failure messages are stored before
`Finished` is emitted, and a failure message left over from a previous
generation is now cleared when a new one starts.
Add regression coverage for metadata around streamed rewrites, Stop and
EOF without a tool call, incomplete rewrites, interrupted responses,
multiple rewrite calls, failure messages, malformed input, mixed tool
calls, and stream errors before and after rewrite output begins.
---
Closes#52714
Release Notes:
- Fixed the inline assistant doing nothing when the model emits
reasoning before its tool call.
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Saves the recent navigation history (up to 20 entries) to the workspace
DB so it survives restarts. When reopening a workspace, persisted paths
that resolve to the current project are merged into the file finder's
history, deduplicated against files already opened in the session.
https://github.com/user-attachments/assets/3d8934e1-0da6-4445-8f3d-acc5597d7ac8
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
Closes: https://github.com/zed-industries/zed/issues/56271
Release Notes:
- Improved file finder history to include recently opened files from
previous sessions.
# Objective
When an user uses the Project Panel to rename a file, it is possible to
change its path too. For example, renaming `README.md` to
`documents/README.md` will create the `documents/` directory, in case it
doesn't yet exist.
Unfortunately, even though undoing a rename operation is already
supported, we were not yet considering this scenario where directories
had been created specifically to support the rename. As such, when undo
was used, for the scenario above, we'd end up moving `README.md` back to
its original location but would leave the empty `documents/` directory
behind.
## Solution
Introduce two new operations and changes specifically for this use-case,
`Operation::CreateDir`, `Operation::RemoveDir`, `Change::DirCreated` and
`Change::DirRemoved`, which we can then batch together with the
`Operation::Rename` in case directories need to be created or removed.
An initial approach of just keeping the list of created directories in
the `Operation::Rename` and `Change::Renamed` variants was considered
but it would require all users of `Operation::Rename` to now set it,
even if they don't actually need it, like the drag and paste operations.
Having separate operations and change variants also makes it clearer
what these are meant to be used for.
Something else worth noting is that, for `Operation::CreateDir`, the
directory will only be created if it doesn't yet exist, otherwise we'll
ignore. Same happens for `Operation::RemoveDir`, where if the directory
is not empty, we don't delete it, as it's possible for new files to have
been added to the directory outside of Zed and we don't want to delete
those.
## Testing
Tested both manually as well as introduced a new test case
– `project_panel::tests::undo::rename_with_dir_undo_redo` .
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
> This section is optional. If this PR does not include a visual change
or does not add a new user-facing feature, you can delete this section.
- Help others understand the result of this PR by showcasing your
awesome work!
- If this PR includes a visual change, consider adding a screenshot,
GIF, or video
- A before/after comparison is very useful for changes to existing
features!
While a showcase should aim to be brief and digestible, you can use a
toggleable section to save space on longer showcases:
<details>
<summary>Before</summary>
https://github.com/user-attachments/assets/15384fa8-9b94-495c-8992-19eee7a8f038
</details>
<details>
<summary>After</summary>
https://github.com/user-attachments/assets/c5be9f38-a2b4-4acc-8a1e-178161e326bb
</details>
---
Release Notes:
- Fixed undoing a file rename leaving behind directories created by the
rename.
# Objective
On case-insensitive volumes (the macOS default), language servers may
return `Location` URIs whose path casing differs from the worktree's
stored casing - e.g. `Utils/helpers.py` when the on-disk (and worktree)
path is `utils/helpers.py`. `LspStore::open_local_buffer_via_lsp` used
the LSP path verbatim, and worktree selection
(`WorktreeStore::find_worktree`) does a case-sensitive prefix match, so
the existing worktree was either missed (creating a duplicate invisible
worktree) or matched but with a relative path that retained the LSP's
intermediate-component casing. That relative path was then used to
`load_file`, which inserted a brand-new `Entry` keyed by the
differently-cased path alongside the existing one - producing duplicate
file entries in the project panel. This was most visible when navigating
Python imports (Go to Definition) where the LSP returned
differently-cased paths.
https://github.com/user-attachments/assets/e36930b5-8dfd-4b43-8fe4-5317d401e198
## Solution
Canonicalize the LSP-provided absolute path via `fs.canonicalize` before
the worktree lookup in `LspStore::open_local_buffer_via_lsp`, so the
path casing matches the filesystem and the existing worktree/entry is
reused. Canonicalization failures (e.g. a path that doesn't exist on
disk yet) fall back to the original path to preserve prior behavior.
To enable testing this on a fake filesystem, `FakeFs` now supports
`set_case_sensitive(false)` and its `canonicalize` resolves names
case-insensitively, returning the stored (canonical) casing.
## Testing
Added `test_open_buffer_via_lsp_case_variant_no_duplicate` in
`crates/project/tests/integration/lsp_store.rs`. It opens a buffer via
an LSP URI with differently-cased intermediate component
(`/root/SRC/main.rs` vs `/root/src/main.rs`) on a case-insensitive
FakeFs and asserts that no differently-cased entry is created and the
canonical entry is preserved. Verified the test fails without the fix
(`SRC/main.rs` duplicate appears) and passes with it. Existing worktree,
fs, and project_panel test suites remain green.
## Self-Review Checklist:
- [X] I've reviewed my own diff for quality, security, and reliability
- [X] Unsafe blocks (if any) have justifying comments
- [X] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [X] Tests cover the new/changed behavior
- [X] Performance impact has been considered and is acceptable
## Showcase
https://github.com/user-attachments/assets/f052cf10-8b45-4547-8425-00ce4050ee7c
---
Release Notes:
- Fixed duplicate file entries in the project panel on macOS when
navigating to definitions via the language server returned paths with
different casing than the worktree root.
---------
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
# Objective
use pickers for all kinds of lsp definitions
## Solution
add handlers for `GoToDeclaration` and `GoToTypeDefinition` in
`lsp_locations.rs`
## Testing
- Did you test these changes? If so, how?
- Are there any parts that need more testing?
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
## Showcase
this rust code can be used to test for multiple type definitions on `a`
```rs
macro_rules! foo {
($e:ident) => {
let $e: Vec<()>;
let $e: String;
};
}
fn main() {
foo!(a);
}
```
<img width="735" height="288" alt="image"
src="https://github.com/user-attachments/assets/578e6dc2-b201-4194-bd8b-e8d17b4d3d50"
/>
---
Release Notes:
- Respect `"lsp_results_location": "picker"` for go to declaration and
type definition
Bundled GLib shadowed the system libraries for host plugins dlopen'd
into the process, like PipeWire's videoconvert on 1.6+, which would
break Wayland screen sharing on newer distros. This PR makes Zed rely on
system GLib instead, since the bundled version pulls from whatever is in
CI (presently Ubuntu 20.04).
Release Notes:
- Removed GLib libraries from Linux release bundle, which could conflict
with system plugins
# Objective
On X11, GPUI raises the ICCCM `WM_HINTS` urgency flag to ask for
attention, but
it never clears it. The window stays urgent for the rest of its life.
`request_attention` was the only thing touching the bit. There was no
code
anywhere to clear it.
Docks and taskbars latch on the rising edge, so they show the attention
state
once and then sit there with a permanent urgent indicator, no further
notifications.
## Solution
Clear the flag when the window becomes active.
The read/modify/write moves out of `request_attention` into a helper,
`set_wm_hints_urgency(xcb, x_window, urgent)`. The raise and clear sites
are on
different self types (`X11Window` vs `X11WindowStatePtr`), so it takes
the
connection and window id.
The clear goes in `set_wm_properties`, where `state.active` gets set
from
`_NET_WM_STATE_FOCUSED`. That's the same field `request_attention`
already checks
in its `if self.is_active() { return; }` guard.
Two implementation notes:
* The clear is edge triggered (`state.active && !was_active`).
`set_wm_properties` recomputes everything on every `_NET_WM_STATE`
change, so a
level triggered check would do a blocking `WmHints::get` round trip on
every
maximize, fullscreen, hide and workspace switch while focused. Edge
triggering
is safe here because `request_attention` early returns when active, so
urgency
only ever gets raised while inactive, and the false to true transition
always
follows a raise.
* Clearing reads the hints first and skips the write if the bit isn't
set.
Otherwise focusing a window that never asked for attention would create
a
`WM_HINTS` property just to say "not urgent".
The raise path behaves exactly as before. The skip can't fire when
`urgent` is
true, so repeat raises still write every time.
Focusing clears the flag even if a second thread is still waiting.
That's already
how it works, since `request_attention` early returns when the window is
active.
## Testing
Tested on X11, Cinnamon with Muffin.
On an unpatched build the window had `_NET_WM_STATE_FOCUSED` and the
urgency bit
set at the same time.
W=$(xdotool search --class "dev.zed.Zed" | head -1)
xprop -id $W WM_HINTS
xprop -spy -id $W WM_HINTS
1. Fresh window says `WM_HINTS: not found`, and still does after
focusing it.
2. With focus on another window, the urgency bit shows up when attention
is
requested. `request_attention` early returns when active, so the window
has to
be unfocused for this to fire.
3. Focusing Zed clears the bit.
4. Repeating 2 and 3 re-arms it every cycle, not just once.
5. No `WM_HINTS` writes during normal use (resize, maximize, workspace
switch).
No automated test. It's an X11 round trip on a real window and there's
no X11
test harness in the tree.
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments (none added)
- [x] The content adheres to Zed's UI standards (no UI change)
- [x] Tests cover the new/changed behavior (see Testing)
- [x] Performance impact has been considered and is acceptable
Note this was manually tested, there wasn't a good way to test it
through the current harness.
---
Release Notes:
- Fixed the X11 urgency hint never being cleared, which left Zed showing
a permanent attention indicator in taskbars and docks after the first
notification
# Objective
Closing a project while a large local text file is loading can be
delayed
because file-reading and UTF-8 streaming loops have no await points.
Partially addresses #27283.
## Solution
Yield between 1 MiB blocks while:
- streaming UTF-8 files into a Rope
- reading files handled by the fallback decoder, including BOM, UTF-16,
and other non-UTF-8 encodings
Release Notes:
- Improved responsiveness when closing projects that are loading large
text files.
# Objective
- Support opening remote paths from SCP-style SSH URLs that use
bracketed IPv6 hosts, such as `ssh://[2600::]:~/foo`.
## Solution
- Validate SSH hosts with `url::Host::parse`, which supports bracketed
IPv6 addresses while continuing to reject malformed or ambiguous hosts.
- Add test coverage for IPv6 URLs with usernames, home-relative paths,
absolute paths, and explicit ports.
- Add rejection tests for unbracketed IPv6 addresses and ambiguous
port-plus-SCP-path syntax.
## Testing
- Ran `cargo fmt --all -- --check`.
- Ran `cargo test -p zed test_parse_ssh_urls -- --nocapture`.
- Ran `cargo test -p zed test_reject_ssh_urls -- --nocapture`.
- All targeted tests passed on macOS. No additional platform-specific
testing is expected to be necessary because the change only affects URL
parsing.
Release Notes:
- Fixed opening remote paths from SCP-style SSH URLs with IPv6 hosts.
Signed-off-by: Xiaobo Liu <cppcoffee@gmail.com>
I was trying out zed after VS Code and I've stumbled upon inconsistency
with debugging hotkeys.
In VS Code it's f10/f11, in zed it was much more awkward f7/ctrl-f11.
Investigating, I've found that I can't just override f11, because it's
used by `zed::ToggleFullScreen` global hotkey and global hotkey always
beats `Workspace && debugger_stopped`.
Furthermore, I've found f11 hotkey is available, but only on Mac. And on
Windows there was no `StepInto` hotkey at all. So configs were unsynced
in that regard.
Code changes:
- To make f11 overridable, I've moved it to `Workspace` context - it's
still pretty global, but now it's overridable. Though `Workspace &&
debugger_stopped` have the same depth as `Workspace`, it will take
priority, because it's registered later in .json.
- StepInto - added f11 hotkey for all platforms (was missing on linux
and windows), kept older ctrl-f11 too as some users might be used to it.
A note that on Mac F11 was added previously as `Workspace &&
debugger_running` - which practically means the hotkey wasn't available.
`debugger_running` means debugger is running in background, user needs
step commands when `debugger_stopped`- when they're actually stepping
through the code.
- StepOver - added f10 hotkey for all platforms (was missing on linux
and mac). Kept old f7 hotkey on linux and mac, didn't added it on
windows as it wasn't present before.
- StepOut - it was consistently shift-f11 on all platforms already, just
moved it from global context for consistency.
- Removed StepOver, StepInto, StepOut from debugger_session context and
kept it only in `debugger_stopped`, as this is when they're actually
useful, similar to how we have `debugger::Continue"` there which also
makes sense only when debugger is stopped.
I've separated changes by commits, so it would be easier to review them.
PS Global hotkeys overriding specific ones seems a bit odd by itself -
it seems global more specific hotkeys should always have a priority, so
maybe it's something to look into too.
Another thing that `default-xxx.json` share a lot of hotkeys, so
maintaining them separately may have other things going out of sync too.
Closes#58899.
----
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior - keymaps are not tested
- [x] Performance impact has been considered and is acceptable
Release Notes:
- Improved debugger step keybindings across platforms to match VS Code
defaults while preserving fullscreen outside paused sessions
---------
Co-authored-by: Kunall Banerjee <hey@kimchiii.space>