956 lines · 33.8 KB · Rust
RawDownload
use crate::available_languages::AvailableLanguage;use crate::{    CachedLspAdapter, File, Language, LanguageConfig, LanguageId, LanguageMatcher,    LanguageServerName, LspAdapter, ManifestName, PLAIN_TEXT, ToolchainLister,    available_languages::AvailableLanguages, language_settings::all_language_settings,    task_context::ContextProvider, with_parser,};use anyhow::{Context as _, Result, anyhow};use collections::{FxHashMap, HashMap, HashSet, hash_map};pub use language_core::{    BinaryStatus, LanguageName, LanguageQueries, LanguageServerStatusUpdate,    QUERY_FILENAME_PREFIXES, ServerHealth,};use settings::{AllLanguageSettingsContent, LanguageSettingsContent}; use futures::{    Future,    channel::{mpsc, oneshot},};use globset::GlobSet;use gpui::{App, BackgroundExecutor};use lsp::LanguageServerId;use parking_lot::{Mutex, RwLock};use postage::watch; use std::{    ffi::OsStr,    path::{Path, PathBuf},    sync::Arc,};use text::Rope;use theme::Theme; use util::{maybe, post_inc}; pub struct LanguageRegistry {    state: RwLock<LanguageRegistryState>,    language_server_download_dir: Option<Arc<Path>>,    executor: BackgroundExecutor,    lsp_binary_status_tx: ServerStatusSender,} struct LanguageRegistryState {    next_language_server_id: usize,    languages: Vec<Arc<Language>>,    language_settings: AllLanguageSettingsContent,    available_languages: AvailableLanguages,    grammars: HashMap<Arc<str>, AvailableGrammar>,    lsp_adapters: HashMap<LanguageName, Vec<Arc<CachedLspAdapter>>>,    all_lsp_adapters: HashMap<LanguageServerName, Arc<CachedLspAdapter>>,    available_lsp_adapters:        HashMap<LanguageServerName, Arc<dyn Fn() -> Arc<CachedLspAdapter> + 'static + Send + Sync>>,    loading_languages: HashMap<LanguageId, Vec<oneshot::Sender<Result<Arc<Language>>>>>,    subscription: (watch::Sender<()>, watch::Receiver<()>),    theme: Option<Arc<Theme>>,    version: usize,    reload_count: usize,     #[cfg(any(test, feature = "test-support"))]    fake_server_entries: HashMap<LanguageServerName, FakeLanguageServerEntry>,} #[cfg(any(test, feature = "test-support"))]pub struct FakeLanguageServerEntry {    pub capabilities: lsp::ServerCapabilities,    pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,    pub tx: futures::channel::mpsc::UnboundedSender<lsp::FakeLanguageServer>,    pub _server: Option<lsp::FakeLanguageServer>,} enum AvailableGrammar {    Native(tree_sitter::Language),    Loaded(#[allow(unused)] PathBuf, tree_sitter::Language),    Loading(        #[allow(unused)] PathBuf,        Vec<oneshot::Sender<Result<tree_sitter::Language, Arc<anyhow::Error>>>>,    ),    Unloaded(PathBuf),    LoadFailed(Arc<anyhow::Error>),} #[derive(Debug)]pub struct LanguageNotFound; impl std::fmt::Display for LanguageNotFound {    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {        write!(f, "language not found")    }} #[derive(Clone, Default)]struct ServerStatusSender {    txs: Arc<Mutex<Vec<mpsc::UnboundedSender<(LanguageServerName, BinaryStatus)>>>>,} pub struct LoadedLanguage {    pub config: LanguageConfig,    pub queries: LanguageQueries,    pub context_provider: Option<Arc<dyn ContextProvider>>,    pub toolchain_provider: Option<Arc<dyn ToolchainLister>>,    pub manifest_name: Option<ManifestName>,} impl LanguageRegistry {    pub fn new(executor: BackgroundExecutor) -> Self {        let this = Self {            state: RwLock::new(LanguageRegistryState {                next_language_server_id: 0,                languages: Vec::new(),                available_languages: AvailableLanguages::default(),                grammars: Default::default(),                language_settings: Default::default(),                loading_languages: Default::default(),                lsp_adapters: Default::default(),                all_lsp_adapters: Default::default(),                available_lsp_adapters: HashMap::default(),                subscription: watch::channel(),                theme: Default::default(),                version: 0,                reload_count: 0,                 #[cfg(any(test, feature = "test-support"))]                fake_server_entries: Default::default(),            }),            language_server_download_dir: None,            lsp_binary_status_tx: Default::default(),            executor,        };        this.add(PLAIN_TEXT.clone());        this    }     #[cfg(any(test, feature = "test-support"))]    pub fn test(executor: BackgroundExecutor) -> Self {        let mut this = Self::new(executor);        this.language_server_download_dir = Some(Path::new("/the-download-dir").into());        this    }     /// Clears out all of the loaded languages and reload them from scratch.    pub fn reload(&self) {        self.state.write().reload();    }     /// Reorders the list of language servers for the given language.    ///    /// Uses the provided list of ordered [`CachedLspAdapters`] as the desired order.    ///    /// Any existing language servers not present in `ordered_lsp_adapters` will be    /// appended to the end.    pub fn reorder_language_servers(        &self,        language: &LanguageName,        ordered_lsp_adapters: Vec<Arc<CachedLspAdapter>>,    ) {        self.state            .write()            .reorder_language_servers(language, ordered_lsp_adapters);    }     /// Removes the specified languages and grammars from the registry.    pub fn remove_languages(        &self,        languages_to_remove: &[LanguageName],        grammars_to_remove: &[Arc<str>],    ) {        self.state            .write()            .remove_languages(languages_to_remove, grammars_to_remove)    }     pub fn remove_lsp_adapter(&self, language_name: &LanguageName, name: &LanguageServerName) {        let mut state = self.state.write();        if let Some(adapters) = state.lsp_adapters.get_mut(language_name) {            adapters.retain(|adapter| &adapter.name != name)        }        state.all_lsp_adapters.remove(name);        state.available_lsp_adapters.remove(name);         state.version += 1;        state.reload_count += 1;        *state.subscription.0.borrow_mut() = ();    }     #[cfg(any(feature = "test-support", test))]    pub fn register_test_language(&self, config: LanguageConfig) {        self.register_language(            config.name.clone(),            config.grammar.clone(),            config.matcher.clone(),            config.hidden,            None,            Arc::new(move || {                Ok(LoadedLanguage {                    config: config.clone(),                    queries: Default::default(),                    toolchain_provider: None,                    context_provider: None,                    manifest_name: None,                })            }),        )    }     /// Registers an available language server adapter.    ///    /// The language server is registered under the language server name, but    /// not bound to a particular language.    ///    /// When a language wants to load this particular language server, it will    /// invoke the `load` function.    pub fn register_available_lsp_adapter(        &self,        name: LanguageServerName,        adapter: Arc<dyn LspAdapter>,    ) {        let mut state = self.state.write();         if adapter.is_extension()            && let Some(existing_adapter) = state.all_lsp_adapters.get(&name)            && !existing_adapter.adapter.is_extension()        {            log::warn!(                "not registering extension-provided language server {name:?}, since a builtin language server exists with that name",            );            return;        }         state.available_lsp_adapters.insert(            name,            Arc::new(move || CachedLspAdapter::new(adapter.clone())),        );    }     /// Loads the language server adapter for the language server with the given name.    pub fn load_available_lsp_adapter(        &self,        name: &LanguageServerName,    ) -> Option<Arc<CachedLspAdapter>> {        let state = self.state.read();        let load_lsp_adapter = state.available_lsp_adapters.get(name)?;         Some(load_lsp_adapter())    }     /// Checks if a language server adapter with the given name is available to be loaded.    pub fn is_lsp_adapter_available(&self, name: &LanguageServerName) -> bool {        let state = self.state.read();        state.available_lsp_adapters.contains_key(name)    }     /// Returns the names of all available LSP adapters (registered via `register_available_lsp_adapter`).    /// These are adapters that are not bound to a specific language but can be enabled via settings.    pub fn available_lsp_adapter_names(&self) -> Vec<LanguageServerName> {        self.state            .read()            .available_lsp_adapters            .keys()            .cloned()            .collect()    }     pub fn register_lsp_adapter(&self, language_name: LanguageName, adapter: Arc<dyn LspAdapter>) {        let mut state = self.state.write();         if adapter.is_extension()            && let Some(existing_adapter) = state.all_lsp_adapters.get(&adapter.name())            && !existing_adapter.adapter.is_extension()        {            log::warn!(                "not registering extension-provided language server {:?} for language {language_name:?}, since a builtin language server exists with that name",                adapter.name(),            );            return;        }         let cached = CachedLspAdapter::new(adapter);        state            .lsp_adapters            .entry(language_name)            .or_default()            .push(cached.clone());        state            .all_lsp_adapters            .insert(cached.name.clone(), cached.clone());        state.version += 1;        *state.subscription.0.borrow_mut() = ();    }     /// Register a fake language server and adapter    /// The returned channel receives a new instance of the language server every time it is started    #[cfg(any(feature = "test-support", test))]    pub fn register_fake_lsp(        &self,        language_name: impl Into<LanguageName>,        mut adapter: crate::FakeLspAdapter,    ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {        let adapter_name = LanguageServerName(adapter.name.into());        let capabilities = adapter.capabilities.clone();        let initializer = adapter.initializer.take();        self.register_fake_lsp_adapter(language_name, adapter);        self.register_fake_lsp_server(adapter_name, capabilities, initializer)    }     /// Register a fake lsp adapter (without the language server)    #[cfg(any(feature = "test-support", test))]    pub fn register_fake_lsp_adapter(        &self,        language_name: impl Into<LanguageName>,        adapter: crate::FakeLspAdapter,    ) {        let language_name = language_name.into();        let mut state = self.state.write();        let cached_adapter = CachedLspAdapter::new(Arc::new(adapter));        state            .lsp_adapters            .entry(language_name)            .or_default()            .push(cached_adapter.clone());        state            .all_lsp_adapters            .insert(cached_adapter.name(), cached_adapter);        state.version += 1;        *state.subscription.0.borrow_mut() = ();    }     /// Register a fake language server (without the adapter)    /// The returned channel receives a new instance of the language server every time it is started    #[cfg(any(feature = "test-support", test))]    pub fn register_fake_lsp_server(        &self,        lsp_name: LanguageServerName,        capabilities: lsp::ServerCapabilities,        initializer: Option<Box<dyn Fn(&mut lsp::FakeLanguageServer) + Send + Sync>>,    ) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {        let (servers_tx, servers_rx) = futures::channel::mpsc::unbounded();        self.state.write().fake_server_entries.insert(            lsp_name,            FakeLanguageServerEntry {                tx: servers_tx,                capabilities,                initializer,                _server: None,            },        );        servers_rx    }     #[cfg(any(feature = "test-support", test))]    pub fn register_fake_available_lsp_adapter(        &self,        name: impl Into<LanguageServerName>,        adapter: crate::FakeLspAdapter,    ) {        let name = name.into();        let adapter = Arc::new(adapter);        let mut state = self.state.write();        state.available_lsp_adapters.insert(            name,            Arc::new(move || CachedLspAdapter::new(adapter.clone())),        );    }     #[cfg(any(feature = "test-support", test))]    pub fn has_fake_lsp_server(&self, lsp_name: &LanguageServerName) -> bool {        self.state.read().fake_server_entries.contains_key(lsp_name)    }     /// Adds a language to the registry, which can be loaded if needed.    pub fn register_language(        &self,        name: LanguageName,        grammar_name: Option<Arc<str>>,        matcher: Arc<LanguageMatcher>,        hidden: bool,        manifest_name: Option<ManifestName>,        load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,    ) {        let state = &mut *self.state.write();         let was_added = state.available_languages.register(            name,            grammar_name,            matcher,            hidden,            manifest_name,            load,        );        if !was_added {            return;        }         state.version += 1;        state.reload_count += 1;        *state.subscription.0.borrow_mut() = ();    }     /// Adds grammars to the registry. Language configurations reference a grammar by name. The    /// grammar controls how the source code is parsed.    pub fn register_native_grammars(        &self,        grammars: impl IntoIterator<Item = (impl Into<Arc<str>>, impl Into<tree_sitter::Language>)>,    ) {        self.state.write().grammars.extend(            grammars                .into_iter()                .map(|(name, grammar)| (name.into(), AvailableGrammar::Native(grammar.into()))),        );    }     /// Adds paths to WASM grammar files, which can be loaded if needed.    pub fn register_wasm_grammars(&self, grammars: Vec<(Arc<str>, PathBuf)>) {        if grammars.is_empty() {            return;        }         let mut state = self.state.write();        state.grammars.extend(            grammars                .into_iter()                .map(|(name, path)| (name, AvailableGrammar::Unloaded(path))),        );        state.version += 1;        state.reload_count += 1;        *state.subscription.0.borrow_mut() = ();    }     pub fn language_settings(&self) -> AllLanguageSettingsContent {        self.state.read().language_settings.clone()    }     pub fn language_names(&self) -> Vec<LanguageName> {        let state = self.state.read();        let mut result = state.available_languages.unloaded_language_names();        result.extend(            state                .languages                .iter()                .map(|language| language.config.name.clone()),        );        result.sort_unstable_by_key(|language_name| language_name.as_ref().to_lowercase());        result    }     pub fn grammar_names(&self) -> Vec<Arc<str>> {        let state = self.state.read();        let mut result = state.grammars.keys().cloned().collect::<Vec<_>>();        result.sort_unstable_by_key(|grammar_name| grammar_name.to_lowercase());        result    }     /// Add a pre-loaded language to the registry.    pub fn add(&self, language: Arc<Language>) {        let mut state = self.state.write();        state.available_languages.add(AvailableLanguage {            id: language.id,            name: language.name(),            grammar: language.config.grammar.clone(),            matcher: language.config.matcher.clone(),            hidden: language.config.hidden,            manifest_name: None,            load: Arc::new(|| Err(anyhow!("already loaded"))),            loaded: true,        });        state.add(language);    }     pub fn subscribe(&self) -> watch::Receiver<()> {        self.state.read().subscription.1.clone()    }     /// Returns the number of times that the registry has been changed,    /// by adding languages or reloading.    pub fn version(&self) -> usize {        self.state.read().version    }     /// Returns the number of times that the registry has been reloaded.    pub fn reload_count(&self) -> usize {        self.state.read().reload_count    }     pub fn set_theme(&self, theme: Arc<Theme>) {        let mut state = self.state.write();        state.theme = Some(theme.clone());        for language in &state.languages {            language.set_theme(theme.syntax());        }    }     pub fn set_language_server_download_dir(&mut self, path: impl Into<Arc<Path>>) {        self.language_server_download_dir = Some(path.into());    }     pub fn language_for_name(        self: &Arc<Self>,        name: &str,    ) -> impl Future<Output = Result<Arc<Language>>> + use<> {        let language_id = self.state.read().available_languages.find_by_name(name);        let rx = self.get_or_load_language(language_id);

Lines 1–500 of 956.