Skip to content

Commit

Permalink
Merge branch 'main' into run-in-terminal-new
Browse files Browse the repository at this point in the history
  • Loading branch information
zobo authored Nov 10, 2024
2 parents 4005663 + 7aca123 commit b94ace2
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 5 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ All notable changes to this project will be documented in this file.

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

## [1.35.0]
## [1.36.0]

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

## [1.35.0]

- Support for DBGp stream command
- Avoid conflict with full screen F11 shortcut
- Improve existing unix socket handling
- Improve close socket handling

## [1.34.0]

- Partial support for virtual workspaces
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ More general information on debugging with VS Code can be found on https://code.
- `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).
- `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.
- `xdebugCloudToken`: Instead of listening locally, open a connection and register with Xdebug Cloud and accept debugging sessions on that connection.
- `stream`: Allows to influence DBGp streams. Xdebug only supports `stdout` see [DBGp stdout](https://xdebug.org/docs/dbgp#stdout-stderr)
- `stdout`: Redirect stdout stream: 0 (disable), 1 (copy), 2 (redirect)

Options specific to CLI debugging:

Expand Down
13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,17 @@
"xdebugCloudToken": {
"type": "string",
"description": "Xdebug Could token"
},
"stream": {
"type": "object",
"description": "Xdebug stream settings",
"properties": {
"stdout": {
"type": "number",
"description": "Redirect stdout stream: 0 (disable), 1 (copy), 2 (redirect)",
"default": 0
}
}
}
}
}
Expand Down Expand Up @@ -586,7 +597,7 @@
{
"command": "extension.php-debug.startWithStopOnEntry",
"key": "F11",
"when": "!inDebugMode && debugConfigurationType == 'php'"
"when": "!inDebugMode && activeViewlet == 'workbench.view.debug' && debugConfigurationType == 'php'"
}
]
}
Expand Down
8 changes: 8 additions & 0 deletions src/cloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,12 @@ class InnerCloudTransport extends EventEmitter implements Transport {
}
return this
}

destroy(error?: Error): this {
if (this._open) {
this._open = false
this.emit('close')
}
return this
}
}
3 changes: 2 additions & 1 deletion src/dbgp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface Transport {
on(event: 'close', listener: () => void): this
write(buffer: Uint8Array | string, cb?: (err?: Error) => void): boolean
end(callback?: () => void): this
destroy(error?: Error): this
}

export declare interface DbgpConnection {
Expand Down Expand Up @@ -145,7 +146,7 @@ export class DbgpConnection extends EventEmitter {

/** closes the underlying socket */
public close(): Promise<void> {
this._socket.end()
this._socket.destroy()
return this._closePromise
}
}
18 changes: 18 additions & 0 deletions src/phpDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ export interface LaunchRequestArguments extends VSCodeDebugProtocol.LaunchReques
maxConnections?: number
/** Xdebug cloud token */
xdebugCloudToken?: string
/** Xdebug stream settings */
stream?: {
stdout?: 0 | 1 | 2
}

// CLI options

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

const stdout =
this._args.stream?.stdout === undefined ? (this._args.externalConsole ? 1 : 0) : this._args.stream.stdout
if (stdout) {
await connection.sendStdout(stdout)
connection.on('stream', (stream: xdebug.Stream) =>
this.sendEvent(new vscode.OutputEvent(stream.value, 'stdout'))
)
}

this.sendEvent(new vscode.ThreadEvent('started', connection.id))

// wait for all breakpoints
Expand Down
27 changes: 26 additions & 1 deletion src/test/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { DebugClient } from '@vscode/debugadapter-testsupport'
import { DebugProtocol } from '@vscode/debugprotocol'
import * as semver from 'semver'
import * as net from 'net'
import { describe, it, beforeEach, afterEach } from 'mocha'
import * as childProcess from 'child_process'
import { describe, it, beforeEach, afterEach, after } from 'mocha'
chai.use(chaiAsPromised)
const assert = chai.assert

Expand Down Expand Up @@ -92,6 +93,16 @@ describe('PHP Debug Adapter', () => {
client.waitForEvent('terminated'),
])
})
;(process.platform === 'win32' ? it.skip : it)('should error on existing unix pipe', async () => {
await assert.isRejected(
client.launch({
program,
hostname: 'unix:///tmp',
runtimeArgs: ['-dxdebug.client_host=unix:///tmp'],
}),
/File .+ exists and cannot be used for Unix Domain socket/
)
})
})

