Skip to content

Commit 3f22f7d

Browse files
committed
Auto merge of #17923 - basvandriel:feature/build-before-restart-debug, r=Veykril
Building before a debugging session was restarted # Background Resolves#17901. It adds support for rebuilding after debugging a test was restarted. This means the test doesn't have to be aborted and manually re-ran again. # How this is tested First, all the Visual Studio Code extensions are loaded into an Extension Host window. Then, a sample test like below was ran and restarted to see if it was correctly rebuild. ```rust #[test] fn test_x() { assert_eq!("1.1.1", "1.1.0"); } ```
2 parents 0d70f9f + b204f48 commit 3f22f7d

4 files changed

Lines changed: 63 additions & 1 deletion

File tree

‎src/tools/rust-analyzer/editors/code/package.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,11 @@
512512
"type": "boolean",
513513
"default": false
514514
},
515+
"rust-analyzer.debug.buildBeforeRestart": {
516+
"markdownDescription": "Whether to rebuild the project modules before debugging the same test again",
517+
"type": "boolean",
518+
"default": false
519+
},
515520
"rust-analyzer.debug.engineSettings": {
516521
"type": "object",
517522
"default": {},

‎src/tools/rust-analyzer/editors/code/src/config.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ export class Config {
299299
engine: this.get<string>("debug.engine"),
300300
engineSettings: this.get<object>("debug.engineSettings")??{},
301301
openDebugPane: this.get<boolean>("debug.openDebugPane"),
302+
buildBeforeRestart: this.get<boolean>("debug.buildBeforeRestart"),
302303
sourceFileMap: sourceFileMap,
303304
};
304305
}

‎src/tools/rust-analyzer/editors/code/src/debug.ts‎

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ import type * as ra from "./lsp_ext";
55

66
import{Cargo}from"./toolchain";
77
importtype{Ctx}from"./ctx";
8-
import{prepareEnv}from"./run";
8+
import{createTaskFromRunnable,prepareEnv}from"./run";
99
import{execute,isCargoRunnableArgs,unwrapUndefinable}from"./util";
1010
importtype{Config}from"./config";
1111

1212
constdebugOutput=vscode.window.createOutputChannel("Debug");
1313

14+
// Here we want to keep track on everything that's currently running
15+
constactiveDebugSessionIds: string[]=[];
16+
1417
exportasyncfunctionmakeDebugConfig(ctx: Ctx,runnable: ra.Runnable): Promise<void>{
1518
constscope=ctx.activeRustEditor?.document.uri;
1619
if(!scope)return;
@@ -45,6 +48,8 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis
4548
constwsLaunchSection=vscode.workspace.getConfiguration("launch");
4649
constconfigurations=wsLaunchSection.get<any[]>("configurations")||[];
4750

51+
// The runnable label is the name of the test with the "test prefix"
52+
// e.g. test test_feature_x
4853
constindex=configurations.findIndex((c)=>c.name===runnable.label);
4954
if(-1!==index){
5055
debugConfig=configurations[index];
@@ -359,3 +364,49 @@ function quote(xs: string[]) {
359364
})
360365
.join(" ");
361366
}
367+
368+
asyncfunctionrecompileTestFromDebuggingSession(session: vscode.DebugSession,ctx: Ctx){
369+
const{ cwd,args: sessionArgs}: vscode.DebugConfiguration=session.configuration;
370+
371+
constargs: 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+
construnnable: ra.Runnable={
379+
kind: "cargo",
380+
label: "compile-test",
381+
args,
382+
};
383+
consttask: vscode.Task=awaitcreateTaskFromRunnable(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+
awaitvscode.tasks.executeTask(task);
388+
}
389+
390+
exportfunctioninitializeDebugSessionTrackingAndRebuild(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+
awaitrecompileTestFromDebuggingSession(session,ctx);
401+
}
402+
removeActiveSession(session);
403+
});
404+
}
405+
406+
functionremoveActiveSession(session: vscode.DebugSession){
407+
constactiveSessionId=activeDebugSessionIds.findIndex((id)=>id===session.id);
408+
409+
if(activeSessionId!==-1){
410+
activeDebugSessionIds.splice(activeSessionId,1);
411+
}
412+
}

‎src/tools/rust-analyzer/editors/code/src/main.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { type CommandFactory, Ctx, fetchWorkspace } from "./ctx";
66
import*asdiagnosticsfrom"./diagnostics";
77
import{activateTaskProvider}from"./tasks";
88
import{setContextValue}from"./util";
9+
import{initializeDebugSessionTrackingAndRebuild}from"./debug";
910

1011
constRUST_PROJECT_CONTEXT_NAME="inRustProject";
1112

@@ -102,6 +103,10 @@ async function activateServer(ctx: Ctx): Promise<RustAnalyzerExtensionApi> {
102103
ctx.subscriptions,
103104
);
104105

106+
if(ctx.config.debug.buildBeforeRestart){
107+
initializeDebugSessionTrackingAndRebuild(ctx);
108+
}
109+
105110
awaitctx.start();
106111
returnctx;
107112
}

0 commit comments

Comments
 (0)