debugger/extensions: Revert changes to extension store related to language config (#30225)

Piotr Osiewicz and Conrad created

Revert #29945 

Release Notes:

- N/A

---------

Co-authored-by: Conrad <conrad@zed.dev>

Change summary

crates/debugger_ui/src/new_session_modal.rs         |  67 ++------
crates/extension/src/extension_host_proxy.rs        |  14 +
crates/extension_host/src/extension_host.rs         | 109 ++++++--------
crates/extension_host/src/extension_store_test.rs   |  88 +++--------
crates/extension_host/src/headless_host.rs          |   5 
crates/language/src/language.rs                     |  24 +--
crates/language/src/language_registry.rs            |  55 ++++---
crates/language_extension/src/language_extension.rs |  10 
crates/languages/src/lib.rs                         |   5 
9 files changed, 159 insertions(+), 218 deletions(-)

Detailed changes

crates/debugger_ui/src/new_session_modal.rs 🔗

@@ -1,12 +1,11 @@
 use std::{
     borrow::Cow,
-    cmp::Reverse,
     ops::Not,
     path::{Path, PathBuf},
     sync::Arc,
+    usize,
 };
 
-use collections::{HashMap, HashSet};
 use dap::{
     DapRegistry, DebugRequest,
     adapters::{DebugAdapterName, DebugTaskDefinition},
@@ -192,25 +191,22 @@ impl NewSessionModal {
         cx: &mut Context<Self>,
     ) -> Option<ui::DropdownMenu> {
         let workspace = self.workspace.clone();
-        let language_registry = self
-            .workspace
-            .update(cx, |this, _| this.app_state().languages.clone())
-            .ok()?;
         let weak = cx.weak_entity();
         let label = self
             .debugger
             .as_ref()
             .map(|d| d.0.clone())
             .unwrap_or_else(|| SELECT_DEBUGGER_LABEL.clone());
-        let active_buffer_language_name =
-            self.task_contexts
-                .active_item_context
-                .as_ref()
-                .and_then(|item| {
-                    item.1
-                        .as_ref()
-                        .and_then(|location| location.buffer.read(cx).language()?.name().into())
-                });
+        let active_buffer_language = self
+            .task_contexts
+            .active_item_context
+            .as_ref()
+            .and_then(|item| {
+                item.1
+                    .as_ref()
+                    .and_then(|location| location.buffer.read(cx).language())
+            })
+            .cloned();
         DropdownMenu::new(
             "dap-adapter-picker",
             label,
@@ -229,42 +225,19 @@ impl NewSessionModal {
                     }
                 };
 
-                let available_languages = language_registry.language_names();
-                let mut debugger_to_languages = HashMap::default();
-                for language in available_languages {
-                    let Some(language) =
-                        language_registry.available_language_for_name(language.as_str())
-                    else {
-                        continue;
-                    };
-
-                    language.config().debuggers.iter().for_each(|adapter| {
-                        debugger_to_languages
-                            .entry(adapter.clone())
-                            .or_insert_with(HashSet::default)
-                            .insert(language.name());
-                    });
-                }
                 let mut available_adapters = workspace
                     .update(cx, |_, cx| DapRegistry::global(cx).enumerate_adapters())
                     .ok()
                     .unwrap_or_default();
-
-                available_adapters.sort_by_key(|name| {
-                    let languages_for_debugger = debugger_to_languages.get(name.as_ref());
-                    let languages_count =
-                        languages_for_debugger.map_or(0, |languages| languages.len());
-                    let contains_language_of_active_buffer = languages_for_debugger
-                        .zip(active_buffer_language_name.as_ref())
-                        .map_or(false, |(languages, active_buffer_language)| {
-                            languages.contains(active_buffer_language)
-                        });
-
-                    (
-                        Reverse(contains_language_of_active_buffer),
-                        Reverse(languages_count),
-                    )
-                });
+                if let Some(language) = active_buffer_language {
+                    available_adapters.sort_by_key(|adapter| {
+                        language
+                            .config()
+                            .debuggers
+                            .get_index_of(adapter.0.as_ref())
+                            .unwrap_or(usize::MAX)
+                    });
+                }
 
                 for adapter in available_adapters.into_iter() {
                     menu = menu.entry(adapter.0.clone(), None, setter_for_name(adapter.clone()));

crates/extension/src/extension_host_proxy.rs 🔗

@@ -4,7 +4,7 @@ use std::sync::Arc;
 use anyhow::Result;
 use fs::Fs;
 use gpui::{App, Global, ReadGlobal, SharedString, Task};
-use language::{BinaryStatus, LanguageConfig, LanguageName, LoadedLanguage};
+use language::{BinaryStatus, LanguageMatcher, LanguageName, LoadedLanguage};
 use lsp::LanguageServerName;
 use parking_lot::RwLock;
 
@@ -224,7 +224,10 @@ impl ExtensionGrammarProxy for ExtensionHostProxy {
 pub trait ExtensionLanguageProxy: Send + Sync + 'static {
     fn register_language(
         &self,
-        config: LanguageConfig,
+        language: LanguageName,
+        grammar: Option<Arc<str>>,
+        matcher: LanguageMatcher,
+        hidden: bool,
         load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
     );
 
@@ -238,14 +241,17 @@ pub trait ExtensionLanguageProxy: Send + Sync + 'static {
 impl ExtensionLanguageProxy for ExtensionHostProxy {
     fn register_language(
         &self,
-        language: LanguageConfig,
+        language: LanguageName,
+        grammar: Option<Arc<str>>,
+        matcher: LanguageMatcher,
+        hidden: bool,
         load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
     ) {
         let Some(proxy) = self.language_proxy.read().clone() else {
             return;
         };
 
-        proxy.register_language(language, load)
+        proxy.register_language(language, grammar, matcher, hidden, load)
     }
 
     fn remove_languages(

crates/extension_host/src/extension_host.rs 🔗

@@ -34,7 +34,8 @@ use gpui::{
 };
 use http_client::{AsyncBody, HttpClient, HttpClientWithUrl};
 use language::{
-    LanguageConfig, LanguageName, LanguageQueries, LoadedLanguage, QUERY_FILENAME_PREFIXES, Rope,
+    LanguageConfig, LanguageMatcher, LanguageName, LanguageQueries, LoadedLanguage,
+    QUERY_FILENAME_PREFIXES, Rope,
 };
 use node_runtime::NodeRuntime;
 use project::ContextProviderWithTasks;
@@ -139,7 +140,7 @@ struct GlobalExtensionStore(Entity<ExtensionStore>);
 
 impl Global for GlobalExtensionStore {}
 
-#[derive(Deserialize, Serialize, Default)]
+#[derive(Debug, Deserialize, Serialize, Default, PartialEq, Eq)]
 pub struct ExtensionIndex {
     pub extensions: BTreeMap<Arc<str>, ExtensionIndexEntry>,
     pub themes: BTreeMap<Arc<str>, ExtensionIndexThemeEntry>,
@@ -166,12 +167,13 @@ pub struct ExtensionIndexIconThemeEntry {
     pub path: PathBuf,
 }
 
-#[derive(Clone, Debug, Deserialize, Serialize)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Deserialize, Serialize)]
 pub struct ExtensionIndexLanguageEntry {
     pub extension: Arc<str>,
     pub path: PathBuf,
-    #[serde(skip)]
-    pub config: LanguageConfig,
+    pub matcher: LanguageMatcher,
+    pub hidden: bool,
+    pub grammar: Option<Arc<str>>,
 }
 
 actions!(zed, [ReloadExtensions]);
@@ -1181,8 +1183,44 @@ impl ExtensionStore {
         }
 
         self.proxy.register_grammars(grammars_to_add);
+        let languages_to_add = new_index
+            .languages
+            .iter_mut()
+            .filter(|(_, entry)| extensions_to_load.contains(&entry.extension))
+            .collect::<Vec<_>>();
+        for (language_name, language) in languages_to_add {
+            let mut language_path = self.installed_dir.clone();
+            language_path.extend([
+                Path::new(language.extension.as_ref()),
+                language.path.as_path(),
+            ]);
+            self.proxy.register_language(
+                language_name.clone(),
+                language.grammar.clone(),
+                language.matcher.clone(),
+                language.hidden,
+                Arc::new(move || {
+                    let config = std::fs::read_to_string(language_path.join("config.toml"))?;
+                    let config: LanguageConfig = ::toml::from_str(&config)?;
+                    let queries = load_plugin_queries(&language_path);
+                    let context_provider =
+                        std::fs::read_to_string(language_path.join("tasks.json"))
+                            .ok()
+                            .and_then(|contents| {
+                                let definitions =
+                                    serde_json_lenient::from_str(&contents).log_err()?;
+                                Some(Arc::new(ContextProviderWithTasks::new(definitions)) as Arc<_>)
+                            });
 
-        let installed_dir = self.installed_dir.clone();
+                    Ok(LoadedLanguage {
+                        config,
+                        queries,
+                        context_provider,
+                        toolchain_provider: None,
+                    })
+                }),
+            );
+        }
 
         let fs = self.fs.clone();
         let wasm_host = self.wasm_host.clone();
@@ -1192,60 +1230,11 @@ impl ExtensionStore {
             .iter()
             .filter_map(|name| new_index.extensions.get(name).cloned())
             .collect::<Vec<_>>();
+        self.extension_index = new_index;
+        cx.notify();
+        cx.emit(Event::ExtensionsUpdated);
 
         cx.spawn(async move |this, cx| {
-            let languages_to_add = new_index
-                .languages
-                .iter_mut()
-                .filter(|(_, entry)| extensions_to_load.contains(&entry.extension))
-                .collect::<Vec<_>>();
-            for (_, language) in languages_to_add {
-                let mut language_path = installed_dir.clone();
-                language_path.extend([
-                    Path::new(language.extension.as_ref()),
-                    language.path.as_path(),
-                ]);
-                let Some(config) = fs.load(&language_path.join("config.toml")).await.ok() else {
-                    log::error!("Could not load config.toml in {:?}", language_path);
-                    continue;
-                };
-                let Some(config) = ::toml::from_str::<LanguageConfig>(&config).ok() else {
-                    log::error!(
-                        "Could not parse language config.toml in {:?}",
-                        language_path
-                    );
-                    continue;
-                };
-                language.config = config.clone();
-                proxy.register_language(
-                    language.config.clone(),
-                    Arc::new(move || {
-                        let queries = load_plugin_queries(&language_path);
-                        let context_provider =
-                            std::fs::read_to_string(language_path.join("tasks.json"))
-                                .ok()
-                                .and_then(|contents| {
-                                    let definitions =
-                                        serde_json_lenient::from_str(&contents).log_err()?;
-                                    Some(Arc::new(ContextProviderWithTasks::new(definitions))
-                                        as Arc<_>)
-                                });
-
-                        Ok(LoadedLanguage {
-                            config: config.clone(),
-                            queries,
-                            context_provider,
-                            toolchain_provider: None,
-                        })
-                    }),
-                );
-            }
-            this.update(cx, |this, cx| {
-                this.extension_index = new_index;
-                cx.notify();
-                cx.emit(Event::ExtensionsUpdated);
-            })
-            .ok();
             cx.background_spawn({
                 let fs = fs.clone();
                 async move {
@@ -1448,7 +1437,9 @@ impl ExtensionStore {
                     ExtensionIndexLanguageEntry {
                         extension: extension_id.clone(),
                         path: relative_path,
-                        config,
+                        matcher: config.matcher,
+                        hidden: config.hidden,
+                        grammar: config.grammar,
                     },
                 );
             }

crates/extension_host/src/extension_store_test.rs 🔗

@@ -10,7 +10,7 @@ use fs::{FakeFs, Fs, RealFs};
 use futures::{AsyncReadExt, StreamExt, io::BufReader};
 use gpui::{AppContext as _, SemanticVersion, SharedString, TestAppContext};
 use http_client::{FakeHttpClient, Response};
-use language::{BinaryStatus, LanguageConfig, LanguageMatcher, LanguageRegistry};
+use language::{BinaryStatus, LanguageMatcher, LanguageRegistry};
 use lsp::LanguageServerName;
 use node_runtime::NodeRuntime;
 use parking_lot::Mutex;
@@ -206,14 +206,11 @@ async fn test_extension_store(cx: &mut TestAppContext) {
                 ExtensionIndexLanguageEntry {
                     extension: "zed-ruby".into(),
                     path: "languages/erb".into(),
-                    config: LanguageConfig {
-                        grammar: Some("embedded_template".into()),
-                        hidden: false,
-                        matcher: LanguageMatcher {
-                            path_suffixes: vec!["erb".into()],
-                            first_line_pattern: None,
-                        },
-                        ..Default::default()
+                    grammar: Some("embedded_template".into()),
+                    hidden: false,
+                    matcher: LanguageMatcher {
+                        path_suffixes: vec!["erb".into()],
+                        first_line_pattern: None,
                     },
                 },
             ),
@@ -222,14 +219,11 @@ async fn test_extension_store(cx: &mut TestAppContext) {
                 ExtensionIndexLanguageEntry {
                     extension: "zed-ruby".into(),
                     path: "languages/ruby".into(),
-                    config: LanguageConfig {
-                        grammar: Some("ruby".into()),
-                        hidden: false,
-                        matcher: LanguageMatcher {
-                            path_suffixes: vec!["rb".into()],
-                            first_line_pattern: None,
-                        },
-                        ..Default::default()
+                    grammar: Some("ruby".into()),
+                    hidden: false,
+                    matcher: LanguageMatcher {
+                        path_suffixes: vec!["rb".into()],
+                        first_line_pattern: None,
                     },
                 },
             ),
@@ -301,18 +295,9 @@ async fn test_extension_store(cx: &mut TestAppContext) {
             index.languages.iter().zip(expected_index.languages.iter())
         {
             assert_eq!(actual_key, expected_key);
-            assert_eq!(
-                actual_language.config.grammar,
-                expected_language.config.grammar
-            );
-            assert_eq!(
-                actual_language.config.matcher,
-                expected_language.config.matcher
-            );
-            assert_eq!(
-                actual_language.config.hidden,
-                expected_language.config.hidden
-            );
+            assert_eq!(actual_language.grammar, expected_language.grammar);
+            assert_eq!(actual_language.matcher, expected_language.matcher);
+            assert_eq!(actual_language.hidden, expected_language.hidden);
         }
         assert_eq!(index.themes, expected_index.themes);
 
@@ -405,18 +390,9 @@ async fn test_extension_store(cx: &mut TestAppContext) {
             index.languages.iter().zip(expected_index.languages.iter())
         {
             assert_eq!(actual_key, expected_key);
-            assert_eq!(
-                actual_language.config.grammar,
-                expected_language.config.grammar
-            );
-            assert_eq!(
-                actual_language.config.matcher,
-                expected_language.config.matcher
-            );
-            assert_eq!(
-                actual_language.config.hidden,
-                expected_language.config.hidden
-            );
+            assert_eq!(actual_language.grammar, expected_language.grammar);
+            assert_eq!(actual_language.matcher, expected_language.matcher);
+            assert_eq!(actual_language.hidden, expected_language.hidden);
         }
 
         assert_eq!(index.extensions, expected_index.extensions);
@@ -470,18 +446,9 @@ async fn test_extension_store(cx: &mut TestAppContext) {
             .zip(expected_index.languages.iter())
         {
             assert_eq!(actual_key, expected_key);
-            assert_eq!(
-                actual_language.config.grammar,
-                expected_language.config.grammar
-            );
-            assert_eq!(
-                actual_language.config.matcher,
-                expected_language.config.matcher
-            );
-            assert_eq!(
-                actual_language.config.hidden,
-                expected_language.config.hidden
-            );
+            assert_eq!(actual_language.grammar, expected_language.grammar);
+            assert_eq!(actual_language.matcher, expected_language.matcher);
+            assert_eq!(actual_language.hidden, expected_language.hidden);
         }
 
         assert_eq!(
@@ -534,18 +501,9 @@ async fn test_extension_store(cx: &mut TestAppContext) {
             .zip(expected_index.languages.iter())
         {
             assert_eq!(actual_key, expected_key);
-            assert_eq!(
-                actual_language.config.grammar,
-                expected_language.config.grammar
-            );
-            assert_eq!(
-                actual_language.config.matcher,
-                expected_language.config.matcher
-            );
-            assert_eq!(
-                actual_language.config.hidden,
-                expected_language.config.hidden
-            );
+            assert_eq!(actual_language.grammar, expected_language.grammar);
+            assert_eq!(actual_language.matcher, expected_language.matcher);
+            assert_eq!(actual_language.hidden, expected_language.hidden);
         }
 
         assert_eq!(language_registry.language_names(), ["Plain Text"]);

crates/extension_host/src/headless_host.rs 🔗

@@ -149,7 +149,10 @@ impl HeadlessExtensionStore {
                 config.grammar = None;
 
                 this.proxy.register_language(
-                    config.clone(),
+                    config.name.clone(),
+                    None,
+                    config.matcher.clone(),
+                    config.hidden,
                     Arc::new(move || {
                         Ok(LoadedLanguage {
                             config: config.clone(),

crates/language/src/language.rs 🔗

@@ -666,7 +666,7 @@ pub struct CodeLabel {
     pub filter_range: Range<usize>,
 }
 
-#[derive(Clone, Deserialize, JsonSchema, Serialize, Debug)]
+#[derive(Clone, Deserialize, JsonSchema)]
 pub struct LanguageConfig {
     /// Human-readable name of the language.
     pub name: LanguageName,
@@ -694,20 +694,12 @@ pub struct LanguageConfig {
     pub auto_indent_on_paste: Option<bool>,
     /// A regex that is used to determine whether the indentation level should be
     /// increased in the following line.
-    #[serde(
-        default,
-        deserialize_with = "deserialize_regex",
-        serialize_with = "serialize_regex"
-    )]
+    #[serde(default, deserialize_with = "deserialize_regex")]
     #[schemars(schema_with = "regex_json_schema")]
     pub increase_indent_pattern: Option<Regex>,
     /// A regex that is used to determine whether the indentation level should be
     /// decreased in the following line.
-    #[serde(
-        default,
-        deserialize_with = "deserialize_regex",
-        serialize_with = "serialize_regex"
-    )]
+    #[serde(default, deserialize_with = "deserialize_regex")]
     #[schemars(schema_with = "regex_json_schema")]
     pub decrease_indent_pattern: Option<Regex>,
     /// A list of characters that trigger the automatic insertion of a closing
@@ -762,7 +754,7 @@ pub struct LanguageConfig {
     pub completion_query_characters: HashSet<char>,
     /// A list of preferred debuggers for this language.
     #[serde(default)]
-    pub debuggers: IndexSet<String>,
+    pub debuggers: IndexSet<SharedString>,
 }
 
 #[derive(Clone, Debug, Serialize, Deserialize, Default, JsonSchema)]
@@ -781,7 +773,7 @@ pub struct LanguageMatcher {
 }
 
 /// The configuration for JSX tag auto-closing.
-#[derive(Clone, Deserialize, JsonSchema, Serialize, Debug)]
+#[derive(Clone, Deserialize, JsonSchema)]
 pub struct JsxTagAutoCloseConfig {
     /// The name of the node for a opening tag
     pub open_tag_node_name: String,
@@ -822,7 +814,7 @@ pub struct LanguageScope {
     override_id: Option<u32>,
 }
 
-#[derive(Clone, Deserialize, Default, Debug, JsonSchema, Serialize)]
+#[derive(Clone, Deserialize, Default, Debug, JsonSchema)]
 pub struct LanguageConfigOverride {
     #[serde(default)]
     pub line_comments: Override<Vec<Arc<str>>>,
@@ -949,7 +941,7 @@ pub struct FakeLspAdapter {
 ///
 /// This struct includes settings for defining which pairs of characters are considered brackets and
 /// also specifies any language-specific scopes where these pairs should be ignored for bracket matching purposes.
-#[derive(Clone, Debug, Default, JsonSchema, Serialize)]
+#[derive(Clone, Debug, Default, JsonSchema)]
 pub struct BracketPairConfig {
     /// A list of character pairs that should be treated as brackets in the context of a given language.
     pub pairs: Vec<BracketPair>,
@@ -999,7 +991,7 @@ impl<'de> Deserialize<'de> for BracketPairConfig {
 
 /// Describes a single bracket pair and how an editor should react to e.g. inserting
 /// an opening bracket or to a newline character insertion in between `start` and `end` characters.
-#[derive(Clone, Debug, Default, Deserialize, PartialEq, JsonSchema, Serialize)]
+#[derive(Clone, Debug, Default, Deserialize, PartialEq, JsonSchema)]
 pub struct BracketPair {
     /// Starting substring for a bracket.
     pub start: String,

crates/language/src/language_registry.rs 🔗

@@ -145,24 +145,25 @@ pub enum BinaryStatus {
 #[derive(Clone)]
 pub struct AvailableLanguage {
     id: LanguageId,
-    config: LanguageConfig,
+    name: LanguageName,
+    grammar: Option<Arc<str>>,
+    matcher: LanguageMatcher,
+    hidden: bool,
     load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
     loaded: bool,
 }
 
 impl AvailableLanguage {
     pub fn name(&self) -> LanguageName {
-        self.config.name.clone()
+        self.name.clone()
     }
 
     pub fn matcher(&self) -> &LanguageMatcher {
-        &self.config.matcher
+        &self.matcher
     }
+
     pub fn hidden(&self) -> bool {
-        self.config.hidden
-    }
-    pub fn config(&self) -> &LanguageConfig {
-        &self.config
+        self.hidden
     }
 }
 
@@ -326,7 +327,10 @@ impl LanguageRegistry {
     #[cfg(any(feature = "test-support", test))]
     pub fn register_test_language(&self, config: LanguageConfig) {
         self.register_language(
-            config.clone(),
+            config.name.clone(),
+            config.grammar.clone(),
+            config.matcher.clone(),
+            config.hidden,
             Arc::new(move || {
                 Ok(LoadedLanguage {
                     config: config.clone(),
@@ -485,14 +489,18 @@ impl LanguageRegistry {
     /// Adds a language to the registry, which can be loaded if needed.
     pub fn register_language(
         &self,
-        config: LanguageConfig,
+        name: LanguageName,
+        grammar_name: Option<Arc<str>>,
+        matcher: LanguageMatcher,
+        hidden: bool,
         load: Arc<dyn Fn() -> Result<LoadedLanguage> + 'static + Send + Sync>,
     ) {
         let state = &mut *self.state.write();
 
         for existing_language in &mut state.available_languages {
-            if existing_language.config.name == config.name {
-                existing_language.config = config;
+            if existing_language.name == name {
+                existing_language.grammar = grammar_name;
+                existing_language.matcher = matcher;
                 existing_language.load = load;
                 return;
             }
@@ -500,8 +508,11 @@ impl LanguageRegistry {
 
         state.available_languages.push(AvailableLanguage {
             id: LanguageId::new(),
-            config,
+            name,
+            grammar: grammar_name,
+            matcher,
             load,
+            hidden,
             loaded: false,
         });
         state.version += 1;
@@ -547,7 +558,7 @@ impl LanguageRegistry {
         let mut result = state
             .available_languages
             .iter()
-            .filter_map(|l| l.loaded.not().then_some(l.config.name.to_string()))
+            .filter_map(|l| l.loaded.not().then_some(l.name.to_string()))
             .chain(state.languages.iter().map(|l| l.config.name.to_string()))
             .collect::<Vec<_>>();
         result.sort_unstable_by_key(|language_name| language_name.to_lowercase());
@@ -566,7 +577,10 @@ impl LanguageRegistry {
         let mut state = self.state.write();
         state.available_languages.push(AvailableLanguage {
             id: language.id,
-            config: language.config.clone(),
+            name: language.name(),
+            grammar: language.config.grammar.clone(),
+            matcher: language.config.matcher.clone(),
+            hidden: language.config.hidden,
             load: Arc::new(|| Err(anyhow!("already loaded"))),
             loaded: true,
         });
@@ -635,7 +649,7 @@ impl LanguageRegistry {
         state
             .available_languages
             .iter()
-            .find(|l| l.config.name.0.as_ref() == name)
+            .find(|l| l.name.0.as_ref() == name)
             .cloned()
     }
 
@@ -752,11 +766,8 @@ impl LanguageRegistry {
                 let current_match_type = best_language_match
                     .as_ref()
                     .map_or(LanguageMatchPrecedence::default(), |(_, score)| *score);
-                let language_score = callback(
-                    &language.config.name,
-                    &language.config.matcher,
-                    current_match_type,
-                );
+                let language_score =
+                    callback(&language.name, &language.matcher, current_match_type);
                 debug_assert!(
                     language_score.is_none_or(|new_score| new_score > current_match_type),
                     "Matching callback should only return a better match than the current one"
@@ -804,7 +815,7 @@ impl LanguageRegistry {
                 let this = self.clone();
 
                 let id = language.id;
-                let name = language.config.name.clone();
+                let name = language.name.clone();
                 let language_load = language.load.clone();
 
                 self.executor
@@ -1120,7 +1131,7 @@ impl LanguageRegistryState {
         self.languages
             .retain(|language| !languages_to_remove.contains(&language.name()));
         self.available_languages
-            .retain(|language| !languages_to_remove.contains(&language.config.name));
+            .retain(|language| !languages_to_remove.contains(&language.name));
         self.grammars
             .retain(|name, _| !grammars_to_remove.contains(name));
         self.version += 1;

crates/language_extension/src/language_extension.rs 🔗

@@ -5,7 +5,7 @@ use std::sync::Arc;
 
 use anyhow::Result;
 use extension::{ExtensionGrammarProxy, ExtensionHostProxy, ExtensionLanguageProxy};
-use language::{LanguageConfig, LanguageName, LanguageRegistry, LoadedLanguage};
+use language::{LanguageMatcher, LanguageName, LanguageRegistry, LoadedLanguage};
 
 pub fn init(
     extension_host_proxy: Arc<ExtensionHostProxy>,
@@ -31,10 +31,14 @@ impl ExtensionGrammarProxy for LanguageServerRegistryProxy {
 impl ExtensionLanguageProxy for LanguageServerRegistryProxy {
     fn register_language(
         &self,
-        language: LanguageConfig,
+        language: LanguageName,
+        grammar: Option<Arc<str>>,
+        matcher: LanguageMatcher,
+        hidden: bool,
         load: Arc<dyn Fn() -> Result<LoadedLanguage> + Send + Sync + 'static>,
     ) {
-        self.language_registry.register_language(language, load);
+        self.language_registry
+            .register_language(language, grammar, matcher, hidden, load);
     }
 
     fn remove_languages(

crates/languages/src/lib.rs 🔗

@@ -325,7 +325,10 @@ fn register_language(
         languages.register_lsp_adapter(config.name.clone(), adapter);
     }
     languages.register_language(
-        config.clone(),
+        config.name.clone(),
+        config.grammar.clone(),
+        config.matcher.clone(),
+        config.hidden,
         Arc::new(move || {
             Ok(LoadedLanguage {
                 config: config.clone(),