Feature gate the LSP button (#33463)

Kirill Bulatov created

Follow-up of https://github.com/zed-industries/zed/pull/32490

The tool still looks like designed by professional developers, and still
may change its UX based on the internal feedback.

Release Notes:

- N/A

Change summary

Cargo.lock                            | 1 +
crates/language_tools/Cargo.toml      | 1 +
crates/language_tools/src/lsp_tool.rs | 9 +++++++++
crates/project/src/lsp_store.rs       | 4 ++--
4 files changed, 13 insertions(+), 2 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -9015,6 +9015,7 @@ dependencies = [
  "collections",
  "copilot",
  "editor",
+ "feature_flags",
  "futures 0.3.31",
  "gpui",
  "itertools 0.14.0",

crates/language_tools/Cargo.toml 🔗

@@ -18,6 +18,7 @@ client.workspace = true
 collections.workspace = true
 copilot.workspace = true
 editor.workspace = true
+feature_flags.workspace = true
 futures.workspace = true
 gpui.workspace = true
 itertools.workspace = true

crates/language_tools/src/lsp_tool.rs 🔗

@@ -3,6 +3,7 @@ use std::{collections::hash_map, path::PathBuf, sync::Arc, time::Duration};
 use client::proto;
 use collections::{HashMap, HashSet};
 use editor::{Editor, EditorEvent};
+use feature_flags::FeatureFlagAppExt as _;
 use gpui::{Corner, DismissEvent, Entity, Focusable as _, Subscription, Task, WeakEntity, actions};
 use language::{BinaryStatus, BufferId, LocalFile, ServerHealth};
 use lsp::{LanguageServerId, LanguageServerName, LanguageServerSelector};
@@ -244,6 +245,10 @@ impl LanguageServers {
             );
         }
     }
+
+    fn is_empty(&self) -> bool {
+        self.binary_statuses.is_empty() && self.health_statuses.is_empty()
+    }
 }
 
 #[derive(Debug)]
@@ -865,6 +870,10 @@ impl StatusItemView for LspTool {
 
 impl Render for LspTool {
     fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl ui::IntoElement {
+        if !cx.is_staff() || self.state.read(cx).language_servers.is_empty() {
+            return div();
+        }
+
         let Some(lsp_picker) = self.lsp_picker.clone() else {
             return div();
         };

crates/project/src/lsp_store.rs 🔗

@@ -2484,11 +2484,11 @@ impl LocalLspStore {
                                }
                            }
                         };
-                        let lsp_tool = self.weak.clone();
+                        let lsp_store = self.weak.clone();
                         let server_name = server_node.name();
                         let buffer_abs_path = abs_path.to_string_lossy().to_string();
                         cx.defer(move |cx| {
-                            lsp_tool.update(cx, |_, cx| cx.emit(LspStoreEvent::LanguageServerUpdate {
+                            lsp_store.update(cx, |_, cx| cx.emit(LspStoreEvent::LanguageServerUpdate {
                                 language_server_id: server_id,
                                 name: server_name,
                                 message: proto::update_language_server::Variant::RegisteredForBuffer(proto::RegisteredForBuffer {