Improve obvious faults

Kirill Bulatov created

Change summary

crates/editor/src/editor.rs   | 94 +++++++++++++++++++++++++-----------
crates/editor/src/element.rs  |  4 
crates/project/src/project.rs | 79 +++++++++++++++---------------
3 files changed, 106 insertions(+), 71 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -1178,6 +1178,7 @@ impl InlayHintState {
 
     pub fn update_if_newer(&self, new_hints: Vec<InlayHint>, 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<TransactionId> {
         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<Self>) {
@@ -7190,7 +7192,7 @@ impl Editor {
         event: &multi_buffer::Event,
         cx: &mut ViewContext<Self>,
     ) {
-        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(),
-            }),
+            } => {
+                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() })
-            }
-            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),
+                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::DiagnosticsUpdated => {
                 self.refresh_active_diagnostics(cx);
+                false
             }
-            _ => {}
+            _ => true,
+        };
+
+        if update_inlay_hints {
+            self.update_inlay_hints(cx);
         }
     }
 

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,

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<ProjectEntryId>),
     WorktreeAdded,
@@ -2814,15 +2815,18 @@ impl Project {
                 .on_request::<lsp::request::InlayHintRefreshRequest, _, _>({
                     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::<lsp::notification::DidChangeWatchedFiles>(params)
-                                .log_err();
-                        }
+                    if !params.changes.is_empty() {
+                        server
+                            .notify::<lsp::notification::DidChangeWatchedFiles>(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 {