Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions crates/editor/src/jsx_tag_auto_close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 4 additions & 0 deletions crates/language/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3796,6 +3796,10 @@ impl BufferSnapshot {
.layers_for_range(range, &self.text, include_hidden)
}

pub fn syntax_layers_languages(&self) -> impl Iterator<Item = &Arc<Language>> {
self.syntax.languages(&self, true)
}

pub fn smallest_syntax_layer_containing<D: ToOffset>(
&self,
range: Range<D>,
Expand Down
24 changes: 24 additions & 0 deletions crates/language/src/syntax_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,30 @@ impl SyntaxSnapshot {
)
}

pub fn languages<'a>(
&'a self,
buffer: &'a BufferSnapshot,
include_hidden: bool,
) -> impl Iterator<Item = &'a Arc<Language>> {
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<SyntaxLayer<'a>> {
self.layers_for_range(0..buffer.len(), buffer, true)
Expand Down
81 changes: 81 additions & 0 deletions crates/language/src/syntax_map/syntax_map_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Vec<_>>();
let all_layer_language_names = syntax_map
.layers_for_range(0..buffer.len(), &buffer, true)
.map(|layer| layer.language.name().to_string())
.collect::<Vec<_>>();

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::<Vec<_>>();
let visible_layer_language_names = syntax_map
.layers_for_range(0..buffer.len(), &buffer, false)
.map(|layer| layer.language.name().to_string())
.collect::<Vec<_>>();

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()));
Expand Down