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