Start to split out initialization and registration (#21787)

Still TODO:

* [x] Factor out `start_language_server` so we can call it on register
(instead of on detect language)
* [x] Only call register in singleton editors (or when
editing/go-to-definition etc. in a multibuffer?)
* [x] Refcount on register so we can unregister when no buffer remain
* [ ] (maybe) Stop language servers that are no longer needed after some
time

Release Notes:

- Fixed language servers starting when doing project search
- Fixed high CPU usage when ignoring warnings in the diagnostics view

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: Cole <cole@zed.dev>
This commit is contained in:
Conrad Irwin 2024-12-11 14:05:10 -07:00 committed by GitHub
parent de89f8cf83
commit 13a81e454a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 2200 additions and 1848 deletions

View file

@ -129,10 +129,10 @@ use multi_buffer::{
};
use parking_lot::RwLock;
use project::{
lsp_store::{FormatTarget, FormatTrigger},
lsp_store::{FormatTarget, FormatTrigger, OpenLspBufferHandle},
project_settings::{GitGutterSetting, ProjectSettings},
CodeAction, Completion, CompletionIntent, DocumentHighlight, InlayHint, Location, LocationLink,
Project, ProjectItem, ProjectTransaction, TaskSourceKind,
LspStore, Project, ProjectItem, ProjectTransaction, TaskSourceKind,
};
use rand::prelude::*;
use rpc::{proto::*, ErrorExt};
@ -663,6 +663,7 @@ pub struct Editor {
focused_block: Option<FocusedBlock>,
next_scroll_position: NextScrollCursorCenterTopBottom,
addons: HashMap<TypeId, Box<dyn Addon>>,
registered_buffers: HashMap<BufferId, OpenLspBufferHandle>,
_scroll_cursor_center_top_bottom_task: Task<()>,
}
@ -1308,6 +1309,7 @@ impl Editor {
focused_block: None,
next_scroll_position: NextScrollCursorCenterTopBottom::default(),
addons: HashMap::default(),
registered_buffers: HashMap::default(),
_scroll_cursor_center_top_bottom_task: Task::ready(()),
text_style_refinement: None,
};
@ -1325,6 +1327,17 @@ impl Editor {
this.git_blame_inline_enabled = true;
this.start_git_blame_inline(false, cx);
}
if let Some(buffer) = buffer.read(cx).as_singleton() {
if let Some(project) = this.project.as_ref() {
let lsp_store = project.read(cx).lsp_store();
let handle = lsp_store.update(cx, |lsp_store, cx| {
lsp_store.register_buffer_with_language_servers(&buffer, cx)
});
this.registered_buffers
.insert(buffer.read(cx).remote_id(), handle);
}
}
}
this.report_editor_event("open", None, cx);
@ -1635,6 +1648,22 @@ impl Editor {
self.collapse_matches = collapse_matches;
}
pub fn register_buffers_with_language_servers(&mut self, cx: &mut ViewContext<Self>) {
let buffers = self.buffer.read(cx).all_buffers();
let Some(lsp_store) = self.lsp_store(cx) else {
return;
};
lsp_store.update(cx, |lsp_store, cx| {
for buffer in buffers {
self.registered_buffers
.entry(buffer.read(cx).remote_id())
.or_insert_with(|| {
lsp_store.register_buffer_with_language_servers(&buffer, cx)
});
}
})
}
pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
if self.collapse_matches {
return range.start..range.start;
@ -9642,6 +9671,7 @@ impl Editor {
|theme| theme.editor_highlighted_line_background,
cx,
);
editor.register_buffers_with_language_servers(cx);
});
let item = Box::new(editor);
@ -11838,6 +11868,12 @@ impl Editor {
cx.notify();
}
pub fn lsp_store(&self, cx: &AppContext) -> Option<Model<LspStore>> {
self.project
.as_ref()
.map(|project| project.read(cx).lsp_store())
}
fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
cx.notify();
}
@ -11851,6 +11887,7 @@ impl Editor {
match event {
multi_buffer::Event::Edited {
singleton_buffer_edited,
edited_buffer: buffer_edited,
} => {
self.scrollbar_marker_state.dirty = true;
self.active_indent_guides_state.dirty = true;
@ -11859,6 +11896,19 @@ impl Editor {
if self.has_active_inline_completion() {
self.update_visible_inline_completion(cx);
}
if let Some(buffer) = buffer_edited {
let buffer_id = buffer.read(cx).remote_id();
if !self.registered_buffers.contains_key(&buffer_id) {
if let Some(lsp_store) = self.lsp_store(cx) {
lsp_store.update(cx, |lsp_store, cx| {
self.registered_buffers.insert(
buffer_id,
lsp_store.register_buffer_with_language_servers(&buffer, cx),
);
})
}
}
}
cx.emit(EditorEvent::BufferEdited);
cx.emit(SearchEvent::MatchesInvalidated);
if *singleton_buffer_edited {
@ -11925,6 +11975,9 @@ impl Editor {
}
multi_buffer::Event::ExcerptsRemoved { ids } => {
self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
let buffer = self.buffer.read(cx);
self.registered_buffers
.retain(|buffer_id, _| buffer.buffer(*buffer_id).is_some());
cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
}
multi_buffer::Event::ExcerptsEdited { ids } => {