From 66deeb05358d43befff365c6101c94251df83e68 Mon Sep 17 00:00:00 2001 From: basejumpa Date: Thu, 16 Nov 2023 18:17:11 +0100 Subject: [PATCH] Same Quick Debugging in Test Explorer as in Project Outline --- src/cmakeProject.ts | 41 ++++++++++++----- src/ctest.ts | 105 +++++--------------------------------------- 2 files changed, 40 insertions(+), 106 deletions(-) diff --git a/src/cmakeProject.ts b/src/cmakeProject.ts index c023877c4f..b34b614c90 100644 --- a/src/cmakeProject.ts +++ b/src/cmakeProject.ts @@ -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(); @@ -2303,10 +2304,17 @@ export class CMakeProject { return EnvironmentUtils.merge([env, configureEnv]); } - /** - * Implementation of `cmake.debugTarget` - */ - async debugTarget(name?: string): Promise { + async getDebugConfiguration(name?: string): Promise { + 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.')); @@ -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); @@ -2370,10 +2372,25 @@ export class CMakeProject { config: debugConfig })); + return debugConfig; + } + + /** + * Implementation of `cmake.debugTarget` + */ + async debugTarget(name?: string): Promise { + + const debugConfig = await this.getDebugConfiguration(name); + + if (debugConfig === null) { + return null; + } + const cfg = vscode.workspace.getConfiguration('cmake', this.workspaceFolder.uri).inspect('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)"; diff --git a/src/ctest.ts b/src/ctest.ts index 39c4af3f0a..ac00df0a29 100644 --- a/src/ctest.ts +++ b/src/ctest.ts @@ -758,54 +758,22 @@ export class CTestDriver implements vscode.Disposable { private async debugCTestImpl(workspaceFolder: vscode.WorkspaceFolder, testName: string, cancellation: vscode.CancellationToken): Promise { 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('configurations') ?? []; - const workspaceConfigs = workspaceLaunchConfig?.get('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(chosenConfig.config, '${cmake.testProgram}', this.testProgram(testName)); - chosenConfig.config = this.replaceAllInObject(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; @@ -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) { @@ -879,57 +847,6 @@ export class CTestDriver implements vscode.Disposable { return []; } - private replaceAllInObject(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;