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, ToPoint};
 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(&self, buffer: &BufferSnapshot) -> Vec<(&Grammar, &Tree, (usize, Point))> {
414        self.layers
415            .iter()
416            .filter_map(|layer| {
417                if let Some(grammar) = &layer.language.grammar {
418                    Some((
419                        grammar.as_ref(),
420                        &layer.tree,
421                        (
422                            layer.range.start.to_offset(buffer),
423                            layer.range.start.to_point(buffer),
424                        ),
425                    ))
426                } else {
427                    None
428                }
429            })
430            .collect()
431    }
432
433    pub fn layers_for_range<'a, T: ToOffset>(
434        &self,
435        range: Range<T>,
436        buffer: &BufferSnapshot,
437    ) -> Vec<(&Grammar, &Tree, (usize, Point))> {
438        let start = buffer.anchor_before(range.start.to_offset(buffer));
439        let end = buffer.anchor_after(range.end.to_offset(buffer));
440
441        let mut cursor = self.layers.filter::<_, ()>(|summary| {
442            let is_before_start = summary.range.end.cmp(&start, buffer).is_lt();
443            let is_after_end = summary.range.start.cmp(&end, buffer).is_gt();
444            !is_before_start && !is_after_end
445        });
446
447        let mut result = Vec::new();
448        cursor.next(buffer);
449        while let Some(layer) = cursor.item() {
450            if let Some(grammar) = &layer.language.grammar {
451                result.push((
452                    grammar.as_ref(),
453                    &layer.tree,
454                    (
455                        layer.range.start.to_offset(buffer),
456                        layer.range.start.to_point(buffer),
457                    ),
458                ));
459            }
460            cursor.next(buffer)
461        }
462
463        result
464    }
465}
466
467fn parse_text(
468    grammar: &Grammar,
469    text: &Rope,
470    old_tree: Option<Tree>,
471    mut ranges: Vec<tree_sitter::Range>,
472) -> Tree {
473    let (start_byte, start_point) = ranges
474        .first()
475        .map(|range| (range.start_byte, Point::from_ts_point(range.start_point)))
476        .unwrap_or_default();
477
478    for range in &mut ranges {
479        range.start_byte -= start_byte;
480        range.end_byte -= start_byte;
481        range.start_point = (Point::from_ts_point(range.start_point) - start_point).to_ts_point();
482        range.end_point = (Point::from_ts_point(range.end_point) - start_point).to_ts_point();
483    }
484
485    PARSER.with(|parser| {
486        let mut parser = parser.borrow_mut();
487        let mut chunks = text.chunks_in_range(start_byte..text.len());
488        parser
489            .set_included_ranges(&ranges)
490            .expect("overlapping ranges");
491        parser
492            .set_language(grammar.ts_language)
493            .expect("incompatible grammar");
494        parser
495            .parse_with(
496                &mut move |offset, _| {
497                    chunks.seek(start_byte + offset);
498                    chunks.next().unwrap_or("").as_bytes()
499                },
500                old_tree.as_ref(),
501            )
502            .expect("invalid language")
503    })
504}
505
506fn get_injections(
507    config: &InjectionConfig,
508    text: &BufferSnapshot,
509    tree: &Tree,
510    language_registry: &LanguageRegistry,
511    depth: usize,
512    start_byte: usize,
513    start_point: Point,
514    query_ranges: &[Range<usize>],
515    stack: &mut BinaryHeap<ReparseStep>,
516) -> bool {
517    let mut result = false;
518    let mut query_cursor = QueryCursorHandle::new();
519    let mut prev_match = None;
520    for query_range in query_ranges {
521        query_cursor.set_byte_range(query_range.start..query_range.end);
522        for mat in query_cursor.matches(
523            &config.query,
524            tree.root_node(),
525            TextProvider(text.as_rope()),
526        ) {
527            let content_ranges = mat
528                .nodes_for_capture_index(config.content_capture_ix)
529                .map(|node| tree_sitter::Range {
530                    start_byte: start_byte + node.start_byte(),
531                    end_byte: start_byte + node.end_byte(),
532                    start_point: (start_point + Point::from_ts_point(node.start_position()))
533                        .to_ts_point(),
534                    end_point: (start_point + Point::from_ts_point(node.end_position()))
535                        .to_ts_point(),
536                })
537                .collect::<Vec<_>>();
538            if content_ranges.is_empty() {
539                continue;
540            }
541
542            // Avoid duplicate matches if two changed ranges intersect the same injection.
543            let content_range =
544                content_ranges.first().unwrap().start_byte..content_ranges.last().unwrap().end_byte;
545            if let Some((last_pattern_ix, last_range)) = &prev_match {
546                if mat.pattern_index == *last_pattern_ix && content_range == *last_range {
547                    continue;
548                }
549            }
550            prev_match = Some((mat.pattern_index, content_range));
551
552            let language_name = config.languages_by_pattern_ix[mat.pattern_index]
553                .as_ref()
554                .map(|s| Cow::Borrowed(s.as_ref()))
555                .or_else(|| {
556                    let ix = config.language_capture_ix?;
557                    let node = mat.nodes_for_capture_index(ix).next()?;
558                    Some(Cow::Owned(
559                        text.text_for_range(
560                            start_byte + node.start_byte()..start_byte + node.end_byte(),
561                        )
562                        .collect(),
563                    ))
564                });
565
566            if let Some(language_name) = language_name {
567                if let Some(language) = language_registry.get_language(language_name.as_ref()) {
568                    result = true;
569                    stack.push(ReparseStep::CreateLayer {
570                        depth,
571                        language,
572                        ranges: content_ranges,
573                    })
574                }
575            }
576        }
577    }
578    result
579}
580
581fn layer_is_changed(
582    layer: &SyntaxLayer,
583    text: &BufferSnapshot,
584    changed_ranges: &HashMap<usize, Range<Anchor>>,
585) -> bool {
586    changed_ranges.values().any(|range| {
587        let is_before_layer = range.end.cmp(&layer.range.start, text).is_le();
588        let is_after_layer = range.start.cmp(&layer.range.end, text).is_ge();
589        !is_before_layer && !is_after_layer
590    })
591}
592
593impl std::ops::Deref for SyntaxMap {
594    type Target = SyntaxSnapshot;
595
596    fn deref(&self) -> &Self::Target {
597        &self.snapshot
598    }
599}
600
601impl ReparseStep {
602    fn sort_key(&self) -> (usize, Range<usize>) {
603        match self {
604            ReparseStep::CreateLayer { depth, ranges, .. } => (
605                *depth,
606                ranges.first().map_or(0, |r| r.start_byte)
607                    ..ranges.last().map_or(usize::MAX, |r| r.end_byte),
608            ),
609            ReparseStep::EnterChangedRange { depth, range, .. } => {
610                (*depth, range.start..usize::MAX)
611            }
612            ReparseStep::LeaveChangedRange { depth, range, .. } => (*depth, range.end..usize::MAX),
613        }
614    }
615}
616
617impl PartialEq for ReparseStep {
618    fn eq(&self, _: &Self) -> bool {
619        false
620    }
621}
622
623impl Eq for ReparseStep {}
624
625impl PartialOrd for ReparseStep {
626    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
627        Some(self.cmp(&other))
628    }
629}
630
631impl Ord for ReparseStep {
632    fn cmp(&self, other: &Self) -> Ordering {
633        let (depth_a, range_a) = self.sort_key();
634        let (depth_b, range_b) = other.sort_key();
635        Ord::cmp(&depth_b, &depth_a)
636            .then_with(|| Ord::cmp(&range_b.start, &range_a.start))
637            .then_with(|| Ord::cmp(&range_a.end, &range_b.end))
638    }
639}
640
641impl Default for SyntaxLayerSummary {
642    fn default() -> Self {
643        Self {
644            max_depth: 0,
645            range: Anchor::MAX..Anchor::MIN,
646            last_layer_range: Anchor::MIN..Anchor::MAX,
647        }
648    }
649}
650
651impl sum_tree::Summary for SyntaxLayerSummary {
652    type Context = BufferSnapshot;
653
654    fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
655        if other.max_depth > self.max_depth {
656            *self = other.clone();
657        } else {
658            if other.range.start.cmp(&self.range.start, buffer).is_lt() {
659                self.range.start = other.range.start;
660            }
661            if other.range.end.cmp(&self.range.end, buffer).is_gt() {
662                self.range.end = other.range.end;
663            }
664            self.last_layer_range = other.last_layer_range.clone();
665        }
666    }
667}
668
669impl<'a> SeekTarget<'a, SyntaxLayerSummary, SyntaxLayerSummary> for Depth {
670    fn cmp(&self, cursor_location: &SyntaxLayerSummary, _: &BufferSnapshot) -> Ordering {
671        Ord::cmp(&self.0, &cursor_location.max_depth)
672    }
673}
674
675impl<'a> SeekTarget<'a, SyntaxLayerSummary, SyntaxLayerSummary> for (Depth, MaxPosition) {
676    fn cmp(&self, cursor_location: &SyntaxLayerSummary, text: &BufferSnapshot) -> Ordering {
677        self.0
678            .cmp(&cursor_location, text)
679            .then_with(|| (self.1).0.cmp(&cursor_location.range.end, text))
680    }
681}
682
683impl<'a> SeekTarget<'a, SyntaxLayerSummary, SyntaxLayerSummary> for (Depth, Range<Anchor>) {
684    fn cmp(&self, cursor_location: &SyntaxLayerSummary, buffer: &BufferSnapshot) -> Ordering {
685        self.0
686            .cmp(&cursor_location, buffer)
687            .then_with(|| {
688                self.1
689                    .start
690                    .cmp(&cursor_location.last_layer_range.start, buffer)
691            })
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}