Skip to content

Commit 065df42

Browse files
Improvements to attach-type debugging (#1417)
1 parent 5e68695 commit 065df42

File tree

4 files changed

+73
-25
lines changed

4 files changed

+73
-25
lines changed

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,12 @@
17191719
"type": "objectscript",
17201720
"request": "launch",
17211721
"name": "XDebug"
1722-
}
1722+
},
1723+
{
1724+
"type": "objectscript",
1725+
"request": "attach",
1726+
"name": "Attach to running process"
1727+
}
17231728
],
17241729
"configurationSnippets": [
17251730
{

src/debug/debugAdapterFactory.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,41 @@ import { ObjectScriptDebugSession } from "./debugSession";
55
export class ObjectScriptDebugAdapterDescriptorFactory
66
implements vscode.DebugAdapterDescriptorFactory, vscode.Disposable
77
{
8-
private server?: net.Server;
8+
private serverMap = new Map<string, net.Server>();
99

1010
public createDebugAdapterDescriptor(
1111
session: vscode.DebugSession,
1212
executable: vscode.DebugAdapterExecutable | undefined
1313
): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
14-
if (!this.server) {
15-
// start listening on a random port
16-
const debugSession = new ObjectScriptDebugSession();
14+
const debugSession = new ObjectScriptDebugSession();
15+
16+
// pickProcess may have added a suffix to inform us which folder's connection it used
17+
const workspaceFolderIndex = (session.configuration.processId as string)?.split("@")[1];
18+
const workspaceFolderUri = workspaceFolderIndex
19+
? vscode.workspace.workspaceFolders[parseInt(workspaceFolderIndex)]?.uri
20+
: undefined;
21+
debugSession.setupAPI(workspaceFolderUri);
1722

18-
this.server = net
23+
const serverId = debugSession.serverId;
24+
let server = this.serverMap.get(serverId);
25+
if (!server) {
26+
// start listening on a random port
27+
server = net
1928
.createServer((socket) => {
2029
debugSession.setRunAsServer(true);
2130
debugSession.start(socket as NodeJS.ReadableStream, socket);
2231
})
2332
.listen(0);
33+
this.serverMap.set(serverId, server);
2434
}
2535

26-
// make VS Code connect to debug server
27-
const address = this.server.address();
36+
// make VS Code connect to this debug server
37+
const address = server.address();
2838
const port = typeof address !== "string" ? address.port : 9000;
2939
return new vscode.DebugAdapterServer(port);
3040
}
3141

3242
public dispose(): void {
33-
if (this.server) {
34-
this.server.close();
35-
}
43+
this.serverMap.forEach((server) => server.close());
3644
}
3745
}

src/debug/debugSession.ts

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ async function convertClientPathToDebugger(uri: vscode.Uri, namespace: string):
6363
}
6464

6565
export class ObjectScriptDebugSession extends LoggingDebugSession {
66+
/** After setupAPI() has been called this will return the serverId string */
67+
public get serverId(): string | undefined {
68+
return this._api?.serverId;
69+
}
70+
71+
private _api?: AtelierAPI;
72+
73+
private _workspaceFolderUri?: vscode.Uri;
74+
6675
private _statuses = new Map<xdebug.Connection, xdebug.StatusResponse>();
6776

6877
private _connection: xdebug.Connection;
@@ -89,8 +98,6 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
8998

9099
private _workspace: string;
91100

92-
private cookies: string[] = [];
93-
94101
/** If this is a CSPDEBUG session */
95102
private _isCsp = false;
96103

@@ -124,6 +131,27 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
124131
} while (!this._debugTargetSet);
125132
}
126133

134+
/** To be called immediately after construction */
135+
public setupAPI(workspaceFolderUri?: vscode.Uri): void {
136+
// Only effective the first time
137+
if (this._api) {
138+
return;
139+
}
140+
141+
this._workspaceFolderUri = workspaceFolderUri;
142+
if (workspaceFolderUri) {
143+
// The uri of the relevant workspace folder was set after construction
144+
this._workspace = undefined;
145+
this._api = new AtelierAPI(workspaceFolderUri);
146+
} else {
147+
// Fall back to old way of deciding where to connect
148+
const file = currentFile();
149+
this._workspace = file?.workspaceFolder;
150+
this._api = new AtelierAPI(file?.uri);
151+
}
152+
return;
153+
}
154+
127155
/** Check if the target is stopped */
128156
private async _isStopped(): Promise<boolean> {
129157
return this._connection
@@ -161,21 +189,16 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
161189
};
162190

163191
try {
164-
const file = currentFile();
165-
this._workspace = file?.workspaceFolder;
166-
167-
const api = new AtelierAPI(file?.uri);
168-
this.cookies = api.cookies;
169-
if (!api.active) {
192+
if (!this._api.active) {
170193
throw new Error("Connection not active");
171194
}
172-
this._namespace = api.ns;
173-
this._url = api.xdebugUrl();
195+
this._namespace = this._api.ns;
196+
this._url = this._api.xdebugUrl();
174197

175198
const socket = new WebSocket(this._url, {
176199
rejectUnauthorized: vscode.workspace.getConfiguration("http").get("proxyStrictSSL"),
177200
headers: {
178-
cookie: this.cookies,
201+
cookie: this._api.cookies,
179202
},
180203
});
181204

@@ -240,7 +263,8 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
240263
protected async attachRequest(response: DebugProtocol.AttachResponse, args: AttachRequestArguments): Promise<void> {
241264
try {
242265
this._debugTargetSet = this._isLaunch = false;
243-
const debugTarget = args.cspDebugId != undefined ? `CSPDEBUG:${args.cspDebugId}` : `PID:${args.processId}`;
266+
const debugTarget =
267+
args.cspDebugId != undefined ? `CSPDEBUG:${args.cspDebugId}` : `PID:${args.processId.split("@")[0]}`;
244268
await this._connection.sendFeatureSetCommand("debug_target", debugTarget);
245269
if (args.cspDebugId != undefined) {
246270
if (args.isUnitTest) {
@@ -590,7 +614,13 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
590614
stack.stack.map(async (stackFrame: xdebug.StackFrame, index): Promise<StackFrame> => {
591615
const [, namespace, name] = decodeURI(stackFrame.fileUri).match(/^dbgp:\/\/\|([^|]+)\|(.*)$/);
592616
const routine = name;
593-
const fileUri = DocumentContentProvider.getUri(routine, this._workspace, namespace);
617+
const fileUri = DocumentContentProvider.getUri(
618+
routine,
619+
this._workspace,
620+
namespace,
621+
undefined,
622+
this._workspaceFolderUri
623+
);
594624
const source = new Source(routine, fileUri.toString());
595625
let line = stackFrame.line + 1;
596626
const place = `${stackFrame.method}+${stackFrame.methodOffset}`;

src/extension.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,12 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
10151015
matchOnDescription: true,
10161016
})
10171017
.then((value) => {
1018-
if (value) return value.label;
1018+
if (value) {
1019+
const workspaceFolderIndex = vscode.workspace.workspaceFolders.findIndex(
1020+
(folder) => folder.uri.toString() === connectionUri.toString()
1021+
);
1022+
return workspaceFolderIndex < 0 ? value.label : `${value.label}@${workspaceFolderIndex}`;
1023+
}
10191024
});
10201025
}),
10211026
vscode.commands.registerCommand("vscode-objectscript.jumpToTagAndOffset", jumpToTagAndOffset),

0 commit comments

Comments
 (0)