Skip to content

Commit 0b5bdd4

Browse files
committed
wip
1 parent 81cb248 commit 0b5bdd4

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),
@@ -429,17 +471,21 @@ impl LogStore {
429471
let language_server_state = self.get_language_server_state(id)?;
430472

431473
let log_lines = &mut language_server_state.log_messages;
432-
Self::add_language_server_message(
474+
if let Some(new_message) = Self::push_new_message(
433475
log_lines,
434-
id,
435476
LogMessage {
436477
message: message.trim_end().to_string(),
437478
typ,
438479
},
439480
language_server_state.log_level,
440-
LogKind::Logs,
441-
cx,
442-
);
481+
) {
482+
cx.emit(Event::NewServerLogEntry {
483+
id,
484+
kind: LanguageServerLogType::Log(typ),
485+
text: new_message,
486+
});
487+
}
488+
443489
Some(())
444490
}
445491

@@ -452,38 +498,81 @@ impl LogStore {
452498
let language_server_state = self.get_language_server_state(id)?;
453499

454500
let log_lines = &mut language_server_state.trace_messages;
455-
Self::add_language_server_message(
501+
if let Some(new_message) = Self::push_new_message(
456502
log_lines,
457-
id,
458503
TraceMessage {
459504
message: message.trim().to_string(),
460505
},
461506
(),
462-
LogKind::Trace,
463-
cx,
464-
);
507+
) {
508+
cx.emit(Event::NewServerLogEntry {
509+
id,
510+
// todo! Ben, fix this here too!
511+
kind: LanguageServerLogType::Trace(project::lsp_store::TraceLevel::Verbose),
512+
text: new_message,
513+
});
514+
}
515+
465516
Some(())
466517
}
467518

468-
fn add_language_server_message<T: Message>(
519+
fn push_new_message<T: Message>(
469520
log_lines: &mut VecDeque<T>,
470-
id: LanguageServerId,
471521
message: T,
472522
current_severity: <T as Message>::Level,
473-
kind: LogKind,
474-
cx: &mut Context<Self>,
475-
) {
523+
) -> Option<String> {
476524
while log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
477525
log_lines.pop_front();
478526
}
479-
let text = message.as_ref().to_string();
480527
let visible = message.should_include(current_severity);
528+
529+
let re = visible.then(|| message.as_ref().to_string());
481530
log_lines.push_back(message);
531+
re
532+
}
482533

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

489578
fn remove_language_server(&mut self, id: LanguageServerId, cx: &mut Context<Self>) {
@@ -520,7 +609,7 @@ impl LogStore {
520609
})
521610
}
522611

523-
fn enable_rpc_trace_for_language_server(
612+
pub fn enable_rpc_trace_for_language_server(
524613
&mut self,
525614
server_id: LanguageServerId,
526615
) -> Option<&mut LanguageServerRpcState> {
@@ -663,47 +752,19 @@ impl LogStore {
663752
}
664753
};
665754

666-
let state = self
667-
.get_language_server_state(language_server_id)?
668-
.rpc_state
669-
.as_mut()?;
670755
let kind = if is_received {
671756
MessageKind::Receive
672757
} else {
673758
MessageKind::Send
674759
};
675760

676-
let rpc_log_lines = &mut state.rpc_messages;
677-
if state.last_message_kind != Some(kind) {
678-
while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
679-
rpc_log_lines.pop_front();
680-
}
681-
let line_before_message = match kind {
682-
MessageKind::Send => SEND_LINE,
683-
MessageKind::Receive => RECEIVE_LINE,
684-
};
685-
rpc_log_lines.push_back(RpcMessage {
686-
message: line_before_message.to_string(),
687-
});
688-
cx.emit(Event::NewServerLogEntry {
689-
id: language_server_id,
690-
kind: LogKind::Rpc,
691-
text: line_before_message.to_string(),
692-
});
693-
}
694-
695-
while rpc_log_lines.len() + 1 >= MAX_STORED_LOG_ENTRIES {
696-
rpc_log_lines.pop_front();
697-
}
698-
699-
let message = message.trim();
700-
rpc_log_lines.push_back(RpcMessage {
701-
message: message.to_string(),
702-
});
761+
self.add_language_server_rpc(language_server_id, kind, message, cx);
703762
cx.emit(Event::NewServerLogEntry {
704763
id: language_server_id,
705-
kind: LogKind::Rpc,
706-
text: message.to_string(),
764+
kind: LanguageServerLogType::Rpc {
765+
received: is_received,
766+
},
767+
text: message.to_owned(),
707768
});
708769
cx.notify();
709770
Some(())
@@ -757,7 +818,7 @@ impl LspLogView {
757818
move |log_view, _, e, window, cx| match e {
758819
Event::NewServerLogEntry { id, kind, text } => {
759820
if log_view.current_server_id == Some(*id)
760-
&& *kind == log_view.active_entry_kind
821+
&& LogKind::from_server_log_type(kind) == log_view.active_entry_kind
761822
{
762823
log_view.editor.update(cx, |editor, cx| {
763824
editor.set_read_only(false);
@@ -1075,6 +1136,21 @@ impl LspLogView {
10751136
} else {
10761137
log_store.disable_rpc_trace_for_language_server(server_id);
10771138
}
1139+
1140+
if let Some(server_state) = log_store.language_servers.get(server_id) {
1141+
server_state
1142+
.project
1143+
.update(cx, |project, cx| {
1144+
if let Some((client, project)) =
1145+
project.lsp_store().read(cx).upstream_client()
1146+
{
1147+
// todo! client.send a new proto message to propagate the enabled
1148+
// !!!! we have to have a handler on both headless and normal projects
1149+
// that handler has to touch the Global<LspLog> and amend the sending bit
1150+
}
1151+
})
1152+
.ok();
1153+
};
10781154
});
10791155
if !enabled && Some(server_id) == self.current_server_id {
10801156
self.show_logs_for_server(server_id, window, cx);
@@ -1113,6 +1189,8 @@ impl LspLogView {
11131189
window: &mut Window,
11141190
cx: &mut Context<Self>,
11151191
) {
1192+
// todo! there's no language server for the remote case, hence no server info!
1193+
// BUT we do have the capabilities info within the LspStore.lsp_server_capabilities
11161194
let lsp_store = self.project.read(cx).lsp_store();
11171195
let Some(server) = lsp_store.read(cx).language_server_for_id(server_id) else {
11181196
return;
@@ -1737,7 +1815,7 @@ impl LspLogToolbarItemView {
17371815
pub enum Event {
17381816
NewServerLogEntry {
17391817
id: LanguageServerId,
1740-
kind: LogKind,
1818+
kind: LanguageServerLogType,
17411819
text: String,
17421820
},
17431821
}

0 commit comments

Comments
 (0)