Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 74 additions & 2 deletions crates/outline/src/outline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,14 @@ impl OutlineViewDelegate {

cx: &mut Context<Picker<OutlineViewDelegate>>,
) {
let Some(selected_match) = self.matches.get(ix) else {
self.selected_match_index = self.matches.len();
return;
};

self.selected_match_index = ix;

if navigate && !self.matches.is_empty() {
let selected_match = &self.matches[self.selected_match_index];
if navigate {
let outline_item = &self.outline.items[selected_match.candidate_id];

self.active_editor.update(cx, |active_editor, cx| {
Expand Down Expand Up @@ -269,6 +273,10 @@ impl PickerDelegate for OutlineViewDelegate {
self.selected_match_index
}

fn can_select(&self, ix: usize, _window: &mut Window, _cx: &mut Context<Picker<Self>>) -> bool {
ix < self.matches.len()
}

fn set_selected_index(
&mut self,
ix: usize,
Expand Down Expand Up @@ -704,6 +712,70 @@ mod tests {
);
}

#[gpui::test]
async fn test_outline_stale_hover_index_after_matches_shrink(cx: &mut TestAppContext) {
init_test(cx);

let mut source = String::new();
for index in 0..69 {
source.push_str(&format!("struct Keep{index};\n"));
}
for index in 69..74 {
source.push_str(&format!("struct Drop{index};\n"));
}

let fs = FakeFs::new(cx.executor());
fs.insert_tree(path!("/dir"), json!({ "a.rs": source }))
.await;

let project = Project::test(fs, [path!("/dir").as_ref()], cx).await;
project.read_with(cx, |project, _| {
project.languages().add(language::rust_lang())
});

let (workspace, cx) =
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));

let workspace = cx.read(|cx| workspace.read(cx).workspace().clone());
let worktree_id = workspace.update(cx, |workspace, cx| {
workspace.project().update(cx, |project, cx| {
project.worktrees(cx).next().unwrap().read(cx).id()
})
});
let _buffer = project
.update(cx, |project, cx| {
project.open_local_buffer(path!("/dir/a.rs"), cx)
})
.await
.unwrap();
workspace
.update_in(cx, |workspace, window, cx| {
workspace.open_path((worktree_id, rel_path("a.rs")), None, true, window, cx)
})
.await
.unwrap();

let outline_view = open_outline_view(&workspace, cx);
outline_view.read_with(cx, |outline_view, _| {
assert_eq!(outline_view.delegate.matches.len(), 74);
});

outline_view
.update_in(cx, |outline_view, window, cx| {
outline_view
.delegate
.update_matches("Keep".to_string(), window, cx)
})
.await;
outline_view.read_with(cx, |outline_view, _| {
assert_eq!(outline_view.delegate.matches.len(), 69);
});

outline_view.update_in(cx, |outline_view, window, cx| {
outline_view.set_selected_index(73, None, false, window, cx);
});
}

#[gpui::test]
async fn test_outline_filtered_selection_prefers_first_match_on_score_ties(
cx: &mut TestAppContext,
Expand Down
Loading