diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index 53751aafb7..321861b161 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs @@ -19,50 +19,48 @@ impl CargoTargetSpec { pub(crate) fn runnable_args( spec: Option, kind: &RunnableKind, - ) -> Result> { - let mut res = Vec::new(); + ) -> Result<(Vec, Vec)> { + let mut args = Vec::new(); + let mut extra_args = Vec::new(); match kind { RunnableKind::Test { test_id } => { - res.push("test".to_string()); + args.push("test".to_string()); if let Some(spec) = spec { - spec.push_to(&mut res); + spec.push_to(&mut args); } - res.push("--".to_string()); - res.push(test_id.to_string()); + extra_args.push(test_id.to_string()); if let TestId::Path(_) = test_id { - res.push("--exact".to_string()); + extra_args.push("--exact".to_string()); } - res.push("--nocapture".to_string()); + extra_args.push("--nocapture".to_string()); } RunnableKind::TestMod { path } => { - res.push("test".to_string()); + args.push("test".to_string()); if let Some(spec) = spec { - spec.push_to(&mut res); + spec.push_to(&mut args); } - res.push("--".to_string()); - res.push(path.to_string()); - res.push("--nocapture".to_string()); + extra_args.push(path.to_string()); + extra_args.push("--nocapture".to_string()); } RunnableKind::Bench { test_id } => { - res.push("bench".to_string()); + args.push("bench".to_string()); if let Some(spec) = spec { - spec.push_to(&mut res); + spec.push_to(&mut args); } - res.push("--".to_string()); - res.push(test_id.to_string()); + extra_args.push(test_id.to_string()); if let TestId::Path(_) = test_id { - res.push("--exact".to_string()); + extra_args.push("--exact".to_string()); } - res.push("--nocapture".to_string()); + extra_args.push("--nocapture".to_string()); } RunnableKind::Bin => { - res.push("run".to_string()); + args.push("run".to_string()); if let Some(spec) = spec { - spec.push_to(&mut res); + spec.push_to(&mut args); } } } - Ok(res) + Ok((args, extra_args)) } pub(crate) fn for_file( diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index fcb40432d4..0442733336 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs @@ -381,6 +381,7 @@ pub fn handle_runnables( label, bin: "cargo".to_string(), args: check_args, + extra_args: Vec::with_capacity(0), env: FxHashMap::default(), cwd: workspace_root.map(|root| root.to_string_lossy().to_string()), }); @@ -795,17 +796,29 @@ pub fn handle_code_lens( } .to_string(); let r = to_lsp_runnable(&world, file_id, runnable)?; + let range = r.range; + let arguments = vec![to_value(r).unwrap()]; let lens = CodeLens { - range: r.range, + range: range.clone(), command: Some(Command { title, command: "rust-analyzer.runSingle".into(), - arguments: Some(vec![to_value(r).unwrap()]), + arguments: Some(arguments.clone()), + }), + data: None, + }; + let debug_lens = CodeLens { + range, + command: Some(Command { + title: "Debug".into(), + command: "rust-analyzer.debugSingle".into(), + arguments: Some(arguments.clone()), }), data: None, }; lenses.push(lens); + lenses.push(debug_lens); } // Handle impls @@ -952,7 +965,7 @@ fn to_lsp_runnable( runnable: Runnable, ) -> Result { let spec = CargoTargetSpec::for_file(world, file_id)?; - let args = CargoTargetSpec::runnable_args(spec, &runnable.kind)?; + let (args, extra_args) = CargoTargetSpec::runnable_args(spec, &runnable.kind)?; let line_index = world.analysis().file_line_index(file_id)?; let label = match &runnable.kind { RunnableKind::Test { test_id } => format!("test {}", test_id), @@ -965,6 +978,7 @@ fn to_lsp_runnable( label, bin: "cargo".to_string(), args, + extra_args, env: { let mut m = FxHashMap::default(); m.insert("RUST_BACKTRACE".to_string(), "short".to_string()); @@ -973,6 +987,7 @@ fn to_lsp_runnable( cwd: world.workspace_root_for(file_id).map(|root| root.to_string_lossy().to_string()), }) } + fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result> { let line_index = world.analysis().file_line_index(file_id)?; let res = world diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/req.rs index a3efe3b9fe..156328df8f 100644 --- a/crates/rust-analyzer/src/req.rs +++ b/crates/rust-analyzer/src/req.rs @@ -169,6 +169,7 @@ pub struct Runnable { pub label: String, pub bin: String, pub args: Vec, + pub extra_args: Vec, pub env: FxHashMap, pub cwd: Option, } diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs index 970185deca..55af6c5e0a 100644 --- a/crates/rust-analyzer/tests/heavy_tests/main.rs +++ b/crates/rust-analyzer/tests/heavy_tests/main.rs @@ -75,7 +75,8 @@ fn foo() { RunnablesParams { text_document: server.doc_id("lib.rs"), position: None }, json!([ { - "args": [ "test", "--", "foo", "--nocapture" ], + "args": [ "test" ], + "extraArgs": [ "foo", "--nocapture" ], "bin": "cargo", "env": { "RUST_BACKTRACE": "short" }, "cwd": null, @@ -90,6 +91,7 @@ fn foo() { "check", "--all" ], + "extraArgs": [], "bin": "cargo", "env": {}, "cwd": null, @@ -147,7 +149,8 @@ fn main() {} }, json!([ { - "args": [ "test", "--package", "foo", "--test", "spam", "--", "test_eggs", "--exact", "--nocapture" ], + "args": [ "test", "--package", "foo", "--test", "spam" ], + "extraArgs": [ "test_eggs", "--exact", "--nocapture" ], "bin": "cargo", "env": { "RUST_BACKTRACE": "short" }, "label": "test test_eggs", @@ -165,6 +168,7 @@ fn main() {} "--test", "spam" ], + "extraArgs": [], "bin": "cargo", "env": {}, "cwd": server.path().join("foo"), diff --git a/editors/code/package.json b/editors/code/package.json index 1fe8e9f8ae..7445857218 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -51,6 +51,9 @@ "typescript-formatter": "^7.2.2", "vsce": "^1.74.0" }, + "extensionDependencies": [ + "vadimcn.vscode-lldb" + ], "activationEvents": [ "onLanguage:rust", "onCommand:rust-analyzer.analyzerStatus", diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts index 06b5134668..faa92799c1 100644 --- a/editors/code/src/commands/runnables.ts +++ b/editors/code/src/commands/runnables.ts @@ -3,6 +3,7 @@ import * as lc from 'vscode-languageclient'; import * as ra from '../rust-analyzer-api'; import { Ctx, Cmd } from '../ctx'; +import { debug } from 'vscode'; export function run(ctx: Ctx): Cmd { let prevRunnable: RunnableQuickPick | undefined; @@ -62,6 +63,31 @@ export function runSingle(ctx: Ctx): Cmd { }; } +export function debugSingle(ctx: Ctx): Cmd { + return async (config: ra.Runnable) => { + const editor = ctx.activeRustEditor; + if (!editor) return; + + if (config.args[0] === 'run') { + config.args[0] = 'build'; + } else { + config.args.push('--no-run'); + } + + const debugConfig = { + type: "lldb", + request: "launch", + name: config.label, + cargo: { + args: config.args, + }, + args: config.extraArgs, + cwd: config.cwd + }; + return debug.startDebugging(undefined, debugConfig); + }; +} + class RunnableQuickPick implements vscode.QuickPickItem { public label: string; public description?: string | undefined; @@ -87,7 +113,7 @@ function createTask(spec: ra.Runnable): vscode.Task { type: 'cargo', label: spec.label, command: spec.bin, - args: spec.args, + args: spec.extraArgs ? [...spec.args, '--', ...spec.extraArgs] : spec.args, env: spec.env, }; diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index ecf53cf775..e01c89cc7c 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -83,6 +83,7 @@ export async function activate(context: vscode.ExtensionContext) { // Internal commands which are invoked by the server. ctx.registerCommand('runSingle', commands.runSingle); + ctx.registerCommand('debugSingle', commands.debugSingle); ctx.registerCommand('showReferences', commands.showReferences); ctx.registerCommand('applySourceChange', commands.applySourceChange); ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange); diff --git a/editors/code/src/rust-analyzer-api.ts b/editors/code/src/rust-analyzer-api.ts index bd6e3ada08..e09a203c9f 100644 --- a/editors/code/src/rust-analyzer-api.ts +++ b/editors/code/src/rust-analyzer-api.ts @@ -80,13 +80,12 @@ export interface Runnable { label: string; bin: string; args: Vec; + extraArgs: Vec; env: FxHashMap; cwd: Option; } export const runnables = request>("runnables"); - - export type InlayHint = InlayHint.TypeHint | InlayHint.ParamHint; export namespace InlayHint {