languages: Allow installing pre-release of rust-analyzer and clangd (#37530)

Release Notes:

- Added lsp binary config to allow fetching nightly rust-analyzer and
clangd releases
This commit is contained in:
Lukas Wirth
2025-09-04 09:22:19 +00:00
committed by GitHub
parent b7ad20773c
commit fca44f89c1
17 changed files with 87 additions and 11 deletions
+4
View File
@@ -16783,6 +16783,7 @@ async fn test_language_server_restart_due_to_settings_change(cx: &mut TestAppCon
"some other init value": false
})),
enable_lsp_tasks: false,
fetch: None,
},
);
});
@@ -16803,6 +16804,7 @@ async fn test_language_server_restart_due_to_settings_change(cx: &mut TestAppCon
"anotherInitValue": false
})),
enable_lsp_tasks: false,
fetch: None,
},
);
});
@@ -16823,6 +16825,7 @@ async fn test_language_server_restart_due_to_settings_change(cx: &mut TestAppCon
"anotherInitValue": false
})),
enable_lsp_tasks: false,
fetch: None,
},
);
});
@@ -16841,6 +16844,7 @@ async fn test_language_server_restart_due_to_settings_change(cx: &mut TestAppCon
settings: None,
initialization_options: None,
enable_lsp_tasks: false,
fetch: None,
},
);
});
+3 -1
View File
@@ -395,6 +395,7 @@ pub trait LspAdapter: 'static + Send + Sync {
async fn fetch_latest_server_version(
&self,
delegate: &dyn LspAdapterDelegate,
cx: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>>;
fn will_fetch_server(
@@ -605,7 +606,7 @@ async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>
delegate.update_status(name.clone(), BinaryStatus::CheckingForUpdate);
let latest_version = adapter
.fetch_latest_server_version(delegate.as_ref())
.fetch_latest_server_version(delegate.as_ref(), cx)
.await?;
if let Some(binary) = adapter
@@ -2222,6 +2223,7 @@ impl LspAdapter for FakeLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
unreachable!();
}
@@ -204,6 +204,7 @@ impl LspAdapter for ExtensionLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
unreachable!("get_language_server_command is overridden")
}
+14 -3
View File
@@ -5,8 +5,9 @@ use gpui::{App, AsyncApp};
use http_client::github::{AssetKind, GitHubLspBinaryVersion, latest_github_release};
pub use language::*;
use lsp::{InitializeParams, LanguageServerBinary, LanguageServerName};
use project::lsp_store::clangd_ext;
use project::{lsp_store::clangd_ext, project_settings::ProjectSettings};
use serde_json::json;
use settings::Settings as _;
use smol::fs;
use std::{any::Any, env::consts, path::PathBuf, sync::Arc};
use util::{ResultExt, fs::remove_matching, maybe, merge_json_value_into};
@@ -42,9 +43,19 @@ impl super::LspAdapter for CLspAdapter {
async fn fetch_latest_server_version(
&self,
delegate: &dyn LspAdapterDelegate,
cx: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
let release =
latest_github_release("clangd/clangd", true, false, delegate.http_client()).await?;
let release = latest_github_release(
"clangd/clangd",
true,
ProjectSettings::try_read_global(cx, |s| {
s.lsp.get(&Self::SERVER_NAME)?.fetch.as_ref()?.pre_release
})
.flatten()
.unwrap_or(false),
delegate.http_client(),
)
.await?;
let os_suffix = match consts::OS {
"macos" => "mac",
"linux" => "linux",
+1
View File
@@ -61,6 +61,7 @@ impl LspAdapter for CssLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Any + Send>> {
Ok(Box::new(
self.node
+1
View File
@@ -59,6 +59,7 @@ impl super::LspAdapter for GoLspAdapter {
async fn fetch_latest_server_version(
&self,
delegate: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
let release =
latest_github_release("golang/tools", false, false, delegate.http_client()).await?;
+2
View File
@@ -321,6 +321,7 @@ impl LspAdapter for JsonLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
Ok(Box::new(
self.node
@@ -494,6 +495,7 @@ impl LspAdapter for NodeVersionAdapter {
async fn fetch_latest_server_version(
&self,
delegate: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
let release = latest_github_release(
"zed-industries/package-version-server",
+3
View File
@@ -157,6 +157,7 @@ impl LspAdapter for PythonLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Any + Send>> {
Ok(Box::new(
self.node
@@ -1111,6 +1112,7 @@ impl LspAdapter for PyLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Any + Send>> {
Ok(Box::new(()) as Box<_>)
}
@@ -1422,6 +1424,7 @@ impl LspAdapter for BasedPyrightLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Any + Send>> {
Ok(Box::new(()) as Box<_>)
}
+6 -1
View File
@@ -147,11 +147,16 @@ impl LspAdapter for RustLspAdapter {
async fn fetch_latest_server_version(
&self,
delegate: &dyn LspAdapterDelegate,
cx: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
let release = latest_github_release(
"rust-lang/rust-analyzer",
true,
false,
ProjectSettings::try_read_global(cx, |s| {
s.lsp.get(&SERVER_NAME)?.fetch.as_ref()?.pre_release
})
.flatten()
.unwrap_or(false),
delegate.http_client(),
)
.await?;
+1
View File
@@ -66,6 +66,7 @@ impl LspAdapter for TailwindLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Any + Send>> {
Ok(Box::new(
self.node
+2
View File
@@ -563,6 +563,7 @@ impl LspAdapter for TypeScriptLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
Ok(Box::new(TypeScriptVersions {
typescript_version: self.node.npm_package_latest_version("typescript").await?,
@@ -885,6 +886,7 @@ impl LspAdapter for EsLintLspAdapter {
async fn fetch_latest_server_version(
&self,
_delegate: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
let url = build_asset_url(
"zed-industries/vscode-eslint",
+1
View File
@@ -73,6 +73,7 @@ impl LspAdapter for VtslsLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
Ok(Box::new(TypeScriptVersions {
typescript_version: self.node.npm_package_latest_version("typescript").await?,
+1
View File
@@ -44,6 +44,7 @@ impl LspAdapter for YamlLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Any + Send>> {
Ok(Box::new(
self.node
+1
View File
@@ -13070,6 +13070,7 @@ impl LspAdapter for SshLspAdapter {
async fn fetch_latest_server_version(
&self,
_: &dyn LspAdapterDelegate,
_: &AsyncApp,
) -> Result<Box<dyn 'static + Send + Any>> {
anyhow::bail!("SshLspAdapter does not support fetch_latest_server_version")
}
+8
View File
@@ -516,6 +516,12 @@ pub struct BinarySettings {
pub ignore_system_version: Option<bool>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Hash)]
pub struct FetchSettings {
// Whether to consider pre-releases for fetching
pub pre_release: Option<bool>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Hash)]
#[serde(rename_all = "snake_case")]
pub struct LspSettings {
@@ -527,6 +533,7 @@ pub struct LspSettings {
/// Default: true
#[serde(default = "default_true")]
pub enable_lsp_tasks: bool,
pub fetch: Option<FetchSettings>,
}
impl Default for LspSettings {
@@ -536,6 +543,7 @@ impl Default for LspSettings {
initialization_options: None,
settings: None,
enable_lsp_tasks: true,
fetch: None,
}
}
}
+23 -5
View File
@@ -9,22 +9,23 @@ C++ support is available natively in Zed.
You can configure which `clangd` binary Zed should use.
To use a binary in a custom location, add the following to your `settings.json`:
By default, Zed will try to find a `clangd` in your `$PATH` and try to use that. If that binary successfully executes, it's used. Otherwise, Zed will fall back to installing its own `clangd` version and use that.
If you want to install a pre-release `clangd` version instead you can instruct Zed to do so by setting `pre_release` to `true` in your `settings.json`:
```json
{
"lsp": {
"clangd": {
"binary": {
"path": "/path/to/clangd",
"arguments": []
"fetch": {
"pre_release": true
}
}
}
}
```
If you want to disable Zed looking for a `clangd` binary, you can set `ignore_system_version` to `true`:
If you want to disable Zed looking for a `clangd` binary, you can set `ignore_system_version` to `true` in your `settings.json`:
```json
{
@@ -38,6 +39,23 @@ If you want to disable Zed looking for a `clangd` binary, you can set `ignore_sy
}
```
If you want to use a binary in a custom location, you can specify a `path` and optional `arguments`:
```json
{
"lsp": {
"cangd": {
"binary": {
"path": "/path/to/clangd",
"arguments": []
}
}
}
}
```
This `"path"` has to be an absolute path.
## Arguments
You can pass any number of arguments to clangd. To see a full set of available options, run `clangd --help` from the command line. For example with `--function-arg-placeholders=0` completions contain only parentheses for function calls, while the default (`--function-arg-placeholders=1`) completions also contain placeholders for method parameters.
+15 -1
View File
@@ -63,7 +63,21 @@ A `true` setting will set the target directory to `target/rust-analyzer`. You ca
You can configure which `rust-analyzer` binary Zed should use.
By default, Zed will try to find a `rust-analyzer` in your `$PATH` and try to use that. If that binary successfully executes `rust-analyzer --help`, it's used. Otherwise, Zed will fall back to installing its own `rust-analyzer` version and using that.
By default, Zed will try to find a `rust-analyzer` in your `$PATH` and try to use that. If that binary successfully executes `rust-analyzer --help`, it's used. Otherwise, Zed will fall back to installing its own stable `rust-analyzer` version and use that.
If you want to install pre-release `rust-analyzer` version instead you can instruct Zed to do so by setting `pre_release` to `true` in your `settings.json`:
```json
{
"lsp": {
"rust-analyzer": {
"fetch": {
"pre_release": true
}
}
}
}
```
If you want to disable Zed looking for a `rust-analyzer` binary, you can set `ignore_system_version` to `true` in your `settings.json`: