diff --git a/crates/editor/src/jsx_tag_auto_close.rs b/crates/editor/src/jsx_tag_auto_close.rs index 8d8f8d43b1ad1d374b130a9b4bc83297e4a76214..538173c45e51697f2a648c1ed3c97c3d6c828565 100644 --- a/crates/editor/src/jsx_tag_auto_close.rs +++ b/crates/editor/src/jsx_tag_auto_close.rs @@ -318,8 +318,7 @@ pub(crate) fn refresh_enabled_in_any_buffer( let buffer = buffer.read(cx); let snapshot = buffer.snapshot(); - for syntax_layer in snapshot.syntax_layers() { - let language = syntax_layer.language; + for language in snapshot.syntax_layers_languages() { if language.config().jsx_tag_auto_close.is_none() { continue; } diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 998bc23e8ee4deb8d5ef547f7992d79e6bc6d13a..c609c51ef995972000010e837d6c731bbf9a2496 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -3796,6 +3796,10 @@ impl BufferSnapshot { .layers_for_range(range, &self.text, include_hidden) } + pub fn syntax_layers_languages(&self) -> impl Iterator> { + self.syntax.languages(&self, true) + } + pub fn smallest_syntax_layer_containing( &self, range: Range, diff --git a/crates/language/src/syntax_map.rs b/crates/language/src/syntax_map.rs index 2922e359d2b8f610a3c4ffb365270eb94cc4f50c..d1da17d9a380224b34d5f809f6bee1ccaba46a29 100644 --- a/crates/language/src/syntax_map.rs +++ b/crates/language/src/syntax_map.rs @@ -971,6 +971,30 @@ impl SyntaxSnapshot { ) } + pub fn languages<'a>( + &'a self, + buffer: &'a BufferSnapshot, + include_hidden: bool, + ) -> impl Iterator> { + let mut cursor = self.layers.cursor::<()>(buffer); + cursor.next(); + iter::from_fn(move || { + while let Some(layer) = cursor.item() { + let mut info = None; + if let SyntaxLayerContent::Parsed { language, .. } = &layer.content { + if include_hidden || !language.config.hidden { + info = Some(language); + } + } + cursor.next(); + if info.is_some() { + return info; + } + } + None + }) + } + #[cfg(test)] pub fn layers<'a>(&'a self, buffer: &'a BufferSnapshot) -> Vec> { self.layers_for_range(0..buffer.len(), buffer, true) diff --git a/crates/language/src/syntax_map/syntax_map_tests.rs b/crates/language/src/syntax_map/syntax_map_tests.rs index 2ee37f19df022a8c3fe1a27924c1542424690b22..b7fec897b98aed7902cd25de65e008ba58ee55f9 100644 --- a/crates/language/src/syntax_map/syntax_map_tests.rs +++ b/crates/language/src/syntax_map/syntax_map_tests.rs @@ -180,6 +180,87 @@ fn test_syntax_map_layers_for_range(cx: &mut App) { ); } +#[gpui::test] +fn test_syntax_map_languages_match_layers_for_range(cx: &mut App) { + let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone())); + let markdown = markdown_lang(); + let markdown_inline = Arc::new(markdown_inline_lang()); + registry.add(markdown.clone()); + registry.add(markdown_inline); + registry.add(rust_lang()); + + let buffer = Buffer::new( + ReplicaId::LOCAL, + BufferId::new(1).unwrap(), + r#" + This is `inline`. + + ```rs + fn a() {} + ``` + "# + .unindent(), + ); + + let mut syntax_map = SyntaxMap::new(&buffer); + syntax_map.set_language_registry(registry); + syntax_map.reparse(markdown, &buffer); + + let all_language_names = syntax_map + .languages(&buffer, true) + .map(|language| language.name().to_string()) + .collect::>(); + let all_layer_language_names = syntax_map + .layers_for_range(0..buffer.len(), &buffer, true) + .map(|layer| layer.language.name().to_string()) + .collect::>(); + + assert_eq!(all_language_names, all_layer_language_names); + assert!( + all_language_names + .iter() + .any(|language_name| language_name == "Markdown-Inline"), + "expected hidden languages to be included when include_hidden is true" + ); + assert!( + all_language_names + .iter() + .any(|language_name| language_name == "Markdown") + ); + assert!( + all_language_names + .iter() + .any(|language_name| language_name == "Rust") + ); + + let visible_language_names = syntax_map + .languages(&buffer, false) + .map(|language| language.name().to_string()) + .collect::>(); + let visible_layer_language_names = syntax_map + .layers_for_range(0..buffer.len(), &buffer, false) + .map(|layer| layer.language.name().to_string()) + .collect::>(); + + assert_eq!(visible_language_names, visible_layer_language_names); + assert!( + !visible_language_names + .iter() + .any(|language_name| language_name == "Markdown-Inline"), + "expected hidden languages to be excluded when include_hidden is false" + ); + assert!( + visible_language_names + .iter() + .any(|language_name| language_name == "Markdown") + ); + assert!( + visible_language_names + .iter() + .any(|language_name| language_name == "Rust") + ); +} + #[gpui::test] fn test_dynamic_language_injection(cx: &mut App) { let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));