From 319c2c036aed26dc79f5c31b3ee42385c05df49e Mon Sep 17 00:00:00 2001 From: Ikhsan Assaat Date: Sat, 3 Feb 2024 22:18:51 +0000 Subject: [PATCH] Create multi session debugger --- README.md | 2 ++ package.json | 5 +++++ src/config.ts | 3 ++- src/extension.ts | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e01dc1c..55dc3d5d 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,8 @@ You can specify the following "attach" configurations. * Specify pairs of remote root path and local root path like `/remote_dir:/local_dir` if sharing the same source repository with local and remote computers. * You can specify multiple pairs like `/rem1:/loc1,/rem2:/loc2` by concatenating with `,`. * default: undefined +* `supportAttachMultiSockets` + * Allow for attaching multiple running sockets at once Without `debugPort` configuration, the diff --git a/package.json b/package.json index 0847c806..fd961fb8 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,11 @@ "type": "string", "description": "Specify pairs of remote root path and local root path like `/remote_dir:/local_dir`. `/remote_dir:$(workspaceFolder)` is useful. You can specify multiple pairs like `/rem1:/loc1,/rem2:/loc2` by concatenating with `,`." }, + "supportAttachMultiSockets": { + "type": "boolean", + "description": "Allow for attaching multiple running sockets at once", + "default": false + }, "env": { "type": "object", "description": "Additional environment variables to pass to the rdbg process", diff --git a/src/config.ts b/src/config.ts index 7893469e..8640e9ed 100644 --- a/src/config.ts +++ b/src/config.ts @@ -8,6 +8,7 @@ export interface AttachConfiguration extends DebugConfiguration { debugPort?: string; cwd?: string; showProtocolLog?: boolean; + supportAttachMultiSockets?: boolean; autoAttach?: string; } @@ -32,5 +33,5 @@ export interface LaunchConfiguration extends DebugConfiguration { rdbgPath?: string; showProtocolLog?: boolean; - useTerminal?: boolean + useTerminal?: boolean; } diff --git a/src/extension.ts b/src/extension.ts index 15cf6748..ccd96ae9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -41,6 +41,7 @@ let lastExecCommand: string | undefined; let lastProgram: string | undefined; const terminalName: string = "Ruby Debug Terminal"; +const attachSingleSocketEvent: string = "attachSingleSocket"; function workspaceFolder(): string | undefined { if (vscode.workspace.workspaceFolders) { @@ -119,6 +120,24 @@ export function activate(context: vscode.ExtensionContext) { } })); + context.subscriptions.push( + vscode.debug.onDidReceiveDebugSessionCustomEvent((e) => { + switch (e.event) { + case attachSingleSocketEvent: + vscode.debug.startDebugging( + e.session.workspaceFolder, + { + type: "rdbg", + name: e.body.name, + request: "attach", + debugPort: e.body.socketPath, + } as AttachConfiguration, + e.session, + ); + } + }), + ); + const folders = vscode.workspace.workspaceFolders; if (folders !== undefined && folders.length > 0) { @@ -265,6 +284,34 @@ class StopDebugAdapter implements vscode.DebugAdapter { } } +class MultiSessionDebugAdapter implements vscode.DebugAdapter { + private sockPaths: Array = []; + private sendMessage = new vscode.EventEmitter(); + readonly onDidSendMessage: vscode.Event = this.sendMessage.event; + + constructor(sockPaths: Array) { + this.sockPaths = sockPaths; + } + + handleMessage(message: any): void { + if (message.type === "request" && message.command === "initialize") { + for (const [index, socketPath] of this.sockPaths.entries()) { + const name = socketPath.split("/").pop(); + this.sendMessage.fire({ + type: "event", + seq: index, + event: attachSingleSocketEvent, + body: { name, socketPath }, + }); + } + } + } + + dispose() { + // Nothing to do + } +} + const findRDBGTerminal = (): vscode.Terminal | undefined => { let terminal: vscode.Terminal | undefined; const currentTerminals: vscode.Terminal[] = Array.from(outputTerminals.values()); @@ -479,6 +526,10 @@ class RdbgAdapterDescriptorFactory implements DebugAdapterDescriptorFactory, Ver sockPath = list[0]; break; default: + if (config.supportAttachMultiSockets) { + return new DebugAdapterInlineImplementation(new MultiSessionDebugAdapter(list)); + } + const simplifiedList = this.simplifySockList(list); const sock = await vscode.window.showQuickPick(simplifiedList, { title: "debug ports in " + path.dirname(list[0])