Skip to content

Commit 84ce2f2

Browse files
authored
get launch config from settings.json as fallback (#585)
* get launch config from settings.json as fallback * update error return * remove dup getConfig
1 parent 9ecfa9f commit 84ce2f2

File tree

2 files changed

+140
-10
lines changed

2 files changed

+140
-10
lines changed

src/extension/debugger/configuration/launch.json/launchJsonReader.ts

+24-10
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,18 @@ export async function getConfigurationsForWorkspace(workspace: WorkspaceFolder):
1212
traceLog('Getting configurations for workspace');
1313
const filename = path.join(workspace.uri.fsPath, '.vscode', 'launch.json');
1414
if (!(await fs.pathExists(filename))) {
15-
// Check launch config in the workspace file
16-
const codeWorkspaceConfig = getConfiguration('launch', workspace);
17-
if (!codeWorkspaceConfig.configurations || !Array.isArray(codeWorkspaceConfig.configurations)) {
18-
return [];
19-
}
20-
traceLog('Using configuration in workspace');
21-
return codeWorkspaceConfig.configurations;
15+
return getConfigurationsFromSettings(workspace);
2216
}
23-
2417
const text = await fs.readFile(filename, 'utf-8');
2518
const parsed = parse(text, [], { allowTrailingComma: true, disallowComments: false });
26-
if (!parsed.configurations || !Array.isArray(parsed.configurations)) {
27-
throw Error('Missing field in launch.json: configurations');
19+
// no launch.json or no configurations found in launch.json, look in settings.json
20+
if (!parsed || !parsed.configurations) {
21+
traceLog('No configurations found in launch.json, looking in settings.json.');
22+
return getConfigurationsFromSettings(workspace);
23+
}
24+
// configurations found in launch.json, verify them then return
25+
if (!Array.isArray(parsed.configurations) || parsed.configurations.length === 0) {
26+
throw Error('Invalid configurations in launch.json');
2827
}
2928
if (!parsed.version) {
3029
throw Error('Missing field in launch.json: version');
@@ -42,3 +41,18 @@ export async function getConfigurationsByUri(uri?: Uri): Promise<DebugConfigurat
4241
}
4342
return [];
4443
}
44+
45+
export function getConfigurationsFromSettings(workspace: WorkspaceFolder): DebugConfiguration[] {
46+
// look in settings.json
47+
const codeWorkspaceConfig = getConfiguration('launch', workspace);
48+
// if this includes user configs, how do I make sure it selects the workspace ones first
49+
if (
50+
!codeWorkspaceConfig.configurations ||
51+
!Array.isArray(codeWorkspaceConfig.configurations) ||
52+
codeWorkspaceConfig.configurations.length === 0
53+
) {
54+
throw Error('No configurations found in launch.json or settings.json');
55+
}
56+
traceLog('Using configuration in workspace settings.json.');
57+
return codeWorkspaceConfig.configurations;
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
'use strict';
2+
3+
import * as assert from 'assert';
4+
import * as sinon from 'sinon';
5+
import * as typemoq from 'typemoq';
6+
import * as fs from 'fs-extra';
7+
import { WorkspaceFolder, Uri, WorkspaceConfiguration } from 'vscode';
8+
import {
9+
getConfigurationsForWorkspace,
10+
getConfigurationsFromSettings,
11+
} from '../../../../extension/debugger/configuration/launch.json/launchJsonReader';
12+
import * as vscodeapi from '../../../../extension/common/vscodeapi';
13+
14+
suite('Debugging - launchJsonReader', () => {
15+
let sandbox: sinon.SinonSandbox;
16+
17+
setup(() => {
18+
sandbox = sinon.createSandbox();
19+
});
20+
21+
teardown(() => {
22+
sandbox.restore();
23+
});
24+
25+
suite('getConfigurationsForWorkspace', () => {
26+
test('Should return configurations from launch.json if it exists', async () => {
27+
const workspace = typemoq.Mock.ofType<WorkspaceFolder>();
28+
workspace.setup((w) => w.uri).returns(() => Uri.file('/path/to/workspace'));
29+
30+
const launchJsonContent = `{
31+
"version": "0.2.0",
32+
"configurations": [
33+
{
34+
"name": "Launch Program",
35+
"type": "python",
36+
"request": "launch",
37+
"program": "${workspace.object.uri}/app.py"
38+
}
39+
]
40+
}`;
41+
42+
sandbox.stub(fs, 'pathExists').resolves(true);
43+
sandbox.stub(fs, 'readFile').resolves(launchJsonContent);
44+
45+
const configurations = await getConfigurationsForWorkspace(workspace.object);
46+
assert.strictEqual(configurations.length, 1);
47+
assert.strictEqual(configurations[0].name, 'Launch Program');
48+
});
49+
50+
test('Should return configurations from settings.json if launch.json does not exist', async () => {
51+
const workspace = typemoq.Mock.ofType<WorkspaceFolder>();
52+
workspace.setup((w) => w.uri).returns(() => Uri.file('/path/to/workspace'));
53+
54+
const mockConfig = typemoq.Mock.ofType<WorkspaceConfiguration>();
55+
mockConfig
56+
.setup((c) => c.configurations)
57+
.returns(() => [
58+
{
59+
name: 'Launch Program 2',
60+
type: 'python',
61+
request: 'launch',
62+
program: '${workspaceFolder}/app.py',
63+
},
64+
]);
65+
66+
sandbox.stub(fs, 'pathExists').resolves(false);
67+
sandbox.stub(vscodeapi, 'getConfiguration').returns(mockConfig.object);
68+
69+
const configurations = await getConfigurationsForWorkspace(workspace.object);
70+
assert.strictEqual(configurations.length, 1);
71+
assert.strictEqual(configurations[0].name, 'Launch Program 2');
72+
});
73+
});
74+
75+
suite('getConfigurationsFromSettings', () => {
76+
test('Should return configurations from settings.json', () => {
77+
const workspace = typemoq.Mock.ofType<WorkspaceFolder>();
78+
workspace.setup((w) => w.uri).returns(() => Uri.file('/path/to/workspace'));
79+
80+
const mockConfig = typemoq.Mock.ofType<WorkspaceConfiguration>();
81+
mockConfig
82+
.setup((c) => c.configurations)
83+
.returns(() => [
84+
{
85+
name: 'Launch Program 3',
86+
type: 'python',
87+
request: 'launch',
88+
program: '${workspaceFolder}/app.py',
89+
},
90+
]);
91+
92+
sandbox.stub(vscodeapi, 'getConfiguration').returns(mockConfig.object);
93+
94+
const configurations = getConfigurationsFromSettings(workspace.object);
95+
assert.strictEqual(configurations.length, 1);
96+
assert.strictEqual(configurations[0].name, 'Launch Program 3');
97+
});
98+
99+
test('Should error if no configurations in settings.json', () => {
100+
const workspace = typemoq.Mock.ofType<WorkspaceFolder>();
101+
workspace.setup((w) => w.uri).returns(() => Uri.file('/path/to/workspace'));
102+
103+
const mockConfig = typemoq.Mock.ofType<WorkspaceConfiguration>();
104+
mockConfig.setup((c) => c.get('configurations')).returns(() => []);
105+
mockConfig.setup((c) => c.configurations).returns(() => []);
106+
107+
sandbox.stub(vscodeapi, 'getConfiguration').returns(mockConfig.object);
108+
109+
assert.throws(
110+
() => getConfigurationsFromSettings(workspace.object),
111+
Error,
112+
'No configurations found in launch.json or settings.json',
113+
);
114+
});
115+
});
116+
});

0 commit comments

Comments
 (0)