Skip to content

Add port provider #85

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"description": "Python Debugger extension using `debugpy`.",
"version": "2023.3.0-dev",
"publisher": "ms-python",
"enabledApiProposals": [
"portsAttributes"
],
"license": "MIT",
"homepage": "https://github.com/Microsoft/vscode-python-debugger",
"repository": {
Expand Down
14 changes: 14 additions & 0 deletions src/extension/debugger/debugPort/portAttributesProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/

import { CancellationToken, PortAttributes, PortAttributesProvider, ProviderResult } from 'vscode';

export class DebugPortAttributesProvider implements PortAttributesProvider {
public providePortAttributes(
_attributes: { port: number; pid?: number; commandLine?: string },
_token: CancellationToken,
): ProviderResult<PortAttributes> {
return undefined;
}
}
11 changes: 10 additions & 1 deletion src/extension/extensionInit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

'use strict';

import { debug, DebugConfigurationProviderTriggerKind, languages, Uri, window } from 'vscode';
import { debug, DebugConfigurationProviderTriggerKind, languages, Uri, window, workspace } from 'vscode';
import { executeCommand, getConfiguration, registerCommand, startDebugging } from './common/vscodeapi';
import { DebuggerTypeName } from './constants';
import { DynamicPythonDebugConfigurationService } from './debugger/configuration/dynamicdebugConfigurationService';
Expand Down Expand Up @@ -31,6 +31,7 @@ import { JsonLanguages, LaunchJsonCompletionProvider } from './debugger/configur
import { LaunchJsonUpdaterServiceHelper } from './debugger/configuration/launch.json/updaterServiceHelper';
import { ignoreErrors } from './common/promiseUtils';
import { pickArgsInput } from './common/utils/localize';
import { DebugPortAttributesProvider } from './debugger/debugPort/portAttributesProvider';

export async function registerDebugger(context: IExtensionContext): Promise<void> {
const childProcessAttachService = new ChildProcessAttachService();
Expand Down Expand Up @@ -125,4 +126,12 @@ export async function registerDebugger(context: IExtensionContext): Promise<void
launchJsonCompletionProvider,
),
);

const debugPortAttributesProvider = new DebugPortAttributesProvider();
context.subscriptions.push(
workspace.registerPortAttributesProvider(
{ commandPattern: /extensions.ms-python.debugpy.*debugpy.(launcher|adapter)/ },
debugPortAttributesProvider,
),
);
}
100 changes: 100 additions & 0 deletions vscode.proposed.portsAttributes.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

declare module 'vscode' {

// https://github.com/microsoft/vscode/issues/115616 @alexr00

/**
* The action that should be taken when a port is discovered through automatic port forwarding discovery.
*/
export enum PortAutoForwardAction {
/**
* Notify the user that the port is being forwarded. This is the default action.
*/
Notify = 1,
/**
* Once the port is forwarded, open the user's web browser to the forwarded port.
*/
OpenBrowser = 2,
/**
* Once the port is forwarded, open the preview browser to the forwarded port.
*/
OpenPreview = 3,
/**
* Forward the port silently.
*/
Silent = 4,
/**
* Do not forward the port.
*/
Ignore = 5
}

/**
* The attributes that a forwarded port can have.
*/
export class PortAttributes {
/**
* The action to be taken when this port is detected for auto forwarding.
*/
autoForwardAction: PortAutoForwardAction;

/**
* Creates a new PortAttributes object
* @param port the port number
* @param autoForwardAction the action to take when this port is detected
*/
constructor(autoForwardAction: PortAutoForwardAction);
}

/**
* A provider of port attributes. Port attributes are used to determine what action should be taken when a port is discovered.
*/
export interface PortAttributesProvider {
/**
* Provides attributes for the given port. For ports that your extension doesn't know about, simply
* return undefined. For example, if `providePortAttributes` is called with ports 3000 but your
* extension doesn't know anything about 3000 you should return undefined.
* @param port The port number of the port that attributes are being requested for.
* @param pid The pid of the process that is listening on the port. If the pid is unknown, undefined will be passed.
* @param commandLine The command line of the process that is listening on the port. If the command line is unknown, undefined will be passed.
* @param token A cancellation token that indicates the result is no longer needed.
*/
providePortAttributes(attributes: { port: number; pid?: number; commandLine?: string }, token: CancellationToken): ProviderResult<PortAttributes>;
}

/**
* A selector that will be used to filter which {@link PortAttributesProvider} should be called for each port.
*/
export interface PortAttributesSelector {
/**
* Specifying a port range will cause your provider to only be called for ports within the range.
* The start is inclusive and the end is exclusive.
*/
portRange?: [number, number] | number;

/**
* Specifying a command pattern will cause your provider to only be called for processes whose command line matches the pattern.
*/
commandPattern?: RegExp;
}

export namespace workspace {
/**
* If your extension listens on ports, consider registering a PortAttributesProvider to provide information
* about the ports. For example, a debug extension may know about debug ports in it's debuggee. By providing
* this information with a PortAttributesProvider the extension can tell the editor that these ports should be
* ignored, since they don't need to be user facing.
*
* The results of the PortAttributesProvider are merged with the user setting `remote.portsAttributes`. If the values conflict, the user setting takes precedence.
*
* @param portSelector It is best practice to specify a port selector to avoid unnecessary calls to your provider.
* If you don't specify a port selector your provider will be called for every port, which will result in slower port forwarding for the user.
* @param provider The {@link PortAttributesProvider PortAttributesProvider}.
*/
export function registerPortAttributesProvider(portSelector: PortAttributesSelector, provider: PortAttributesProvider): Disposable;
}
}