Support tasks from rust-analyzer (#28359)

(and any other LSP server in theory, if it exposes any LSP-ext endpoint
for the same)

Closes https://github.com/zed-industries/zed/issues/16160

* adds a way to disable tree-sitter tasks (the ones from the plugins,
enabled by default) with
```json5
"languages": {
  "Rust": "tasks": {
      "enabled": false
    }
  }
}
```
language settings

* adds a way to disable LSP tasks (the ones from the rust-analyzer
language server, enabled by default) with
```json5
"lsp": {
  "rust-analyzer": {
    "enable_lsp_tasks": false,
  }
}
```

* adds rust-analyzer tasks into tasks modal and gutter:

<img width="1728" alt="modal"
src="https://github.com/user-attachments/assets/22b9cee1-4ffb-4c9e-b1f1-d01e80e72508"
/>

<img width="396" alt="gutter"
src="https://github.com/user-attachments/assets/bd818079-e247-4332-bdb5-1b7cb1cce768"
/>


Release Notes:

- Added tasks from rust-analyzer
This commit is contained in:
Kirill Bulatov 2025-04-08 15:07:56 -06:00 committed by GitHub
parent 763cc6dba3
commit 39c98ce882
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 882 additions and 201 deletions

View file

@ -1,7 +1,7 @@
use anyhow::{Context, Result, anyhow, bail};
use async_trait::async_trait;
use futures::StreamExt;
use gpui::AsyncApp;
use gpui::{App, AsyncApp};
use http_client::github::{GitHubLspBinaryVersion, latest_github_release};
pub use language::*;
use lsp::{DiagnosticTag, InitializeParams, LanguageServerBinary, LanguageServerName};
@ -273,6 +273,7 @@ impl super::LspAdapter for CLspAdapter {
fn prepare_initialize_params(
&self,
mut original: InitializeParams,
_: &App,
) -> Result<InitializeParams> {
let experimental = json!({
"textDocument": {

View file

@ -7,8 +7,11 @@ use gpui::{App, AsyncApp, SharedString, Task};
use http_client::github::AssetKind;
use http_client::github::{GitHubLspBinaryVersion, latest_github_release};
pub use language::*;
use lsp::LanguageServerBinary;
use lsp::{InitializeParams, LanguageServerBinary};
use project::project_settings::ProjectSettings;
use regex::Regex;
use serde_json::json;
use settings::Settings as _;
use smol::fs::{self};
use std::fmt::Display;
use std::{
@ -18,6 +21,7 @@ use std::{
sync::{Arc, LazyLock},
};
use task::{TaskTemplate, TaskTemplates, TaskType, TaskVariables, VariableName};
use util::merge_json_value_into;
use util::{ResultExt, fs::remove_matching, maybe};
use crate::language_settings::language_settings;
@ -48,9 +52,9 @@ impl RustLspAdapter {
const ARCH_SERVER_NAME: &str = "pc-windows-msvc";
}
impl RustLspAdapter {
const SERVER_NAME: LanguageServerName = LanguageServerName::new_static("rust-analyzer");
const SERVER_NAME: LanguageServerName = LanguageServerName::new_static("rust-analyzer");
impl RustLspAdapter {
fn build_asset_name() -> String {
let extension = match Self::GITHUB_ASSET_KIND {
AssetKind::TarGz => "tar.gz",
@ -60,7 +64,7 @@ impl RustLspAdapter {
format!(
"{}-{}-{}.{}",
Self::SERVER_NAME,
SERVER_NAME,
std::env::consts::ARCH,
Self::ARCH_SERVER_NAME,
extension
@ -98,7 +102,7 @@ impl ManifestProvider for CargoManifestProvider {
#[async_trait(?Send)]
impl LspAdapter for RustLspAdapter {
fn name(&self) -> LanguageServerName {
Self::SERVER_NAME.clone()
SERVER_NAME.clone()
}
fn manifest_name(&self) -> Option<ManifestName> {
@ -473,6 +477,30 @@ impl LspAdapter for RustLspAdapter {
filter_range,
})
}
fn prepare_initialize_params(
&self,
mut original: InitializeParams,
cx: &App,
) -> Result<InitializeParams> {
let enable_lsp_tasks = ProjectSettings::get_global(cx)
.lsp
.get(&SERVER_NAME)
.map_or(false, |s| s.enable_lsp_tasks);
if enable_lsp_tasks {
let experimental = json!({
"runnables": {
"kinds": [ "cargo", "shell" ],
},
});
if let Some(ref mut original_experimental) = original.capabilities.experimental {
merge_json_value_into(experimental, original_experimental);
} else {
original.capabilities.experimental = Some(experimental);
}
}
Ok(original)
}
}
pub(crate) struct RustContextProvider;
@ -776,6 +804,10 @@ impl ContextProvider for RustContextProvider {
Some(TaskTemplates(task_templates))
}
fn lsp_task_source(&self) -> Option<LanguageServerName> {
Some(SERVER_NAME)
}
}
/// Part of the data structure of Cargo metadata