Add messages and handlers for RPC log toggling
Co-authored-by: Ben Kunkle <ben@zed.dev> Co-authored-by: Lukas Wirth <lukas@zed.dev>
This commit is contained in:
parent
848d1101d3
commit
ab5da3af83
8 changed files with 94 additions and 51 deletions
|
@ -476,7 +476,8 @@ impl Server {
|
||||||
.add_request_handler(forward_mutating_project_request::<proto::GitChangeBranch>)
|
.add_request_handler(forward_mutating_project_request::<proto::GitChangeBranch>)
|
||||||
.add_request_handler(forward_mutating_project_request::<proto::CheckForPushedCommits>)
|
.add_request_handler(forward_mutating_project_request::<proto::CheckForPushedCommits>)
|
||||||
.add_message_handler(broadcast_project_message_from_host::<proto::AdvertiseContexts>)
|
.add_message_handler(broadcast_project_message_from_host::<proto::AdvertiseContexts>)
|
||||||
.add_message_handler(update_context);
|
.add_message_handler(update_context)
|
||||||
|
.add_request_handler(forward_mutating_project_request::<proto::ToggleLspLogs>);
|
||||||
|
|
||||||
Arc::new(server)
|
Arc::new(server)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ mod syntax_tree_view;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod lsp_log_tests;
|
mod lsp_log_tests;
|
||||||
|
|
||||||
|
use client::AnyProtoClient;
|
||||||
use gpui::{App, AppContext, Entity};
|
use gpui::{App, AppContext, Entity};
|
||||||
|
|
||||||
pub use lsp_log::{LogStore, LspLogToolbarItemView, LspLogView};
|
pub use lsp_log::{LogStore, LspLogToolbarItemView, LspLogView};
|
||||||
|
@ -13,8 +14,8 @@ pub use syntax_tree_view::{SyntaxTreeToolbarItemView, SyntaxTreeView};
|
||||||
use ui::{Context, Window};
|
use ui::{Context, Window};
|
||||||
use workspace::{Item, ItemHandle, SplitDirection, Workspace};
|
use workspace::{Item, ItemHandle, SplitDirection, Workspace};
|
||||||
|
|
||||||
pub fn init(cx: &mut App) {
|
pub fn init(client: AnyProtoClient, cx: &mut App) {
|
||||||
lsp_log::init(cx);
|
lsp_log::init(client, cx);
|
||||||
syntax_tree_view::init(cx);
|
syntax_tree_view::init(cx);
|
||||||
key_context_view::init(cx);
|
key_context_view::init(cx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use client::AnyProtoClient;
|
||||||
use collections::{HashMap, VecDeque};
|
use collections::{HashMap, VecDeque};
|
||||||
use copilot::Copilot;
|
use copilot::Copilot;
|
||||||
use editor::{Editor, EditorEvent, actions::MoveToEnd, scroll::Autoscroll};
|
use editor::{Editor, EditorEvent, actions::MoveToEnd, scroll::Autoscroll};
|
||||||
use futures::{StreamExt, channel::mpsc};
|
use futures::{StreamExt, channel::mpsc};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyView, App, Context, Corner, Entity, EventEmitter, FocusHandle, Focusable, Global,
|
AnyView, App, AsyncApp, Context, Corner, Entity, EventEmitter, FocusHandle, Focusable, Global,
|
||||||
IntoElement, ParentElement, Render, Styled, Subscription, WeakEntity, Window, actions, div,
|
IntoElement, ParentElement, Render, Styled, Subscription, WeakEntity, Window, actions, div,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -13,6 +15,7 @@ use lsp::{
|
||||||
SetTraceParams, TraceValue, notification::SetTrace,
|
SetTraceParams, TraceValue, notification::SetTrace,
|
||||||
};
|
};
|
||||||
use project::{Project, WorktreeId, lsp_store::LanguageServerLogType, search::SearchQuery};
|
use project::{Project, WorktreeId, lsp_store::LanguageServerLogType, search::SearchQuery};
|
||||||
|
use proto::TypedEnvelope;
|
||||||
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 _;
|
||||||
|
@ -103,7 +106,7 @@ impl Message for RpcMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct LanguageServerState {
|
pub(super) struct LanguageServerState {
|
||||||
project: WeakEntity<Project>,
|
project: Option<WeakEntity<Project>>,
|
||||||
name: Option<LanguageServerName>,
|
name: Option<LanguageServerName>,
|
||||||
worktree_id: Option<WorktreeId>,
|
worktree_id: Option<WorktreeId>,
|
||||||
kind: LanguageServerKind,
|
kind: LanguageServerKind,
|
||||||
|
@ -226,7 +229,9 @@ pub struct GlobalLogStore(pub WeakEntity<LogStore>);
|
||||||
impl Global for GlobalLogStore {}
|
impl Global for GlobalLogStore {}
|
||||||
|
|
||||||
// todo! do separate headless and local cases here: headless cares only about the downstream_client() part, NO log storage is needed
|
// todo! do separate headless and local cases here: headless cares only about the downstream_client() part, NO log storage is needed
|
||||||
pub fn init(cx: &mut App) {
|
pub fn init(client: AnyProtoClient, cx: &mut App) {
|
||||||
|
client.add_entity_message_handler(handle_toggle_lsp_logs);
|
||||||
|
|
||||||
let log_store = cx.new(LogStore::new);
|
let log_store = cx.new(LogStore::new);
|
||||||
cx.set_global(GlobalLogStore(log_store.downgrade()));
|
cx.set_global(GlobalLogStore(log_store.downgrade()));
|
||||||
|
|
||||||
|
@ -291,6 +296,7 @@ impl LogStore {
|
||||||
Some(name),
|
Some(name),
|
||||||
None,
|
None,
|
||||||
Some(server.clone()),
|
Some(server.clone()),
|
||||||
|
None,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -331,7 +337,8 @@ impl LogStore {
|
||||||
this.language_servers
|
this.language_servers
|
||||||
.retain(|_, state| state.kind.project() != Some(&weak_project));
|
.retain(|_, state| state.kind.project() != Some(&weak_project));
|
||||||
}),
|
}),
|
||||||
cx.subscribe(project, |this, project, event, cx| {
|
cx.subscribe(project, move |log_store, project, event, cx| {
|
||||||
|
let subscription_weak_project = project.downgrade();
|
||||||
let server_kind = if project.read(cx).is_via_ssh() {
|
let server_kind = if project.read(cx).is_via_ssh() {
|
||||||
LanguageServerKind::Remote {
|
LanguageServerKind::Remote {
|
||||||
project: project.downgrade(),
|
project: project.downgrade(),
|
||||||
|
@ -344,7 +351,7 @@ impl LogStore {
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
project::Event::LanguageServerAdded(id, name, worktree_id) => {
|
project::Event::LanguageServerAdded(id, name, worktree_id) => {
|
||||||
this.add_language_server(
|
log_store.add_language_server(
|
||||||
server_kind,
|
server_kind,
|
||||||
*id,
|
*id,
|
||||||
Some(name.clone()),
|
Some(name.clone()),
|
||||||
|
@ -354,21 +361,30 @@ impl LogStore {
|
||||||
.lsp_store()
|
.lsp_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.language_server_for_id(*id),
|
.language_server_for_id(*id),
|
||||||
|
Some(subscription_weak_project),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
project::Event::LanguageServerRemoved(id) => {
|
project::Event::LanguageServerRemoved(id) => {
|
||||||
this.remove_language_server(*id, cx);
|
log_store.remove_language_server(*id, cx);
|
||||||
}
|
}
|
||||||
project::Event::LanguageServerLog(id, typ, message) => {
|
project::Event::LanguageServerLog(id, typ, message) => {
|
||||||
this.add_language_server(server_kind, *id, None, None, None, cx);
|
log_store.add_language_server(
|
||||||
|
server_kind,
|
||||||
|
*id,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(subscription_weak_project),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
match typ {
|
match typ {
|
||||||
project::LanguageServerLogType::Log(typ) => {
|
project::LanguageServerLogType::Log(typ) => {
|
||||||
this.add_language_server_log(*id, *typ, message, cx);
|
log_store.add_language_server_log(*id, *typ, message, cx);
|
||||||
}
|
}
|
||||||
project::LanguageServerLogType::Trace(_) => {
|
project::LanguageServerLogType::Trace(_) => {
|
||||||
// todo! do something with trace level
|
// todo! do something with trace level
|
||||||
this.add_language_server_trace(*id, message, cx);
|
log_store.add_language_server_trace(*id, message, cx);
|
||||||
}
|
}
|
||||||
project::LanguageServerLogType::Rpc { received } => {
|
project::LanguageServerLogType::Rpc { received } => {
|
||||||
let kind = if *received {
|
let kind = if *received {
|
||||||
|
@ -376,7 +392,7 @@ impl LogStore {
|
||||||
} else {
|
} else {
|
||||||
MessageKind::Send
|
MessageKind::Send
|
||||||
};
|
};
|
||||||
this.add_language_server_rpc(*id, kind, message, cx);
|
log_store.add_language_server_rpc(*id, kind, message, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -422,7 +438,7 @@ impl LogStore {
|
||||||
name: Option<LanguageServerName>,
|
name: Option<LanguageServerName>,
|
||||||
worktree_id: Option<WorktreeId>,
|
worktree_id: Option<WorktreeId>,
|
||||||
server: Option<Arc<LanguageServer>>,
|
server: Option<Arc<LanguageServer>>,
|
||||||
project: WeakEntity<Project>,
|
project: Option<WeakEntity<Project>>,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Option<&mut LanguageServerState> {
|
) -> Option<&mut LanguageServerState> {
|
||||||
let server_state = self.language_servers.entry(server_id).or_insert_with(|| {
|
let server_state = self.language_servers.entry(server_id).or_insert_with(|| {
|
||||||
|
@ -609,7 +625,7 @@ impl LogStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enable_rpc_trace_for_language_server(
|
fn enable_rpc_trace_for_language_server(
|
||||||
&mut self,
|
&mut self,
|
||||||
server_id: LanguageServerId,
|
server_id: LanguageServerId,
|
||||||
) -> Option<&mut LanguageServerRpcState> {
|
) -> Option<&mut LanguageServerRpcState> {
|
||||||
|
@ -771,6 +787,23 @@ impl LogStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_toggle_lsp_logs(
|
||||||
|
lsp_log: Entity<LogStore>,
|
||||||
|
envelope: TypedEnvelope<proto::ToggleLspLogs>,
|
||||||
|
mut cx: AsyncApp,
|
||||||
|
) -> Result<()> {
|
||||||
|
let server_id = LanguageServerId::from_proto(envelope.payload.server_id);
|
||||||
|
lsp_log.update(&mut cx, |lsp_log, _| {
|
||||||
|
// we do not support any other log toggling yet
|
||||||
|
if envelope.payload.enabled {
|
||||||
|
lsp_log.enable_rpc_trace_for_language_server(server_id);
|
||||||
|
} else {
|
||||||
|
lsp_log.disable_rpc_trace_for_language_server(server_id);
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
impl LspLogView {
|
impl LspLogView {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
project: Entity<Project>,
|
project: Entity<Project>,
|
||||||
|
@ -1130,26 +1163,32 @@ impl LspLogView {
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
self.log_store.update(cx, |log_store, _| {
|
self.log_store.update(cx, |log_store, cx| {
|
||||||
if enabled {
|
if enabled {
|
||||||
log_store.enable_rpc_trace_for_language_server(server_id);
|
log_store.enable_rpc_trace_for_language_server(server_id);
|
||||||
} else {
|
} else {
|
||||||
log_store.disable_rpc_trace_for_language_server(server_id);
|
log_store.disable_rpc_trace_for_language_server(server_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(server_state) = log_store.language_servers.get(server_id) {
|
if let Some(server_state) = log_store.language_servers.get(&server_id) {
|
||||||
server_state
|
if let Some(project) = &server_state.project {
|
||||||
.project
|
project
|
||||||
.update(cx, |project, cx| {
|
.update(cx, |project, cx| {
|
||||||
if let Some((client, project)) =
|
if let Some((client, project_id)) =
|
||||||
project.lsp_store().read(cx).upstream_client()
|
project.lsp_store().read(cx).upstream_client()
|
||||||
{
|
{
|
||||||
// todo! client.send a new proto message to propagate the enabled
|
client
|
||||||
// !!!! we have to have a handler on both headless and normal projects
|
.send(proto::ToggleLspLogs {
|
||||||
// that handler has to touch the Global<LspLog> and amend the sending bit
|
project_id,
|
||||||
}
|
log_type: proto::toggle_lsp_logs::LogType::Rpc as i32,
|
||||||
})
|
server_id: server_id.to_proto(),
|
||||||
.ok();
|
enabled,
|
||||||
|
})
|
||||||
|
.log_err();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
if !enabled && Some(server_id) == self.current_server_id {
|
if !enabled && Some(server_id) == self.current_server_id {
|
||||||
|
|
|
@ -963,3 +963,16 @@ message MultiLspQuery {
|
||||||
message MultiLspQueryResponse {
|
message MultiLspQueryResponse {
|
||||||
repeated LspResponse responses = 1;
|
repeated LspResponse responses = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ToggleLspLogs {
|
||||||
|
uint64 project_id = 1;
|
||||||
|
LogType log_type = 2;
|
||||||
|
uint64 server_id = 3;
|
||||||
|
bool enabled = 4;
|
||||||
|
|
||||||
|
enum LogType {
|
||||||
|
LOG = 0;
|
||||||
|
TRACE = 1;
|
||||||
|
RPC = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -396,7 +396,8 @@ message Envelope {
|
||||||
GitCloneResponse git_clone_response = 364;
|
GitCloneResponse git_clone_response = 364;
|
||||||
|
|
||||||
LspQuery lsp_query = 365;
|
LspQuery lsp_query = 365;
|
||||||
LspQueryResponse lsp_query_response = 366; // current max
|
LspQueryResponse lsp_query_response = 366;
|
||||||
|
ToggleLspLogs toggle_lsp_logs = 367; // current max
|
||||||
}
|
}
|
||||||
|
|
||||||
reserved 87 to 88;
|
reserved 87 to 88;
|
||||||
|
|
|
@ -312,7 +312,8 @@ messages!(
|
||||||
(GetDefaultBranch, Background),
|
(GetDefaultBranch, Background),
|
||||||
(GetDefaultBranchResponse, Background),
|
(GetDefaultBranchResponse, Background),
|
||||||
(GitClone, Background),
|
(GitClone, Background),
|
||||||
(GitCloneResponse, Background)
|
(GitCloneResponse, Background),
|
||||||
|
(ToggleLspLogs, Background),
|
||||||
);
|
);
|
||||||
|
|
||||||
request_messages!(
|
request_messages!(
|
||||||
|
@ -481,7 +482,8 @@ request_messages!(
|
||||||
(GetDocumentDiagnostics, GetDocumentDiagnosticsResponse),
|
(GetDocumentDiagnostics, GetDocumentDiagnosticsResponse),
|
||||||
(PullWorkspaceDiagnostics, Ack),
|
(PullWorkspaceDiagnostics, Ack),
|
||||||
(GetDefaultBranch, GetDefaultBranchResponse),
|
(GetDefaultBranch, GetDefaultBranchResponse),
|
||||||
(GitClone, GitCloneResponse)
|
(GitClone, GitCloneResponse),
|
||||||
|
(ToggleLspLogs, Ack),
|
||||||
);
|
);
|
||||||
|
|
||||||
lsp_messages!(
|
lsp_messages!(
|
||||||
|
@ -612,6 +614,7 @@ entity_messages!(
|
||||||
GitReset,
|
GitReset,
|
||||||
GitCheckoutFiles,
|
GitCheckoutFiles,
|
||||||
SetIndexText,
|
SetIndexText,
|
||||||
|
ToggleLspLogs,
|
||||||
|
|
||||||
Push,
|
Push,
|
||||||
Fetch,
|
Fetch,
|
||||||
|
|
|
@ -65,13 +65,6 @@ impl HeadlessProject {
|
||||||
settings::init(cx);
|
settings::init(cx);
|
||||||
language::init(cx);
|
language::init(cx);
|
||||||
project::Project::init_settings(cx);
|
project::Project::init_settings(cx);
|
||||||
// todo! what to do with the RPC log spam?
|
|
||||||
// if we have not enabled RPC logging on the remote client, we do not need these
|
|
||||||
//
|
|
||||||
// Maybe, add another RPC message, proto::ToggleRpcLogging(bool)
|
|
||||||
// and send it into the upstream client from the remotes, so that the local/headless counterpart
|
|
||||||
// can access this Global<LspLog> and toggle the spam send
|
|
||||||
language_tools::lsp_log::init(cx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
@ -87,6 +80,8 @@ impl HeadlessProject {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
debug_adapter_extension::init(proxy.clone(), cx);
|
debug_adapter_extension::init(proxy.clone(), cx);
|
||||||
languages::init(languages.clone(), node_runtime.clone(), cx);
|
languages::init(languages.clone(), node_runtime.clone(), cx);
|
||||||
|
// todo! avoid "memory leaks" here as we do not need to gather any logs locally, just proxy the to the client
|
||||||
|
language_tools::lsp_log::init(session.clone(), cx);
|
||||||
|
|
||||||
let worktree_store = cx.new(|cx| {
|
let worktree_store = cx.new(|cx| {
|
||||||
let mut store = WorktreeStore::local(true, fs.clone());
|
let mut store = WorktreeStore::local(true, fs.clone());
|
||||||
|
@ -333,16 +328,6 @@ impl HeadlessProject {
|
||||||
})
|
})
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
LspStoreEvent::LanguageServerLog(language_server_id, log_type, message) => {
|
|
||||||
self.session
|
|
||||||
.send(proto::LanguageServerLog {
|
|
||||||
project_id: SSH_PROJECT_ID,
|
|
||||||
language_server_id: language_server_id.to_proto(),
|
|
||||||
message: message.clone(),
|
|
||||||
log_type: Some(log_type.to_proto()),
|
|
||||||
})
|
|
||||||
.log_err();
|
|
||||||
}
|
|
||||||
LspStoreEvent::LanguageServerPrompt(prompt) => {
|
LspStoreEvent::LanguageServerPrompt(prompt) => {
|
||||||
let request = self.session.request(proto::LanguageServerPromptRequest {
|
let request = self.session.request(proto::LanguageServerPromptRequest {
|
||||||
project_id: SSH_PROJECT_ID,
|
project_id: SSH_PROJECT_ID,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use agent_ui::AgentPanel;
|
||||||
use anyhow::{Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
use clap::{Parser, command};
|
use clap::{Parser, command};
|
||||||
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
|
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
|
||||||
use client::{Client, ProxySettings, UserStore, parse_zed_link};
|
use client::{AnyProtoClient, Client, ProxySettings, UserStore, parse_zed_link};
|
||||||
use collab_ui::channel_view::ChannelView;
|
use collab_ui::channel_view::ChannelView;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use crashes::InitCrashHandler;
|
use crashes::InitCrashHandler;
|
||||||
|
@ -621,7 +621,7 @@ pub fn main() {
|
||||||
toolchain_selector::init(cx);
|
toolchain_selector::init(cx);
|
||||||
theme_selector::init(cx);
|
theme_selector::init(cx);
|
||||||
settings_profile_selector::init(cx);
|
settings_profile_selector::init(cx);
|
||||||
language_tools::init(cx);
|
language_tools::init(AnyProtoClient::new(app_state.client.clone()), cx);
|
||||||
call::init(app_state.client.clone(), app_state.user_store.clone(), cx);
|
call::init(app_state.client.clone(), app_state.user_store.clone(), cx);
|
||||||
notifications::init(app_state.client.clone(), app_state.user_store.clone(), cx);
|
notifications::init(app_state.client.clone(), app_state.user_store.clone(), cx);
|
||||||
collab_ui::init(&app_state, cx);
|
collab_ui::init(&app_state, cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue