Skip to content

Commit

Permalink
src/goDebugConfiguration: resolve relative paths used in cwd, output,…
Browse files Browse the repository at this point in the history
… 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 <hyangah@gmail.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Suzy Mueller <suzmue@golang.org>
  • Loading branch information
hyangah committed Jun 10, 2021
1 parent ac7b209 commit 1bc09d8
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 7 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,8 @@
},
"cwd": {
"type": "string",
"description": "Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.",
"default": "."
"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.",
"default": ""
},
"env": {
"type": "object",
Expand Down
18 changes: 17 additions & 1 deletion src/goDebugConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { packagePathToGoModPathMap } from './goModules';
import { getTool, getToolAtVersion } from './goTools';
import { pickProcess, pickProcessByName } from './pickProcess';
import { getFromGlobalState, updateGlobalState } from './stateUtils';
import { getBinPath, getGoVersion } from './util';
import { getBinPath, getGoVersion, getWorkspaceFolderPath, resolvePath } from './util';
import { parseEnvFiles } from './utils/envUtils';
import { resolveHomeDir } from './utils/pathUtils';

Expand Down Expand Up @@ -389,6 +389,22 @@ export class GoDebugConfigurationProvider implements vscode.DebugConfigurationPr
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 (debugConfiguration['debugAdapter'] === 'dlv-dap' && entriesWithRelativePaths.length > 0) {
const workspaceRoot = folder?.uri.fsPath;
if (!workspaceRoot) {
this.showWarning(
'relativePathsWithoutWorkspaceFolder',
'Relative paths without a workspace folder for `cwd`, `program`, or `output` are not allowed.'
);
return null;
}
entriesWithRelativePaths.forEach((attr) => {
debugConfiguration[attr] = path.join(workspaceRoot, debugConfiguration[attr]);
});
}
return debugConfiguration;
}

Expand Down
8 changes: 4 additions & 4 deletions src/goDebugFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,10 @@ function spawnDlvDapServerProcess(

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

// TODO(hyangah): determine the directories:
// run `dlv` => where dlv will create the default __debug_bin. (This won't work if the directory is not writable. Fix it)
// build program => 'program' directory. (This won't work for multimodule workspace. Fix it)
// run program => cwd (If test, make sure to run in the package directory.)
// TODO(hyangah): In module-module workspace mode, the program should be build in the super module directory
// where go.work (gopls.mod) file is present. Where dlv runs determines the build directory currently. Two options:
// 1) launch dlv in the super-module module directory and adjust launchArgs.cwd (--wd).
// 2) introduce a new buildDir launch attribute.
return new Promise<ChildProcess>((resolve, reject) => {
const p = spawn(dlvPath, dlvArgs, {
cwd: dir,
Expand Down
106 changes: 106 additions & 0 deletions test/integration/goDebugConfiguration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,112 @@ suite('Debug Configuration Resolve Paths', () => {
});
});

suite('Debug Configuration Converts Relative Paths', () => {
const debugConfigProvider = new GoDebugConfigurationProvider();

function debugConfig(adapter: string) {
return {
name: 'Launch',
type: 'go',
request: 'launch',
mode: 'auto',
debugAdapter: adapter,
program: path.join('foo', 'bar.go'),
cwd: '.',
output: 'debug'
};
}

test('resolve relative paths with workspace root in dlv-dap mode', () => {
const config = debugConfig('dlv-dap');
const workspaceFolder = {
uri: vscode.Uri.file(os.tmpdir()),
name: 'test',
index: 0
};
const { program, cwd, output } = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(
workspaceFolder,
config
);
assert.deepStrictEqual(
{ program, cwd, output },
{
program: path.join(os.tmpdir(), 'foo/bar.go'),
cwd: os.tmpdir(),
output: path.join(os.tmpdir(), 'debug')
}
);
});

test('empty, undefined paths are not affected', () => {
const config = debugConfig('dlv-dap');
config.program = undefined;
config.cwd = '';
delete config.output;

const workspaceFolder = {
uri: vscode.Uri.file(os.tmpdir()),
name: 'test',
index: 0
};
const { program, cwd, output } = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(
workspaceFolder,
config
);
assert.deepStrictEqual(
{ program, cwd, output },
{
program: undefined,
cwd: '',
output: undefined
}
);
});

test('disallow relative paths with no workspace root', () => {
const config = debugConfig('dlv-dap');
const got = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(undefined, config);
assert.strictEqual(got, null);
});

test('do not affect relative paths (workspace) in legacy mode', () => {
const config = debugConfig('legacy');
const workspaceFolder = {
uri: vscode.Uri.file(os.tmpdir()),
name: 'test',
index: 0
};
const { program, cwd, output } = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(
workspaceFolder,
config
);
assert.deepStrictEqual(
{ program, cwd, output },
{
program: path.join('foo', 'bar.go'),
cwd: '.',
output: 'debug'
}
);
});

test('do not affect relative paths (no workspace) in legacy mode', () => {
const config = debugConfig('legacy');
const { program, cwd, output } = debugConfigProvider.resolveDebugConfigurationWithSubstitutedVariables(
undefined,
config
);
assert.deepStrictEqual(
{ program, cwd, output },
{
program: path.join('foo', 'bar.go'),
cwd: '.',
output: 'debug'
}
);
});
});

suite('Debug Configuration Auto Mode', () => {
const debugConfigProvider = new GoDebugConfigurationProvider();
test('resolve auto to debug with non-test file', () => {
Expand Down

0 comments on commit 1bc09d8

Please # to comment.