async provideDebugConfigurations()

in Extension/src/Debugger/configurationProvider.ts [121:246]


    async provideDebugConfigurations(folder?: vscode.WorkspaceFolder, token?: vscode.CancellationToken): Promise<vscode.DebugConfiguration[]> {
        const defaultConfig: vscode.DebugConfiguration = this.provider.getInitialConfigurations(this.type).find((config: any) =>
            isDebugLaunchStr(config.name) && config.request === "launch");
        console.assert(defaultConfig, "Could not find default debug configuration.");

        const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation();
        const platform: string = platformInfo.platform;

        // Import the tasks from tasks.json file.
        const buildTasksJson: CppBuildTask[] = await cppBuildTaskProvider.getJsonTasks();

        // Provide detected tasks by cppBuildTaskProvider.
        const buildTasksDetected: CppBuildTask[] = await cppBuildTaskProvider.getTasks(true);

        // Rename the provided tasks that has same name as tasks in tasks.json.
        const buildTasksDetectedRename: CppBuildTask[] = buildTasksDetected.map(taskDetected => {
            for (const taskJson of buildTasksJson) {
                if ((taskDetected.definition.label as string) === (taskJson.definition.label as string)) {
                    taskDetected.name = cppBuildTaskProvider.provideUniqueTaskLabel(taskJson.definition.label, buildTasksJson);
                    taskDetected.definition.label = taskDetected.name;
                    break;
                }
            }
            return taskDetected;
        });

        let buildTasks: CppBuildTask[] = [];
        buildTasks = buildTasks.concat(buildTasksJson, buildTasksDetectedRename);

        if (buildTasks.length === 0) {
            return Promise.resolve(this.provider.getInitialConfigurations(this.type));
        }

        if (buildTasks.length === 0) {
            return Promise.resolve(this.provider.getInitialConfigurations(this.type));
        }
        // Filter out build tasks that don't match the currently selected debug configuration type.
        buildTasks = buildTasks.filter((task: CppBuildTask) => {
            const command: string = task.definition.command as string;
            if (!command) {
                return false;
            }
            if (defaultConfig.name.startsWith("(Windows) ")) {
                if (command.startsWith("cl.exe")) {
                    return true;
                }
            } else {
                if (!command.startsWith("cl.exe")) {
                    return true;
                }
            }
            return false;
        });

        // Generate new configurations for each build task.
        // Generating a task is async, therefore we must *await* *all* map(task => config) Promises to resolve.
        const configs: vscode.DebugConfiguration[] = await Promise.all(buildTasks.map<Promise<vscode.DebugConfiguration>>(async task => {
            const definition: CppBuildTaskDefinition = task.definition as CppBuildTaskDefinition;
            const compilerPath: string = definition.command;
            const compilerName: string = path.basename(compilerPath);
            const newConfig: vscode.DebugConfiguration = {...defaultConfig}; // Copy enumerables and properties

            newConfig.name = compilerName + buildAndDebugActiveFileStr();
            newConfig.preLaunchTask = task.name;
            if (newConfig.type === "cppdbg") {
                newConfig.externalConsole = false;
            } else {
                newConfig.console = "externalTerminal";
            }
            const exeName: string = path.join("${fileDirname}", "${fileBasenameNoExtension}");
            const isWindows: boolean = platform === 'win32';
            newConfig.program = isWindows ? exeName + ".exe" : exeName;
            // Add the "detail" property to show the compiler path in QuickPickItem.
            // This property will be removed before writing the DebugConfiguration in launch.json.
            newConfig.detail = task.detail ? task.detail : definition.command;
            const isCl: boolean = compilerName === "cl.exe";
            newConfig.cwd = isWindows && !isCl && !process.env.PATH?.includes(path.dirname(compilerPath)) ? path.dirname(compilerPath) : "${fileDirname}";

            return new Promise<vscode.DebugConfiguration>(resolve => {
                if (platform === "darwin") {
                    return resolve(newConfig);
                } else {
                    let debuggerName: string;
                    if (compilerName.startsWith("clang")) {
                        newConfig.MIMode = "lldb";
                        debuggerName = "lldb-mi";
                        // Search for clang-8, clang-10, etc.
                        if ((compilerName !== "clang-cl.exe") && (compilerName !== "clang-cpp.exe")) {
                            const suffixIndex: number = compilerName.indexOf("-");
                            if (suffixIndex !== -1) {
                                const suffix: string = compilerName.substr(suffixIndex);
                                debuggerName += suffix;
                            }
                        }
                        newConfig.type = "cppdbg";
                    } else if (compilerName === "cl.exe") {
                        newConfig.miDebuggerPath = undefined;
                        newConfig.type = "cppvsdbg";
                        return resolve(newConfig);
                    } else {
                        debuggerName = "gdb";
                    }
                    if (isWindows) {
                        debuggerName = debuggerName.endsWith(".exe") ? debuggerName : (debuggerName + ".exe");
                    }
                    const compilerDirname: string = path.dirname(compilerPath);
                    const debuggerPath: string = path.join(compilerDirname, debuggerName);
                    if (isWindows) {
                        newConfig.miDebuggerPath = debuggerPath;
                        return resolve(newConfig);
                    } else {
                        fs.stat(debuggerPath, (err, stats: fs.Stats) => {
                            if (!err && stats && stats.isFile) {
                                newConfig.miDebuggerPath = debuggerPath;
                            } else {
                                newConfig.miDebuggerPath = path.join("/usr", "bin", debuggerName);
                            }
                            return resolve(newConfig);
                        });
                    }
                }
            });
        }));
        configs.push(defaultConfig);
        return configs;
    }