Skip to content

Commit b94ace2

Browse files
authored
Merge branch 'main' into run-in-terminal-new
2 parents 4005663 + 7aca123 commit b94ace2

File tree

8 files changed

+115
-5
lines changed

8 files changed

+115
-5
lines changed

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,17 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
66

7-
## [1.35.0]
7+
## [1.36.0]
88

99
- Support for console option with internalConsole, integratedTerminal and externalTerminal options.
1010

11+
## [1.35.0]
12+
13+
- Support for DBGp stream command
14+
- Avoid conflict with full screen F11 shortcut
15+
- Improve existing unix socket handling
16+
- Improve close socket handling
17+
1118
## [1.34.0]
1219

1320
- Partial support for virtual workspaces

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ More general information on debugging with VS Code can be found on https://code.
8989
- `max_depth`: maximum depth that the debugger engine may return when sending arrays, hashes or object structures to the IDE (there should be no need to change this as depth is retrieved incrementally, large value can cause IDE to hang).
9090
- `show_hidden`: This feature can get set by the IDE if it wants to have more detailed internal information on properties (eg. private members of classes, etc.) Zero means that hidden members are not shown to the IDE.
9191
- `xdebugCloudToken`: Instead of listening locally, open a connection and register with Xdebug Cloud and accept debugging sessions on that connection.
92+
- `stream`: Allows to influence DBGp streams. Xdebug only supports `stdout` see [DBGp stdout](https://xdebug.org/docs/dbgp#stdout-stderr)
93+
- `stdout`: Redirect stdout stream: 0 (disable), 1 (copy), 2 (redirect)
9294

9395
Options specific to CLI debugging:
9496

package.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,17 @@
371371
"xdebugCloudToken": {
372372
"type": "string",
373373
"description": "Xdebug Could token"
374+
},
375+
"stream": {
376+
"type": "object",
377+
"description": "Xdebug stream settings",
378+
"properties": {
379+
"stdout": {
380+
"type": "number",
381+
"description": "Redirect stdout stream: 0 (disable), 1 (copy), 2 (redirect)",
382+
"default": 0
383+
}
384+
}
374385
}
375386
}
376387
}
@@ -586,7 +597,7 @@
586597
{
587598
"command": "extension.php-debug.startWithStopOnEntry",
588599
"key": "F11",
589-
"when": "!inDebugMode && debugConfigurationType == 'php'"
600+
"when": "!inDebugMode && activeViewlet == 'workbench.view.debug' && debugConfigurationType == 'php'"
590601
}
591602
]
592603
}

src/cloud.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,12 @@ class InnerCloudTransport extends EventEmitter implements Transport {
225225
}
226226
return this
227227
}
228+
229+
destroy(error?: Error): this {
230+
if (this._open) {
231+
this._open = false
232+
this.emit('close')
233+
}
234+
return this
235+
}
228236
}

src/dbgp.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface Transport {
1818
on(event: 'close', listener: () => void): this
1919
write(buffer: Uint8Array | string, cb?: (err?: Error) => void): boolean
2020
end(callback?: () => void): this
21+
destroy(error?: Error): this
2122
}
2223

2324
export declare interface DbgpConnection {
@@ -145,7 +146,7 @@ export class DbgpConnection extends EventEmitter {
145146

146147
/** closes the underlying socket */
147148
public close(): Promise<void> {
148-
this._socket.end()
149+
this._socket.destroy()
149150
return this._closePromise
150151
}
151152
}

src/phpDebug.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ export interface LaunchRequestArguments extends VSCodeDebugProtocol.LaunchReques
9898
maxConnections?: number
9999
/** Xdebug cloud token */
100100
xdebugCloudToken?: string
101+
/** Xdebug stream settings */
102+
stream?: {
103+
stdout?: 0 | 1 | 2
104+
}
101105

102106
// CLI options
103107

@@ -439,6 +443,11 @@ class PhpDebugSession extends vscode.DebugSession {
439443
throw new Error('Cannot have port and socketPath set at the same time')
440444
}
441445
if (args.hostname?.toLowerCase()?.startsWith('unix://') === true) {
446+
if (fs.existsSync(args.hostname.substring(7))) {
447+
throw new Error(
448+
`File ${args.hostname.substring(7)} exists and cannot be used for Unix Domain socket`
449+
)
450+
}
442451
server.listen(args.hostname.substring(7))
443452
} else if (args.hostname?.startsWith('\\\\') === true) {
444453
server.listen(args.hostname)
@@ -601,6 +610,15 @@ class PhpDebugSession extends vscode.DebugSession {
601610
throw new Error(`Error applying xdebugSettings: ${String(error instanceof Error ? error.message : error)}`)
602611
}
603612

613+
const stdout =
614+
this._args.stream?.stdout === undefined ? (this._args.externalConsole ? 1 : 0) : this._args.stream.stdout
615+
if (stdout) {
616+
await connection.sendStdout(stdout)
617+
connection.on('stream', (stream: xdebug.Stream) =>
618+
this.sendEvent(new vscode.OutputEvent(stream.value, 'stdout'))
619+
)
620+
}
621+
604622
this.sendEvent(new vscode.ThreadEvent('started', connection.id))
605623

606624
// wait for all breakpoints

src/test/adapter.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { DebugClient } from '@vscode/debugadapter-testsupport'
55
import { DebugProtocol } from '@vscode/debugprotocol'
66
import * as semver from 'semver'
77
import * as net from 'net'
8-
import { describe, it, beforeEach, afterEach } from 'mocha'
8+
import * as childProcess from 'child_process'
9+
import { describe, it, beforeEach, afterEach, after } from 'mocha'
910
chai.use(chaiAsPromised)
1011
const assert = chai.assert
1112

@@ -92,6 +93,16 @@ describe('PHP Debug Adapter', () => {
9293
client.waitForEvent('terminated'),
9394
])
9495
})
96+
;(process.platform === 'win32' ? it.skip : it)('should error on existing unix pipe', async () => {
97+
await assert.isRejected(
98+
client.launch({
99+
program,
100+
hostname: 'unix:///tmp',
101+
runtimeArgs: ['-dxdebug.client_host=unix:///tmp'],
102+
}),
103+
/File .+ exists and cannot be used for Unix Domain socket/
104+
)
105+
})
95106
})
96107

