Skip to content

Commit 1bc09d8

Browse files
committed
src/goDebugConfiguration: resolve relative paths used in cwd, output, program
If relative paths are used, translate them to be relative to the workspace folder when using dlv-dap. The description in the package.json says cwd is a workspace relative or absolute path, but this seems to be broken in the old adapter (I.e., when cwd=., the old adapter simply used it as --wd value and launched the headless server in the program directory. As a result, '.' is translated as the program or package source directory). This CL doesn't attempt to fix or change the behavior of the old adapter though, but applies the translation only when dlv-dap is used. This changes the default cwd value (when users attempt to add cwd to their launch config) to be '' which is treated as if 'cwd' attribute was undefined. Users who want to use the workspace folder can use `${workspaceFolder}` or `.`. This change doesn't change 'cwd' in attach mode because this is currently used for different purpose in the legacy adapter, and it will become irrelevant in dlv-dap. Updates #1348 Change-Id: Ieb15f6bbb470a17d2e7350ccf1d8a003cbb92eeb Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/317210 Trust: Hyang-Ah Hana Kim <[email protected]> Run-TryBot: Hyang-Ah Hana Kim <[email protected]> TryBot-Result: kokoro <[email protected]> Reviewed-by: Suzy Mueller <[email protected]>
1 parent ac7b209 commit 1bc09d8

File tree

4 files changed

+129
-7
lines changed

4 files changed

+129
-7
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,8 @@
576576
},
577577
"cwd": {
578578
"type": "string",
579-
"description": "Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.",
580-
"default": "."
579+
"description": "Workspace relative or absolute path to the working directory of the program being debugged if a non-empty value is specified. The 'program' folder is used as the working directory if it is omitted or empty.",
580+
"default": ""
581581
},
582582
"env": {
583583
"type": "object",

src/goDebugConfiguration.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { packagePathToGoModPathMap } from './goModules';
2323
import { getTool, getToolAtVersion } from './goTools';
2424
import { pickProcess, pickProcessByName } from './pickProcess';
2525
import { getFromGlobalState, updateGlobalState } from './stateUtils';
26-
import { getBinPath, getGoVersion } from './util';
26+
import { getBinPath, getGoVersion, getWorkspaceFolderPath, resolvePath } from './util';
2727
import { parseEnvFiles } from './utils/envUtils';
2828
import { resolveHomeDir } from './utils/pathUtils';
2929

@@ -389,6 +389,22 @@ export class GoDebugConfigurationProvider implements vscode.DebugConfigurationPr
389389
debugConfiguration['env'] = Object.assign(goToolsEnvVars, fileEnvs, env);
390390
debugConfiguration['envFile'] = undefined; // unset, since we already processed.
391391

392+
const entriesWithRelativePaths = ['cwd', 'output', 'program'].filter(
393+
(attr) => debugConfiguration[attr] && !path.isAbsolute(debugConfiguration[attr])
394+
);
395+
if (debugConfiguration['debugAdapter'] === 'dlv-dap' && entriesWithRelativePaths.length > 0) {
396+
const workspaceRoot = folder?.uri.fsPath;
397+
if (!workspaceRoot) {
398+
this.showWarning(
399+
'relativePathsWithoutWorkspaceFolder',
400+
'Relative paths without a workspace folder for `cwd`, `program`, or `output` are not allowed.'
401+
);
402+
return null;
403+
}
404+
entriesWithRelativePaths.forEach((attr) => {
405+
debugConfiguration[attr] = path.join(workspaceRoot, debugConfiguration[attr]);
406+
});
407+
}
392408
return debugConfiguration;
393409
}
394410

