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::{Node, Parser, Tree};
11
12thread_local! {
13 static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
14}
15
16#[derive(Default)]
17pub struct SyntaxMap {
18 parsed_version: clock::Global,
19 interpolated_version: clock::Global,
20 snapshot: SyntaxSnapshot,
21 language_registry: Option<Arc<LanguageRegistry>>,
22}
23
24#[derive(Clone, Default)]
25pub struct SyntaxSnapshot {
26 layers: SumTree<SyntaxLayer>,
27}
28
29#[derive(Clone)]
30struct SyntaxLayer {
31 depth: usize,
32 range: Range<Anchor>,
33 tree: tree_sitter::Tree,
34 language: Arc<Language>,
35}
36
37#[derive(Debug, Clone)]
38struct SyntaxLayerSummary {
39 max_depth: usize,
40 range: Range<Anchor>,
41 last_layer_range: Range<Anchor>,
42}
43
44#[derive(Clone, Debug)]
45struct DepthAndRange(usize, Range<Anchor>);
46
47#[derive(Clone, Debug)]
48struct DepthAndMaxPosition(usize, Anchor);
49
50#[derive(Clone, Debug)]
51struct DepthAndRangeOrMaxPosition(DepthAndRange, DepthAndMaxPosition);
52
53struct ReparseStep {
54 depth: usize,
55 language: Arc<Language>,
56 ranges: Vec<tree_sitter::Range>,
57 range: Range<Anchor>,
58}
59
60#[derive(Debug, PartialEq, Eq)]
61struct ChangedRegion {
62 depth: usize,
63 range: Range<Anchor>,
64}
65
66#[derive(Default)]
67struct ChangeRegionSet(Vec<ChangedRegion>);
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.interpolated_version, text);
84 self.interpolated_version = text.version.clone();
85 }
86
87 pub fn reparse(&mut self, language: Arc<Language>, text: &BufferSnapshot) {
88 if !self.interpolated_version.observed_all(&text.version) {
89 self.interpolate(text);
90 }
91
92 self.snapshot.reparse(
93 &self.parsed_version,
94 text,
95 self.language_registry.clone(),
96 language,
97 );
98 self.parsed_version = text.version.clone();
99 }
100}
101
102impl SyntaxSnapshot {
103 pub fn interpolate(&mut self, from_version: &clock::Global, text: &BufferSnapshot) {
104 let edits = text
105 .edits_since::<(usize, Point)>(&from_version)
106 .collect::<Vec<_>>();
107 if edits.is_empty() {
108 return;
109 }
110
111 let mut layers = SumTree::new();
112 let mut edits_for_depth = &edits[..];
113 let mut cursor = self.layers.cursor::<SyntaxLayerSummary>();
114 cursor.next(text);
115
116 'outer: loop {
117 let depth = cursor.end(text).max_depth;
118
119 // Preserve any layers at this depth that precede the first edit.
120 if let Some(first_edit) = edits_for_depth.first() {
121 let target = DepthAndMaxPosition(depth, text.anchor_before(first_edit.new.start.0));
122 if target.cmp(&cursor.start(), text).is_gt() {
123 let slice = cursor.slice(&target, Bias::Left, text);
124 layers.push_tree(slice, text);
125 }
126 }
127 // If this layer follows all of the edits, then preserve it and any
128 // subsequent layers at this same depth.
129 else {
130 let slice = cursor.slice(
131 &DepthAndRange(depth + 1, Anchor::MIN..Anchor::MAX),
132 Bias::Left,
133 text,
134 );
135 layers.push_tree(slice, text);
136 edits_for_depth = &edits[..];
137 continue;
138 };
139
140 let layer = if let Some(layer) = cursor.item() {
141 layer
142 } else {
143 break;
144 };
145
146 let mut endpoints = text
147 .summaries_for_anchors::<(usize, Point), _>([&layer.range.start, &layer.range.end]);
148 let layer_range = endpoints.next().unwrap()..endpoints.next().unwrap();
149 let start_byte = layer_range.start.0;
150 let start_point = layer_range.start.1;
151 let end_byte = layer_range.end.0;
152
153 // Ignore edits that end before the start of this layer, and don't consider them
154 // for any subsequent layers at this same depth.
155 loop {
156 if let Some(edit) = edits_for_depth.first() {
157 if edit.new.end.0 < start_byte {
158 edits_for_depth = &edits_for_depth[1..];
159 } else {
160 break;
161 }
162 } else {
163 continue 'outer;
164 }
165 }
166
167 let mut layer = layer.clone();
168 for edit in edits_for_depth {
169 // Ignore any edits that follow this layer.
170 if edit.new.start.0 > end_byte {
171 break;
172 }
173
174 // Apply any edits that intersect this layer to the layer's syntax tree.
175 let tree_edit = if edit.new.start.0 >= start_byte {
176 tree_sitter::InputEdit {
177 start_byte: edit.new.start.0 - start_byte,
178 old_end_byte: edit.new.start.0 - start_byte
179 + (edit.old.end.0 - edit.old.start.0),
180 new_end_byte: edit.new.end.0 - start_byte,
181 start_position: (edit.new.start.1 - start_point).to_ts_point(),
182 old_end_position: (edit.new.start.1 - start_point
183 + (edit.old.end.1 - edit.old.start.1))
184 .to_ts_point(),
185 new_end_position: (edit.new.end.1 - start_point).to_ts_point(),
186 }
187 } else {
188 tree_sitter::InputEdit {
189 start_byte: 0,
190 old_end_byte: edit.new.end.0 - start_byte,
191 new_end_byte: 0,
192 start_position: Default::default(),
193 old_end_position: (edit.new.end.1 - start_point).to_ts_point(),
194 new_end_position: Default::default(),
195 }
196 };
197
198 layer.tree.edit(&tree_edit);
199 if edit.new.start.0 < start_byte {
200 break;
201 }
202 }
203
204 layers.push(layer, text);
205 cursor.next(text);
206 }
207
208 layers.push_tree(cursor.suffix(&text), &text);
209 drop(cursor);
210 self.layers = layers;
211 }
212
213 pub fn reparse(
214 &mut self,
215 from_version: &clock::Global,
216 text: &BufferSnapshot,
217 registry: Option<Arc<LanguageRegistry>>,
218 language: Arc<Language>,
219 ) {
220 let edits = text.edits_since::<usize>(from_version).collect::<Vec<_>>();
221 if edits.is_empty() {
222 return;
223 }
224
225 let max_depth = self.layers.summary().max_depth;
226 let mut cursor = self.layers.cursor::<SyntaxLayerSummary>();
227 cursor.next(&text);
228 let mut layers = SumTree::new();
229
230 let mut changed_regions = ChangeRegionSet::default();
231 let mut queue = BinaryHeap::new();
232 queue.push(ReparseStep {
233 depth: 0,
234 language: language.clone(),
235 ranges: Vec::new(),
236 range: Anchor::MIN..Anchor::MAX,
237 });
238
239 loop {
240 let step = queue.pop();
241 let (depth, range) = if let Some(step) = &step {
242 (step.depth, step.range.clone())
243 } else {
244 (max_depth + 1, Anchor::MAX..Anchor::MAX)
245 };
246
247 let target = DepthAndRange(depth, range.clone());
248 let mut done = cursor.item().is_none();
249 while !done && target.cmp(&cursor.end(text), &text).is_gt() {
250 done = true;
251
252 let bounded_target =
253 DepthAndRangeOrMaxPosition(target.clone(), changed_regions.start_position());
254 if bounded_target.cmp(&cursor.start(), &text).is_gt() {
255 let slice = cursor.slice(&bounded_target, Bias::Left, text);
256 if !slice.is_empty() {
257 layers.push_tree(slice, &text);
258 if changed_regions.prune(cursor.end(text), text) {
259 done = false;
260 }
261 }
262 }
263
264 while target.cmp(&cursor.end(text), text).is_gt() {
265 let layer = if let Some(layer) = cursor.item() {
266 layer
267 } else {
268 break;
269 };
270
271 if changed_regions.intersects(&layer, text) {
272 changed_regions.insert(
273 ChangedRegion {
274 depth: depth + 1,
275 range: layer.range.clone(),
276 },
277 text,
278 );
279 } else {
280 layers.push(layer.clone(), text);
281 }
282
283 cursor.next(text);
284 if changed_regions.prune(cursor.end(text), text) {
285 done = false;
286 }
287 }
288 }
289
290 let (ranges, language) = if let Some(step) = step {
291 (step.ranges, step.language)
292 } else {
293 break;
294 };
295
296 let start_point;
297 let start_byte;
298 let end_byte;
299 if let Some((first, last)) = ranges.first().zip(ranges.last()) {
300 start_point = first.start_point;
301 start_byte = first.start_byte;
302 end_byte = last.end_byte;
303 } else {
304 start_point = Point::zero().to_ts_point();
305 start_byte = 0;
306 end_byte = text.len();
307 };
308
309 let mut old_layer = cursor.item();
310 if let Some(layer) = old_layer {
311 if layer.range.to_offset(text) == (start_byte..end_byte) {
312 cursor.next(&text);
313 } else {
314 old_layer = None;
315 }
316 }
317
318 let grammar = if let Some(grammar) = language.grammar.as_deref() {
319 grammar
320 } else {
321 continue;
322 };
323
324 let tree;
325 let changed_ranges;
326 if let Some(old_layer) = old_layer {
327 tree = parse_text(
328 grammar,
329 text.as_rope(),
330 Some(old_layer.tree.clone()),
331 ranges,
332 );
333 changed_ranges = join_ranges(
334 edits
335 .iter()
336 .map(|e| e.new.clone())
337 .filter(|range| range.start < end_byte && range.end > start_byte),
338 old_layer
339 .tree
340 .changed_ranges(&tree)
341 .map(|r| start_byte + r.start_byte..start_byte + r.end_byte),
342 );
343 } else {
344 tree = parse_text(grammar, text.as_rope(), None, ranges);
345 changed_ranges = vec![start_byte..end_byte];
346 }
347
348 layers.push(
349 SyntaxLayer {
350 depth,
351 range,
352 tree: tree.clone(),
353 language: language.clone(),
354 },
355 &text,
356 );
357
358 if let (Some((config, registry)), false) = (
359 grammar.injection_config.as_ref().zip(registry.as_ref()),
360 changed_ranges.is_empty(),
361 ) {
362 let depth = depth + 1;
363 for range in &changed_ranges {
364 changed_regions.insert(
365 ChangedRegion {
366 depth,
367 range: text.anchor_before(range.start)..text.anchor_after(range.end),
368 },
369 text,
370 );
371 }
372 get_injections(
373 config,
374 text,
375 tree.root_node_with_offset(start_byte, start_point),
376 registry,
377 depth,
378 &changed_ranges,
379 &mut queue,
380 );
381 }
382 }
383
384 drop(cursor);
385 self.layers = layers;
386 }
387
388 pub fn layers(&self, buffer: &BufferSnapshot) -> Vec<(&Grammar, Node)> {
389 self.layers
390 .iter()
391 .filter_map(|layer| {
392 if let Some(grammar) = &layer.language.grammar {
393 Some((
394 grammar.as_ref(),
395 layer.tree.root_node_with_offset(
396 layer.range.start.to_offset(buffer),
397 layer.range.start.to_point(buffer).to_ts_point(),
398 ),
399 ))
400 } else {
401 None
402 }
403 })
404 .collect()
405 }
406
407 pub fn layers_for_range<'a, T: ToOffset>(
408 &self,
409 range: Range<T>,
410 buffer: &BufferSnapshot,
411 ) -> Vec<(&Grammar, Node)> {
412 let start = buffer.anchor_before(range.start.to_offset(buffer));
413 let end = buffer.anchor_after(range.end.to_offset(buffer));
414
415 let mut cursor = self.layers.filter::<_, ()>(|summary| {
416 let is_before_start = summary.range.end.cmp(&start, buffer).is_lt();
417 let is_after_end = summary.range.start.cmp(&end, buffer).is_gt();
418 !is_before_start && !is_after_end
419 });
420
421 let mut result = Vec::new();
422 cursor.next(buffer);
423 while let Some(layer) = cursor.item() {
424 if let Some(grammar) = &layer.language.grammar {
425 result.push((
426 grammar.as_ref(),
427 layer.tree.root_node_with_offset(
428 layer.range.start.to_offset(buffer),
429 layer.range.start.to_point(buffer).to_ts_point(),
430 ),
431 ));
432 }
433 cursor.next(buffer)
434 }
435
436 result
437 }
438}
439
440fn join_ranges(
441 a: impl Iterator<Item = Range<usize>>,
442 b: impl Iterator<Item = Range<usize>>,
443) -> Vec<Range<usize>> {
444 let mut result = Vec::<Range<usize>>::new();
445 let mut a = a.peekable();
446 let mut b = b.peekable();
447 loop {
448 let range = match (a.peek(), b.peek()) {
449 (Some(range_a), Some(range_b)) => {
450 if range_a.start < range_b.start {
451 a.next().unwrap()
452 } else {
453 b.next().unwrap()
454 }
455 }
456 (None, Some(_)) => b.next().unwrap(),
457 (Some(_), None) => a.next().unwrap(),
458 (None, None) => break,
459 };
460
461 if let Some(last) = result.last_mut() {
462 if range.start <= last.end {
463 last.end = last.end.max(range.end);
464 continue;
465 }
466 }
467 result.push(range);
468 }
469 result
470}
471
472fn parse_text(
473 grammar: &Grammar,
474 text: &Rope,
475 old_tree: Option<Tree>,
476 mut ranges: Vec<tree_sitter::Range>,
477) -> Tree {
478 let (start_byte, start_point) = ranges
479 .first()
480 .map(|range| (range.start_byte, Point::from_ts_point(range.start_point)))
481 .unwrap_or_default();
482
483 for range in &mut ranges {
484 range.start_byte -= start_byte;
485 range.end_byte -= start_byte;
486 range.start_point = (Point::from_ts_point(range.start_point) - start_point).to_ts_point();
487 range.end_point = (Point::from_ts_point(range.end_point) - start_point).to_ts_point();
488 }
489
490 PARSER.with(|parser| {
491 let mut parser = parser.borrow_mut();
492 let mut chunks = text.chunks_in_range(start_byte..text.len());
493 parser
494 .set_included_ranges(&ranges)
495 .expect("overlapping ranges");
496 parser
497 .set_language(grammar.ts_language)
498 .expect("incompatible grammar");
499 parser
500 .parse_with(
501 &mut move |offset, _| {
502 chunks.seek(start_byte + offset);
503 chunks.next().unwrap_or("").as_bytes()
504 },
505 old_tree.as_ref(),
506 )
507 .expect("invalid language")
508 })
509}
510
511fn get_injections(
512 config: &InjectionConfig,
513 text: &BufferSnapshot,
514 node: Node,
515 language_registry: &LanguageRegistry,
516 depth: usize,
517 query_ranges: &[Range<usize>],
518 queue: &mut BinaryHeap<ReparseStep>,
519) -> bool {
520 let mut result = false;
521 let mut query_cursor = QueryCursorHandle::new();
522 let mut prev_match = None;
523 for query_range in query_ranges {
524 query_cursor.set_byte_range(query_range.start..query_range.end);
525 for mat in query_cursor.matches(&config.query, node, TextProvider(text.as_rope())) {
526 let content_ranges = mat
527 .nodes_for_capture_index(config.content_capture_ix)
528 .map(|node| node.range())
529 .collect::<Vec<_>>();
530 if content_ranges.is_empty() {
531 continue;
532 }
533
534 // Avoid duplicate matches if two changed ranges intersect the same injection.
535 let content_range =
536 content_ranges.first().unwrap().start_byte..content_ranges.last().unwrap().end_byte;
537 if let Some((last_pattern_ix, last_range)) = &prev_match {
538 if mat.pattern_index == *last_pattern_ix && content_range == *last_range {
539 continue;
540 }
541 }
542 prev_match = Some((mat.pattern_index, content_range.clone()));
543
544 let language_name = config.languages_by_pattern_ix[mat.pattern_index]
545 .as_ref()
546 .map(|s| Cow::Borrowed(s.as_ref()))
547 .or_else(|| {
548 let ix = config.language_capture_ix?;
549 let node = mat.nodes_for_capture_index(ix).next()?;
550 Some(Cow::Owned(text.text_for_range(node.byte_range()).collect()))
551 });
552
553 if let Some(language_name) = language_name {
554 if let Some(language) = language_registry.get_language(language_name.as_ref()) {
555 result = true;
556 let range = text.anchor_before(content_range.start)
557 ..text.anchor_after(content_range.end);
558 queue.push(ReparseStep {
559 depth,
560 language,
561 ranges: content_ranges,
562 range,
563 })
564 }
565 }
566 }
567 }
568 result
569}
570
571impl std::ops::Deref for SyntaxMap {
572 type Target = SyntaxSnapshot;
573
574 fn deref(&self) -> &Self::Target {
575 &self.snapshot
576 }
577}
578
579impl PartialEq for ReparseStep {
580 fn eq(&self, _: &Self) -> bool {
581 false
582 }
583}
584
585impl Eq for ReparseStep {}
586
587impl PartialOrd for ReparseStep {
588 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
589 Some(self.cmp(&other))
590 }
591}
592
593impl Ord for ReparseStep {
594 fn cmp(&self, other: &Self) -> Ordering {
595 let range_a = self.range();
596 let range_b = other.range();
597 Ord::cmp(&other.depth, &self.depth)
598 .then_with(|| Ord::cmp(&range_b.start, &range_a.start))
599 .then_with(|| Ord::cmp(&range_a.end, &range_b.end))
600 }
601}
602
603impl ReparseStep {
604 fn range(&self) -> Range<usize> {
605 let start = self.ranges.first().map_or(0, |r| r.start_byte);
606 let end = self.ranges.last().map_or(0, |r| r.end_byte);
607 start..end
608 }
609}
610
611impl ChangedRegion {
612 fn cmp(&self, other: &Self, buffer: &BufferSnapshot) -> Ordering {
613 let range_a = &self.range;
614 let range_b = &other.range;
615 Ord::cmp(&self.depth, &other.depth)
616 .then_with(|| range_a.start.cmp(&range_b.start, buffer))
617 .then_with(|| range_b.end.cmp(&range_a.end, buffer))
618 }
619}
620
621impl ChangeRegionSet {
622 fn start_position(&self) -> DepthAndMaxPosition {
623 self.0
624 .first()
625 .map_or(DepthAndMaxPosition(usize::MAX, Anchor::MAX), |region| {
626 DepthAndMaxPosition(region.depth, region.range.start)
627 })
628 }
629
630 fn intersects(&self, layer: &SyntaxLayer, text: &BufferSnapshot) -> bool {
631 for region in &self.0 {
632 if region.depth < layer.depth {
633 continue;
634 }
635 if region.depth > layer.depth {
636 break;
637 }
638 if region.range.end.cmp(&layer.range.start, text).is_le() {
639 continue;
640 }
641 if region.range.start.cmp(&layer.range.end, text).is_ge() {
642 break;
643 }
644 return true;
645 }
646 false
647 }
648
649 fn insert(&mut self, region: ChangedRegion, text: &BufferSnapshot) {
650 if let Err(ix) = self.0.binary_search_by(|probe| probe.cmp(®ion, text)) {
651 self.0.insert(ix, region);
652 }
653 }
654
655 fn prune(&mut self, summary: SyntaxLayerSummary, text: &BufferSnapshot) -> bool {
656 let prev_len = self.0.len();
657 self.0.retain(|region| {
658 region.depth > summary.max_depth
659 || (region.depth == summary.max_depth
660 && region
661 .range
662 .end
663 .cmp(&summary.last_layer_range.start, text)
664 .is_gt())
665 });
666 self.0.len() < prev_len
667 }
668}
669
670impl Default for SyntaxLayerSummary {
671 fn default() -> Self {
672 Self {
673 max_depth: 0,
674 range: Anchor::MAX..Anchor::MIN,
675 last_layer_range: Anchor::MIN..Anchor::MAX,
676 }
677 }
678}
679
680impl sum_tree::Summary for SyntaxLayerSummary {
681 type Context = BufferSnapshot;
682
683 fn add_summary(&mut self, other: &Self, buffer: &Self::Context) {
684 if other.max_depth > self.max_depth {
685 *self = other.clone();
686 } else {
687 if other.range.start.cmp(&self.range.start, buffer).is_lt() {
688 self.range.start = other.range.start;
689 }
690 if other.range.end.cmp(&self.range.end, buffer).is_gt() {
691 self.range.end = other.range.end;
692 }
693 self.last_layer_range = other.last_layer_range.clone();
694 }
695 }
696}
697
698impl<'a> SeekTarget<'a, SyntaxLayerSummary, SyntaxLayerSummary> for DepthAndRange {
699 fn cmp(&self, cursor_location: &SyntaxLayerSummary, buffer: &BufferSnapshot) -> Ordering {
700 Ord::cmp(&self.0, &cursor_location.max_depth)
701 .then_with(|| {
702 self.1
703 .start
704 .cmp(&cursor_location.last_layer_range.start, buffer)
705 })
706 .then_with(|| {
707 cursor_location
708 .last_layer_range
709 .end
710 .cmp(&self.1.end, buffer)
711 })
712 }
713}
714
715impl<'a> SeekTarget<'a, SyntaxLayerSummary, SyntaxLayerSummary> for DepthAndMaxPosition {
716 fn cmp(&self, cursor_location: &SyntaxLayerSummary, text: &BufferSnapshot) -> Ordering {
717 Ord::cmp(&self.0, &cursor_location.max_depth)
718 .then_with(|| self.1.cmp(&cursor_location.range.end, text))
719 }
720}
721
722impl<'a> SeekTarget<'a, SyntaxLayerSummary, SyntaxLayerSummary> for DepthAndRangeOrMaxPosition {
723 fn cmp(&self, cursor_location: &SyntaxLayerSummary, buffer: &BufferSnapshot) -> Ordering {
724 if self.1.cmp(cursor_location, buffer).is_le() {
725 return Ordering::Less;
726 } else {
727 self.0.cmp(cursor_location, buffer)
728 }
729 }
730}
731
732impl sum_tree::Item for SyntaxLayer {
733 type Summary = SyntaxLayerSummary;
734
735 fn summary(&self) -> Self::Summary {
736 SyntaxLayerSummary {
737 max_depth: self.depth,
738 range: self.range.clone(),
739 last_layer_range: self.range.clone(),
740 }
741 }
742}
743
744impl std::fmt::Debug for SyntaxLayer {
745 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
746 f.debug_struct("SyntaxLayer")
747 .field("depth", &self.depth)
748 .field("range", &self.range)
749 .field("tree", &self.tree)
750 .finish()
751 }
752}
753
754#[cfg(test)]
755mod tests {
756 use super::*;
757 use crate::LanguageConfig;
758 use text::{Buffer, Point};
759 use tree_sitter::Query;
760 use unindent::Unindent as _;
761 use util::test::marked_text_ranges;
762
763 #[gpui::test]
764 fn test_syntax_map_layers_for_range() {
765 let registry = Arc::new(LanguageRegistry::test());
766 let language = Arc::new(rust_lang());
767 registry.add(language.clone());
768
769 let mut buffer = Buffer::new(
770 0,
771 0,
772 r#"
773 fn a() {
774 assert_eq!(
775 b(vec![C {}]),
776 vec![d.e],
777 );
778 println!("{}", f(|_| true));
779 }
780 "#
781 .unindent(),
782 );
783
784 let mut syntax_map = SyntaxMap::new();
785 syntax_map.set_language_registry(registry.clone());
786 syntax_map.reparse(language.clone(), &buffer);
787
788 assert_layers_for_range(
789 &syntax_map,
790 &buffer,
791 Point::new(2, 0)..Point::new(2, 0),
792 &[
793 "...(function_item ... (block (expression_statement (macro_invocation...",
794 "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
795 ],
796 );
797 assert_layers_for_range(
798 &syntax_map,
799 &buffer,
800 Point::new(2, 14)..Point::new(2, 16),
801 &[
802 "...(function_item ...",
803 "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
804 "...(array_expression (struct_expression ...",
805 ],
806 );
807 assert_layers_for_range(
808 &syntax_map,
809 &buffer,
810 Point::new(3, 14)..Point::new(3, 16),
811 &[
812 "...(function_item ...",
813 "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
814 "...(array_expression (field_expression ...",
815 ],
816 );
817 assert_layers_for_range(
818 &syntax_map,
819 &buffer,
820 Point::new(5, 12)..Point::new(5, 16),
821 &[
822 "...(function_item ...",
823 "...(call_expression ... (arguments (closure_expression ...",
824 ],
825 );
826
827 // Replace a vec! macro invocation with a plain slice, removing a syntactic layer.
828 let macro_name_range = range_for_text(&buffer, "vec!");
829 buffer.edit([(macro_name_range, "&")]);
830 syntax_map.interpolate(&buffer);
831 syntax_map.reparse(language.clone(), &buffer);
832
833 assert_layers_for_range(
834 &syntax_map,
835 &buffer,
836 Point::new(2, 14)..Point::new(2, 16),
837 &[
838 "...(function_item ...",
839 "...(tuple_expression (call_expression ... arguments: (arguments (reference_expression value: (array_expression...",
840 ],
841 );
842
843 // Put the vec! macro back, adding back the syntactic layer.
844 buffer.undo();
845 syntax_map.interpolate(&buffer);
846 syntax_map.reparse(language.clone(), &buffer);
847
848 assert_layers_for_range(
849 &syntax_map,
850 &buffer,
851 Point::new(2, 14)..Point::new(2, 16),
852 &[
853 "...(function_item ...",
854 "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
855 "...(array_expression (struct_expression ...",
856 ],
857 );
858 }
859
860 #[gpui::test]
861 fn test_typing_multiple_new_injections() {
862 let (buffer, syntax_map) = test_edit_sequence(&[
863 "fn a() { dbg }",
864 "fn a() { dbg«!» }",
865 "fn a() { dbg!«()» }",
866 "fn a() { dbg!(«b») }",
867 "fn a() { dbg!(b«.») }",
868 "fn a() { dbg!(b.«c») }",
869 "fn a() { dbg!(b.c«()») }",
870 "fn a() { dbg!(b.c(«vec»)) }",
871 "fn a() { dbg!(b.c(vec«!»)) }",
872 "fn a() { dbg!(b.c(vec!«[]»)) }",
873 "fn a() { dbg!(b.c(vec![«d»])) }",
874 "fn a() { dbg!(b.c(vec![d«.»])) }",
875 "fn a() { dbg!(b.c(vec![d.«e»])) }",
876 ]);
877
878 assert_node_ranges(
879 &syntax_map,
880 &buffer,
881 "(field_identifier) @_",
882 "fn a() { dbg!(b.«c»(vec![d.«e»])) }",
883 );
884 }
885
886 #[gpui::test]
887 fn test_pasting_new_injection_line_between_others() {
888 let (buffer, syntax_map) = test_edit_sequence(&[
889 "
890 fn a() {
891 b!(B {});
892 c!(C {});
893 d!(D {});
894 e!(E {});
895 f!(F {});
896 g!(G {});
897 }
898 ",
899 "
900 fn a() {
901 b!(B {});
902 c!(C {});
903 d!(D {});
904 « h!(H {});
905 » e!(E {});
906 f!(F {});
907 g!(G {});
908 }
909 ",
910 ]);
911
912 assert_node_ranges(
913 &syntax_map,
914 &buffer,
915 "(struct_expression) @_",
916 "
917 fn a() {
918 b!(«B {}»);
919 c!(«C {}»);
920 d!(«D {}»);
921 h!(«H {}»);
922 e!(«E {}»);
923 f!(«F {}»);
924 g!(«G {}»);
925 }
926 ",
927 );
928 }
929
930 #[gpui::test]
931 fn test_joining_injections_with_child_injections() {
932 let (buffer, syntax_map) = test_edit_sequence(&[
933 "
934 fn a() {
935 b!(
936 c![one.two.three],
937 d![four.five.six],
938 );
939 e!(
940 f![seven.eight],
941 );
942 }
943 ",
944 "
945 fn a() {
946 b!(
947 c![one.two.three],
948 d![four.five.six],
949 ˇ f![seven.eight],
950 );
951 }
952 ",
953 ]);
954
955 assert_node_ranges(
956 &syntax_map,
957 &buffer,
958 "(field_identifier) @_",
959 "
960 fn a() {
961 b!(
962 c![one.«two».«three»],
963 d![four.«five».«six»],
964 f![seven.«eight»],
965 );
966 }
967 ",
968 );
969 }
970
971 #[gpui::test]
972 fn test_editing_edges_of_injection() {
973 test_edit_sequence(&[
974 "
975 fn a() {
976 b!(c!())
977 }
978 ",
979 "
980 fn a() {
981 «d»!(c!())
982 }
983 ",
984 "
985 fn a() {
986 «e»d!(c!())
987 }
988 ",
989 "
990 fn a() {
991 ed!«[»c!()«]»
992 }
993 ",
994 ]);
995 }
996
997 #[gpui::test]
998 fn test_edits_preceding_and_intersecting_injection() {
999 test_edit_sequence(&[
1000 //
1001 "const aaaaaaaaaaaa: B = c!(d(e.f));",
1002 "const aˇa: B = c!(d(eˇ));",
1003 ]);
1004 }
1005
1006 #[gpui::test]
1007 fn test_non_local_changes_create_injections() {
1008 test_edit_sequence(&[
1009 "
1010 // a! {
1011 static B: C = d;
1012 // }
1013 ",
1014 "
1015 ˇa! {
1016 static B: C = d;
1017 ˇ}
1018 ",
1019 ]);
1020 }
1021
1022 #[gpui::test]
1023 fn test_creating_many_injections_in_one_edit() {
1024 test_edit_sequence(&[
1025 "
1026 fn a() {
1027 one(Two::three(3));
1028 four(Five::six(6));
1029 seven(Eight::nine(9));
1030 }
1031 ",
1032 "
1033 fn a() {
1034 one«!»(Two::three(3));
1035 four«!»(Five::six(6));
1036 seven«!»(Eight::nine(9));
1037 }
1038 ",
1039 "
1040 fn a() {
1041 one!(Two::three«!»(3));
1042 four!(Five::six«!»(6));
1043 seven!(Eight::nine«!»(9));
1044 }
1045 ",
1046 ]);
1047 }
1048
1049 #[gpui::test]
1050 fn test_editing_across_injection_boundary() {
1051 test_edit_sequence(&[
1052 "
1053 fn one() {
1054 two();
1055 three!(
1056 three.four,
1057 five.six,
1058 );
1059 }
1060 ",
1061 "
1062 fn one() {
1063 two();
1064 th«irty_five![»
1065 three.four,
1066 five.six,
1067 « seven.eight,
1068 ];»
1069 }
1070 ",
1071 ]);
1072 }
1073
1074 fn test_edit_sequence(steps: &[&str]) -> (Buffer, SyntaxMap) {
1075 let registry = Arc::new(LanguageRegistry::test());
1076 let language = Arc::new(rust_lang());
1077 registry.add(language.clone());
1078 let mut buffer = Buffer::new(0, 0, Default::default());
1079
1080 let mut mutated_syntax_map = SyntaxMap::new();
1081 mutated_syntax_map.set_language_registry(registry.clone());
1082 mutated_syntax_map.reparse(language.clone(), &buffer);
1083
1084 for (i, marked_string) in steps.into_iter().enumerate() {
1085 edit_buffer(&mut buffer, &marked_string.unindent());
1086
1087 // Reparse the syntax map
1088 mutated_syntax_map.interpolate(&buffer);
1089 mutated_syntax_map.reparse(language.clone(), &buffer);
1090
1091 // Create a second syntax map from scratch
1092 let mut reference_syntax_map = SyntaxMap::new();
1093 reference_syntax_map.set_language_registry(registry.clone());
1094 reference_syntax_map.reparse(language.clone(), &buffer);
1095
1096 // Compare the mutated syntax map to the new syntax map
1097 let mutated_layers = mutated_syntax_map.layers(&buffer);
1098 let reference_layers = reference_syntax_map.layers(&buffer);
1099 assert_eq!(
1100 mutated_layers.len(),
1101 reference_layers.len(),
1102 "wrong number of layers at step {i}"
1103 );
1104 for (edited_layer, reference_layer) in
1105 mutated_layers.into_iter().zip(reference_layers.into_iter())
1106 {
1107 assert_eq!(
1108 edited_layer.1.to_sexp(),
1109 reference_layer.1.to_sexp(),
1110 "different layer at step {i}"
1111 );
1112 assert_eq!(
1113 edited_layer.1.range(),
1114 reference_layer.1.range(),
1115 "different layer at step {i}"
1116 );
1117 }
1118 }
1119
1120 (buffer, mutated_syntax_map)
1121 }
1122
1123 fn rust_lang() -> Language {
1124 Language::new(
1125 LanguageConfig {
1126 name: "Rust".into(),
1127 path_suffixes: vec!["rs".to_string()],
1128 ..Default::default()
1129 },
1130 Some(tree_sitter_rust::language()),
1131 )
1132 .with_injection_query(
1133 r#"
1134 (macro_invocation
1135 (token_tree) @content
1136 (#set! "language" "rust"))
1137 "#,
1138 )
1139 .unwrap()
1140 }
1141
1142 fn range_for_text(buffer: &Buffer, text: &str) -> Range<usize> {
1143 let start = buffer.as_rope().to_string().find(text).unwrap();
1144 start..start + text.len()
1145 }
1146
1147 fn assert_layers_for_range(
1148 syntax_map: &SyntaxMap,
1149 buffer: &BufferSnapshot,
1150 range: Range<Point>,
1151 expected_layers: &[&str],
1152 ) {
1153 let layers = syntax_map.layers_for_range(range, &buffer);
1154 assert_eq!(
1155 layers.len(),
1156 expected_layers.len(),
1157 "wrong number of layers"
1158 );
1159 for (i, ((_, node), expected_s_exp)) in
1160 layers.iter().zip(expected_layers.iter()).enumerate()
1161 {
1162 let actual_s_exp = node.to_sexp();
1163 assert!(
1164 string_contains_sequence(
1165 &actual_s_exp,
1166 &expected_s_exp.split("...").collect::<Vec<_>>()
1167 ),
1168 "layer {i}:\n\nexpected: {expected_s_exp}\nactual: {actual_s_exp}",
1169 );
1170 }
1171 }
1172
1173 fn assert_node_ranges(
1174 syntax_map: &SyntaxMap,
1175 buffer: &BufferSnapshot,
1176 query: &str,
1177 marked_string: &str,
1178 ) {
1179 let mut cursor = QueryCursorHandle::new();
1180 let mut actual_ranges = Vec::<Range<usize>>::new();
1181 for (grammar, node) in syntax_map.layers(buffer) {
1182 let query = Query::new(grammar.ts_language, query).unwrap();
1183 for (mat, ix) in cursor.captures(&query, node, TextProvider(buffer.as_rope())) {
1184 actual_ranges.push(mat.captures[ix].node.byte_range());
1185 }
1186 }
1187
1188 let (text, expected_ranges) = marked_text_ranges(&marked_string.unindent(), false);
1189 assert_eq!(text, buffer.text());
1190 assert_eq!(actual_ranges, expected_ranges);
1191 }
1192
1193 fn edit_buffer(buffer: &mut Buffer, marked_string: &str) {
1194 let old_text = buffer.text();
1195 let (new_text, mut ranges) = marked_text_ranges(marked_string, false);
1196 if ranges.is_empty() {
1197 ranges.push(0..new_text.len());
1198 }
1199
1200 assert_eq!(
1201 old_text[..ranges[0].start],
1202 new_text[..ranges[0].start],
1203 "invalid edit"
1204 );
1205
1206 let mut delta = 0;
1207 let mut edits = Vec::new();
1208 let mut ranges = ranges.into_iter().peekable();
1209
1210 while let Some(inserted_range) = ranges.next() {
1211 let new_start = inserted_range.start;
1212 let old_start = (new_start as isize - delta) as usize;
1213
1214 let following_text = if let Some(next_range) = ranges.peek() {
1215 &new_text[inserted_range.end..next_range.start]
1216 } else {
1217 &new_text[inserted_range.end..]
1218 };
1219
1220 let inserted_len = inserted_range.len();
1221 let deleted_len = old_text[old_start..]
1222 .find(following_text)
1223 .expect("invalid edit");
1224
1225 let old_range = old_start..old_start + deleted_len;
1226 edits.push((old_range, new_text[inserted_range].to_string()));
1227 delta += inserted_len as isize - deleted_len as isize;
1228 }
1229
1230 assert_eq!(
1231 old_text.len() as isize + delta,
1232 new_text.len() as isize,
1233 "invalid edit"
1234 );
1235
1236 buffer.edit(edits);
1237 }
1238
1239 pub fn string_contains_sequence(text: &str, parts: &[&str]) -> bool {
1240 let mut last_part_end = 0;
1241 for part in parts {
1242 if let Some(start_ix) = text[last_part_end..].find(part) {
1243 last_part_end = start_ix + part.len();
1244 } else {
1245 return false;
1246 }
1247 }
1248 true
1249 }
1250}