Skip to content

Commit 0e00762

Browse files
authored
Add wizard to provide attach to pid debug configuration (#8915)
* Add attach to pid debug configuration wizard * Update language file * Add news * Use enum for default value
1 parent ea254b5 commit 0e00762

File tree

13 files changed

+121
-6
lines changed

13 files changed

+121
-6
lines changed

news/1 Enhancements/8702.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Provide attach to pid configuration via picker.

package.json

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,8 +1372,19 @@
13721372
"default": true
13731373
},
13741374
"processId": {
1375-
"type": "number",
1376-
"description": "ID of the local process to attach to."
1375+
"anyOf": [
1376+
{
1377+
"enum": [
1378+
"${command:pickProcess}"
1379+
],
1380+
"description": "Use process picker to select a process to attach, or Process ID as integer.",
1381+
"default": "${command:pickProcess}"
1382+
},
1383+
{
1384+
"type": "integer",
1385+
"description": "ID of the local process to attach to."
1386+
}
1387+
]
13771388
}
13781389
}
13791390
}

package.nls.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
"python.snippet.launch.module.label": "Python: Module",
7878
"python.snippet.launch.module.default": "enter-your-module-name",
7979
"python.snippet.launch.attach.label": "Python: Remote Attach",
80+
"python.snippet.launch.attachpid.label": "Python: Attach using Process Id",
8081
"python.snippet.launch.django.label": "Python: Django",
8182
"python.snippet.launch.flask.label": "Python: Flask",
8283
"python.snippet.launch.pyramid.label": "Python: Pyramid Application",
@@ -255,6 +256,8 @@
255256
"debug.attachRemotePortTitle": "Remote Debugging",
256257
"debug.attachRemotePortPrompt": "Enter the port number that the ptvsd server is listening on",
257258
"debug.attachRemotePortValidationError": "Enter a valid port number",
259+
"debug.attachPidConfigurationLabel": "Attach using Process ID",
260+
"debug.attachPidConfigurationDescription": "Attach to a local process",
258261
"debug.debugDjangoConfigurationLabel": "Django",
259262
"debug.debugDjangoConfigurationDescription": "Launch and debug a Django web application",
260263
"debug.djangoEnterManagePyPathTitle": "Debug Django",

