1use super::*;
2use crate::LanguageConfig;
3use rand::rngs::StdRng;
4use std::{env, ops::Range, sync::Arc};
5use text::Buffer;
6use tree_sitter::Node;
7use unindent::Unindent as _;
8use util::test::marked_text_ranges;
9
10#[test]
11fn test_splice_included_ranges() {
12 let ranges = vec![ts_range(20..30), ts_range(50..60), ts_range(80..90)];
13
14 let new_ranges = splice_included_ranges(
15 ranges.clone(),
16 &[54..56, 58..68],
17 &[ts_range(50..54), ts_range(59..67)],
18 );
19 assert_eq!(
20 new_ranges,
21 &[
22 ts_range(20..30),
23 ts_range(50..54),
24 ts_range(59..67),
25 ts_range(80..90),
26 ]
27 );
28
29 let new_ranges = splice_included_ranges(ranges.clone(), &[70..71, 91..100], &[]);
30 assert_eq!(
31 new_ranges,
32 &[ts_range(20..30), ts_range(50..60), ts_range(80..90)]
33 );
34
35 let new_ranges =
36 splice_included_ranges(ranges.clone(), &[], &[ts_range(0..2), ts_range(70..75)]);
37 assert_eq!(
38 new_ranges,
39 &[
40 ts_range(0..2),
41 ts_range(20..30),
42 ts_range(50..60),
43 ts_range(70..75),
44 ts_range(80..90)
45 ]
46 );
47
48 let new_ranges = splice_included_ranges(ranges.clone(), &[30..50], &[ts_range(25..55)]);
49 assert_eq!(new_ranges, &[ts_range(25..55), ts_range(80..90)]);
50
51 // does not create overlapping ranges
52 let new_ranges = splice_included_ranges(ranges.clone(), &[0..18], &[ts_range(20..32)]);
53 assert_eq!(
54 new_ranges,
55 &[ts_range(20..32), ts_range(50..60), ts_range(80..90)]
56 );
57
58 fn ts_range(range: Range<usize>) -> tree_sitter::Range {
59 tree_sitter::Range {
60 start_byte: range.start,
61 start_point: tree_sitter::Point {
62 row: 0,
63 column: range.start,
64 },
65 end_byte: range.end,
66 end_point: tree_sitter::Point {
67 row: 0,
68 column: range.end,
69 },
70 }
71 }
72}
73
74#[gpui::test]
75fn test_syntax_map_layers_for_range() {
76 let registry = Arc::new(LanguageRegistry::test());
77 let language = Arc::new(rust_lang());
78 registry.add(language.clone());
79
80 let mut buffer = Buffer::new(
81 0,
82 0,
83 r#"
84 fn a() {
85 assert_eq!(
86 b(vec![C {}]),
87 vec![d.e],
88 );
89 println!("{}", f(|_| true));
90 }
91 "#
92 .unindent(),
93 );
94
95 let mut syntax_map = SyntaxMap::new();
96 syntax_map.set_language_registry(registry.clone());
97 syntax_map.reparse(language.clone(), &buffer);
98
99 assert_layers_for_range(
100 &syntax_map,
101 &buffer,
102 Point::new(2, 0)..Point::new(2, 0),
103 &[
104 "...(function_item ... (block (expression_statement (macro_invocation...",
105 "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
106 ],
107 );
108 assert_layers_for_range(
109 &syntax_map,
110 &buffer,
111 Point::new(2, 14)..Point::new(2, 16),
112 &[
113 "...(function_item ...",
114 "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
115 "...(array_expression (struct_expression ...",
116 ],
117 );
118 assert_layers_for_range(
119 &syntax_map,
120 &buffer,
121 Point::new(3, 14)..Point::new(3, 16),
122 &[
123 "...(function_item ...",
124 "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
125 "...(array_expression (field_expression ...",
126 ],
127 );
128 assert_layers_for_range(
129 &syntax_map,
130 &buffer,
131 Point::new(5, 12)..Point::new(5, 16),
132 &[
133 "...(function_item ...",
134 "...(call_expression ... (arguments (closure_expression ...",
135 ],
136 );
137
138 // Replace a vec! macro invocation with a plain slice, removing a syntactic layer.
139 let macro_name_range = range_for_text(&buffer, "vec!");
140 buffer.edit([(macro_name_range, "&")]);
141 syntax_map.interpolate(&buffer);
142 syntax_map.reparse(language.clone(), &buffer);
143
144 assert_layers_for_range(
145 &syntax_map,
146 &buffer,
147 Point::new(2, 14)..Point::new(2, 16),
148 &[
149 "...(function_item ...",
150 "...(tuple_expression (call_expression ... arguments: (arguments (reference_expression value: (array_expression...",
151 ],
152 );
153
154 // Put the vec! macro back, adding back the syntactic layer.
155 buffer.undo();
156 syntax_map.interpolate(&buffer);
157 syntax_map.reparse(language.clone(), &buffer);
158
159 assert_layers_for_range(
160 &syntax_map,
161 &buffer,
162 Point::new(2, 14)..Point::new(2, 16),
163 &[
164 "...(function_item ...",
165 "...(tuple_expression (call_expression ... arguments: (arguments (macro_invocation...",
166 "...(array_expression (struct_expression ...",
167 ],
168 );
169}
170
171#[gpui::test]
172fn test_dynamic_language_injection() {
173 let registry = Arc::new(LanguageRegistry::test());
174 let markdown = Arc::new(markdown_lang());
175 registry.add(markdown.clone());
176 registry.add(Arc::new(rust_lang()));
177 registry.add(Arc::new(ruby_lang()));
178
179 let mut buffer = Buffer::new(
180 0,
181 0,
182 r#"
183 This is a code block:
184
185 ```rs
186 fn foo() {}
187 ```
188 "#
189 .unindent(),
190 );
191
192 let mut syntax_map = SyntaxMap::new();
193 syntax_map.set_language_registry(registry.clone());
194 syntax_map.reparse(markdown.clone(), &buffer);
195 assert_layers_for_range(
196 &syntax_map,
197 &buffer,
198 Point::new(3, 0)..Point::new(3, 0),
199 &[
200 "...(fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (code_fence_content) (fenced_code_block_delimiter...",
201 "...(function_item name: (identifier) parameters: (parameters) body: (block)...",
202 ],
203 );
204
205 // Replace Rust with Ruby in code block.
206 let macro_name_range = range_for_text(&buffer, "rs");
207 buffer.edit([(macro_name_range, "ruby")]);
208 syntax_map.interpolate(&buffer);
209 syntax_map.reparse(markdown.clone(), &buffer);
210 assert_layers_for_range(
211 &syntax_map,
212 &buffer,
213 Point::new(3, 0)..Point::new(3, 0),
214 &[
215 "...(fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (code_fence_content) (fenced_code_block_delimiter...",
216 "...(call method: (identifier) arguments: (argument_list (call method: (identifier) arguments: (argument_list) block: (block)...",
217 ],
218 );
219
220 // Replace Ruby with a language that hasn't been loaded yet.
221 let macro_name_range = range_for_text(&buffer, "ruby");
222 buffer.edit([(macro_name_range, "html")]);
223 syntax_map.interpolate(&buffer);
224 syntax_map.reparse(markdown.clone(), &buffer);
225 assert_layers_for_range(
226 &syntax_map,
227 &buffer,
228 Point::new(3, 0)..Point::new(3, 0),
229 &[
230 "...(fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (code_fence_content) (fenced_code_block_delimiter..."
231 ],
232 );
233 assert!(syntax_map.contains_unknown_injections());
234
235 registry.add(Arc::new(html_lang()));
236 syntax_map.reparse(markdown.clone(), &buffer);
237 assert_layers_for_range(
238 &syntax_map,
239 &buffer,
240 Point::new(3, 0)..Point::new(3, 0),
241 &[
242 "...(fenced_code_block (fenced_code_block_delimiter) (info_string (language)) (code_fence_content) (fenced_code_block_delimiter...",
243 "(fragment (text))",
244 ],
245 );
246 assert!(!syntax_map.contains_unknown_injections());
247}
248
249#[gpui::test]
250fn test_typing_multiple_new_injections() {
251 let (buffer, syntax_map) = test_edit_sequence(
252 "Rust",
253 &[
254 "fn a() { dbg }",
255 "fn a() { dbg«!» }",
256 "fn a() { dbg!«()» }",
257 "fn a() { dbg!(«b») }",
258 "fn a() { dbg!(b«.») }",
259 "fn a() { dbg!(b.«c») }",
260 "fn a() { dbg!(b.c«()») }",
261 "fn a() { dbg!(b.c(«vec»)) }",
262 "fn a() { dbg!(b.c(vec«!»)) }",
263 "fn a() { dbg!(b.c(vec!«[]»)) }",
264 "fn a() { dbg!(b.c(vec![«d»])) }",
265 "fn a() { dbg!(b.c(vec![d«.»])) }",
266 "fn a() { dbg!(b.c(vec![d.«e»])) }",
267 ],
268 );
269
270 assert_capture_ranges(
271 &syntax_map,
272 &buffer,
273 &["field"],
274 "fn a() { dbg!(b.«c»(vec![d.«e»])) }",
275 );
276}
277
278#[gpui::test]
279fn test_pasting_new_injection_line_between_others() {
280 let (buffer, syntax_map) = test_edit_sequence(
281 "Rust",
282 &[
283 "
284 fn a() {
285 b!(B {});
286 c!(C {});
287 d!(D {});
288 e!(E {});
289 f!(F {});
290 g!(G {});
291 }
292 ",
293 "
294 fn a() {
295 b!(B {});
296 c!(C {});
297 d!(D {});
298 « h!(H {});
299 » e!(E {});
300 f!(F {});
301 g!(G {});
302 }
303 ",
304 ],
305 );
306
307 assert_capture_ranges(
308 &syntax_map,
309 &buffer,
310 &["struct"],
311 "
312 fn a() {
313 b!(«B {}»);
314 c!(«C {}»);
315 d!(«D {}»);
316 h!(«H {}»);
317 e!(«E {}»);
318 f!(«F {}»);
319 g!(«G {}»);
320 }
321 ",
322 );
323}
324
325#[gpui::test]
326fn test_joining_injections_with_child_injections() {
327 let (buffer, syntax_map) = test_edit_sequence(
328 "Rust",
329 &[
330 "
331 fn a() {
332 b!(
333 c![one.two.three],
334 d![four.five.six],
335 );
336 e!(
337 f![seven.eight],
338 );
339 }
340 ",
341 "
342 fn a() {
343 b!(
344 c![one.two.three],
345 d![four.five.six],
346 ˇ f![seven.eight],
347 );
348 }
349 ",
350 ],
351 );
352
353 assert_capture_ranges(
354 &syntax_map,
355 &buffer,
356 &["field"],
357 "
358 fn a() {
359 b!(
360 c![one.«two».«three»],
361 d![four.«five».«six»],
362 f![seven.«eight»],
363 );
364 }
365 ",
366 );
367}
368
369#[gpui::test]
370fn test_editing_edges_of_injection() {
371 test_edit_sequence(
372 "Rust",
373 &[
374 "
375 fn a() {
376 b!(c!())
377 }
378 ",
379 "
380 fn a() {
381 «d»!(c!())
382 }
383 ",
384 "
385 fn a() {
386 «e»d!(c!())
387 }
388 ",
389 "
390 fn a() {
391 ed!«[»c!()«]»
392 }
393 ",
394 ],
395 );
396}
397
398#[gpui::test]
399fn test_edits_preceding_and_intersecting_injection() {
400 test_edit_sequence(
401 "Rust",
402 &[
403 //
404 "const aaaaaaaaaaaa: B = c!(d(e.f));",
405 "const aˇa: B = c!(d(eˇ));",
406 ],
407 );
408}
409
410#[gpui::test]
411fn test_non_local_changes_create_injections() {
412 test_edit_sequence(
413 "Rust",
414 &[
415 "
416 // a! {
417 static B: C = d;
418 // }
419 ",
420 "
421 ˇa! {
422 static B: C = d;
423 ˇ}
424 ",
425 ],
426 );
427}
428
429#[gpui::test]
430fn test_creating_many_injections_in_one_edit() {
431 test_edit_sequence(
432 "Rust",
433 &[
434 "
435 fn a() {
436 one(Two::three(3));
437 four(Five::six(6));
438 seven(Eight::nine(9));
439 }
440 ",
441 "
442 fn a() {
443 one«!»(Two::three(3));
444 four«!»(Five::six(6));
445 seven«!»(Eight::nine(9));
446 }
447 ",
448 "
449 fn a() {
450 one!(Two::three«!»(3));
451 four!(Five::six«!»(6));
452 seven!(Eight::nine«!»(9));
453 }
454 ",
455 ],
456 );
457}
458
459#[gpui::test]
460fn test_editing_across_injection_boundary() {
461 test_edit_sequence(
462 "Rust",
463 &[
464 "
465 fn one() {
466 two();
467 three!(
468 three.four,
469 five.six,
470 );
471 }
472 ",
473 "
474 fn one() {
475 two();
476 th«irty_five![»
477 three.four,
478 five.six,
479 « seven.eight,
480 ];»
481 }
482 ",
483 ],
484 );
485}
486
487#[gpui::test]
488fn test_removing_injection_by_replacing_across_boundary() {
489 test_edit_sequence(
490 "Rust",
491 &[
492 "
493 fn one() {
494 two!(
495 three.four,
496 );
497 }
498 ",
499 "
500 fn one() {
501 t«en
502 .eleven(
503 twelve,
504 »
505 three.four,
506 );
507 }
508 ",
509 ],
510 );
511}
512
513#[gpui::test]
514fn test_combined_injections() {
515 let (buffer, syntax_map) = test_edit_sequence(
516 "ERB",
517 &[
518 "
519 <body>
520 <% if @one %>
521 <div class=one>
522 <% else %>
523 <div class=two>
524 <% end %>
525 </div>
526 </body>
527 ",
528 "
529 <body>
530 <% if @one %>
531 <div class=one>
532 ˇ else ˇ
533 <div class=two>
534 <% end %>
535 </div>
536 </body>
537 ",
538 "
539 <body>
540 <% if @one «;» end %>
541 </div>
542 </body>
543 ",
544 ],
545 );
546
547 assert_capture_ranges(
548 &syntax_map,
549 &buffer,
550 &["tag", "ivar"],
551 "
552 <«body»>
553 <% if «@one» ; end %>
554 </«div»>
555 </«body»>
556 ",
557 );
558}
559
560#[gpui::test]
561fn test_combined_injections_empty_ranges() {
562 test_edit_sequence(
563 "ERB",
564 &[
565 "
566 <% if @one %>
567 <% else %>
568 <% end %>
569 ",
570 "
571 <% if @one %>
572 ˇ<% end %>
573 ",
574 ],
575 );
576}
577
578#[gpui::test]
579fn test_combined_injections_edit_edges_of_ranges() {
580 let (buffer, syntax_map) = test_edit_sequence(
581 "ERB",
582 &[
583 "
584 <%= one @two %>
585 <%= three @four %>
586 ",
587 "
588 <%= one @two %ˇ
589 <%= three @four %>
590 ",
591 "
592 <%= one @two %«>»
593 <%= three @four %>
594 ",
595 ],
596 );
597
598 assert_capture_ranges(
599 &syntax_map,
600 &buffer,
601 &["tag", "ivar"],
602 "
603 <%= one «@two» %>
604 <%= three «@four» %>
605 ",
606 );
607}
608
609#[gpui::test]
610fn test_combined_injections_splitting_some_injections() {
611 let (_buffer, _syntax_map) = test_edit_sequence(
612 "ERB",
613 &[
614 r#"
615 <%A if b(:c) %>
616 d
617 <% end %>
618 eee
619 <% f %>
620 "#,
621 r#"
622 <%« AAAAAAA %>
623 hhhhhhh
624 <%=» if b(:c) %>
625 d
626 <% end %>
627 eee
628 <% f %>
629 "#,
630 ],
631 );
632}
633
634#[gpui::test]
635fn test_combined_injections_editing_after_last_injection() {
636 test_edit_sequence(
637 "ERB",
638 &[
639 r#"
640 <% foo %>
641 <div></div>
642 <% bar %>
643 "#,
644 r#"
645 <% foo %>
646 <div></div>
647 <% bar %>«
648 more text»
649 "#,
650 ],
651 );
652}
653
654#[gpui::test]
655fn test_combined_injections_inside_injections() {
656 let (_buffer, _syntax_map) = test_edit_sequence(
657 "Markdown",
658 &[
659 r#"
660 here is some ERB code:
661
662 ```erb
663 <ul>
664 <% people.each do |person| %>
665 <li><%= person.name %></li>
666 <% end %>
667 </ul>
668 ```
669 "#,
670 r#"
671 here is some ERB code:
672
673 ```erb
674 <ul>
675 <% people«2».each do |person| %>
676 <li><%= person.name %></li>
677 <% end %>
678 </ul>
679 ```
680 "#,
681 ],
682 );
683}
684
685#[gpui::test]
686fn test_empty_combined_injections_inside_injections() {
687 let (buffer, syntax_map) = test_edit_sequence(
688 "Markdown",
689 &[r#"
690 ```erb
691 hello
692 ```
693
694 goodbye
695 "#],
696 );
697
698 assert_layers_for_range(
699 &syntax_map,
700 &buffer,
701 Point::new(0, 0)..Point::new(5, 0),
702 &[
703 "...(paragraph)...",
704 "(template...",
705 "(fragment...",
706 // The ruby syntax tree should be empty, since there are
707 // no interpolations in the ERB template.
708 "(program)",
709 ],
710 );
711}
712
713#[gpui::test(iterations = 50)]
714fn test_random_syntax_map_edits(mut rng: StdRng) {
715 let operations = env::var("OPERATIONS")
716 .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
717 .unwrap_or(10);
718
719 let text = r#"
720 fn test_something() {
721 let vec = vec![5, 1, 3, 8];
722 assert_eq!(
723 vec
724 .into_iter()
725 .map(|i| i * 2)
726 .collect::<Vec<usize>>(),
727 vec![
728 5 * 2, 1 * 2, 3 * 2, 8 * 2
729 ],
730 );
731 }
732 "#
733 .unindent()
734 .repeat(2);
735
736 let registry = Arc::new(LanguageRegistry::test());
737 let language = Arc::new(rust_lang());
738 registry.add(language.clone());
739 let mut buffer = Buffer::new(0, 0, text);
740
741 let mut syntax_map = SyntaxMap::new();
742 syntax_map.set_language_registry(registry.clone());
743 syntax_map.reparse(language.clone(), &buffer);
744
745 let mut reference_syntax_map = SyntaxMap::new();
746 reference_syntax_map.set_language_registry(registry.clone());
747
748 log::info!("initial text:\n{}", buffer.text());
749
750 for _ in 0..operations {
751 let prev_buffer = buffer.snapshot();
752 let prev_syntax_map = syntax_map.snapshot();
753
754 buffer.randomly_edit(&mut rng, 3);
755 log::info!("text:\n{}", buffer.text());
756
757 syntax_map.interpolate(&buffer);
758 check_interpolation(&prev_syntax_map, &syntax_map, &prev_buffer, &buffer);
759
760 syntax_map.reparse(language.clone(), &buffer);
761
762 reference_syntax_map.clear();
763 reference_syntax_map.reparse(language.clone(), &buffer);
764 }
765
766 for i in 0..operations {
767 let i = operations - i - 1;
768 buffer.undo();
769 log::info!("undoing operation {}", i);
770 log::info!("text:\n{}", buffer.text());
771
772 syntax_map.interpolate(&buffer);
773 syntax_map.reparse(language.clone(), &buffer);
774
775 reference_syntax_map.clear();
776 reference_syntax_map.reparse(language.clone(), &buffer);
777 assert_eq!(
778 syntax_map.layers(&buffer).len(),
779 reference_syntax_map.layers(&buffer).len(),
780 "wrong number of layers after undoing edit {i}"
781 );
782 }
783
784 let layers = syntax_map.layers(&buffer);
785 let reference_layers = reference_syntax_map.layers(&buffer);
786 for (edited_layer, reference_layer) in layers.into_iter().zip(reference_layers.into_iter()) {
787 assert_eq!(
788 edited_layer.node().to_sexp(),
789 reference_layer.node().to_sexp()
790 );
791 assert_eq!(edited_layer.node().range(), reference_layer.node().range());
792 }
793}
794
795#[gpui::test(iterations = 50)]
796fn test_random_syntax_map_edits_with_combined_injections(mut rng: StdRng) {
797 let operations = env::var("OPERATIONS")
798 .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
799 .unwrap_or(10);
800
801 let text = r#"
802 <div id="main">
803 <% if one?(:two) %>
804 <p class="three" four>
805 <%= yield :five %>
806 </p>
807 <% elsif Six.seven(8) %>
808 <p id="three" four>
809 <%= yield :five %>
810 </p>
811 <% else %>
812 <span>Ok</span>
813 <% end %>
814 </div>
815 "#
816 .unindent()
817 .repeat(8);
818
819 let registry = Arc::new(LanguageRegistry::test());
820 let language = Arc::new(erb_lang());
821 registry.add(language.clone());
822 registry.add(Arc::new(ruby_lang()));
823 registry.add(Arc::new(html_lang()));
824 let mut buffer = Buffer::new(0, 0, text);
825
826 let mut syntax_map = SyntaxMap::new();
827 syntax_map.set_language_registry(registry.clone());
828 syntax_map.reparse(language.clone(), &buffer);
829
830 let mut reference_syntax_map = SyntaxMap::new();
831 reference_syntax_map.set_language_registry(registry.clone());
832
833 log::info!("initial text:\n{}", buffer.text());
834
835 for _ in 0..operations {
836 let prev_buffer = buffer.snapshot();
837 let prev_syntax_map = syntax_map.snapshot();
838
839 buffer.randomly_edit(&mut rng, 3);
840 log::info!("text:\n{}", buffer.text());
841
842 syntax_map.interpolate(&buffer);
843 check_interpolation(&prev_syntax_map, &syntax_map, &prev_buffer, &buffer);
844
845 syntax_map.reparse(language.clone(), &buffer);
846
847 reference_syntax_map.clear();
848 reference_syntax_map.reparse(language.clone(), &buffer);
849 }
850
851 for i in 0..operations {
852 let i = operations - i - 1;
853 buffer.undo();
854 log::info!("undoing operation {}", i);
855 log::info!("text:\n{}", buffer.text());
856
857 syntax_map.interpolate(&buffer);
858 syntax_map.reparse(language.clone(), &buffer);
859
860 reference_syntax_map.clear();
861 reference_syntax_map.reparse(language.clone(), &buffer);
862 assert_eq!(
863 syntax_map.layers(&buffer).len(),
864 reference_syntax_map.layers(&buffer).len(),
865 "wrong number of layers after undoing edit {i}"
866 );
867 }
868
869 let layers = syntax_map.layers(&buffer);
870 let reference_layers = reference_syntax_map.layers(&buffer);
871 for (edited_layer, reference_layer) in layers.into_iter().zip(reference_layers.into_iter()) {
872 assert_eq!(
873 edited_layer.node().to_sexp(),
874 reference_layer.node().to_sexp()
875 );
876 assert_eq!(edited_layer.node().range(), reference_layer.node().range());
877 }
878}
879
880fn check_interpolation(
881 old_syntax_map: &SyntaxSnapshot,
882 new_syntax_map: &SyntaxSnapshot,
883 old_buffer: &BufferSnapshot,
884 new_buffer: &BufferSnapshot,
885) {
886 let edits = new_buffer
887 .edits_since::<usize>(&old_buffer.version())
888 .collect::<Vec<_>>();
889
890 for (old_layer, new_layer) in old_syntax_map
891 .layers
892 .iter()
893 .zip(new_syntax_map.layers.iter())
894 {
895 assert_eq!(old_layer.range, new_layer.range);
896 let Some(old_tree) = old_layer.content.tree() else { continue };
897 let Some(new_tree) = new_layer.content.tree() else { continue };
898 let old_start_byte = old_layer.range.start.to_offset(old_buffer);
899 let new_start_byte = new_layer.range.start.to_offset(new_buffer);
900 let old_start_point = old_layer.range.start.to_point(old_buffer).to_ts_point();
901 let new_start_point = new_layer.range.start.to_point(new_buffer).to_ts_point();
902 let old_node = old_tree.root_node_with_offset(old_start_byte, old_start_point);
903 let new_node = new_tree.root_node_with_offset(new_start_byte, new_start_point);
904 check_node_edits(
905 old_layer.depth,
906 &old_layer.range,
907 old_node,
908 new_node,
909 old_buffer,
910 new_buffer,
911 &edits,
912 );
913 }
914
915 fn check_node_edits(
916 depth: usize,
917 range: &Range<Anchor>,
918 old_node: Node,
919 new_node: Node,
920 old_buffer: &BufferSnapshot,
921 new_buffer: &BufferSnapshot,
922 edits: &[text::Edit<usize>],
923 ) {
924 assert_eq!(old_node.kind(), new_node.kind());
925
926 let old_range = old_node.byte_range();
927 let new_range = new_node.byte_range();
928
929 let is_edited = edits
930 .iter()
931 .any(|edit| edit.new.start < new_range.end && edit.new.end > new_range.start);
932 if is_edited {
933 assert!(
934 new_node.has_changes(),
935 concat!(
936 "failed to mark node as edited.\n",
937 "layer depth: {}, old layer range: {:?}, new layer range: {:?},\n",
938 "node kind: {}, old node range: {:?}, new node range: {:?}",
939 ),
940 depth,
941 range.to_offset(old_buffer),
942 range.to_offset(new_buffer),
943 new_node.kind(),
944 old_range,
945 new_range,
946 );
947 }
948
949 if !new_node.has_changes() {
950 assert_eq!(
951 old_buffer
952 .text_for_range(old_range.clone())
953 .collect::<String>(),
954 new_buffer
955 .text_for_range(new_range.clone())
956 .collect::<String>(),
957 concat!(
958 "mismatched text for node\n",
959 "layer depth: {}, old layer range: {:?}, new layer range: {:?},\n",
960 "node kind: {}, old node range:{:?}, new node range:{:?}",
961 ),
962 depth,
963 range.to_offset(old_buffer),
964 range.to_offset(new_buffer),
965 new_node.kind(),
966 old_range,
967 new_range,
968 );
969 }
970
971 for i in 0..new_node.child_count() {
972 check_node_edits(
973 depth,
974 range,
975 old_node.child(i).unwrap(),
976 new_node.child(i).unwrap(),
977 old_buffer,
978 new_buffer,
979 edits,
980 )
981 }
982 }
983}
984
985fn test_edit_sequence(language_name: &str, steps: &[&str]) -> (Buffer, SyntaxMap) {
986 let registry = Arc::new(LanguageRegistry::test());
987 registry.add(Arc::new(rust_lang()));
988 registry.add(Arc::new(ruby_lang()));
989 registry.add(Arc::new(html_lang()));
990 registry.add(Arc::new(erb_lang()));
991 registry.add(Arc::new(markdown_lang()));
992 let language = registry
993 .language_for_name(language_name)
994 .now_or_never()
995 .unwrap()
996 .unwrap();
997 let mut buffer = Buffer::new(0, 0, Default::default());
998
999 let mut mutated_syntax_map = SyntaxMap::new();
1000 mutated_syntax_map.set_language_registry(registry.clone());
1001 mutated_syntax_map.reparse(language.clone(), &buffer);
1002
1003 for (i, marked_string) in steps.into_iter().enumerate() {
1004 let marked_string = marked_string.unindent();
1005 log::info!("incremental parse {i}: {marked_string:?}");
1006 buffer.edit_via_marked_text(&marked_string);
1007
1008 // Reparse the syntax map
1009 mutated_syntax_map.interpolate(&buffer);
1010 mutated_syntax_map.reparse(language.clone(), &buffer);
1011
1012 // Create a second syntax map from scratch
1013 log::info!("fresh parse {i}: {marked_string:?}");
1014 let mut reference_syntax_map = SyntaxMap::new();
1015 reference_syntax_map.set_language_registry(registry.clone());
1016 reference_syntax_map.reparse(language.clone(), &buffer);
1017
1018 // Compare the mutated syntax map to the new syntax map
1019 let mutated_layers = mutated_syntax_map.layers(&buffer);
1020 let reference_layers = reference_syntax_map.layers(&buffer);
1021 assert_eq!(
1022 mutated_layers.len(),
1023 reference_layers.len(),
1024 "wrong number of layers at step {i}"
1025 );
1026 for (edited_layer, reference_layer) in
1027 mutated_layers.into_iter().zip(reference_layers.into_iter())
1028 {
1029 assert_eq!(
1030 edited_layer.node().to_sexp(),
1031 reference_layer.node().to_sexp(),
1032 "different layer at step {i}"
1033 );
1034 assert_eq!(
1035 edited_layer.node().range(),
1036 reference_layer.node().range(),
1037 "different layer at step {i}"
1038 );
1039 }
1040 }
1041
1042 (buffer, mutated_syntax_map)
1043}
1044
1045fn html_lang() -> Language {
1046 Language::new(
1047 LanguageConfig {
1048 name: "HTML".into(),
1049 path_suffixes: vec!["html".to_string()],
1050 ..Default::default()
1051 },
1052 Some(tree_sitter_html::language()),
1053 )
1054 .with_highlights_query(
1055 r#"
1056 (tag_name) @tag
1057 (erroneous_end_tag_name) @tag
1058 (attribute_name) @property
1059 "#,
1060 )
1061 .unwrap()
1062}
1063
1064fn ruby_lang() -> Language {
1065 Language::new(
1066 LanguageConfig {
1067 name: "Ruby".into(),
1068 path_suffixes: vec!["rb".to_string()],
1069 ..Default::default()
1070 },
1071 Some(tree_sitter_ruby::language()),
1072 )
1073 .with_highlights_query(
1074 r#"
1075 ["if" "do" "else" "end"] @keyword
1076 (instance_variable) @ivar
1077 "#,
1078 )
1079 .unwrap()
1080}
1081
1082fn erb_lang() -> Language {
1083 Language::new(
1084 LanguageConfig {
1085 name: "ERB".into(),
1086 path_suffixes: vec!["erb".to_string()],
1087 ..Default::default()
1088 },
1089 Some(tree_sitter_embedded_template::language()),
1090 )
1091 .with_highlights_query(
1092 r#"
1093 ["<%" "%>"] @keyword
1094 "#,
1095 )
1096 .unwrap()
1097 .with_injection_query(
1098 r#"
1099 (
1100 (code) @content
1101 (#set! "language" "ruby")
1102 (#set! "combined")
1103 )
1104
1105 (
1106 (content) @content
1107 (#set! "language" "html")
1108 (#set! "combined")
1109 )
1110 "#,
1111 )
1112 .unwrap()
1113}
1114
1115fn rust_lang() -> Language {
1116 Language::new(
1117 LanguageConfig {
1118 name: "Rust".into(),
1119 path_suffixes: vec!["rs".to_string()],
1120 ..Default::default()
1121 },
1122 Some(tree_sitter_rust::language()),
1123 )
1124 .with_highlights_query(
1125 r#"
1126 (field_identifier) @field
1127 (struct_expression) @struct
1128 "#,
1129 )
1130 .unwrap()
1131 .with_injection_query(
1132 r#"
1133 (macro_invocation
1134 (token_tree) @content
1135 (#set! "language" "rust"))
1136 "#,
1137 )
1138 .unwrap()
1139}
1140
1141fn markdown_lang() -> Language {
1142 Language::new(
1143 LanguageConfig {
1144 name: "Markdown".into(),
1145 path_suffixes: vec!["md".into()],
1146 ..Default::default()
1147 },
1148 Some(tree_sitter_markdown::language()),
1149 )
1150 .with_injection_query(
1151 r#"
1152 (fenced_code_block
1153 (info_string
1154 (language) @language)
1155 (code_fence_content) @content)
1156 "#,
1157 )
1158 .unwrap()
1159}
1160
1161fn range_for_text(buffer: &Buffer, text: &str) -> Range<usize> {
1162 let start = buffer.as_rope().to_string().find(text).unwrap();
1163 start..start + text.len()
1164}
1165
1166#[track_caller]
1167fn assert_layers_for_range(
1168 syntax_map: &SyntaxMap,
1169 buffer: &BufferSnapshot,
1170 range: Range<Point>,
1171 expected_layers: &[&str],
1172) {
1173 let layers = syntax_map
1174 .layers_for_range(range, &buffer)
1175 .collect::<Vec<_>>();
1176 assert_eq!(
1177 layers.len(),
1178 expected_layers.len(),
1179 "wrong number of layers"
1180 );
1181 for (i, (layer, expected_s_exp)) in layers.iter().zip(expected_layers.iter()).enumerate() {
1182 let actual_s_exp = layer.node().to_sexp();
1183 assert!(
1184 string_contains_sequence(
1185 &actual_s_exp,
1186 &expected_s_exp.split("...").collect::<Vec<_>>()
1187 ),
1188 "layer {i}:\n\nexpected: {expected_s_exp}\nactual: {actual_s_exp}",
1189 );
1190 }
1191}
1192
1193fn assert_capture_ranges(
1194 syntax_map: &SyntaxMap,
1195 buffer: &BufferSnapshot,
1196 highlight_query_capture_names: &[&str],
1197 marked_string: &str,
1198) {
1199 let mut actual_ranges = Vec::<Range<usize>>::new();
1200 let captures = syntax_map.captures(0..buffer.len(), buffer, |grammar| {
1201 grammar.highlights_query.as_ref()
1202 });
1203 let queries = captures
1204 .grammars()
1205 .iter()
1206 .map(|grammar| grammar.highlights_query.as_ref().unwrap())
1207 .collect::<Vec<_>>();
1208 for capture in captures {
1209 let name = &queries[capture.grammar_index].capture_names()[capture.index as usize];
1210 if highlight_query_capture_names.contains(&name.as_str()) {
1211 actual_ranges.push(capture.node.byte_range());
1212 }
1213 }
1214
1215 let (text, expected_ranges) = marked_text_ranges(&marked_string.unindent(), false);
1216 assert_eq!(text, buffer.text());
1217 assert_eq!(actual_ranges, expected_ranges);
1218}
1219
1220pub fn string_contains_sequence(text: &str, parts: &[&str]) -> bool {
1221 let mut last_part_end = 0;
1222 for part in parts {
1223 if let Some(start_ix) = text[last_part_end..].find(part) {
1224 last_part_end = start_ix + part.len();
1225 } else {
1226 return false;
1227 }
1228 }
1229 true
1230}