syntax_map.rs

  1use crate::{
  2    Grammar, InjectionConfig, Language, LanguageRegistry, QueryCursorHandle, TextProvider,
  3    ToTreeSitterPoint,
  4};
  5use collections::HashMap;
  6use std::{
  7    borrow::Cow, cell::RefCell, cmp::Ordering, collections::BinaryHeap, ops::Range, sync::Arc,
  8};
  9use sum_tree::{Bias, SeekTarget, SumTree};
 10use text::{Anchor, BufferSnapshot, OffsetRangeExt, Point, Rope, ToOffset};
 11use tree_sitter::{Parser, Tree};
 12use util::post_inc;
 13
 14thread_local! {
 15    static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
 16}
 17
 18#[derive(Default)]
 19pub struct SyntaxMap {
 20    version: clock::Global,
 21    snapshot: SyntaxSnapshot,
 22    language_registry: Option<Arc<LanguageRegistry>>,
 23}
 24
 25#[derive(Clone, Default)]
 26pub struct SyntaxSnapshot {
 27    layers: SumTree<SyntaxLayer>,
 28}
 29
 30#[derive(Clone)]
 31struct SyntaxLayer {
 32    depth: usize,
 33    range: Range<Anchor>,
 34    tree: tree_sitter::Tree,
 35    language: Arc<Language>,
 36}
 37
 38#[derive(Debug, Clone)]
 39struct SyntaxLayerSummary {
 40    max_depth: usize,
 41    range: Range<Anchor>,
 42    last_layer_range: Range<Anchor>,
 43}
 44
 45#[derive(Clone, Debug)]
 46struct Depth(usize);
 47
 48#[derive(Clone, Debug)]
 49struct MaxPosition(Anchor);
 50
 51enum ReparseStep {
 52    CreateLayer {
 53        depth: usize,
 54        language: Arc<Language>,
 55        ranges: Vec<tree_sitter::Range>,
 56    },
 57    EnterChangedRange {
 58        id: usize,
 59        depth: usize,
 60        range: Range<usize>,
 61    },
 62    LeaveChangedRange {
 63        id: usize,
 64        depth: usize,
 65        range: Range<usize>,
 66    },
 67}
 68
 69impl SyntaxMap {
 70    pub fn new() -> Self {
 71        Self::default()
 72    }
 73
 74    pub fn set_language_registry(&mut self, registry: Arc<LanguageRegistry>) {
 75        self.language_registry = Some(registry);
 76    }
 77
 78    pub fn snapshot(&self) -> SyntaxSnapshot {
 79        self.snapshot.clone()
 80    }
 81
 82    pub fn interpolate(&mut self, text: &BufferSnapshot) {
 83        self.snapshot.interpolate(&self.version, text);
 84        self.version = text.version.clone();
 85    }
 86
 87    pub fn reparse(&mut self, language: Arc<Language>, text: &BufferSnapshot) {
 88        self.version = text.version.clone();
 89        self.snapshot
 90            .reparse(self.language_registry.clone(), language, text);
 91    }
 92}
 93
 94// Assumptions:
 95// * The maximum depth is small (< 5)
 96// * For a given depth, the number of layers that touch a given range
 97//   is small (usually only 1)
 98
 99//                                  |change|
