diff --git a/crates/language_tools/src/lsp_log.rs b/crates/language_tools/src/lsp_log.rs index 383ca94851..a796bc46c8 100644 --- a/crates/language_tools/src/lsp_log.rs +++ b/crates/language_tools/src/lsp_log.rs @@ -36,7 +36,7 @@ struct ProjectState { } struct LanguageServerState { - log_buffer: ModelHandle, + log_storage: Vec, rpc_state: Option, _io_logs_subscription: Option, _lsp_logs_subscription: Option, @@ -168,15 +168,14 @@ impl LogStore { project: &ModelHandle, id: LanguageServerId, cx: &mut ModelContext, - ) -> Option> { + ) -> Option<&mut Vec> { let project_state = self.projects.get_mut(&project.downgrade())?; let server_state = project_state.servers.entry(id).or_insert_with(|| { cx.notify(); LanguageServerState { rpc_state: None, - log_buffer: cx - .add_model(|cx| Buffer::new(0, cx.model_id() as u64, "")) - .clone(), + // TODO kb move this to settings? + log_storage: Vec::with_capacity(10_000), _io_logs_subscription: None, _lsp_logs_subscription: None, } @@ -186,7 +185,7 @@ impl LogStore { if let Some(server) = server.as_deref() { if server.has_notification_handler::() { // Another event wants to re-add the server that was already added and subscribed to, avoid doing it again. - return Some(server_state.log_buffer.clone()); + return Some(&mut server_state.log_storage); } } @@ -215,7 +214,7 @@ impl LogStore { } }) }); - Some(server_state.log_buffer.clone()) + Some(&mut server_state.log_storage) } fn add_language_server_log( @@ -225,25 +224,23 @@ impl LogStore { message: &str, cx: &mut ModelContext, ) -> Option<()> { - let buffer = match self + let log_lines = match self .projects .get_mut(&project.downgrade())? .servers - .get(&id) - .map(|state| state.log_buffer.clone()) + .get_mut(&id) + .map(|state| &mut state.log_storage) { Some(existing_buffer) => existing_buffer, None => self.add_language_server(&project, id, cx)?, }; - buffer.update(cx, |buffer, cx| { - let len = buffer.len(); - let has_newline = message.ends_with("\n"); - buffer.edit([(len..len, message)], None, cx); - if !has_newline { - let len = buffer.len(); - buffer.edit([(len..len, "\n")], None, cx); - } - }); + + // TODO kb something better VecDequeue? + if log_lines.capacity() == log_lines.len() { + log_lines.drain(..log_lines.len() / 2); + } + log_lines.push(message.trim().to_string()); + cx.notify(); Some(()) } @@ -260,15 +257,15 @@ impl LogStore { Some(()) } - pub fn log_buffer_for_server( + fn server_logs( &self, project: &ModelHandle, server_id: LanguageServerId, - ) -> Option> { + ) -> Option<&[String]> { let weak_project = project.downgrade(); let project_state = self.projects.get(&weak_project)?; let server_state = project_state.servers.get(&server_id)?; - Some(server_state.log_buffer.clone()) + Some(&server_state.log_storage) } fn enable_rpc_trace_for_language_server( @@ -487,14 +484,24 @@ impl LspLogView { } fn show_logs_for_server(&mut self, server_id: LanguageServerId, cx: &mut ViewContext) { - let buffer = self + let log_contents = self .log_store .read(cx) - .log_buffer_for_server(&self.project, server_id); - if let Some(buffer) = buffer { + .server_logs(&self.project, server_id) + .map(|lines| lines.join("\n")); + if let Some(log_contents) = log_contents { self.current_server_id = Some(server_id); self.is_showing_rpc_trace = false; - self.editor = Self::editor_for_buffer(self.project.clone(), buffer, cx); + let buffer = cx.add_model(|cx| Buffer::new(0, cx.model_id() as u64, log_contents)); + let editor = cx.add_view(|cx| { + let mut editor = Editor::for_buffer(buffer, Some(self.project.clone()), cx); + editor.set_read_only(true); + editor.move_to_end(&Default::default(), cx); + editor + }); + cx.subscribe(&editor, |_, _, event, cx| cx.emit(event.clone())) + .detach(); + self.editor = editor; cx.notify(); } } @@ -505,6 +512,7 @@ impl LspLogView { cx: &mut ViewContext, ) { let buffer = self.log_store.update(cx, |log_set, cx| { + // TODO kb save this buffer from overflows too log_set.enable_rpc_trace_for_language_server(&self.project, server_id, cx) }); if let Some(buffer) = buffer {