src/goDebugFactory.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,10 +412,10 @@ function spawnDlvDapServerProcess(
412412

413413
logConsole(`Starting: ${dlvPath} ${dlvArgs.join(' ')}\n`);
414414

415-
// TODO(hyangah): determine the directories:
416-
// run `dlv` => where dlv will create the default __debug_bin. (This won't work if the directory is not writable. Fix it)
417-
// build program => 'program' directory. (This won't work for multimodule workspace. Fix it)
418-
// run program => cwd (If test, make sure to run in the package directory.)
415+
// TODO(hyangah): In module-module workspace mode, the program should be build in the super module directory
416+
// where go.work (gopls.mod) file is present. Where dlv runs determines the build directory currently. Two options:
417+
// 1) launch dlv in the super-module module directory and adjust launchArgs.cwd (--wd).
418+
// 2) introduce a new buildDir launch attribute.
419419
return new Promise<ChildProcess>((resolve, reject) => {
420420
const p = spawn(dlvPath, dlvArgs, {
421421
cwd: dir,

test/integration/goDebugConfiguration.test.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,112 @@ suite('Debug Configuration Resolve Paths', () => {
439439
});
440440
});
441441

442+
suite('Debug Configuration Converts Relative Paths', () => {
443+
const debugConfigProvider = new GoDebugConfigurationProvider();
444+
445+
function debugConfig(adapter: string) {
446+
return {
447+
name: 'Launch',
448+
type: 'go',
449+
request: 'launch',
450+
mode: 'auto',
451+
debugAdapter: adapter,
452+
program: path.join('foo', 'bar.go'),
453+
cwd: '.',
454+
output: 'debug'
455+
};
456+
}
457+
458+
test('resolve relative paths with workspace root in dlv-dap mode', () => {
459+
const config = debugConfig('dlv-dap');
460+
const workspaceFolder = {
461+
uri: vscode.Uri.file(os.tmpdir()),
462+
name: 'test',
463+
index: 0
464+
};
465+
const { program, cwd, output } = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(
466+
workspaceFolder,
467+
config
468+
);
469+
assert.deepStrictEqual(
470+
{ program, cwd, output },
471+
{
472+
program: path.join(os.tmpdir(), 'foo/bar.go'),
473+
cwd: os.tmpdir(),
474+
output: path.join(os.tmpdir(), 'debug')
475+
}
476+
);
477+
});
478+
479+
test('empty, undefined paths are not affected', () => {
480+
const config = debugConfig('dlv-dap');
481+
config.program = undefined;
482+
config.cwd = '';
483+
delete config.output;
484+
485+
const workspaceFolder = {
486+
uri: vscode.Uri.file(os.tmpdir()),
487+
name: 'test',
488+
index: 0
489+
};
490+
const { program, cwd, output } = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(
491+
workspaceFolder,
492+
config
493+
);
494+
assert.deepStrictEqual(
495+
{ program, cwd, output },
496+
{
497+
program: undefined,
498+
cwd: '',
499+
output: undefined
500+
}
501+
);
502+
});
503+
504+
test('disallow relative paths with no workspace root', () => {
505+
const config = debugConfig('dlv-dap');
506+
const got = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(undefined, config);
507+
assert.strictEqual(got, null);
508+
});
509+
510+
test('do not affect relative paths (workspace) in legacy mode', () => {
511+
const config = debugConfig('legacy');
512+
const workspaceFolder = {
513+
uri: vscode.Uri.file(os.tmpdir()),
514+
name: 'test',
515+
index: 0
516+
};
517+
const { program, cwd, output } = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(
518+
workspaceFolder,
519+
config
520+
);
521+
assert.deepStrictEqual(
522+
{ program, cwd, output },
523+
{
524+
program: path.join('foo', 'bar.go'),
525+
cwd: '.',
526+
output: 'debug'
527+
}
528+
);
529+
});
530+
531+
test('do not affect relative paths (no workspace) in legacy mode', () => {
532+
const config = debugConfig('legacy');
533+
const { program, cwd, output } = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(
534+
undefined,
535+
config
536+
);
537+
assert.deepStrictEqual(
538+
{ program, cwd, output },
539+
{
540+
program: path.join('foo', 'bar.go'),
541+
cwd: '.',
542+
output: 'debug'
543+
}
544+
);
545+
});
546+
});
547+
442548
suite('Debug Configuration Auto Mode', () => {
443549
const debugConfigProvider = new GoDebugConfigurationProvider();
444550
test('resolve auto to debug with non-test file', () => {

0 commit comments

Comments
 (0)