From 5caefd62429029a2aff44a5da433ff006b207fd2 Mon Sep 17 00:00:00 2001 From: Vladimir Sheremet Date: Wed, 22 Jan 2025 18:15:30 +0100 Subject: [PATCH] fix: run debugger in terminal shell when shellType is `terminal` Fixes #571 --- debug-shims.d.ts | 38 ++++++++++++++++++++++++++++++++++++++ src/api/terminal.ts | 27 ++++++++++++++++++--------- src/debug/api.ts | 14 ++++++++++---- src/extension.ts | 37 +++++++++++++++++++++++++++++++++++++ tsconfig.json | 2 +- 5 files changed, 104 insertions(+), 14 deletions(-) create mode 100644 debug-shims.d.ts diff --git a/debug-shims.d.ts b/debug-shims.d.ts new file mode 100644 index 0000000..13be086 --- /dev/null +++ b/debug-shims.d.ts @@ -0,0 +1,38 @@ +/* eslint-disable ts/method-signature-style */ +// https://github.com/microsoft/vscode-js-debug/blob/main/src/typings/vscode-js-debug.d.ts + +declare module '@vscode/js-debug' { + import type * as vscode from 'vscode' + + /** @see {IExports.registerDebugTerminalOptionsProvider} */ + export interface IDebugTerminalOptionsProvider { + /** + * Called when the user creates a JavaScript Debug Terminal. It's called + * with the options js-debug wants to use to create the terminal. It should + * modify and return the options to use in the terminal. + * + * In order to avoid conflicting with existing logic, participants should + * try to modify options in a additive way. For example prefer appending + * to rather than reading and overwriting `options.env.PATH`. + */ + provideTerminalOptions(options: vscode.TerminalOptions): vscode.ProviderResult + } + + /** + * Defines the exports of the `js-debug` extension. Once you have this typings + * file, these can be acquired in your extension using the following code: + * + * ``` + * const jsDebugExt = vscode.extensions.getExtension('ms-vscode.js-debug-nightly') + * || vscode.extensions.getExtension('ms-vscode.js-debug'); + * await jsDebugExt.activate() + * const jsDebug: import('@vscode/js-debug').IExports = jsDebug.exports; + * ``` + */ + export interface IExports { + /** + * Registers a participant used when the user creates a JavaScript Debug Terminal. + */ + registerDebugTerminalOptionsProvider(provider: IDebugTerminalOptionsProvider): vscode.Disposable + } +} diff --git a/src/api/terminal.ts b/src/api/terminal.ts index bd83ce6..7b75346 100644 --- a/src/api/terminal.ts +++ b/src/api/terminal.ts @@ -56,19 +56,24 @@ export async function createVitestTerminalProcess(pkg: VitestPackage): Promise + constructor( public readonly id: number, private wsProcess: VitestWebSocketProcess, private readonly terminal: vscode.Terminal, ) { - const disposer = vscode.window.onDidCloseTerminal(async (e) => { - if (e === terminal) { - const exitCode = e.exitStatus?.code - // TODO: have a single emitter, don't reuse ws one - // this event is required for api.dispose() and onUnexpectedExit - wsProcess.ws.emit('exit', exitCode) - disposer.dispose() - } + this.stopped = new Promise((resolve) => { + const disposer = vscode.window.onDidCloseTerminal(async (e) => { + if (e === terminal) { + const exitCode = e.exitStatus?.code + // TODO: have a single emitter, don't reuse ws one + // this event is required for api.dispose() and onUnexpectedExit + wsProcess.ws.emit('exit', exitCode) + disposer.dispose() + resolve() + } + }) }) } @@ -82,7 +87,11 @@ export class VitestTerminalProcess implements VitestProcess { close() { this.wsProcess.close() - this.terminal.dispose() + // send ctrl+c to sigint any running processs (vscode/#108289) + this.terminal.sendText('\x03') + // and then destroy it on the next event loop tick + setTimeout(() => this.terminal.dispose(), 1) + return this.stopped } on(event: string, listener: (...args: any[]) => void) { diff --git a/src/debug/api.ts b/src/debug/api.ts index 675a684..3112cb6 100644 --- a/src/debug/api.ts +++ b/src/debug/api.ts @@ -37,15 +37,21 @@ export async function debugTests( const debugConfig = { __name: 'Vitest', - type: 'pwa-node', + type: config.shellType === 'terminal' ? 'node-terminal' : 'pwa-node', request: 'launch', name: 'Debug Tests', autoAttachChildProcesses: true, skipFiles: config.debugExclude, smartStep: true, - runtimeArgs, - runtimeExecutable, - program: workerPath, + ...(config.shellType === 'terminal' + ? { + command: `${runtimeExecutable} ${workerPath}`, + } + : { + program: workerPath, + runtimeArgs, + runtimeExecutable, + }), cwd: pkg.cwd, env: { ...process.env, diff --git a/src/extension.ts b/src/extension.ts index 555beb4..2a0f7e4 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -39,6 +39,9 @@ class VitestExtension { private disposables: vscode.Disposable[] = [] + /** @internal */ + _debugDisposable: vscode.Disposable | undefined + constructor() { log.info(`[v${version}] Vitest extension is activated because Vitest is installed or there is a Vite/Vitest config file in the workspace.`) @@ -206,6 +209,8 @@ class VitestExtension { } debugProfile.tag = api.tag debugProfile.runHandler = async (request, token) => { + await this.registerDebugOptions() + await debugTests( this.testController, this.testTree, @@ -400,6 +405,38 @@ class VitestExtension { } } + async registerDebugOptions() { + if (this._debugDisposable) { + return + } + const config = getConfig() + if (config.shellType !== 'terminal') { + return + } + try { + const jsDebugExt = vscode.extensions.getExtension('ms-vscode.js-debug-nightly') || vscode.extensions.getExtension('ms-vscode.js-debug') + await jsDebugExt?.activate() + const jsDebug: import('@vscode/js-debug').IExports = jsDebugExt?.exports + + if (jsDebug) { + this._debugDisposable = jsDebug.registerDebugTerminalOptionsProvider({ + provideTerminalOptions(options) { + options.shellArgs = getConfig().terminalShellArgs + options.shellPath = getConfig().terminalShellPath + return options + }, + }) + this.disposables.push(this._debugDisposable) + } + else { + log.error('Failed to connect to the debug extension. Debugger will open a terminal window.') + } + } + catch (err) { + log.error('Cannot create debug options provider.', err) + } + } + async dispose() { this.api?.dispose() this.testTree.dispose() diff --git a/tsconfig.json b/tsconfig.json index 0bed40d..4b959e8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,4 @@ { "extends": ["./tsconfig.base.json"], - "include": ["src"] + "include": ["src", "./debug-shims.d.ts"] } -- 2.51.2