From f3509824e89b413713af9b60e3b5b7212abe4325 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 24 Jan 2023 12:55:49 +0100 Subject: [PATCH] WIP: Start on `SyntaxMapSnapshot::unknown_injection_languages` --- crates/language/src/syntax_map.rs | 50 ++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/crates/language/src/syntax_map.rs b/crates/language/src/syntax_map.rs index 7564d234e568b125343960d99deefec9753ce331..aa402bccd8293f5091c7ef52772c859de7ae7988 100644 --- a/crates/language/src/syntax_map.rs +++ b/crates/language/src/syntax_map.rs @@ -7,6 +7,7 @@ use std::{ cell::RefCell, cmp::{self, Ordering, Reverse}, collections::BinaryHeap, + iter, ops::{Deref, DerefMut, Range}, sync::Arc, }; @@ -133,6 +134,7 @@ struct SyntaxLayerSummary { range: Range, last_layer_range: Range, last_layer_language: Option, + contains_pending_layer: bool, } #[derive(Clone, Debug)] @@ -642,7 +644,7 @@ impl SyntaxSnapshot { }); cursor.next(buffer); - std::iter::from_fn(move || { + iter::from_fn(move || { while let Some(layer) = cursor.item() { if let SyntaxLayerContent::Parsed { tree, language } = &layer.content { let info = SyntaxLayerInfo { @@ -662,6 +664,27 @@ impl SyntaxSnapshot { None }) } + + pub fn unknown_injection_languages<'a>( + &'a self, + buffer: &'a BufferSnapshot, + ) -> impl 'a + Iterator> { + let mut cursor = self + .layers + .filter::<_, ()>(|summary| summary.contains_pending_layer); + cursor.next(buffer); + iter::from_fn(move || { + while let Some(layer) = cursor.item() { + if let SyntaxLayerContent::Pending { language_name } = &layer.content { + cursor.next(buffer); + return Some(language_name); + } else { + cursor.next(buffer); + } + } + None + }) + } } impl<'a> SyntaxMapCaptures<'a> { @@ -1356,6 +1379,7 @@ impl Default for SyntaxLayerSummary { range: Anchor::MAX..Anchor::MIN, last_layer_range: Anchor::MIN..Anchor::MAX, last_layer_language: None, + contains_pending_layer: false, } } } @@ -1377,6 +1401,7 @@ impl sum_tree::Summary for SyntaxLayerSummary { } self.last_layer_range = other.last_layer_range.clone(); self.last_layer_language = other.last_layer_language; + self.contains_pending_layer |= other.contains_pending_layer; } } @@ -1427,6 +1452,7 @@ impl sum_tree::Item for SyntaxLayer { range: self.range.clone(), last_layer_range: self.range.clone(), last_layer_language: self.content.language_id(), + contains_pending_layer: matches!(self.content, SyntaxLayerContent::Pending { .. }), } } } @@ -1715,6 +1741,28 @@ mod tests { "...(call method: (identifier) arguments: (argument_list (call method: (identifier) arguments: (argument_list) block: (block)...", ], ); + + // Replace Ruby with a language that hasn't been loaded yet. + let macro_name_range = range_for_text(&buffer, "ruby"); + buffer.edit([(macro_name_range, "erb")]); + syntax_map.interpolate(&buffer); + syntax_map.reparse(markdown.clone(), &buffer); + assert_layers_for_range( + &syntax_map, + &buffer, + Point::new(3, 0)..Point::new(3, 0), + &[ + "...(fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (code_fence_content) (fenced_code_block_delimiter..." + ], + ); + assert_eq!( + syntax_map + .unknown_injection_languages(&buffer) + .collect::>(), + vec![&Arc::from("erb")] + ); + + registry.add(Arc::new(erb_lang())); } #[gpui::test]