Properly dedup restarts of language servers

Keith Simmons created

Change summary

crates/editor/src/editor.rs       | 11 ++++-------
crates/project/src/project.rs     | 26 +++++++++++++++++---------
crates/workspace/src/workspace.rs |  6 ------
3 files changed, 21 insertions(+), 22 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -4871,14 +4871,11 @@ impl Editor {
     }
 
     fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
-        let project = self.project.clone();
-        if let Some(project) = project {
+        if let Some(project) = self.project.clone() {
             self.buffer.update(cx, |multi_buffer, cx| {
-                for buffer in multi_buffer.all_buffers() {
-                    project.update(cx, |project, cx| {
-                        project.restart_language_server_for_buffer(&buffer, cx);
-                    });
-                }
+                project.update(cx, |project, cx| {
+                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
+                });
             })
         }
     }

crates/project/src/project.rs 🔗

@@ -1508,18 +1508,26 @@ impl Project {
             });
     }
 
-    pub fn restart_language_server_for_buffer(
+    pub fn restart_language_servers_for_buffers(
         &mut self,
-        buffer: &ModelHandle<Buffer>,
+        buffers: impl IntoIterator<Item = ModelHandle<Buffer>>,
         cx: &mut ModelContext<Self>,
     ) -> Option<()> {
-        let file = File::from_dyn(buffer.read(cx).file())?;
-        let worktree = file.worktree.read(cx).as_local()?;
-        let worktree_id = worktree.id();
-        let worktree_abs_path = worktree.abs_path().clone();
-        let full_path = buffer.read(cx).file()?.full_path(cx);
-        let language = self.languages.select_language(&full_path)?;
-        self.restart_language_server(worktree_id, worktree_abs_path, language, cx);
+        let language_server_lookup_info: HashSet<(WorktreeId, Arc<Path>, PathBuf)> = buffers
+            .into_iter()
+            .filter_map(|buffer| {
+                let file = File::from_dyn(buffer.read(cx).file())?;
+                let worktree = file.worktree.read(cx).as_local()?;
+                let worktree_id = worktree.id();
+                let worktree_abs_path = worktree.abs_path().clone();
+                let full_path = file.full_path(cx);
+                Some((worktree_id, worktree_abs_path, full_path))
+            })
+            .collect();
+        for (worktree_id, worktree_abs_path, full_path) in language_server_lookup_info {
+            let language = self.languages.select_language(&full_path)?;
+            self.restart_language_server(worktree_id, worktree_abs_path, language, cx);
+        }
 
         None
     }

crates/workspace/src/workspace.rs 🔗

@@ -80,7 +80,6 @@ action!(Save);
 action!(DebugElements);
 action!(ActivatePreviousPane);
 action!(ActivateNextPane);
-action!(RestartLanguageServer);
 
 pub fn init(client: &Arc<Client>, cx: &mut MutableAppContext) {
     pane::init(cx);
@@ -120,9 +119,6 @@ pub fn init(client: &Arc<Client>, cx: &mut MutableAppContext) {
     cx.add_action(|workspace: &mut Workspace, _: &ActivateNextPane, cx| {
         workspace.activate_next_pane(cx)
     });
-    cx.add_action(|workspace: &mut Workspace, _: &RestartLanguageServer, cx| {
-        workspace.restart_language_server(cx)
-    });
     cx.add_bindings(vec![
         Binding::new("ctrl-alt-cmd-f", FollowNextCollaborator, None),
         Binding::new("cmd-s", Save, None),
@@ -1423,8 +1419,6 @@ impl Workspace {
         None
     }
 
-    fn restart_language_server(&mut self, cx: &mut ViewContext<Self>) {}
-
     fn render_connection_status(&self, cx: &mut RenderContext<Self>) -> Option<ElementBox> {
         let theme = &cx.global::<Settings>().theme;
         match &*self.client.status().borrow() {