100// 0 (............................................................)
101// 1  (...............................................)
102// 1                         (................)
103// 1                                                    (.......)
104// 2      (....)
105// 2       (....)
106// 2              (.......)
107// 2                        (...)
108// 2                               (.........)
109// 2                                           (...)
110// 3       (.)
111// 3              (.)
112// 3                  (..)
113// 3                               (..)
114// 3                                   (..)
115// 3                                       (.)
116
117impl SyntaxSnapshot {
118    pub fn interpolate(&mut self, current_version: &clock::Global, text: &BufferSnapshot) {
119        let edits = text
120            .edits_since::<(usize, Point)>(&current_version)
121            .collect::<Vec<_>>();
122        if edits.is_empty() {
123            return;
124        }
125
126        let mut layers = SumTree::new();
127        let max_depth = self.layers.summary().max_depth;
128        let mut cursor = self.layers.cursor::<SyntaxLayerSummary>();
129        cursor.next(&text);
130
131        for depth in 0..max_depth {
132            let mut edits = &edits[..];
133            layers.push_tree(cursor.slice(&Depth(depth), Bias::Left, text), text);
134
135            while let Some(layer) = cursor.item() {
136                let mut endpoints = text.summaries_for_anchors::<(usize, Point), _>([
137                    &layer.range.start,
138                    &layer.range.end,
139                ]);
140                let layer_range = endpoints.next().unwrap()..endpoints.next().unwrap();
141                let start_byte = layer_range.start.0;
142                let start_point = layer_range.start.1;
143
144                // Preserve any layers at this depth that precede the first edit.
145                let first_edit = if let Some(edit) = edits.first() {
146                    edit
147                } else {
148                    break;
149                };
150                if first_edit.new.start.0 > layer_range.end.0 {
151                    layers.push_tree(
152                        cursor.slice(
153                            &(
154                                Depth(depth),
155                                MaxPosition(text.anchor_before(first_edit.new.start.0)),
156                            ),
157                            Bias::Left,
158                            text,
159                        ),
160                        text,
161                    );
162                    continue;
163                }
164
165                // Preserve any layers at this depth that follow the last edit.
166                let last_edit = edits.last().unwrap();
167                if last_edit.new.end.0 < layer_range.start.0 {
168                    break;
169                }
170
171                let mut layer = layer.clone();
172                for (i, edit) in edits.iter().enumerate().rev() {
173                    // Ignore any edits that start after the end of this layer.
174                    if edit.new.start.0 > layer_range.end.0 {
175                        continue;
176                    }
177
178                    // Ignore edits that end before the start of this layer, and don't consider them
179                    // for any subsequent layers at this same depth.
180                    if edit.new.end.0 <= start_byte {
181                        edits = &edits[i + 1..];
182                        break;
183                    }
184
185                    // Apply any edits that intersect this layer to the layer's syntax tree.
186                    if edit.new.start.0 >= start_byte {
187                        layer.tree.edit(&tree_sitter::InputEdit {
188                            start_byte: edit.new.start.0 - start_byte,
189                            old_end_byte: edit.new.start.0 - start_byte
190                                + (edit.old.end.0 - edit.old.start.0),
191                            new_end_byte: edit.new.end.0 - start_byte,
192                            start_position: (edit.new.start.1 - start_point).to_ts_point(),
193                            old_end_position: (edit.new.start.1 - start_point
194                                + (edit.old.end.1 - edit.old.start.1))
195                                .to_ts_point(),
196                            new_end_position: (edit.new.end.1 - start_point).to_ts_point(),
197                        });
198                    } else {
199                        layer.tree.edit(&tree_sitter::InputEdit {
200                            start_byte: 0,
201                            old_end_byte: edit.new.end.0 - start_byte,
202                            new_end_byte: 0,
203                            start_position: Default::default(),
204                            old_end_position: (edit.new.end.1 - start_point).to_ts_point(),
205                            new_end_position: Default::default(),
206                        });
207                        break;
208                    }
209                }
210
211                layers.push(layer, text);
212                cursor.next(text);
213            }
214        }
215
216        layers.push_tree(cursor.suffix(&text), &text);
217        drop(cursor);
218        self.layers = layers;
219    }
220
221    pub fn reparse(
222        &mut self,
223        registry: Option<Arc<LanguageRegistry>>,
224        language: Arc<Language>,
225        text: &BufferSnapshot,
226    ) {
227        let mut cursor = self.layers.cursor::<SyntaxLayerSummary>();
228        cursor.next(&text);
229        let mut layers = SumTree::new();
230
231        let mut next_change_id = 0;
232        let mut current_changes = HashMap::default();
233        let mut queue = BinaryHeap::new();
234        queue.push(ReparseStep::CreateLayer {
235            depth: 0,
236            language: language.clone(),
237            ranges: Vec::new(),
238        });
239
240        while let Some(step) = queue.pop() {
241            match step {
242                ReparseStep::CreateLayer {
243                    depth,
244                    language,
245                    ranges,
246                } => {
247                    let range;
248                    let start_point;
249                    let start_byte;
250                    let end_byte;
251                    if let Some((first, last)) = ranges.first().zip(ranges.last()) {
252                        start_point = first.start_point;
253                        start_byte = first.start_byte;
254                        end_byte = last.end_byte;
255                        range = text.anchor_before(start_byte)..text.anchor_after(end_byte);
256                    } else {
257                        start_point = Point::zero().to_ts_point();
258                        start_byte = 0;
259                        end_byte = text.len();
260                        range = Anchor::MIN..Anchor::MAX;
261                    };
262
263                    let target = (Depth(depth), range.clone());
264                    if target.cmp(cursor.start(), &text).is_gt() {
265                        if current_changes.is_empty() {
266                            let slice = cursor.slice(&target, Bias::Left, text);
267                            layers.push_tree(slice, &text);
268                        } else {
269                            while let Some(layer) = cursor.item() {
270                                if layer.depth > depth
271                                    || layer.depth == depth
272                                        && layer.range.start.cmp(&range.end, text).is_ge()
273                                {
274                                    break;
275                                }
276                                if !layer_is_changed(layer, text, &current_changes) {
277                                    layers.push(layer.clone(), text);
278                                }
279                                cursor.next(text);
280                            }
281                        }
282                    }
283
284                    let mut old_layer = cursor.item();
285                    if let Some(layer) = old_layer {
286                        if layer.range.to_offset(text) == (start_byte..end_byte) {
287                            cursor.next(&text);
288                        } else {
289                            old_layer = None;
290                        }
291                    }
292
293                    let grammar = if let Some(grammar) = language.grammar.as_deref() {
294                        grammar
295                    } else {
296                        continue;
297                    };
298
299                    let tree;
300                    let changed_ranges;
301                    if let Some(old_layer) = old_layer {
302                        tree = parse_text(
303                            grammar,
304                            text.as_rope(),
305                            Some(old_layer.tree.clone()),
306                            ranges,
307                        );
308
309                        changed_ranges = old_layer
310                            .tree
311                            .changed_ranges(&tree)
312                            .map(|r| r.start_byte..r.end_byte)
313                            .collect();
314                    } else {
315                        tree = parse_text(grammar, text.as_rope(), None, ranges);
316                        changed_ranges = vec![0..end_byte - start_byte];
317                    }
318
319                    layers.push(
320                        SyntaxLayer {
321                            depth,
322                            range,
323                            tree: tree.clone(),
324                            language: language.clone(),
325                        },
326                        &text,
327                    );
328
329                    if let (Some((config, registry)), false) = (
330                        grammar.injection_config.as_ref().zip(registry.as_ref()),
331                        changed_ranges.is_empty(),
332                    ) {
333                        let depth = depth + 1;
334                        queue.extend(changed_ranges.iter().flat_map(|range| {
335                            let id = post_inc(&mut next_change_id);
336                            let range = start_byte + range.start..start_byte + range.end;
337                            [
338                                ReparseStep::EnterChangedRange {
339                                    id,
340                                    depth,
341                                    range: range.clone(),
342                                },
343                                ReparseStep::LeaveChangedRange {
344                                    id,
345                                    depth,
346                                    range: range.clone(),
347                                },
348                            ]
349                        }));
350
351                        get_injections(
352                            config,
353                            text,
354                            &tree,
355                            registry,
356                            depth,
357                            start_byte,
358                            Point::from_ts_point(start_point),
359                            &changed_ranges,
360                            &mut queue,
361                        );
362                    }
363                }
364                ReparseStep::EnterChangedRange { id, depth, range } => {
365                    let range = text.anchor_before(range.start)..text.anchor_after(range.end);
366                    if current_changes.is_empty() {
367                        let target = (Depth(depth), range.start..Anchor::MAX);
368                        let slice = cursor.slice(&target, Bias::Left, text);
369                        layers.push_tree(slice, text);
370                    } else {
371                        while let Some(layer) = cursor.item() {
372                            if layer.depth > depth
373                                || layer.depth == depth
374                                    && layer.range.end.cmp(&range.start, text).is_gt()
375                            {
376                                break;
377                            }
378                            if !layer_is_changed(layer, text, &current_changes) {
379                                layers.push(layer.clone(), text);
380                            }
381                            cursor.next(text);
382                        }
383                    }
384
385                    current_changes.insert(id, range);
386                }
387                ReparseStep::LeaveChangedRange { id, depth, range } => {
388                    let range = text.anchor_before(range.start)..text.anchor_after(range.end);
389                    while let Some(layer) = cursor.item() {
390                        if layer.depth > depth
391                            || layer.depth == depth
392                                && layer.range.start.cmp(&range.end, text).is_ge()
393                        {
394                            break;
395                        }
396                        if !layer_is_changed(layer, text, &current_changes) {
397                            layers.push(layer.clone(), text);
398                        }
399                        cursor.next(text);
400                    }
401
402                    current_changes.remove(&id);
403                }
404            }
405        }
406
407        let slice = cursor.suffix(&text);
408        layers.push_tree(slice, &text);
409        drop(cursor);
410        self.layers = layers;
411    }
412
413    pub fn layers_for_range<'a, T: ToOffset>(
414        &self,
415        range: Range<T>,
416        buffer: &BufferSnapshot,
417    ) -> Vec<(Tree, &Grammar)> {
418        let start = buffer.anchor_before(range.start.to_offset(buffer));
419        let end = buffer.anchor_after(range.end.to_offset(buffer));
420
421        let mut cursor = self.layers.filter::<_, ()>(|summary| {
422            let is_before_start = summary.range.end.cmp(&start, buffer).is_lt();
423            let is_after_end = summary.range.start.cmp(&end, buffer).is_gt();
424            !is_before_start && !is_after_end
425        });
426
427        let mut result = Vec::new();
428        cursor.next(buffer);
429        while let Some(item) = cursor.item() {
430            if let Some(grammar) = &item.language.grammar {
431                result.push((item.tree.clone(), grammar.as_ref()));
432            }
433            cursor.next(buffer)
434        }
435
436        result
437    }
438}
439
440fn parse_text(
441    grammar: &Grammar,
442    text: &Rope,
443    old_tree: Option<Tree>,
444    mut ranges: Vec<tree_sitter::Range>,
445) -> Tree {
446    let (start_byte, start_point) = ranges
447        .first()
448        .map(|range| (range.start_byte, Point::from_ts_point(range.start_point)))
449        .unwrap_or_default();
450
451    for range in &mut ranges {
452        range.start_byte -= start_byte;
453        range.end_byte -= start_byte;
454        range.start_point = (Point::from_ts_point(range.start_point) - start_point).to_ts_point();
455        range.end_point = (Point::from_ts_point(range.end_point) - start_point).to_ts_point();
456    }
457
458    PARSER.with(|parser| {
459        let mut parser = parser.borrow_mut();
460        let mut chunks = text.chunks_in_range(start_byte..text.len());
461        parser
462            .set_included_ranges(&ranges)
463            .expect("overlapping ranges");
464        parser
465            .set_language(grammar.ts_language)
466            .expect("incompatible grammar");
467        parser
468            .parse_with(
469                &mut move |offset, _| {
470                    chunks.seek(start_byte + offset);
471                    chunks.next().unwrap_or("").as_bytes()
472                },
473                old_tree.as_ref(),
474            )
475            .expect("invalid language")
476    })
477}
478
479fn get_injections(
480    config: &InjectionConfig,
481    text: &BufferSnapshot,
482    tree: &Tree,
483    language_registry: &LanguageRegistry,
484    depth: usize,
485    start_byte: usize,
486    start_point: Point,
487    query_ranges: &[Range<usize>],
488    stack: &mut BinaryHeap<ReparseStep>,
489) -> bool {
490    let mut result = false;
491    let mut query_cursor = QueryCursorHandle::new();
492    let mut prev_match = None;
493    for query_range in query_ranges {
494        query_cursor.set_byte_range(query_range.start..query_range.end);
495        for mat in query_cursor.matches(
496            &config.query,
497            tree.root_node(),
498            TextProvider(text.as_rope()),
499        ) {
500            let content_ranges = mat
501                .nodes_for_capture_index(config.content_capture_ix)
502                .map(|node| tree_sitter::Range {
503                    start_byte: start_byte + node.start_byte(),
504                    end_byte: start_byte + node.end_byte(),
505                    start_point: (start_point + Point::from_ts_point(node.start_position()))
506                        .to_ts_point(),
507                    end_point: (start_point + Point::from_ts_point(node.end_position()))
508                        .to_ts_point(),
509                })
510                .collect::<Vec<_>>();
511            if content_ranges.is_empty() {
512                continue;
513            }
514
515            // Avoid duplicate matches if two changed ranges intersect the same injection.
516            let content_range =
517                content_ranges.first().unwrap().start_byte..content_ranges.last().unwrap().end_byte;
518            if let Some((last_pattern_ix, last_range)) = &prev_match {
519                if mat.pattern_index == *last_pattern_ix && content_range == *last_range {
520                    continue;
521                }
522            }
523            prev_match = Some((mat.pattern_index, content_range));
524
525            let language_name = config.languages_by_pattern_ix[mat.pattern_index]
526                .as_ref()
527                .map(|s| Cow::Borrowed(s.as_ref()))
528                .or_else(|| {
529                    let ix = config.language_capture_ix?;
530                    let node = mat.nodes_for_capture_index(ix).next()?;
531                    Some(Cow::Owned(
532                        text.text_for_range(
533                            start_byte + node.start_byte()..start_byte + node.end_byte(),
534                        )
535                        .collect(),
536                    ))
537                });
538
539            if let Some(language_name) = language_name {
540                if let Some(language) = language_registry.get_language(language_name.as_ref()) {
541                    result = true;
542                    stack.push(ReparseStep::CreateLayer {
543                        depth,
544                        language,
545                        ranges: content_ranges,
546                    })
547                }
548            }
549        }
550    }
551    result
552}
553
554fn layer_is_changed(
555    layer: &SyntaxLayer,
556    text: &BufferSnapshot,
557    changed_ranges: &HashMap<usize, Range<Anchor>>,
558) -> bool {
559    changed_ranges.values().any(|range| {
560        let is_before_layer = range.end.cmp(&layer.range.start, text).is_le();
561        let is_after_layer = range.start.cmp(&layer.range.end, text).is_ge();
562        !is_before_layer && !is_after_layer
563    })
564}
565
566impl std::ops::Deref for SyntaxMap {
567    type Target = SyntaxSnapshot;
568
569    fn deref(&self) -> &Self::Target {
570        &self.snapshot
571    }
572}
573
574impl ReparseStep {
575    fn sort_key(&self) -> (usize, Range<usize>) {
576        match self {
577            ReparseStep::CreateLayer { depth, ranges, .. } => (
578                *depth,
579                ranges.first().map_or(0, |r| r.start_byte)
580                    ..ranges.last().map_or(usize::MAX, |r| r.end_byte),
581            ),
582            ReparseStep::EnterChangedRange { depth, range, .. } => {
583                (*depth, range.start..usize::MAX)
584            }
585            ReparseStep::LeaveChangedRange { depth, range, .. } => (*depth, range.end..usize::MAX),
586        }
587    }
588}
589
590impl PartialEq for ReparseStep {
591    fn eq(&self, _: &Self) -> bool {
592        false
593    }
594}
595
596impl Eq for ReparseStep {}
597
598impl PartialOrd for ReparseStep {
599    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
600        Some(self.cmp(&other))
601    }
602}
603
604impl Ord for ReparseStep {
605    fn cmp(&self, other: &Self) -> Ordering {
606        let (depth_a, range_a) = self.sort_key();
607        let (depth_b, range_b) = other.sort_key();
608        Ord::cmp(&depth_b, &depth_a)
609            .then_with(|| Ord::cmp(&range_b.start, &range_a.start))
610            .then_with(|| Ord::cmp(&range_a.end, &range_b.end))
611    }
612}
613
614impl Default for SyntaxLayerSummary {
615    fn default() -> Self {
616        Self {
617            max_depth: 0,
618            range: Anchor::MAX..Anchor::MIN,
619            last_layer_range: Anchor::MIN..Anchor::MAX,
620        }
621    }
622}
623
624impl sum_tree::Summary for SyntaxLayerSummary {
625    type Context = BufferSnapshot;
626
627    fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
628        if other.max_depth > self.max_depth {
629            *self = other.clone();
630        } else {
631            if other.range.start.cmp(&self.range.start, buffer).is_lt() {
632                self.range.start = other.range.start;
633            }
634            if other.range.end.cmp(&self.range.end, buffer).is_gt() {
635                self.range.end = other.range.end;
636            }
637            self.last_layer_range = other.last_layer_range.clone();
638        }
639    }
640}
641
642impl<'a> SeekTarget<'a, SyntaxLayerSummary, SyntaxLayerSummary> for Depth {
643    fn cmp(&self, cursor_location: &SyntaxLayerSummary, _: &BufferSnapshot) -> Ordering {
644        Ord::cmp(&self.0, &cursor_location.max_depth)
645    }
646}
647
648impl<'a> SeekTarget<'a, SyntaxLayerSummary, SyntaxLayerSummary> for (Depth, MaxPosition) {
649    fn cmp(&self, cursor_location: &SyntaxLayerSummary, text: &BufferSnapshot) -> Ordering {
650        self.0
651            .cmp(&cursor_location, text)
652            .then_with(|| (self.1).0.cmp(&cursor_location.range.end, text))
653    }
654}
655
656impl<'a> SeekTarget<'a, SyntaxLayerSummary, SyntaxLayerSummary> for (Depth, Range<Anchor>) {
657    fn cmp(&self, cursor_location: &SyntaxLayerSummary, buffer: &BufferSnapshot) -> Ordering {
658        self.0
659            .cmp(&cursor_location, buffer)
660            .then_with(|| {
661                self.1
662                    .start
663                    .cmp(&cursor_location.last_layer_range.start, buffer)
664            })
665            .then_with(|| {
666                cursor_location
667                    .last_layer_range
668                    .end
669                    .cmp(&self.1.end, buffer)
670            })
671    }
672}
673
674impl sum_tree::Item for SyntaxLayer {
675    type Summary = SyntaxLayerSummary;
676
677    fn summary(&self) -> Self::Summary {
678        SyntaxLayerSummary {
679            max_depth: self.depth,
680            range: self.range.clone(),
681            last_layer_range: self.range.clone(),
682        }
683    }
684}
685
686impl std::fmt::Debug for SyntaxLayer {
687    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
688        f.debug_struct("SyntaxLayer")
689            .field("depth", &self.depth)
690            .field("range", &self.range)
691            .field("tree", &self.tree)
692            .finish()
693    }
694}
695
696#[cfg(test)]
697mod tests {
698    use super::*;
699    use crate::LanguageConfig;
700    use text::{Buffer, Point};
701    use unindent::Unindent as _;
702
703    #[gpui::test]
704    fn test_syntax_map_layers_for_range() {
705        let registry = Arc::new(LanguageRegistry::test());
706        let language = Arc::new(rust_lang());
707        registry.add(language.clone());
708
709        let mut buffer = Buffer::new(
710            0,
711            0,
712            r#"
713                fn a() {
714                    assert_eq!(
715                        b(vec![C {}]),
716                        vec![d.e],
717                    );
718                    println!("{}", f(|_| true));
719                }
720            "#
721            .unindent(),
722        );
723
724        let mut syntax_map = SyntaxMap::new();
725        syntax_map.set_language_registry(registry.clone());
726        syntax_map.reparse(language.clone(), &buffer);
727
728        assert_layers_for_range(
729            &syntax_map,
730            &buffer,
731            Point::new(2, 0)..Point::new(2, 0),
732            &[
733                "...(function_item ... (block (expression_statement (macro_invocation...",
734                "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
735            ],
736        );
737        assert_layers_for_range(
738            &syntax_map,
739            &buffer,
740            Point::new(2, 14)..Point::new(2, 16),
741            &[
742                "...(function_item ...",
743                "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
744                "...(array_expression (struct_expression ...",
745            ],
746        );
747        assert_layers_for_range(
748            &syntax_map,
749            &buffer,
750            Point::new(3, 14)..Point::new(3, 16),
751            &[
752                "...(function_item ...",
753                "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
754                "...(array_expression (field_expression ...",
755            ],
756        );
757        assert_layers_for_range(
758            &syntax_map,
759            &buffer,
760            Point::new(5, 12)..Point::new(5, 16),
761            &[
762                "...(function_item ...",
763                "...(call_expression ... (arguments (closure_expression ...",
764            ],
765        );
766
767        // Replace a vec! macro invocation with a plain slice, removing a syntactic layer.
768        let macro_name_range = range_for_text(&buffer, "vec!");
769        buffer.edit([(macro_name_range, "&")]);
770        syntax_map.interpolate(&buffer);
771        syntax_map.reparse(language.clone(), &buffer);
772
773        assert_layers_for_range(
774            &syntax_map,
775            &buffer,
776            Point::new(2, 14)..Point::new(2, 16),
777            &[
778                "...(function_item ...",
779                "...(tuple_expression (call_expression ... arguments: (arguments (reference_expression value: (array_expression...",
780            ],
781        );
782
783        // Put the vec! macro back, adding back the syntactic layer.
784        buffer.undo();
785        syntax_map.interpolate(&buffer);
786        syntax_map.reparse(language.clone(), &buffer);
787
788        assert_layers_for_range(
789            &syntax_map,
790            &buffer,
791            Point::new(2, 14)..Point::new(2, 16),
792            &[
793                "...(function_item ...",
794                "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
795                "...(array_expression (struct_expression ...",
796            ],
797        );
798    }
799
800    fn rust_lang() -> Language {
801        Language::new(
802            LanguageConfig {
803                name: "Rust".into(),
804                path_suffixes: vec!["rs".to_string()],
805                ..Default::default()
806            },
807            Some(tree_sitter_rust::language()),
808        )
809        .with_injection_query(
810            r#"
811                (macro_invocation
812                    (token_tree) @content
813                    (#set! "language" "rust"))
814            "#,
815        )
816        .unwrap()
817    }
818
819    fn range_for_text(buffer: &Buffer, text: &str) -> Range<usize> {
820        let start = buffer.as_rope().to_string().find(text).unwrap();
821        start..start + text.len()
822    }
823
824    fn assert_layers_for_range(
825        syntax_map: &SyntaxMap,
826        buffer: &BufferSnapshot,
827        range: Range<Point>,
828        expected_layers: &[&str],
829    ) {
830        let layers = syntax_map.layers_for_range(range, &buffer);
831        assert_eq!(
832            layers.len(),
833            expected_layers.len(),
834            "wrong number of layers"
835        );
836        for (i, (layer, expected_s_exp)) in layers.iter().zip(expected_layers.iter()).enumerate() {
837            let actual_s_exp = layer.0.root_node().to_sexp();
838            assert!(
839                string_contains_sequence(
840                    &actual_s_exp,
841                    &expected_s_exp.split("...").collect::<Vec<_>>()
842                ),
843                "layer {i}:\n\nexpected: {expected_s_exp}\nactual:   {actual_s_exp}",
844            );
845        }
846    }
847
848    pub fn string_contains_sequence(text: &str, parts: &[&str]) -> bool {
849        let mut last_part_end = 0;
850        for part in parts {
851            if let Some(start_ix) = text[last_part_end..].find(part) {
852                last_part_end = start_ix + part.len();
853            } else {
854                return false;
855            }
856        }
857        true
858    }
859}