1989 lines · 68.3 KB · Rust
RawDownload
use super::*;use gpui::{AppContext, Context, TestAppContext};use language::{Buffer, Rope};use parking_lot::RwLock;use rand::prelude::*;use settings::SettingsStore;use std::env;use util::test::sample_text; #[ctor::ctor]fn init_logger() {    if std::env::var("RUST_LOG").is_ok() {        env_logger::init();    }} #[gpui::test]fn test_singleton(cx: &mut AppContext) {    let buffer = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));    let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(buffer.clone(), cx));     let snapshot = multibuffer.read(cx).snapshot(cx);    assert_eq!(snapshot.text(), buffer.read(cx).text());     assert_eq!(        snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),        (0..buffer.read(cx).row_count())            .map(Some)            .collect::<Vec<_>>()    );     buffer.update(cx, |buffer, cx| buffer.edit([(1..3, "XXX\n")], None, cx));    let snapshot = multibuffer.read(cx).snapshot(cx);     assert_eq!(snapshot.text(), buffer.read(cx).text());    assert_eq!(        snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),        (0..buffer.read(cx).row_count())            .map(Some)            .collect::<Vec<_>>()    );} #[gpui::test]fn test_remote(cx: &mut AppContext) {    let host_buffer = cx.new_model(|cx| Buffer::local("a", cx));    let guest_buffer = cx.new_model(|cx| {        let state = host_buffer.read(cx).to_proto(cx);        let ops = cx            .background_executor()            .block(host_buffer.read(cx).serialize_ops(None, cx));        let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();        buffer.apply_ops(            ops.into_iter()                .map(|op| language::proto::deserialize_operation(op).unwrap()),            cx,        );        buffer    });    let multibuffer = cx.new_model(|cx| MultiBuffer::singleton(guest_buffer.clone(), cx));    let snapshot = multibuffer.read(cx).snapshot(cx);    assert_eq!(snapshot.text(), "a");     guest_buffer.update(cx, |buffer, cx| buffer.edit([(1..1, "b")], None, cx));    let snapshot = multibuffer.read(cx).snapshot(cx);    assert_eq!(snapshot.text(), "ab");     guest_buffer.update(cx, |buffer, cx| buffer.edit([(2..2, "c")], None, cx));    let snapshot = multibuffer.read(cx).snapshot(cx);    assert_eq!(snapshot.text(), "abc");} #[gpui::test]fn test_excerpt_boundaries_and_clipping(cx: &mut AppContext) {    let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));    let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'g'), cx));    let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));     let events = Arc::new(RwLock::new(Vec::<Event>::new()));    multibuffer.update(cx, |_, cx| {        let events = events.clone();        cx.subscribe(&multibuffer, move |_, _, event, _| {            if let Event::Edited { .. } = event {                events.write().push(event.clone())            }        })        .detach();    });     let subscription = multibuffer.update(cx, |multibuffer, cx| {        let subscription = multibuffer.subscribe();        multibuffer.push_excerpts(            buffer_1.clone(),            [ExcerptRange {                context: Point::new(1, 2)..Point::new(2, 5),                primary: None,            }],            cx,        );        assert_eq!(            subscription.consume().into_inner(),            [Edit {                old: 0..0,                new: 0..10            }]        );         multibuffer.push_excerpts(            buffer_1.clone(),            [ExcerptRange {                context: Point::new(3, 3)..Point::new(4, 4),                primary: None,            }],            cx,        );        multibuffer.push_excerpts(            buffer_2.clone(),            [ExcerptRange {                context: Point::new(3, 1)..Point::new(3, 3),                primary: None,            }],            cx,        );        assert_eq!(            subscription.consume().into_inner(),            [Edit {                old: 10..10,                new: 10..22            }]        );         subscription    });     // Adding excerpts emits an edited event.    assert_eq!(        events.read().as_slice(),        &[            Event::Edited {                singleton_buffer_edited: false,                edited_buffer: None,            },            Event::Edited {                singleton_buffer_edited: false,                edited_buffer: None,            },            Event::Edited {                singleton_buffer_edited: false,                edited_buffer: None,            }        ]    );     let snapshot = multibuffer.read(cx).snapshot(cx);    assert_eq!(        snapshot.text(),        concat!(            "bbbb\n",  // Preserve newlines            "ccccc\n", //            "ddd\n",   //            "eeee\n",  //            "jj"       //        )    );    assert_eq!(        snapshot.buffer_rows(MultiBufferRow(0)).collect::<Vec<_>>(),        [Some(1), Some(2), Some(3), Some(4), Some(3)]    );    assert_eq!(        snapshot.buffer_rows(MultiBufferRow(2)).collect::<Vec<_>>(),        [Some(3), Some(4), Some(3)]    );    assert_eq!(        snapshot.buffer_rows(MultiBufferRow(4)).collect::<Vec<_>>(),        [Some(3)]    );    assert_eq!(        snapshot.buffer_rows(MultiBufferRow(5)).collect::<Vec<_>>(),        []    );     assert_eq!(        boundaries_in_range(Point::new(0, 0)..Point::new(4, 2), &snapshot),        &[            (MultiBufferRow(0), "bbbb\nccccc".to_string(), true),            (MultiBufferRow(2), "ddd\neeee".to_string(), false),            (MultiBufferRow(4), "jj".to_string(), true),        ]    );    assert_eq!(        boundaries_in_range(Point::new(0, 0)..Point::new(2, 0), &snapshot),        &[(MultiBufferRow(0), "bbbb\nccccc".to_string(), true)]    );    assert_eq!(        boundaries_in_range(Point::new(1, 0)..Point::new(1, 5), &snapshot),        &[]    );    assert_eq!(        boundaries_in_range(Point::new(1, 0)..Point::new(2, 0), &snapshot),        &[]    );    assert_eq!(        boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),        &[(MultiBufferRow(2), "ddd\neeee".to_string(), false)]    );    assert_eq!(        boundaries_in_range(Point::new(1, 0)..Point::new(4, 0), &snapshot),        &[(MultiBufferRow(2), "ddd\neeee".to_string(), false)]    );    assert_eq!(        boundaries_in_range(Point::new(2, 0)..Point::new(3, 0), &snapshot),        &[(MultiBufferRow(2), "ddd\neeee".to_string(), false)]    );    assert_eq!(        boundaries_in_range(Point::new(4, 0)..Point::new(4, 2), &snapshot),        &[(MultiBufferRow(4), "jj".to_string(), true)]    );    assert_eq!(        boundaries_in_range(Point::new(4, 2)..Point::new(4, 2), &snapshot),        &[]    );     buffer_1.update(cx, |buffer, cx| {        let text = "\n";        buffer.edit(            [                (Point::new(0, 0)..Point::new(0, 0), text),                (Point::new(2, 1)..Point::new(2, 3), text),            ],            None,            cx,        );    });     let snapshot = multibuffer.read(cx).snapshot(cx);    assert_eq!(        snapshot.text(),        concat!(            "bbbb\n", // Preserve newlines            "c\n",    //            "cc\n",   //            "ddd\n",  //            "eeee\n", //            "jj"      //        )    );     assert_eq!(        subscription.consume().into_inner(),        [Edit {            old: 6..8,            new: 6..7        }]    );     let snapshot = multibuffer.read(cx).snapshot(cx);    assert_eq!(        snapshot.clip_point(Point::new(0, 5), Bias::Left),        Point::new(0, 4)    );    assert_eq!(        snapshot.clip_point(Point::new(0, 5), Bias::Right),        Point::new(0, 4)    );    assert_eq!(        snapshot.clip_point(Point::new(5, 1), Bias::Right),        Point::new(5, 1)    );    assert_eq!(        snapshot.clip_point(Point::new(5, 2), Bias::Right),        Point::new(5, 2)    );    assert_eq!(        snapshot.clip_point(Point::new(5, 3), Bias::Right),        Point::new(5, 2)    );     let snapshot = multibuffer.update(cx, |multibuffer, cx| {        let (buffer_2_excerpt_id, _) = multibuffer.excerpts_for_buffer(&buffer_2, cx)[0].clone();        multibuffer.remove_excerpts([buffer_2_excerpt_id], cx);        multibuffer.snapshot(cx)    });     assert_eq!(        snapshot.text(),        concat!(            "bbbb\n", // Preserve newlines            "c\n",    //            "cc\n",   //            "ddd\n",  //            "eeee",   //        )    );     fn boundaries_in_range(        range: Range<Point>,        snapshot: &MultiBufferSnapshot,    ) -> Vec<(MultiBufferRow, String, bool)> {        snapshot            .excerpt_boundaries_in_range(range)            .filter_map(|boundary| {                let starts_new_buffer = boundary.starts_new_buffer();                boundary.next.map(|next| {                    (                        boundary.row,                        next.buffer                            .text_for_range(next.range.context)                            .collect::<String>(),                        starts_new_buffer,                    )                })            })            .collect::<Vec<_>>()    }} #[gpui::test]fn test_excerpt_events(cx: &mut AppContext) {    let buffer_1 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'a'), cx));    let buffer_2 = cx.new_model(|cx| Buffer::local(sample_text(10, 3, 'm'), cx));     let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));    let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));    let follower_edit_event_count = Arc::new(RwLock::new(0));     follower_multibuffer.update(cx, |_, cx| {        let follower_edit_event_count = follower_edit_event_count.clone();        cx.subscribe(            &leader_multibuffer,            move |follower, _, event, cx| match event.clone() {                Event::ExcerptsAdded {                    buffer,                    predecessor,                    excerpts,                } => follower.insert_excerpts_with_ids_after(predecessor, buffer, excerpts, cx),                Event::ExcerptsRemoved { ids } => follower.remove_excerpts(ids, cx),                Event::Edited { .. } => {                    *follower_edit_event_count.write() += 1;                }                _ => {}            },        )        .detach();    });     leader_multibuffer.update(cx, |leader, cx| {        leader.push_excerpts(            buffer_1.clone(),            [                ExcerptRange {                    context: 0..8,                    primary: None,                },                ExcerptRange {                    context: 12..16,                    primary: None,                },            ],            cx,        );        leader.insert_excerpts_after(            leader.excerpt_ids()[0],            buffer_2.clone(),            [                ExcerptRange {                    context: 0..5,                    primary: None,                },                ExcerptRange {                    context: 10..15,                    primary: None,                },            ],            cx,        )    });    assert_eq!(        leader_multibuffer.read(cx).snapshot(cx).text(),        follower_multibuffer.read(cx).snapshot(cx).text(),    );    assert_eq!(*follower_edit_event_count.read(), 2);     leader_multibuffer.update(cx, |leader, cx| {        let excerpt_ids = leader.excerpt_ids();        leader.remove_excerpts([excerpt_ids[1], excerpt_ids[3]], cx);    });    assert_eq!(        leader_multibuffer.read(cx).snapshot(cx).text(),        follower_multibuffer.read(cx).snapshot(cx).text(),    );    assert_eq!(*follower_edit_event_count.read(), 3);     // Removing an empty set of excerpts is a noop.    leader_multibuffer.update(cx, |leader, cx| {        leader.remove_excerpts([], cx);    });    assert_eq!(        leader_multibuffer.read(cx).snapshot(cx).text(),        follower_multibuffer.read(cx).snapshot(cx).text(),    );    assert_eq!(*follower_edit_event_count.read(), 3);     // Adding an empty set of excerpts is a noop.    leader_multibuffer.update(cx, |leader, cx| {        leader.push_excerpts::<usize>(buffer_2.clone(), [], cx);    });    assert_eq!(        leader_multibuffer.read(cx).snapshot(cx).text(),        follower_multibuffer.read(cx).snapshot(cx).text(),    );    assert_eq!(*follower_edit_event_count.read(), 3);     leader_multibuffer.update(cx, |leader, cx| {        leader.clear(cx);    });    assert_eq!(        leader_multibuffer.read(cx).snapshot(cx).text(),        follower_multibuffer.read(cx).snapshot(cx).text(),    );    assert_eq!(*follower_edit_event_count.read(), 4);} #[gpui::test]fn test_expand_excerpts(cx: &mut AppContext) {    let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));    let multibuffer = cx.new_model(|_| MultiBuffer::new(Capability::ReadWrite));     multibuffer.update(cx, |multibuffer, cx| {        multibuffer.push_excerpts_with_context_lines(            buffer.clone(),            vec![                // Note that in this test, this first excerpt                // does not contain a new line                Point::new(3, 2)..Point::new(3, 3),                Point::new(7, 1)..Point::new(7, 3),                Point::new(15, 0)..Point::new(15, 0),            ],            1,            cx,        )    });     let snapshot = multibuffer.read(cx).snapshot(cx);     assert_eq!(        snapshot.text(),        concat!(            "ccc\n", //            "ddd\n", //            "eee",   //            "\n",    // End of excerpt            "ggg\n", //            "hhh\n", //            "iii",   //            "\n",    // End of excerpt            "ooo\n", //            "ppp\n", //            "qqq",   // End of excerpt        )    );    drop(snapshot);     multibuffer.update(cx, |multibuffer, cx| {        multibuffer.expand_excerpts(            multibuffer.excerpt_ids(),            1,            ExpandExcerptDirection::UpAndDown,            cx,        )    });     let snapshot = multibuffer.read(cx).snapshot(cx);     // Expanding context lines causes the line containing 'fff' to appear in two different excerpts.    // We don't attempt to merge them, because removing the excerpt could create inconsistency with other layers    // that are tracking excerpt ids.    assert_eq!(        snapshot.text(),        concat!(            "bbb\n", //            "ccc\n", //            "ddd\n", //            "eee\n", //            "fff\n", // End of excerpt            "fff\n", //            "ggg\n", //            "hhh\n", //            "iii\n", //            "jjj\n", // End of excerpt            "nnn\n", //            "ooo\n", //            "ppp\n", //            "qqq\n", //            "rrr",   // End of excerpt        )    );} #[gpui::test]fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {

Lines 1–500 of 1989.