From 460ac96df4496a55dddaba6cc23da89be051ea70 Mon Sep 17 00:00:00 2001 From: Stanislav Alekseev <43210583+WeetHet@users.noreply.github.com> Date: Fri, 2 May 2025 14:01:39 +0300 Subject: [PATCH] Use project environment in LSP runnables context (#29761) Release Notes: - Fixed the tasks from LSP not inheriting the worktree environment ---- cc @SomeoneToIgnore --- crates/editor/src/lsp_ext.rs | 41 +++++++++++++++++++++++++++++-- crates/project/src/environment.rs | 4 +-- crates/project/src/lsp_store.rs | 2 +- crates/project/src/project.rs | 13 +++++++++- crates/project/src/task_store.rs | 6 +---- 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/crates/editor/src/lsp_ext.rs b/crates/editor/src/lsp_ext.rs index fb3158a720783fcd5438bb50319759c90119fd7d..6c22ba505e228b6ed17a676354f4f91ecb765ffb 100644 --- a/crates/editor/src/lsp_ext.rs +++ b/crates/editor/src/lsp_ext.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use crate::Editor; use collections::HashMap; use futures::stream::FuturesUnordered; +use gpui::AsyncApp; use gpui::{App, AppContext as _, Entity, Task}; use itertools::Itertools; use language::Buffer; @@ -74,6 +75,39 @@ where }) } +async fn lsp_task_context( + project: &Entity, + buffer: &Entity, + cx: &mut AsyncApp, +) -> Option { + let worktree_store = project + .update(cx, |project, _| project.worktree_store()) + .ok()?; + + let worktree_abs_path = cx + .update(|cx| { + let worktree_id = buffer.read(cx).file().map(|f| f.worktree_id(cx)); + + worktree_id + .and_then(|worktree_id| worktree_store.read(cx).worktree_for_id(worktree_id, cx)) + .and_then(|worktree| worktree.read(cx).root_dir()) + }) + .ok()?; + + let project_env = project + .update(cx, |project, cx| { + project.buffer_environment(&buffer, &worktree_store, cx) + }) + .ok()? + .await; + + Some(TaskContext { + cwd: worktree_abs_path.map(|p| p.to_path_buf()), + project_env: project_env.unwrap_or_default(), + ..TaskContext::default() + }) +} + pub fn lsp_tasks( project: Entity, task_sources: &HashMap>, @@ -97,13 +131,16 @@ pub fn lsp_tasks( cx.spawn(async move |cx| { let mut lsp_tasks = Vec::new(); - let lsp_task_context = TaskContext::default(); while let Some(server_to_query) = lsp_task_sources.next().await { if let Some((server_id, buffers)) = server_to_query { let source_kind = TaskSourceKind::Lsp(server_id); let id_base = source_kind.to_id_base(); let mut new_lsp_tasks = Vec::new(); for buffer in buffers { + let lsp_buffer_context = lsp_task_context(&project, &buffer, cx) + .await + .unwrap_or_default(); + if let Ok(runnables_task) = project.update(cx, |project, cx| { let buffer_id = buffer.read(cx).remote_id(); project.request_lsp( @@ -120,7 +157,7 @@ pub fn lsp_tasks( new_lsp_tasks.extend(new_runnables.runnables.into_iter().filter_map( |(location, runnable)| { let resolved_task = - runnable.resolve_task(&id_base, &lsp_task_context)?; + runnable.resolve_task(&id_base, &lsp_buffer_context)?; Some((location, resolved_task)) }, )); diff --git a/crates/project/src/environment.rs b/crates/project/src/environment.rs index dfb1114a37d36e7e26ec224c7bc5449c2d32a2af..f3bf43e708c3e938a97117044974d815cec99c9e 100644 --- a/crates/project/src/environment.rs +++ b/crates/project/src/environment.rs @@ -59,8 +59,8 @@ impl ProjectEnvironment { pub(crate) fn get_buffer_environment( &mut self, - buffer: Entity, - worktree_store: Entity, + buffer: &Entity, + worktree_store: &Entity, cx: &mut Context, ) -> Shared>>> { if cfg!(any(test, feature = "test-support")) { diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index d46c60654ff08d1f17d1901c90cfca3d5fb66ae2..07a9d3212efe975575525131dfeca6af15aa0923 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -8190,7 +8190,7 @@ impl LspStore { ) -> Shared>>> { if let Some(environment) = &self.as_local().map(|local| local.environment.clone()) { environment.update(cx, |env, cx| { - env.get_buffer_environment(buffer.clone(), self.worktree_store.clone(), cx) + env.get_buffer_environment(&buffer, &self.worktree_store, cx) }) } else { Task::ready(None).shared() diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 314634c63abb4ddbc37d543ace6bef5c7d8c349e..54a040e4741c4224a2152ad1019491072d045996 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -56,7 +56,7 @@ use futures::future::join_all; use futures::{ StreamExt, channel::mpsc::{self, UnboundedReceiver}, - future::try_join_all, + future::{Shared, try_join_all}, }; pub use image_store::{ImageItem, ImageStore}; use image_store::{ImageItemEvent, ImageStoreEvent}; @@ -1605,6 +1605,17 @@ impl Project { self.environment.read(cx).get_cli_environment() } + pub fn buffer_environment<'a>( + &'a self, + buffer: &Entity, + worktree_store: &Entity, + cx: &'a mut App, + ) -> Shared>>> { + self.environment.update(cx, |environment, cx| { + environment.get_buffer_environment(&buffer, &worktree_store, cx) + }) + } + pub fn shell_environment_errors<'a>( &'a self, cx: &'a App, diff --git a/crates/project/src/task_store.rs b/crates/project/src/task_store.rs index 331f956018bdb85aacdb9ef2e48cd85330fb1bf2..c85cd05e663e880ebb4f4a116bd0dca3b80d8de1 100644 --- a/crates/project/src/task_store.rs +++ b/crates/project/src/task_store.rs @@ -315,11 +315,7 @@ fn local_task_context_for_location( cx.spawn(async move |cx| { let project_env = environment .update(cx, |environment, cx| { - environment.get_buffer_environment( - location.buffer.clone(), - worktree_store.clone(), - cx, - ) + environment.get_buffer_environment(&location.buffer, &worktree_store, cx) }) .ok()? .await;