@@ -5,12 +5,15 @@ import type * as ra from "./lsp_ext";
5
5
6
6
import { Cargo } from "./toolchain" ;
7
7
import type { Ctx } from "./ctx" ;
8
- import { prepareEnv } from "./run" ;
8
+ import { createTaskFromRunnable , prepareEnv } from "./run" ;
9
9
import { execute , isCargoRunnableArgs , unwrapUndefinable } from "./util" ;
10
10
import type { Config } from "./config" ;
11
11
12
12
const debugOutput = vscode . window . createOutputChannel ( "Debug" ) ;
13
13
14
+ // Here we want to keep track on everything that's currently running
15
+ const activeDebugSessionIds : string [ ] = [ ] ;
16
+
14
17
export async function makeDebugConfig ( ctx : Ctx , runnable : ra . Runnable ) : Promise < void > {
15
18
const scope = ctx . activeRustEditor ?. document . uri ;
16
19
if ( ! scope ) return ;
@@ -45,6 +48,8 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis
45
48
const wsLaunchSection = vscode . workspace . getConfiguration ( "launch" ) ;
46
49
const configurations = wsLaunchSection . get < any [ ] > ( "configurations" ) || [ ] ;
47
50
51
+ // The runnable label is the name of the test with the "test prefix"
52
+ // e.g. test test_feature_x
48
53
const index = configurations . findIndex ( ( c ) => c . name === runnable . label ) ;
49
54
if ( - 1 !== index ) {
50
55
debugConfig = configurations [ index ] ;
@@ -359,3 +364,49 @@ function quote(xs: string[]) {
359
364
} )
360
365
. join ( " " ) ;
361
366
}
367
+
368
+ async function recompileTestFromDebuggingSession ( session : vscode . DebugSession , ctx : Ctx ) {
369
+ const { cwd, args : sessionArgs } : vscode . DebugConfiguration = session . configuration ;
370
+
371
+ const args : ra . CargoRunnableArgs = {
372
+ cwd : cwd ,
373
+ cargoArgs : [ "test" , "--no-run" , "--test" , "lib" ] ,
374
+
375
+ // The first element of the debug configuration args is the test path e.g. "test_bar::foo::test_a::test_b"
376
+ executableArgs : sessionArgs ,
377
+ } ;
378
+ const runnable : ra . Runnable = {
379
+ kind : "cargo" ,
380
+ label : "compile-test" ,
381
+ args,
382
+ } ;
383
+ const task : vscode . Task = await createTaskFromRunnable ( runnable , ctx . config ) ;
384
+
385
+ // It is not needed to call the language server, since the test path is already resolved in the
386
+ // configuration option. We can simply call a debug configuration with the --no-run option to compile
387
+ await vscode . tasks . executeTask ( task ) ;
388
+ }
389
+
390
+ export function initializeDebugSessionTrackingAndRebuild ( ctx : Ctx ) {
391
+ vscode . debug . onDidStartDebugSession ( ( session : vscode . DebugSession ) => {
392
+ if ( ! activeDebugSessionIds . includes ( session . id ) ) {
393
+ activeDebugSessionIds . push ( session . id ) ;
394
+ }
395
+ } ) ;
396
+
397
+ vscode . debug . onDidTerminateDebugSession ( async ( session : vscode . DebugSession ) => {
398
+ // The id of the session will be the same when pressing restart the restart button
399
+ if ( activeDebugSessionIds . find ( ( s ) => s === session . id ) ) {
400
+ await recompileTestFromDebuggingSession ( session , ctx ) ;
401
+ }
402
+ removeActiveSession ( session ) ;
403
+ } ) ;
404
+ }
405
+
406
+ function removeActiveSession ( session : vscode . DebugSession ) {
407
+ const activeSessionId = activeDebugSessionIds . findIndex ( ( id ) => id === session . id ) ;
408
+
409
+ if ( activeSessionId !== - 1 ) {
410
+ activeDebugSessionIds . splice ( activeSessionId , 1 ) ;
411
+ }
412
+ }
0 commit comments