Skip to content

Configless debug #557

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 13 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from 11 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
69 changes: 32 additions & 37 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,35 @@
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
{
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": [
"${workspaceFolder}/dist/**/*.js",
"!${workspaceFolder}/**/node_modules**/*"
],
"preLaunchTask": "npm: watch",
"presentation": {
"hidden": false,
"group": "",
"order": 2
}
},
{
"name": "Unit Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"./out/test/**/*.unit.test.js",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/unittest/index"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js",
],
"preLaunchTask": "tasks: watch-tests"
},
]
}
"version": "0.2.0",
"configurations": [
{
"name": "Run Extension",
"type": "extensionHost",
"request": "launch",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/dist/**/*.js", "!${workspaceFolder}/**/node_modules**/*"],
"preLaunchTask": "npm: watch",
"presentation": {
"hidden": false,
"group": "",
"order": 2
}
},
{
"name": "Unit Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"./out/test/**/*.unit.test.js",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/unittest/index",
//"--grep", "<suite name>",
"--timeout=300000"
],
"outFiles": ["${workspaceFolder}/out/**/*.js"],
"preLaunchTask": "tasks: watch-tests"
}
]
}
4 changes: 4 additions & 0 deletions bundled/scripts/noConfigScripts/debugpy
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#! /bin/bash
# Bash script
python $BUNDLED_DEBUGPY_PATH --listen 0 --wait-for-client $@
echo "Executed: python $BUNDLED_DEBUGPY_PATH --listen 0 --wait-for-client $@"
3 changes: 3 additions & 0 deletions bundled/scripts/noConfigScripts/debugpy.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@echo off
:: Bat script
python %BUNDLED_DEBUGPY_PATH% --listen 0 --wait-for-client %*
2 changes: 2 additions & 0 deletions bundled/scripts/noConfigScripts/debugpy.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Fish script
python $BUNDLED_DEBUGPY_PATH --listen 0 --wait-for-client $argv
2 changes: 2 additions & 0 deletions bundled/scripts/noConfigScripts/debugpy.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# PowerShell script
python $env:BUNDLED_DEBUGPY_PATH --listen 0 --wait-for-client $args
5 changes: 5 additions & 0 deletions noConfigDebugAdapterEndpoints/info.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the MIT License.

This folder is necessary as it is the location where the debug adapter
will create the debuggerAdapterEndpoint.txt to communicate the endpoint.
3 changes: 3 additions & 0 deletions src/extension/extensionInit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import { IExtensionApi } from './apiTypes';
import { registerHexDebugVisualizationTreeProvider } from './debugger/visualizers/inlineHexDecoder';
import { PythonInlineValueProvider } from './debugger/inlineValue/pythonInlineValueProvider';
import { traceLog } from './common/log/logging';
import { registerNoConfigDebug } from './noConfigDebugInit';

export async function registerDebugger(context: IExtensionContext): Promise<IExtensionApi> {
const childProcessAttachService = new ChildProcessAttachService();
Expand Down Expand Up @@ -247,5 +248,7 @@ export async function registerDebugger(context: IExtensionContext): Promise<IExt
window.activeTextEditor?.document.languageId === 'python',
);

registerNoConfigDebug(context);

return buildApi();
}
92 changes: 92 additions & 0 deletions src/extension/noConfigDebugInit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import * as fs from 'fs';
import * as path from 'path';
import { IExtensionContext } from './common/types';
import { DebugSessionOptions, RelativePattern } from 'vscode';
import { createFileSystemWatcher, debugStartDebugging } from './utils';
import { traceError, traceVerbose } from './common/log/logging';

/**
* Registers the configuration-less debugging setup for the extension.
*
* This function sets up environment variables and a file system watcher to
* facilitate debugging without requiring a pre-configured launch.json file.
*
* @param context - The extension context which provides access to the environment variable collection and subscriptions.
*
* Environment Variables:
* - `DEBUGPY_ADAPTER_ENDPOINTS`: Path to the file containing the debugger adapter endpoint.
* - `BUNDLED_DEBUGPY_PATH`: Path to the bundled debugpy library.
* - `PATH`: Appends the path to the noConfigScripts directory.
*/
export async function registerNoConfigDebug(context: IExtensionContext): Promise<void> {
const collection = context.environmentVariableCollection;

// Add env vars for DEBUGPY_ADAPTER_ENDPOINTS, BUNDLED_DEBUGPY_PATH, and PATH
const debugAdapterEndpointDir = path.join(context.extensionPath, 'noConfigDebugAdapterEndpoints');
const debuggerAdapterEndpointPath = path.join(debugAdapterEndpointDir, 'debuggerAdapterEndpoint.txt');
collection.replace('DEBUGPY_ADAPTER_ENDPOINTS', debuggerAdapterEndpointPath);

const noConfigScriptsDir = path.join(context.extensionPath, 'bundled', 'scripts', 'noConfigScripts');
const pathSeparator = process.platform === 'win32' ? ';' : ':';
collection.append('PATH', `${pathSeparator}${noConfigScriptsDir}`);

const bundledDebugPath = path.join(context.extensionPath, 'bundled', 'libs', 'debugpy');
collection.replace('BUNDLED_DEBUGPY_PATH', bundledDebugPath);

// create file system watcher for the debuggerAdapterEndpointFolder for when the communication port is written
const fileSystemWatcher = createFileSystemWatcher(new RelativePattern(debugAdapterEndpointDir, '**/*'));
const fileCreationEvent = fileSystemWatcher.onDidCreate(async (uri) => {
const filePath = uri.fsPath;
fs.readFile(filePath, (err, data) => {
const dataParse = data.toString();
if (err) {
traceError(`Error reading debuggerAdapterEndpoint.txt file: ${err}`);
return;
}
try {
// parse the client port
const jsonData = JSON.parse(dataParse);
const clientPort = jsonData.client?.port;
traceVerbose(`Parsed client port: ${clientPort}`);

const options: DebugSessionOptions = {
noDebug: false,
};

// start debug session with the client port
debugStartDebugging(
undefined,
{
type: 'python',
request: 'attach',
name: 'Attach to Python',
connect: {
port: clientPort,
host: 'localhost',
},
},
options,
).then(
(started) => {
if (started) {
traceVerbose('Successfully started debug session');
} else {
traceError('Error starting debug session, session not started.');
}
},
(error) => {
traceError(`Error starting debug session: ${error}`);
},
);
} catch (parseErr) {
traceError(`Error parsing JSON: ${parseErr}`);
}
});
JSON.parse;
});
context.subscriptions.push(fileCreationEvent);
context.subscriptions.push(fileSystemWatcher);
}
21 changes: 21 additions & 0 deletions src/extension/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {
workspace,
debug,
WorkspaceFolder,
DebugConfiguration,
DebugSession,
DebugSessionOptions,
FileSystemWatcher,
} from 'vscode';

export function createFileSystemWatcher(args: any): FileSystemWatcher {
return workspace.createFileSystemWatcher(args);
}

export async function debugStartDebugging(
folder: WorkspaceFolder | undefined,
nameOrConfiguration: string | DebugConfiguration,
parentSessionOrOptions?: DebugSession | DebugSessionOptions,
): Promise<boolean> {
return debug.startDebugging(folder, nameOrConfiguration, parentSessionOrOptions);
}
Loading
Loading