@@ -8,7 +8,7 @@ import * as childProcess from 'child_process'
88import * as path from 'path'
99import * as util from 'util'
1010import * as fs from 'fs'
11- import { Terminal } from './terminal'
11+ import { Terminal , IProgram , ProgramPidWrapper } from './terminal'
1212import { convertClientPathToDebugger , convertDebuggerPathToClient , isPositiveMatchInGlobs } from './paths'
1313import minimatch from 'minimatch'
1414import { BreakpointManager , BreakpointAdapter } from './breakpoints'
@@ -115,19 +115,24 @@ export interface LaunchRequestArguments extends VSCodeDebugProtocol.LaunchReques
115115 env ?: { [ key : string ] : string }
116116 /** Absolute path to a file containing environment variable definitions. */
117117 envFile ?: string
118- /** If true launch the target in an external console. */
118+ /** DEPRECATED: If true launch the target in an external console. */
119119 externalConsole ?: boolean
120+ /** Where to launch the debug target: internal console, integrated terminal, or external terminal. */
121+ console ?: 'internalConsole' | 'integratedTerminal' | 'externalTerminal'
120122}
121123
122124class PhpDebugSession extends vscode . DebugSession {
125+ /** The arguments that were given to initializeRequest */
126+ private _initializeArgs : VSCodeDebugProtocol . InitializeRequestArguments
127+
123128 /** The arguments that were given to launchRequest */
124129 private _args : LaunchRequestArguments
125130
126131 /** The TCP server that listens for Xdebug connections */
127132 private _server : net . Server
128133
129134 /** The child process of the launched PHP script, if launched by the debug adapter */
130- private _phpProcess ?: childProcess . ChildProcess
135+ private _phpProcess ?: IProgram
131136
132137 /**
133138 * A map from VS Code thread IDs to Xdebug Connections.
@@ -211,6 +216,7 @@ class PhpDebugSession extends vscode.DebugSession {
211216 response : VSCodeDebugProtocol . InitializeResponse ,
212217 args : VSCodeDebugProtocol . InitializeRequestArguments
213218 ) : void {
219+ this . _initializeArgs = args
214220 response . body = {
215221 supportsConfigurationDoneRequest : true ,
216222 supportsEvaluateForHovers : true ,
@@ -287,29 +293,48 @@ class PhpDebugSession extends vscode.DebugSession {
287293 const program = args . program ? [ args . program ] : [ ]
288294 const cwd = args . cwd || process . cwd ( )
289295 const env = Object . fromEntries (
290- Object . entries ( { ... process . env , ... getConfiguredEnvironment ( args ) } ) . map ( v => [
296+ Object . entries ( getConfiguredEnvironment ( args ) ) . map ( v => [
291297 v [ 0 ] ,
292298 v [ 1 ] ?. replace ( '${port}' , port . toString ( ) ) ,
293299 ] )
294300 )
295301 // launch in CLI mode
296- if ( args . externalConsole ) {
297- const script = await Terminal . launchInTerminal (
298- cwd ,
299- [ runtimeExecutable , ...runtimeArgs , ...program , ...programArgs ] ,
300- env
301- )
302+ if ( args . externalConsole || args . console == 'integratedTerminal' || args . console == 'externalTerminal' ) {
303+ let script : IProgram | undefined
304+ if ( this . _initializeArgs . supportsRunInTerminalRequest ) {
305+ const kind : 'integrated' | 'external' =
306+ args . externalConsole || args . console === 'externalTerminal' ? 'external' : 'integrated'
307+ const ritr = await new Promise < VSCodeDebugProtocol . RunInTerminalResponse > ( ( resolve , reject ) => {
308+ this . runInTerminalRequest (
309+ { args : [ runtimeExecutable , ...runtimeArgs , ...program , ...programArgs ] , env, cwd, kind } ,
310+ 5000 ,
311+ resolve
312+ )
313+ } )
314+ script =
315+ ritr . success && ritr . body . shellProcessId
316+ ? new ProgramPidWrapper ( ritr . body . shellProcessId )
317+ : undefined
318+ } else {
319+ script = await Terminal . launchInTerminal (
320+ cwd ,
321+ [ runtimeExecutable , ...runtimeArgs , ...program , ...programArgs ] ,
322+ env
323+ )
324+ }
325+
302326 if ( script ) {
303327 // we only do this for CLI mode. In normal listen mode, only a thread exited event is send.
304328 script . on ( 'exit' , ( code : number | null ) => {
305329 this . sendEvent ( new vscode . ExitedEvent ( code ?? 0 ) )
306330 this . sendEvent ( new vscode . TerminatedEvent ( ) )
307331 } )
308332 }
333+ // this._phpProcess = script
309334 } else {
310335 const script = childProcess . spawn ( runtimeExecutable , [ ...runtimeArgs , ...program , ...programArgs ] , {
311336 cwd,
312- env,
337+ env : { ... process . env , ... env } ,
313338 } )
314339 // redirect output to debug console
315340 script . stdout . on ( 'data' , ( data : Buffer ) => {
@@ -1423,8 +1448,10 @@ class PhpDebugSession extends vscode.DebugSession {
14231448 }
14241449 }
14251450 // If launched as CLI, kill process
1426- if ( this . _phpProcess ) {
1427- this . _phpProcess . kill ( )
1451+ if ( this . _phpProcess ?. pid ) {
1452+ Terminal . killTree ( this . _phpProcess . pid ) . catch ( err =>
1453+ this . sendEvent ( new vscode . OutputEvent ( `killTree: ${ err as string } \n` ) )
1454+ )
14281455 }
14291456 } catch ( error ) {
14301457 this . sendErrorResponse ( response , error as Error )
0 commit comments