Skip to content

Commit

Permalink
Improvements to attach-type debugging (#1417)
Browse files Browse the repository at this point in the history
  • Loading branch information
gjsjohnmurray authored Jul 26, 2024
1 parent 5e68695 commit 065df42
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 25 deletions.
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1719,7 +1719,12 @@
"type": "objectscript",
"request": "launch",
"name": "XDebug"
}
},
{
"type": "objectscript",
"request": "attach",
"name": "Attach to running process"
}
],
"configurationSnippets": [
{
Expand Down
28 changes: 18 additions & 10 deletions src/debug/debugAdapterFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,41 @@ import { ObjectScriptDebugSession } from "./debugSession";
export class ObjectScriptDebugAdapterDescriptorFactory
implements vscode.DebugAdapterDescriptorFactory, vscode.Disposable
{
private server?: net.Server;
private serverMap = new Map<string, net.Server>();

public createDebugAdapterDescriptor(
session: vscode.DebugSession,
executable: vscode.DebugAdapterExecutable | undefined
): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
if (!this.server) {
// start listening on a random port
const debugSession = new ObjectScriptDebugSession();
const debugSession = new ObjectScriptDebugSession();

// pickProcess may have added a suffix to inform us which folder's connection it used
const workspaceFolderIndex = (session.configuration.processId as string)?.split("@")[1];
const workspaceFolderUri = workspaceFolderIndex
? vscode.workspace.workspaceFolders[parseInt(workspaceFolderIndex)]?.uri
: undefined;
debugSession.setupAPI(workspaceFolderUri);

this.server = net
const serverId = debugSession.serverId;
let server = this.serverMap.get(serverId);
if (!server) {
// start listening on a random port
server = net
.createServer((socket) => {
debugSession.setRunAsServer(true);
debugSession.start(socket as NodeJS.ReadableStream, socket);
})
.listen(0);
this.serverMap.set(serverId, server);
}

// make VS Code connect to debug server
const address = this.server.address();
// make VS Code connect to this debug server
const address = server.address();
const port = typeof address !== "string" ? address.port : 9000;
return new vscode.DebugAdapterServer(port);
}

public dispose(): void {
if (this.server) {
this.server.close();
}
this.serverMap.forEach((server) => server.close());
}
}
56 changes: 43 additions & 13 deletions src/debug/debugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ async function convertClientPathToDebugger(uri: vscode.Uri, namespace: string):
}

export class ObjectScriptDebugSession extends LoggingDebugSession {
/** After setupAPI() has been called this will return the serverId string */
public get serverId(): string | undefined {
return this._api?.serverId;
}

private _api?: AtelierAPI;

private _workspaceFolderUri?: vscode.Uri;

private _statuses = new Map<xdebug.Connection, xdebug.StatusResponse>();

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

private _workspace: string;

private cookies: string[] = [];

/** If this is a CSPDEBUG session */
private _isCsp = false;

Expand Down Expand Up @@ -124,6 +131,27 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
} while (!this._debugTargetSet);
}

/** To be called immediately after construction */
public setupAPI(workspaceFolderUri?: vscode.Uri): void {
// Only effective the first time
if (this._api) {
return;
}

this._workspaceFolderUri = workspaceFolderUri;
if (workspaceFolderUri) {
// The uri of the relevant workspace folder was set after construction
this._workspace = undefined;
this._api = new AtelierAPI(workspaceFolderUri);
} else {
// Fall back to old way of deciding where to connect
const file = currentFile();
this._workspace = file?.workspaceFolder;
this._api = new AtelierAPI(file?.uri);
}
return;
}

/** Check if the target is stopped */
private async _isStopped(): Promise<boolean> {
return this._connection
Expand Down Expand Up @@ -161,21 +189,16 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
};

try {
const file = currentFile();
this._workspace = file?.workspaceFolder;

const api = new AtelierAPI(file?.uri);
this.cookies = api.cookies;
if (!api.active) {
if (!this._api.active) {
throw new Error("Connection not active");
}
this._namespace = api.ns;
this._url = api.xdebugUrl();
this._namespace = this._api.ns;
this._url = this._api.xdebugUrl();

const socket = new WebSocket(this._url, {
rejectUnauthorized: vscode.workspace.getConfiguration("http").get("proxyStrictSSL"),
headers: {
cookie: this.cookies,
cookie: this._api.cookies,
},
});

Expand Down Expand Up @@ -240,7 +263,8 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
protected async attachRequest(response: DebugProtocol.AttachResponse, args: AttachRequestArguments): Promise<void> {
try {
this._debugTargetSet = this._isLaunch = false;
const debugTarget = args.cspDebugId != undefined ? `CSPDEBUG:${args.cspDebugId}` : `PID:${args.processId}`;
const debugTarget =
args.cspDebugId != undefined ? `CSPDEBUG:${args.cspDebugId}` : `PID:${args.processId.split("@")[0]}`;
await this._connection.sendFeatureSetCommand("debug_target", debugTarget);
if (args.cspDebugId != undefined) {
if (args.isUnitTest) {
Expand Down Expand Up @@ -590,7 +614,13 @@ export class ObjectScriptDebugSession extends LoggingDebugSession {
stack.stack.map(async (stackFrame: xdebug.StackFrame, index): Promise<StackFrame> => {
const [, namespace, name] = decodeURI(stackFrame.fileUri).match(/^dbgp:\/\/\|([^|]+)\|(.*)$/);
const routine = name;
const fileUri = DocumentContentProvider.getUri(routine, this._workspace, namespace);
const fileUri = DocumentContentProvider.getUri(
routine,
this._workspace,
namespace,
undefined,
this._workspaceFolderUri
);
const source = new Source(routine, fileUri.toString());
let line = stackFrame.line + 1;
const place = `${stackFrame.method}+${stackFrame.methodOffset}`;
Expand Down
7 changes: 6 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,12 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
matchOnDescription: true,
})
.then((value) => {
if (value) return value.label;
if (value) {
const workspaceFolderIndex = vscode.workspace.workspaceFolders.findIndex(
(folder) => folder.uri.toString() === connectionUri.toString()
);
return workspaceFolderIndex < 0 ? value.label : `${value.label}@${workspaceFolderIndex}`;
}
});
}),
vscode.commands.registerCommand("vscode-objectscript.jumpToTagAndOffset", jumpToTagAndOffset),
Expand Down

0 comments on commit 065df42

Please sign in to comment.