src/client/common/utils/localize.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,16 @@ export namespace DebugConfigStrings {
394394
invalid: localize('debug.attachRemotePortValidationError')
395395
};
396396
}
397+
export namespace attachPid {
398+
export const snippet = {
399+
name: localize('python.snippet.launch.attachpid.label')
400+
};
401+
// tslint:disable-next-line:no-shadowed-variable
402+
export const selectConfiguration = {
403+
label: localize('debug.attachPidConfigurationLabel'),
404+
description: localize('debug.attachPidConfigurationDescription')
405+
};
406+
}
397407
export namespace django {
398408
export const snippet = {
399409
name: localize('python.snippet.launch.django.label')

src/client/debugger/extension/configuration/debugConfigurationService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ export class PythonDebugConfigurationService implements IDebugConfigurationServi
7777
label: DebugConfigStrings.attach.selectConfiguration.label(),
7878
type: DebugConfigurationType.remoteAttach,
7979
description: DebugConfigStrings.attach.selectConfiguration.description()
80+
}, {
81+
label: DebugConfigStrings.attachPid.selectConfiguration.label(),
82+
type: DebugConfigurationType.pidAttach,
83+
description: DebugConfigStrings.attachPid.selectConfiguration.description()
8084
}, {
8185
label: DebugConfigStrings.django.selectConfiguration.label(),
8286
type: DebugConfigurationType.launchDjango,
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
'use strict';
5+
6+
import { injectable } from 'inversify';
7+
import { DebugConfigStrings } from '../../../../common/utils/localize';
8+
import { MultiStepInput } from '../../../../common/utils/multiStepInput';
9+
import { captureTelemetry } from '../../../../telemetry';
10+
import { EventName } from '../../../../telemetry/constants';
11+
import { DebuggerTypeName } from '../../../constants';
12+
import { AttachRequestArguments } from '../../../types';
13+
import { DebugConfigurationState, DebugConfigurationType, IDebugConfigurationProvider } from '../../types';
14+
15+
@injectable()
16+
export class PidAttachDebugConfigurationProvider implements IDebugConfigurationProvider {
17+
@captureTelemetry(EventName.DEBUGGER_CONFIGURATION_PROMPTS, { configurationType: DebugConfigurationType.pidAttach }, false)
18+
public async buildConfiguration(_input: MultiStepInput<DebugConfigurationState>, state: DebugConfigurationState) {
19+
const config: Partial<AttachRequestArguments> = {
20+
name: DebugConfigStrings.attachPid.snippet.name(),
21+
type: DebuggerTypeName,
22+
request: 'attach',
23+
// tslint:disable-next-line:no-invalid-template-strings
24+
processId: '${command:pickProcess}',
25+
pathMappings: [
26+
{
27+
// tslint:disable-next-line:no-invalid-template-strings
28+
localRoot: '${workspaceFolder}',
29+
remoteRoot: '.'
30+
}
31+
]
32+
};
33+
Object.assign(state.config, config);
34+
}
35+
}

src/client/debugger/extension/configuration/providers/providerFactory.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ export class DebugConfigurationProviderFactory implements IDebugConfigurationPro
1616
@inject(IDebugConfigurationProvider) @named(DebugConfigurationType.launchModule) moduleProvider: IDebugConfigurationProvider,
1717
@inject(IDebugConfigurationProvider) @named(DebugConfigurationType.launchFile) fileProvider: IDebugConfigurationProvider,
1818
@inject(IDebugConfigurationProvider) @named(DebugConfigurationType.launchPyramid) pyramidProvider: IDebugConfigurationProvider,
19-
@inject(IDebugConfigurationProvider) @named(DebugConfigurationType.remoteAttach) remoteAttachProvider: IDebugConfigurationProvider
19+
@inject(IDebugConfigurationProvider) @named(DebugConfigurationType.remoteAttach) remoteAttachProvider: IDebugConfigurationProvider,
20+
@inject(IDebugConfigurationProvider) @named(DebugConfigurationType.pidAttach) pidAttachProvider: IDebugConfigurationProvider
2021
) {
2122
this.providers = new Map<DebugConfigurationType, IDebugConfigurationProvider>();
2223
this.providers.set(DebugConfigurationType.launchDjango, djangoProvider);
@@ -25,6 +26,7 @@ export class DebugConfigurationProviderFactory implements IDebugConfigurationPro
2526
this.providers.set(DebugConfigurationType.launchModule, moduleProvider);
2627
this.providers.set(DebugConfigurationType.launchPyramid, pyramidProvider);
2728
this.providers.set(DebugConfigurationType.remoteAttach, remoteAttachProvider);
29+
this.providers.set(DebugConfigurationType.pidAttach, pidAttachProvider);
2830
}
2931
public create(configurationType: DebugConfigurationType): IDebugConfigurationProvider {
3032
return this.providers.get(configurationType)!;

src/client/debugger/extension/serviceRegistry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { DjangoLaunchDebugConfigurationProvider } from './configuration/provider
1919
import { FileLaunchDebugConfigurationProvider } from './configuration/providers/fileLaunch';
2020
import { FlaskLaunchDebugConfigurationProvider } from './configuration/providers/flaskLaunch';
2121
import { ModuleLaunchDebugConfigurationProvider } from './configuration/providers/moduleLaunch';
22+
import { PidAttachDebugConfigurationProvider } from './configuration/providers/pidAttach';
2223
import { DebugConfigurationProviderFactory } from './configuration/providers/providerFactory';
2324
import { PyramidLaunchDebugConfigurationProvider } from './configuration/providers/pyramidLaunch';
2425
import { RemoteAttachDebugConfigurationProvider } from './configuration/providers/remoteAttach';
@@ -55,6 +56,7 @@ export function registerTypes(serviceManager: IServiceManager) {
5556
serviceManager.addSingleton<IDebugConfigurationProvider>(IDebugConfigurationProvider, RemoteAttachDebugConfigurationProvider, DebugConfigurationType.remoteAttach);
5657
serviceManager.addSingleton<IDebugConfigurationProvider>(IDebugConfigurationProvider, ModuleLaunchDebugConfigurationProvider, DebugConfigurationType.launchModule);
5758
serviceManager.addSingleton<IDebugConfigurationProvider>(IDebugConfigurationProvider, PyramidLaunchDebugConfigurationProvider, DebugConfigurationType.launchPyramid);
59+
serviceManager.addSingleton<IDebugConfigurationProvider>(IDebugConfigurationProvider, PidAttachDebugConfigurationProvider, DebugConfigurationType.pidAttach);
5860
serviceManager.addSingleton<IDebugEnvironmentVariablesService>(IDebugEnvironmentVariablesService, DebugEnvironmentVariablesHelper);
5961
serviceManager.addSingleton<IExtensionSingleActivationService>(IExtensionSingleActivationService, DebugAdapterActivator);
6062
serviceManager.addSingleton<IDebugAdapterDescriptorFactory>(IDebugAdapterDescriptorFactory, DebugAdapterDescriptorFactory);

src/client/debugger/extension/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ export enum DebugConfigurationType {
2828
launchDjango = 'launchDjango',
2929
launchFlask = 'launchFlask',
3030
launchModule = 'launchModule',
31-
launchPyramid = 'launchPyramid'
31+
launchPyramid = 'launchPyramid',
32+
pidAttach = 'pidAttach'
3233
}
3334

3435
export enum PythonPathSource {

src/client/debugger/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export interface IKnownAttachDebugArguments extends ICommonDebugArguments {
5353
// Internal files used to attach to subprocess using python debug adapter
5454
subProcessId?: number;
5555

56-
processId?: number;
56+
processId?: number | string;
5757
}
5858

5959
export interface IKnownLaunchRequestArguments extends ICommonDebugArguments {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
'use strict';
5+
6+
// tslint:disable:no-any no-invalid-template-strings max-func-body-length
7+
8+
import { expect } from 'chai';
9+
import * as path from 'path';
10+
import { Uri } from 'vscode';
11+
import { DebugConfigStrings } from '../../../../../client/common/utils/localize';
12+
import { DebuggerTypeName } from '../../../../../client/debugger/constants';
13+
import { PidAttachDebugConfigurationProvider } from '../../../../../client/debugger/extension/configuration/providers/pidAttach';
14+
15+
suite('Debugging - Configuration Provider File', () => {
16+
let provider: PidAttachDebugConfigurationProvider;
17+
setup(() => {
18+
provider = new PidAttachDebugConfigurationProvider();
19+
});
20+
test('Launch JSON with default process id', async () => {
21+
const folder = { uri: Uri.parse(path.join('one', 'two')), name: '1', index: 0 };
22+
const state = { config: {}, folder };
23+
24+
await provider.buildConfiguration(undefined as any, state);
25+
26+
const config = {
27+
name: DebugConfigStrings.attachPid.snippet.name(),
28+
type: DebuggerTypeName,
29+
request: 'attach',
30+
// tslint:disable-next-line:no-invalid-template-strings
31+
processId: '${command:pickProcess}',
32+
pathMappings: [
33+
{
34+
// tslint:disable-next-line:no-invalid-template-strings
35+
localRoot: '${workspaceFolder}',
36+
remoteRoot: '.'
37+
}
38+
]
39+
};
40+
41+
expect(state.config).to.be.deep.equal(config);
42+
});
43+
});

src/test/debugger/extension/configuration/providers/providerFactory.unit.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ suite('Debugging - Configuration Provider Factory', () => {
2525
mappedProviders.get(DebugConfigurationType.launchModule)!,
2626
mappedProviders.get(DebugConfigurationType.launchFile)!,
2727
mappedProviders.get(DebugConfigurationType.launchPyramid)!,
28-
mappedProviders.get(DebugConfigurationType.remoteAttach)!
28+
mappedProviders.get(DebugConfigurationType.remoteAttach)!,
29+
mappedProviders.get(DebugConfigurationType.pidAttach)!
2930
);
3031
});
3132
getNamesAndValues<DebugConfigurationType>(DebugConfigurationType).forEach(item => {

src/test/debugger/extension/serviceRegistry.unit.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { DjangoLaunchDebugConfigurationProvider } from '../../../client/debugger
1717
import { FileLaunchDebugConfigurationProvider } from '../../../client/debugger/extension/configuration/providers/fileLaunch';
1818
import { FlaskLaunchDebugConfigurationProvider } from '../../../client/debugger/extension/configuration/providers/flaskLaunch';
1919
import { ModuleLaunchDebugConfigurationProvider } from '../../../client/debugger/extension/configuration/providers/moduleLaunch';
20+
import { PidAttachDebugConfigurationProvider } from '../../../client/debugger/extension/configuration/providers/pidAttach';
2021
import { DebugConfigurationProviderFactory } from '../../../client/debugger/extension/configuration/providers/providerFactory';
2122
import { PyramidLaunchDebugConfigurationProvider } from '../../../client/debugger/extension/configuration/providers/pyramidLaunch';
2223
import { RemoteAttachDebugConfigurationProvider } from '../../../client/debugger/extension/configuration/providers/remoteAttach';
@@ -64,5 +65,6 @@ suite('Debugging - Service Registry', () => {
6465
verify(serviceManager.addSingleton<IDebugConfigurationProvider>(IDebugConfigurationProvider, RemoteAttachDebugConfigurationProvider, DebugConfigurationType.remoteAttach)).once();
6566
verify(serviceManager.addSingleton<IDebugConfigurationProvider>(IDebugConfigurationProvider, ModuleLaunchDebugConfigurationProvider, DebugConfigurationType.launchModule)).once();
6667
verify(serviceManager.addSingleton<IDebugConfigurationProvider>(IDebugConfigurationProvider, PyramidLaunchDebugConfigurationProvider, DebugConfigurationType.launchPyramid)).once();
68+
verify(serviceManager.addSingleton<IDebugConfigurationProvider>(IDebugConfigurationProvider, PidAttachDebugConfigurationProvider, DebugConfigurationType.pidAttach)).once();
6769
});
6870
});

0 commit comments

Comments
 (0)