public resolveDebugConfigurationWithSubstitutedVariables()

in src/goDebugConfiguration.ts [405:501]


	public resolveDebugConfigurationWithSubstitutedVariables(
		folder: vscode.WorkspaceFolder | undefined,
		debugConfiguration: vscode.DebugConfiguration,
		token?: vscode.CancellationToken
	): vscode.DebugConfiguration | null {
		const debugAdapter = debugConfiguration['debugAdapter'];
		if (debugAdapter === '') {
			return null;
		}

		// Read debugConfiguration.envFile and
		// combine the environment variables from all the env files and
		// debugConfiguration.env.
		// We also unset 'envFile' from the user-suppled debugConfiguration
		// because it is already applied.
		//
		// For legacy mode, we merge the environment variables on top of
		// the tools execution environment variables and update the debugConfiguration
		// because VS Code directly handles launch of the legacy debug adapter.
		// For dlv-dap mode, we do not merge process.env environment
		// variables here to reduce the number of environment variables passed
		// as launch/attach parameters.
		const mergeProcessEnv = debugAdapter === 'legacy';
		const goToolsEnvVars = toolExecutionEnvironment(folder?.uri, mergeProcessEnv);
		const fileEnvs = parseEnvFiles(debugConfiguration['envFile']);
		const env = debugConfiguration['env'] || {};

		debugConfiguration['env'] = Object.assign(goToolsEnvVars, fileEnvs, env);
		debugConfiguration['envFile'] = undefined; // unset, since we already processed.

		const entriesWithRelativePaths = ['cwd', 'output', 'program'].filter(
			(attr) => debugConfiguration[attr] && !path.isAbsolute(debugConfiguration[attr])
		);
		if (debugAdapter === 'dlv-dap') {
			// 1. Relative paths -> absolute paths
			if (entriesWithRelativePaths.length > 0) {
				const workspaceRoot = folder?.uri.fsPath;
				if (workspaceRoot) {
					entriesWithRelativePaths.forEach((attr) => {
						debugConfiguration[attr] = path.join(workspaceRoot, debugConfiguration[attr]);
					});
				} else {
					this.showWarning(
						'relativePathsWithoutWorkspaceFolder',
						'Behavior when using relative paths without a workspace folder for `cwd`, `program`, or `output` is undefined.'
					);
				}
			}
			// 2. For launch debug/test modes that builds the debug target,
			//    delve needs to be launched from the right directory (inside the main module of the target).
			//    Compute the launch dir heuristically, and translate the dirname in program to a path relative to buildDir.
			//    We skip this step when working with externally launched debug adapter
			//    because we do not control the adapter's launch process.
			if (debugConfiguration.request === 'launch') {
				const mode = debugConfiguration['mode'] || 'debug';
				if (['debug', 'test', 'auto'].includes(mode)) {
					// Massage config to build the target from the package directory
					// with a relative path. (https://github.com/golang/vscode-go/issues/1713)
					// parseDebugProgramArgSync will throw an error if `program` is invalid.
					const { program, dirname, programIsDirectory } = parseDebugProgramArgSync(
						debugConfiguration['program']
					);
					if (
						dirname &&
						// Presence of the following attributes indicates externally launched debug adapter.
						// Don't mess with 'program' if the debug adapter was launched externally.
						!debugConfiguration.port &&
						!debugConfiguration.debugServer
					) {
						debugConfiguration['__buildDir'] = dirname;
						debugConfiguration['program'] = programIsDirectory
							? '.'
							: '.' + path.sep + path.relative(dirname, program);
					}
				}
			}
		}

		// convert args string into string array if needed
		if (debugConfiguration.request === 'launch' && typeof debugConfiguration['args'] === 'string') {
			const argsOrErrorMsg = parseArgsString(debugConfiguration['args']);
			if (typeof argsOrErrorMsg === 'string') {
				throw new Error(argsOrErrorMsg);
			} else {
				debugConfiguration['args'] = argsOrErrorMsg;
			}
		}

		if (debugConfiguration.request === 'attach' && debugConfiguration['mode'] === 'local') {
			// processId needs to be an int, but the substituted variables from pickGoProcess and pickProcess
			// become a string. Convert any strings to integers.
			if (typeof debugConfiguration['processId'] === 'string') {
				debugConfiguration['processId'] = parseInt(debugConfiguration['processId'], 10);
			}
		}
		return debugConfiguration;
	}