124 lines · 4.0 KB · Rust
RawDownload
//! Provides core data types for language toolchains.//!//! A language can have associated toolchains,//! which is a set of tools used to interact with the projects written in said language.//! For example, a Python project can have an associated virtual environment; a Rust project can have a toolchain override. use std::{path::Path, sync::Arc}; use gpui_shared_string::SharedString;use util::rel_path::RelPath; use crate::{LanguageName, ManifestName}; /// Represents a single toolchain.#[derive(Clone, Eq, Debug)]pub struct Toolchain {    /// User-facing label    pub name: SharedString,    /// Absolute path    pub path: SharedString,    pub language_name: LanguageName,    /// Full toolchain data (including language-specific details)    pub as_json: serde_json::Value,} impl std::hash::Hash for Toolchain {    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {        let Self {            name,            path,            language_name,            as_json: _,        } = self;        name.hash(state);        path.hash(state);        language_name.hash(state);    }} impl PartialEq for Toolchain {    fn eq(&self, other: &Self) -> bool {        let Self {            name,            path,            language_name,            as_json: _,        } = self;        // Do not use as_json for comparisons; it shouldn't impact equality, as it's not user-surfaced.        // Thus, there could be multiple entries that look the same in the UI.        (name, path, language_name).eq(&(&other.name, &other.path, &other.language_name))    }} /// 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(Arc<Path>, Arc<RelPath>),    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.",        }    }} #[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,} type DefaultIndex = usize;#[derive(Default, Clone, Debug)]pub struct ToolchainList {    pub toolchains: Vec<Toolchain>,    pub default: Option<DefaultIndex>,    pub groups: Box<[(usize, SharedString)]>,} impl ToolchainList {    pub fn toolchains(&self) -> &[Toolchain] {        &self.toolchains    }    pub fn default_toolchain(&self) -> Option<Toolchain> {        self.default.and_then(|ix| self.toolchains.get(ix)).cloned()    }    pub fn group_for_index(&self, index: usize) -> Option<(usize, SharedString)> {        if index >= self.toolchains.len() {            return None;        }        let first_equal_or_greater = self            .groups            .partition_point(|(group_lower_bound, _)| group_lower_bound <= &index);        self.groups            .get(first_equal_or_greater.checked_sub(1)?)            .cloned()    }}