Fix ssh message sending

This commit is contained in:
Kirill Bulatov 2025-08-26 10:39:57 +03:00
parent 679c24282d
commit 03ba256d96
2 changed files with 102 additions and 60 deletions

View file

@ -12,7 +12,9 @@ use lsp::{
IoKind, LanguageServer, LanguageServerBinary, LanguageServerName, LanguageServerSelector, IoKind, LanguageServer, LanguageServerBinary, LanguageServerName, LanguageServerSelector,
MessageType, SetTraceParams, TraceValue, notification::SetTrace, 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 std::{any::TypeId, borrow::Cow, sync::Arc};
use ui::{Button, Checkbox, ContextMenu, Label, PopoverMenu, ToggleState, prelude::*}; use ui::{Button, Checkbox, ContextMenu, Label, PopoverMenu, ToggleState, prelude::*};
use util::ResultExt as _; use util::ResultExt as _;
@ -128,6 +130,7 @@ pub struct LanguageServerState {
pub enum LanguageServerKind { pub enum LanguageServerKind {
Local { project: WeakEntity<Project> }, Local { project: WeakEntity<Project> },
Remote { project: WeakEntity<Project> }, Remote { project: WeakEntity<Project> },
LocalSsh { lsp_store: WeakEntity<LspStore> },
Global, Global,
} }
@ -136,6 +139,7 @@ impl std::fmt::Debug for LanguageServerKind {
match self { match self {
LanguageServerKind::Local { .. } => write!(f, "LanguageServerKind::Local"), LanguageServerKind::Local { .. } => write!(f, "LanguageServerKind::Local"),
LanguageServerKind::Remote { .. } => write!(f, "LanguageServerKind::Remote"), LanguageServerKind::Remote { .. } => write!(f, "LanguageServerKind::Remote"),
LanguageServerKind::LocalSsh { .. } => write!(f, "LanguageServerKind::LocalSsh"),
LanguageServerKind::Global => write!(f, "LanguageServerKind::Global"), LanguageServerKind::Global => write!(f, "LanguageServerKind::Global"),
} }
} }
@ -146,6 +150,7 @@ impl LanguageServerKind {
match self { match self {
Self::Local { project } => Some(project), Self::Local { project } => Some(project),
Self::Remote { project } => Some(project), Self::Remote { project } => Some(project),
Self::LocalSsh { .. } => None,
Self::Global { .. } => None, Self::Global { .. } => None,
} }
} }
@ -264,13 +269,13 @@ impl LogStore {
&& let Some(server) = copilot.read(cx).language_server() && let Some(server) = copilot.read(cx).language_server()
{ {
let server_id = server.server_id(); let server_id = server.server_id();
let weak_this = cx.weak_entity(); let weak_lsp_store = cx.weak_entity();
log_store.copilot_log_subscription = log_store.copilot_log_subscription =
Some(server.on_notification::<copilot::request::LogMessage, _>( Some(server.on_notification::<copilot::request::LogMessage, _>(
move |params, cx| { move |params, cx| {
weak_this weak_lsp_store
.update(cx, |this, cx| { .update(cx, |lsp_store, cx| {
this.add_language_server_log( lsp_store.add_language_server_log(
server_id, server_id,
MessageType::LOG, MessageType::LOG,
&params.message, &params.message,
@ -460,21 +465,27 @@ impl LogStore {
let message = message.trim_end().to_string(); let message = message.trim_end().to_string();
if !store_logs { if !store_logs {
// Send all messages regardless of the visibility in case of not storing, to notify the receiver anyway // Send all messages regardless of the visibility in case of not storing, to notify the receiver anyway
cx.emit(Event::NewServerLogEntry { self.emit_event(
id, Event::NewServerLogEntry {
kind: LanguageServerLogType::Log(typ), id,
text: message, kind: LanguageServerLogType::Log(typ),
}); text: message,
},
cx,
);
} else if let Some(new_message) = Self::push_new_message( } else if let Some(new_message) = Self::push_new_message(
log_lines, log_lines,
LogMessage { message, typ }, LogMessage { message, typ },
language_server_state.log_level, language_server_state.log_level,
) { ) {
cx.emit(Event::NewServerLogEntry { self.emit_event(
id, Event::NewServerLogEntry {
kind: LanguageServerLogType::Log(typ), id,
text: new_message, kind: LanguageServerLogType::Log(typ),
}); text: new_message,
},
cx,
);
} }
Some(()) Some(())
} }
@ -492,11 +503,14 @@ impl LogStore {
let log_lines = &mut language_server_state.trace_messages; let log_lines = &mut language_server_state.trace_messages;
if !store_logs { if !store_logs {
// Send all messages regardless of the visibility in case of not storing, to notify the receiver anyway // Send all messages regardless of the visibility in case of not storing, to notify the receiver anyway
cx.emit(Event::NewServerLogEntry { self.emit_event(
id, Event::NewServerLogEntry {
kind: LanguageServerLogType::Trace { verbose_info }, id,
text: message.trim().to_string(), kind: LanguageServerLogType::Trace { verbose_info },
}); text: message.trim().to_string(),
},
cx,
);
} else if let Some(new_message) = Self::push_new_message( } else if let Some(new_message) = Self::push_new_message(
log_lines, log_lines,
TraceMessage { TraceMessage {
@ -515,11 +529,14 @@ impl LogStore {
TraceValue::Verbose, TraceValue::Verbose,
); );
} }
cx.emit(Event::NewServerLogEntry { self.emit_event(
id, Event::NewServerLogEntry {
kind: LanguageServerLogType::Trace { verbose_info }, id,
text: new_message, kind: LanguageServerLogType::Trace { verbose_info },
}); text: new_message,
},
cx,
);
} }
Some(()) Some(())
} }
@ -544,7 +561,7 @@ impl LogStore {
language_server_id: LanguageServerId, language_server_id: LanguageServerId,
kind: MessageKind, kind: MessageKind,
message: &str, message: &str,
cx: &mut Context<'_, LogStore>, cx: &mut Context<'_, Self>,
) { ) {
let store_logs = self.store_logs; let store_logs = self.store_logs;
let Some(state) = self let Some(state) = self
@ -554,6 +571,7 @@ impl LogStore {
return; return;
}; };
let mut line_before_message_to_send = None;
let rpc_log_lines = &mut state.rpc_messages; let rpc_log_lines = &mut state.rpc_messages;
if state.last_message_kind != Some(kind) { if state.last_message_kind != Some(kind) {
while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES { while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
@ -568,13 +586,7 @@ impl LogStore {
message: line_before_message.to_string(), message: line_before_message.to_string(),
}); });
} }
cx.emit(Event::NewServerLogEntry { line_before_message_to_send = Some(line_before_message);
id: language_server_id,
kind: LanguageServerLogType::Rpc {
received: kind == MessageKind::Receive,
},
text: line_before_message.to_string(),
});
} }
while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES { while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
@ -587,14 +599,25 @@ impl LogStore {
}); });
} }
log::error!("|||||||||| {message}"); let received = kind == MessageKind::Receive;
cx.emit(Event::NewServerLogEntry { if let Some(line_before_message) = line_before_message_to_send {
id: language_server_id, self.emit_event(
kind: LanguageServerLogType::Rpc { Event::NewServerLogEntry {
received: kind == MessageKind::Receive, 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<Self>) { pub fn remove_language_server(&mut self, id: LanguageServerId, cx: &mut Context<Self>) {
@ -627,7 +650,7 @@ impl LogStore {
None None
} }
} }
LanguageServerKind::Global => Some(*id), LanguageServerKind::Global | LanguageServerKind::LocalSsh { .. } => Some(*id),
}) })
} }
@ -784,6 +807,37 @@ impl LogStore {
cx.notify(); cx.notify();
Some(()) Some(())
} }
fn emit_event(&mut self, e: Event, cx: &mut Context<Self>) {
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 { impl LspLogView {
@ -828,27 +882,11 @@ impl LspLogView {
cx.notify(); cx.notify();
}); });
let weak_lsp_store = project.read(cx).lsp_store().downgrade();
let events_subscriptions = let events_subscriptions =
cx.subscribe_in(&log_store, window, move |log_view, _, e, window, cx| { cx.subscribe_in(&log_store, window, move |log_view, _, e, window, cx| {
log::error!("||||||||@@@@|| {e:?}"); log::error!("@@@@@@ {e:?}");
match e { match e {
Event::NewServerLogEntry { id, kind, text } => { 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) if log_view.current_server_id == Some(*id)
&& LogKind::from_server_log_type(kind) == log_view.active_entry_kind && LogKind::from_server_log_type(kind) == log_view.active_entry_kind
{ {
@ -983,7 +1021,9 @@ impl LspLogView {
.language_servers .language_servers
.iter() .iter()
.map(|(server_id, state)| match &state.kind { .map(|(server_id, state)| match &state.kind {
LanguageServerKind::Local { .. } | LanguageServerKind::Remote { .. } => { LanguageServerKind::Local { .. }
| LanguageServerKind::Remote { .. }
| LanguageServerKind::LocalSsh { .. } => {
let worktree_root_name = state let worktree_root_name = state
.worktree_id .worktree_id
.and_then(|id| self.project.read(cx).worktree_for_id(id, cx)) .and_then(|id| self.project.read(cx).worktree_for_id(id, cx))

View file

@ -314,7 +314,9 @@ impl HeadlessProject {
if let Some(log_store) = log_store { if let Some(log_store) = log_store {
log_store.update(cx, |log_store, cx| { log_store.update(cx, |log_store, cx| {
log_store.add_language_server( log_store.add_language_server(
LanguageServerKind::Global, LanguageServerKind::LocalSsh {
lsp_store: self.lsp_store.downgrade(),
},
*id, *id,
Some(name.clone()), Some(name.clone()),
*worktree_id, *worktree_id,