From 03ba256d965ceee031d3e2221286b77ce4b91c27 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 26 Aug 2025 10:39:57 +0300 Subject: [PATCH] Fix ssh message sending --- crates/language_tools/src/lsp_log.rs | 158 ++++++++++++------- crates/remote_server/src/headless_project.rs | 4 +- 2 files changed, 102 insertions(+), 60 deletions(-) diff --git a/crates/language_tools/src/lsp_log.rs b/crates/language_tools/src/lsp_log.rs index 054ae44317..5a52a103a6 100644 --- a/crates/language_tools/src/lsp_log.rs +++ b/crates/language_tools/src/lsp_log.rs @@ -12,7 +12,9 @@ use lsp::{ IoKind, LanguageServer, LanguageServerBinary, LanguageServerName, LanguageServerSelector, MessageType, SetTraceParams, TraceValue, notification::SetTrace, }; -use project::{Project, WorktreeId, lsp_store::LanguageServerLogType, search::SearchQuery}; +use project::{ + LspStore, Project, WorktreeId, lsp_store::LanguageServerLogType, search::SearchQuery, +}; use std::{any::TypeId, borrow::Cow, sync::Arc}; use ui::{Button, Checkbox, ContextMenu, Label, PopoverMenu, ToggleState, prelude::*}; use util::ResultExt as _; @@ -128,6 +130,7 @@ pub struct LanguageServerState { pub enum LanguageServerKind { Local { project: WeakEntity }, Remote { project: WeakEntity }, + LocalSsh { lsp_store: WeakEntity }, Global, } @@ -136,6 +139,7 @@ impl std::fmt::Debug for LanguageServerKind { match self { LanguageServerKind::Local { .. } => write!(f, "LanguageServerKind::Local"), LanguageServerKind::Remote { .. } => write!(f, "LanguageServerKind::Remote"), + LanguageServerKind::LocalSsh { .. } => write!(f, "LanguageServerKind::LocalSsh"), LanguageServerKind::Global => write!(f, "LanguageServerKind::Global"), } } @@ -146,6 +150,7 @@ impl LanguageServerKind { match self { Self::Local { project } => Some(project), Self::Remote { project } => Some(project), + Self::LocalSsh { .. } => None, Self::Global { .. } => None, } } @@ -264,13 +269,13 @@ impl LogStore { && let Some(server) = copilot.read(cx).language_server() { let server_id = server.server_id(); - let weak_this = cx.weak_entity(); + let weak_lsp_store = cx.weak_entity(); log_store.copilot_log_subscription = Some(server.on_notification::( move |params, cx| { - weak_this - .update(cx, |this, cx| { - this.add_language_server_log( + weak_lsp_store + .update(cx, |lsp_store, cx| { + lsp_store.add_language_server_log( server_id, MessageType::LOG, ¶ms.message, @@ -460,21 +465,27 @@ impl LogStore { let message = message.trim_end().to_string(); if !store_logs { // Send all messages regardless of the visibility in case of not storing, to notify the receiver anyway - cx.emit(Event::NewServerLogEntry { - id, - kind: LanguageServerLogType::Log(typ), - text: message, - }); + self.emit_event( + Event::NewServerLogEntry { + id, + kind: LanguageServerLogType::Log(typ), + text: message, + }, + cx, + ); } else if let Some(new_message) = Self::push_new_message( log_lines, LogMessage { message, typ }, language_server_state.log_level, ) { - cx.emit(Event::NewServerLogEntry { - id, - kind: LanguageServerLogType::Log(typ), - text: new_message, - }); + self.emit_event( + Event::NewServerLogEntry { + id, + kind: LanguageServerLogType::Log(typ), + text: new_message, + }, + cx, + ); } Some(()) } @@ -492,11 +503,14 @@ impl LogStore { let log_lines = &mut language_server_state.trace_messages; if !store_logs { // Send all messages regardless of the visibility in case of not storing, to notify the receiver anyway - cx.emit(Event::NewServerLogEntry { - id, - kind: LanguageServerLogType::Trace { verbose_info }, - text: message.trim().to_string(), - }); + self.emit_event( + Event::NewServerLogEntry { + id, + kind: LanguageServerLogType::Trace { verbose_info }, + text: message.trim().to_string(), + }, + cx, + ); } else if let Some(new_message) = Self::push_new_message( log_lines, TraceMessage { @@ -515,11 +529,14 @@ impl LogStore { TraceValue::Verbose, ); } - cx.emit(Event::NewServerLogEntry { - id, - kind: LanguageServerLogType::Trace { verbose_info }, - text: new_message, - }); + self.emit_event( + Event::NewServerLogEntry { + id, + kind: LanguageServerLogType::Trace { verbose_info }, + text: new_message, + }, + cx, + ); } Some(()) } @@ -544,7 +561,7 @@ impl LogStore { language_server_id: LanguageServerId, kind: MessageKind, message: &str, - cx: &mut Context<'_, LogStore>, + cx: &mut Context<'_, Self>, ) { let store_logs = self.store_logs; let Some(state) = self @@ -554,6 +571,7 @@ impl LogStore { return; }; + let mut line_before_message_to_send = None; let rpc_log_lines = &mut state.rpc_messages; if state.last_message_kind != Some(kind) { while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES { @@ -568,13 +586,7 @@ impl LogStore { message: line_before_message.to_string(), }); } - cx.emit(Event::NewServerLogEntry { - id: language_server_id, - kind: LanguageServerLogType::Rpc { - received: kind == MessageKind::Receive, - }, - text: line_before_message.to_string(), - }); + line_before_message_to_send = Some(line_before_message); } while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES { @@ -587,14 +599,25 @@ impl LogStore { }); } - log::error!("|||||||||| {message}"); - cx.emit(Event::NewServerLogEntry { - id: language_server_id, - kind: LanguageServerLogType::Rpc { - received: kind == MessageKind::Receive, + let received = kind == MessageKind::Receive; + if let Some(line_before_message) = line_before_message_to_send { + self.emit_event( + Event::NewServerLogEntry { + id: language_server_id, + kind: LanguageServerLogType::Rpc { received }, + text: line_before_message.to_string(), + }, + cx, + ); + } + self.emit_event( + Event::NewServerLogEntry { + id: language_server_id, + kind: LanguageServerLogType::Rpc { received }, + text: message.to_owned(), }, - text: message.to_owned(), - }); + cx, + ); } pub fn remove_language_server(&mut self, id: LanguageServerId, cx: &mut Context) { @@ -627,7 +650,7 @@ impl LogStore { None } } - LanguageServerKind::Global => Some(*id), + LanguageServerKind::Global | LanguageServerKind::LocalSsh { .. } => Some(*id), }) } @@ -784,6 +807,37 @@ impl LogStore { cx.notify(); Some(()) } + + fn emit_event(&mut self, e: Event, cx: &mut Context) { + match &e { + Event::NewServerLogEntry { id, kind, text } => { + if let Some(state) = self.get_language_server_state(*id) { + let downstream_client = match &state.kind { + LanguageServerKind::Remote { project } + | LanguageServerKind::Local { project } => project + .upgrade() + .map(|project| project.read(cx).lsp_store()), + LanguageServerKind::LocalSsh { lsp_store } => lsp_store.upgrade(), + LanguageServerKind::Global => None, + } + .and_then(|lsp_store| lsp_store.read(cx).downstream_client()); + if let Some((client, project_id)) = downstream_client { + log::error!("|||||||||| {text}"); + client + .send(proto::LanguageServerLog { + project_id, + language_server_id: id.to_proto(), + message: text.clone(), + log_type: Some(kind.to_proto()), + }) + .ok(); + } + } + } + } + + cx.emit(e); + } } impl LspLogView { @@ -828,27 +882,11 @@ impl LspLogView { cx.notify(); }); - let weak_lsp_store = project.read(cx).lsp_store().downgrade(); let events_subscriptions = cx.subscribe_in(&log_store, window, move |log_view, _, e, window, cx| { - log::error!("||||||||@@@@|| {e:?}"); + log::error!("@@@@@@ {e:?}"); match e { Event::NewServerLogEntry { id, kind, text } => { - weak_lsp_store - .update(cx, |lsp_store, _| { - if let Some((client, project_id)) = lsp_store.downstream_client() { - client - .send(proto::LanguageServerLog { - project_id, - language_server_id: id.to_proto(), - message: text.clone(), - log_type: Some(kind.to_proto()), - }) - .log_err(); - }; - }) - .ok(); - if log_view.current_server_id == Some(*id) && LogKind::from_server_log_type(kind) == log_view.active_entry_kind { @@ -983,7 +1021,9 @@ impl LspLogView { .language_servers .iter() .map(|(server_id, state)| match &state.kind { - LanguageServerKind::Local { .. } | LanguageServerKind::Remote { .. } => { + LanguageServerKind::Local { .. } + | LanguageServerKind::Remote { .. } + | LanguageServerKind::LocalSsh { .. } => { let worktree_root_name = state .worktree_id .and_then(|id| self.project.read(cx).worktree_for_id(id, cx)) diff --git a/crates/remote_server/src/headless_project.rs b/crates/remote_server/src/headless_project.rs index 5156dda246..71eeaede15 100644 --- a/crates/remote_server/src/headless_project.rs +++ b/crates/remote_server/src/headless_project.rs @@ -314,7 +314,9 @@ impl HeadlessProject { if let Some(log_store) = log_store { log_store.update(cx, |log_store, cx| { log_store.add_language_server( - LanguageServerKind::Global, + LanguageServerKind::LocalSsh { + lsp_store: self.lsp_store.downgrade(), + }, *id, Some(name.clone()), *worktree_id,