describe('continuation commands', () => {
Expand Down Expand Up @@ -822,6 +833,20 @@ describe('PHP Debug Adapter', () => {
})
})

describe('stream tests', () => {
const program = path.join(TEST_PROJECT, 'output.php')

it('listen with externalConsole', async () => {
// this is how we can currently turn on stdout redirect
await Promise.all([client.launch({ stream: { stdout: '1' } }), client.configurationSequence()])

const script = childProcess.spawn('php', [program])
after(() => script.kill())
await client.assertOutput('stdout', 'stdout output 1')
await client.assertOutput('stdout', 'stdout output 2')
})
})

describe('special adapter tests', () => {
it('max connections', async () => {
await Promise.all([client.launch({ maxConnections: 1, log: true }), client.configurationSequence()])
Expand Down
40 changes: 39 additions & 1 deletion src/xdebugConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,24 @@ export class UserNotify extends Notify {
}
}

export class Stream {
/** Type of stream */
type: string
/** Data of the stream */
value: string

/** Constructs a stream object from an XML node from a Xdebug response */
constructor(document: XMLDocument) {
this.type = document.documentElement.getAttribute('type')!
const encoding = document.documentElement.getAttribute('encoding')
if (encoding) {
this.value = iconv.encode(document.documentElement.textContent!, encoding).toString()
} else {
this.value = document.documentElement.textContent!
}
}
}

export type BreakpointType = 'line' | 'call' | 'return' | 'exception' | 'conditional' | 'watch'
export type BreakpointState = 'enabled' | 'disabled'
export type BreakpointResolved = 'resolved' | 'unresolved'
Expand Down Expand Up @@ -748,6 +766,7 @@ export declare interface Connection extends DbgpConnection {
on(event: 'log', listener: (text: string) => void): this
on(event: 'notify_user', listener: (notify: UserNotify) => void): this
on(event: 'notify_breakpoint_resolved', listener: (notify: BreakpointResolvedNotify) => void): this
on(event: 'stream', listener: (stream: Stream) => void): this
}

/**
Expand Down Expand Up @@ -812,6 +831,9 @@ export class Connection extends DbgpConnection {
} else if (response.documentElement.nodeName === 'notify') {
const n = Notify.fromXml(response, this)
this.emit('notify_' + n.name, n)
} else if (response.documentElement.nodeName === 'stream') {
const s = new Stream(response)
this.emit('stream', s)
} else {
const transactionId = parseInt(response.documentElement.getAttribute('transaction_id')!)
if (this._pendingCommands.has(transactionId)) {
Expand All @@ -826,7 +848,13 @@ export class Connection extends DbgpConnection {
}
}
})
this.on('close', () => this._initPromiseRejectFn(new Error('connection closed (on close)')))
this.on('close', () => {
this._pendingCommands.forEach(command => command.rejectFn(new Error('connection closed (on close)')))
this._pendingCommands.clear()
this._commandQueue.forEach(command => command.rejectFn(new Error('connection closed (on close)')))
this._commandQueue = []
this._initPromiseRejectFn(new Error('connection closed (on close)'))
})
}

/** Returns a promise that gets resolved once the init packet arrives */
Expand Down Expand Up @@ -1112,4 +1140,14 @@ export class Connection extends DbgpConnection {
public async sendEvalCommand(expression: string): Promise<EvalResponse> {
return new EvalResponse(await this._enqueueCommand('eval', undefined, expression), this)
}

// ------------------------------ stream ----------------------------------------

public async sendStdout(mode: 0 | 1 | 2): Promise<Response> {
return new Response(await this._enqueueCommand('stdout', `-c ${mode}`), this)
}

public async sendStderr(mode: 0 | 1 | 2): Promise<Response> {
return new Response(await this._enqueueCommand('stderr', `-c ${mode}`), this)
}
}

0 comments on commit b94ace2

Please sign in to comment.