Move `DidSaveTextDocument` notification from `Buffer` to `Project`

Antonio Scandurra created

Change summary

crates/language/src/buffer.rs | 20 --------------------
crates/project/src/project.rs | 36 +++++++++++++++++++++++++++++++-----
2 files changed, 31 insertions(+), 25 deletions(-)

Detailed changes

crates/language/src/buffer.rs 🔗

@@ -691,26 +691,6 @@ impl Buffer {
             self.file = Some(new_file);
             self.file_update_count += 1;
         }
-        if let Some((state, local_file)) = &self
-            .language_server
-            .as_ref()
-            .zip(self.file.as_ref().and_then(|f| f.as_local()))
-        {
-            cx.background()
-                .spawn(
-                    state
-                        .server
-                        .notify::<lsp::notification::DidSaveTextDocument>(
-                            lsp::DidSaveTextDocumentParams {
-                                text_document: lsp::TextDocumentIdentifier {
-                                    uri: lsp::Url::from_file_path(local_file.abs_path(cx)).unwrap(),
-                                },
-                                text: None,
-                            },
-                        ),
-                )
-                .detach()
-        }
         cx.emit(Event::Saved);
         cx.notify();
     }

crates/project/src/project.rs 🔗

@@ -964,11 +964,37 @@ impl Project {
                         buffer_id: buffer.read(cx).remote_id(),
                         operations: vec![language::proto::serialize_operation(&operation)],
                     });
-                    cx.foreground()
-                        .spawn(async move {
-                            request.await.log_err();
-                        })
-                        .detach();
+                    cx.background().spawn(request).detach_and_log_err(cx);
+                }
+            }
+            BufferEvent::Saved => {
+                if let Some(file) = File::from_dyn(buffer.read(cx).file()) {
+                    let worktree_id = file.worktree_id(cx);
+                    if let Some(abs_path) = file.as_local().map(|file| file.abs_path(cx)) {
+                        let text_document = lsp::TextDocumentIdentifier {
+                            uri: lsp::Url::from_file_path(abs_path).unwrap(),
+                        };
+
+                        let mut notifications = Vec::new();
+                        for ((lang_server_worktree_id, _), lang_server) in &self.language_servers {
+                            if *lang_server_worktree_id != worktree_id {
+                                continue;
+                            }
+
+                            notifications.push(
+                                lang_server.notify::<lsp::notification::DidSaveTextDocument>(
+                                    lsp::DidSaveTextDocumentParams {
+                                        text_document: text_document.clone(),
+                                        text: None,
+                                    },
+                                ),
+                            );
+                        }
+
+                        cx.background()
+                            .spawn(futures::future::try_join_all(notifications))
+                            .detach_and_log_err(cx);
+                    }
                 }
             }
             _ => {}