tests.rs

   1use super::*;
   2use clock::ReplicaId;
   3use collections::BTreeMap;
   4use gpui::{ModelHandle, MutableAppContext};
   5use proto::deserialize_operation;
   6use rand::prelude::*;
   7use settings::Settings;
   8use std::{
   9    cell::RefCell,
  10    env,
  11    ops::Range,
  12    rc::Rc,
  13    time::{Duration, Instant},
  14};
  15use text::network::Network;
  16use unindent::Unindent as _;
  17use util::post_inc;
  18
  19#[cfg(test)]
  20#[ctor::ctor]
  21fn init_logger() {
  22    if std::env::var("RUST_LOG").is_ok() {
  23        env_logger::init();
  24    }
  25}
  26
  27#[gpui::test]
  28fn test_line_endings(cx: &mut gpui::MutableAppContext) {
  29    cx.set_global(Settings::test(cx));
  30    cx.add_model(|cx| {
  31        let mut buffer =
  32            Buffer::new(0, "one\r\ntwo\rthree", cx).with_language(Arc::new(rust_lang()), cx);
  33        assert_eq!(buffer.text(), "one\ntwo\nthree");
  34        assert_eq!(buffer.line_ending(), LineEnding::Windows);
  35
  36        buffer.check_invariants();
  37        buffer.edit(
  38            [(buffer.len()..buffer.len(), "\r\nfour")],
  39            Some(AutoindentMode::EachLine),
  40            cx,
  41        );
  42        buffer.edit([(0..0, "zero\r\n")], None, cx);
  43        assert_eq!(buffer.text(), "zero\none\ntwo\nthree\nfour");
  44        assert_eq!(buffer.line_ending(), LineEnding::Windows);
  45        buffer.check_invariants();
  46
  47        buffer
  48    });
  49}
  50
  51#[gpui::test]
  52fn test_select_language() {
  53    let registry = LanguageRegistry::test();
  54    registry.add(Arc::new(Language::new(
  55        LanguageConfig {
  56            name: "Rust".into(),
  57            path_suffixes: vec!["rs".to_string()],
  58            ..Default::default()
  59        },
  60        Some(tree_sitter_rust::language()),
  61    )));
  62    registry.add(Arc::new(Language::new(
  63        LanguageConfig {
  64            name: "Make".into(),
  65            path_suffixes: vec!["Makefile".to_string(), "mk".to_string()],
  66            ..Default::default()
  67        },
  68        Some(tree_sitter_rust::language()),
  69    )));
  70
  71    // matching file extension
  72    assert_eq!(
  73        registry.select_language("zed/lib.rs").map(|l| l.name()),
  74        Some("Rust".into())
  75    );
  76    assert_eq!(
  77        registry.select_language("zed/lib.mk").map(|l| l.name()),
  78        Some("Make".into())
  79    );
  80
  81    // matching filename
  82    assert_eq!(
  83        registry.select_language("zed/Makefile").map(|l| l.name()),
  84        Some("Make".into())
  85    );
  86
  87    // matching suffix that is not the full file extension or filename
  88    assert_eq!(registry.select_language("zed/cars").map(|l| l.name()), None);
  89    assert_eq!(
  90        registry.select_language("zed/a.cars").map(|l| l.name()),
  91        None
  92    );
  93    assert_eq!(registry.select_language("zed/sumk").map(|l| l.name()), None);
  94}
  95
  96#[gpui::test]
  97fn test_edit_events(cx: &mut gpui::MutableAppContext) {
  98    let mut now = Instant::now();
  99    let buffer_1_events = Rc::new(RefCell::new(Vec::new()));
 100    let buffer_2_events = Rc::new(RefCell::new(Vec::new()));
 101
 102    let buffer1 = cx.add_model(|cx| Buffer::new(0, "abcdef", cx));
 103    let buffer2 = cx.add_model(|cx| Buffer::new(1, "abcdef", cx));
 104    let buffer1_ops = Rc::new(RefCell::new(Vec::new()));
 105    buffer1.update(cx, {
 106        let buffer1_ops = buffer1_ops.clone();
 107        |buffer, cx| {
 108            let buffer_1_events = buffer_1_events.clone();
 109            cx.subscribe(&buffer1, move |_, _, event, _| match event.clone() {
 110                Event::Operation(op) => buffer1_ops.borrow_mut().push(op),
 111                event => buffer_1_events.borrow_mut().push(event),
 112            })
 113            .detach();
 114            let buffer_2_events = buffer_2_events.clone();
 115            cx.subscribe(&buffer2, move |_, _, event, _| {
 116                buffer_2_events.borrow_mut().push(event.clone())
 117            })
 118            .detach();
 119
 120            // An edit emits an edited event, followed by a dirty changed event,
 121            // since the buffer was previously in a clean state.
 122            buffer.edit([(2..4, "XYZ")], None, cx);
 123
 124            // An empty transaction does not emit any events.
 125            buffer.start_transaction();
 126            buffer.end_transaction(cx);
 127
 128            // A transaction containing two edits emits one edited event.
 129            now += Duration::from_secs(1);
 130            buffer.start_transaction_at(now);
 131            buffer.edit([(5..5, "u")], None, cx);
 132            buffer.edit([(6..6, "w")], None, cx);
 133            buffer.end_transaction_at(now, cx);
 134
 135            // Undoing a transaction emits one edited event.
 136            buffer.undo(cx);
 137        }
 138    });
 139
 140    // Incorporating a set of remote ops emits a single edited event,
 141    // followed by a dirty changed event.
 142    buffer2.update(cx, |buffer, cx| {
 143        buffer
 144            .apply_ops(buffer1_ops.borrow_mut().drain(..), cx)
 145            .unwrap();
 146    });
 147    assert_eq!(
 148        mem::take(&mut *buffer_1_events.borrow_mut()),
 149        vec![
 150            Event::Edited,
 151            Event::DirtyChanged,
 152            Event::Edited,
 153            Event::Edited,
 154        ]
 155    );
 156    assert_eq!(
 157        mem::take(&mut *buffer_2_events.borrow_mut()),
 158        vec![Event::Edited, Event::DirtyChanged]
 159    );
 160
 161    buffer1.update(cx, |buffer, cx| {
 162        // Undoing the first transaction emits edited event, followed by a
 163        // dirty changed event, since the buffer is again in a clean state.
 164        buffer.undo(cx);
 165    });
 166    // Incorporating the remote ops again emits a single edited event,
 167    // followed by a dirty changed event.
 168    buffer2.update(cx, |buffer, cx| {
 169        buffer
 170            .apply_ops(buffer1_ops.borrow_mut().drain(..), cx)
 171            .unwrap();
 172    });
 173    assert_eq!(
 174        mem::take(&mut *buffer_1_events.borrow_mut()),
 175        vec![Event::Edited, Event::DirtyChanged,]
 176    );
 177    assert_eq!(
 178        mem::take(&mut *buffer_2_events.borrow_mut()),
 179        vec![Event::Edited, Event::DirtyChanged]
 180    );
 181}
 182
 183#[gpui::test]
 184async fn test_apply_diff(cx: &mut gpui::TestAppContext) {
 185    let text = "a\nbb\nccc\ndddd\neeeee\nffffff\n";
 186    let buffer = cx.add_model(|cx| Buffer::new(0, text, cx));
 187    let anchor = buffer.read_with(cx, |buffer, _| buffer.anchor_before(Point::new(3, 3)));
 188
 189    let text = "a\nccc\ndddd\nffffff\n";
 190    let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await;
 191    buffer.update(cx, |buffer, cx| {
 192        buffer.apply_diff(diff, cx).unwrap();
 193        assert_eq!(buffer.text(), text);
 194        assert_eq!(anchor.to_point(buffer), Point::new(2, 3));
 195    });
 196
 197    let text = "a\n1\n\nccc\ndd2dd\nffffff\n";
 198    let diff = buffer.read_with(cx, |b, cx| b.diff(text.into(), cx)).await;
 199    buffer.update(cx, |buffer, cx| {
 200        buffer.apply_diff(diff, cx).unwrap();
 201        assert_eq!(buffer.text(), text);
 202        assert_eq!(anchor.to_point(buffer), Point::new(4, 4));
 203    });
 204}
 205
 206#[gpui::test]
 207async fn test_reparse(cx: &mut gpui::TestAppContext) {
 208    let text = "fn a() {}";
 209    let buffer =
 210        cx.add_model(|cx| Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx));
 211
 212    // Wait for the initial text to parse
 213    buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
 214    assert_eq!(
 215        get_tree_sexp(&buffer, cx),
 216        concat!(
 217            "(source_file (function_item name: (identifier) ",
 218            "parameters: (parameters) ",
 219            "body: (block)))"
 220        )
 221    );
 222
 223    buffer.update(cx, |buffer, _| {
 224        buffer.set_sync_parse_timeout(Duration::ZERO)
 225    });
 226
 227    // Perform some edits (add parameter and variable reference)
 228    // Parsing doesn't begin until the transaction is complete
 229    buffer.update(cx, |buf, cx| {
 230        buf.start_transaction();
 231
 232        let offset = buf.text().find(')').unwrap();
 233        buf.edit([(offset..offset, "b: C")], None, cx);
 234        assert!(!buf.is_parsing());
 235
 236        let offset = buf.text().find('}').unwrap();
 237        buf.edit([(offset..offset, " d; ")], None, cx);
 238        assert!(!buf.is_parsing());
 239
 240        buf.end_transaction(cx);
 241        assert_eq!(buf.text(), "fn a(b: C) { d; }");
 242        assert!(buf.is_parsing());
 243    });
 244    buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
 245    assert_eq!(
 246        get_tree_sexp(&buffer, cx),
 247        concat!(
 248            "(source_file (function_item name: (identifier) ",
 249            "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
 250            "body: (block (expression_statement (identifier)))))"
 251        )
 252    );
 253
 254    // Perform a series of edits without waiting for the current parse to complete:
 255    // * turn identifier into a field expression
 256    // * turn field expression into a method call
 257    // * add a turbofish to the method call
 258    buffer.update(cx, |buf, cx| {
 259        let offset = buf.text().find(';').unwrap();
 260        buf.edit([(offset..offset, ".e")], None, cx);
 261        assert_eq!(buf.text(), "fn a(b: C) { d.e; }");
 262        assert!(buf.is_parsing());
 263    });
 264    buffer.update(cx, |buf, cx| {
 265        let offset = buf.text().find(';').unwrap();
 266        buf.edit([(offset..offset, "(f)")], None, cx);
 267        assert_eq!(buf.text(), "fn a(b: C) { d.e(f); }");
 268        assert!(buf.is_parsing());
 269    });
 270    buffer.update(cx, |buf, cx| {
 271        let offset = buf.text().find("(f)").unwrap();
 272        buf.edit([(offset..offset, "::<G>")], None, cx);
 273        assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
 274        assert!(buf.is_parsing());
 275    });
 276    buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
 277    assert_eq!(
 278        get_tree_sexp(&buffer, cx),
 279        concat!(
 280            "(source_file (function_item name: (identifier) ",
 281            "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
 282            "body: (block (expression_statement (call_expression ",
 283            "function: (generic_function ",
 284            "function: (field_expression value: (identifier) field: (field_identifier)) ",
 285            "type_arguments: (type_arguments (type_identifier))) ",
 286            "arguments: (arguments (identifier)))))))",
 287        )
 288    );
 289
 290    buffer.update(cx, |buf, cx| {
 291        buf.undo(cx);
 292        assert_eq!(buf.text(), "fn a() {}");
 293        assert!(buf.is_parsing());
 294    });
 295    buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
 296    assert_eq!(
 297        get_tree_sexp(&buffer, cx),
 298        concat!(
 299            "(source_file (function_item name: (identifier) ",
 300            "parameters: (parameters) ",
 301            "body: (block)))"
 302        )
 303    );
 304
 305    buffer.update(cx, |buf, cx| {
 306        buf.redo(cx);
 307        assert_eq!(buf.text(), "fn a(b: C) { d.e::<G>(f); }");
 308        assert!(buf.is_parsing());
 309    });
 310    buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
 311    assert_eq!(
 312        get_tree_sexp(&buffer, cx),
 313        concat!(
 314            "(source_file (function_item name: (identifier) ",
 315            "parameters: (parameters (parameter pattern: (identifier) type: (type_identifier))) ",
 316            "body: (block (expression_statement (call_expression ",
 317            "function: (generic_function ",
 318            "function: (field_expression value: (identifier) field: (field_identifier)) ",
 319            "type_arguments: (type_arguments (type_identifier))) ",
 320            "arguments: (arguments (identifier)))))))",
 321        )
 322    );
 323}
 324
 325#[gpui::test]
 326async fn test_resetting_language(cx: &mut gpui::TestAppContext) {
 327    let buffer = cx.add_model(|cx| {
 328        let mut buffer = Buffer::new(0, "{}", cx).with_language(Arc::new(rust_lang()), cx);
 329        buffer.set_sync_parse_timeout(Duration::ZERO);
 330        buffer
 331    });
 332
 333    // Wait for the initial text to parse
 334    buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
 335    assert_eq!(
 336        get_tree_sexp(&buffer, cx),
 337        "(source_file (expression_statement (block)))"
 338    );
 339
 340    buffer.update(cx, |buffer, cx| {
 341        buffer.set_language(Some(Arc::new(json_lang())), cx)
 342    });
 343    buffer.condition(cx, |buffer, _| !buffer.is_parsing()).await;
 344    assert_eq!(get_tree_sexp(&buffer, cx), "(document (object))");
 345}
 346
 347#[gpui::test]
 348async fn test_outline(cx: &mut gpui::TestAppContext) {
 349    let text = r#"
 350        struct Person {
 351            name: String,
 352            age: usize,
 353        }
 354
 355        mod module {
 356            enum LoginState {
 357                LoggedOut,
 358                LoggingOn,
 359                LoggedIn {
 360                    person: Person,
 361                    time: Instant,
 362                }
 363            }
 364        }
 365
 366        impl Eq for Person {}
 367
 368        impl Drop for Person {
 369            fn drop(&mut self) {
 370                println!("bye");
 371            }
 372        }
 373    "#
 374    .unindent();
 375
 376    let buffer =
 377        cx.add_model(|cx| Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx));
 378    let outline = buffer
 379        .read_with(cx, |buffer, _| buffer.snapshot().outline(None))
 380        .unwrap();
 381
 382    assert_eq!(
 383        outline
 384            .items
 385            .iter()
 386            .map(|item| (item.text.as_str(), item.depth))
 387            .collect::<Vec<_>>(),
 388        &[
 389            ("struct Person", 0),
 390            ("name", 1),
 391            ("age", 1),
 392            ("mod module", 0),
 393            ("enum LoginState", 1),
 394            ("LoggedOut", 2),
 395            ("LoggingOn", 2),
 396            ("LoggedIn", 2),
 397            ("person", 3),
 398            ("time", 3),
 399            ("impl Eq for Person", 0),
 400            ("impl Drop for Person", 0),
 401            ("fn drop", 1),
 402        ]
 403    );
 404
 405    // Without space, we only match on names
 406    assert_eq!(
 407        search(&outline, "oon", cx).await,
 408        &[
 409            ("mod module", vec![]),                    // included as the parent of a match
 410            ("enum LoginState", vec![]),               // included as the parent of a match
 411            ("LoggingOn", vec![1, 7, 8]),              // matches
 412            ("impl Drop for Person", vec![7, 18, 19]), // matches in two disjoint names
 413        ]
 414    );
 415
 416    assert_eq!(
 417        search(&outline, "dp p", cx).await,
 418        &[
 419            ("impl Drop for Person", vec![5, 8, 9, 14]),
 420            ("fn drop", vec![]),
 421        ]
 422    );
 423    assert_eq!(
 424        search(&outline, "dpn", cx).await,
 425        &[("impl Drop for Person", vec![5, 14, 19])]
 426    );
 427    assert_eq!(
 428        search(&outline, "impl ", cx).await,
 429        &[
 430            ("impl Eq for Person", vec![0, 1, 2, 3, 4]),
 431            ("impl Drop for Person", vec![0, 1, 2, 3, 4]),
 432            ("fn drop", vec![]),
 433        ]
 434    );
 435
 436    async fn search<'a>(
 437        outline: &'a Outline<Anchor>,
 438        query: &'a str,
 439        cx: &'a gpui::TestAppContext,
 440    ) -> Vec<(&'a str, Vec<usize>)> {
 441        let matches = cx
 442            .read(|cx| outline.search(query, cx.background().clone()))
 443            .await;
 444        matches
 445            .into_iter()
 446            .map(|mat| (outline.items[mat.candidate_id].text.as_str(), mat.positions))
 447            .collect::<Vec<_>>()
 448    }
 449}
 450
 451#[gpui::test]
 452async fn test_symbols_containing(cx: &mut gpui::TestAppContext) {
 453    let text = r#"
 454        impl Person {
 455            fn one() {
 456                1
 457            }
 458
 459            fn two() {
 460                2
 461            }fn three() {
 462                3
 463            }
 464        }
 465    "#
 466    .unindent();
 467
 468    let buffer =
 469        cx.add_model(|cx| Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx));
 470    let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
 471
 472    // point is at the start of an item
 473    assert_eq!(
 474        symbols_containing(Point::new(1, 4), &snapshot),
 475        vec![
 476            (
 477                "impl Person".to_string(),
 478                Point::new(0, 0)..Point::new(10, 1)
 479            ),
 480            ("fn one".to_string(), Point::new(1, 4)..Point::new(3, 5))
 481        ]
 482    );
 483
 484    // point is in the middle of an item
 485    assert_eq!(
 486        symbols_containing(Point::new(2, 8), &snapshot),
 487        vec![
 488            (
 489                "impl Person".to_string(),
 490                Point::new(0, 0)..Point::new(10, 1)
 491            ),
 492            ("fn one".to_string(), Point::new(1, 4)..Point::new(3, 5))
 493        ]
 494    );
 495
 496    // point is at the end of an item
 497    assert_eq!(
 498        symbols_containing(Point::new(3, 5), &snapshot),
 499        vec![
 500            (
 501                "impl Person".to_string(),
 502                Point::new(0, 0)..Point::new(10, 1)
 503            ),
 504            ("fn one".to_string(), Point::new(1, 4)..Point::new(3, 5))
 505        ]
 506    );
 507
 508    // point is in between two adjacent items
 509    assert_eq!(
 510        symbols_containing(Point::new(7, 5), &snapshot),
 511        vec![
 512            (
 513                "impl Person".to_string(),
 514                Point::new(0, 0)..Point::new(10, 1)
 515            ),
 516            ("fn two".to_string(), Point::new(5, 4)..Point::new(7, 5))
 517        ]
 518    );
 519
 520    fn symbols_containing(
 521        position: Point,
 522        snapshot: &BufferSnapshot,
 523    ) -> Vec<(String, Range<Point>)> {
 524        snapshot
 525            .symbols_containing(position, None)
 526            .unwrap()
 527            .into_iter()
 528            .map(|item| {
 529                (
 530                    item.text,
 531                    item.range.start.to_point(snapshot)..item.range.end.to_point(snapshot),
 532                )
 533            })
 534            .collect()
 535    }
 536}
 537
 538#[gpui::test]
 539fn test_enclosing_bracket_ranges(cx: &mut MutableAppContext) {
 540    cx.set_global(Settings::test(cx));
 541    let buffer = cx.add_model(|cx| {
 542        let text = "
 543            mod x {
 544                mod y {
 545
 546                }
 547            }
 548        "
 549        .unindent();
 550        Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx)
 551    });
 552    let buffer = buffer.read(cx);
 553    assert_eq!(
 554        buffer.enclosing_bracket_point_ranges(Point::new(1, 6)..Point::new(1, 6)),
 555        Some((
 556            Point::new(0, 6)..Point::new(0, 7),
 557            Point::new(4, 0)..Point::new(4, 1)
 558        ))
 559    );
 560    assert_eq!(
 561        buffer.enclosing_bracket_point_ranges(Point::new(1, 10)..Point::new(1, 10)),
 562        Some((
 563            Point::new(1, 10)..Point::new(1, 11),
 564            Point::new(3, 4)..Point::new(3, 5)
 565        ))
 566    );
 567    assert_eq!(
 568        buffer.enclosing_bracket_point_ranges(Point::new(3, 5)..Point::new(3, 5)),
 569        Some((
 570            Point::new(1, 10)..Point::new(1, 11),
 571            Point::new(3, 4)..Point::new(3, 5)
 572        ))
 573    );
 574}
 575
 576#[gpui::test]
 577fn test_range_for_syntax_ancestor(cx: &mut MutableAppContext) {
 578    cx.add_model(|cx| {
 579        let text = "fn a() { b(|c| {}) }";
 580        let buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 581        let snapshot = buffer.snapshot();
 582
 583        assert_eq!(
 584            snapshot.range_for_syntax_ancestor(empty_range_at(text, "|")),
 585            Some(range_of(text, "|"))
 586        );
 587        assert_eq!(
 588            snapshot.range_for_syntax_ancestor(range_of(text, "|")),
 589            Some(range_of(text, "|c|"))
 590        );
 591        assert_eq!(
 592            snapshot.range_for_syntax_ancestor(range_of(text, "|c|")),
 593            Some(range_of(text, "|c| {}"))
 594        );
 595        assert_eq!(
 596            snapshot.range_for_syntax_ancestor(range_of(text, "|c| {}")),
 597            Some(range_of(text, "(|c| {})"))
 598        );
 599
 600        buffer
 601    });
 602
 603    fn empty_range_at(text: &str, part: &str) -> Range<usize> {
 604        let start = text.find(part).unwrap();
 605        start..start
 606    }
 607
 608    fn range_of(text: &str, part: &str) -> Range<usize> {
 609        let start = text.find(part).unwrap();
 610        start..start + part.len()
 611    }
 612}
 613
 614#[gpui::test]
 615fn test_autoindent_with_soft_tabs(cx: &mut MutableAppContext) {
 616    let settings = Settings::test(cx);
 617    cx.set_global(settings);
 618
 619    cx.add_model(|cx| {
 620        let text = "fn a() {}";
 621        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 622
 623        buffer.edit([(8..8, "\n\n")], Some(AutoindentMode::EachLine), cx);
 624        assert_eq!(buffer.text(), "fn a() {\n    \n}");
 625
 626        buffer.edit(
 627            [(Point::new(1, 4)..Point::new(1, 4), "b()\n")],
 628            Some(AutoindentMode::EachLine),
 629            cx,
 630        );
 631        assert_eq!(buffer.text(), "fn a() {\n    b()\n    \n}");
 632
 633        // Create a field expression on a new line, causing that line
 634        // to be indented.
 635        buffer.edit(
 636            [(Point::new(2, 4)..Point::new(2, 4), ".c")],
 637            Some(AutoindentMode::EachLine),
 638            cx,
 639        );
 640        assert_eq!(buffer.text(), "fn a() {\n    b()\n        .c\n}");
 641
 642        // Remove the dot so that the line is no longer a field expression,
 643        // causing the line to be outdented.
 644        buffer.edit(
 645            [(Point::new(2, 8)..Point::new(2, 9), "")],
 646            Some(AutoindentMode::EachLine),
 647            cx,
 648        );
 649        assert_eq!(buffer.text(), "fn a() {\n    b()\n    c\n}");
 650
 651        buffer
 652    });
 653}
 654
 655#[gpui::test]
 656fn test_autoindent_with_hard_tabs(cx: &mut MutableAppContext) {
 657    let mut settings = Settings::test(cx);
 658    settings.editor_overrides.hard_tabs = Some(true);
 659    cx.set_global(settings);
 660
 661    cx.add_model(|cx| {
 662        let text = "fn a() {}";
 663        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 664
 665        buffer.edit([(8..8, "\n\n")], Some(AutoindentMode::EachLine), cx);
 666        assert_eq!(buffer.text(), "fn a() {\n\t\n}");
 667
 668        buffer.edit(
 669            [(Point::new(1, 1)..Point::new(1, 1), "b()\n")],
 670            Some(AutoindentMode::EachLine),
 671            cx,
 672        );
 673        assert_eq!(buffer.text(), "fn a() {\n\tb()\n\t\n}");
 674
 675        // Create a field expression on a new line, causing that line
 676        // to be indented.
 677        buffer.edit(
 678            [(Point::new(2, 1)..Point::new(2, 1), ".c")],
 679            Some(AutoindentMode::EachLine),
 680            cx,
 681        );
 682        assert_eq!(buffer.text(), "fn a() {\n\tb()\n\t\t.c\n}");
 683
 684        // Remove the dot so that the line is no longer a field expression,
 685        // causing the line to be outdented.
 686        buffer.edit(
 687            [(Point::new(2, 2)..Point::new(2, 3), "")],
 688            Some(AutoindentMode::EachLine),
 689            cx,
 690        );
 691        assert_eq!(buffer.text(), "fn a() {\n\tb()\n\tc\n}");
 692
 693        buffer
 694    });
 695}
 696
 697#[gpui::test]
 698fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut MutableAppContext) {
 699    let settings = Settings::test(cx);
 700    cx.set_global(settings);
 701
 702    cx.add_model(|cx| {
 703        let text = "
 704            fn a() {
 705            c;
 706            d;
 707            }
 708        "
 709        .unindent();
 710
 711        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 712
 713        // Lines 2 and 3 don't match the indentation suggestion. When editing these lines,
 714        // their indentation is not adjusted.
 715        buffer.edit(
 716            [
 717                (empty(Point::new(1, 1)), "()"),
 718                (empty(Point::new(2, 1)), "()"),
 719            ],
 720            Some(AutoindentMode::EachLine),
 721            cx,
 722        );
 723        assert_eq!(
 724            buffer.text(),
 725            "
 726            fn a() {
 727            c();
 728            d();
 729            }
 730            "
 731            .unindent()
 732        );
 733
 734        // When appending new content after these lines, the indentation is based on the
 735        // preceding lines' actual indentation.
 736        buffer.edit(
 737            [
 738                (empty(Point::new(1, 1)), "\n.f\n.g"),
 739                (empty(Point::new(2, 1)), "\n.f\n.g"),
 740            ],
 741            Some(AutoindentMode::EachLine),
 742            cx,
 743        );
 744        assert_eq!(
 745            buffer.text(),
 746            "
 747            fn a() {
 748            c
 749                .f
 750                .g();
 751            d
 752                .f
 753                .g();
 754            }
 755            "
 756            .unindent()
 757        );
 758        buffer
 759    });
 760
 761    cx.add_model(|cx| {
 762        let text = "
 763            fn a() {
 764                {
 765                    b()?
 766                }
 767                Ok(())
 768            }
 769        "
 770        .unindent();
 771        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 772
 773        // Delete a closing curly brace changes the suggested indent for the line.
 774        buffer.edit(
 775            [(Point::new(3, 4)..Point::new(3, 5), "")],
 776            Some(AutoindentMode::EachLine),
 777            cx,
 778        );
 779        assert_eq!(
 780            buffer.text(),
 781            "
 782            fn a() {
 783                {
 784                    b()?
 785                        |
 786                Ok(())
 787            }
 788            "
 789            .replace('|', "") // included in the string to preserve trailing whites
 790            .unindent()
 791        );
 792
 793        // Manually editing the leading whitespace
 794        buffer.edit(
 795            [(Point::new(3, 0)..Point::new(3, 12), "")],
 796            Some(AutoindentMode::EachLine),
 797            cx,
 798        );
 799        assert_eq!(
 800            buffer.text(),
 801            "
 802            fn a() {
 803                {
 804                    b()?
 805
 806                Ok(())
 807            }
 808            "
 809            .unindent()
 810        );
 811        buffer
 812    });
 813}
 814
 815#[gpui::test]
 816fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut MutableAppContext) {
 817    cx.set_global(Settings::test(cx));
 818    cx.add_model(|cx| {
 819        let text = "
 820            fn a() {}
 821        "
 822        .unindent();
 823
 824        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 825
 826        buffer.edit([(5..5, "\nb")], Some(AutoindentMode::EachLine), cx);
 827        assert_eq!(
 828            buffer.text(),
 829            "
 830                fn a(
 831                    b) {}
 832            "
 833            .unindent()
 834        );
 835
 836        // The indentation suggestion changed because `@end` node (a close paren)
 837        // is now at the beginning of the line.
 838        buffer.edit(
 839            [(Point::new(1, 4)..Point::new(1, 5), "")],
 840            Some(AutoindentMode::EachLine),
 841            cx,
 842        );
 843        assert_eq!(
 844            buffer.text(),
 845            "
 846                fn a(
 847                ) {}
 848            "
 849            .unindent()
 850        );
 851
 852        buffer
 853    });
 854}
 855
 856#[gpui::test]
 857fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut MutableAppContext) {
 858    cx.set_global(Settings::test(cx));
 859    cx.add_model(|cx| {
 860        let text = "a\nb";
 861        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 862        buffer.edit(
 863            [(0..1, "\n"), (2..3, "\n")],
 864            Some(AutoindentMode::EachLine),
 865            cx,
 866        );
 867        assert_eq!(buffer.text(), "\n\n\n");
 868        buffer
 869    });
 870}
 871
 872#[gpui::test]
 873fn test_autoindent_multi_line_insertion(cx: &mut MutableAppContext) {
 874    cx.set_global(Settings::test(cx));
 875    cx.add_model(|cx| {
 876        let text = "
 877            const a: usize = 1;
 878            fn b() {
 879                if c {
 880                    let d = 2;
 881                }
 882            }
 883        "
 884        .unindent();
 885
 886        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 887        buffer.edit(
 888            [(Point::new(3, 0)..Point::new(3, 0), "e(\n    f()\n);\n")],
 889            Some(AutoindentMode::EachLine),
 890            cx,
 891        );
 892        assert_eq!(
 893            buffer.text(),
 894            "
 895                const a: usize = 1;
 896                fn b() {
 897                    if c {
 898                        e(
 899                            f()
 900                        );
 901                        let d = 2;
 902                    }
 903                }
 904            "
 905            .unindent()
 906        );
 907
 908        buffer
 909    });
 910}
 911
 912#[gpui::test]
 913fn test_autoindent_block_mode(cx: &mut MutableAppContext) {
 914    cx.set_global(Settings::test(cx));
 915    cx.add_model(|cx| {
 916        let text = r#"
 917            fn a() {
 918                b();
 919            }
 920        "#
 921        .unindent();
 922        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 923
 924        let inserted_text = r#"
 925            "
 926              c
 927                d
 928                  e
 929            "
 930        "#
 931        .unindent();
 932
 933        // Insert the block at column zero. The entire block is indented
 934        // so that the first line matches the previous line's indentation.
 935        buffer.edit(
 936            [(Point::new(2, 0)..Point::new(2, 0), inserted_text.clone())],
 937            Some(AutoindentMode::Block {
 938                original_indent_columns: vec![0],
 939            }),
 940            cx,
 941        );
 942        assert_eq!(
 943            buffer.text(),
 944            r#"
 945            fn a() {
 946                b();
 947                "
 948                  c
 949                    d
 950                      e
 951                "
 952            }
 953            "#
 954            .unindent()
 955        );
 956
 957        // Insert the block at a deeper indent level. The entire block is outdented.
 958        buffer.undo(cx);
 959        buffer.edit([(Point::new(2, 0)..Point::new(2, 0), "        ")], None, cx);
 960        buffer.edit(
 961            [(Point::new(2, 8)..Point::new(2, 8), inserted_text)],
 962            Some(AutoindentMode::Block {
 963                original_indent_columns: vec![0],
 964            }),
 965            cx,
 966        );
 967        assert_eq!(
 968            buffer.text(),
 969            r#"
 970            fn a() {
 971                b();
 972                "
 973                  c
 974                    d
 975                      e
 976                "
 977            }
 978            "#
 979            .unindent()
 980        );
 981
 982        buffer
 983    });
 984}
 985
 986#[gpui::test]
 987fn test_autoindent_language_without_indents_query(cx: &mut MutableAppContext) {
 988    cx.set_global(Settings::test(cx));
 989    cx.add_model(|cx| {
 990        let text = "
 991            * one
 992                - a
 993                - b
 994            * two
 995        "
 996        .unindent();
 997
 998        let mut buffer = Buffer::new(0, text, cx).with_language(
 999            Arc::new(Language::new(
1000                LanguageConfig {
1001                    name: "Markdown".into(),
1002                    ..Default::default()
1003                },
1004                Some(tree_sitter_json::language()),
1005            )),
1006            cx,
1007        );
1008        buffer.edit(
1009            [(Point::new(3, 0)..Point::new(3, 0), "\n")],
1010            Some(AutoindentMode::EachLine),
1011            cx,
1012        );
1013        assert_eq!(
1014            buffer.text(),
1015            "
1016            * one
1017                - a
1018                - b
1019
1020            * two
1021            "
1022            .unindent()
1023        );
1024        buffer
1025    });
1026}
1027
1028#[gpui::test]
1029fn test_serialization(cx: &mut gpui::MutableAppContext) {
1030    let mut now = Instant::now();
1031
1032    let buffer1 = cx.add_model(|cx| {
1033        let mut buffer = Buffer::new(0, "abc", cx);
1034        buffer.edit([(3..3, "D")], None, cx);
1035
1036        now += Duration::from_secs(1);
1037        buffer.start_transaction_at(now);
1038        buffer.edit([(4..4, "E")], None, cx);
1039        buffer.end_transaction_at(now, cx);
1040        assert_eq!(buffer.text(), "abcDE");
1041
1042        buffer.undo(cx);
1043        assert_eq!(buffer.text(), "abcD");
1044
1045        buffer.edit([(4..4, "F")], None, cx);
1046        assert_eq!(buffer.text(), "abcDF");
1047        buffer
1048    });
1049    assert_eq!(buffer1.read(cx).text(), "abcDF");
1050
1051    let state = buffer1.read(cx).to_proto();
1052    let ops = cx.background().block(buffer1.read(cx).serialize_ops(cx));
1053    let buffer2 = cx.add_model(|cx| {
1054        let mut buffer = Buffer::from_proto(1, state, None).unwrap();
1055        buffer
1056            .apply_ops(
1057                ops.into_iter()
1058                    .map(|op| proto::deserialize_operation(op).unwrap()),
1059                cx,
1060            )
1061            .unwrap();
1062        buffer
1063    });
1064    assert_eq!(buffer2.read(cx).text(), "abcDF");
1065}
1066
1067#[gpui::test(iterations = 100)]
1068fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
1069    let min_peers = env::var("MIN_PEERS")
1070        .map(|i| i.parse().expect("invalid `MIN_PEERS` variable"))
1071        .unwrap_or(1);
1072    let max_peers = env::var("MAX_PEERS")
1073        .map(|i| i.parse().expect("invalid `MAX_PEERS` variable"))
1074        .unwrap_or(5);
1075    let operations = env::var("OPERATIONS")
1076        .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
1077        .unwrap_or(10);
1078
1079    let base_text_len = rng.gen_range(0..10);
1080    let base_text = RandomCharIter::new(&mut rng)
1081        .take(base_text_len)
1082        .collect::<String>();
1083    let mut replica_ids = Vec::new();
1084    let mut buffers = Vec::new();
1085    let network = Rc::new(RefCell::new(Network::new(rng.clone())));
1086    let base_buffer = cx.add_model(|cx| Buffer::new(0, base_text.as_str(), cx));
1087
1088    for i in 0..rng.gen_range(min_peers..=max_peers) {
1089        let buffer = cx.add_model(|cx| {
1090            let state = base_buffer.read(cx).to_proto();
1091            let ops = cx
1092                .background()
1093                .block(base_buffer.read(cx).serialize_ops(cx));
1094            let mut buffer = Buffer::from_proto(i as ReplicaId, state, None).unwrap();
1095            buffer
1096                .apply_ops(
1097                    ops.into_iter()
1098                        .map(|op| proto::deserialize_operation(op).unwrap()),
1099                    cx,
1100                )
1101                .unwrap();
1102            buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
1103            let network = network.clone();
1104            cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
1105                if let Event::Operation(op) = event {
1106                    network
1107                        .borrow_mut()
1108                        .broadcast(buffer.replica_id(), vec![proto::serialize_operation(op)]);
1109                }
1110            })
1111            .detach();
1112            buffer
1113        });
1114        buffers.push(buffer);
1115        replica_ids.push(i as ReplicaId);
1116        network.borrow_mut().add_peer(i as ReplicaId);
1117        log::info!("Adding initial peer with replica id {}", i);
1118    }
1119
1120    log::info!("initial text: {:?}", base_text);
1121
1122    let mut now = Instant::now();
1123    let mut mutation_count = operations;
1124    let mut next_diagnostic_id = 0;
1125    let mut active_selections = BTreeMap::default();
1126    loop {
1127        let replica_index = rng.gen_range(0..replica_ids.len());
1128        let replica_id = replica_ids[replica_index];
1129        let buffer = &mut buffers[replica_index];
1130        let mut new_buffer = None;
1131        match rng.gen_range(0..100) {
1132            0..=29 if mutation_count != 0 => {
1133                buffer.update(cx, |buffer, cx| {
1134                    buffer.start_transaction_at(now);
1135                    buffer.randomly_edit(&mut rng, 5, cx);
1136                    buffer.end_transaction_at(now, cx);
1137                    log::info!("buffer {} text: {:?}", buffer.replica_id(), buffer.text());
1138                });
1139                mutation_count -= 1;
1140            }
1141            30..=39 if mutation_count != 0 => {
1142                buffer.update(cx, |buffer, cx| {
1143                    let mut selections = Vec::new();
1144                    for id in 0..rng.gen_range(1..=5) {
1145                        let range = buffer.random_byte_range(0, &mut rng);
1146                        selections.push(Selection {
1147                            id,
1148                            start: buffer.anchor_before(range.start),
1149                            end: buffer.anchor_before(range.end),
1150                            reversed: false,
1151                            goal: SelectionGoal::None,
1152                        });
1153                    }
1154                    let selections: Arc<[Selection<Anchor>]> = selections.into();
1155                    log::info!(
1156                        "peer {} setting active selections: {:?}",
1157                        replica_id,
1158                        selections
1159                    );
1160                    active_selections.insert(replica_id, selections.clone());
1161                    buffer.set_active_selections(selections, false, cx);
1162                });
1163                mutation_count -= 1;
1164            }
1165            40..=49 if mutation_count != 0 && replica_id == 0 => {
1166                let entry_count = rng.gen_range(1..=5);
1167                buffer.update(cx, |buffer, cx| {
1168                    let diagnostics = DiagnosticSet::new(
1169                        (0..entry_count).map(|_| {
1170                            let range = buffer.random_byte_range(0, &mut rng);
1171                            let range = range.to_point_utf16(buffer);
1172                            DiagnosticEntry {
1173                                range,
1174                                diagnostic: Diagnostic {
1175                                    message: post_inc(&mut next_diagnostic_id).to_string(),
1176                                    ..Default::default()
1177                                },
1178                            }
1179                        }),
1180                        buffer,
1181                    );
1182                    log::info!("peer {} setting diagnostics: {:?}", replica_id, diagnostics);
1183                    buffer.update_diagnostics(diagnostics, cx);
1184                });
1185                mutation_count -= 1;
1186            }
1187            50..=59 if replica_ids.len() < max_peers => {
1188                let old_buffer_state = buffer.read(cx).to_proto();
1189                let old_buffer_ops = cx.background().block(buffer.read(cx).serialize_ops(cx));
1190                let new_replica_id = (0..=replica_ids.len() as ReplicaId)
1191                    .filter(|replica_id| *replica_id != buffer.read(cx).replica_id())
1192                    .choose(&mut rng)
1193                    .unwrap();
1194                log::info!(
1195                    "Adding new replica {} (replicating from {})",
1196                    new_replica_id,
1197                    replica_id
1198                );
1199                new_buffer = Some(cx.add_model(|cx| {
1200                    let mut new_buffer =
1201                        Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap();
1202                    new_buffer
1203                        .apply_ops(
1204                            old_buffer_ops
1205                                .into_iter()
1206                                .map(|op| deserialize_operation(op).unwrap()),
1207                            cx,
1208                        )
1209                        .unwrap();
1210                    log::info!(
1211                        "New replica {} text: {:?}",
1212                        new_buffer.replica_id(),
1213                        new_buffer.text()
1214                    );
1215                    new_buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
1216                    let network = network.clone();
1217                    cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
1218                        if let Event::Operation(op) = event {
1219                            network.borrow_mut().broadcast(
1220                                buffer.replica_id(),
1221                                vec![proto::serialize_operation(op)],
1222                            );
1223                        }
1224                    })
1225                    .detach();
1226                    new_buffer
1227                }));
1228                network.borrow_mut().replicate(replica_id, new_replica_id);
1229
1230                if new_replica_id as usize == replica_ids.len() {
1231                    replica_ids.push(new_replica_id);
1232                } else {
1233                    let new_buffer = new_buffer.take().unwrap();
1234                    while network.borrow().has_unreceived(new_replica_id) {
1235                        let ops = network
1236                            .borrow_mut()
1237                            .receive(new_replica_id)
1238                            .into_iter()
1239                            .map(|op| proto::deserialize_operation(op).unwrap());
1240                        if ops.len() > 0 {
1241                            log::info!(
1242                                "peer {} (version: {:?}) applying {} ops from the network. {:?}",
1243                                new_replica_id,
1244                                buffer.read(cx).version(),
1245                                ops.len(),
1246                                ops
1247                            );
1248                            new_buffer.update(cx, |new_buffer, cx| {
1249                                new_buffer.apply_ops(ops, cx).unwrap();
1250                            });
1251                        }
1252                    }
1253                    buffers[new_replica_id as usize] = new_buffer;
1254                }
1255            }
1256            60..=69 if mutation_count != 0 => {
1257                buffer.update(cx, |buffer, cx| {
1258                    buffer.randomly_undo_redo(&mut rng, cx);
1259                    log::info!("buffer {} text: {:?}", buffer.replica_id(), buffer.text());
1260                });
1261                mutation_count -= 1;
1262            }
1263            _ if network.borrow().has_unreceived(replica_id) => {
1264                let ops = network
1265                    .borrow_mut()
1266                    .receive(replica_id)
1267                    .into_iter()
1268                    .map(|op| proto::deserialize_operation(op).unwrap());
1269                if ops.len() > 0 {
1270                    log::info!(
1271                        "peer {} (version: {:?}) applying {} ops from the network. {:?}",
1272                        replica_id,
1273                        buffer.read(cx).version(),
1274                        ops.len(),
1275                        ops
1276                    );
1277                    buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx).unwrap());
1278                }
1279            }
1280            _ => {}
1281        }
1282
1283        now += Duration::from_millis(rng.gen_range(0..=200));
1284        buffers.extend(new_buffer);
1285
1286        for buffer in &buffers {
1287            buffer.read(cx).check_invariants();
1288        }
1289
1290        if mutation_count == 0 && network.borrow().is_idle() {
1291            break;
1292        }
1293    }
1294
1295    let first_buffer = buffers[0].read(cx).snapshot();
1296    for buffer in &buffers[1..] {
1297        let buffer = buffer.read(cx).snapshot();
1298        assert_eq!(
1299            buffer.version(),
1300            first_buffer.version(),
1301            "Replica {} version != Replica 0 version",
1302            buffer.replica_id()
1303        );
1304        assert_eq!(
1305            buffer.text(),
1306            first_buffer.text(),
1307            "Replica {} text != Replica 0 text",
1308            buffer.replica_id()
1309        );
1310        assert_eq!(
1311            buffer
1312                .diagnostics_in_range::<_, usize>(0..buffer.len(), false)
1313                .collect::<Vec<_>>(),
1314            first_buffer
1315                .diagnostics_in_range::<_, usize>(0..first_buffer.len(), false)
1316                .collect::<Vec<_>>(),
1317            "Replica {} diagnostics != Replica 0 diagnostics",
1318            buffer.replica_id()
1319        );
1320    }
1321
1322    for buffer in &buffers {
1323        let buffer = buffer.read(cx).snapshot();
1324        let actual_remote_selections = buffer
1325            .remote_selections_in_range(Anchor::MIN..Anchor::MAX)
1326            .map(|(replica_id, _, selections)| (replica_id, selections.collect::<Vec<_>>()))
1327            .collect::<Vec<_>>();
1328        let expected_remote_selections = active_selections
1329            .iter()
1330            .filter(|(replica_id, _)| **replica_id != buffer.replica_id())
1331            .map(|(replica_id, selections)| (*replica_id, selections.iter().collect::<Vec<_>>()))
1332            .collect::<Vec<_>>();
1333        assert_eq!(
1334            actual_remote_selections,
1335            expected_remote_selections,
1336            "Replica {} remote selections != expected selections",
1337            buffer.replica_id()
1338        );
1339    }
1340}
1341
1342#[test]
1343fn test_contiguous_ranges() {
1344    assert_eq!(
1345        contiguous_ranges([1, 2, 3, 5, 6, 9, 10, 11, 12].into_iter(), 100).collect::<Vec<_>>(),
1346        &[1..4, 5..7, 9..13]
1347    );
1348
1349    // Respects the `max_len` parameter
1350    assert_eq!(
1351        contiguous_ranges(
1352            [2, 3, 4, 5, 6, 7, 8, 9, 23, 24, 25, 26, 30, 31].into_iter(),
1353            3
1354        )
1355        .collect::<Vec<_>>(),
1356        &[2..5, 5..8, 8..10, 23..26, 26..27, 30..32],
1357    );
1358}
1359
1360impl Buffer {
1361    pub fn enclosing_bracket_point_ranges<T: ToOffset>(
1362        &self,
1363        range: Range<T>,
1364    ) -> Option<(Range<Point>, Range<Point>)> {
1365        self.snapshot()
1366            .enclosing_bracket_ranges(range)
1367            .map(|(start, end)| {
1368                let point_start = start.start.to_point(self)..start.end.to_point(self);
1369                let point_end = end.start.to_point(self)..end.end.to_point(self);
1370                (point_start, point_end)
1371            })
1372    }
1373}
1374
1375fn rust_lang() -> Language {
1376    Language::new(
1377        LanguageConfig {
1378            name: "Rust".into(),
1379            path_suffixes: vec!["rs".to_string()],
1380            ..Default::default()
1381        },
1382        Some(tree_sitter_rust::language()),
1383    )
1384    .with_indents_query(
1385        r#"
1386        (call_expression) @indent
1387        (field_expression) @indent
1388        (_ "(" ")" @end) @indent
1389        (_ "{" "}" @end) @indent
1390        "#,
1391    )
1392    .unwrap()
1393    .with_brackets_query(
1394        r#"
1395        ("{" @open "}" @close)
1396        "#,
1397    )
1398    .unwrap()
1399    .with_outline_query(
1400        r#"
1401        (struct_item
1402            "struct" @context
1403            name: (_) @name) @item
1404        (enum_item
1405            "enum" @context
1406            name: (_) @name) @item
1407        (enum_variant
1408            name: (_) @name) @item
1409        (field_declaration
1410            name: (_) @name) @item
1411        (impl_item
1412            "impl" @context
1413            trait: (_)? @name
1414            "for"? @context
1415            type: (_) @name) @item
1416        (function_item
1417            "fn" @context
1418            name: (_) @name) @item
1419        (mod_item
1420            "mod" @context
1421            name: (_) @name) @item
1422        "#,
1423    )
1424    .unwrap()
1425}
1426
1427fn json_lang() -> Language {
1428    Language::new(
1429        LanguageConfig {
1430            name: "Json".into(),
1431            path_suffixes: vec!["js".to_string()],
1432            ..Default::default()
1433        },
1434        Some(tree_sitter_json::language()),
1435    )
1436}
1437
1438fn get_tree_sexp(buffer: &ModelHandle<Buffer>, cx: &gpui::TestAppContext) -> String {
1439    buffer.read_with(cx, |buffer, _| {
1440        buffer.syntax_tree().unwrap().root_node().to_sexp()
1441    })
1442}
1443
1444fn empty(point: Point) -> Range<Point> {
1445    point..point
1446}