Skip to content

Commit 9e2a1a5

Browse files
committed
feat: Launch with random port and command line configuration (#588)
* Setting port=0 will use a random port and pass that to either env or runtimeArgs. * Initial configuration and configuration snippets with random port. Command line debug triggers. * Port description. * Xdebug 2 configuration snippets
1 parent e741072 commit 9e2a1a5

File tree

5 files changed

+77
-15
lines changed

5 files changed

+77
-15
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ More general information on debugging with VS Code can be found on https://code.
6767

6868
- `request`: Always `"launch"`
6969
- `hostname`: The address to bind to when listening for Xdebug (default: all IPv6 connections if available, else all IPv4 connections)
70-
- `port`: The port on which to listen for Xdebug (default: `9003`)
70+
- `port`: The port on which to listen for Xdebug (default: `9003`). If port is set to `0` a random port is chosen by the system and a placeholder `${port}` is replaced with the chosen port in `env` and `runtimeArgs`.
7171
- `stopOnEntry`: Whether to break at the beginning of the script (default: `false`)
7272
- `pathMappings`: A list of server paths mapping to the local source paths on your machine, see "Remote Host Debugging" below
7373
- `log`: Whether to log all communication between VS Code and the adapter to the debug console. See _Troubleshooting_ further down.

package.json

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,14 @@
279279
"request": "launch",
280280
"program": "${file}",
281281
"cwd": "${fileDirname}",
282-
"port": 9003
282+
"port": 0,
283+
"runtimeArgs": [
284+
"-dxdebug.start_with_request=yes"
285+
],
286+
"env": {
287+
"XDEBUG_MODE": "debug,develop",
288+
"XDEBUG_CONFIG": "client_port=${port}"
289+
}
283290
},
284291
{
285292
"name": "Launch Built-in web server",
@@ -312,6 +319,16 @@
312319
"port": 9003
313320
}
314321
},
322+
{
323+
"label": "PHP: Listen for Xdebug 2 (Legacy)",
324+
"description": "Listen for incoming XDebug connections on legacy port",
325+
"body": {
326+
"name": "Listen for Xdebug 2 (Legacy)",
327+
"type": "php",
328+
"request": "launch",
329+
"port": 9000
330+
}
331+
},
315332
{
316333
"label": "PHP: Launch currently open script",
317334
"description": "Debug the currently open PHP script in CLI mode",
@@ -321,7 +338,33 @@
321338
"request": "launch",
322339
"program": "^\"${1:\\${file\\}}\"",
323340
"cwd": "^\"${2:\\${fileDirname\\}}\"",
324-
"port": 9003
341+
"port": 0,
342+
"runtimeArgs": [
343+
"-dxdebug.start_with_request=yes"
344+
],
345+
"env": {
346+
"XDEBUG_MODE": "debug,develop",
347+
"XDEBUG_CONFIG": "^\"client_port=\\${port\\}\""
348+
}
349+
}
350+
},
351+
{
352+
"label": "PHP: Launch currently open script with Xdebug 2 (Legacy)",
353+
"description": "Debug the currently open PHP script in CLI mode",
354+
"body": {
355+
"name": "Launch currently open script with Xdebug 2 (Legacy)",
356+
"type": "php",
357+
"request": "launch",
358+
"program": "^\"${1:\\${file\\}}\"",
359+
"cwd": "^\"${2:\\${fileDirname\\}}\"",
360+
"port": 0,
361+
"runtimeArgs": [
362+
"-dxdebug.remote_enable=yes",
363+
"-dxdebug.remote_autostart=yes"
364+
],
365+
"env": {
366+
"XDEBUG_CONFIG": "^\"remote_port=\\${port\\}\""
367+
}
325368
}
326369
},
327370
{

src/phpDebug.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,19 +210,21 @@ class PhpDebugSession extends vscode.DebugSession {
210210
}
211211
this._args = args
212212
/** launches the script as CLI */
213-
const launchScript = async () => {
213+
const launchScript = async (port: number) => {
214214
// check if program exists
215215
if (args.program) {
216216
await new Promise<void>((resolve, reject) =>
217217
fs.access(args.program!, fs.constants.F_OK, err => (err ? reject(err) : resolve()))
218218
)
219219
}
220-
const runtimeArgs = args.runtimeArgs || []
220+
const runtimeArgs = (args.runtimeArgs || []).map(v => v.replace('${port}', port.toString()))
221221
const runtimeExecutable = args.runtimeExecutable || 'php'
222222
const programArgs = args.args || []
223223
const program = args.program ? [args.program] : []
224224
const cwd = args.cwd || process.cwd()
225-
const env = args.env || process.env
225+
const env = Object.fromEntries(
226+
Object.entries(args.env || process.env).map(v => [v[0], v[1]?.replace('${port}', port.toString())])
227+
)
226228
// launch in CLI mode
227229
if (args.externalConsole) {
228230
const script = await Terminal.launchInTerminal(
@@ -260,7 +262,7 @@ class PhpDebugSession extends vscode.DebugSession {
260262
}
261263
/** sets up a TCP server to listen for Xdebug connections */
262264
const createServer = () =>
263-
new Promise<void>((resolve, reject) => {
265+
new Promise<number>((resolve, reject) => {
264266
const server = (this._server = net.createServer())
265267
server.on('connection', async (socket: net.Socket) => {
266268
try {
@@ -342,16 +344,22 @@ class PhpDebugSession extends vscode.DebugSession {
342344
})
343345
server.on('error', (error: Error) => {
344346
this.sendEvent(new vscode.OutputEvent(util.inspect(error) + '\n'))
345-
this.sendErrorResponse(response, <Error>error)
347+
reject(error)
348+
})
349+
server.on('listening', () => {
350+
const port = (server.address() as net.AddressInfo).port
351+
resolve(port)
346352
})
347-
server.listen(args.port || 9003, args.hostname, () => resolve())
353+
const listenPort = args.port === undefined ? 9003 : args.port
354+
server.listen(listenPort, args.hostname)
348355
})
349356
try {
357+
let port = 0
350358
if (!args.noDebug) {
351-
await createServer()
359+
port = await createServer()
352360
}
353361
if (args.program || args.runtimeArgs) {
354-
await launchScript()
362+
await launchScript(port)
355363
}
356364
} catch (error) {
357365
this.sendErrorResponse(response, <Error>error)

testproject/.vscode/launch.json

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,28 @@
1616
"request": "launch",
1717
"program": "${file}",
1818
"cwd": "${fileDirname}",
19-
"port": 9003
19+
"port": 0,
20+
"runtimeArgs": ["-dxdebug.start_with_request=yes"],
21+
"env": {
22+
"XDEBUG_MODE": "debug,develop",
23+
"XDEBUG_CONFIG": "client_port=${port}"
24+
}
2025
},
2126
{
2227
//"debugServer": 4711, // Uncomment for debugging the adapter
2328
"name": "Launch Built-in web server",
2429
"type": "php",
2530
"request": "launch",
26-
"runtimeArgs": ["-dxdebug.mode=debug", "-dxdebug.start_with_request=yes", "-S", "localhost:0"],
31+
"runtimeArgs": [
32+
"-dxdebug.mode=debug",
33+
"-dxdebug.start_with_request=yes",
34+
"-dxdebug.client_port=${port}",
35+
"-S",
36+
"localhost:0"
37+
],
2738
"program": "",
2839
"cwd": "${workspaceRoot}",
29-
"port": 9003,
40+
"port": 0,
3041
"serverReadyAction": {
3142
"pattern": "Development Server \\(http://localhost:([0-9]+)\\) started",
3243
"uriFormat": "http://localhost:%s",

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"include": ["src/**/*"],
33
"compilerOptions": {
4-
"target": "es6",
4+
"target": "es2019",
55
"module": "commonjs",
66
"rootDir": "src",
77
"outDir": "out",

0 commit comments

Comments
 (0)