Skip to content

Commit 127457d

Browse files
Set debug as deprecated (#22738)
- Add provider in order to keep python debugger type working. - Set debugger as deprecated
1 parent d5a8141 commit 127457d

7 files changed

Lines changed: 164 additions & 5 deletions

File tree

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,7 @@
11411141
}
11421142
}
11431143
},
1144+
"deprecated": "%python.debugger.deprecatedMessage%",
11441145
"configurationSnippets": [],
11451146
"label": "Python",
11461147
"languages": [
@@ -1150,7 +1151,8 @@
11501151
"variables": {
11511152
"pickProcess": "python.pickLocalProcess"
11521153
},
1153-
"when": "!virtualWorkspace && shellExecutionSupported"
1154+
"when": "!virtualWorkspace && shellExecutionSupported",
1155+
"hiddenWhen": "true"
11541156
}
11551157
],
11561158
"grammars": [

package.nls.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"python.command.python.createNewFile.title": "New Python File",
55
"python.command.python.createTerminal.title": "Create Terminal",
66
"python.command.python.execInTerminal.title": "Run Python File in Terminal",
7-
"python.command.python.debugInTerminal.title": "Debug Python File",
87
"python.command.python.execInTerminalIcon.title": "Run Python File",
98
"python.command.python.execInDedicatedTerminal.title": "Run Python File in Dedicated Terminal",
109
"python.command.python.setInterpreter.title": "Select Interpreter",
@@ -30,6 +29,7 @@
3029
"python.activeStateToolPath.description": "Path to the State Tool executable for ActiveState runtimes (version 0.36+).",
3130
"python.autoComplete.extraPaths.description": "List of paths to libraries and the like that need to be imported by auto complete engine. E.g. when using Google App SDK, the paths are not in system path, hence need to be added into this list.",
3231
"python.condaPath.description": "Path to the conda executable to use for activation (version 4.4+).",
32+
"python.debugger.deprecatedMessage": "This configuration will be deprecated soon. Please replace `python` with `debugpy` to use the new Python Debugger extension.",
3333
"python.defaultInterpreterPath.description": "Path to default Python to use when extension loads up for the first time, no longer used once an interpreter is selected for the workspace. See [here](https://aka.ms/AAfekmf) to understand when this is used",
3434
"python.diagnostics.sourceMapsEnabled.description": "Enable source map support for meaningful stack traces in error logs.",
3535
"python.envFile.description": "Absolute path to a file containing environment variable definitions.",
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
'use strict';
5+
6+
import { inject, injectable, named } from 'inversify';
7+
import { CancellationToken, DebugConfiguration, WorkspaceFolder } from 'vscode';
8+
import { AttachRequestArguments, LaunchRequestArguments } from '../../types';
9+
import { IDebugConfigurationService } from '../types';
10+
import { IDebugConfigurationResolver } from './types';
11+
12+
@injectable()
13+
export class PythonDebugConfigurationService implements IDebugConfigurationService {
14+
constructor(
15+
@inject(IDebugConfigurationResolver)
16+
@named('attach')
17+
private readonly attachResolver: IDebugConfigurationResolver<AttachRequestArguments>,
18+
@inject(IDebugConfigurationResolver)
19+
@named('launch')
20+
private readonly launchResolver: IDebugConfigurationResolver<LaunchRequestArguments>,
21+
) {}
22+
23+
public async resolveDebugConfiguration(
24+
folder: WorkspaceFolder | undefined,
25+
debugConfiguration: DebugConfiguration,
26+
token?: CancellationToken,
27+
): Promise<DebugConfiguration | undefined> {
28+
if (debugConfiguration.request === 'attach') {
29+
return this.attachResolver.resolveDebugConfiguration(
30+
folder,
31+
debugConfiguration as AttachRequestArguments,
32+
token,
33+
);
34+
}
35+
if (debugConfiguration.request === 'test') {
36+
// `"request": "test"` is now deprecated. But some users might have it in their
37+
// launch config. We get here if they triggered it using F5 or start with debugger.
38+
throw Error(
39+
'This configuration can only be used by the test debugging commands. `"request": "test"` is deprecated, please keep as `"request": "launch"` and add `"purpose": ["debug-test"]` instead.',
40+
);
41+
} else {
42+
if (Object.keys(debugConfiguration).length === 0) {
43+
return undefined;
44+
}
45+
return this.launchResolver.resolveDebugConfiguration(
46+
folder,
47+
debugConfiguration as LaunchRequestArguments,
48+
token,
49+
);
50+
}
51+
}
52+
53+
public async resolveDebugConfigurationWithSubstitutedVariables(
54+
folder: WorkspaceFolder | undefined,
55+
debugConfiguration: DebugConfiguration,
56+
token?: CancellationToken,
57+
): Promise<DebugConfiguration | undefined> {
58+
function resolve<T extends DebugConfiguration>(resolver: IDebugConfigurationResolver<T>) {
59+
return resolver.resolveDebugConfigurationWithSubstitutedVariables(folder, debugConfiguration as T, token);
60+
}
61+
return debugConfiguration.request === 'attach' ? resolve(this.attachResolver) : resolve(this.launchResolver);
62+
}
63+
}

src/client/debugger/extension/serviceRegistry.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { DebugSessionLoggingFactory } from './adapter/logging';
1212
import { OutdatedDebuggerPromptFactory } from './adapter/outdatedDebuggerPrompt';
1313
import { AttachProcessProviderFactory } from './attachQuickPick/factory';
1414
import { IAttachProcessProviderFactory } from './attachQuickPick/types';
15+
import { PythonDebugConfigurationService } from './configuration/debugConfigurationService';
1516
import { AttachConfigurationResolver } from './configuration/resolvers/attach';
1617
import { DebugEnvironmentVariablesHelper, IDebugEnvironmentVariablesService } from './configuration/resolvers/helper';
1718
import { LaunchConfigurationResolver } from './configuration/resolvers/launch';
@@ -20,9 +21,18 @@ import { DebugCommands } from './debugCommands';
2021
import { ChildProcessAttachEventHandler } from './hooks/childProcessAttachHandler';
2122
import { ChildProcessAttachService } from './hooks/childProcessAttachService';
2223
import { IChildProcessAttachService, IDebugSessionEventHandlers } from './hooks/types';
23-
import { IDebugAdapterDescriptorFactory, IDebugSessionLoggingFactory, IOutdatedDebuggerPromptFactory } from './types';
24+
import {
25+
IDebugAdapterDescriptorFactory,
26+
IDebugConfigurationService,
27+
IDebugSessionLoggingFactory,
28+
IOutdatedDebuggerPromptFactory,
29+
} from './types';
2430

2531
export function registerTypes(serviceManager: IServiceManager): void {
32+
serviceManager.addSingleton<IDebugConfigurationService>(
33+
IDebugConfigurationService,
34+
PythonDebugConfigurationService,
35+
);
2636
serviceManager.addSingleton<IChildProcessAttachService>(IChildProcessAttachService, ChildProcessAttachService);
2737
serviceManager.addSingleton<IDebugSessionEventHandlers>(IDebugSessionEventHandlers, ChildProcessAttachEventHandler);
2838
serviceManager.addSingleton<IDebugConfigurationResolver<LaunchRequestArguments>>(

src/client/debugger/extension/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
'use strict';
55

6-
import { DebugAdapterDescriptorFactory, DebugAdapterTrackerFactory } from 'vscode';
6+
import { DebugAdapterDescriptorFactory, DebugAdapterTrackerFactory, DebugConfigurationProvider } from 'vscode';
7+
8+
export const IDebugConfigurationService = Symbol('IDebugConfigurationService');
9+
export interface IDebugConfigurationService extends DebugConfigurationProvider {}
710

811
export const IDebugAdapterDescriptorFactory = Symbol('IDebugAdapterDescriptorFactory');
912
export interface IDebugAdapterDescriptorFactory extends DebugAdapterDescriptorFactory {}

src/client/extensionActivation.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
'use strict';
55

6-
import { languages, window } from 'vscode';
6+
import { DebugConfigurationProvider, debug, languages, window } from 'vscode';
77

88
import { registerTypes as activationRegisterTypes } from './activation/serviceRegistry';
99
import { IExtensionActivationManager } from './activation/types';
@@ -23,6 +23,7 @@ import {
2323
} from './common/types';
2424
import { noop } from './common/utils/misc';
2525
import { registerTypes as debugConfigurationRegisterTypes } from './debugger/extension/serviceRegistry';
26+
import { IDebugConfigurationService } from './debugger/extension/types';
2627
import { IInterpreterService } from './interpreter/contracts';
2728
import { getLanguageConfiguration } from './language/languageConfiguration';
2829
import { ReplProvider } from './providers/replProvider';
@@ -49,6 +50,7 @@ import { registerAllCreateEnvironmentFeatures } from './pythonEnvironments/creat
4950
import { registerCreateEnvironmentTriggers } from './pythonEnvironments/creation/createEnvironmentTrigger';
5051
import { initializePersistentStateForTriggers } from './common/persistentState';
5152
import { logAndNotifyOnLegacySettings } from './logging/settingLogs';
53+
import { DebuggerTypeName } from './debugger/constants';
5254

5355
export async function activateComponents(
5456
// `ext` is passed to any extra activation funcs.
@@ -162,6 +164,12 @@ async function activateLegacy(ext: ExtensionState): Promise<ActivationResult> {
162164

163165
const terminalProvider = new TerminalProvider(serviceContainer);
164166
terminalProvider.initialize(window.activeTerminal).ignoreErrors();
167+
168+
serviceContainer
169+
.getAll<DebugConfigurationProvider>(IDebugConfigurationService)
170+
.forEach((debugConfigProvider) => {
171+
disposables.push(debug.registerDebugConfigurationProvider(DebuggerTypeName, debugConfigProvider));
172+
});
165173
disposables.push(terminalProvider);
166174

167175
logAndNotifyOnLegacySettings();
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
'use strict';
5+
6+
import { expect } from 'chai';
7+
import * as typemoq from 'typemoq';
8+
import { DebugConfiguration, Uri } from 'vscode';
9+
import { PythonDebugConfigurationService } from '../../../../client/debugger/extension/configuration/debugConfigurationService';
10+
import { IDebugConfigurationResolver } from '../../../../client/debugger/extension/configuration/types';
11+
import { AttachRequestArguments, LaunchRequestArguments } from '../../../../client/debugger/types';
12+
13+
suite('Debugging - Configuration Service', () => {
14+
let attachResolver: typemoq.IMock<IDebugConfigurationResolver<AttachRequestArguments>>;
15+
let launchResolver: typemoq.IMock<IDebugConfigurationResolver<LaunchRequestArguments>>;
16+
let configService: TestPythonDebugConfigurationService;
17+
18+
class TestPythonDebugConfigurationService extends PythonDebugConfigurationService {}
19+
setup(() => {
20+
attachResolver = typemoq.Mock.ofType<IDebugConfigurationResolver<AttachRequestArguments>>();
21+
launchResolver = typemoq.Mock.ofType<IDebugConfigurationResolver<LaunchRequestArguments>>();
22+
configService = new TestPythonDebugConfigurationService(attachResolver.object, launchResolver.object);
23+
});
24+
test('Should use attach resolver when passing attach config', async () => {
25+
const config = ({
26+
request: 'attach',
27+
} as DebugConfiguration) as AttachRequestArguments;
28+
const folder = { name: '1', index: 0, uri: Uri.parse('1234') };
29+
const expectedConfig = { yay: 1 };
30+
31+
attachResolver
32+
.setup((a) =>
33+
a.resolveDebugConfiguration(typemoq.It.isValue(folder), typemoq.It.isValue(config), typemoq.It.isAny()),
34+
)
35+
.returns(() => Promise.resolve((expectedConfig as unknown) as AttachRequestArguments))
36+
.verifiable(typemoq.Times.once());
37+
launchResolver
38+
.setup((a) => a.resolveDebugConfiguration(typemoq.It.isAny(), typemoq.It.isAny(), typemoq.It.isAny()))
39+
.verifiable(typemoq.Times.never());
40+
41+
const resolvedConfig = await configService.resolveDebugConfiguration(folder, config as DebugConfiguration);
42+
43+
expect(resolvedConfig).to.deep.equal(expectedConfig);
44+
attachResolver.verifyAll();
45+
launchResolver.verifyAll();
46+
});
47+
[{ request: 'launch' }, { request: undefined }].forEach((config) => {
48+
test(`Should use launch resolver when passing launch config with request=${config.request}`, async () => {
49+
const folder = { name: '1', index: 0, uri: Uri.parse('1234') };
50+
const expectedConfig = { yay: 1 };
51+
52+
launchResolver
53+
.setup((a) =>
54+
a.resolveDebugConfiguration(
55+
typemoq.It.isValue(folder),
56+
typemoq.It.isValue((config as DebugConfiguration) as LaunchRequestArguments),
57+
typemoq.It.isAny(),
58+
),
59+
)
60+
.returns(() => Promise.resolve((expectedConfig as unknown) as LaunchRequestArguments))
61+
.verifiable(typemoq.Times.once());
62+
attachResolver
63+
.setup((a) => a.resolveDebugConfiguration(typemoq.It.isAny(), typemoq.It.isAny(), typemoq.It.isAny()))
64+
.verifiable(typemoq.Times.never());
65+
66+
const resolvedConfig = await configService.resolveDebugConfiguration(folder, config as DebugConfiguration);
67+
68+
expect(resolvedConfig).to.deep.equal(expectedConfig);
69+
attachResolver.verifyAll();
70+
launchResolver.verifyAll();
71+
});
72+
});
73+
});

0 commit comments

Comments
 (0)