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_symbols_containing(cx: &mut gpui::TestAppContext) {
 460    let text = r#"
 461        impl Person {
 462            fn one() {
 463                1
 464            }
 465
 466            fn two() {
 467                2
 468            }fn three() {
 469                3
 470            }
 471        }
 472    "#
 473    .unindent();
 474
 475    let buffer =
 476        cx.add_model(|cx| Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx));
 477    let snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
 478
 479    // point is at the start of an item
 480    assert_eq!(
 481        symbols_containing(Point::new(1, 4), &snapshot),
 482        vec![
 483            (
 484                "impl Person".to_string(),
 485                Point::new(0, 0)..Point::new(10, 1)
 486            ),
 487            ("fn one".to_string(), Point::new(1, 4)..Point::new(3, 5))
 488        ]
 489    );
 490
 491    // point is in the middle of an item
 492    assert_eq!(
 493        symbols_containing(Point::new(2, 8), &snapshot),
 494        vec![
 495            (
 496                "impl Person".to_string(),
 497                Point::new(0, 0)..Point::new(10, 1)
 498            ),
 499            ("fn one".to_string(), Point::new(1, 4)..Point::new(3, 5))
 500        ]
 501    );
 502
 503    // point is at the end of an item
 504    assert_eq!(
 505        symbols_containing(Point::new(3, 5), &snapshot),
 506        vec![
 507            (
 508                "impl Person".to_string(),
 509                Point::new(0, 0)..Point::new(10, 1)
 510            ),
 511            ("fn one".to_string(), Point::new(1, 4)..Point::new(3, 5))
 512        ]
 513    );
 514
 515    // point is in between two adjacent items
 516    assert_eq!(
 517        symbols_containing(Point::new(7, 5), &snapshot),
 518        vec![
 519            (
 520                "impl Person".to_string(),
 521                Point::new(0, 0)..Point::new(10, 1)
 522            ),
 523            ("fn two".to_string(), Point::new(5, 4)..Point::new(7, 5))
 524        ]
 525    );
 526
 527    fn symbols_containing(
 528        position: Point,
 529        snapshot: &BufferSnapshot,
 530    ) -> Vec<(String, Range<Point>)> {
 531        snapshot
 532            .symbols_containing(position, None)
 533            .unwrap()
 534            .into_iter()
 535            .map(|item| {
 536                (
 537                    item.text,
 538                    item.range.start.to_point(snapshot)..item.range.end.to_point(snapshot),
 539                )
 540            })
 541            .collect()
 542    }
 543}
 544
 545#[gpui::test]
 546fn test_enclosing_bracket_ranges(cx: &mut MutableAppContext) {
 547    cx.set_global(Settings::test(cx));
 548    let buffer = cx.add_model(|cx| {
 549        let text = "
 550            mod x {
 551                mod y {
 552
 553                }
 554            }
 555        "
 556        .unindent();
 557        Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx)
 558    });
 559    let buffer = buffer.read(cx);
 560    assert_eq!(
 561        buffer.enclosing_bracket_point_ranges(Point::new(1, 6)..Point::new(1, 6)),
 562        Some((
 563            Point::new(0, 6)..Point::new(0, 7),
 564            Point::new(4, 0)..Point::new(4, 1)
 565        ))
 566    );
 567    assert_eq!(
 568        buffer.enclosing_bracket_point_ranges(Point::new(1, 10)..Point::new(1, 10)),
 569        Some((
 570            Point::new(1, 10)..Point::new(1, 11),
 571            Point::new(3, 4)..Point::new(3, 5)
 572        ))
 573    );
 574    assert_eq!(
 575        buffer.enclosing_bracket_point_ranges(Point::new(3, 5)..Point::new(3, 5)),
 576        Some((
 577            Point::new(1, 10)..Point::new(1, 11),
 578            Point::new(3, 4)..Point::new(3, 5)
 579        ))
 580    );
 581
 582    assert_eq!(
 583        buffer.enclosing_bracket_point_ranges(Point::new(4, 1)..Point::new(4, 1)),
 584        Some((
 585            Point::new(0, 6)..Point::new(0, 7),
 586            Point::new(4, 0)..Point::new(4, 1)
 587        ))
 588    );
 589
 590    // Regression test: avoid crash when querying at the end of the buffer.
 591    assert_eq!(
 592        buffer.enclosing_bracket_point_ranges(Point::new(4, 1)..Point::new(5, 0)),
 593        None
 594    );
 595}
 596
 597#[gpui::test]
 598fn test_enclosing_bracket_ranges_where_brackets_are_not_outermost_children(
 599    cx: &mut MutableAppContext,
 600) {
 601    let javascript_language = Arc::new(
 602        Language::new(
 603            LanguageConfig {
 604                name: "JavaScript".into(),
 605                ..Default::default()
 606            },
 607            Some(tree_sitter_javascript::language()),
 608        )
 609        .with_brackets_query(
 610            r#"
 611            ("{" @open "}" @close)
 612            ("(" @open ")" @close)
 613            "#,
 614        )
 615        .unwrap(),
 616    );
 617
 618    cx.set_global(Settings::test(cx));
 619    let buffer = cx.add_model(|cx| {
 620        let text = "
 621            for (const a in b) {
 622                // a comment that's longer than the for-loop header
 623            }
 624        "
 625        .unindent();
 626        Buffer::new(0, text, cx).with_language(javascript_language, cx)
 627    });
 628
 629    let buffer = buffer.read(cx);
 630    assert_eq!(
 631        buffer.enclosing_bracket_point_ranges(Point::new(0, 18)..Point::new(0, 18)),
 632        Some((
 633            Point::new(0, 4)..Point::new(0, 5),
 634            Point::new(0, 17)..Point::new(0, 18)
 635        ))
 636    );
 637
 638    // Regression test: even though the parent node of the parentheses (the for loop) does
 639    // intersect the given range, the parentheses themselves do not contain the range, so
 640    // they should not be returned. Only the curly braces contain the range.
 641    assert_eq!(
 642        buffer.enclosing_bracket_point_ranges(Point::new(0, 20)..Point::new(0, 20)),
 643        Some((
 644            Point::new(0, 19)..Point::new(0, 20),
 645            Point::new(2, 0)..Point::new(2, 1)
 646        ))
 647    );
 648}
 649
 650#[gpui::test]
 651fn test_range_for_syntax_ancestor(cx: &mut MutableAppContext) {
 652    cx.add_model(|cx| {
 653        let text = "fn a() { b(|c| {}) }";
 654        let buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 655        let snapshot = buffer.snapshot();
 656
 657        assert_eq!(
 658            snapshot.range_for_syntax_ancestor(empty_range_at(text, "|")),
 659            Some(range_of(text, "|"))
 660        );
 661        assert_eq!(
 662            snapshot.range_for_syntax_ancestor(range_of(text, "|")),
 663            Some(range_of(text, "|c|"))
 664        );
 665        assert_eq!(
 666            snapshot.range_for_syntax_ancestor(range_of(text, "|c|")),
 667            Some(range_of(text, "|c| {}"))
 668        );
 669        assert_eq!(
 670            snapshot.range_for_syntax_ancestor(range_of(text, "|c| {}")),
 671            Some(range_of(text, "(|c| {})"))
 672        );
 673
 674        buffer
 675    });
 676
 677    fn empty_range_at(text: &str, part: &str) -> Range<usize> {
 678        let start = text.find(part).unwrap();
 679        start..start
 680    }
 681
 682    fn range_of(text: &str, part: &str) -> Range<usize> {
 683        let start = text.find(part).unwrap();
 684        start..start + part.len()
 685    }
 686}
 687
 688#[gpui::test]
 689fn test_autoindent_with_soft_tabs(cx: &mut MutableAppContext) {
 690    let settings = Settings::test(cx);
 691    cx.set_global(settings);
 692
 693    cx.add_model(|cx| {
 694        let text = "fn a() {}";
 695        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 696
 697        buffer.edit([(8..8, "\n\n")], Some(AutoindentMode::EachLine), cx);
 698        assert_eq!(buffer.text(), "fn a() {\n    \n}");
 699
 700        buffer.edit(
 701            [(Point::new(1, 4)..Point::new(1, 4), "b()\n")],
 702            Some(AutoindentMode::EachLine),
 703            cx,
 704        );
 705        assert_eq!(buffer.text(), "fn a() {\n    b()\n    \n}");
 706
 707        // Create a field expression on a new line, causing that line
 708        // to be indented.
 709        buffer.edit(
 710            [(Point::new(2, 4)..Point::new(2, 4), ".c")],
 711            Some(AutoindentMode::EachLine),
 712            cx,
 713        );
 714        assert_eq!(buffer.text(), "fn a() {\n    b()\n        .c\n}");
 715
 716        // Remove the dot so that the line is no longer a field expression,
 717        // causing the line to be outdented.
 718        buffer.edit(
 719            [(Point::new(2, 8)..Point::new(2, 9), "")],
 720            Some(AutoindentMode::EachLine),
 721            cx,
 722        );
 723        assert_eq!(buffer.text(), "fn a() {\n    b()\n    c\n}");
 724
 725        buffer
 726    });
 727}
 728
 729#[gpui::test]
 730fn test_autoindent_with_hard_tabs(cx: &mut MutableAppContext) {
 731    let mut settings = Settings::test(cx);
 732    settings.editor_overrides.hard_tabs = Some(true);
 733    cx.set_global(settings);
 734
 735    cx.add_model(|cx| {
 736        let text = "fn a() {}";
 737        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 738
 739        buffer.edit([(8..8, "\n\n")], Some(AutoindentMode::EachLine), cx);
 740        assert_eq!(buffer.text(), "fn a() {\n\t\n}");
 741
 742        buffer.edit(
 743            [(Point::new(1, 1)..Point::new(1, 1), "b()\n")],
 744            Some(AutoindentMode::EachLine),
 745            cx,
 746        );
 747        assert_eq!(buffer.text(), "fn a() {\n\tb()\n\t\n}");
 748
 749        // Create a field expression on a new line, causing that line
 750        // to be indented.
 751        buffer.edit(
 752            [(Point::new(2, 1)..Point::new(2, 1), ".c")],
 753            Some(AutoindentMode::EachLine),
 754            cx,
 755        );
 756        assert_eq!(buffer.text(), "fn a() {\n\tb()\n\t\t.c\n}");
 757
 758        // Remove the dot so that the line is no longer a field expression,
 759        // causing the line to be outdented.
 760        buffer.edit(
 761            [(Point::new(2, 2)..Point::new(2, 3), "")],
 762            Some(AutoindentMode::EachLine),
 763            cx,
 764        );
 765        assert_eq!(buffer.text(), "fn a() {\n\tb()\n\tc\n}");
 766
 767        buffer
 768    });
 769}
 770
 771#[gpui::test]
 772fn test_autoindent_does_not_adjust_lines_with_unchanged_suggestion(cx: &mut MutableAppContext) {
 773    let settings = Settings::test(cx);
 774    cx.set_global(settings);
 775
 776    cx.add_model(|cx| {
 777        let text = "
 778            fn a() {
 779            c;
 780            d;
 781            }
 782        "
 783        .unindent();
 784
 785        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 786
 787        // Lines 2 and 3 don't match the indentation suggestion. When editing these lines,
 788        // their indentation is not adjusted.
 789        buffer.edit(
 790            [
 791                (empty(Point::new(1, 1)), "()"),
 792                (empty(Point::new(2, 1)), "()"),
 793            ],
 794            Some(AutoindentMode::EachLine),
 795            cx,
 796        );
 797        assert_eq!(
 798            buffer.text(),
 799            "
 800            fn a() {
 801            c();
 802            d();
 803            }
 804            "
 805            .unindent()
 806        );
 807
 808        // When appending new content after these lines, the indentation is based on the
 809        // preceding lines' actual indentation.
 810        buffer.edit(
 811            [
 812                (empty(Point::new(1, 1)), "\n.f\n.g"),
 813                (empty(Point::new(2, 1)), "\n.f\n.g"),
 814            ],
 815            Some(AutoindentMode::EachLine),
 816            cx,
 817        );
 818        assert_eq!(
 819            buffer.text(),
 820            "
 821            fn a() {
 822            c
 823                .f
 824                .g();
 825            d
 826                .f
 827                .g();
 828            }
 829            "
 830            .unindent()
 831        );
 832        buffer
 833    });
 834
 835    cx.add_model(|cx| {
 836        let text = "
 837            fn a() {
 838                {
 839                    b()?
 840                }
 841                Ok(())
 842            }
 843        "
 844        .unindent();
 845        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 846
 847        // Delete a closing curly brace changes the suggested indent for the line.
 848        buffer.edit(
 849            [(Point::new(3, 4)..Point::new(3, 5), "")],
 850            Some(AutoindentMode::EachLine),
 851            cx,
 852        );
 853        assert_eq!(
 854            buffer.text(),
 855            "
 856            fn a() {
 857                {
 858                    b()?
 859                        |
 860                Ok(())
 861            }
 862            "
 863            .replace('|', "") // included in the string to preserve trailing whites
 864            .unindent()
 865        );
 866
 867        // Manually editing the leading whitespace
 868        buffer.edit(
 869            [(Point::new(3, 0)..Point::new(3, 12), "")],
 870            Some(AutoindentMode::EachLine),
 871            cx,
 872        );
 873        assert_eq!(
 874            buffer.text(),
 875            "
 876            fn a() {
 877                {
 878                    b()?
 879
 880                Ok(())
 881            }
 882            "
 883            .unindent()
 884        );
 885        buffer
 886    });
 887}
 888
 889#[gpui::test]
 890fn test_autoindent_adjusts_lines_when_only_text_changes(cx: &mut MutableAppContext) {
 891    cx.set_global(Settings::test(cx));
 892    cx.add_model(|cx| {
 893        let text = "
 894            fn a() {}
 895        "
 896        .unindent();
 897
 898        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 899
 900        buffer.edit([(5..5, "\nb")], Some(AutoindentMode::EachLine), cx);
 901        assert_eq!(
 902            buffer.text(),
 903            "
 904                fn a(
 905                    b) {}
 906            "
 907            .unindent()
 908        );
 909
 910        // The indentation suggestion changed because `@end` node (a close paren)
 911        // is now at the beginning of the line.
 912        buffer.edit(
 913            [(Point::new(1, 4)..Point::new(1, 5), "")],
 914            Some(AutoindentMode::EachLine),
 915            cx,
 916        );
 917        assert_eq!(
 918            buffer.text(),
 919            "
 920                fn a(
 921                ) {}
 922            "
 923            .unindent()
 924        );
 925
 926        buffer
 927    });
 928}
 929
 930#[gpui::test]
 931fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut MutableAppContext) {
 932    cx.set_global(Settings::test(cx));
 933    cx.add_model(|cx| {
 934        let text = "a\nb";
 935        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 936        buffer.edit(
 937            [(0..1, "\n"), (2..3, "\n")],
 938            Some(AutoindentMode::EachLine),
 939            cx,
 940        );
 941        assert_eq!(buffer.text(), "\n\n\n");
 942        buffer
 943    });
 944}
 945
 946#[gpui::test]
 947fn test_autoindent_multi_line_insertion(cx: &mut MutableAppContext) {
 948    cx.set_global(Settings::test(cx));
 949    cx.add_model(|cx| {
 950        let text = "
 951            const a: usize = 1;
 952            fn b() {
 953                if c {
 954                    let d = 2;
 955                }
 956            }
 957        "
 958        .unindent();
 959
 960        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 961        buffer.edit(
 962            [(Point::new(3, 0)..Point::new(3, 0), "e(\n    f()\n);\n")],
 963            Some(AutoindentMode::EachLine),
 964            cx,
 965        );
 966        assert_eq!(
 967            buffer.text(),
 968            "
 969                const a: usize = 1;
 970                fn b() {
 971                    if c {
 972                        e(
 973                            f()
 974                        );
 975                        let d = 2;
 976                    }
 977                }
 978            "
 979            .unindent()
 980        );
 981
 982        buffer
 983    });
 984}
 985
 986#[gpui::test]
 987fn test_autoindent_block_mode(cx: &mut MutableAppContext) {
 988    cx.set_global(Settings::test(cx));
 989    cx.add_model(|cx| {
 990        let text = r#"
 991            fn a() {
 992                b();
 993            }
 994        "#
 995        .unindent();
 996        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
 997
 998        // When this text was copied, both of the quotation marks were at the same
 999        // indent level, but the indentation of the first line was not included in
1000        // the copied text. This information is retained in the
1001        // 'original_indent_columns' vector.
1002        let original_indent_columns = vec![4];
1003        let inserted_text = r#"
1004            "
1005                  c
1006                    d
1007                      e
1008                "
1009        "#
1010        .unindent();
1011
1012        // Insert the block at column zero. The entire block is indented
1013        // so that the first line matches the previous line's indentation.
1014        buffer.edit(
1015            [(Point::new(2, 0)..Point::new(2, 0), inserted_text.clone())],
1016            Some(AutoindentMode::Block {
1017                original_indent_columns: original_indent_columns.clone(),
1018            }),
1019            cx,
1020        );
1021        assert_eq!(
1022            buffer.text(),
1023            r#"
1024            fn a() {
1025                b();
1026                "
1027                  c
1028                    d
1029                      e
1030                "
1031            }
1032            "#
1033            .unindent()
1034        );
1035
1036        // Grouping is disabled in tests, so we need 2 undos
1037        buffer.undo(cx); // Undo the auto-indent
1038        buffer.undo(cx); // Undo the original edit
1039
1040        // Insert the block at a deeper indent level. The entire block is outdented.
1041        buffer.edit([(Point::new(2, 0)..Point::new(2, 0), "        ")], None, cx);
1042        buffer.edit(
1043            [(Point::new(2, 8)..Point::new(2, 8), inserted_text)],
1044            Some(AutoindentMode::Block {
1045                original_indent_columns: original_indent_columns.clone(),
1046            }),
1047            cx,
1048        );
1049        assert_eq!(
1050            buffer.text(),
1051            r#"
1052            fn a() {
1053                b();
1054                "
1055                  c
1056                    d
1057                      e
1058                "
1059            }
1060            "#
1061            .unindent()
1062        );
1063
1064        buffer
1065    });
1066}
1067
1068#[gpui::test]
1069fn test_autoindent_block_mode_without_original_indent_columns(cx: &mut MutableAppContext) {
1070    cx.set_global(Settings::test(cx));
1071    cx.add_model(|cx| {
1072        let text = r#"
1073            fn a() {
1074                if b() {
1075
1076                }
1077            }
1078        "#
1079        .unindent();
1080        let mut buffer = Buffer::new(0, text, cx).with_language(Arc::new(rust_lang()), cx);
1081
1082        // The original indent columns are not known, so this text is
1083        // auto-indented in a block as if the first line was copied in
1084        // its entirety.
1085        let original_indent_columns = Vec::new();
1086        let inserted_text = "    c\n        .d()\n        .e();";
1087
1088        // Insert the block at column zero. The entire block is indented
1089        // so that the first line matches the previous line's indentation.
1090        buffer.edit(
1091            [(Point::new(2, 0)..Point::new(2, 0), inserted_text.clone())],
1092            Some(AutoindentMode::Block {
1093                original_indent_columns: original_indent_columns.clone(),
1094            }),
1095            cx,
1096        );
1097        assert_eq!(
1098            buffer.text(),
1099            r#"
1100            fn a() {
1101                if b() {
1102                    c
1103                        .d()
1104                        .e();
1105                }
1106            }
1107            "#
1108            .unindent()
1109        );
1110
1111        // Grouping is disabled in tests, so we need 2 undos
1112        buffer.undo(cx); // Undo the auto-indent
1113        buffer.undo(cx); // Undo the original edit
1114
1115        // Insert the block at a deeper indent level. The entire block is outdented.
1116        buffer.edit(
1117            [(Point::new(2, 0)..Point::new(2, 0), " ".repeat(12))],
1118            None,
1119            cx,
1120        );
1121        buffer.edit(
1122            [(Point::new(2, 12)..Point::new(2, 12), inserted_text)],
1123            Some(AutoindentMode::Block {
1124                original_indent_columns: Vec::new(),
1125            }),
1126            cx,
1127        );
1128        assert_eq!(
1129            buffer.text(),
1130            r#"
1131            fn a() {
1132                if b() {
1133                    c
1134                        .d()
1135                        .e();
1136                }
1137            }
1138            "#
1139            .unindent()
1140        );
1141
1142        buffer
1143    });
1144}
1145
1146#[gpui::test]
1147fn test_autoindent_language_without_indents_query(cx: &mut MutableAppContext) {
1148    cx.set_global(Settings::test(cx));
1149    cx.add_model(|cx| {
1150        let text = "
1151            * one
1152                - a
1153                - b
1154            * two
1155        "
1156        .unindent();
1157
1158        let mut buffer = Buffer::new(0, text, cx).with_language(
1159            Arc::new(Language::new(
1160                LanguageConfig {
1161                    name: "Markdown".into(),
1162                    auto_indent_using_last_non_empty_line: false,
1163                    ..Default::default()
1164                },
1165                Some(tree_sitter_json::language()),
1166            )),
1167            cx,
1168        );
1169        buffer.edit(
1170            [(Point::new(3, 0)..Point::new(3, 0), "\n")],
1171            Some(AutoindentMode::EachLine),
1172            cx,
1173        );
1174        assert_eq!(
1175            buffer.text(),
1176            "
1177            * one
1178                - a
1179                - b
1180
1181            * two
1182            "
1183            .unindent()
1184        );
1185        buffer
1186    });
1187}
1188
1189#[gpui::test]
1190fn test_autoindent_with_injected_languages(cx: &mut MutableAppContext) {
1191    cx.set_global({
1192        let mut settings = Settings::test(cx);
1193        settings.language_overrides.extend([
1194            (
1195                "HTML".into(),
1196                settings::EditorSettings {
1197                    tab_size: Some(2.try_into().unwrap()),
1198                    ..Default::default()
1199                },
1200            ),
1201            (
1202                "JavaScript".into(),
1203                settings::EditorSettings {
1204                    tab_size: Some(8.try_into().unwrap()),
1205                    ..Default::default()
1206                },
1207            ),
1208        ]);
1209        settings
1210    });
1211
1212    let html_language = Arc::new(
1213        Language::new(
1214            LanguageConfig {
1215                name: "HTML".into(),
1216                ..Default::default()
1217            },
1218            Some(tree_sitter_html::language()),
1219        )
1220        .with_indents_query(
1221            "
1222            (element
1223              (start_tag) @start
1224              (end_tag)? @end) @indent
1225            ",
1226        )
1227        .unwrap()
1228        .with_injection_query(
1229            r#"
1230            (script_element
1231                (raw_text) @content
1232                (#set! "language" "javascript"))
1233            "#,
1234        )
1235        .unwrap(),
1236    );
1237
1238    let javascript_language = Arc::new(
1239        Language::new(
1240            LanguageConfig {
1241                name: "JavaScript".into(),
1242                ..Default::default()
1243            },
1244            Some(tree_sitter_javascript::language()),
1245        )
1246        .with_indents_query(
1247            r#"
1248            (object "}" @end) @indent
1249            "#,
1250        )
1251        .unwrap(),
1252    );
1253
1254    let language_registry = Arc::new(LanguageRegistry::test());
1255    language_registry.add(html_language.clone());
1256    language_registry.add(javascript_language.clone());
1257
1258    cx.add_model(|cx| {
1259        let (text, ranges) = marked_text_ranges(
1260            &"
1261                <div>ˇ
1262                </div>
1263                <script>
1264                    init({ˇ
1265                    })
1266                </script>
1267                <span>ˇ
1268                </span>
1269            "
1270            .unindent(),
1271            false,
1272        );
1273
1274        let mut buffer = Buffer::new(0, text, cx);
1275        buffer.set_language_registry(language_registry);
1276        buffer.set_language(Some(html_language), cx);
1277        buffer.edit(
1278            ranges.into_iter().map(|range| (range, "\na")),
1279            Some(AutoindentMode::EachLine),
1280            cx,
1281        );
1282        assert_eq!(
1283            buffer.text(),
1284            "
1285                <div>
1286                  a
1287                </div>
1288                <script>
1289                    init({
1290                            a
1291                    })
1292                </script>
1293                <span>
1294                  a
1295                </span>
1296            "
1297            .unindent()
1298        );
1299        buffer
1300    });
1301}
1302
1303#[gpui::test]
1304fn test_autoindent_query_with_outdent_captures(cx: &mut MutableAppContext) {
1305    let mut settings = Settings::test(cx);
1306    settings.editor_defaults.tab_size = Some(2.try_into().unwrap());
1307    cx.set_global(settings);
1308    cx.add_model(|cx| {
1309        let mut buffer = Buffer::new(0, "", cx).with_language(Arc::new(ruby_lang()), cx);
1310
1311        let text = r#"
1312            class C
1313            def a(b, c)
1314            puts b
1315            puts c
1316            rescue
1317            puts "errored"
1318            exit 1
1319            end
1320            end
1321        "#
1322        .unindent();
1323
1324        buffer.edit([(0..0, text)], Some(AutoindentMode::EachLine), cx);
1325
1326        assert_eq!(
1327            buffer.text(),
1328            r#"
1329                class C
1330                  def a(b, c)
1331                    puts b
1332                    puts c
1333                  rescue
1334                    puts "errored"
1335                    exit 1
1336                  end
1337                end
1338            "#
1339            .unindent()
1340        );
1341
1342        buffer
1343    });
1344}
1345
1346#[gpui::test]
1347fn test_serialization(cx: &mut gpui::MutableAppContext) {
1348    let mut now = Instant::now();
1349
1350    let buffer1 = cx.add_model(|cx| {
1351        let mut buffer = Buffer::new(0, "abc", cx);
1352        buffer.edit([(3..3, "D")], None, cx);
1353
1354        now += Duration::from_secs(1);
1355        buffer.start_transaction_at(now);
1356        buffer.edit([(4..4, "E")], None, cx);
1357        buffer.end_transaction_at(now, cx);
1358        assert_eq!(buffer.text(), "abcDE");
1359
1360        buffer.undo(cx);
1361        assert_eq!(buffer.text(), "abcD");
1362
1363        buffer.edit([(4..4, "F")], None, cx);
1364        assert_eq!(buffer.text(), "abcDF");
1365        buffer
1366    });
1367    assert_eq!(buffer1.read(cx).text(), "abcDF");
1368
1369    let state = buffer1.read(cx).to_proto();
1370    let ops = cx
1371        .background()
1372        .block(buffer1.read(cx).serialize_ops(None, cx));
1373    let buffer2 = cx.add_model(|cx| {
1374        let mut buffer = Buffer::from_proto(1, state, None).unwrap();
1375        buffer
1376            .apply_ops(
1377                ops.into_iter()
1378                    .map(|op| proto::deserialize_operation(op).unwrap()),
1379                cx,
1380            )
1381            .unwrap();
1382        buffer
1383    });
1384    assert_eq!(buffer2.read(cx).text(), "abcDF");
1385}
1386
1387#[gpui::test(iterations = 100)]
1388fn test_random_collaboration(cx: &mut MutableAppContext, mut rng: StdRng) {
1389    let min_peers = env::var("MIN_PEERS")
1390        .map(|i| i.parse().expect("invalid `MIN_PEERS` variable"))
1391        .unwrap_or(1);
1392    let max_peers = env::var("MAX_PEERS")
1393        .map(|i| i.parse().expect("invalid `MAX_PEERS` variable"))
1394        .unwrap_or(5);
1395    let operations = env::var("OPERATIONS")
1396        .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
1397        .unwrap_or(10);
1398
1399    let base_text_len = rng.gen_range(0..10);
1400    let base_text = RandomCharIter::new(&mut rng)
1401        .take(base_text_len)
1402        .collect::<String>();
1403    let mut replica_ids = Vec::new();
1404    let mut buffers = Vec::new();
1405    let network = Rc::new(RefCell::new(Network::new(rng.clone())));
1406    let base_buffer = cx.add_model(|cx| Buffer::new(0, base_text.as_str(), cx));
1407
1408    for i in 0..rng.gen_range(min_peers..=max_peers) {
1409        let buffer = cx.add_model(|cx| {
1410            let state = base_buffer.read(cx).to_proto();
1411            let ops = cx
1412                .background()
1413                .block(base_buffer.read(cx).serialize_ops(None, cx));
1414            let mut buffer = Buffer::from_proto(i as ReplicaId, state, None).unwrap();
1415            buffer
1416                .apply_ops(
1417                    ops.into_iter()
1418                        .map(|op| proto::deserialize_operation(op).unwrap()),
1419                    cx,
1420                )
1421                .unwrap();
1422            buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
1423            let network = network.clone();
1424            cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
1425                if let Event::Operation(op) = event {
1426                    network
1427                        .borrow_mut()
1428                        .broadcast(buffer.replica_id(), vec![proto::serialize_operation(op)]);
1429                }
1430            })
1431            .detach();
1432            buffer
1433        });
1434        buffers.push(buffer);
1435        replica_ids.push(i as ReplicaId);
1436        network.borrow_mut().add_peer(i as ReplicaId);
1437        log::info!("Adding initial peer with replica id {}", i);
1438    }
1439
1440    log::info!("initial text: {:?}", base_text);
1441
1442    let mut now = Instant::now();
1443    let mut mutation_count = operations;
1444    let mut next_diagnostic_id = 0;
1445    let mut active_selections = BTreeMap::default();
1446    loop {
1447        let replica_index = rng.gen_range(0..replica_ids.len());
1448        let replica_id = replica_ids[replica_index];
1449        let buffer = &mut buffers[replica_index];
1450        let mut new_buffer = None;
1451        match rng.gen_range(0..100) {
1452            0..=29 if mutation_count != 0 => {
1453                buffer.update(cx, |buffer, cx| {
1454                    buffer.start_transaction_at(now);
1455                    buffer.randomly_edit(&mut rng, 5, cx);
1456                    buffer.end_transaction_at(now, cx);
1457                    log::info!("buffer {} text: {:?}", buffer.replica_id(), buffer.text());
1458                });
1459                mutation_count -= 1;
1460            }
1461            30..=39 if mutation_count != 0 => {
1462                buffer.update(cx, |buffer, cx| {
1463                    let mut selections = Vec::new();
1464                    for id in 0..rng.gen_range(1..=5) {
1465                        let range = buffer.random_byte_range(0, &mut rng);
1466                        selections.push(Selection {
1467                            id,
1468                            start: buffer.anchor_before(range.start),
1469                            end: buffer.anchor_before(range.end),
1470                            reversed: false,
1471                            goal: SelectionGoal::None,
1472                        });
1473                    }
1474                    let selections: Arc<[Selection<Anchor>]> = selections.into();
1475                    log::info!(
1476                        "peer {} setting active selections: {:?}",
1477                        replica_id,
1478                        selections
1479                    );
1480                    active_selections.insert(replica_id, selections.clone());
1481                    buffer.set_active_selections(selections, false, Default::default(), cx);
1482                });
1483                mutation_count -= 1;
1484            }
1485            40..=49 if mutation_count != 0 && replica_id == 0 => {
1486                let entry_count = rng.gen_range(1..=5);
1487                buffer.update(cx, |buffer, cx| {
1488                    let diagnostics = DiagnosticSet::new(
1489                        (0..entry_count).map(|_| {
1490                            let range = buffer.random_byte_range(0, &mut rng);
1491                            let range = range.to_point_utf16(buffer);
1492                            let range = range.start..range.end;
1493                            DiagnosticEntry {
1494                                range,
1495                                diagnostic: Diagnostic {
1496                                    message: post_inc(&mut next_diagnostic_id).to_string(),
1497                                    ..Default::default()
1498                                },
1499                            }
1500                        }),
1501                        buffer,
1502                    );
1503                    log::info!("peer {} setting diagnostics: {:?}", replica_id, diagnostics);
1504                    buffer.update_diagnostics(diagnostics, cx);
1505                });
1506                mutation_count -= 1;
1507            }
1508            50..=59 if replica_ids.len() < max_peers => {
1509                let old_buffer_state = buffer.read(cx).to_proto();
1510                let old_buffer_ops = cx
1511                    .background()
1512                    .block(buffer.read(cx).serialize_ops(None, cx));
1513                let new_replica_id = (0..=replica_ids.len() as ReplicaId)
1514                    .filter(|replica_id| *replica_id != buffer.read(cx).replica_id())
1515                    .choose(&mut rng)
1516                    .unwrap();
1517                log::info!(
1518                    "Adding new replica {} (replicating from {})",
1519                    new_replica_id,
1520                    replica_id
1521                );
1522                new_buffer = Some(cx.add_model(|cx| {
1523                    let mut new_buffer =
1524                        Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap();
1525                    new_buffer
1526                        .apply_ops(
1527                            old_buffer_ops
1528                                .into_iter()
1529                                .map(|op| deserialize_operation(op).unwrap()),
1530                            cx,
1531                        )
1532                        .unwrap();
1533                    log::info!(
1534                        "New replica {} text: {:?}",
1535                        new_buffer.replica_id(),
1536                        new_buffer.text()
1537                    );
1538                    new_buffer.set_group_interval(Duration::from_millis(rng.gen_range(0..=200)));
1539                    let network = network.clone();
1540                    cx.subscribe(&cx.handle(), move |buffer, _, event, _| {
1541                        if let Event::Operation(op) = event {
1542                            network.borrow_mut().broadcast(
1543                                buffer.replica_id(),
1544                                vec![proto::serialize_operation(op)],
1545                            );
1546                        }
1547                    })
1548                    .detach();
1549                    new_buffer
1550                }));
1551                network.borrow_mut().replicate(replica_id, new_replica_id);
1552
1553                if new_replica_id as usize == replica_ids.len() {
1554                    replica_ids.push(new_replica_id);
1555                } else {
1556                    let new_buffer = new_buffer.take().unwrap();
1557                    while network.borrow().has_unreceived(new_replica_id) {
1558                        let ops = network
1559                            .borrow_mut()
1560                            .receive(new_replica_id)
1561                            .into_iter()
1562                            .map(|op| proto::deserialize_operation(op).unwrap());
1563                        if ops.len() > 0 {
1564                            log::info!(
1565                                "peer {} (version: {:?}) applying {} ops from the network. {:?}",
1566                                new_replica_id,
1567                                buffer.read(cx).version(),
1568                                ops.len(),
1569                                ops
1570                            );
1571                            new_buffer.update(cx, |new_buffer, cx| {
1572                                new_buffer.apply_ops(ops, cx).unwrap();
1573                            });
1574                        }
1575                    }
1576                    buffers[new_replica_id as usize] = new_buffer;
1577                }
1578            }
1579            60..=69 if mutation_count != 0 => {
1580                buffer.update(cx, |buffer, cx| {
1581                    buffer.randomly_undo_redo(&mut rng, cx);
1582                    log::info!("buffer {} text: {:?}", buffer.replica_id(), buffer.text());
1583                });
1584                mutation_count -= 1;
1585            }
1586            _ if network.borrow().has_unreceived(replica_id) => {
1587                let ops = network
1588                    .borrow_mut()
1589                    .receive(replica_id)
1590                    .into_iter()
1591                    .map(|op| proto::deserialize_operation(op).unwrap());
1592                if ops.len() > 0 {
1593                    log::info!(
1594                        "peer {} (version: {:?}) applying {} ops from the network. {:?}",
1595                        replica_id,
1596                        buffer.read(cx).version(),
1597                        ops.len(),
1598                        ops
1599                    );
1600                    buffer.update(cx, |buffer, cx| buffer.apply_ops(ops, cx).unwrap());
1601                }
1602            }
1603            _ => {}
1604        }
1605
1606        now += Duration::from_millis(rng.gen_range(0..=200));
1607        buffers.extend(new_buffer);
1608
1609        for buffer in &buffers {
1610            buffer.read(cx).check_invariants();
1611        }
1612
1613        if mutation_count == 0 && network.borrow().is_idle() {
1614            break;
1615        }
1616    }
1617
1618    let first_buffer = buffers[0].read(cx).snapshot();
1619    for buffer in &buffers[1..] {
1620        let buffer = buffer.read(cx).snapshot();
1621        assert_eq!(
1622            buffer.version(),
1623            first_buffer.version(),
1624            "Replica {} version != Replica 0 version",
1625            buffer.replica_id()
1626        );
1627        assert_eq!(
1628            buffer.text(),
1629            first_buffer.text(),
1630            "Replica {} text != Replica 0 text",
1631            buffer.replica_id()
1632        );
1633        assert_eq!(
1634            buffer
1635                .diagnostics_in_range::<_, usize>(0..buffer.len(), false)
1636                .collect::<Vec<_>>(),
1637            first_buffer
1638                .diagnostics_in_range::<_, usize>(0..first_buffer.len(), false)
1639                .collect::<Vec<_>>(),
1640            "Replica {} diagnostics != Replica 0 diagnostics",
1641            buffer.replica_id()
1642        );
1643    }
1644
1645    for buffer in &buffers {
1646        let buffer = buffer.read(cx).snapshot();
1647        let actual_remote_selections = buffer
1648            .remote_selections_in_range(Anchor::MIN..Anchor::MAX)
1649            .map(|(replica_id, _, _, selections)| (replica_id, selections.collect::<Vec<_>>()))
1650            .collect::<Vec<_>>();
1651        let expected_remote_selections = active_selections
1652            .iter()
1653            .filter(|(replica_id, _)| **replica_id != buffer.replica_id())
1654            .map(|(replica_id, selections)| (*replica_id, selections.iter().collect::<Vec<_>>()))
1655            .collect::<Vec<_>>();
1656        assert_eq!(
1657            actual_remote_selections,
1658            expected_remote_selections,
1659            "Replica {} remote selections != expected selections",
1660            buffer.replica_id()
1661        );
1662    }
1663}
1664
1665#[test]
1666fn test_contiguous_ranges() {
1667    assert_eq!(
1668        contiguous_ranges([1, 2, 3, 5, 6, 9, 10, 11, 12].into_iter(), 100).collect::<Vec<_>>(),
1669        &[1..4, 5..7, 9..13]
1670    );
1671
1672    // Respects the `max_len` parameter
1673    assert_eq!(
1674        contiguous_ranges(
1675            [2, 3, 4, 5, 6, 7, 8, 9, 23, 24, 25, 26, 30, 31].into_iter(),
1676            3
1677        )
1678        .collect::<Vec<_>>(),
1679        &[2..5, 5..8, 8..10, 23..26, 26..27, 30..32],
1680    );
1681}
1682
1683impl Buffer {
1684    pub fn enclosing_bracket_point_ranges<T: ToOffset>(
1685        &self,
1686        range: Range<T>,
1687    ) -> Option<(Range<Point>, Range<Point>)> {
1688        self.snapshot()
1689            .enclosing_bracket_ranges(range)
1690            .map(|(start, end)| {
1691                let point_start = start.start.to_point(self)..start.end.to_point(self);
1692                let point_end = end.start.to_point(self)..end.end.to_point(self);
1693                (point_start, point_end)
1694            })
1695    }
1696}
1697
1698fn ruby_lang() -> Language {
1699    Language::new(
1700        LanguageConfig {
1701            name: "Ruby".into(),
1702            path_suffixes: vec!["rb".to_string()],
1703            ..Default::default()
1704        },
1705        Some(tree_sitter_ruby::language()),
1706    )
1707    .with_indents_query(
1708        r#"
1709            (class "end" @end) @indent
1710            (method "end" @end) @indent
1711            (rescue) @outdent
1712            (then) @indent
1713        "#,
1714    )
1715    .unwrap()
1716}
1717
1718fn rust_lang() -> Language {
1719    Language::new(
1720        LanguageConfig {
1721            name: "Rust".into(),
1722            path_suffixes: vec!["rs".to_string()],
1723            ..Default::default()
1724        },
1725        Some(tree_sitter_rust::language()),
1726    )
1727    .with_indents_query(
1728        r#"
1729        (call_expression) @indent
1730        (field_expression) @indent
1731        (_ "(" ")" @end) @indent
1732        (_ "{" "}" @end) @indent
1733        "#,
1734    )
1735    .unwrap()
1736    .with_brackets_query(
1737        r#"
1738        ("{" @open "}" @close)
1739        "#,
1740    )
1741    .unwrap()
1742    .with_outline_query(
1743        r#"
1744        (struct_item
1745            "struct" @context
1746            name: (_) @name) @item
1747        (enum_item
1748            "enum" @context
1749            name: (_) @name) @item
1750        (enum_variant
1751            name: (_) @name) @item
1752        (field_declaration
1753            name: (_) @name) @item
1754        (impl_item
1755            "impl" @context
1756            trait: (_)? @name
1757            "for"? @context
1758            type: (_) @name) @item
1759        (function_item
1760            "fn" @context
1761            name: (_) @name) @item
1762        (mod_item
1763            "mod" @context
1764            name: (_) @name) @item
1765        "#,
1766    )
1767    .unwrap()
1768}
1769
1770fn json_lang() -> Language {
1771    Language::new(
1772        LanguageConfig {
1773            name: "Json".into(),
1774            path_suffixes: vec!["js".to_string()],
1775            ..Default::default()
1776        },
1777        Some(tree_sitter_json::language()),
1778    )
1779}
1780
1781fn get_tree_sexp(buffer: &ModelHandle<Buffer>, cx: &gpui::TestAppContext) -> String {
1782    buffer.read_with(cx, |buffer, _| {
1783        let snapshot = buffer.snapshot();
1784        let layers = snapshot.syntax.layers(buffer.as_text_snapshot());
1785        layers[0].node.to_sexp()
1786    })
1787}
1788
1789fn empty(point: Point) -> Range<Point> {
1790    point..point
1791}