Improve outline panel performance (#17183)

Part of https://github.com/zed-industries/zed/issues/14235

* moved search results highlight calculation into the background thread,
with highlight-less representation as a fallback
* show only a part of the line per search result, stop uniting them into
a single line if possible, always trim left trailing whitespaces
* highlight results in batches
* better cache all search result data, related to rendering
* add test infra and fix folding-related issues
* improve entry displays when multi buffer has a buffer search (find
references one has)
* fix cloud notes not showing search matches

Release Notes:

- Improved outline panel performance
This commit is contained in:
Kirill Bulatov 2024-09-02 01:46:16 +03:00 committed by GitHub
parent 16942610cb
commit d682594c4a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 1767 additions and 675 deletions

594
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -30,10 +30,15 @@ search.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
settings.workspace = true settings.workspace = true
smol.workspace = true
theme.workspace = true theme.workspace = true
util.workspace = true util.workspace = true
worktree.workspace = true worktree.workspace = true
workspace.workspace = true workspace.workspace = true
[dev-dependencies]
search = { workspace = true, features = ["test-support"] }
pretty_assertions.workspace = true
[package.metadata.cargo-machete] [package.metadata.cargo-machete]
ignored = ["log"] ignored = ["log"]

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,14 @@ edition = "2021"
publish = false publish = false
license = "GPL-3.0-or-later" license = "GPL-3.0-or-later"
[features]
test-support = [
"client/test-support",
"editor/test-support",
"gpui/test-support",
"workspace/test-support",
]
[lints] [lints]
workspace = true workspace = true

View file

@ -114,7 +114,7 @@ pub fn init(cx: &mut AppContext) {
.detach(); .detach();
} }
struct ProjectSearch { pub struct ProjectSearch {
project: Model<Project>, project: Model<Project>,
excerpts: Model<MultiBuffer>, excerpts: Model<MultiBuffer>,
pending_search: Option<Task<Option<()>>>, pending_search: Option<Task<Option<()>>>,
@ -154,7 +154,7 @@ pub struct ProjectSearchView {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct ProjectSearchSettings { pub struct ProjectSearchSettings {
search_options: SearchOptions, search_options: SearchOptions,
filters_enabled: bool, filters_enabled: bool,
} }
@ -165,7 +165,7 @@ pub struct ProjectSearchBar {
} }
impl ProjectSearch { impl ProjectSearch {
fn new(project: Model<Project>, cx: &mut ModelContext<Self>) -> Self { pub fn new(project: Model<Project>, cx: &mut ModelContext<Self>) -> Self {
let replica_id = project.read(cx).replica_id(); let replica_id = project.read(cx).replica_id();
let capability = project.read(cx).capability(); let capability = project.read(cx).capability();
@ -612,7 +612,7 @@ impl ProjectSearchView {
}); });
} }
fn new( pub fn new(
workspace: WeakView<Workspace>, workspace: WeakView<Workspace>,
model: Model<ProjectSearch>, model: Model<ProjectSearch>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
@ -763,9 +763,9 @@ impl ProjectSearchView {
}); });
} }
// Re-activate the most recently activated search in this pane or the most recent if it has been closed. /// Re-activate the most recently activated search in this pane or the most recent if it has been closed.
// If no search exists in the workspace, create a new one. /// If no search exists in the workspace, create a new one.
fn deploy_search( pub fn deploy_search(
workspace: &mut Workspace, workspace: &mut Workspace,
action: &workspace::DeploySearch, action: &workspace::DeploySearch,
cx: &mut ViewContext<Workspace>, cx: &mut ViewContext<Workspace>,
@ -1179,6 +1179,11 @@ impl ProjectSearchView {
return self.focus_results_editor(cx); return self.focus_results_editor(cx);
} }
} }
#[cfg(any(test, feature = "test-support"))]
pub fn results_editor(&self) -> &View<Editor> {
&self.results_editor
}
} }
impl ProjectSearchBar { impl ProjectSearchBar {
@ -1823,15 +1828,31 @@ fn register_workspace_action_for_present_search<A: Action>(
}); });
} }
#[cfg(any(test, feature = "test-support"))]
pub fn perform_project_search(
search_view: &View<ProjectSearchView>,
text: impl Into<std::sync::Arc<str>>,
cx: &mut gpui::VisualTestContext,
) {
search_view.update(cx, |search_view, cx| {
search_view
.query_editor
.update(cx, |query_editor, cx| query_editor.set_text(text, cx));
search_view.search(cx);
});
cx.run_until_parked();
}
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use std::sync::Arc;
use super::*; use super::*;
use editor::{display_map::DisplayRow, DisplayPoint}; use editor::{display_map::DisplayRow, DisplayPoint};
use gpui::{Action, TestAppContext, WindowHandle}; use gpui::{Action, TestAppContext, WindowHandle};
use project::FakeFs; use project::FakeFs;
use serde_json::json; use serde_json::json;
use settings::SettingsStore; use settings::SettingsStore;
use std::sync::Arc;
use workspace::DeploySearch; use workspace::DeploySearch;
#[gpui::test] #[gpui::test]

View file

@ -118,7 +118,7 @@ pub struct RevealInProjectPanel {
pub entry_id: Option<u64>, pub entry_id: Option<u64>,
} }
#[derive(PartialEq, Clone, Deserialize)] #[derive(Default, PartialEq, Clone, Deserialize)]
pub struct DeploySearch { pub struct DeploySearch {
#[serde(default)] #[serde(default)]
pub replace_enabled: bool, pub replace_enabled: bool,