tests.rs

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