syntax_map.rs

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