Skip to content

Commit 60b182f

Browse files
committed
wip
1 parent e464dc6 commit 60b182f

File tree

9 files changed

+261
-91
lines changed

9 files changed

+261
-91
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/language_tools/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ itertools.workspace = true
2424
language.workspace = true
2525
lsp.workspace = true
2626
project.workspace = true
27+
proto.workspace = true
2728
serde_json.workspace = true
2829
settings.workspace = true
2930
theme.workspace = true

crates/language_tools/src/language_tools.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod key_context_view;
2-
mod lsp_log;
2+
pub mod lsp_log;
33
pub mod lsp_tool;
44
mod syntax_tree_view;
55

crates/language_tools/src/lsp_log.rs

Lines changed: 136 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ use lsp::{
1212
IoKind, LanguageServer, LanguageServerName, LanguageServerSelector, MessageType,
1313
SetTraceParams, TraceValue, notification::SetTrace,
1414
};
15-
use project::{Project, WorktreeId, search::SearchQuery};
15+
use project::{Project, WorktreeId, lsp_store::LanguageServerLogType, search::SearchQuery};
1616
use std::{any::TypeId, borrow::Cow, sync::Arc};
1717
use ui::{Button, Checkbox, ContextMenu, Label, PopoverMenu, ToggleState, prelude::*};
18+
use util::ResultExt as _;
1819
use workspace::{
1920
SplitDirection, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace, WorkspaceId,
2021
item::{Item, ItemHandle},
@@ -36,7 +37,7 @@ pub struct LogStore {
3637
}
3738

3839
struct ProjectState {
39-
_subscriptions: [gpui::Subscription; 2],
40+
_subscriptions: [gpui::Subscription; 3],
4041
}
4142

4243
trait Message: AsRef<str> {
@@ -102,6 +103,7 @@ impl Message for RpcMessage {
102103
}
103104

104105
pub(super) struct LanguageServerState {
106+
project: WeakEntity<Project>,
105107
name: Option<LanguageServerName>,
106108
worktree_id: Option<WorktreeId>,
107109
kind: LanguageServerKind,
@@ -183,6 +185,13 @@ pub enum LogKind {
183185
}
184186

185187
impl LogKind {
188+
fn from_server_log_type(log_type: &LanguageServerLogType) -> Self {
189+
match log_type {
190+
LanguageServerLogType::Log(_) => Self::Logs,
191+
LanguageServerLogType::Trace(_) => Self::Trace,
192+
LanguageServerLogType::Rpc { .. } => Self::Rpc,
193+
}
194+
}
186195
fn label(&self) -> &'static str {
187196
match self {
188197
LogKind::Rpc => RPC_MESSAGES,
@@ -212,10 +221,11 @@ actions!(
212221
]
213222
);
214223

215-
pub(super) struct GlobalLogStore(pub WeakEntity<LogStore>);
224+
pub struct GlobalLogStore(pub WeakEntity<LogStore>);
216225

217226
impl Global for GlobalLogStore {}
218227

228+
// todo! do separate headless and local cases here: headless cares only about the downstream_client() part, NO log storage is needed
219229
pub fn init(cx: &mut App) {
220230
let log_store = cx.new(LogStore::new);
221231
cx.set_global(GlobalLogStore(log_store.downgrade()));
@@ -311,6 +321,7 @@ impl LogStore {
311321

312322
pub fn add_project(&mut self, project: &Entity<Project>, cx: &mut Context<Self>) {
313323
let weak_project = project.downgrade();
324+
let subscription_weak_project = weak_project.clone();
314325
self.projects.insert(
315326
project.downgrade(),
316327
ProjectState {
@@ -356,13 +367,42 @@ impl LogStore {
356367
this.add_language_server_log(*id, *typ, message, cx);
357368
}
358369
project::LanguageServerLogType::Trace(_) => {
370+
// todo! do something with trace level
359371
this.add_language_server_trace(*id, message, cx);
360372
}
373+
project::LanguageServerLogType::Rpc { received } => {
374+
let kind = if *received {
375+
MessageKind::Receive
376+
} else {
377+
MessageKind::Send
378+
};
379+
this.add_language_server_rpc(*id, kind, message, cx);
380+
}
361381
}
362382
}
363383
_ => {}
364384
}
365385
}),
386+
cx.subscribe_self(move |_, e, cx| match e {
387+
Event::NewServerLogEntry { id, kind, text } => {
388+
subscription_weak_project
389+
.update(cx, |project, cx| {
390+
if let Some((client, project_id)) =
391+
project.lsp_store().read(cx).downstream_client()
392+
{
393+
client
394+
.send(proto::LanguageServerLog {
395+
project_id,
396+
language_server_id: id.to_proto(),
397+
message: text.clone(),
398+
log_type: Some(kind.to_proto()),
399+
})
400+
.log_err();
401+
};
402+
})
403+
.ok();
404+
}
405+
}),
366406
],
367407
},
368408
);
@@ -382,6 +422,7 @@ impl LogStore {
382422
name: Option<LanguageServerName>,
383423
worktree_id: Option<WorktreeId>,
384424
server: Option<Arc<LanguageServer>>,
425+
project: WeakEntity<Project>,
385426
cx: &mut Context<Self>,
386427
) -> Option<&mut LanguageServerState> {
387428
let server_state = self.language_servers.entry(server_id).or_insert_with(|| {
@@ -390,6 +431,7 @@ impl LogStore {
390431
name: None,
391432
worktree_id: None,
392433
kind,
434+
project,
393435
rpc_state: None,
394436
log_messages: VecDeque::with_capacity(MAX_STORED_LOG_ENTRIES),
395437
trace_messages: VecDeque::with_capacity(MAX_STORED_LOG_ENTRIES),
@@ -432,17 +474,21 @@ impl LogStore {
432474
let language_server_state = self.get_language_server_state(id)?;
433475

434476
let log_lines = &mut language_server_state.log_messages;
435-
Self::add_language_server_message(
477+
if let Some(new_message) = Self::push_new_message(
436478
log_lines,
437-
id,
438479
LogMessage {
439480
message: message.trim_end().to_string(),
440481
typ,
441482
},
442483
language_server_state.log_level,
443-
LogKind::Logs,
444-
cx,
445-
);
484+
) {
485+
cx.emit(Event::NewServerLogEntry {
486+
id,
487+
kind: LanguageServerLogType::Log(typ),
488+
text: new_message,
489+
});
490+
}
491+
446492
Some(())
447493
}
448494

@@ -455,38 +501,81 @@ impl LogStore {
455501
let language_server_state = self.get_language_server_state(id)?;
456502

457503
let log_lines = &mut language_server_state.trace_messages;
458-
Self::add_language_server_message(
504+
if let Some(new_message) = Self::push_new_message(
459505
log_lines,
460-
id,
461506
TraceMessage {
462507
message: message.trim().to_string(),
463508
},
464509
(),
465-
LogKind::Trace,
466-
cx,
467-
);
510+
) {
511+
cx.emit(Event::NewServerLogEntry {
512+
id,
513+
// todo! Ben, fix this here too!
514+
kind: LanguageServerLogType::Trace(project::lsp_store::TraceLevel::Verbose),
515+
text: new_message,
516+
});
517+
}
518+
468519
Some(())
469520
}
470521

471-
fn add_language_server_message<T: Message>(
522+
fn push_new_message<T: Message>(
472523
log_lines: &mut VecDeque<T>,
473-
id: LanguageServerId,
474524
message: T,
475525
current_severity: <T as Message>::Level,
476-
kind: LogKind,
477-
cx: &mut Context<Self>,
478-
) {
526+
) -> Option<String> {
479527
while log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
480528
log_lines.pop_front();
481529
}
482-
let text = message.as_ref().to_string();
483530
let visible = message.should_include(current_severity);
531+
532+
let re = visible.then(|| message.as_ref().to_string());
484533
log_lines.push_back(message);
534+
re
535+
}
485536

486-
if visible {
487-
cx.emit(Event::NewServerLogEntry { id, kind, text });
488-
cx.notify();
537+
fn add_language_server_rpc(
538+
&mut self,
539+
language_server_id: LanguageServerId,
540+
kind: MessageKind,
541+
message: &str,
542+
cx: &mut Context<'_, LogStore>,
543+
) {
544+
let Some(state) = self
545+
.get_language_server_state(language_server_id)
546+
.and_then(|state| state.rpc_state.as_mut())
547+
else {
548+
return;
549+
};
550+
551+
let rpc_log_lines = &mut state.rpc_messages;
552+
if state.last_message_kind != Some(kind) {
553+
while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
554+
rpc_log_lines.pop_front();
555+
}
556+
let line_before_message = match kind {
557+
MessageKind::Send => SEND_LINE,
558+
MessageKind::Receive => RECEIVE_LINE,
559+
};
560+
rpc_log_lines.push_back(RpcMessage {
561+
message: line_before_message.to_string(),
562+
});
563+
cx.emit(Event::NewServerLogEntry {
564+
id: language_server_id,
565+
kind: LanguageServerLogType::Rpc {
566+
received: kind == MessageKind::Receive,
567+
},
568+
text: line_before_message.to_string(),
569+
});
489570
}
571+
572+
while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
573+
rpc_log_lines.pop_front();
574+
}
575+
576+
rpc_log_lines.push_back(RpcMessage {
577+
message: message.trim().to_owned(),
578+
});
490579
}
491580

492581
fn remove_language_server(&mut self, id: LanguageServerId, cx: &mut Context<Self>) {
@@ -523,7 +612,7 @@ impl LogStore {
523612
})
524613
}
525614

526-
fn enable_rpc_trace_for_language_server(
615+
pub fn enable_rpc_trace_for_language_server(
527616
&mut self,
528617
server_id: LanguageServerId,
529618
) -> Option<&mut LanguageServerRpcState> {
@@ -666,47 +755,19 @@ impl LogStore {
666755
}
667756
};
668757

669-
let state = self
670-
.get_language_server_state(language_server_id)?
671-
.rpc_state
672-
.as_mut()?;
673758
let kind = if is_received {
674759
MessageKind::Receive
675760
} else {
676761
MessageKind::Send
677762
};
678763

679-
let rpc_log_lines = &mut state.rpc_messages;
680-
if state.last_message_kind != Some(kind) {
681-
while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
682-
rpc_log_lines.pop_front();
683-
}
684-
let line_before_message = match kind {
685-
MessageKind::Send => SEND_LINE,
686-
MessageKind::Receive => RECEIVE_LINE,
687-
};
688-
rpc_log_lines.push_back(RpcMessage {
689-
message: line_before_message.to_string(),
690-
});
691-
cx.emit(Event::NewServerLogEntry {
692-
id: language_server_id,
693-
kind: LogKind::Rpc,
694-
text: line_before_message.to_string(),
695-
});
696-
}
697-
698-
while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
699-
rpc_log_lines.pop_front();
700-
}
701-
702-
let message = message.trim();
703-
rpc_log_lines.push_back(RpcMessage {
704-
message: message.to_string(),
705-
});
764+
self.add_language_server_rpc(language_server_id, kind, message, cx);
706765
cx.emit(Event::NewServerLogEntry {
707766
id: language_server_id,
708-
kind: LogKind::Rpc,
709-
text: message.to_string(),
767+
kind: LanguageServerLogType::Rpc {
768+
received: is_received,
769+
},
770+
text: message.to_owned(),
710771
});
711772
cx.notify();
712773
Some(())
@@ -762,7 +823,7 @@ impl LspLogView {
762823
move |log_view, _, e, window, cx| match e {
763824
Event::NewServerLogEntry { id, kind, text } => {
764825
if log_view.current_server_id == Some(*id)
765-
&& *kind == log_view.active_entry_kind
826+
&& LogKind::from_server_log_type(kind) == log_view.active_entry_kind
766827
{
767828
log_view.editor.update(cx, |editor, cx| {
768829
editor.set_read_only(false);
@@ -1084,6 +1145,21 @@ impl LspLogView {
10841145
} else {
10851146
log_store.disable_rpc_trace_for_language_server(server_id);
10861147
}
1148+
1149+
if let Some(server_state) = log_store.language_servers.get(server_id) {
1150+
server_state
1151+
.project
1152+
.update(cx, |project, cx| {
1153+
if let Some((client, project)) =
1154+
project.lsp_store().read(cx).upstream_client()
1155+
{
1156+
// todo! client.send a new proto message to propagate the enabled
1157+
// !!!! we have to have a handler on both headless and normal projects
1158+
// that handler has to touch the Global<LspLog> and amend the sending bit
1159+
}
1160+
})
1161+
.ok();
1162+
};
10871163
});
10881164
if !enabled && Some(server_id) == self.current_server_id {
10891165
self.show_logs_for_server(server_id, window, cx);
@@ -1122,6 +1198,8 @@ impl LspLogView {
11221198
window: &mut Window,
11231199
cx: &mut Context<Self>,
11241200
) {
1201+
// todo! there's no language server for the remote case, hence no server info!
1202+
// BUT we do have the capabilities info within the LspStore.lsp_server_capabilities
11251203
let lsp_store = self.project.read(cx).lsp_store();
11261204
let Some(server) = lsp_store.read(cx).language_server_for_id(server_id) else {
11271205
return;
@@ -1746,7 +1824,7 @@ impl LspLogToolbarItemView {
17461824
pub enum Event {
17471825
NewServerLogEntry {
17481826
id: LanguageServerId,
1749-
kind: LogKind,
1827+
kind: LanguageServerLogType,
17501828
text: String,
17511829
},
17521830
}

0 commit comments

Comments
 (0)