Skip to content

Commit

Permalink
Same Quick Debugging in Test Explorer as in Project Outline
Browse files Browse the repository at this point in the history
  • Loading branch information
basejumpa committed Nov 16, 2023
1 parent 8d4eb87 commit 66deeb0
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 106 deletions.
41 changes: 29 additions & 12 deletions src/cmakeProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import paths from './paths';
import { ProjectController } from './projectController';
import { MessageItem } from 'vscode';
import { DebugTrackerFactory, DebuggerInformation, getDebuggerPipeName } from './debug/debuggerConfigureDriver';
import { VSCodeDebugConfiguration } from './debugger';

nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
Expand Down Expand Up @@ -2303,10 +2304,17 @@ export class CMakeProject {
return EnvironmentUtils.merge([env, configureEnv]);
}

/**
* Implementation of `cmake.debugTarget`
*/
async debugTarget(name?: string): Promise<vscode.DebugSession | null> {
async getDebugConfiguration(name?: string): Promise<VSCodeDebugConfiguration | null> {
const targetExecutable = await this.prepareLaunchTargetExecutable(name);
if (!targetExecutable) {
log.error(localize('failed.to.prepare.target', 'Failed to prepare executable target with name {0}', `"${name}"`));
return null;
}

if (!targetExecutable) {
return null;
}

const drv = await this.getCMakeDriverInstance();
if (!drv) {
void vscode.window.showErrorMessage(localize('set.up.and.build.project.before.debugging', 'Set up and build your CMake project before debugging.'));
Expand All @@ -2326,12 +2334,6 @@ export class CMakeProject {
return null;
}

const targetExecutable = await this.prepareLaunchTargetExecutable(name);
if (!targetExecutable) {
log.error(localize('failed.to.prepare.target', 'Failed to prepare executable target with name {0}', `"${name}"`));
return null;
}

let debugConfig;
try {
const cache = await CMakeCache.fromPath(drv.cachePath);
Expand Down Expand Up @@ -2370,10 +2372,25 @@ export class CMakeProject {
config: debugConfig
}));

return debugConfig;
}

/**
* Implementation of `cmake.debugTarget`
*/
async debugTarget(name?: string): Promise<vscode.DebugSession | null> {

const debugConfig = await this.getDebugConfiguration(name);

if (debugConfig === null) {
return null;
}

const cfg = vscode.workspace.getConfiguration('cmake', this.workspaceFolder.uri).inspect<object>('debugConfig');
const customSetting = (cfg?.globalValue !== undefined || cfg?.workspaceValue !== undefined || cfg?.workspaceFolderValue !== undefined);
let dbg = debugConfig.MIMode?.toString();
if (!dbg && debugConfig.type === "cppvsdbg") {

let dbg = debugConfig?.MIMode?.toString();
if (!dbg && debugConfig?.type === "cppvsdbg") {
dbg = "vsdbg";
} else {
dbg = "(unset)";
Expand Down
105 changes: 11 additions & 94 deletions src/ctest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -758,54 +758,22 @@ export class CTestDriver implements vscode.Disposable {

private async debugCTestImpl(workspaceFolder: vscode.WorkspaceFolder, testName: string, cancellation: vscode.CancellationToken): Promise<void> {
const magicValue = sessionNum++;
const launchConfig = vscode.workspace.getConfiguration(
'launch',
workspaceFolder.uri
);
const workspaceLaunchConfig = vscode.workspace.workspaceFile ? vscode.workspace.getConfiguration(
'launch',
vscode.workspace.workspaceFile
) : undefined;
const configs = launchConfig.get<vscode.DebugConfiguration[]>('configurations') ?? [];
const workspaceConfigs = workspaceLaunchConfig?.get<vscode.DebugConfiguration[]>('configurations') ?? [];
if (configs.length === 0 && workspaceConfigs.length === 0) {

const testProgram = this.testProgram(testName);
const basename = path.parse(testProgram).name;
const debugConfig = await this.projectController?.getActiveCMakeProject()?.getDebugConfiguration(basename);

if (debugConfig === null || debugConfig === undefined) {
log.error(localize('no.launch.config', 'No launch configurations found.'));
return;
}

interface ConfigItem extends vscode.QuickPickItem {
label: string;
config: vscode.DebugConfiguration;
detail: string;
// Undefined for workspace launch config
folder?: vscode.WorkspaceFolder;
}
let allConfigItems: ConfigItem[] = configs.map(config => ({ label: config.name, config, folder: workspaceFolder, detail: workspaceFolder.uri.fsPath }));
allConfigItems = allConfigItems.concat(workspaceConfigs.map(config => ({ label: config.name, config, detail: vscode.workspace.workspaceFile!.fsPath })));
let chosenConfig: ConfigItem | undefined;
if (allConfigItems.length === 1) {
chosenConfig = allConfigItems[0];
} else {
// TODO: we can remember the last choice once the CMake side panel work is done
const chosen = await vscode.window.showQuickPick(allConfigItems, { placeHolder: localize('choose.launch.config', 'Choose a launch configuration to debug the test with.') });
if (chosen) {
chosenConfig = chosen;
} else {
return;
}
}

// Commands can't be used to replace array (i.e., args); and both test program and test args requires folder and
// test name as parameters, which means one lauch config for each test. So replacing them here is a better way.
chosenConfig.config = this.replaceAllInObject<vscode.DebugConfiguration>(chosenConfig.config, '${cmake.testProgram}', this.testProgram(testName));
chosenConfig.config = this.replaceAllInObject<vscode.DebugConfiguration>(chosenConfig.config, '${cmake.testWorkingDirectory}', this.testWorkingDirectory(testName));

// Replace cmake.testArgs wrapped in quotes, like `"${command:cmake.testArgs}"`, without any spaces in between,
// since we need to repalce the quotes as well.
chosenConfig.config = this.replaceArrayItems(chosenConfig.config, '${cmake.testArgs}', this.testArgs(testName)) as vscode.DebugConfiguration;
debugConfig.cwd = this.testWorkingDirectory(testName)!;
debugConfig.args = this.testArgs(testName)!;

// Identify the session we started
chosenConfig.config[magicKey] = magicValue;
debugConfig[magicKey] = magicValue;

let onDidStartDebugSession: vscode.Disposable | undefined;
let onDidTerminateDebugSession: vscode.Disposable | undefined;
let sessionId: string | undefined;
Expand All @@ -828,7 +796,7 @@ export class CTestDriver implements vscode.Disposable {
log.info('debugSessionTerminated');
});

const debugStarted = await vscode.debug.startDebugging(chosenConfig.folder, chosenConfig.config!);
const debugStarted = await vscode.debug.startDebugging(workspaceFolder, debugConfig!);
if (debugStarted) {
const session = await started;
if (session) {
Expand Down Expand Up @@ -879,57 +847,6 @@ export class CTestDriver implements vscode.Disposable {
return [];
}

private replaceAllInObject<T>(obj: any, str: string, replace: string): T {
const regex = new RegExp(util.escapeStringForRegex(str), 'g');
if (util.isString(obj)) {
obj = obj.replace(regex, replace);
} else if (util.isArray(obj)) {
for (let i = 0; i < obj.length; i++) {
obj[i] = this.replaceAllInObject(obj[i], str, replace);
}
} else if (typeof obj === 'object') {
for (const key of Object.keys(obj)) {
obj[key] = this.replaceAllInObject(obj[key], str, replace);
}
}
return obj;
}

private replaceArrayItems(obj: any, str: string, replace: string[]) {
if (util.isArray(obj) && obj.length !== 0) {
const result: any[] = [];
for (let i = 0; i < obj.length; i++) {
if (util.isArray(obj[i]) || typeof obj[i] === 'object') {
result.push(this.replaceArrayItems(obj[i], str, replace));
} else if (util.isString(obj[i])) {
const replacedItem = this.replaceArrayItemsHelper(obj[i] as string, str, replace);
if (util.isArray(replacedItem)) {
result.push(...replacedItem);
} else {
result.push(replacedItem);
}
} else {
result.push(obj[i]);
}
}
return result;
}
if (typeof obj === 'object') {
for (const key of Object.keys(obj)) {
obj[key] = this.replaceArrayItems(obj[key], str, replace);
}
return obj;
}
return obj;
}

private replaceArrayItemsHelper(orig: string, str: string, replace: string[]): string | string[] {
if (orig === str) {
return replace;
}
return orig;
}

private async debugTestHandler(request: vscode.TestRunRequest, cancellation: vscode.CancellationToken) {
if (!testExplorer) {
return;
Expand Down

0 comments on commit 66deeb0

Please sign in to comment.