debugger beta: Fix dap_schema for DAP extensions (#31173)

Anthony Eid created

We now actually call dap_schema provided by extensions instead of
defaulting to a null `serde_json::Value`. We still need to update the
Json LSP whenever a new dap is installed.

Release Notes:

- N/A

Change summary

crates/dap/src/adapters.rs                                  |  4 
crates/dap/src/registry.rs                                  | 11 ++-
crates/dap_adapters/src/codelldb.rs                         |  2 
crates/dap_adapters/src/gdb.rs                              |  2 
crates/dap_adapters/src/go.rs                               |  2 
crates/dap_adapters/src/javascript.rs                       |  2 
crates/dap_adapters/src/php.rs                              |  2 
crates/dap_adapters/src/python.rs                           |  2 
crates/dap_adapters/src/ruby.rs                             |  2 
crates/debug_adapter_extension/src/extension_dap_adapter.rs |  4 
crates/extension/src/extension.rs                           |  2 
crates/extension_host/src/wasm_host.rs                      |  2 
crates/languages/src/json.rs                                | 20 +++++-
13 files changed, 35 insertions(+), 22 deletions(-)

Detailed changes

crates/dap/src/adapters.rs 🔗

@@ -386,7 +386,7 @@ pub trait DebugAdapter: 'static + Send + Sync {
         }
     }
 
-    fn dap_schema(&self) -> serde_json::Value;
+    async fn dap_schema(&self) -> serde_json::Value;
 }
 
 #[cfg(any(test, feature = "test-support"))]
@@ -434,7 +434,7 @@ impl DebugAdapter for FakeAdapter {
         DebugAdapterName(Self::ADAPTER_NAME.into())
     }
 
-    fn dap_schema(&self) -> serde_json::Value {
+    async fn dap_schema(&self) -> serde_json::Value {
         serde_json::Value::Null
     }
 

crates/dap/src/registry.rs 🔗

@@ -64,13 +64,16 @@ impl DapRegistry {
         );
     }
 
