zed: Add `OpenRequestKind` (#34860)

Marshall Bowers created

This PR refactors the `OpenRequest` to introduce an `OpenRequestKind`
enum.

It seems most of the fields on `OpenRequest` are mutually-exclusive, so
it is better to model it as an enum rather than using a bunch of
`Option`s.

There are likely more of the existing fields that can be converted into
`OpenRequestKind` variants, but I'm being conservative for this first
pass.

Release Notes:

- N/A

Change summary

crates/zed/src/main.rs              | 54 ++++++++++++++++--------------
crates/zed/src/zed/open_listener.rs | 23 +++++++++----
2 files changed, 45 insertions(+), 32 deletions(-)

Detailed changes

crates/zed/src/main.rs 🔗

@@ -55,6 +55,8 @@ use zed::{
     inline_completion_registry, open_paths_with_positions,
 };
 
+use crate::zed::OpenRequestKind;
+
 #[cfg(feature = "mimalloc")]
 #[global_allocator]
 static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
@@ -746,32 +748,34 @@ pub fn main() {
 }
 
 fn handle_open_request(request: OpenRequest, app_state: Arc<AppState>, cx: &mut App) {
-    if let Some(connection) = request.cli_connection {
-        let app_state = app_state.clone();
-        cx.spawn(async move |cx| handle_cli_connection(connection, app_state, cx).await)
-            .detach();
-        return;
-    }
-
-    if let Some(action_index) = request.dock_menu_action {
-        cx.perform_dock_menu_action(action_index);
-        return;
-    }
+    if let Some(kind) = request.kind {
+        match kind {
+            OpenRequestKind::CliConnection(connection) => {
+                let app_state = app_state.clone();
+                cx.spawn(async move |cx| handle_cli_connection(connection, app_state, cx).await)
+                    .detach();
+            }
+            OpenRequestKind::Extension { extension_id } => {
+                cx.spawn(async move |cx| {
+                    let workspace =
+                        workspace::get_any_active_workspace(app_state, cx.clone()).await?;
+                    workspace.update(cx, |_, window, cx| {
+                        window.dispatch_action(
+                            Box::new(zed_actions::Extensions {
+                                category_filter: None,
+                                id: Some(extension_id),
+                            }),
+                            cx,
+                        );
+                    })
+                })
+                .detach_and_log_err(cx);
+            }
+            OpenRequestKind::DockMenuAction { index } => {
+                cx.perform_dock_menu_action(index);
+            }
+        }
 
-    if let Some(extension) = request.extension_id {
-        cx.spawn(async move |cx| {
-            let workspace = workspace::get_any_active_workspace(app_state, cx.clone()).await?;
-            workspace.update(cx, |_, window, cx| {
-                window.dispatch_action(
-                    Box::new(zed_actions::Extensions {
-                        category_filter: None,
-                        id: Some(extension),
-                    }),
-                    cx,
-                );
-            })
-        })
-        .detach_and_log_err(cx);
         return;
     }
 

crates/zed/src/zed/open_listener.rs 🔗

@@ -30,14 +30,19 @@ use workspace::{AppState, OpenOptions, SerializedWorkspaceLocation, Workspace};
 
 #[derive(Default, Debug)]
 pub struct OpenRequest {
-    pub cli_connection: Option<(mpsc::Receiver<CliRequest>, IpcSender<CliResponse>)>,
+    pub kind: Option<OpenRequestKind>,
     pub open_paths: Vec<String>,
     pub diff_paths: Vec<[String; 2]>,
     pub open_channel_notes: Vec<(u64, Option<String>)>,
     pub join_channel: Option<u64>,
     pub ssh_connection: Option<SshConnectionOptions>,
-    pub dock_menu_action: Option<usize>,
-    pub extension_id: Option<String>,
+}
+
+#[derive(Debug)]
+pub enum OpenRequestKind {
+    CliConnection((mpsc::Receiver<CliRequest>, IpcSender<CliResponse>)),
+    Extension { extension_id: String },
+    DockMenuAction { index: usize },
 }
 
 impl OpenRequest {
@@ -45,9 +50,11 @@ impl OpenRequest {
         let mut this = Self::default();
         for url in request.urls {
             if let Some(server_name) = url.strip_prefix("zed-cli://") {
-                this.cli_connection = Some(connect_to_cli(server_name)?);
+                this.kind = Some(OpenRequestKind::CliConnection(connect_to_cli(server_name)?));
             } else if let Some(action_index) = url.strip_prefix("zed-dock-action://") {
-                this.dock_menu_action = Some(action_index.parse()?);
+                this.kind = Some(OpenRequestKind::DockMenuAction {
+                    index: action_index.parse()?,
+                });
             } else if let Some(file) = url.strip_prefix("file://") {
                 this.parse_file_path(file)
             } else if let Some(file) = url.strip_prefix("zed://file") {
@@ -55,8 +62,10 @@ impl OpenRequest {
             } else if let Some(file) = url.strip_prefix("zed://ssh") {
                 let ssh_url = "ssh:/".to_string() + file;
                 this.parse_ssh_file_path(&ssh_url, cx)?
-            } else if let Some(file) = url.strip_prefix("zed://extension/") {
-                this.extension_id = Some(file.to_string())
+            } else if let Some(extension_id) = url.strip_prefix("zed://extension/") {
+                this.kind = Some(OpenRequestKind::Extension {
+                    extension_id: extension_id.to_string(),
+                });
             } else if url.starts_with("ssh://") {
                 this.parse_ssh_file_path(&url, cx)?
             } else if let Some(request_path) = parse_zed_link(&url, cx) {