diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index a583bdee0e..cc3368f677 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1178,6 +1178,7 @@ impl InlayHintState { pub fn update_if_newer(&self, new_hints: Vec, new_timestamp: usize) { let last_updated_timestamp = self.last_updated_timestamp.load(atomic::Ordering::Acquire); + dbg!(last_updated_timestamp, new_timestamp, new_hints.len()); if last_updated_timestamp < new_timestamp { let mut guard = self.hints.write(); match self.last_updated_timestamp.compare_exchange( @@ -1330,12 +1331,22 @@ impl Editor { let soft_wrap_mode_override = (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None); - let mut project_subscription = None; + let mut project_subscriptions = Vec::new(); if mode == EditorMode::Full && buffer.read(cx).is_singleton() { if let Some(project) = project.as_ref() { - project_subscription = Some(cx.observe(project, |_, _, cx| { + project_subscriptions.push(cx.observe(project, |_, _, cx| { cx.emit(Event::TitleChanged); - })) + })); + project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| { + match event { + project::Event::LanguageServerReady(_) => { + dbg!("@@@@@@@@@@@@@ ReceiveD event"); + editor.update_inlay_hints(cx); + } + _ => {} + }; + cx.notify() + })); } } @@ -1399,9 +1410,7 @@ impl Editor { ], }; - if let Some(project_subscription) = project_subscription { - this._subscriptions.push(project_subscription); - } + this._subscriptions.extend(project_subscriptions); this.end_selection(cx); this.scroll_manager.show_scrollbar(cx); @@ -1415,8 +1424,6 @@ impl Editor { } this.report_editor_event("open", None, cx); - // this.update_inlay_hints(cx); - this } @@ -2644,14 +2651,12 @@ impl Editor { // This way we can reuse tasks result for the same timestamp? The counter has to be global among all buffer changes & other reloads. let new_timestamp = self.inlay_hints.new_timestamp(); - // TODO kb this would not work until the language server is ready, how to wait for it? // TODO kb waiting before the server starts and handling workspace/inlayHint/refresh commands is kind of orthogonal? // need to be able to not to start new tasks, if current one is running on the same state already. cx.spawn(|editor, mut cx| async move { let task = editor.update(&mut cx, |editor, cx| { editor.project.as_ref().map(|project| { project.update(cx, |project, cx| { - // TODO kb use visible_lines as a range instead? let end = generator_buffer.read(cx).len(); project.inlay_hints(generator_buffer, 0..end, cx) }) @@ -6707,10 +6712,7 @@ impl Editor { ) -> Option { self.start_transaction_at(Instant::now(), cx); update(self, cx); - let transaction_id = self.end_transaction_at(Instant::now(), cx); - // TODO kb is this the right idea? Maybe instead we should react on `BufferEvent::Edited`? - self.update_inlay_hints(cx); - transaction_id + self.end_transaction_at(Instant::now(), cx) } fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext) { @@ -7190,7 +7192,7 @@ impl Editor { event: &multi_buffer::Event, cx: &mut ViewContext, ) { - match event { + let update_inlay_hints = match event { multi_buffer::Event::Edited => { self.refresh_active_diagnostics(cx); self.refresh_code_actions(cx); @@ -7198,30 +7200,62 @@ impl Editor { self.update_visible_copilot_suggestion(cx); } cx.emit(Event::BufferEdited); + true } multi_buffer::Event::ExcerptsAdded { buffer, predecessor, excerpts, - } => cx.emit(Event::ExcerptsAdded { - buffer: buffer.clone(), - predecessor: *predecessor, - excerpts: excerpts.clone(), - }), - multi_buffer::Event::ExcerptsRemoved { ids } => { - cx.emit(Event::ExcerptsRemoved { ids: ids.clone() }) + } => { + cx.emit(Event::ExcerptsAdded { + buffer: buffer.clone(), + predecessor: *predecessor, + excerpts: excerpts.clone(), + }); + // TODO kb wrong? + false + } + multi_buffer::Event::ExcerptsRemoved { ids } => { + cx.emit(Event::ExcerptsRemoved { ids: ids.clone() }); + false + } + multi_buffer::Event::Reparsed => { + cx.emit(Event::Reparsed); + true + } + multi_buffer::Event::DirtyChanged => { + cx.emit(Event::DirtyChanged); + true + } + multi_buffer::Event::Saved => { + cx.emit(Event::Saved); + false + } + multi_buffer::Event::FileHandleChanged => { + cx.emit(Event::TitleChanged); + true + } + multi_buffer::Event::Reloaded => { + cx.emit(Event::TitleChanged); + true + } + multi_buffer::Event::DiffBaseChanged => { + cx.emit(Event::DiffBaseChanged); + true + } + multi_buffer::Event::Closed => { + cx.emit(Event::Closed); + false } - multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed), - multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged), - multi_buffer::Event::Saved => cx.emit(Event::Saved), - multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged), - multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged), - multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged), - multi_buffer::Event::Closed => cx.emit(Event::Closed), multi_buffer::Event::DiagnosticsUpdated => { self.refresh_active_diagnostics(cx); + false } - _ => {} + _ => true, + }; + + if update_inlay_hints { + self.update_inlay_hints(cx); } } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index ee0bd3e8b4..2a58f959d3 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1819,9 +1819,9 @@ impl LineWithInvisibles { cx, ); - // TODO kb bad: cloning happens very frequently, check the timestamp first + // TODO kb bad: syscalls + cloning happen very frequently, check the timestamp first let new_hints = editor.inlay_hints.read(); - // dbg!(new_hints); + dbg!(new_hints.last()); self.draw_invisibles( &selection_ranges, diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 46da79c5b7..5625efddc2 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -254,6 +254,7 @@ pub enum Event { LanguageServerAdded(LanguageServerId), LanguageServerRemoved(LanguageServerId), LanguageServerLog(LanguageServerId, String), + LanguageServerReady(LanguageServerId), Notification(String), ActiveEntryChanged(Option), WorktreeAdded, @@ -2814,15 +2815,18 @@ impl Project { .on_request::({ dbg!("!!!!!!!!!!!!!!"); let this = this.downgrade(); - move |params, cx| async move { - // TODO kb: trigger an event, to call on every open editor + move |params, mut cx| async move { // TODO kb does not get called now, why? - dbg!("@@@@@@@@@@@@@@@@@@@@@@@@@@"); + dbg!("#########################"); - let _this = this + let this = this .upgrade(&cx) .ok_or_else(|| anyhow!("project dropped"))?; dbg!(params); + this.update(&mut cx, |_, cx| { + dbg!("@@@@@@@@@@@@@ SENT event"); + cx.emit(Event::LanguageServerReady(server_id)); + }); Ok(()) } }) @@ -5477,41 +5481,39 @@ impl Project { let abs_path = worktree_handle.read(cx).abs_path(); for server_id in &language_server_ids { - if let Some(server) = self.language_servers.get(server_id) { - if let LanguageServerState::Running { - server, - watched_paths, - .. - } = server - { - if let Some(watched_paths) = watched_paths.get(&worktree_id) { - let params = lsp::DidChangeWatchedFilesParams { - changes: changes - .iter() - .filter_map(|(path, _, change)| { - if !watched_paths.is_match(&path) { - return None; - } - let typ = match change { - PathChange::Loaded => return None, - PathChange::Added => lsp::FileChangeType::CREATED, - PathChange::Removed => lsp::FileChangeType::DELETED, - PathChange::Updated => lsp::FileChangeType::CHANGED, - PathChange::AddedOrUpdated => lsp::FileChangeType::CHANGED, - }; - Some(lsp::FileEvent { - uri: lsp::Url::from_file_path(abs_path.join(path)).unwrap(), - typ, - }) + if let Some(LanguageServerState::Running { + server, + watched_paths, + .. + }) = self.language_servers.get(server_id) + { + if let Some(watched_paths) = watched_paths.get(&worktree_id) { + let params = lsp::DidChangeWatchedFilesParams { + changes: changes + .iter() + .filter_map(|(path, _, change)| { + if !watched_paths.is_match(&path) { + return None; + } + let typ = match change { + PathChange::Loaded => return None, + PathChange::Added => lsp::FileChangeType::CREATED, + PathChange::Removed => lsp::FileChangeType::DELETED, + PathChange::Updated => lsp::FileChangeType::CHANGED, + PathChange::AddedOrUpdated => lsp::FileChangeType::CHANGED, + }; + Some(lsp::FileEvent { + uri: lsp::Url::from_file_path(abs_path.join(path)).unwrap(), + typ, }) - .collect(), - }; + }) + .collect(), + }; - if !params.changes.is_empty() { - server - .notify::(params) - .log_err(); - } + if !params.changes.is_empty() { + server + .notify::(params) + .log_err(); } } } @@ -7385,10 +7387,9 @@ impl Project { self.language_server_ids_for_buffer(buffer, cx) .into_iter() .filter_map(|server_id| { - let server = self.language_servers.get(&server_id)?; if let LanguageServerState::Running { adapter, server, .. - } = server + } = self.language_servers.get(&server_id)? { Some((adapter, server)) } else {