buffer_tests.rs

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