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)>(¤t_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(®ion, 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(®ion, 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}