Hide inlay hints toggle if they are not supported by the current editor (#3041)

Kirill Bulatov created

Release Notes:

- N/A

Change summary

crates/editor/src/editor.rs                     | 23 ++++++++
crates/quick_action_bar/src/quick_action_bar.rs | 52 ++++++++++--------
2 files changed, 53 insertions(+), 22 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -8588,6 +8588,29 @@ impl Editor {
 
         self.handle_input(text, cx);
     }
+
+    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
+        let Some(project) = self.project.as_ref() else {
+            return false;
+        };
+        let project = project.read(cx);
+
+        let mut supports = false;
+        self.buffer().read(cx).for_each_buffer(|buffer| {
+            if !supports {
+                supports = project
+                    .language_servers_for_buffer(buffer.read(cx), cx)
+                    .any(
+                        |(_, server)| match server.capabilities().inlay_hint_provider {
+                            Some(lsp::OneOf::Left(enabled)) => enabled,
+                            Some(lsp::OneOf::Right(_)) => true,
+                            None => false,
+                        },
+                    )
+            }
+        });
+        supports
+    }
 }
 
 fn inlay_hint_settings(

crates/quick_action_bar/src/quick_action_bar.rs 🔗

@@ -48,24 +48,26 @@ impl View for QuickActionBar {
             return Empty::new().into_any();
         };
 
-        let inlay_hints_enabled = editor.read(cx).inlay_hints_enabled();
-        let mut bar = Flex::row().with_child(render_quick_action_bar_button(
-            0,
-            "icons/inlay_hint.svg",
-            inlay_hints_enabled,
-            (
-                "Toggle Inlay Hints".to_string(),
-                Some(Box::new(editor::ToggleInlayHints)),
-            ),
-            cx,
-            |this, cx| {
-                if let Some(editor) = this.active_editor() {
-                    editor.update(cx, |editor, cx| {
-                        editor.toggle_inlay_hints(&editor::ToggleInlayHints, cx);
-                    });
-                }
-            },
-        ));
+        let mut bar = Flex::row();
+        if editor.read(cx).supports_inlay_hints(cx) {
+            bar = bar.with_child(render_quick_action_bar_button(
+                0,
+                "icons/inlay_hint.svg",
+                editor.read(cx).inlay_hints_enabled(),
+                (
+                    "Toggle Inlay Hints".to_string(),
+                    Some(Box::new(editor::ToggleInlayHints)),
+                ),
+                cx,
+                |this, cx| {
+                    if let Some(editor) = this.active_editor() {
+                        editor.update(cx, |editor, cx| {
+                            editor.toggle_inlay_hints(&editor::ToggleInlayHints, cx);
+                        });
+                    }
+                },
+            ));
+        }
 
         if editor.read(cx).buffer().read(cx).is_singleton() {
             let search_bar_shown = !self.buffer_search_bar.read(cx).is_dismissed();
@@ -163,12 +165,18 @@ impl ToolbarItemView for QuickActionBar {
 
                 if let Some(editor) = active_item.downcast::<Editor>() {
                     let mut inlay_hints_enabled = editor.read(cx).inlay_hints_enabled();
+                    let mut supports_inlay_hints = editor.read(cx).supports_inlay_hints(cx);
                     self._inlay_hints_enabled_subscription =
                         Some(cx.observe(&editor, move |_, editor, cx| {
-                            let new_inlay_hints_enabled = editor.read(cx).inlay_hints_enabled();
-                            if inlay_hints_enabled != new_inlay_hints_enabled {
-                                inlay_hints_enabled = new_inlay_hints_enabled;
-                                cx.notify();
+                            let editor = editor.read(cx);
+                            let new_inlay_hints_enabled = editor.inlay_hints_enabled();
+                            let new_supports_inlay_hints = editor.supports_inlay_hints(cx);
+                            let should_notify = inlay_hints_enabled != new_inlay_hints_enabled
+                                || supports_inlay_hints != new_supports_inlay_hints;
+                            inlay_hints_enabled = new_inlay_hints_enabled;
+                            supports_inlay_hints = new_supports_inlay_hints;
+                            if should_notify {
+                                cx.notify()
                             }
                         }));
                     ToolbarItemLocation::PrimaryRight { flex: None }