diff --git a/crates/dap_adapters/schemas/CodeLLDB.json b/crates/dap_adapters/schemas/CodeLLDB.json new file mode 100644 index 0000000000000000000000000000000000000000..201cb4c9aba38965e1536dde2255f3ed40d99dd9 --- /dev/null +++ b/crates/dap_adapters/schemas/CodeLLDB.json @@ -0,0 +1,253 @@ +{ + "allOf": [ + { + "if": { "properties": { "request": { "const": "launch" } }, "required": ["request"] }, + "then": { + "properties": { + "program": { "description": "Path to the program to debug.", "type": "string" }, + "cargo": { + "description": "Cargo invocation parameters.", + "type": "object", + "properties": { + "args": { "description": "Cargo command line arguments.", "type": "array", "default": [] }, + "env": { + "description": "Additional environment variables passed to Cargo.", + "type": "object", + "patternProperties": { ".*": { "type": "string" } }, + "default": {} + }, + "cwd": { "description": "Cargo working directory.", "type": "string" }, + "problemMatcher": { + "description": "Problem matcher(s) to apply to Cargo output.", + "type": ["string", "array"] + }, + "filter": { + "description": "Filter applied to compilation artifacts.", + "type": "object", + "properties": { "name": { "type": "string" }, "kind": { "type": "string" } } + } + }, + "required": ["args"], + "additionalProperties": false, + "defaultSnippets": [ + { + "label": "Library unit tests", + "body": { "args": ["test", "--no-run", "--lib"], "filter": { "kind": "lib" } } + }, + { "label": "Executable", "body": { "args": ["build", "--bin=${1:}"], "filter": { "kind": "bin" } } } + ] + }, + "args": { "description": "Program arguments.", "type": ["array", "string"] }, + "cwd": { "description": "Program working directory.", "type": "string" }, + "env": { + "description": "Additional environment variables.", + "type": "object", + "patternProperties": { ".*": { "type": "string" } } + }, + "envFile": { "description": "File to read the environment variables from.", "type": "string" }, + "stdio": { + "description": "Destination for stdio streams: null = send to debugger console or a terminal, \"\" = attach to a file/tty/fifo.", + "type": ["null", "string", "array", "object"], + "default": null + }, + "terminal": { + "description": "Terminal type to use.", + "type": "string", + "enum": ["integrated", "external", "console"], + "enumDescriptions": [ + "Use integrated terminal in VSCode.", + "Use external terminal window.", + "Use VScode Debug Console for stdout and stderr. Stdin will be unavailable." + ], + "default": "integrated" + }, + "console": { + "description": "Terminal type to use. (This setting is a compatibility alias of 'terminal'.)", + "type": "string", + "enum": ["integratedTerminal", "externalTerminal", "internalConsole"], + "enumDescriptions": [ + "Use integrated terminal in VSCode.", + "Use external terminal window.", + "Use VScode Debug Console for stdout and stderr. Stdin will be unavailable." + ] + }, + "stopOnEntry": { + "description": "Automatically stop debuggee after launch.", + "type": "boolean", + "default": false + }, + "initCommands": { + "description": "Initialization commands executed upon debugger startup.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "targetCreateCommands": { + "description": "Commands that create the debug target.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "preRunCommands": { + "description": "Commands executed just before the program is launched.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "processCreateCommands": { + "description": "Commands that create the debuggee process.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "postRunCommands": { + "description": "Commands executed just after the program has been launched.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "preTerminateCommands": { + "description": "Commands executed just before the debuggee is terminated or disconnected from.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "exitCommands": { + "description": "Commands executed at the end of debugging session.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "expressions": { + "description": "The default evaluator type used for expressions.", + "type": "string", + "enum": ["simple", "python", "native"] + }, + "sourceMap": { + "description": "Source path remapping between the build machine and the local machine. Each item is a pair of remote and local path prefixes.", + "type": "object", + "patternProperties": { ".*": { "type": ["string", "null"] } }, + "default": {} + }, + "relativePathBase": { + "description": "Base directory used for resolution of relative source paths. Defaults to \"${ZED_WORKTREE_ROOT}\".", + "type": "string" + }, + "sourceLanguages": { + "description": "A list of source languages to enable language-specific features for.", + "type": "array", + "default": [] + }, + "reverseDebugging": { + "description": "Enable reverse debugging (Requires reverse execution support in the debug server, see User's Manual for details).", + "type": "boolean", + "default": false + }, + "breakpointMode": { + "description": "Specifies how source breakpoints should be set.", + "type": "string", + "enum": ["path", "file"], + "enumDescriptions": [ + "Resolve locations using full source file path.", + "Resolve locations using file name only." + ] + } + }, + "anyOf": [{ "required": ["program"] }, { "required": ["targetCreateCommands"] }, { "required": ["cargo"] }] + } + }, + { + "if": { "properties": { "request": { "const": "attach" } }, "required": ["request"] }, + "then": { + "properties": { + "program": { "description": "Path to the program to attach to.", "type": "string" }, + "pid": { + "description": "Process id to attach to.", + "type": ["integer", "string"], + "default": "${command:pickMyProcess}" + }, + "stopOnEntry": { + "description": "Automatically stop debuggee after attach.", + "type": "boolean", + "default": false + }, + "waitFor": { + "description": "Wait for the process to launch (MacOS only).", + "type": "boolean", + "default": false + }, + "initCommands": { + "description": "Initialization commands executed upon debugger startup.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "targetCreateCommands": { + "description": "Commands that create the debug target.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "preRunCommands": { + "description": "Commands executed just before the program is launched.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "processCreateCommands": { + "description": "Commands that create the debuggee process.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "postRunCommands": { + "description": "Commands executed just after the program has been launched.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "exitCommands": { + "description": "Commands executed at the end of debugging session.", + "type": "array", + "items": { "type": "string" }, + "default": [] + }, + "expressions": { + "description": "The default evaluator type used for expressions.", + "type": "string", + "enum": ["simple", "python", "native"] + }, + "sourceMap": { + "description": "Source path remapping between the build machine and the local machine. Each item is a pair of remote and local path prefixes.", + "type": "object", + "patternProperties": { ".*": { "type": ["string", "null"] } }, + "default": {} + }, + "relativePathBase": { + "description": "Base directory used for resolution of relative source paths. Defaults to \"${ZED_WORKTREE_ROOT}\".", + "type": "string" + }, + "sourceLanguages": { + "description": "A list of source languages to enable language-specific features for.", + "type": "array", + "default": [] + }, + "reverseDebugging": { + "description": "Enable reverse debugging (Requires reverse execution support in the debug server, see User's Manual for details).", + "type": "boolean", + "default": false + }, + "breakpointMode": { + "description": "Specifies how source breakpoints should be set.", + "type": "string", + "enum": ["path", "file"], + "enumDescriptions": [ + "Resolve locations using full source file path.", + "Resolve locations using file name only." + ] + } + } + } + } + ] +} diff --git a/crates/dap_adapters/src/codelldb.rs b/crates/dap_adapters/src/codelldb.rs index fd35bc748532f6879615b06fc8d03a24a618a300..5696844e3098f107250c1851b8802c45e842f759 100644 --- a/crates/dap_adapters/src/codelldb.rs +++ b/crates/dap_adapters/src/codelldb.rs @@ -1,4 +1,9 @@ -use std::{borrow::Cow, collections::HashMap, path::PathBuf, sync::OnceLock}; +use std::{ + borrow::Cow, + collections::HashMap, + path::PathBuf, + sync::{LazyLock, OnceLock}, +}; use anyhow::{Context as _, Result}; use async_trait::async_trait; @@ -12,12 +17,12 @@ use util::fs::remove_matching; use crate::*; #[derive(Default)] -pub(crate) struct CodeLldbDebugAdapter { +pub struct CodeLldbDebugAdapter { path_to_codelldb: OnceLock, } impl CodeLldbDebugAdapter { - const ADAPTER_NAME: &'static str = "CodeLLDB"; + pub const ADAPTER_NAME: &'static str = "CodeLLDB"; async fn request_args( &self, @@ -82,6 +87,34 @@ impl CodeLldbDebugAdapter { } } +#[cfg(feature = "update-schemas")] +impl CodeLldbDebugAdapter { + pub fn get_schema( + temp_dir: &TempDir, + delegate: UpdateSchemasDapDelegate, + ) -> anyhow::Result { + let (package_json, package_nls_json) = get_vsix_package_json( + temp_dir, + "vadimcn/codelldb", + |_| Ok(format!("codelldb-bootstrap.vsix")), + delegate, + )?; + let package_json = parse_package_json(package_json, package_nls_json)?; + + let [debugger] = + <[_; 1]>::try_from(package_json.contributes.debuggers).map_err(|debuggers| { + anyhow::anyhow!( + "unexpected number of codelldb debuggers: {}", + debuggers.len() + ) + })?; + + Ok(schema_for_configuration_attributes( + debugger.configuration_attributes, + )) + } +} + #[async_trait(?Send)] impl DebugAdapter for CodeLldbDebugAdapter { fn name(&self) -> DebugAdapterName { @@ -133,194 +166,11 @@ impl DebugAdapter for CodeLldbDebugAdapter { } fn dap_schema(&self) -> Cow<'static, serde_json::Value> { - Cow::Owned(json!({ - "properties": { - "request": { - "type": "string", - "enum": ["attach", "launch"], - "description": "Debug adapter request type" - }, - "program": { - "type": "string", - "description": "Path to the program to debug or attach to" - }, - "args": { - "type": ["array", "string"], - "description": "Program arguments" - }, - "cwd": { - "type": "string", - "description": "Program working directory" - }, - "env": { - "type": "object", - "description": "Additional environment variables", - "patternProperties": { - ".*": { - "type": "string" - } - } - }, - "envFile": { - "type": "string", - "description": "File to read the environment variables from" - }, - "stdio": { - "type": ["null", "string", "array", "object"], - "description": "Destination for stdio streams: null = send to debugger console or a terminal, \"\" = attach to a file/tty/fifo" - }, - "terminal": { - "type": "string", - "enum": ["integrated", "console"], - "description": "Terminal type to use", - "default": "integrated" - }, - "console": { - "type": "string", - "enum": ["integratedTerminal", "internalConsole"], - "description": "Terminal type to use (compatibility alias of 'terminal')" - }, - "stopOnEntry": { - "type": "boolean", - "description": "Automatically stop debuggee after launch", - "default": false - }, - "initCommands": { - "type": "array", - "description": "Initialization commands executed upon debugger startup", - "items": { - "type": "string" - } - }, - "targetCreateCommands": { - "type": "array", - "description": "Commands that create the debug target", - "items": { - "type": "string" - } - }, - "preRunCommands": { - "type": "array", - "description": "Commands executed just before the program is launched", - "items": { - "type": "string" - } - }, - "processCreateCommands": { - "type": "array", - "description": "Commands that create the debuggee process", - "items": { - "type": "string" - } - }, - "postRunCommands": { - "type": "array", - "description": "Commands executed just after the program has been launched", - "items": { - "type": "string" - } - }, - "preTerminateCommands": { - "type": "array", - "description": "Commands executed just before the debuggee is terminated or disconnected from", - "items": { - "type": "string" - } - }, - "exitCommands": { - "type": "array", - "description": "Commands executed at the end of debugging session", - "items": { - "type": "string" - } - }, - "expressions": { - "type": "string", - "enum": ["simple", "python", "native"], - "description": "The default evaluator type used for expressions" - }, - "sourceMap": { - "type": "object", - "description": "Source path remapping between the build machine and the local machine", - "patternProperties": { - ".*": { - "type": ["string", "null"] - } - } - }, - "relativePathBase": { - "type": "string", - "description": "Base directory used for resolution of relative source paths. Defaults to the workspace folder" - }, - "sourceLanguages": { - "type": "array", - "description": "A list of source languages to enable language-specific features for", - "items": { - "type": "string" - } - }, - "reverseDebugging": { - "type": "boolean", - "description": "Enable reverse debugging", - "default": false - }, - "breakpointMode": { - "type": "string", - "enum": ["path", "file"], - "description": "Specifies how source breakpoints should be set" - }, - "pid": { - "type": ["integer", "string"], - "description": "Process id to attach to" - }, - "waitFor": { - "type": "boolean", - "description": "Wait for the process to launch (MacOS only)", - "default": false - } - }, - "required": ["request"], - "allOf": [ - { - "if": { - "properties": { - "request": { - "enum": ["launch"] - } - } - }, - "then": { - "oneOf": [ - { - "required": ["program"] - }, - { - "required": ["targetCreateCommands"] - } - ] - } - }, - { - "if": { - "properties": { - "request": { - "enum": ["attach"] - } - } - }, - "then": { - "oneOf": [ - { - "required": ["pid"] - }, - { - "required": ["program"] - } - ] - } - } - ] - })) + static SCHEMA: LazyLock = LazyLock::new(|| { + const RAW_SCHEMA: &str = include_str!("../schemas/CodeLLDB.json"); + serde_json::from_str(RAW_SCHEMA).unwrap() + }); + Cow::Borrowed(&*SCHEMA) } async fn get_binary( diff --git a/crates/dap_adapters/src/dap_adapters.rs b/crates/dap_adapters/src/dap_adapters.rs index 68d2f7f5f5ad6af732a847f753c467c5132d2849..1fb9c7af572ad2346b99ce8308a6a7e2cc8849fd 100644 --- a/crates/dap_adapters/src/dap_adapters.rs +++ b/crates/dap_adapters/src/dap_adapters.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use anyhow::{Context as _, Result}; use async_trait::async_trait; -use codelldb::CodeLldbDebugAdapter; +pub use codelldb::CodeLldbDebugAdapter; use collections::HashMap; use dap::{ DapRegistry, @@ -243,3 +243,31 @@ fn parse_package_json( let package_json: PackageJson = serde_json::from_value(package_json)?; Ok(package_json) } + +fn schema_for_configuration_attributes( + attrs: PackageJsonConfigurationAttributes, +) -> serde_json::Value { + let conjuncts = attrs + .launch + .map(|schema| ("launch", schema)) + .into_iter() + .chain(attrs.attach.map(|schema| ("attach", schema))) + .map(|(request, schema)| { + json!({ + "if": { + "properties": { + "request": { + "const": request + } + }, + "required": ["request"] + }, + "then": schema + }) + }) + .collect::>(); + + json!({ + "allOf": conjuncts + }) +} diff --git a/crates/dap_adapters/src/go.rs b/crates/dap_adapters/src/go.rs index 877ca3b896ae99e6a3c50735c10fa9caff6125f9..39fc4711fd3b5fd5a645243326534eae257cd863 100644 --- a/crates/dap_adapters/src/go.rs +++ b/crates/dap_adapters/src/go.rs @@ -122,35 +122,9 @@ impl GoDebugAdapter { anyhow::anyhow!("unexpected number of go debuggers: {}", debuggers.len()) })?; - let configuration_attributes = debugger.configuration_attributes; - let conjuncts = configuration_attributes - .launch - .map(|schema| ("launch", schema)) - .into_iter() - .chain( - configuration_attributes - .attach - .map(|schema| ("attach", schema)), - ) - .map(|(request, schema)| { - json!({ - "if": { - "properties": { - "request": { - "const": request - } - }, - "required": ["request"] - }, - "then": schema - }) - }) - .collect::>(); - - let schema = json!({ - "allOf": conjuncts - }); - Ok(schema) + Ok(schema_for_configuration_attributes( + debugger.configuration_attributes, + )) } } diff --git a/crates/dap_adapters/src/python.rs b/crates/dap_adapters/src/python.rs index 06fdd4bf8a18c107fb99fdbe4a277a722114a39a..7fc827ff989afe5a75fff603dc1766d8fd81653d 100644 --- a/crates/dap_adapters/src/python.rs +++ b/crates/dap_adapters/src/python.rs @@ -400,35 +400,9 @@ impl PythonDebugAdapter { anyhow::anyhow!("unexpected number of python debuggers: {}", debuggers.len()) })?; - let configuration_attributes = debugger.configuration_attributes; - let conjuncts = configuration_attributes - .launch - .map(|schema| ("launch", schema)) - .into_iter() - .chain( - configuration_attributes - .attach - .map(|schema| ("attach", schema)), - ) - .map(|(request, schema)| { - json!({ - "if": { - "properties": { - "request": { - "const": request - } - }, - "required": ["request"] - }, - "then": schema - }) - }) - .collect::>(); - - let schema = json!({ - "allOf": conjuncts - }); - Ok(schema) + Ok(schema_for_configuration_attributes( + debugger.configuration_attributes, + )) } } diff --git a/crates/dap_adapters/src/update_schemas.rs b/crates/dap_adapters/src/update_schemas.rs index b59ff359f20e7f5d6882aba8ca2c98c13d76d7a8..63c82b5527eb71820f8f39628923b622ec0b22f9 100644 --- a/crates/dap_adapters/src/update_schemas.rs +++ b/crates/dap_adapters/src/update_schemas.rs @@ -1,6 +1,10 @@ use std::{path::Path, process::Command}; -use dap_adapters::{GoDebugAdapter, JsDebugAdapter, PythonDebugAdapter, UpdateSchemasDapDelegate}; +use dap::adapters::DapDelegate as _; +use dap_adapters::{ + CodeLldbDebugAdapter, GoDebugAdapter, JsDebugAdapter, PythonDebugAdapter, + UpdateSchemasDapDelegate, +}; use tempfile::TempDir; fn main() -> anyhow::Result<()> { @@ -32,6 +36,15 @@ fn main() -> anyhow::Result<()> { serde_json::to_string(&schema)?, )?; + let schema = CodeLldbDebugAdapter::get_schema(&temp_dir, delegate.clone())?; + std::fs::write( + &output_dir + .join(CodeLldbDebugAdapter::ADAPTER_NAME) + .with_extension("json"), + serde_json::to_string(&schema)?, + )?; + + delegate.output_to_console("Formatting schemas with prettier...".into()); Command::new("npx") .arg("prettier") .arg("--write")