Closes#60761
Follow-up to #60970, which fixed this for `typescript-language-server`.
`vtsls` had the same problem, we only checked that the workspace tsdk
directory exists, but TypeScript 7 ships it without `tsserver.js`,
causing vtsls to error on startup.
Now we do the same `tsserver.js` check, so vtsls silently falls back to
its bundled TypeScript (see #60951).
Release Notes:
- Fixed vtsls showing a "doesn't point to a valid tsserver install"
error on startup in projects using TypeScript 7. For full TypeScript 7
support, install the `tsgo` extension to use TypeScript's native
language server.
# Objective
Closes#55936
Helps #57288
There is a strange behavior for Python users when using basedpyright or
pyright as the language server. As reported in #55936, when no settings
are configured in `lsp.basedpyright.settings`, the language server
correctly receives toolchain information discovered by Zed:
```json
{
"venvPath": ".",
"venv": ".venv",
"python": {
"pythonPath": "/home/xin/works/test/test_python/.venv/bin/python",
"defaultInterpreterPath": "/home/xin/works/test/test_python/.venv/bin/python"
},
"basedpyright.analysis": {
"typeCheckingMode": "standard"
},
"basedpyright.disableOrganizeImports": true
}
```
However, when the user configures any other settings in
`lsp.basedpyright.settings`, the toolchain information is silently lost.
For example, with the following `settings.json`:
```jsonc
{
"lsp": {
"basedpyright": {
"settings": {
"analysis": {
"diagnosticMode": "workspace",
"typeCheckingMode": "standard",
"inlayHints.callArgumentNames": true,
"inlayHints.variableTypes": true,
},
},
}
}
}
```
The final configuration sent to the language server becomes:
```json
{
"analysis": {
"diagnosticMode": "workspace",
"typeCheckingMode": "standard",
"inlayHints.callArgumentNames": true,
"inlayHints.variableTypes": true
}
}
```
No toolchain information is passed, so the language server ignores the
user's selected Python environment and falls back to whatever virtual
environment it discovers on its own. To make toolchain selection work,
users currently have to manually configure virtual environment settings
themselves (as noted in
https://github.com/zed-industries/zed/issues/57288#issuecomment-4750935341).
This issue was introduced in #48262, which aimed to make the virtual
environment used by basedpyright/pyright configurable. The core logic is
the `should_insert_toolchain` closure, originally designed to check
whether Zed should inject the detected toolchain into the language
server configuration. The intent was: if the user has already configured
a virtual environment in the language server settings, skip the
injection.
https://github.com/zed-industries/zed/blob/d4e43845fa1086512dedafdd2c852d167d005bb0/crates/languages/src/python.rs#L2115-L2128
However, the original logic was inverted — it injected the toolchain
when the user had no settings at all or when they had configured virtual
environment keys. This meant that when the user had LSP settings but no
virtual environment configuration, toolchain injection was skipped, as
reported in #55936.
## Solution
Change the logic defined in `should_insert_toolchain` closure, instead
of insert toolchain when detected virtual environment settings, now we
insert toolchain when no virtual environment settings is detected.
## Testing
Tested locally. The logic change is simple, should be easy for review.
## 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 toolchain selection being ignored when Pyright or Basedpyright
settings are configured without specifying a Python interpreter path
This is necessary to remove some `util` dependencies from crates, as
well as better sharing for our projects. This also includes the WIP
AbsPath abstraction as well as some bug fixes from internal tooling.
Release Notes:
- N/A or Added/Fixed/Improved ...
Closes https://github.com/zed-industries/zed/issues/60618
TypeScript 7 no longer ships `tsserver.js`, which
`typescript-language-server` depends on.
This PR does two things:
1. Pins the `typescript` package Zed auto-installs for
`typescript-language-server` to `^6`. For projects without their own
TypeScript in `node_modules` (which rely on the copy Zed installs), an
existing 7.x install gets downgraded to the latest 6.x, making the
server usable again.
2. Only hands the workspace's TypeScript to the server as a tsdk when it
actually contains `tsserver.js`, falling back to Zed's installed 6.x
otherwise. So if you upgraded your project to TypeScript 7, the language
server won't break. It keeps working against the 6.x TypeScript Zed
ships.
Note that vtsls, the default TypeScript language server, is unaffected
by the TypeScript 7 release. It bundles its own compatible TypeScript.
See #60951 for details. This PR only affects users who have manually
configured `typescript-language-server` as their language server.
Release Notes:
- Fixed `typescript-language-server` breaking after the TypeScript 7
release. For projects that have upgraded to TypeScript 7, install the
`tsgo` extension to use TypeScript's native language server.
Context:
While looking at #60618, I found out the TypeScript 7 upgrade only
breaks the `typescript-language-server` adapter, not the default vtsls
adapter.
After digging in, it turns out the initial vtsls implementation in
#12606 followed the same two-package installation pattern as the
`typescript-language-server` adapter: it installed both
`@vtsls/language-server` and the latest `typescript`. However, vtsls
already bundles a compatible TypeScript version via
`@vtsls/language-service` and uses it whenever a workspace SDK is
unavailable.
I also cross-checked an intermediate vtsls upgrade issue, #18349, where
we used the installed TypeScript version to decide whether both packages
needed updating, so a new vtsls release could go uninstalled when
TypeScript hadn't changed. #20197 fixed that by checking both packages
independently, but kept the unnecessary standalone TypeScript
installation.
Changes:
This PR removes that redundant installation and version tracking from
the vtsls adapter. Zed now tracks only `@vtsls/language-server` and
relies on its declared TypeScript dependency. Workspace TypeScript and
Yarn SDK detection remain unchanged, so vtsls still uses a workspace SDK
when one is available and otherwise falls back to its bundled version.
As for the consequence of this change:
1. New users are not affected since npm installs vtsls's own pinned
TypeScript dependency anyway.
2. For existing users, the previously installed standalone `typescript`
was never resolvable by vtsls (its pinned version gets installed nested
when the versions conflict), so leaving it there is harmless.
To verify the standalone copy was really unused, I nuked the vtsls dir
and ran main (without this fix), which installed both the top-level
`typescript@7.0.2` and vtsls's own pinned `typescript@5.9.3` nested
under `@vtsls/language-service`. Node's module resolution shows vtsls
can only ever see the nested copy as well as the LSP logs from the
running server shows, all lib definition locations point at the nested
copy:
```
"uri": "file:///.../vtsls/node_modules/@vtsls/language-service/node_modules/typescript/lib/lib.es5.d.ts"
```
I also tested this branch with a fresh install TypeScript files work the
same as before.
Release Notes:
- N/A
# Objective
Fixes#60261
Nothing under a `case` gets indented in C or C++, and the next `case`
doesn't come back out. It stays flat until you hit `editor: format`.
## Solution
The indent queries had no rule for case labels. Added the same pair
`cpp/indents.scm` uses for `access_specifier`: open an indent range at
the label, close it at the switch's `}`, outdent on the next label.
The part that got me: `@start` uses the *end* of the node you capture.
Fine for `access_specifier`, which is just `public:`. But a
`case_statement` swallows the statements under it, so capturing the node
starts the range after the last one. Capture the `:` instead. `default:`
is a `case_statement` too, so it comes along free.
Only affects what happens after a label, so existing `case` alignment
doesn't move.
## Testing
`test_c_autoindent_switch_case` and `test_cpp_autoindent_switch_case`
cover a plain case, fall-through labels and `default`. Both fail on
main. The `access_specifier` tests still pass.
Not mine, but worth knowing: `typescript::tests::test_outline` and
`test_generator_function_outline` are flaky on main, failing about half
my full `cargo test -p languages --lib` runs with or without this
change.
## 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:
- Fixed statements under a `case` label not being indented in C and C++
([#60261](https://github.com/zed-industries/zed/issues/60261)).
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
This fixes Go outline extraction for methods whose receiver has no name,
such as `func (v2) Method()`. These methods are now included in outline
symbols, which also feed breadcrumbs and sticky
scroll.
Tested with:
- `cargo test -p languages`
- `cargo test -p grammars`
- `./script/clippy -p languages`
- `cargo fmt --check --package languages`
Before:
[before_cut.webm](https://github.com/user-attachments/assets/91eb5cb0-703a-4496-b0dd-5369c4c219fc)
After:
[after_cut.webm](https://github.com/user-attachments/assets/76d13d88-3671-4118-99fc-c073a6e64727)
Release Notes:
- Fixed Go methods with unnamed receivers not appearing in breadcrumbs
and sticky scroll.
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
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
Closes#57030
When `fullFunctionSignatures` is enabled in `rust-analyzer`, some
completion items returned by the language server have an unexpected
`filterText`. For example:
```jsonc
{
"label": "sync_all(…)",
"labelDetails": {
"detail": "(alias fsync)",
"description": "pub fn sync_all(&self) -> io::Result<()>"
},
"kind": 2,
"sortText": "7ffffffa",
"filterText": "sync_allfsync",
...
}
```
For such completion items, the rust-analyzer adapter falls back to an
outer range passed into the `mk_label` closure to determine the display
range:
https://github.com/zed-industries/zed/blob/22852a6431ca8a5e0fe07a4769e9fe521d2b1b0a/crates/languages/src/rust.rs#L362-L371
For functions or methods, this fallback range is calculated here:
https://github.com/zed-industries/zed/blob/22852a6431ca8a5e0fe07a4769e9fe521d2b1b0a/crates/languages/src/rust.rs#L424-L435
In this example, the `function_signature` is `"pub fn sync_all(&self) ->
io::Result<()>"`, and the regex matches up to `fn sync_all(&self) ->
io::Result<(`. Currently, the range passed to the `mk_label` closure
mistakenly covers `"ub fn sync_all(&self) -> io::Result<"` (causing the
first character 'p' to be truncated, as reported in #57030), whereas we
only want `"sync_all"` itself
This PR introduces two main changes to fix this behavior:
- Adjust the range start: Skip the leading `fn` keyword so that the
range starts exactly at the function or method name.
- Update the regex pattern: The current pattern matches up to the last
`(`, which causes incorrect slicing if the return type contains
parentheses (e.g., `Result<()>`). This is changed to match up to the
first `(`.
Release Notes:
- Fixed some rust completions has `ub fn ` as prefix when
`fullFunctionSignatures` is enabled
# Objective
Consider a simple Python file with the following content, where both a
method and a function are defined:
```python
class TestCase:
def a_test_method(self): # a method
print("This is a method test")
def a_test_function(): # a function
print("This is a function test")
```
Below this, if we type `a_test_func` and trigger language server
completion, we would expect to see `a_test_function` in the completion
list. Similarly, if we have:
```python
test = TestCase()
test.a_testˇ
```
and trigger language server completion, we should see `a_test_method` in
the completion list.
In both cases, we expect the items in the completion list to have the
same color highlighting as they do in the editor buffer, but currently,
they do not. This is because Zed uses the wrong queries to retrieve the
highlight. Taking the `ty` LSP adapter as an example:
https://github.com/zed-industries/zed/blob/ef7fc3c28828ff9edbe35849567634c13ce2ee3b/crates/languages/src/python.rs#L323-L332
the key `"function.method"` and `"function"` are used to look up the
method and function highlight IDs, but these keys do not exist in
`crates/grammars/src/python/highlights.scm`, which defines the syntax
highlighting. The correct keys here should be `"function.method.call"`
and `"function.call"`.
## Solution
- As stated above, change the keys from `"function.method"` and
`"function"` to `"function.method.call"` and `"function.call"`,
respectively.
- Additionally, since we have several built-in language servers for
Python, a minor refactoring has been done to reduce duplicate code and
simplify future changes.
## Testing
- I have tested this change locally; the before and after comparison is
provided below.
## 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
<details>
<summary>Click to view showcase</summary>
| Before | After |
| :---: | :---: |
| <img width="767" height="308" alt="function_before"
src="https://github.com/user-attachments/assets/943852d6-f54e-411d-916f-add7aac57956"
/> | <img width="767" height="308" alt="function_after"
src="https://github.com/user-attachments/assets/3a817229-ce32-4d13-88b8-9e9151869338"
/> |
| <img width="767" height="308" alt="method_before"
src="https://github.com/user-attachments/assets/cbc0f4f4-be6e-44d3-9798-df29df5731a3"
/> | <img width="767" height="308" alt="method_after"
src="https://github.com/user-attachments/assets/6e8f7e84-c5c6-4b37-a2c5-10820f12a09d"
/> |
</details>
---
Release Notes:
- Improved Python completion item highlighting for methods and
functions.
The `go-subtest` task template wrapped the `-run` arg in single quotes
for shell safety. This works for Run Test (terminal strips quotes), but
Debug Test sends the arg through Delve’s DAP protocol with no shell
involved, so the literal quote characters ended up in the regex and
prevented any match.
All other Go task templates (`go-test`, `go-testify-suite`,
`go-table-test-case`) use the backslash-escaped format which `GoLocator`
already knows how to handle. Align the `go-subtest` template to the same
format.
Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] 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#53230.
Release Notes:
- Fixed Debug Test for Go subtests
---------
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
This removes gpui's dependency on the `util` crate, which depends on
async process. It now depends on `gpui_util` only, and uses
`std::process::Command` for the two cases where it was previously using
an async `Command`. This lifts the requirement of non-Zed consumers of
gpui to depend on our forked async-process (see #59156).
Release Notes:
- N/A
Both cloning and dropping of these has quite a bit of overhead (despite
them being snapshots), so avoid where possible, especially in display
map syncing
Release Notes:
- N/A or Added/Fixed/Improved ...
Closes#46881
Depends on #57276.
Implements `GoRunnableResolver` to post-process table test matches. The
resolver picks the correct string field by comparing against the field
used in `t.Run(tc.<field>, ...)`.
Release Notes:
- Fixed Go table tests not showing run buttons in files with many test
cases.
Resolves https://github.com/zed-industries/zed/issues/58086
This diff fixes `package.json` runnables using npm for projects that
declare their package manager through
`devEngines.packageManager`. The `package.json` parser only looked at
the top-level `packageManager` field, so projects using the newer
`devEngines` shape fell back to `npm` even when they specified `pnpm`,
`yarn`, or `bun`.
With this change, package manager detection also reads
`devEngines.packageManager` in both object and array forms. The
top-level `packageManager` field still takes precedence when both are
present, and the shared parser means the fix applies to `package.json`
gutter runnables as well as TypeScript package-script tasks.
Release Notes:
- Fixed `package.json` runnables ignoring package managers declared via
`devEngines.packageManager`.
---------
Co-authored-by: dino <dinojoaocosta@gmail.com>
Stops the `conda activate base` fallback in
`PythonToolchainProvider::activation_script` for two cases:
1. A Conda toolchain whose `environment.name` is `None`.
2. A Conda toolchain whose name is `Some(...)` but `shell.try_quote`
rejects it.
Previously both cases pushed `conda activate base` into the activation
script. With miniforge installed and no env explicitly selected, every
terminal silently activated `(base)`. The user didn't pick `base`;
injecting it is contamination.
Both branches now log a warning and emit no activation line. Users who
want `(base)` can select it as the toolchain explicitly.
Two unit tests cover the new behavior:
`test_conda_activation_skips_when_name_missing` (name=None) and
`test_conda_activation_skips_unquotable_name` (name=Some but unquotable,
exercised with an embedded NUL byte that `shlex::try_quote` rejects).
The existing `test_conda_activation_script_injection` still verifies
that quotable names get activated.
Release Notes:
- Fixed Zed silently injecting `conda activate base` into terminals when
a Conda manager (miniforge/miniconda) was installed but no specific
environment was selected.
rust-analyzer does not really attempt to be backwards compatible, so
when users opt-into the component a toolchain override, we should prefer
that over any other rust-analyzer (especially our own) for better
toolchain compatibility in case people have a more out of date install.
This mirrors the VSCode extension behavior
Release Notes:
- When a worktree contains a Rust toolchain file with a rust analyzer
component specified, Zed will now spawn the given toolchain's
rust-analyzer for toolchain compatability
Zed-managed npm installers were resolving a concrete latest version with
`npm info` and then installing `package@version`. That is brittle when
users
configure npm release-age filtering via `before` or `min-release-age`:
npm's
installer applies those rules during resolution, but our pinned install
target
could disagree with it, and therefore fail to install.
This changes managed npm installs to install `package@latest` and let
npm apply
its own resolver and user config. The local latest-version lookup
remains as a
best-effort cache freshness check, not as the exact install target.
Exact extension API installs remain unchanged because extensions
explicitly
request a package and version. If we want to revisit that we can.
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#53611
Release Notes:
- Fixed npm-backed tool installs to better respect npm release-age
filters.
The function is unsound due to the classic fact that one can leak tasks,
sidestepping the blocking drop behavior resulting in a use after free.
Release Notes:
- N/A or Added/Fixed/Improved ...
…/` URI
The ESLint adapter was sending `workspaceFolder.uri` as a raw filesystem
path (e.g. `/Users/foo/project`) instead of a proper `file://` URI (e.g.
`file:///Users/foo/project`).
This caused the vscode-eslint server's `workingDirectory: { mode: "auto"
}` to fail when resolving the workspace root, falling back to the linted
file's directory as the working directory. As a result,
`eslint-import-resolver-typescript` could not locate `tsconfig.json`,
breaking path alias resolution for rules like `import/order` — producing
different lint results compared to VS Code.
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
Release Notes:
- N/A or Added/Fixed/Improved ...
This PR introduces native LSP support for Bash by integrating
`bash-language-server`. Combined with the existing Tree-sitter grammar,
Zed now provides a complete, out-of-the-box development experience for
shell scripting.
The implementation is very similar to other npm-managed language
servers. With `shellcheck` installed, standard LSP features—including
diagnostics, code actions, go-to-definition, find-references, and code
completion—work as expected.
Since I am not a frequent user of Bash, I have intentionally limited
this implementation to a standard, "out-of-the-box" setup. I lack the
hands-on experience to identify specific pain points or advanced LSP
features that might require custom integration, so I've avoided adding
any speculative or specialized configurations, especially within the
`LspAdapter` trait.
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
Closes#51917
Release Notes:
- Added built-in language server support for Bash
---------
Co-authored-by: Finn Evers <finn@zed.dev>
Powershell does not support eval, furthermore pwsh is also a
"powershell" shell for micromamba.
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
Release Notes:
- Fixes micromamba powershell activation
## Context
Previously the Run Debugger gutter arrow would fail silently when the
Cargo.toml had garbage lines such as “asdfasdf”. This fix makes it so
that the error is detected and bubbles up to the editor, which will
notify the user with a toast diagnostic.
Closes#46716
## Fix
https://github.com/user-attachments/assets/2e9ac7e9-1306-4607-a762-457131473572
## How to Review
Small PR - focused on four different files:
In - `crates/languages/src/rust.rs`:
- `target_info_from_abs_path()` - The function signature was changed
from `Option<(Option<TargetInfo>, Arc<Path>)>` to
`Result<Option<(Option<TargetInfo>, Arc<Path>)>>`. A condition was added
to ensure that if the Cargo metadata command is unsuccessful, the
function returns an error instead of causing an EOF error while
deserializing the stdout of the command.
- `build_context()` - Added a `?` in `target_info_from_abs_path(path,
project_env.as_ref()).await` in order to return the error.
In - `crates/project/src/task_store.rs`:
- `local_task_context_for_location()` and
`remote_task_context_for_location()` - The functions signatures were
changed from `Task<Option<TaskContext>>` to
`Task<anyhow::Result<Option<TaskContext>>>` for the purpose of
propagating the error.
In - `crates/editor/src/editor_tests.rs`:
- `build_tasks_context()` - The function signature was changed from
`Task<Option<TaskContext>>` to
`Task<anyhow::Result<Option<TaskContext>>>` .
- `toggle_code_actions()` - In case `build_tasks_context()` fails, the
functions notifies the error to the user as a Toast notification.
In - `crates/editor/src/runnables.rs`:
- Since `build_tasks_context()` and
`task_store.task_context_for_location()` now return a Result, the
callers` spawn_nearest_task() `and `task_context()` were modified. The
resulting Result types are transformed to match the expected return
types of `TaskContext` and `Task<Option<TaskContext>>`
Two new tests were added. The first, `target_info_from_abs_path_failed`
in `crates/languages/src/rust.rs`, checks if the system properly catches
the error. The second,
`test_toggle_code_actions_build_tasks_context_error_notifies` in
`crates/editor/src/editor_tests.rs`, confirms that the editor triggers
the expected error notification.
## 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](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
Release Notes:
- Fixed the error: Run Debugger failing silently due to invalid
Cargo.toml content
---------
Co-authored-by: Lukas Wirth <lukas@zed.dev>
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 #ISSUE
Release Notes:
- N/A
No, sadly, the title is not a typo. See
https://www.githubstatus.com/incidents/zsg1lk7w13cf for the context.
I'll read with joy and popcorn through that root cause analysis.
It makes literally zero sense what happened here, but for some completly
bonkers reason GitHub completely messed up the merge queue with
https://github.com/zed-industries/zed/pull/54632.
I have no idea how it happened. It makes literally zero sense. A PR
going into the merge queue should have the same LoC when getting out of
it. GitHub obviously does not check this. GitHub causes extra work with
a feature that is supposed to save time.
Thanks, I guess.
Release Notes:
- N/A
---------
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This PR brings back the button to filter remote branches when accessing
the title bar's branch picker with the mouse. It was unintentionally
removed when we introduced the new worktree picker.
Release Notes:
- N/A
Uses tree-sitter indent queries to create a pseudo-scope, since access
modifiers are single-node in thetree-sitter grammar.
The @outdent capture truncates the parent { } indent range at the access
specifier, keeping it at the same level as the class keyword and the
pseudo-scopes from stacking.
The @outdent range selects siblings so we don't outdent the access
specifiers themselves, since screenshots from the reference issue seem
to show that at least one interested party does not prefer outdented
access modifiers, and also it seemed like less of a departure from
existing design.
Also, there are probably more tests than needed because this is my first
time writing treesitter queries and I wanted to triple-guess myself.
Quite open too feedback on which ones are more valuable.
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#53175
Release Notes:
- Improves handling of indentation after C++ access modifiers
Shorthand methods (`methodName() {}`) inside nested object literals were
not shown in the Outline panel. The outline query only captured
method_definition when it was a direct child of a variable_declarator's
object, so nested objects (e.g. `deep: { subFn() {} }`) were missed.
Extended the outline query to match method_definition in any object
node, not just top-level variable_declarator objects. Applied the fix to
TypeScript, JavaScript, and TSX outline definitions. Added tests for the
issue reproduction and edge cases.
Supporting evidence:
<img width="1352" height="812" alt="image"
src="https://github.com/user-attachments/assets/64868a70-abd3-4935-9c03-4c809b55262b"
/>
Fixes#48711
Release Notes:
- Fixed nested object methods not appearing in the Outline panel for
JavaScript and TypeScript files
Closes#47926
## Summary
When using a uv (or Poetry/PDM) workspace with multiple subprojects,
Python LSP servers (Pyright, Ruff, ty, etc.) are initialized with the
subproject directory as their workspace folder instead of the workspace
root. This happens because `PyprojectTomlManifestProvider::search()`
returns the first (innermost)
`pyproject.toml` found walking up the directory tree.
For example, in a uv workspace like:
main-project/
├── pyproject.toml # workspace root with [tool.uv.workspace]
├── uv.lock
├── packages/
│ └── project-api/
│ └── pyproject.toml # subpackage
└── projects/
└── project-a/
└── pyproject.toml # subpackage
Opening a file in `packages/project-api/` would register
`packages/project-api/` as the LSP workspace folder instead of
`main-project/`.
## Approach
The fix uses lockfile existence as a heuristic to detect workspace
roots. The updated `search()` method walks all ancestors (similar to
`CargoManifestProvider`) and:
- Tracks the **innermost** `pyproject.toml` as a fallback
- Tracks the **outermost** `pyproject.toml` that has a sibling lockfile
(`uv.lock`, `poetry.lock`, `pdm.lock`, or `Pipfile.lock`)
- Returns the outermost workspace root if found, otherwise falls back to
the innermost
This works within the existing `ManifestDelegate` interface (existence
checks only, no file content reading).
| Scenario | Result |
|---|---|
| uv workspace (root `pyproject.toml` + `uv.lock`) | Returns workspace
root |
| Poetry workspace (root `pyproject.toml` + `poetry.lock`) | Returns
workspace root |
| Simple project (single `pyproject.toml`, no lockfile) | Returns
project dir (unchanged) |
| Independent subprojects (no lockfile at any level) | Returns each
project's own dir (unchanged) |
Since the manifest provider is set at the Python **language** level,
this fix applies to all Python LSP servers (Pyright, Ruff, ty, etc.).
## Test plan
- [x] Added unit tests for `PyprojectTomlManifestProvider` covering all
scenarios above
- [x] Existing integration test
`test_running_multiple_instances_of_a_single_server_in_one_worktree`
passes (independent subprojects without lockfiles)
- [x] `cargo check -p languages` compiles cleanly
- [x] Manual testing with a real uv workspace (Pyright and Ruff both
receive correct workspace root)
Release Notes:
- Fixed Python LSP servers (Pyright, Ruff, etc.) using the wrong
workspace folder in uv/Poetry/PDM workspaces with multiple subprojects.
This fixes#53819.
JSON schema downloads were still going through the JSON language server
without picking up Zed's configured proxy. On networks that require the
proxy, that made schema fetches fail even though the rest of the app
could connect normally.
This passes the proxy setting through to the JSON language server
configuration so schema requests follow the same network path as the
rest of Zed.
## Test plan
- `rustfmt --edition 2024 crates/languages/src/json.rs`
- `git diff --check -- crates/languages/src/json.rs`
Release Notes:
- Fixed JSON schema downloads ignoring Zed's proxy setting.
---------
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
Self-Review Checklist:
- [X] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] 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
- [ ] Performance impact has been considered and is acceptable
Release Notes:
- Added the option for highlights from languages to specify fallbacks.
That means that if you have a pattern with the captures `@second.capture
@first.capture`, Zed will first try resolving a highlight from your
theme for the code fragment using the first capture, then look for the
second capture if no match for the first capture could be found.
---------
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Closes#29757Closes#49387
This PR upgrades ESLint language server from `vscode-eslint 2.4.4` to
upstream `microsoft/vscode-eslint 3.0.24`, and make the workspace
configuration version-aware so ESLint 8, 9, and 10 take the correct
config-mode path.
The key part is that the 3.x bump alone is not enough. This PR keeps Zed
out of that path except where it is still actually needed. Rest
heavy-lifting is done by eslint server itself.
Zed now only overrides ESLint settings in the two known broken cases:
- ESLint 8.21-8.56 flat config: send `experimental.useFlatConfig = true`
- ESLint 9 legacy config: send `useFlatConfig = false`
All other cases defer to `vscode-eslint 3.x`'s own config and
working-directory discovery.
For testing, I created https://github.com/smitbarmase/eslint-repros,
which contains a versioned ESLint repros covering root flat config,
legacy config, and package-local monorepo cases across ESLint 8, 9, and
10. Here is compare between `zed/main`, a pure `vscode-eslint 3.x`
upgrade and this branch with the config-mode fixes:
## zed main
```text
eslint-v8_21-flat-root-single
eslint-v8_56-flat-package-local-monorepo -> breaks on main
eslint-v8_56-flat-root-single
eslint-v8_56-legacy-root-single
eslint-v8_57-flat-package-local-monorepo -> breaks on main
eslint-v8_57-flat-root-single
eslint-v8_57-legacy-root-single
eslint-v9_0-flat-package-local-monorepo
eslint-v9_0-flat-root-single
eslint-v9_0-legacy-root-single -> breaks on main
eslint-v10_0-flat-package-local-monorepo
eslint-v10_0-flat-root-single -> breaks on main
```
## vscode-eslint 3.x upgrade
```text
eslint-v8_21-flat-root-single
eslint-v8_56-flat-package-local-monorepo -> breaks on 3.x upgrade
eslint-v8_56-flat-root-single
eslint-v8_56-legacy-root-single
eslint-v8_57-flat-package-local-monorepo
eslint-v8_57-flat-root-single
eslint-v8_57-legacy-root-single
eslint-v9_0-flat-package-local-monorepo
eslint-v9_0-flat-root-single
eslint-v9_0-legacy-root-single -> breaks on 3.x upgrade
eslint-v10_0-flat-package-local-monorepo
eslint-v10_0-flat-root-single -> breaks on 3.x upgrade
```
## vscode-eslint 3.x upgrade + use flat config fixes
```text
eslint-v8_21-flat-root-single
eslint-v8_56-flat-package-local-monorepo
eslint-v8_56-flat-root-single
eslint-v8_56-legacy-root-single
eslint-v8_57-flat-package-local-monorepo
eslint-v8_57-flat-root-single
eslint-v8_57-legacy-root-single
eslint-v9_0-flat-package-local-monorepo
eslint-v9_0-flat-root-single
eslint-v9_0-legacy-root-single
eslint-v10_0-flat-package-local-monorepo
eslint-v10_0-flat-root-single
```
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
Release Notes:
- Fixed ESLint not reporting diagnostics in some cases for projects that
use flat-config, legacy-config, and monorepo projects across ESLint 8,
9, and 10.
Closes
https://github.com/zed-industries/zed/issues/19709#issuecomment-3494789304
Closes
https://github.com/zed-industries/zed/issues/24194#issuecomment-2835787560
This PR fixes case where if eslint cached install is partial or stale,
Zed can try to launch a missing `eslintServer.js` and the server crashes
with `MODULE_NOT_FOUND`.
```
Error: Cannot find module '/Users/.../languages/eslint/vscode-eslint-2.4.4/vscode-eslint/server/out/eslintServer.js'
```
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
Release Notes:
- Fixed ESLint server startup failures caused by reusing an incomplete
or stale cached server install.
The watcher had been broken for some time, but became even more broken
after the recent move of the queries.
This PR restores the reloading behavior for debug builds so that
languages are reloaded once a scheme file is changed.
Release Notes:
- N/A
This extracts a `language_core` crate from the existing `language`
crate, and creates a `grammars` data crate. The goal is to separate
tree-sitter grammar infrastructure, language configuration, and LSP
adapter types from the heavier buffer/editor integration layer in
`language`.
## Motivation
The `language` crate pulls in `text`, `theme`, `settings`, `rpc`,
`task`, `fs`, `clock`, `sum_tree`, and `fuzzy` — all of which are needed
for buffer integration (`Buffer`, `SyntaxMap`, `Outline`,
`DiagnosticSet`) but not for grammar parsing or language configuration.
Extracting the core types lets downstream consumers depend on
`language_core` without pulling in the full integration stack.
## Dependency graph after extraction
```
language_core ← gpui, lsp, tree-sitter, util, collections
grammars ← language_core, rust_embed, tree-sitter-{rust,python,...}
language ← language_core, text, theme, settings, rpc, task, fs, ...
languages ← language, grammars
```
## What moved to `language_core`
- `Grammar`, `GrammarId`, and all query config/builder types
- `LanguageConfig`, `LanguageMatcher`, bracket/comment/indent config
types
- `HighlightMap`, `HighlightId` (theme-dependent free functions
`highlight_style` and `highlight_name` stay in `language`)
- `LanguageName`, `LanguageId`
- `LanguageQueries`, `QUERY_FILENAME_PREFIXES`
- `CodeLabel`, `CodeLabelBuilder`, `Symbol`
- `Diagnostic`, `DiagnosticSourceKind`
- `Toolchain`, `ToolchainScope`, `ToolchainList`, `ToolchainMetadata`
- `ManifestName`
- `SoftWrap`
- LSP data types: `BinaryStatus`, `ServerHealth`,
`LanguageServerStatusUpdate`, `PromptResponseContext`, `ToLspPosition`
## What stays in `language`
- `Buffer`, `BufferSnapshot`, `SyntaxMap`, `Outline`, `DiagnosticSet`,
`LanguageScope`
- `LspAdapter`, `CachedLspAdapter`, `LspAdapterDelegate` (reference
`Arc<Language>` and `WorktreeId`)
- `ToolchainLister`, `LanguageToolchainStore` (reference `task` and
`settings` types)
- `ManifestQuery`, `ManifestProvider`, `ManifestDelegate` (reference
`WorktreeId`)
- Parser/query cursor pools, `PLAIN_TEXT`, point conversion functions
## What the `grammars` crate provides
- Embedded `.scm` query files and `config.toml` files for all built-in
languages (via `rust_embed`)
- `load_queries(name)`, `load_config(name)`,
`load_config_for_feature(name, grammars_loaded)`, and `get_file(path)`
functions
- `native_grammars()` for tree-sitter grammar registration (behind
`load-grammars` feature)
## Pre-cleanup (also in this PR)
- Removed unused `Option<&Buffer>` from
`LspAdapter::process_diagnostics`
- Removed unused `&App` from `LspAdapter::retain_old_diagnostic`
- Removed `fs: &dyn Fs` from `ToolchainLister` trait methods
(`PythonToolchainProvider` captures `fs` at construction time instead)
- Moved `Diagnostic`/`DiagnosticSourceKind` out of `buffer.rs` into
their own module
## Backward compatibility
The `language` crate re-exports everything from `language_core`, so
existing `use language::Grammar` (etc.) continues to work unchanged. The
only downstream change required is importing `CodeLabelExt` where
`.fallback_for_completion()` is called on the now-foreign `CodeLabel`
type.
Release Notes:
- N/A
---------
Co-authored-by: Agus Zubiaga <agus@zed.dev>
Co-authored-by: Tom Houlé <tom@tomhoule.com>
- zed-extensions/elixir#61 renames `HEEX` to `HEEx`; to prevent any
disruptions from that change, this adds the correct name alongside a
settings migration
- zed-extensions/elixir#101 adds support for `EEx` templates; this sets
the default language server to be the same as that of `Elixir` and
`HEEx`
This also adds a few more extensions that should be recognized as `HEEx`
files
Release Notes:
- N/A
---------
Co-authored-by: Finn Evers <finn@zed.dev>
## Context
Closes#52391
gopls sends semantic tokens for format args with [format] modifier.
Without a simple support for there is no special highlighting for format
args like `%s`. Its a simple change inside
`go/semantic_token_rules.json` that makes this a default behavior.
Currently (on 0.229 preview):
<img width="1136" height="675" alt="Screenshot 2026-03-25 at 11 34 57"
src="https://github.com/user-attachments/assets/cd3d9a52-6740-47b5-8f05-02514cb4f9df"
/>
After fix:
<img width="1136" height="675" alt="Screenshot 2026-03-25 at 11 58 37"
src="https://github.com/user-attachments/assets/5ec4277b-39c1-4fe1-bed5-8a6fa63c18c9"
/>
## Self-Review Checklist
<!-- Check before requesting review: -->
- [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
Release Notes:
- gopls: Add semantic token rule for format string interpolations
## Summary
- Added `TarBz2` variant to `AssetKind` enum for `.tar.bz2` / `.tbz2`
archives
- Implemented `extract_tar_bz2` using the `bzip2` feature of
`async-compression` (already a workspace dependency, just enabled the
feature flag)
- Wired up both streaming and file-based extraction paths in
`github_download.rs`
- Added `.tar.bz2` / `.tbz2` URL detection in both
`LocalExtensionArchiveAgent` and `LocalRegistryArchiveAgent`
This unblocks ACP registry entries (like Goose) that only ship
`.tar.bz2` archives.
Reference: https://github.com/block/goose/issues/8047
## Test plan
- [ ] Verify `cargo check` and `clippy` pass (confirmed locally)
- [ ] Test downloading an ACP agent that ships a `.tar.bz2` archive
(e.g., Goose)
- [ ] Verify existing `.tar.gz` and `.zip` agent downloads still work
Release Notes:
- Added support for `.tar.bz2` archives in ACP agent server downloads,
unblocking registry entries like Goose that only ship bzip2-compressed
tarballs.
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Many editors such as vim and emacs support "modelines", a comment at the
beginning of the file that allows the file type to be explicitly
specified along with per-file specific settings
- The amount of configurations, style and settings mapping cannot be
handled in one go, so this opens up a lot of potential improvements.
- I left out the possiblity to have "zed" specific modelines for now,
but this could be potentially interesting.
- Mapping the mode or filetype to zed language names isn't obvious
either. We may want to make it configurable.
This is my first contribution to zed, be kind. I struggled a bit to find
the right place to add those settings. I use a similar approach as done
with editorconfig (merge_with_editorconfig). There might be better ways.
Closes#4762
Release Notes:
- Add basic emacs/vim modeline support.
Supersedes #41899, changes:
- limit reading to the first and last 1kb
- add documentation
- more variables handled
- add Arc around ModelineSettings to avoid extra cloning
- changed the way mode -> language mapping is done, thanks to
`modeline_aliases` language config
- drop vim ex: support
- made "Local Variables:" handling a separate commit, so we can drop it
easily
- various code style improvements
---------
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
## Context
Recently, we put bsn in the list of "macros to not reparse as rust"
(#51353).
We have since updated tree-sitter-rust to better handle the `@"string"`,
`:"string"`, etc cases, and can un-list bsn from the special casing.
on main, the highlighting currently looks like this for `bsn` and for
`not` (represents "other macros"). Note the `:"player.bsn"` string is
re-parsed as rust tokens.
<img width="1728" height="1084" alt="Screenshot 2026-03-23 at 9 33
35 AM"
src="https://github.com/user-attachments/assets/94ea5a6d-228b-44dd-857b-c41edcbd9af0"
/>
This pr, plus the tree-sitter-rust updates results in better handling by
default.
<img width="1728" height="1084" alt="Screenshot 2026-03-23 at 11 38
47 AM"
src="https://github.com/user-attachments/assets/fb6f71e3-7bcf-4c06-8e84-ce0823010b2e"
/>
Release Notes:
- N/A
## Context
Zed's semantic token highlighting does not cover all token types
returned by language servers, so the highlighting looks fairly primitive
compared with tree-sitter highlighting, especially for Python language
servers. This PR adds some global and Python-specific rules for better
highlighting.
I need to admit that the built-in Python language servers currently have
weak semantic highlighting implementations. Pylance, the closed-source
Python language server from Microsoft, provides the best highlighting
for now, but I think ty will do better, even though it still has a long
way to go.
## How to Review
Basically, this is a rule-adding change. Some rules are made global, and
some are made Python-specific.
## Self-Review Checklist
<!-- Check before requesting review: -->
- [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
Release Notes:
- Improved semantic token highlighting for parameters and Python
## Context
Fixes https://github.com/zed-industries/zed/issues/51921
`await` was grouped under the generic `@keyword` capture in the
tree-sitter highlights queries for JavaScript, TypeScript, and TSX. It
should be `@keyword.control`, since it's a control flow keyword — same
as `return`, `yield`, `throw`, `break`, etc., which were already
correctly classified.
This aligns Zed's highlighting with VSCode's behavior, where `await` is
tokenized as `keyword.control`.
## How to Review
Three single-line moves across highlights files — `await` removed from
the `@keyword` list, added to the `@keyword.control` list:
1. `crates/languages/src/javascript/highlights.scm`
2. `crates/languages/src/typescript/highlights.scm`
3. `crates/languages/src/tsx/highlights.scm`
## 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](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
## Image :
<img width="3072" height="1728" alt="Screenshot from 2026-03-20
22-15-40"
src="https://github.com/user-attachments/assets/9e849d4d-dad4-4fa0-b3b8-8e633f96c585"
/>
Release Notes:
- Fixed `await` keyword not being highlighted as `keyword.control` in
JavaScript, TypeScript, and TSX files
---------
Co-authored-by: Kunall Banerjee <hey@kimchiii.space>
This PR updates the pet dependency to incorporate performance
improvements from upstream.
Related Upstream Changes:
- Issue: microsoft/python-environment-tools#369
- PR: microsoft/python-environment-tools#370
Updating pet reduces toolchain discovery time in WSL environments,
specifically when Conda is installed on the host Windows system. In my
testing, the time from clicking the toolchain button to the list
appearing was reduced by approximately 2 seconds.
While this is a notable improvement, discovery in WSL remains slightly
slower than in native development or remote Linux environments, where
toolchains are typically loaded near-instantaneously.
Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing (no need)
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
Release Notes:
- Improved python toolchain discovery under WSL environment