toolchains: Allow users to provide custom paths to toolchains (#37009)

- **toolchains: Add new state to toolchain selector**
- **Use toolchain term for Add Toolchain button**
- **Hoist out a meta function for toolchain listers**

Closes #27332

Release Notes:

- python: Users can now specify a custom path to their virtual
environment from within the picker.

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This commit is contained in:
Piotr Osiewicz
2025-09-06 00:47:39 +02:00
committed by GitHub
co-authored by Danilo Leal
parent 59bdbf5a5d
commit 6a7b84eb87
22 changed files with 1506 additions and 233 deletions
+1
View File
@@ -69,6 +69,7 @@ pub use text_diff::{
use theme::SyntaxTheme;
pub use toolchain::{
LanguageToolchainStore, LocalLanguageToolchainStore, Toolchain, ToolchainList, ToolchainLister,
ToolchainMetadata, ToolchainScope,
};
use tree_sitter::{self, Query, QueryCursor, WasmStore, wasmtime};
use util::serde::default_true;
+57 -5
View File
@@ -29,6 +29,40 @@ pub struct Toolchain {
pub as_json: serde_json::Value,
}
/// Declares a scope of a toolchain added by user.
///
/// When the user adds a toolchain, we give them an option to see that toolchain in:
/// - All of their projects
/// - A project they're currently in.
/// - Only in the subproject they're currently in.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum ToolchainScope {
Subproject(WorktreeId, Arc<Path>),
Project,
/// Available in all projects on this box. It wouldn't make sense to show suggestions across machines.
Global,
}
impl ToolchainScope {
pub fn label(&self) -> &'static str {
match self {
ToolchainScope::Subproject(_, _) => "Subproject",
ToolchainScope::Project => "Project",
ToolchainScope::Global => "Global",
}
}
pub fn description(&self) -> &'static str {
match self {
ToolchainScope::Subproject(_, _) => {
"Available only in the subproject you're currently in."
}
ToolchainScope::Project => "Available in all locations in your current project.",
ToolchainScope::Global => "Available in all of your projects on this machine.",
}
}
}
impl std::hash::Hash for Toolchain {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let Self {
@@ -58,23 +92,41 @@ impl PartialEq for Toolchain {
}
#[async_trait]
pub trait ToolchainLister: Send + Sync {
pub trait ToolchainLister: Send + Sync + 'static {
/// List all available toolchains for a given path.
async fn list(
&self,
worktree_root: PathBuf,
subroot_relative_path: Arc<Path>,
project_env: Option<HashMap<String, String>>,
) -> ToolchainList;
// Returns a term which we should use in UI to refer to a toolchain.
fn term(&self) -> SharedString;
/// Returns the name of the manifest file for this toolchain.
fn manifest_name(&self) -> ManifestName;
/// Given a user-created toolchain, resolve lister-specific details.
/// Put another way: fill in the details of the toolchain so the user does not have to.
async fn resolve(
&self,
path: PathBuf,
project_env: Option<HashMap<String, String>>,
) -> anyhow::Result<Toolchain>;
async fn activation_script(
&self,
toolchain: &Toolchain,
shell: ShellKind,
fs: &dyn Fs,
) -> Vec<String>;
/// Returns various "static" bits of information about this toolchain lister. This function should be pure.
fn meta(&self) -> ToolchainMetadata;
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct ToolchainMetadata {
/// Returns a term which we should use in UI to refer to toolchains produced by a given `[ToolchainLister]`.
pub term: SharedString,
/// A user-facing placeholder describing the semantic meaning of a path to a new toolchain.
pub new_toolchain_placeholder: SharedString,
/// The name of the manifest file for this toolchain.
pub manifest_name: ManifestName,
}
#[async_trait(?Send)]