Skip to content

Commit 8317e55

Browse files
Copilothanniavalera
andcommitted
Register cmake.testProgram, cmake.testWorkingDirectory, cmake.testArgs as VS Code commands
Fixes #4574 - The ${cmake.testProgram}, ${cmake.testWorkingDirectory}, and ${cmake.testArgs} variables were only resolved internally by CMake Tools when debugging from the Test Explorer. They were not registered as VS Code commands, so using ${command:cmake.testProgram} in launch.json from the Run and Debug panel would fail with "program does not exist". Changes: - Make testProgram, testWorkingDirectory, testArgs public on CTestDriver - Add corresponding methods to ExtensionManager with test name quick pick - Register them in the funs array and package.json activation events - Handle ${command:cmake.testProgram} form in debugCTestImpl for Test Explorer - Update docs to recommend ${command:cmake.testProgram} format - Add CHANGELOG entry Co-authored-by: hanniavalera <[email protected]>
1 parent ef5b428 commit 8317e55

5 files changed

Lines changed: 69 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Features:
77

88
Bug Fixes:
99

10+
- Register `cmake.testProgram`, `cmake.testWorkingDirectory`, and `cmake.testArgs` as VS Code commands so they can be used as `${command:cmake.testProgram}` in launch.json from the Run and Debug panel. [#4574](https://github.com/microsoft/vscode-cmake-tools/issues/4574)
1011
- Fix CMake script path links not working in CHS/CSY/FRA/PLK locales due to localized quotes. [#4383](https://github.com/microsoft/vscode-cmake-tools/issues/4383)
1112
- Fix user-level tasks defined in `~/.config/Code/User/tasks.json` causing infinite spinner. [#4659](https://github.com/microsoft/vscode-cmake-tools/pull/4659)
1213
- Fix "Copy Value" in CMake debugger copying variable name instead of value. [#4551](https://github.com/microsoft/vscode-cmake-tools/issues/4551)

docs/debug-launch.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,9 @@ You can substitute the value of any variable in the CMake cache by adding a `com
213213

214214
You can also construct launch.json configurations that allow you to debug tests in the Test Explorer.
215215

216-
> **Note:**
217-
> These launch.json configurations are to be used specifically from the UI of the Test Explorer.
216+
There are two forms of these variables:
217+
- `${command:cmake.testProgram}`, `${command:cmake.testArgs}`, `${command:cmake.testWorkingDirectory}` — These are resolved as VS Code command substitutions and work both from the **Test Explorer** and the **Run and Debug** panel. When launched from Run and Debug, you will be prompted to select a test.
218+
- `${cmake.testProgram}`, `${cmake.testArgs}`, `${cmake.testWorkingDirectory}` — These are only resolved when launching from the **Test Explorer** UI. If used from the Run and Debug panel, they will not be substituted.
218219

219220
The easiest way to do this is to construct the debug configuration using `cmake.testProgram` for the `program` field, `cmake.testArgs` for
220221
the `args` field, and `cmake.testWorkingDirectory` for the `cwd` field.
@@ -227,11 +228,10 @@ A couple of examples:
227228
"name": "(ctest) Launch",
228229
"type": "cppdbg",
229230
"request": "launch",
230-
"presentation": { "hidden": true },
231231
// Resolved by CMake Tools:
232-
"cwd": "${cmake.testWorkingDirectory}",
233-
"program": "${cmake.testProgram}",
234-
"args": [ "${cmake.testArgs}"],
232+
"cwd": "${command:cmake.testWorkingDirectory}",
233+
"program": "${command:cmake.testProgram}",
234+
"args": [ "${command:cmake.testArgs}"],
235235
}
236236
```
237237
### msvc
@@ -240,10 +240,9 @@ A couple of examples:
240240
"name": "(ctest) Launch",
241241
"type": "cppvsdbg",
242242
"request": "launch",
243-
"presentation": { "hidden": true },
244243
// Resolved by CMake Tools:
245-
"program": "${cmake.testProgram}",
246-
"args": [ "${cmake.testArgs}"],
244+
"program": "${command:cmake.testProgram}",
245+
"args": [ "${command:cmake.testArgs}"],
247246
}
248247
```
249248

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
"onCommand:cmake.launchTargetDirectory",
4949
"onCommand:cmake.launchTargetFilename",
5050
"onCommand:cmake.launchTargetName",
51+
"onCommand:cmake.testProgram",
52+
"onCommand:cmake.testWorkingDirectory",
53+
"onCommand:cmake.testArgs",
5154
"onCommand:cmake.getLaunchTargetPath",
5255
"onCommand:cmake.getLaunchTargetDirectory",
5356
"onCommand:cmake.getLaunchTargetFilename",

src/ctest.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,11 +1259,14 @@ export class CTestDriver implements vscode.Disposable {
12591259
// Commands can't be used to replace array (i.e., args); and both test program and test args requires folder and
12601260
// test name as parameters, which means one lauch config for each test. So replacing them here is a better way.
12611261
chosenConfig.config = this.replaceAllInObject<vscode.DebugConfiguration>(chosenConfig.config, '${cmake.testProgram}', this.testProgram(testName));
1262+
chosenConfig.config = this.replaceAllInObject<vscode.DebugConfiguration>(chosenConfig.config, '${command:cmake.testProgram}', this.testProgram(testName));
12621263
chosenConfig.config = this.replaceAllInObject<vscode.DebugConfiguration>(chosenConfig.config, '${cmake.testWorkingDirectory}', this.testWorkingDirectory(testName));
1264+
chosenConfig.config = this.replaceAllInObject<vscode.DebugConfiguration>(chosenConfig.config, '${command:cmake.testWorkingDirectory}', this.testWorkingDirectory(testName));
12631265

12641266
// Replace cmake.testArgs wrapped in quotes, like `"${command:cmake.testArgs}"`, without any spaces in between,
12651267
// since we need to repalce the quotes as well.
12661268
chosenConfig.config = this.replaceArrayItems(chosenConfig.config, '${cmake.testArgs}', this.testArgs(testName)) as vscode.DebugConfiguration;
1269+
chosenConfig.config = this.replaceArrayItems(chosenConfig.config, '${command:cmake.testArgs}', this.testArgs(testName)) as vscode.DebugConfiguration;
12671270

12681271
// Identify the session we started
12691272
chosenConfig.config[magicKey] = magicValue;
@@ -1307,7 +1310,7 @@ export class CTestDriver implements vscode.Disposable {
13071310
}
13081311
}
13091312

1310-
private testProgram(testName: string): string {
1313+
public testProgram(testName: string): string {
13111314
if (this.tests) {
13121315
for (const test of this.tests.tests) {
13131316
if (test.name === testName) {
@@ -1324,7 +1327,7 @@ export class CTestDriver implements vscode.Disposable {
13241327
return '';
13251328
}
13261329

1327-
private testWorkingDirectory(testName: string): string {
1330+
public testWorkingDirectory(testName: string): string {
13281331
const property = this.tests?.tests
13291332
.find(test => test.name === testName)?.properties
13301333
.find(prop => prop.name === 'WORKING_DIRECTORY');
@@ -1335,7 +1338,7 @@ export class CTestDriver implements vscode.Disposable {
13351338
return '';
13361339
}
13371340

1338-
private testArgs(testName: string): string[] {
1341+
public testArgs(testName: string): string[] {
13391342
if (this.tests) {
13401343
for (const test of this.tests.tests) {
13411344
if (test.name === testName) {

src/extension.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,54 @@ export class ExtensionManager implements vscode.Disposable {
17951795
}, folder);
17961796
}
17971797

1798+
private async pickTestName(cmakeProject: CMakeProject): Promise<string | undefined> {
1799+
const testNames = cmakeProject.cTestController.getTestNames();
1800+
if (!testNames || testNames.length === 0) {
1801+
void vscode.window.showWarningMessage(localize('no.ctest.tests.found', 'No CTest tests found. Make sure to configure and build your project first.'));
1802+
return undefined;
1803+
}
1804+
if (testNames.length === 1) {
1805+
return testNames[0];
1806+
}
1807+
const chosen = await vscode.window.showQuickPick(testNames, {
1808+
placeHolder: localize('choose.test', 'Select a test')
1809+
});
1810+
return chosen;
1811+
}
1812+
1813+
testProgram(folder?: vscode.WorkspaceFolder | string) {
1814+
telemetry.logEvent("substitution", { command: "testProgram" });
1815+
return this.queryCMakeProject(async cmakeProject => {
1816+
const testName = await this.pickTestName(cmakeProject);
1817+
if (!testName) {
1818+
return '';
1819+
}
1820+
return cmakeProject.cTestController.testProgram(testName);
1821+
}, folder);
1822+
}
1823+
1824+
testWorkingDirectory(folder?: vscode.WorkspaceFolder | string) {
1825+
telemetry.logEvent("substitution", { command: "testWorkingDirectory" });
1826+
return this.queryCMakeProject(async cmakeProject => {
1827+
const testName = await this.pickTestName(cmakeProject);
1828+
if (!testName) {
1829+
return '';
1830+
}
1831+
return cmakeProject.cTestController.testWorkingDirectory(testName);
1832+
}, folder);
1833+
}
1834+
1835+
testArgs(folder?: vscode.WorkspaceFolder | string) {
1836+
telemetry.logEvent("substitution", { command: "testArgs" });
1837+
return this.queryCMakeProject(async cmakeProject => {
1838+
const testName = await this.pickTestName(cmakeProject);
1839+
if (!testName) {
1840+
return [];
1841+
}
1842+
return cmakeProject.cTestController.testArgs(testName);
1843+
}, folder);
1844+
}
1845+
17981846
buildTargetName(folder?: vscode.WorkspaceFolder | string) {
17991847
telemetry.logEvent("substitution", { command: "buildTargetName" });
18001848
return this.queryCMakeProject(cmakeProject => cmakeProject.buildTargetName(), folder);
@@ -2395,6 +2443,9 @@ async function setup(context: vscode.ExtensionContext, progress?: ProgressHandle
23952443
'getLaunchTargetDirectory',
23962444
'getLaunchTargetFilename',
23972445
'getLaunchTargetName',
2446+
'testProgram',
2447+
'testWorkingDirectory',
2448+
'testArgs',
23982449
'buildTargetName',
23992450
'buildKit',
24002451
'buildType',

0 commit comments

Comments
 (0)