extensions: Add "Debug Adapters" category to the extension store (#32845)

Piotr Osiewicz created

Closes #ISSUE

Release Notes:

- N/A

Change summary

crates/collab/migrations.sqlite/20221109000000_test_schema.sql                             |  1 
crates/collab/migrations/20250617082236_add_debug_adapter_provides_field_to_extensions.sql |  2 
crates/collab/src/db/queries/extensions.rs                                                 |  7 
crates/collab/src/db/tables/extension_version.rs                                           |  5 
crates/debugger_ui/src/debugger_panel.rs                                                   | 29 
crates/extension_cli/src/main.rs                                                           |  4 
crates/extensions_ui/src/extensions_ui.rs                                                  |  2 
crates/rpc/src/extension.rs                                                                |  1 
crates/zed_actions/src/lib.rs                                                              |  1 
docs/src/debugger.md                                                                       |  3 
10 files changed, 46 insertions(+), 9 deletions(-)

Detailed changes

crates/collab/migrations.sqlite/20221109000000_test_schema.sql 🔗

@@ -465,6 +465,7 @@ CREATE TABLE extension_versions (
     provides_slash_commands BOOLEAN NOT NULL DEFAULT FALSE,
     provides_indexed_docs_providers BOOLEAN NOT NULL DEFAULT FALSE,
     provides_snippets BOOLEAN NOT NULL DEFAULT FALSE,
+    provides_debug_adapters BOOLEAN NOT NULL DEFAULT FALSE,
     PRIMARY KEY (extension_id, version)
 );
 

crates/collab/src/db/queries/extensions.rs 🔗

@@ -321,6 +321,9 @@ impl Database {
                         provides_snippets: ActiveValue::Set(
                             version.provides.contains(&ExtensionProvides::Snippets),
                         ),
+                        provides_debug_adapters: ActiveValue::Set(
+                            version.provides.contains(&ExtensionProvides::DebugAdapters),
+                        ),
                         download_count: ActiveValue::NotSet,
                     }
                 }))
@@ -431,6 +434,10 @@ fn apply_provides_filter(
         condition = condition.add(extension_version::Column::ProvidesSnippets.eq(true));
     }
 
+    if provides_filter.contains(&ExtensionProvides::DebugAdapters) {
+        condition = condition.add(extension_version::Column::ProvidesDebugAdapters.eq(true));
+    }
+
     condition
 }
 

crates/collab/src/db/tables/extension_version.rs 🔗

@@ -27,6 +27,7 @@ pub struct Model {
     pub provides_slash_commands: bool,
     pub provides_indexed_docs_providers: bool,
     pub provides_snippets: bool,
+    pub provides_debug_adapters: bool,
 }
 
 impl Model {
@@ -68,6 +69,10 @@ impl Model {
             provides.insert(ExtensionProvides::Snippets);
         }
 
+        if self.provides_debug_adapters {
+            provides.insert(ExtensionProvides::DebugAdapters);
+        }
+
         provides
     }
 }

crates/debugger_ui/src/debugger_panel.rs 🔗

@@ -1430,14 +1430,27 @@ impl Render for DebugPanel {
                                 ),
                             )
                             .child(
-                                h_flex().flex_shrink().child(
-                                    Button::new("spawn-new-session-empty-state", "New Session")
-                                        .size(ButtonSize::Large)
-                                        .on_click(|_, window, cx| {
-                                            window.dispatch_action(crate::Start.boxed_clone(), cx);
-                                        }),
-                                ),
-                            ),
+                                v_flex().gap_4().items_center()
+                                .justify_center()
+                                .child(
+                                    h_flex().flex_shrink().child(
+                                        Button::new("spawn-new-session-empty-state", "New Session")
+                                            .size(ButtonSize::Large)
+                                            .on_click(|_, window, cx| {
+                                                window.dispatch_action(crate::Start.boxed_clone(), cx);
+                                            })
+                                    )
+                                )
+                                .child(
+                                    h_flex().flex_shrink().child(
+                                        Button::new("spawn-new-session-install-extensions", "Install Debug Extensions")
+                                            .label_size(LabelSize::Small)
+                                            .on_click(|_, window, cx| {
+                                                window.dispatch_action(zed_actions::Extensions { category_filter: Some(zed_actions::ExtensionCategoryFilter::DebugAdapters)}.boxed_clone(), cx);
+                                            })
+                                    )
+                                )
+                            )
                     )
                 }
             })

crates/extension_cli/src/main.rs 🔗

@@ -152,6 +152,10 @@ fn extension_provides(manifest: &ExtensionManifest) -> BTreeSet<ExtensionProvide
         provides.insert(ExtensionProvides::Snippets);
     }
 
+    if !manifest.debug_adapters.is_empty() {
+        provides.insert(ExtensionProvides::DebugAdapters);
+    }
+
     provides
 }
 

crates/extensions_ui/src/extensions_ui.rs 🔗

@@ -64,6 +64,7 @@ pub fn init(cx: &mut App) {
                             ExtensionProvides::IndexedDocsProviders
                         }
                         ExtensionCategoryFilter::Snippets => ExtensionProvides::Snippets,
+                        ExtensionCategoryFilter::DebugAdapters => ExtensionProvides::DebugAdapters,
                     });
 
                     let existing = workspace
@@ -175,6 +176,7 @@ fn extension_provides_label(provides: ExtensionProvides) -> &'static str {
         ExtensionProvides::SlashCommands => "Slash Commands",
         ExtensionProvides::IndexedDocsProviders => "Indexed Docs Providers",
         ExtensionProvides::Snippets => "Snippets",
+        ExtensionProvides::DebugAdapters => "Debug Adapters",
     }
 }
 

crates/rpc/src/extension.rs 🔗

@@ -45,6 +45,7 @@ pub enum ExtensionProvides {
     SlashCommands,
     IndexedDocsProviders,
     Snippets,
+    DebugAdapters,
 }
 
 #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]

crates/zed_actions/src/lib.rs 🔗

@@ -53,6 +53,7 @@ pub enum ExtensionCategoryFilter {
     SlashCommands,
     IndexedDocsProviders,
     Snippets,
+    DebugAdapters,
 }
 
 #[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]

docs/src/debugger.md 🔗

@@ -29,7 +29,8 @@ Zed supports a variety of debug adapters for different programming languages out
 
 These adapters enable Zed to provide a consistent debugging experience across multiple languages while leveraging the specific features and capabilities of each debugger.
 
-> Is your desired debugger not listed? You can contribute by adding support for your favorite language or debugger. Check out our [debugger extensions](extensions/debugger-extensions.md) documentation for more information.
+> Is your desired debugger not listed? You can install a [Debug Adapter extension](https://zed.dev/extensions?filter=debug-adapters) to add support for your favorite debugger.
+> If that's not enough, you can contribute by creating an extension yourself. Check out our [debugger extensions](extensions/debugger-extensions.md) documentation for more information.
 
 ## Getting Started