-    pub fn adapters_schema(&self) -> task::AdapterSchemas {
+    pub async fn adapters_schema(&self) -> task::AdapterSchemas {
         let mut schemas = AdapterSchemas(vec![]);
 
-        for (name, adapter) in self.0.read().adapters.iter() {
+        // Clone to avoid holding lock over await points
+        let adapters = self.0.read().adapters.clone();
+
+        for (name, adapter) in adapters.into_iter() {
             schemas.0.push(AdapterSchema {
-                adapter: name.clone().into(),
-                schema: adapter.dap_schema(),
+                adapter: name.into(),
+                schema: adapter.dap_schema().await,
             });
         }
 

crates/dap_adapters/src/codelldb.rs 🔗

@@ -175,7 +175,7 @@ impl DebugAdapter for CodeLldbDebugAdapter {
         })
     }
 
-    fn dap_schema(&self) -> serde_json::Value {
+    async fn dap_schema(&self) -> serde_json::Value {
         json!({
             "properties": {
                 "request": {

crates/dap_adapters/src/gdb.rs 🔗

@@ -61,7 +61,7 @@ impl DebugAdapter for GdbDebugAdapter {
         })
     }
 
-    fn dap_schema(&self) -> serde_json::Value {
+    async fn dap_schema(&self) -> serde_json::Value {
         json!({
             "oneOf": [
                 {

crates/dap_adapters/src/go.rs 🔗

@@ -27,7 +27,7 @@ impl DebugAdapter for GoDebugAdapter {
         Some(SharedString::new_static("Go").into())
     }
 
-    fn dap_schema(&self) -> serde_json::Value {
+    async fn dap_schema(&self) -> serde_json::Value {
         // Create common properties shared between launch and attach
         let common_properties = json!({
             "debugAdapter": {

crates/dap_adapters/src/javascript.rs 🔗

@@ -170,7 +170,7 @@ impl DebugAdapter for JsDebugAdapter {
         })
     }
 
-    fn dap_schema(&self) -> serde_json::Value {
+    async fn dap_schema(&self) -> serde_json::Value {
         json!({
             "oneOf": [
                 {

crates/dap_adapters/src/php.rs 🔗

@@ -101,7 +101,7 @@ impl PhpDebugAdapter {
 
 #[async_trait(?Send)]
 impl DebugAdapter for PhpDebugAdapter {
-    fn dap_schema(&self) -> serde_json::Value {
+    async fn dap_schema(&self) -> serde_json::Value {
         json!({
             "properties": {
                 "request": {

crates/dap_adapters/src/python.rs 🔗

@@ -210,7 +210,7 @@ impl DebugAdapter for PythonDebugAdapter {
         }
     }
 
-    fn dap_schema(&self) -> serde_json::Value {
+    async fn dap_schema(&self) -> serde_json::Value {
         json!({
             "properties": {
                 "request": {

crates/dap_adapters/src/ruby.rs 🔗

@@ -31,7 +31,7 @@ impl DebugAdapter for RubyDebugAdapter {
         Some(SharedString::new_static("Ruby").into())
     }
 
-    fn dap_schema(&self) -> serde_json::Value {
+    async fn dap_schema(&self) -> serde_json::Value {
         json!({
             "oneOf": [
                 {

crates/debug_adapter_extension/src/extension_dap_adapter.rs 🔗

@@ -61,8 +61,8 @@ impl DebugAdapter for ExtensionDapAdapter {
         self.debug_adapter_name.as_ref().into()
     }
 
-    fn dap_schema(&self) -> serde_json::Value {
-        serde_json::Value::Null
+    async fn dap_schema(&self) -> serde_json::Value {
+        self.extension.get_dap_schema().await.unwrap_or_default()
     }
 
     async fn get_binary(

crates/extension/src/extension.rs 🔗

@@ -144,7 +144,7 @@ pub trait Extension: Send + Sync + 'static {
         worktree: Arc<dyn WorktreeDelegate>,
     ) -> Result<DebugAdapterBinary>;
 
-    async fn dap_schema(&self) -> Result<serde_json::Value>;
+    async fn get_dap_schema(&self) -> Result<serde_json::Value>;
 }
 
 pub fn parse_wasm_extension_version(

crates/extension_host/src/wasm_host.rs 🔗

@@ -399,7 +399,7 @@ impl extension::Extension for WasmExtension {
         .await
     }
 
-    async fn dap_schema(&self) -> Result<serde_json::Value> {
+    async fn get_dap_schema(&self) -> Result<serde_json::Value> {
         self.call(|extension, store| {
             async move {
                 extension

crates/languages/src/json.rs 🔗

@@ -26,7 +26,7 @@ use std::{
     str::FromStr,
     sync::Arc,
 };
-use task::{TaskTemplate, TaskTemplates, VariableName};
+use task::{AdapterSchemas, TaskTemplate, TaskTemplates, VariableName};
 use util::{ResultExt, archive::extract_zip, fs::remove_matching, maybe, merge_json_value_into};
 
 const SERVER_PATH: &str =
@@ -76,7 +76,11 @@ impl JsonLspAdapter {
         }
     }
 
-    fn get_workspace_config(language_names: Vec<String>, cx: &mut App) -> Value {
+    fn get_workspace_config(
+        language_names: Vec<String>,
+        adapter_schemas: AdapterSchemas,
+        cx: &mut App,
+    ) -> Value {
         let keymap_schema = KeymapFile::generate_json_schema_for_registered_actions(cx);
         let font_names = &cx.text_system().all_font_names();
         let settings_schema = cx.global::<SettingsStore>().json_schema(
@@ -87,7 +91,6 @@ impl JsonLspAdapter {
             cx,
         );
 
-        let adapter_schemas = cx.global::<DapRegistry>().adapters_schema();
         let tasks_schema = task::TaskTemplates::generate_json_schema();
         let debug_schema = task::DebugTaskFile::generate_json_schema(&adapter_schemas);
         let snippets_schema = snippet_provider::format::VsSnippetsFile::generate_json_schema();
@@ -163,8 +166,15 @@ impl JsonLspAdapter {
             }
         }
         let mut writer = self.workspace_config.write().await;
-        let config =
-            cx.update(|cx| Self::get_workspace_config(self.languages.language_names(), cx))?;
+
+        let adapter_schemas = cx
+            .read_global::<DapRegistry, _>(|dap_registry, _| dap_registry.to_owned())?
+            .adapters_schema()
+            .await;
+
+        let config = cx.update(|cx| {
+            Self::get_workspace_config(self.languages.language_names().clone(), adapter_schemas, cx)
+        })?;
         writer.replace(config.clone());
         return Ok(config);
     }