97108
describe('continuation commands', () => {
@@ -822,6 +833,20 @@ describe('PHP Debug Adapter', () => {
822833
})
823834
})
824835

836+
describe('stream tests', () => {
837+
const program = path.join(TEST_PROJECT, 'output.php')
838+
839+
it('listen with externalConsole', async () => {
840+
// this is how we can currently turn on stdout redirect
841+
await Promise.all([client.launch({ stream: { stdout: '1' } }), client.configurationSequence()])
842+
843+
const script = childProcess.spawn('php', [program])
844+
after(() => script.kill())
845+
await client.assertOutput('stdout', 'stdout output 1')
846+
await client.assertOutput('stdout', 'stdout output 2')
847+
})
848+
})
849+
825850
describe('special adapter tests', () => {
826851
it('max connections', async () => {
827852
await Promise.all([client.launch({ maxConnections: 1, log: true }), client.configurationSequence()])

src/xdebugConnection.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,24 @@ export class UserNotify extends Notify {
182182
}
183183
}
184184

185+
export class Stream {
186+
/** Type of stream */
187+
type: string
188+
/** Data of the stream */
189+
value: string
190+
191+
/** Constructs a stream object from an XML node from a Xdebug response */
192+
constructor(document: XMLDocument) {
193+
this.type = document.documentElement.getAttribute('type')!
194+
const encoding = document.documentElement.getAttribute('encoding')
195+
if (encoding) {
196+
this.value = iconv.encode(document.documentElement.textContent!, encoding).toString()
197+
} else {
198+
this.value = document.documentElement.textContent!
199+
}
200+
}
201+
}
202+
185203
export type BreakpointType = 'line' | 'call' | 'return' | 'exception' | 'conditional' | 'watch'
186204
export type BreakpointState = 'enabled' | 'disabled'
187205
export type BreakpointResolved = 'resolved' | 'unresolved'
@@ -748,6 +766,7 @@ export declare interface Connection extends DbgpConnection {
748766
on(event: 'log', listener: (text: string) => void): this
749767
on(event: 'notify_user', listener: (notify: UserNotify) => void): this
750768
on(event: 'notify_breakpoint_resolved', listener: (notify: BreakpointResolvedNotify) => void): this
769+
on(event: 'stream', listener: (stream: Stream) => void): this
751770
}
752771

753772
/**
@@ -812,6 +831,9 @@ export class Connection extends DbgpConnection {
812831
} else if (response.documentElement.nodeName === 'notify') {
813832
const n = Notify.fromXml(response, this)
814833
this.emit('notify_' + n.name, n)
834+
} else if (response.documentElement.nodeName === 'stream') {
835+
const s = new Stream(response)
836+
this.emit('stream', s)
815837
} else {
816838
const transactionId = parseInt(response.documentElement.getAttribute('transaction_id')!)
817839
if (this._pendingCommands.has(transactionId)) {
@@ -826,7 +848,13 @@ export class Connection extends DbgpConnection {
826848
}
827849
}
828850
})
829-
this.on('close', () => this._initPromiseRejectFn(new Error('connection closed (on close)')))
851+
this.on('close', () => {
852+
this._pendingCommands.forEach(command => command.rejectFn(new Error('connection closed (on close)')))
853+
this._pendingCommands.clear()
854+
this._commandQueue.forEach(command => command.rejectFn(new Error('connection closed (on close)')))
855+
this._commandQueue = []
856+
this._initPromiseRejectFn(new Error('connection closed (on close)'))
857+
})
830858
}
831859

832860
/** Returns a promise that gets resolved once the init packet arrives */
@@ -1112,4 +1140,14 @@ export class Connection extends DbgpConnection {
11121140
public async sendEvalCommand(expression: string): Promise<EvalResponse> {
11131141
return new EvalResponse(await this._enqueueCommand('eval', undefined, expression), this)
11141142
}
1143+
1144+
// ------------------------------ stream ----------------------------------------
1145+
1146+
public async sendStdout(mode: 0 | 1 | 2): Promise<Response> {
1147+
return new Response(await this._enqueueCommand('stdout', `-c ${mode}`), this)
1148+
}
1149+
1150+
public async sendStderr(mode: 0 | 1 | 2): Promise<Response> {
1151+
return new Response(await this._enqueueCommand('stderr', `-c ${mode}`), this)
1152+
}
11151153
}

0 commit comments

Comments
 (0)