Do not resubscribe for Copilot logs events (#3014)

Kirill Bulatov created

Last follow-up of https://github.com/zed-industries/zed/pull/3002
Fixes
https://zed-industries.slack.com/archives/C04S6T1T7TQ/p1695281196667609

Copilot sends multiple events about its LSP server readiness, not
necessarily recreating the server from scratch (e.g. due to re-sign in
action). Avoid re-adding same log subscriptions on the same LSP server,
which causes panics.

Release Notes:

- N/A

Change summary

crates/language_tools/src/lsp_log.rs | 7 +++++++
crates/lsp/src/lsp.rs                | 4 ++++
2 files changed, 11 insertions(+)

Detailed changes

crates/language_tools/src/lsp_log.rs 🔗

@@ -181,6 +181,13 @@ impl LogStore {
         });
 
         let server = project.read(cx).language_server_for_id(id);
+        if let Some(server) = server.as_deref() {
+            if server.has_notification_handler::<lsp::notification::LogMessage>() {
+                // Another event wants to re-add the server that was already added and subscribed to, avoid doing it again.
+                return Some(server_state.log_buffer.clone());
+            }
+        }
+
         let weak_project = project.downgrade();
         let io_tx = self.io_tx.clone();
         server_state._io_logs_subscription = server.as_ref().map(|server| {

crates/lsp/src/lsp.rs 🔗

@@ -605,6 +605,10 @@ impl LanguageServer {
         self.notification_handlers.lock().remove(T::METHOD);
     }
 
+    pub fn has_notification_handler<T: notification::Notification>(&self) -> bool {
+        self.notification_handlers.lock().contains_key(T::METHOD)
+    }
+
     #[must_use]
     pub fn on_custom_notification<Params, F>(&self, method: &'static str, mut f: F) -> Subscription
     where