tasks: Add ability to query active toolchains for languages (#20667)

Closes #18649

Release Notes:

- Python tasks now use active toolchain to run.
This commit is contained in:
Piotr Osiewicz 2024-11-14 14:37:37 +01:00 committed by GitHub
parent 04ba75e2e5
commit 89f9a506f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 170 additions and 103 deletions

View file

@ -418,9 +418,10 @@ impl ContextProvider for GoContextProvider {
&self,
variables: &TaskVariables,
location: &Location,
_: Option<&HashMap<String, String>>,
_: Option<HashMap<String, String>>,
_: Arc<dyn LanguageToolchainStore>,
cx: &mut gpui::AppContext,
) -> Result<TaskVariables> {
) -> Task<Result<TaskVariables>> {
let local_abs_path = location
.buffer
.read(cx)
@ -468,7 +469,7 @@ impl ContextProvider for GoContextProvider {
let go_subtest_variable = extract_subtest_name(_subtest_name.unwrap_or(""))
.map(|subtest_name| (GO_SUBTEST_NAME_TASK_VARIABLE.clone(), subtest_name));
Ok(TaskVariables::from_iter(
Task::ready(Ok(TaskVariables::from_iter(
[
go_package_variable,
go_subtest_variable,
@ -476,7 +477,7 @@ impl ContextProvider for GoContextProvider {
]
.into_iter()
.flatten(),
))
)))
}
fn associated_tasks(

View file

@ -2,8 +2,8 @@ use anyhow::ensure;
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use collections::HashMap;
use gpui::AppContext;
use gpui::AsyncAppContext;
use gpui::{AppContext, Task};
use language::LanguageName;
use language::LanguageToolchainStore;
use language::Toolchain;
@ -267,14 +267,17 @@ pub(crate) struct PythonContextProvider;
const PYTHON_UNITTEST_TARGET_TASK_VARIABLE: VariableName =
VariableName::Custom(Cow::Borrowed("PYTHON_UNITTEST_TARGET"));
const PYTHON_ACTIVE_TOOLCHAIN_PATH: VariableName =
VariableName::Custom(Cow::Borrowed("PYTHON_ACTIVE_ZED_TOOLCHAIN"));
impl ContextProvider for PythonContextProvider {
fn build_context(
&self,
variables: &task::TaskVariables,
_location: &project::Location,
_: Option<&HashMap<String, String>>,
_cx: &mut gpui::AppContext,
) -> Result<task::TaskVariables> {
location: &project::Location,
_: Option<HashMap<String, String>>,
toolchains: Arc<dyn LanguageToolchainStore>,
cx: &mut gpui::AppContext,
) -> Task<Result<task::TaskVariables>> {
let python_module_name = python_module_name_from_relative_path(
variables.get(&VariableName::RelativeFile).unwrap_or(""),
);
@ -290,15 +293,26 @@ impl ContextProvider for PythonContextProvider {
}
(Some(class_name), None) => format!("{}.{}", python_module_name, class_name),
(None, None) => python_module_name,
(None, Some(_)) => return Ok(task::TaskVariables::default()), // should never happen, a TestCase class is the unit of testing
(None, Some(_)) => return Task::ready(Ok(task::TaskVariables::default())), // should never happen, a TestCase class is the unit of testing
};
let unittest_target = (
PYTHON_UNITTEST_TARGET_TASK_VARIABLE.clone(),
unittest_target_str,
);
Ok(task::TaskVariables::from_iter([unittest_target]))
let worktree_id = location.buffer.read(cx).file().map(|f| f.worktree_id(cx));
cx.spawn(move |mut cx| async move {
let active_toolchain = if let Some(worktree_id) = worktree_id {
toolchains
.active_toolchain(worktree_id, "Python".into(), &mut cx)
.await
.map_or_else(|| "python3".to_owned(), |toolchain| toolchain.path.into())
} else {
String::from("python3")
};
let toolchain = (PYTHON_ACTIVE_TOOLCHAIN_PATH, active_toolchain);
Ok(task::TaskVariables::from_iter([unittest_target, toolchain]))
})
}
fn associated_tasks(
@ -309,19 +323,19 @@ impl ContextProvider for PythonContextProvider {
Some(TaskTemplates(vec![
TaskTemplate {
label: "execute selection".to_owned(),
command: "python3".to_owned(),
command: PYTHON_ACTIVE_TOOLCHAIN_PATH.template_value(),
args: vec!["-c".to_owned(), VariableName::SelectedText.template_value()],
..TaskTemplate::default()
},
TaskTemplate {
label: format!("run '{}'", VariableName::File.template_value()),
command: "python3".to_owned(),
command: PYTHON_ACTIVE_TOOLCHAIN_PATH.template_value(),
args: vec![VariableName::File.template_value()],
..TaskTemplate::default()
},
TaskTemplate {
label: format!("unittest '{}'", VariableName::File.template_value()),
command: "python3".to_owned(),
command: PYTHON_ACTIVE_TOOLCHAIN_PATH.template_value(),
args: vec![
"-m".to_owned(),
"unittest".to_owned(),
@ -331,7 +345,7 @@ impl ContextProvider for PythonContextProvider {
},
TaskTemplate {
label: "unittest $ZED_CUSTOM_PYTHON_UNITTEST_TARGET".to_owned(),
command: "python3".to_owned(),
command: PYTHON_ACTIVE_TOOLCHAIN_PATH.template_value(),
args: vec![
"-m".to_owned(),
"unittest".to_owned(),

View file

@ -3,7 +3,7 @@ use async_compression::futures::bufread::GzipDecoder;
use async_trait::async_trait;
use collections::HashMap;
use futures::{io::BufReader, StreamExt};
use gpui::{AppContext, AsyncAppContext};
use gpui::{AppContext, AsyncAppContext, Task};
use http_client::github::AssetKind;
use http_client::github::{latest_github_release, GitHubLspBinaryVersion};
pub use language::*;
@ -424,9 +424,10 @@ impl ContextProvider for RustContextProvider {
&self,
task_variables: &TaskVariables,
location: &Location,
project_env: Option<&HashMap<String, String>>,
project_env: Option<HashMap<String, String>>,
_: Arc<dyn LanguageToolchainStore>,
cx: &mut gpui::AppContext,
) -> Result<TaskVariables> {
) -> Task<Result<TaskVariables>> {
let local_abs_path = location
.buffer
.read(cx)
@ -440,27 +441,27 @@ impl ContextProvider for RustContextProvider {
.is_some();
if is_main_function {
if let Some((package_name, bin_name)) = local_abs_path
.and_then(|path| package_name_and_bin_name_from_abs_path(path, project_env))
{
return Ok(TaskVariables::from_iter([
if let Some((package_name, bin_name)) = local_abs_path.and_then(|path| {
package_name_and_bin_name_from_abs_path(path, project_env.as_ref())
}) {
return Task::ready(Ok(TaskVariables::from_iter([
(RUST_PACKAGE_TASK_VARIABLE.clone(), package_name),
(RUST_BIN_NAME_TASK_VARIABLE.clone(), bin_name),
]));
])));
}
}
if let Some(package_name) = local_abs_path
.and_then(|local_abs_path| local_abs_path.parent())
.and_then(|path| human_readable_package_name(path, project_env))
.and_then(|path| human_readable_package_name(path, project_env.as_ref()))
{
return Ok(TaskVariables::from_iter([(
return Task::ready(Ok(TaskVariables::from_iter([(
RUST_PACKAGE_TASK_VARIABLE.clone(),
package_name,
)]));
)])));
}
Ok(TaskVariables::default())
Task::ready(Ok(TaskVariables::default()))
}
fn associated_tasks(