test.rs

  1pub mod editor_lsp_test_context;
  2pub mod editor_test_context;
  3
  4use crate::{
  5    display_map::{DisplayMap, DisplaySnapshot, ToDisplayPoint},
  6    DisplayPoint, Editor, EditorMode, MultiBuffer,
  7};
  8
  9use gpui::{Context, Font, FontFeatures, FontStyle, FontWeight, Model, Pixels, ViewContext};
 10
 11use project::Project;
 12use util::test::{marked_text_offsets, marked_text_ranges};
 13
 14#[cfg(test)]
 15#[ctor::ctor]
 16fn init_logger() {
 17    if std::env::var("RUST_LOG").is_ok() {
 18        env_logger::init();
 19    }
 20}
 21
 22// Returns a snapshot from text containing '|' character markers with the markers removed, and DisplayPoints for each one.
 23pub fn marked_display_snapshot(
 24    text: &str,
 25    cx: &mut gpui::AppContext,
 26) -> (DisplaySnapshot, Vec<DisplayPoint>) {
 27    let (unmarked_text, markers) = marked_text_offsets(text);
 28
 29    let font = Font {
 30        family: "Courier".into(),
 31        features: FontFeatures::default(),
 32        weight: FontWeight::default(),
 33        style: FontStyle::default(),
 34    };
 35    let font_size: Pixels = 14usize.into();
 36
 37    let buffer = MultiBuffer::build_simple(&unmarked_text, cx);
 38    let display_map = cx.new_model(|cx| DisplayMap::new(buffer, font, font_size, None, 1, 1, cx));
 39    let snapshot = display_map.update(cx, |map, cx| map.snapshot(cx));
 40    let markers = markers
 41        .into_iter()
 42        .map(|offset| offset.to_display_point(&snapshot))
 43        .collect();
 44
 45    (snapshot, markers)
 46}
 47
 48pub fn select_ranges(editor: &mut Editor, marked_text: &str, cx: &mut ViewContext<Editor>) {
 49    let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
 50    assert_eq!(editor.text(cx), unmarked_text);
 51    editor.change_selections(None, cx, |s| s.select_ranges(text_ranges));
 52}
 53
 54pub fn assert_text_with_selections(
 55    editor: &mut Editor,
 56    marked_text: &str,
 57    cx: &mut ViewContext<Editor>,
 58) {
 59    let (unmarked_text, text_ranges) = marked_text_ranges(marked_text, true);
 60    assert_eq!(editor.text(cx), unmarked_text);
 61    assert_eq!(editor.selections.ranges(cx), text_ranges);
 62}
 63
 64// RA thinks this is dead code even though it is used in a whole lot of tests
 65#[allow(dead_code)]
 66#[cfg(any(test, feature = "test-support"))]
 67pub(crate) fn build_editor(buffer: Model<MultiBuffer>, cx: &mut ViewContext<Editor>) -> Editor {
 68    Editor::new(EditorMode::Full, buffer, None, cx)
 69}
 70
 71pub(crate) fn build_editor_with_project(
 72    project: Model<Project>,
 73    buffer: Model<MultiBuffer>,
 74    cx: &mut ViewContext<Editor>,
 75) -> Editor {
 76    Editor::new(EditorMode::Full, buffer, Some(project), cx)
 77}
 78
 79#[cfg(any(test, feature = "test-support"))]
 80pub fn editor_hunks(
 81    editor: &Editor,
 82    snapshot: &DisplaySnapshot,
 83    cx: &mut ViewContext<'_, Editor>,
 84) -> Vec<(
 85    String,
 86    git::diff::DiffHunkStatus,
 87    std::ops::Range<crate::DisplayRow>,
 88)> {
 89    use multi_buffer::MultiBufferRow;
 90    use text::Point;
 91
 92    use crate::hunk_status;
 93
 94    snapshot
 95        .buffer_snapshot
 96        .git_diff_hunks_in_range(MultiBufferRow::MIN..MultiBufferRow::MAX)
 97        .map(|hunk| {
 98            let display_range = Point::new(hunk.associated_range.start.0, 0)
 99                .to_display_point(snapshot)
100                .row()
101                ..Point::new(hunk.associated_range.end.0, 0)
102                    .to_display_point(snapshot)
103                    .row();
104            let (_, buffer, _) = editor
105                .buffer()
106                .read(cx)
107                .excerpt_containing(Point::new(hunk.associated_range.start.0, 0), cx)
108                .expect("no excerpt for expanded buffer's hunk start");
109            let diff_base = buffer
110                .read(cx)
111                .diff_base()
112                .expect("should have a diff base for expanded hunk")
113                .slice(hunk.diff_base_byte_range.clone())
114                .to_string();
115            (diff_base, hunk_status(&hunk), display_range)
116        })
117        .collect()
118}
119
120#[cfg(any(test, feature = "test-support"))]
121pub fn expanded_hunks(
122    editor: &Editor,
123    snapshot: &DisplaySnapshot,
124    cx: &mut ViewContext<'_, Editor>,
125) -> Vec<(
126    String,
127    git::diff::DiffHunkStatus,
128    std::ops::Range<crate::DisplayRow>,
129)> {
130    editor
131        .expanded_hunks
132        .hunks(false)
133        .map(|expanded_hunk| {
134            let hunk_display_range = expanded_hunk
135                .hunk_range
136                .start
137                .to_display_point(snapshot)
138                .row()
139                ..expanded_hunk
140                    .hunk_range
141                    .end
142                    .to_display_point(snapshot)
143                    .row();
144            let (_, buffer, _) = editor
145                .buffer()
146                .read(cx)
147                .excerpt_containing(expanded_hunk.hunk_range.start, cx)
148                .expect("no excerpt for expanded buffer's hunk start");
149            let diff_base = buffer
150                .read(cx)
151                .diff_base()
152                .expect("should have a diff base for expanded hunk")
153                .slice(expanded_hunk.diff_base_byte_range.clone())
154                .to_string();
155            (diff_base, expanded_hunk.status, hunk_display_range)
156        })
157        .collect()
158}
159
160#[cfg(any(test, feature = "test-support"))]
161pub fn expanded_hunks_background_highlights(
162    editor: &mut Editor,
163    cx: &mut gpui::WindowContext,
164) -> Vec<std::ops::RangeInclusive<crate::DisplayRow>> {
165    use crate::DisplayRow;
166
167    let mut highlights = Vec::new();
168
169    let mut range_start = 0;
170    let mut previous_highlighted_row = None;
171    for (highlighted_row, _) in editor.highlighted_display_rows(cx) {
172        match previous_highlighted_row {
173            Some(previous_row) => {
174                if previous_row + 1 != highlighted_row.0 {
175                    highlights.push(DisplayRow(range_start)..=DisplayRow(previous_row));
176                    range_start = highlighted_row.0;
177                }
178            }
179            None => {
180                range_start = highlighted_row.0;
181            }
182        }
183        previous_highlighted_row = Some(highlighted_row.0);
184    }
185    if let Some(previous_row) = previous_highlighted_row {
186        highlights.push(DisplayRow(range_start)..=DisplayRow(previous_row));
187    }
188
189    highlights
190}