language_registry.rs

   1use crate::{
   2    CachedLspAdapter, File, Language, LanguageConfig, LanguageId, LanguageMatcher,
   3    LanguageServerName, LspAdapter, PLAIN_TEXT, ToolchainLister,
   4    language_settings::{
   5        AllLanguageSettingsContent, LanguageSettingsContent, all_language_settings,
   6    },
   7    task_context::ContextProvider,
   8    with_parser,
   9};
  10use anyhow::{Context as _, Result, anyhow};
  11use collections::{FxHashMap, HashMap, HashSet, hash_map};
  12
  13use futures::{
  14    Future,
  15    channel::{mpsc, oneshot},
  16};
  17use globset::GlobSet;
  18use gpui::{App, BackgroundExecutor, SharedString};
  19use itertools::FoldWhile::{Continue, Done};
  20use itertools::Itertools;
  21use lsp::LanguageServerId;
  22use parking_lot::{Mutex, RwLock};
  23use postage::watch;
  24use schemars::JsonSchema;
  25use serde::{Deserialize, Serialize};
  26use smallvec::SmallVec;
  27use std::{
  28    borrow::{Borrow, Cow},
  29    cell::LazyCell,
  30    ffi::OsStr,
  31    ops::Not,
  32    path::{Path, PathBuf},
  33    sync::Arc,
  34};
  35use sum_tree::Bias;
  36use text::{Point, Rope};
  37use theme::Theme;
  38use unicase::UniCase;
  39use util::{ResultExt, maybe, post_inc};
  40
  41#[derive(
  42    Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema,
  43)]
  44pub struct LanguageName(SharedString);
  45
  46impl LanguageName {
  47    pub fn new(s: &str) -> Self {
  48        Self(SharedString::new(s))
  49    }
  50
  51    pub fn from_proto(s: String) -> Self {
  52        Self(SharedString::from(s))
  53    }
  54    pub fn to_proto(self) -> String {
  55        self.0.to_string()
  56    }
  57    pub fn lsp_id(&self) -> String {
  58        match self.0.as_ref() {
  59            "Plain Text" => "plaintext".to_string(),
  60            language_name => language_name.to_lowercase(),
  61        }
  62    }
  63}
  64
  65impl From<LanguageName> for SharedString {
  66    fn from(value: LanguageName) -> Self {
  67        value.0
  68    }
  69}
  70
  71impl AsRef<str> for LanguageName {
  72    fn as_ref(&self) -> &str {
  73        self.0.as_ref()
  74    }
  75}
  76
  77impl Borrow<str> for LanguageName {
  78    fn borrow(&self) -> &str {
  79        self.0.as_ref()
  80    }
  81}
  82
  83impl std::fmt::Display for LanguageName {
  84    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  85        write!(f, "{}", self.0)
  86    }
  87}
  88
  89impl<'a> From<&'a str> for LanguageName {
  90    fn from(str: &'a str) -> LanguageName {
  91        LanguageName(SharedString::new(str))
  92    }
  93}
  94
  95impl From<LanguageName> for String {
  96    fn from(value: LanguageName) -> Self {
  97        let value: &str = &value.0;
  98        Self::from(value)
  99    }
 100}
 101
 102pub struct LanguageRegistry {
 103    state: RwLock<LanguageRegistryState>,
 104    language_server_download_dir: Option<Arc<Path>>,
 105    executor: BackgroundExecutor,
 106    lsp_binary_status_tx: BinaryStatusSender,
 107}
 108
 109struct LanguageRegistryState {
 110    next_language_server_id: usize,
 111    languages: Vec<Arc<Language>>,
 112    language_settings: AllLanguageSettingsContent,
 113    available_languages: Vec<AvailableLanguage>,
 114    grammars: HashMap<Arc<str>, AvailableGrammar>,
 115    lsp_adapters: HashMap<LanguageName, Vec<Arc<CachedLspAdapter>>>,
 116    all_lsp_adapters: HashMap<LanguageServerName, Arc<CachedLspAdapter>>,
 117    available_lsp_adapters:
 118        HashMap<LanguageServerName, Arc<dyn Fn() -> Arc<CachedLspAdapter> + 'static + Send + Sync>>,
 119    loading_languages: HashMap<LanguageId, Vec<oneshot::Sender<Result<Arc<Language>>>>>,
 120    subscription: (watch::Sender<()>, watch::Receiver<()>),
 121    theme: Option<Arc<Theme>>,
 122    version: usize,
 123    reload_count: usize,
 124
 125    #[cfg(any(test, feature = "test-support"))]
 126    fake_server_entries: HashMap<LanguageServerName, FakeLanguageServerEntry>,
 127}
 128
 129#[cfg(any(test, feature = "test-support"))]
 130pub struct FakeLanguageServerEntry {
 131    pub capabilities: lsp::ServerCapabilities,
 132    pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
 133    pub tx: futures::channel::mpsc::UnboundedSender<lsp::FakeLanguageServer>,
 134    pub _server: Option<lsp::FakeLanguageServer>,
 135}
 136
 137#[derive(Clone, Debug, PartialEq, Eq)]
 138pub enum BinaryStatus {
 139    None,
 140    CheckingForUpdate,
 141    Downloading,
 142    Failed { error: String },
 143}
 144
 145#[derive(Clone)]
 146pub struct AvailableLanguage {
 147    id: LanguageId,
 148    config: LanguageConfig,
 149    load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
 150    loaded: bool,
 151}
 152
 153impl AvailableLanguage {
 154    pub fn name(&self) -> LanguageName {
 155        self.config.name.clone()
 156    }
 157
 158    pub fn matcher(&self) -> &LanguageMatcher {
 159        &self.config.matcher
 160    }
 161    pub fn hidden(&self) -> bool {
 162        self.config.hidden
 163    }
 164    pub fn config(&self) -> &LanguageConfig {
 165        &self.config
 166    }
 167}
 168
 169#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord)]
 170enum LanguageMatchPrecedence {
 171    #[default]
 172    Undetermined,
 173    PathOrContent,
 174    UserConfigured,
 175}
 176
 177impl LanguageMatchPrecedence {
 178    fn best_possible_match(&self) -> bool {
 179        *self == LanguageMatchPrecedence::UserConfigured
 180    }
 181}
 182
 183enum AvailableGrammar {
 184    Native(tree_sitter::Language),
 185    Loaded(#[allow(unused)] PathBuf, tree_sitter::Language),
 186    Loading(
 187        #[allow(unused)] PathBuf,
 188        Vec<oneshot::Sender<Result<tree_sitter::Language, Arc<anyhow::Error>>>>,
 189    ),
 190    Unloaded(PathBuf),
 191    LoadFailed(Arc<anyhow::Error>),
 192}
 193
 194#[derive(Debug)]
 195pub struct LanguageNotFound;
 196
 197impl std::fmt::Display for LanguageNotFound {
 198    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 199        write!(f, "language not found")
 200    }
 201}
 202
 203pub const QUERY_FILENAME_PREFIXES: &[(
 204    &str,
 205    fn(&mut LanguageQueries) -> &mut Option<Cow<'static, str>>,
 206)] = &[
 207    ("highlights", |q| &mut q.highlights),
 208    ("brackets", |q| &mut q.brackets),
 209    ("outline", |q| &mut q.outline),
 210    ("indents", |q| &mut q.indents),
 211    ("embedding", |q| &mut q.embedding),
 212    ("injections", |q| &mut q.injections),
 213    ("overrides", |q| &mut q.overrides),
 214    ("redactions", |q| &mut q.redactions),
 215    ("runnables", |q| &mut q.runnables),
 216    ("debug_variables", |q| &mut q.debug_variables),
 217    ("textobjects", |q| &mut q.text_objects),
 218];
 219
 220/// Tree-sitter language queries for a given language.
 221#[derive(Debug, Default)]
 222pub struct LanguageQueries {
 223    pub highlights: Option<Cow<'static, str>>,
 224    pub brackets: Option<Cow<'static, str>>,
 225    pub indents: Option<Cow<'static, str>>,
 226    pub outline: Option<Cow<'static, str>>,
 227    pub embedding: Option<Cow<'static, str>>,
 228    pub injections: Option<Cow<'static, str>>,
 229    pub overrides: Option<Cow<'static, str>>,
 230    pub redactions: Option<Cow<'static, str>>,
 231    pub runnables: Option<Cow<'static, str>>,
 232    pub text_objects: Option<Cow<'static, str>>,
 233    pub debug_variables: Option<Cow<'static, str>>,
 234}
 235
 236#[derive(Clone, Default)]
 237struct BinaryStatusSender {
 238    txs: Arc<Mutex<Vec<mpsc::UnboundedSender<(SharedString, BinaryStatus)>>>>,
 239}
 240
 241pub struct LoadedLanguage {
 242    pub config: LanguageConfig,
 243    pub queries: LanguageQueries,
 244    pub context_provider: Option<Arc<dyn ContextProvider>>,
 245    pub toolchain_provider: Option<Arc<dyn ToolchainLister>>,
 246}
 247
 248impl LanguageRegistry {
 249    pub fn new(executor: BackgroundExecutor) -> Self {
 250        let this = Self {
 251            state: RwLock::new(LanguageRegistryState {
 252                next_language_server_id: 0,
 253                languages: Vec::new(),
 254                available_languages: Vec::new(),
 255                grammars: Default::default(),
 256                language_settings: Default::default(),
 257                loading_languages: Default::default(),
 258                lsp_adapters: Default::default(),
 259                all_lsp_adapters: Default::default(),
 260                available_lsp_adapters: HashMap::default(),
 261                subscription: watch::channel(),
 262                theme: Default::default(),
 263                version: 0,
 264                reload_count: 0,
 265
 266                #[cfg(any(test, feature = "test-support"))]
 267                fake_server_entries: Default::default(),
 268            }),
 269            language_server_download_dir: None,
 270            lsp_binary_status_tx: Default::default(),
 271            executor,
 272        };
 273        this.add(PLAIN_TEXT.clone());
 274        this
 275    }
 276
 277    #[cfg(any(test, feature = "test-support"))]
 278    pub fn test(executor: BackgroundExecutor) -> Self {
 279        let mut this = Self::new(executor);
 280        this.language_server_download_dir = Some(Path::new("/the-download-dir").into());
 281        this
 282    }
 283
 284    /// Clears out all of the loaded languages and reload them from scratch.
 285    pub fn reload(&self) {
 286        self.state.write().reload();
 287    }
 288
 289    /// Reorders the list of language servers for the given language.
 290    ///
 291    /// Uses the provided list of ordered [`CachedLspAdapters`] as the desired order.
 292    ///
 293    /// Any existing language servers not present in `ordered_lsp_adapters` will be
 294    /// appended to the end.
 295    pub fn reorder_language_servers(
 296        &self,
 297        language: &LanguageName,
 298        ordered_lsp_adapters: Vec<Arc<CachedLspAdapter>>,
 299    ) {
 300        self.state
 301            .write()
 302            .reorder_language_servers(language, ordered_lsp_adapters);
 303    }
 304
 305    /// Removes the specified languages and grammars from the registry.
 306    pub fn remove_languages(
 307        &self,
 308        languages_to_remove: &[LanguageName],
 309        grammars_to_remove: &[Arc<str>],
 310    ) {
 311        self.state
 312            .write()
 313            .remove_languages(languages_to_remove, grammars_to_remove)
 314    }
 315
 316    pub fn remove_lsp_adapter(&self, language_name: &LanguageName, name: &LanguageServerName) {
 317        let mut state = self.state.write();
 318        if let Some(adapters) = state.lsp_adapters.get_mut(language_name) {
 319            adapters.retain(|adapter| &adapter.name != name)
 320        }
 321        state.version += 1;
 322        state.reload_count += 1;
 323        *state.subscription.0.borrow_mut() = ();
 324    }
 325
 326    #[cfg(any(feature = "test-support", test))]
 327    pub fn register_test_language(&self, config: LanguageConfig) {
 328        self.register_language(
 329            config.clone(),
 330            Arc::new(move || {
 331                Ok(LoadedLanguage {
 332                    config: config.clone(),
 333                    queries: Default::default(),
 334                    toolchain_provider: None,
 335                    context_provider: None,
 336                })
 337            }),
 338        )
 339    }
 340
 341    /// Registers an available language server adapter.
 342    ///
 343    /// The language server is registered under the language server name, but
 344    /// not bound to a particular language.
 345    ///
 346    /// When a language wants to load this particular language server, it will
 347    /// invoke the `load` function.
 348    pub fn register_available_lsp_adapter(
 349        &self,
 350        name: LanguageServerName,
 351        load: impl Fn() -> Arc<dyn LspAdapter> + 'static + Send + Sync,
 352    ) {
 353        self.state.write().available_lsp_adapters.insert(
 354            name,
 355            Arc::new(move || {
 356                let lsp_adapter = load();
 357                CachedLspAdapter::new(lsp_adapter)
 358            }),
 359        );
 360    }
 361
 362    /// Loads the language server adapter for the language server with the given name.
 363    pub fn load_available_lsp_adapter(
 364        &self,
 365        name: &LanguageServerName,
 366    ) -> Option<Arc<CachedLspAdapter>> {
 367        let state = self.state.read();
 368        let load_lsp_adapter = state.available_lsp_adapters.get(name)?;
 369
 370        Some(load_lsp_adapter())
 371    }
 372
 373    pub fn register_lsp_adapter(
 374        &self,
 375        language_name: LanguageName,
 376        adapter: Arc<dyn LspAdapter>,
 377    ) -> Arc<CachedLspAdapter> {
 378        let cached = CachedLspAdapter::new(adapter);
 379        let mut state = self.state.write();
 380        state
 381            .lsp_adapters
 382            .entry(language_name)
 383            .or_default()
 384            .push(cached.clone());
 385        state
 386            .all_lsp_adapters
 387            .insert(cached.name.clone(), cached.clone());
 388
 389        cached
 390    }
 391
 392    pub fn get_or_register_lsp_adapter(
 393        &self,
 394        language_name: LanguageName,
 395        server_name: LanguageServerName,
 396        build_adapter: impl FnOnce() -> Arc<dyn LspAdapter> + 'static,
 397    ) -> Arc<CachedLspAdapter> {
 398        let registered = self
 399            .state
 400            .write()
 401            .lsp_adapters
 402            .entry(language_name.clone())
 403            .or_default()
 404            .iter()
 405            .find(|cached_adapter| cached_adapter.name == server_name)
 406            .cloned();
 407
 408        if let Some(found) = registered {
 409            found
 410        } else {
 411            let adapter = build_adapter();
 412            self.register_lsp_adapter(language_name, adapter)
 413        }
 414    }
 415
 416    /// Register a fake language server and adapter
 417    /// The returned channel receives a new instance of the language server every time it is started
 418    #[cfg(any(feature = "test-support", test))]
 419    pub fn register_fake_lsp(
 420        &self,
 421        language_name: impl Into<LanguageName>,
 422        mut adapter: crate::FakeLspAdapter,
 423    ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
 424        let language_name = language_name.into();
 425        let adapter_name = LanguageServerName(adapter.name.into());
 426        let capabilities = adapter.capabilities.clone();
 427        let initializer = adapter.initializer.take();
 428        let adapter = CachedLspAdapter::new(Arc::new(adapter));
 429        {
 430            let mut state = self.state.write();
 431            state
 432                .lsp_adapters
 433                .entry(language_name.clone())
 434                .or_default()
 435                .push(adapter.clone());
 436            state.all_lsp_adapters.insert(adapter.name(), adapter);
 437        }
 438
 439        self.register_fake_language_server(adapter_name, capabilities, initializer)
 440    }
 441
 442    /// Register a fake lsp adapter (without the language server)
 443    /// The returned channel receives a new instance of the language server every time it is started
 444    #[cfg(any(feature = "test-support", test))]
 445    pub fn register_fake_lsp_adapter(
 446        &self,
 447        language_name: impl Into<LanguageName>,
 448        adapter: crate::FakeLspAdapter,
 449    ) {
 450        let language_name = language_name.into();
 451        let mut state = self.state.write();
 452        let cached_adapter = CachedLspAdapter::new(Arc::new(adapter));
 453        state
 454            .lsp_adapters
 455            .entry(language_name.clone())
 456            .or_default()
 457            .push(cached_adapter.clone());
 458        state
 459            .all_lsp_adapters
 460            .insert(cached_adapter.name(), cached_adapter);
 461    }
 462
 463    /// Register a fake language server (without the adapter)
 464    /// The returned channel receives a new instance of the language server every time it is started
 465    #[cfg(any(feature = "test-support", test))]
 466    pub fn register_fake_language_server(
 467        &self,
 468        lsp_name: LanguageServerName,
 469        capabilities: lsp::ServerCapabilities,
 470        initializer: Option<Box<dyn Fn(&mut lsp::FakeLanguageServer) + Send + Sync>>,
 471    ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
 472        let (servers_tx, servers_rx) = futures::channel::mpsc::unbounded();
 473        self.state.write().fake_server_entries.insert(
 474            lsp_name,
 475            FakeLanguageServerEntry {
 476                tx: servers_tx,
 477                capabilities,
 478                initializer,
 479                _server: None,
 480            },
 481        );
 482        servers_rx
 483    }
 484
 485    /// Adds a language to the registry, which can be loaded if needed.
 486    pub fn register_language(
 487        &self,
 488        config: LanguageConfig,
 489        load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
 490    ) {
 491        let state = &mut *self.state.write();
 492
 493        for existing_language in &mut state.available_languages {
 494            if existing_language.config.name == config.name {
 495                existing_language.config = config;
 496                existing_language.load = load;
 497                return;
 498            }
 499        }
 500
 501        state.available_languages.push(AvailableLanguage {
 502            id: LanguageId::new(),
 503            config,
 504            load,
 505            loaded: false,
 506        });
 507        state.version += 1;
 508        state.reload_count += 1;
 509        *state.subscription.0.borrow_mut() = ();
 510    }
 511
 512    /// Adds grammars to the registry. Language configurations reference a grammar by name. The
 513    /// grammar controls how the source code is parsed.
 514    pub fn register_native_grammars(
 515        &self,
 516        grammars: impl IntoIterator<Item = (impl Into<Arc<str>>, impl Into<tree_sitter::Language>)>,
 517    ) {
 518        self.state.write().grammars.extend(
 519            grammars
 520                .into_iter()
 521                .map(|(name, grammar)| (name.into(), AvailableGrammar::Native(grammar.into()))),
 522        );
 523    }
 524
 525    /// Adds paths to WASM grammar files, which can be loaded if needed.
 526    pub fn register_wasm_grammars(
 527        &self,
 528        grammars: impl IntoIterator<Item = (impl Into<Arc<str>>, PathBuf)>,
 529    ) {
 530        let mut state = self.state.write();
 531        state.grammars.extend(
 532            grammars
 533                .into_iter()
 534                .map(|(name, path)| (name.into(), AvailableGrammar::Unloaded(path))),
 535        );
 536        state.version += 1;
 537        state.reload_count += 1;
 538        *state.subscription.0.borrow_mut() = ();
 539    }
 540
 541    pub fn language_settings(&self) -> AllLanguageSettingsContent {
 542        self.state.read().language_settings.clone()
 543    }
 544
 545    pub fn language_names(&self) -> Vec<String> {
 546        let state = self.state.read();
 547        let mut result = state
 548            .available_languages
 549            .iter()
 550            .filter_map(|l| l.loaded.not().then_some(l.config.name.to_string()))
 551            .chain(state.languages.iter().map(|l| l.config.name.to_string()))
 552            .collect::<Vec<_>>();
 553        result.sort_unstable_by_key(|language_name| language_name.to_lowercase());
 554        result
 555    }
 556
 557    pub fn grammar_names(&self) -> Vec<Arc<str>> {
 558        let state = self.state.read();
 559        let mut result = state.grammars.keys().cloned().collect::<Vec<_>>();
 560        result.sort_unstable_by_key(|grammar_name| grammar_name.to_lowercase());
 561        result
 562    }
 563
 564    /// Add a pre-loaded language to the registry.
 565    pub fn add(&self, language: Arc<Language>) {
 566        let mut state = self.state.write();
 567        state.available_languages.push(AvailableLanguage {
 568            id: language.id,
 569            config: language.config.clone(),
 570            load: Arc::new(|| Err(anyhow!("already loaded"))),
 571            loaded: true,
 572        });
 573        state.add(language);
 574    }
 575
 576    pub fn subscribe(&self) -> watch::Receiver<()> {
 577        self.state.read().subscription.1.clone()
 578    }
 579
 580    /// Returns the number of times that the registry has been changed,
 581    /// by adding languages or reloading.
 582    pub fn version(&self) -> usize {
 583        self.state.read().version
 584    }
 585
 586    /// Returns the number of times that the registry has been reloaded.
 587    pub fn reload_count(&self) -> usize {
 588        self.state.read().reload_count
 589    }
 590
 591    pub fn set_theme(&self, theme: Arc<Theme>) {
 592        let mut state = self.state.write();
 593        state.theme = Some(theme.clone());
 594        for language in &state.languages {
 595            language.set_theme(theme.syntax());
 596        }
 597    }
 598
 599    pub fn set_language_server_download_dir(&mut self, path: impl Into<Arc<Path>>) {
 600        self.language_server_download_dir = Some(path.into());
 601    }
 602
 603    pub fn language_for_name(
 604        self: &Arc<Self>,
 605        name: &str,
 606    ) -> impl Future<Output = Result<Arc<Language>>> + use<> {
 607        let name = UniCase::new(name);
 608        let rx = self.get_or_load_language(|language_name, _, current_best_match| {
 609            (current_best_match < LanguageMatchPrecedence::PathOrContent
 610                && UniCase::new(&language_name.0) == name)
 611                .then_some(LanguageMatchPrecedence::PathOrContent)
 612        });
 613        async move { rx.await? }
 614    }
 615
 616    pub fn language_for_name_or_extension(
 617        self: &Arc<Self>,
 618        string: &str,
 619    ) -> impl Future<Output = Result<Arc<Language>>> {
 620        let string = UniCase::new(string);
 621        let rx = self.get_or_load_language(|name, config, current_best_match| {
 622            (current_best_match < LanguageMatchPrecedence::PathOrContent
 623                && (UniCase::new(&name.0) == string
 624                    || config
 625                        .path_suffixes
 626                        .iter()
 627                        .any(|suffix| UniCase::new(suffix) == string)))
 628            .then_some(LanguageMatchPrecedence::PathOrContent)
 629        });
 630        async move { rx.await? }
 631    }
 632
 633    pub fn available_language_for_name(self: &Arc<Self>, name: &str) -> Option<AvailableLanguage> {
 634        let state = self.state.read();
 635        state
 636            .available_languages
 637            .iter()
 638            .find(|l| l.config.name.0.as_ref() == name)
 639            .cloned()
 640    }
 641
 642    pub fn language_for_file(
 643        self: &Arc<Self>,
 644        file: &Arc<dyn File>,
 645        content: Option<&Rope>,
 646        cx: &App,
 647    ) -> Option<AvailableLanguage> {
 648        let user_file_types = all_language_settings(Some(file), cx);
 649
 650        self.language_for_file_internal(
 651            &file.full_path(cx),
 652            content,
 653            Some(&user_file_types.file_types),
 654        )
 655    }
 656
 657    pub fn language_for_file_path<'a>(
 658        self: &Arc<Self>,
 659        path: &'a Path,
 660    ) -> impl Future<Output = Result<Arc<Language>>> + 'a {
 661        let available_language = self.language_for_file_internal(path, None, None);
 662
 663        let this = self.clone();
 664        async move {
 665            if let Some(language) = available_language {
 666                this.load_language(&language).await?
 667            } else {
 668                Err(anyhow!(LanguageNotFound))
 669            }
 670        }
 671    }
 672
 673    fn language_for_file_internal(
 674        self: &Arc<Self>,
 675        path: &Path,
 676        content: Option<&Rope>,
 677        user_file_types: Option<&FxHashMap<Arc<str>, GlobSet>>,
 678    ) -> Option<AvailableLanguage> {
 679        let filename = path.file_name().and_then(|name| name.to_str());
 680        // `Path.extension()` returns None for files with a leading '.'
 681        // and no other extension which is not the desired behavior here,
 682        // as we want `.zshrc` to result in extension being `Some("zshrc")`
 683        let extension = filename.and_then(|filename| filename.split('.').next_back());
 684        let path_suffixes = [extension, filename, path.to_str()];
 685        let path_suffixes_candidates = path_suffixes
 686            .iter()
 687            .filter_map(|suffix| suffix.map(globset::Candidate::new))
 688            .collect::<SmallVec<[_; 3]>>();
 689        let content = LazyCell::new(|| {
 690            content.map(|content| {
 691                let end = content.clip_point(Point::new(0, 256), Bias::Left);
 692                let end = content.point_to_offset(end);
 693                content.chunks_in_range(0..end).collect::<String>()
 694            })
 695        });
 696        self.find_matching_language(move |language_name, config, current_best_match| {
 697            let path_matches_default_suffix = || {
 698                config
 699                    .path_suffixes
 700                    .iter()
 701                    .any(|suffix| path_suffixes.contains(&Some(suffix.as_str())))
 702            };
 703            let path_matches_custom_suffix = || {
 704                user_file_types
 705                    .and_then(|types| types.get(language_name.as_ref()))
 706                    .map_or(false, |custom_suffixes| {
 707                        path_suffixes_candidates
 708                            .iter()
 709                            .any(|suffix| custom_suffixes.is_match_candidate(suffix))
 710                    })
 711            };
 712            let content_matches = || {
 713                config.first_line_pattern.as_ref().map_or(false, |pattern| {
 714                    content
 715                        .as_ref()
 716                        .is_some_and(|content| pattern.is_match(content))
 717                })
 718            };
 719
 720            // Only return a match for the given file if we have a better match than
 721            // the current one.
 722            match current_best_match {
 723                LanguageMatchPrecedence::PathOrContent | LanguageMatchPrecedence::Undetermined
 724                    if path_matches_custom_suffix() =>
 725                {
 726                    Some(LanguageMatchPrecedence::UserConfigured)
 727                }
 728                LanguageMatchPrecedence::Undetermined
 729                    if path_matches_default_suffix() || content_matches() =>
 730                {
 731                    Some(LanguageMatchPrecedence::PathOrContent)
 732                }
 733                _ => None,
 734            }
 735        })
 736    }
 737
 738    fn find_matching_language(
 739        self: &Arc<Self>,
 740        callback: impl Fn(
 741            &LanguageName,
 742            &LanguageMatcher,
 743            LanguageMatchPrecedence,
 744        ) -> Option<LanguageMatchPrecedence>,
 745    ) -> Option<AvailableLanguage> {
 746        let state = self.state.read();
 747        let available_language = state
 748            .available_languages
 749            .iter()
 750            .rev()
 751            .fold_while(None, |best_language_match, language| {
 752                let current_match_type = best_language_match
 753                    .as_ref()
 754                    .map_or(LanguageMatchPrecedence::default(), |(_, score)| *score);
 755                let language_score = callback(
 756                    &language.config.name,
 757                    &language.config.matcher,
 758                    current_match_type,
 759                );
 760                debug_assert!(
 761                    language_score.is_none_or(|new_score| new_score > current_match_type),
 762                    "Matching callback should only return a better match than the current one"
 763                );
 764
 765                match language_score {
 766                    Some(new_score) if new_score.best_possible_match() => {
 767                        Done(Some((language.clone(), new_score)))
 768                    }
 769                    Some(new_score) if current_match_type < new_score => {
 770                        Continue(Some((language.clone(), new_score)))
 771                    }
 772                    _ => Continue(best_language_match),
 773                }
 774            })
 775            .into_inner()
 776            .map(|(available_language, _)| available_language);
 777        drop(state);
 778        available_language
 779    }
 780
 781    pub fn load_language(
 782        self: &Arc<Self>,
 783        language: &AvailableLanguage,
 784    ) -> oneshot::Receiver<Result<Arc<Language>>> {
 785        let (tx, rx) = oneshot::channel();
 786
 787        let mut state = self.state.write();
 788
 789        // If the language is already loaded, resolve with it immediately.
 790        for loaded_language in state.languages.iter() {
 791            if loaded_language.id == language.id {
 792                tx.send(Ok(loaded_language.clone())).unwrap();
 793                return rx;
 794            }
 795        }
 796
 797        match state.loading_languages.entry(language.id) {
 798            // If the language is already being loaded, then add this
 799            // channel to a list that will be sent to when the load completes.
 800            hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(tx),
 801
 802            // Otherwise, start loading the language.
 803            hash_map::Entry::Vacant(entry) => {
 804                let this = self.clone();
 805
 806                let id = language.id;
 807                let name = language.config.name.clone();
 808                let language_load = language.load.clone();
 809
 810                self.executor
 811                    .spawn(async move {
 812                        let language = async {
 813                            let loaded_language = (language_load)()?;
 814                            if let Some(grammar) = loaded_language.config.grammar.clone() {
 815                                let grammar = Some(this.get_or_load_grammar(grammar).await?);
 816
 817                                Language::new_with_id(id, loaded_language.config, grammar)
 818                                    .with_context_provider(loaded_language.context_provider)
 819                                    .with_toolchain_lister(loaded_language.toolchain_provider)
 820                                    .with_queries(loaded_language.queries)
 821                            } else {
 822                                Ok(Language::new_with_id(id, loaded_language.config, None)
 823                                    .with_context_provider(loaded_language.context_provider)
 824                                    .with_toolchain_lister(loaded_language.toolchain_provider))
 825                            }
 826                        }
 827                        .await;
 828
 829                        match language {
 830                            Ok(language) => {
 831                                let language = Arc::new(language);
 832                                let mut state = this.state.write();
 833
 834                                state.add(language.clone());
 835                                state.mark_language_loaded(id);
 836                                if let Some(mut txs) = state.loading_languages.remove(&id) {
 837                                    for tx in txs.drain(..) {
 838                                        let _ = tx.send(Ok(language.clone()));
 839                                    }
 840                                }
 841                            }
 842                            Err(e) => {
 843                                log::error!("failed to load language {name}:\n{:?}", e);
 844                                let mut state = this.state.write();
 845                                state.mark_language_loaded(id);
 846                                if let Some(mut txs) = state.loading_languages.remove(&id) {
 847                                    for tx in txs.drain(..) {
 848                                        let _ = tx.send(Err(anyhow!(
 849                                            "failed to load language {}: {}",
 850                                            name,
 851                                            e
 852                                        )));
 853                                    }
 854                                }
 855                            }
 856                        };
 857                    })
 858                    .detach();
 859
 860                entry.insert(vec![tx]);
 861            }
 862        }
 863
 864        drop(state);
 865        rx
 866    }
 867
 868    fn get_or_load_language(
 869        self: &Arc<Self>,
 870        callback: impl Fn(
 871            &LanguageName,
 872            &LanguageMatcher,
 873            LanguageMatchPrecedence,
 874        ) -> Option<LanguageMatchPrecedence>,
 875    ) -> oneshot::Receiver<Result<Arc<Language>>> {
 876        let Some(language) = self.find_matching_language(callback) else {
 877            let (tx, rx) = oneshot::channel();
 878            let _ = tx.send(Err(anyhow!(LanguageNotFound)));
 879            return rx;
 880        };
 881
 882        self.load_language(&language)
 883    }
 884
 885    fn get_or_load_grammar(
 886        self: &Arc<Self>,
 887        name: Arc<str>,
 888    ) -> impl Future<Output = Result<tree_sitter::Language>> {
 889        let (tx, rx) = oneshot::channel();
 890        let mut state = self.state.write();
 891
 892        if let Some(grammar) = state.grammars.get_mut(name.as_ref()) {
 893            match grammar {
 894                AvailableGrammar::LoadFailed(error) => {
 895                    tx.send(Err(error.clone())).ok();
 896                }
 897                AvailableGrammar::Native(grammar) | AvailableGrammar::Loaded(_, grammar) => {
 898                    tx.send(Ok(grammar.clone())).ok();
 899                }
 900                AvailableGrammar::Loading(_, txs) => {
 901                    txs.push(tx);
 902                }
 903                AvailableGrammar::Unloaded(wasm_path) => {
 904                    let this = self.clone();
 905                    let wasm_path = wasm_path.clone();
 906                    *grammar = AvailableGrammar::Loading(wasm_path.clone(), vec![tx]);
 907                    self.executor
 908                        .spawn(async move {
 909                            let grammar_result = maybe!({
 910                                let wasm_bytes = std::fs::read(&wasm_path)?;
 911                                let grammar_name = wasm_path
 912                                    .file_stem()
 913                                    .and_then(OsStr::to_str)
 914                                    .ok_or_else(|| anyhow!("invalid grammar filename"))?;
 915                                anyhow::Ok(with_parser(|parser| {
 916                                    let mut store = parser.take_wasm_store().unwrap();
 917                                    let grammar = store.load_language(grammar_name, &wasm_bytes);
 918                                    parser.set_wasm_store(store).unwrap();
 919                                    grammar
 920                                })?)
 921                            })
 922                            .map_err(Arc::new);
 923
 924                            let value = match &grammar_result {
 925                                Ok(grammar) => AvailableGrammar::Loaded(wasm_path, grammar.clone()),
 926                                Err(error) => AvailableGrammar::LoadFailed(error.clone()),
 927                            };
 928
 929                            let old_value = this.state.write().grammars.insert(name, value);
 930                            if let Some(AvailableGrammar::Loading(_, txs)) = old_value {
 931                                for tx in txs {
 932                                    tx.send(grammar_result.clone()).ok();
 933                                }
 934                            }
 935                        })
 936                        .detach();
 937                }
 938            }
 939        } else {
 940            tx.send(Err(Arc::new(anyhow!("no such grammar {}", name))))
 941                .ok();
 942        }
 943
 944        async move { rx.await?.map_err(|e| anyhow!(e)) }
 945    }
 946
 947    pub fn to_vec(&self) -> Vec<Arc<Language>> {
 948        self.state.read().languages.to_vec()
 949    }
 950
 951    pub fn lsp_adapters(&self, language_name: &LanguageName) -> Vec<Arc<CachedLspAdapter>> {
 952        self.state
 953            .read()
 954            .lsp_adapters
 955            .get(language_name)
 956            .cloned()
 957            .unwrap_or_default()
 958    }
 959
 960    pub fn all_lsp_adapters(&self) -> Vec<Arc<CachedLspAdapter>> {
 961        self.state
 962            .read()
 963            .all_lsp_adapters
 964            .values()
 965            .cloned()
 966            .collect()
 967    }
 968
 969    pub fn adapter_for_name(&self, name: &LanguageServerName) -> Option<Arc<CachedLspAdapter>> {
 970        self.state.read().all_lsp_adapters.get(name).cloned()
 971    }
 972
 973    pub fn update_lsp_status(&self, server_name: LanguageServerName, status: BinaryStatus) {
 974        self.lsp_binary_status_tx.send(server_name.0, status);
 975    }
 976
 977    pub fn next_language_server_id(&self) -> LanguageServerId {
 978        self.state.write().next_language_server_id()
 979    }
 980
 981    pub fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>> {
 982        self.language_server_download_dir
 983            .as_ref()
 984            .map(|dir| Arc::from(dir.join(name.0.as_ref())))
 985    }
 986
 987    #[cfg(any(test, feature = "test-support"))]
 988    pub fn create_fake_language_server(
 989        &self,
 990        server_id: LanguageServerId,
 991        name: &LanguageServerName,
 992        binary: lsp::LanguageServerBinary,
 993        cx: &mut gpui::AsyncApp,
 994    ) -> Option<lsp::LanguageServer> {
 995        use gpui::AppContext as _;
 996
 997        let mut state = self.state.write();
 998        let fake_entry = state.fake_server_entries.get_mut(&name)?;
 999        let (server, mut fake_server) = lsp::FakeLanguageServer::new(
1000            server_id,
1001            binary,
1002            name.0.to_string(),
1003            fake_entry.capabilities.clone(),
1004            cx,
1005        );
1006        fake_entry._server = Some(fake_server.clone());
1007
1008        if let Some(initializer) = &fake_entry.initializer {
1009            initializer(&mut fake_server);
1010        }
1011
1012        let tx = fake_entry.tx.clone();
1013        cx.background_spawn(async move {
1014            if fake_server
1015                .try_receive_notification::<lsp::notification::Initialized>()
1016                .await
1017                .is_some()
1018            {
1019                tx.unbounded_send(fake_server.clone()).ok();
1020            }
1021        })
1022        .detach();
1023
1024        Some(server)
1025    }
1026
1027    pub fn language_server_binary_statuses(
1028        &self,
1029    ) -> mpsc::UnboundedReceiver<(SharedString, BinaryStatus)> {
1030        self.lsp_binary_status_tx.subscribe()
1031    }
1032
1033    pub async fn delete_server_container(&self, name: LanguageServerName) {
1034        log::info!("deleting server container");
1035        let Some(dir) = self.language_server_download_dir(&name) else {
1036            return;
1037        };
1038
1039        smol::fs::remove_dir_all(dir)
1040            .await
1041            .context("server container removal")
1042            .log_err();
1043    }
1044}
1045
1046impl LanguageRegistryState {
1047    fn next_language_server_id(&mut self) -> LanguageServerId {
1048        LanguageServerId(post_inc(&mut self.next_language_server_id))
1049    }
1050
1051    fn add(&mut self, language: Arc<Language>) {
1052        if let Some(theme) = self.theme.as_ref() {
1053            language.set_theme(theme.syntax());
1054        }
1055        self.language_settings.languages.insert(
1056            language.name(),
1057            LanguageSettingsContent {
1058                tab_size: language.config.tab_size,
1059                hard_tabs: language.config.hard_tabs,
1060                soft_wrap: language.config.soft_wrap,
1061                auto_indent_on_paste: language.config.auto_indent_on_paste,
1062                ..Default::default()
1063            }
1064            .clone(),
1065        );
1066        self.languages.push(language);
1067        self.version += 1;
1068        *self.subscription.0.borrow_mut() = ();
1069    }
1070
1071    fn reload(&mut self) {
1072        self.languages.clear();
1073        self.version += 1;
1074        self.reload_count += 1;
1075        for language in &mut self.available_languages {
1076            language.loaded = false;
1077        }
1078        *self.subscription.0.borrow_mut() = ();
1079    }
1080
1081    /// Reorders the list of language servers for the given language.
1082    ///
1083    /// Uses the provided list of ordered [`CachedLspAdapters`] as the desired order.
1084    ///
1085    /// Any existing language servers not present in `ordered_lsp_adapters` will be
1086    /// appended to the end.
1087    fn reorder_language_servers(
1088        &mut self,
1089        language_name: &LanguageName,
1090        ordered_lsp_adapters: Vec<Arc<CachedLspAdapter>>,
1091    ) {
1092        let Some(lsp_adapters) = self.lsp_adapters.get_mut(language_name) else {
1093            return;
1094        };
1095
1096        let ordered_lsp_adapter_ids = ordered_lsp_adapters
1097            .iter()
1098            .map(|lsp_adapter| lsp_adapter.name.clone())
1099            .collect::<HashSet<_>>();
1100
1101        let mut new_lsp_adapters = ordered_lsp_adapters;
1102        for adapter in lsp_adapters.iter() {
1103            if !ordered_lsp_adapter_ids.contains(&adapter.name) {
1104                new_lsp_adapters.push(adapter.clone());
1105            }
1106        }
1107
1108        *lsp_adapters = new_lsp_adapters;
1109    }
1110
1111    fn remove_languages(
1112        &mut self,
1113        languages_to_remove: &[LanguageName],
1114        grammars_to_remove: &[Arc<str>],
1115    ) {
1116        if languages_to_remove.is_empty() && grammars_to_remove.is_empty() {
1117            return;
1118        }
1119
1120        self.languages
1121            .retain(|language| !languages_to_remove.contains(&language.name()));
1122        self.available_languages
1123            .retain(|language| !languages_to_remove.contains(&language.config.name));
1124        self.grammars
1125            .retain(|name, _| !grammars_to_remove.contains(name));
1126        self.version += 1;
1127        self.reload_count += 1;
1128        *self.subscription.0.borrow_mut() = ();
1129    }
1130
1131    /// Mark the given language as having been loaded, so that the
1132    /// language registry won't try to load it again.
1133    fn mark_language_loaded(&mut self, id: LanguageId) {
1134        for language in &mut self.available_languages {
1135            if language.id == id {
1136                language.loaded = true;
1137                break;
1138            }
1139        }
1140    }
1141}
1142
1143impl BinaryStatusSender {
1144    fn subscribe(&self) -> mpsc::UnboundedReceiver<(SharedString, BinaryStatus)> {
1145        let (tx, rx) = mpsc::unbounded();
1146        self.txs.lock().push(tx);
1147        rx
1148    }
1149
1150    fn send(&self, name: SharedString, status: BinaryStatus) {
1151        let mut txs = self.txs.lock();
1152        txs.retain(|tx| tx.unbounded_send((name.clone(), status.clone())).is_ok());
1153    }
1154}