Fixed outline panel panicking on filtering (#19811)
Closes https://github.com/zed-industries/zed/issues/19732 Release Notes: - Fixed outline panel panicking on filtering ([#19732](https://github.com/zed-industries/zed/issues/19732))
This commit is contained in:
parent
c69da2df70
commit
2d16d2d036
1 changed files with 132 additions and 181 deletions
|
@ -2825,7 +2825,6 @@ impl OutlinePanel {
|
||||||
cx.spawn(|outline_panel, mut cx| async move {
|
cx.spawn(|outline_panel, mut cx| async move {
|
||||||
let mut entries = Vec::new();
|
let mut entries = Vec::new();
|
||||||
let mut match_candidates = Vec::new();
|
let mut match_candidates = Vec::new();
|
||||||
let mut added_contexts = HashSet::default();
|
|
||||||
|
|
||||||
let Ok(()) = outline_panel.update(&mut cx, |outline_panel, cx| {
|
let Ok(()) = outline_panel.update(&mut cx, |outline_panel, cx| {
|
||||||
let auto_fold_dirs = OutlinePanelSettings::get_global(cx).auto_fold_dirs;
|
let auto_fold_dirs = OutlinePanelSettings::get_global(cx).auto_fold_dirs;
|
||||||
|
@ -2947,7 +2946,6 @@ impl OutlinePanel {
|
||||||
outline_panel.push_entry(
|
outline_panel.push_entry(
|
||||||
&mut entries,
|
&mut entries,
|
||||||
&mut match_candidates,
|
&mut match_candidates,
|
||||||
&mut added_contexts,
|
|
||||||
track_matches,
|
track_matches,
|
||||||
new_folded_dirs,
|
new_folded_dirs,
|
||||||
folded_depth,
|
folded_depth,
|
||||||
|
@ -2986,7 +2984,6 @@ impl OutlinePanel {
|
||||||
outline_panel.push_entry(
|
outline_panel.push_entry(
|
||||||
&mut entries,
|
&mut entries,
|
||||||
&mut match_candidates,
|
&mut match_candidates,
|
||||||
&mut added_contexts,
|
|
||||||
track_matches,
|
track_matches,
|
||||||
PanelEntry::FoldedDirs(worktree_id, folded_dirs),
|
PanelEntry::FoldedDirs(worktree_id, folded_dirs),
|
||||||
folded_depth,
|
folded_depth,
|
||||||
|
@ -3012,7 +3009,6 @@ impl OutlinePanel {
|
||||||
outline_panel.push_entry(
|
outline_panel.push_entry(
|
||||||
&mut entries,
|
&mut entries,
|
||||||
&mut match_candidates,
|
&mut match_candidates,
|
||||||
&mut added_contexts,
|
|
||||||
track_matches,
|
track_matches,
|
||||||
PanelEntry::FoldedDirs(worktree_id, folded_dirs),
|
PanelEntry::FoldedDirs(worktree_id, folded_dirs),
|
||||||
folded_depth,
|
folded_depth,
|
||||||
|
@ -3049,7 +3045,6 @@ impl OutlinePanel {
|
||||||
outline_panel.push_entry(
|
outline_panel.push_entry(
|
||||||
&mut entries,
|
&mut entries,
|
||||||
&mut match_candidates,
|
&mut match_candidates,
|
||||||
&mut added_contexts,
|
|
||||||
track_matches,
|
track_matches,
|
||||||
PanelEntry::Fs(entry.clone()),
|
PanelEntry::Fs(entry.clone()),
|
||||||
depth,
|
depth,
|
||||||
|
@ -3063,7 +3058,6 @@ impl OutlinePanel {
|
||||||
outline_panel.add_search_entries(
|
outline_panel.add_search_entries(
|
||||||
&mut entries,
|
&mut entries,
|
||||||
&mut match_candidates,
|
&mut match_candidates,
|
||||||
&mut added_contexts,
|
|
||||||
entry.clone(),
|
entry.clone(),
|
||||||
depth,
|
depth,
|
||||||
query.clone(),
|
query.clone(),
|
||||||
|
@ -3097,7 +3091,6 @@ impl OutlinePanel {
|
||||||
query.as_deref(),
|
query.as_deref(),
|
||||||
&mut entries,
|
&mut entries,
|
||||||
&mut match_candidates,
|
&mut match_candidates,
|
||||||
&mut added_contexts,
|
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3113,7 +3106,6 @@ impl OutlinePanel {
|
||||||
outline_panel.push_entry(
|
outline_panel.push_entry(
|
||||||
&mut entries,
|
&mut entries,
|
||||||
&mut match_candidates,
|
&mut match_candidates,
|
||||||
&mut added_contexts,
|
|
||||||
track_matches,
|
track_matches,
|
||||||
PanelEntry::Fs(entry.clone()),
|
PanelEntry::Fs(entry.clone()),
|
||||||
0,
|
0,
|
||||||
|
@ -3132,7 +3124,6 @@ impl OutlinePanel {
|
||||||
outline_panel.push_entry(
|
outline_panel.push_entry(
|
||||||
&mut entries,
|
&mut entries,
|
||||||
&mut match_candidates,
|
&mut match_candidates,
|
||||||
&mut added_contexts,
|
|
||||||
track_matches,
|
track_matches,
|
||||||
PanelEntry::FoldedDirs(worktree_id, folded_dirs),
|
PanelEntry::FoldedDirs(worktree_id, folded_dirs),
|
||||||
folded_depth,
|
folded_depth,
|
||||||
|
@ -3144,22 +3135,10 @@ impl OutlinePanel {
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
};
|
};
|
||||||
|
|
||||||
outline_panel
|
|
||||||
.update(&mut cx, |outline_panel, _| {
|
|
||||||
if matches!(outline_panel.mode, ItemsDisplayMode::Search(_)) {
|
|
||||||
cleanup_fs_entries_without_search_children(
|
|
||||||
&outline_panel.collapsed_entries,
|
|
||||||
&mut entries,
|
|
||||||
&mut match_candidates,
|
|
||||||
&mut added_contexts,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
|
|
||||||
let Some(query) = query else {
|
let Some(query) = query else {
|
||||||
return entries;
|
return entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut matched_ids = match_strings(
|
let mut matched_ids = match_strings(
|
||||||
&match_candidates,
|
&match_candidates,
|
||||||
&query,
|
&query,
|
||||||
|
@ -3195,7 +3174,6 @@ impl OutlinePanel {
|
||||||
&self,
|
&self,
|
||||||
entries: &mut Vec<CachedEntry>,
|
entries: &mut Vec<CachedEntry>,
|
||||||
match_candidates: &mut Vec<StringMatchCandidate>,
|
match_candidates: &mut Vec<StringMatchCandidate>,
|
||||||
added_contexts: &mut HashSet<String>,
|
|
||||||
track_matches: bool,
|
track_matches: bool,
|
||||||
entry: PanelEntry,
|
entry: PanelEntry,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
|
@ -3221,47 +3199,39 @@ impl OutlinePanel {
|
||||||
if let Some(file_name) =
|
if let Some(file_name) =
|
||||||
self.relative_path(fs_entry, cx).as_deref().map(file_name)
|
self.relative_path(fs_entry, cx).as_deref().map(file_name)
|
||||||
{
|
{
|
||||||
if added_contexts.insert(file_name.clone()) {
|
match_candidates.push(StringMatchCandidate {
|
||||||
match_candidates.push(StringMatchCandidate {
|
id,
|
||||||
id,
|
string: file_name.to_string(),
|
||||||
string: file_name.to_string(),
|
char_bag: file_name.chars().collect(),
|
||||||
char_bag: file_name.chars().collect(),
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PanelEntry::FoldedDirs(worktree_id, entries) => {
|
PanelEntry::FoldedDirs(worktree_id, entries) => {
|
||||||
let dir_names = self.dir_names_string(entries, *worktree_id, cx);
|
let dir_names = self.dir_names_string(entries, *worktree_id, cx);
|
||||||
{
|
{
|
||||||
if added_contexts.insert(dir_names.clone()) {
|
match_candidates.push(StringMatchCandidate {
|
||||||
match_candidates.push(StringMatchCandidate {
|
id,
|
||||||
id,
|
string: dir_names.clone(),
|
||||||
string: dir_names.clone(),
|
char_bag: dir_names.chars().collect(),
|
||||||
char_bag: dir_names.chars().collect(),
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PanelEntry::Outline(outline_entry) => match outline_entry {
|
PanelEntry::Outline(outline_entry) => match outline_entry {
|
||||||
OutlineEntry::Outline(_, _, outline) => {
|
OutlineEntry::Outline(_, _, outline) => {
|
||||||
if added_contexts.insert(outline.text.clone()) {
|
match_candidates.push(StringMatchCandidate {
|
||||||
match_candidates.push(StringMatchCandidate {
|
id,
|
||||||
id,
|
string: outline.text.clone(),
|
||||||
string: outline.text.clone(),
|
char_bag: outline.text.chars().collect(),
|
||||||
char_bag: outline.text.chars().collect(),
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
OutlineEntry::Excerpt(..) => {}
|
OutlineEntry::Excerpt(..) => {}
|
||||||
},
|
},
|
||||||
PanelEntry::Search(new_search_entry) => {
|
PanelEntry::Search(new_search_entry) => {
|
||||||
if added_contexts.insert(new_search_entry.render_data.context_text.clone()) {
|
match_candidates.push(StringMatchCandidate {
|
||||||
match_candidates.push(StringMatchCandidate {
|
id,
|
||||||
id,
|
char_bag: new_search_entry.render_data.context_text.chars().collect(),
|
||||||
char_bag: new_search_entry.render_data.context_text.chars().collect(),
|
string: new_search_entry.render_data.context_text.clone(),
|
||||||
string: new_search_entry.render_data.context_text.clone(),
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3408,7 +3378,6 @@ impl OutlinePanel {
|
||||||
query: Option<&str>,
|
query: Option<&str>,
|
||||||
entries: &mut Vec<CachedEntry>,
|
entries: &mut Vec<CachedEntry>,
|
||||||
match_candidates: &mut Vec<StringMatchCandidate>,
|
match_candidates: &mut Vec<StringMatchCandidate>,
|
||||||
added_contexts: &mut HashSet<String>,
|
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) {
|
) {
|
||||||
if let Some(excerpts) = self.excerpts.get(&buffer_id) {
|
if let Some(excerpts) = self.excerpts.get(&buffer_id) {
|
||||||
|
@ -3420,7 +3389,6 @@ impl OutlinePanel {
|
||||||
self.push_entry(
|
self.push_entry(
|
||||||
entries,
|
entries,
|
||||||
match_candidates,
|
match_candidates,
|
||||||
added_contexts,
|
|
||||||
track_matches,
|
track_matches,
|
||||||
PanelEntry::Outline(OutlineEntry::Excerpt(
|
PanelEntry::Outline(OutlineEntry::Excerpt(
|
||||||
buffer_id,
|
buffer_id,
|
||||||
|
@ -3448,7 +3416,6 @@ impl OutlinePanel {
|
||||||
self.push_entry(
|
self.push_entry(
|
||||||
entries,
|
entries,
|
||||||
match_candidates,
|
match_candidates,
|
||||||
added_contexts,
|
|
||||||
track_matches,
|
track_matches,
|
||||||
PanelEntry::Outline(OutlineEntry::Outline(
|
PanelEntry::Outline(OutlineEntry::Outline(
|
||||||
buffer_id,
|
buffer_id,
|
||||||
|
@ -3468,7 +3435,6 @@ impl OutlinePanel {
|
||||||
&mut self,
|
&mut self,
|
||||||
entries: &mut Vec<CachedEntry>,
|
entries: &mut Vec<CachedEntry>,
|
||||||
match_candidates: &mut Vec<StringMatchCandidate>,
|
match_candidates: &mut Vec<StringMatchCandidate>,
|
||||||
added_contexts: &mut HashSet<String>,
|
|
||||||
parent_entry: FsEntry,
|
parent_entry: FsEntry,
|
||||||
parent_depth: usize,
|
parent_depth: usize,
|
||||||
filter_query: Option<String>,
|
filter_query: Option<String>,
|
||||||
|
@ -3556,7 +3522,6 @@ impl OutlinePanel {
|
||||||
self.push_entry(
|
self.push_entry(
|
||||||
entries,
|
entries,
|
||||||
match_candidates,
|
match_candidates,
|
||||||
added_contexts,
|
|
||||||
filter_query.is_some(),
|
filter_query.is_some(),
|
||||||
PanelEntry::Search(new_search_entry),
|
PanelEntry::Search(new_search_entry),
|
||||||
depth,
|
depth,
|
||||||
|
@ -3618,131 +3583,6 @@ impl OutlinePanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cleanup_fs_entries_without_search_children(
|
|
||||||
collapsed_entries: &HashSet<CollapsedEntry>,
|
|
||||||
entries: &mut Vec<CachedEntry>,
|
|
||||||
string_match_candidates: &mut Vec<StringMatchCandidate>,
|
|
||||||
added_contexts: &mut HashSet<String>,
|
|
||||||
) {
|
|
||||||
let mut match_ids_to_remove = BTreeSet::new();
|
|
||||||
let mut previous_entry = None::<&PanelEntry>;
|
|
||||||
for (id, entry) in entries.iter().enumerate().rev() {
|
|
||||||
let has_search_items = match (previous_entry, &entry.entry) {
|
|
||||||
(Some(PanelEntry::Outline(_)), _) => unreachable!(),
|
|
||||||
(_, PanelEntry::Outline(_)) => false,
|
|
||||||
(_, PanelEntry::Search(_)) => true,
|
|
||||||
(None, PanelEntry::FoldedDirs(_, _) | PanelEntry::Fs(_)) => false,
|
|
||||||
(
|
|
||||||
Some(PanelEntry::Search(_)),
|
|
||||||
PanelEntry::FoldedDirs(_, _) | PanelEntry::Fs(FsEntry::Directory(..)),
|
|
||||||
) => false,
|
|
||||||
(Some(PanelEntry::FoldedDirs(..)), PanelEntry::FoldedDirs(..)) => true,
|
|
||||||
(
|
|
||||||
Some(PanelEntry::Search(_)),
|
|
||||||
PanelEntry::Fs(FsEntry::File(..) | FsEntry::ExternalFile(..)),
|
|
||||||
) => true,
|
|
||||||
(
|
|
||||||
Some(PanelEntry::Fs(previous_fs)),
|
|
||||||
PanelEntry::FoldedDirs(folded_worktree, folded_dirs),
|
|
||||||
) => {
|
|
||||||
let expected_parent = folded_dirs.last().map(|dir_entry| dir_entry.path.as_ref());
|
|
||||||
match previous_fs {
|
|
||||||
FsEntry::ExternalFile(..) => false,
|
|
||||||
FsEntry::File(file_worktree, file_entry, ..) => {
|
|
||||||
file_worktree == folded_worktree
|
|
||||||
&& file_entry.path.parent() == expected_parent
|
|
||||||
}
|
|
||||||
FsEntry::Directory(directory_wortree, directory_entry) => {
|
|
||||||
directory_wortree == folded_worktree
|
|
||||||
&& directory_entry.path.parent() == expected_parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(
|
|
||||||
Some(PanelEntry::FoldedDirs(folded_worktree, folded_dirs)),
|
|
||||||
PanelEntry::Fs(fs_entry),
|
|
||||||
) => match fs_entry {
|
|
||||||
FsEntry::File(..) | FsEntry::ExternalFile(..) => false,
|
|
||||||
FsEntry::Directory(directory_wortree, maybe_parent_directory) => {
|
|
||||||
directory_wortree == folded_worktree
|
|
||||||
&& Some(maybe_parent_directory.path.as_ref())
|
|
||||||
== folded_dirs
|
|
||||||
.first()
|
|
||||||
.and_then(|dir_entry| dir_entry.path.parent())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
(Some(PanelEntry::Fs(previous_entry)), PanelEntry::Fs(maybe_parent_entry)) => {
|
|
||||||
match (previous_entry, maybe_parent_entry) {
|
|
||||||
(FsEntry::ExternalFile(..), _) | (_, FsEntry::ExternalFile(..)) => false,
|
|
||||||
(FsEntry::Directory(..) | FsEntry::File(..), FsEntry::File(..)) => false,
|
|
||||||
(
|
|
||||||
FsEntry::Directory(previous_worktree, previous_directory),
|
|
||||||
FsEntry::Directory(new_worktree, maybe_parent_directory),
|
|
||||||
) => {
|
|
||||||
previous_worktree == new_worktree
|
|
||||||
&& previous_directory.path.parent()
|
|
||||||
== Some(maybe_parent_directory.path.as_ref())
|
|
||||||
}
|
|
||||||
(
|
|
||||||
FsEntry::File(previous_worktree, previous_file, ..),
|
|
||||||
FsEntry::Directory(new_worktree, maybe_parent_directory),
|
|
||||||
) => {
|
|
||||||
previous_worktree == new_worktree
|
|
||||||
&& previous_file.path.parent()
|
|
||||||
== Some(maybe_parent_directory.path.as_ref())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if has_search_items {
|
|
||||||
previous_entry = Some(&entry.entry);
|
|
||||||
} else {
|
|
||||||
let collapsed_entries_to_check = match &entry.entry {
|
|
||||||
PanelEntry::FoldedDirs(worktree_id, entries) => entries
|
|
||||||
.iter()
|
|
||||||
.map(|entry| CollapsedEntry::Dir(*worktree_id, entry.id))
|
|
||||||
.collect(),
|
|
||||||
PanelEntry::Fs(FsEntry::Directory(worktree_id, entry)) => {
|
|
||||||
vec![CollapsedEntry::Dir(*worktree_id, entry.id)]
|
|
||||||
}
|
|
||||||
PanelEntry::Fs(FsEntry::ExternalFile(buffer_id, _)) => {
|
|
||||||
vec![CollapsedEntry::ExternalFile(*buffer_id)]
|
|
||||||
}
|
|
||||||
PanelEntry::Fs(FsEntry::File(worktree_id, _, buffer_id, _)) => {
|
|
||||||
vec![CollapsedEntry::File(*worktree_id, *buffer_id)]
|
|
||||||
}
|
|
||||||
PanelEntry::Search(_) | PanelEntry::Outline(_) => Vec::new(),
|
|
||||||
};
|
|
||||||
if !collapsed_entries_to_check.is_empty()
|
|
||||||
&& collapsed_entries_to_check
|
|
||||||
.iter()
|
|
||||||
.any(|collapsed_entry| collapsed_entries.contains(collapsed_entry))
|
|
||||||
{
|
|
||||||
previous_entry = Some(&entry.entry);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
match_ids_to_remove.insert(id);
|
|
||||||
previous_entry = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if match_ids_to_remove.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_match_candidates.retain(|candidate| {
|
|
||||||
let retain = !match_ids_to_remove.contains(&candidate.id);
|
|
||||||
if !retain {
|
|
||||||
added_contexts.remove(&candidate.string);
|
|
||||||
}
|
|
||||||
retain
|
|
||||||
});
|
|
||||||
match_ids_to_remove.into_iter().rev().for_each(|id| {
|
|
||||||
entries.remove(id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn workspace_active_editor(
|
fn workspace_active_editor(
|
||||||
workspace: &Workspace,
|
workspace: &Workspace,
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
|
@ -4374,6 +4214,117 @@ mod tests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_item_filtering(cx: &mut TestAppContext) {
|
||||||
|
init_test(cx);
|
||||||
|
|
||||||
|
let fs = FakeFs::new(cx.background_executor.clone());
|
||||||
|
populate_with_test_ra_project(&fs, "/rust-analyzer").await;
|
||||||
|
let project = Project::test(fs.clone(), ["/rust-analyzer".as_ref()], cx).await;
|
||||||
|
project.read_with(cx, |project, _| {
|
||||||
|
project.languages().add(Arc::new(rust_lang()))
|
||||||
|
});
|
||||||
|
let workspace = add_outline_panel(&project, cx).await;
|
||||||
|
let cx = &mut VisualTestContext::from_window(*workspace, cx);
|
||||||
|
let outline_panel = outline_panel(&workspace, cx);
|
||||||
|
outline_panel.update(cx, |outline_panel, cx| outline_panel.set_active(true, cx));
|
||||||
|
|
||||||
|
workspace
|
||||||
|
.update(cx, |workspace, cx| {
|
||||||
|
ProjectSearchView::deploy_search(workspace, &workspace::DeploySearch::default(), cx)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
let search_view = workspace
|
||||||
|
.update(cx, |workspace, cx| {
|
||||||
|
workspace
|
||||||
|
.active_pane()
|
||||||
|
.read(cx)
|
||||||
|
.items()
|
||||||
|
.find_map(|item| item.downcast::<ProjectSearchView>())
|
||||||
|
.expect("Project search view expected to appear after new search event trigger")
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let query = "param_names_for_lifetime_elision_hints";
|
||||||
|
perform_project_search(&search_view, query, cx);
|
||||||
|
search_view.update(cx, |search_view, cx| {
|
||||||
|
search_view
|
||||||
|
.results_editor()
|
||||||
|
.update(cx, |results_editor, cx| {
|
||||||
|
assert_eq!(
|
||||||
|
results_editor.display_text(cx).match_indices(query).count(),
|
||||||
|
9
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
let all_matches = r#"/
|
||||||
|
crates/
|
||||||
|
ide/src/
|
||||||
|
inlay_hints/
|
||||||
|
fn_lifetime_fn.rs
|
||||||
|
search: match config.param_names_for_lifetime_elision_hints {
|
||||||
|
search: allocated_lifetimes.push(if config.param_names_for_lifetime_elision_hints {
|
||||||
|
search: Some(it) if config.param_names_for_lifetime_elision_hints => {
|
||||||
|
search: InlayHintsConfig { param_names_for_lifetime_elision_hints: true, ..TEST_CONFIG },
|
||||||
|
inlay_hints.rs
|
||||||
|
search: pub param_names_for_lifetime_elision_hints: bool,
|
||||||
|
search: param_names_for_lifetime_elision_hints: self
|
||||||
|
static_index.rs
|
||||||
|
search: param_names_for_lifetime_elision_hints: false,
|
||||||
|
rust-analyzer/src/
|
||||||
|
cli/
|
||||||
|
analysis_stats.rs
|
||||||
|
search: param_names_for_lifetime_elision_hints: true,
|
||||||
|
config.rs
|
||||||
|
search: param_names_for_lifetime_elision_hints: self"#;
|
||||||
|
|
||||||
|
cx.executor()
|
||||||
|
.advance_clock(UPDATE_DEBOUNCE + Duration::from_millis(100));
|
||||||
|
cx.run_until_parked();
|
||||||
|
outline_panel.update(cx, |outline_panel, _| {
|
||||||
|
assert_eq!(
|
||||||
|
display_entries(&outline_panel.cached_entries, None,),
|
||||||
|
all_matches,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
let filter_text = "a";
|
||||||
|
outline_panel.update(cx, |outline_panel, cx| {
|
||||||
|
outline_panel.filter_editor.update(cx, |filter_editor, cx| {
|
||||||
|
filter_editor.set_text(filter_text, cx);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
cx.executor()
|
||||||
|
.advance_clock(UPDATE_DEBOUNCE + Duration::from_millis(100));
|
||||||
|
cx.run_until_parked();
|
||||||
|
|
||||||
|
outline_panel.update(cx, |outline_panel, _| {
|
||||||
|
assert_eq!(
|
||||||
|
display_entries(&outline_panel.cached_entries, None),
|
||||||
|
all_matches
|
||||||
|
.lines()
|
||||||
|
.filter(|item| item.contains(filter_text))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
outline_panel.update(cx, |outline_panel, cx| {
|
||||||
|
outline_panel.filter_editor.update(cx, |filter_editor, cx| {
|
||||||
|
filter_editor.set_text("", cx);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
cx.executor()
|
||||||
|
.advance_clock(UPDATE_DEBOUNCE + Duration::from_millis(100));
|
||||||
|
cx.run_until_parked();
|
||||||
|
outline_panel.update(cx, |outline_panel, _| {
|
||||||
|
assert_eq!(
|
||||||
|
display_entries(&outline_panel.cached_entries, None,),
|
||||||
|
all_matches,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
async fn test_frontend_repo_structure(cx: &mut TestAppContext) {
|
async fn test_frontend_repo_structure(cx: &mut TestAppContext) {
|
||||||
init_test(cx);
|
init_test(cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue