Skip to content

Commit a1cdde6

Browse files
committed
Implement debugging in client-side mode (fix #1)
1 parent dab7205 commit a1cdde6

2 files changed

Lines changed: 45 additions & 5 deletions

File tree

src/commonRunTestsHandler.ts

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export async function commonRunTestsHandler(controller: vscode.TestController, r
124124
}
125125
return;
126126
}
127-
127+
128128
const username: string = server.username || 'UnknownUser';
129129
const testRoot = vscode.Uri.from({ scheme: 'isfs', authority, path: `/.vscode/UnitTestRoot/${username}` });
130130
try {
@@ -160,8 +160,10 @@ export async function commonRunTestsHandler(controller: vscode.TestController, r
160160
}
161161

162162
// Finally, run the tests using the debugger API
163-
const runQualifiers = controller.id === `${extensionId}-Local` ? "" : "/noload/nodelete";
164-
// Run tests through the debugger but only stop at breakpoints etc if user chose "Debug Test" instead of "Run Test"
163+
// but only stop at breakpoints etc if user chose "Debug Test" instead of "Run Test"
164+
const isClientSideMode = controller.id === `${extensionId}-Local`;
165+
const isDebug = request.profile?.kind === vscode.TestRunProfileKind.Debug;
166+
const runQualifiers = !isClientSideMode ? "/noload/nodelete" : isDebug ? "/noload" : "";
165167
const runIndex = allTestRuns.push(run) - 1;
166168
runIndices.push(runIndex);
167169

@@ -187,15 +189,49 @@ export async function commonRunTestsHandler(controller: vscode.TestController, r
187189
"testingIdBase": firstClassTestItem.id.split(":", 2).join(":")
188190
};
189191
const sessionOptions: vscode.DebugSessionOptions = {
190-
noDebug: request.profile?.kind !== vscode.TestRunProfileKind.Debug,
192+
noDebug: !isDebug,
191193
suppressDebugToolbar: request.profile?.kind !== vscode.TestRunProfileKind.Debug
192194
};
193195

194196
// ObjectScript debugger's initializeRequest handler needs to identify target server and namespace
195197
// and does this from current active document, so here we make sure there's a suitable one.
196198
vscode.commands.executeCommand("vscode.open", oneUri, { preserveFocus: true });
197199

198-
// Start the debugger unless cancelled
200+
// When debugging in client-side mode the classes must be loaded and compiled before the debug run happens, otherwise breakpoints don't bind
201+
if (isClientSideMode && isDebug && !cancellation.isCancellationRequested) {
202+
203+
// Without the /debug option the classes are compiled without maps, preventing breakpoints from binding.
204+
const preloadConfig = {
205+
"type": "objectscript",
206+
"request": "launch",
207+
"name": 'LocalTests.Preload',
208+
"program": `##class(%UnitTest.Manager).RunTest("${testSpec}","/nodisplay/load/debug/norun/nodelete")`,
209+
};
210+
211+
// Prepare to detect when the preload completes
212+
let sessionTerminated: () => void;
213+
const listener = vscode.debug.onDidTerminateDebugSession((session) => {
214+
if (session.name === 'LocalTests.Preload') {
215+
sessionTerminated();
216+
}
217+
});
218+
const sessionTerminatedPromise = new Promise<void>(resolve => sessionTerminated = resolve);
219+
220+
// Start the preload
221+
if (!await vscode.debug.startDebugging(folder, preloadConfig, { noDebug: true, suppressDebugStatusbar: true })) {
222+
listener.dispose();
223+
await vscode.window.showErrorMessage(`Failed to preload client-side test classes for debugging`, { modal: true });
224+
run.end();
225+
allTestRuns[runIndex] = undefined;
226+
return;
227+
};
228+
229+
// Wait for it to complete
230+
await sessionTerminatedPromise;
231+
listener.dispose();
232+
}
233+
234+
// Start the run unless already cancelled
199235
if (cancellation.isCancellationRequested || !await vscode.debug.startDebugging(folder, configuration, sessionOptions)) {
200236
if (!cancellation.isCancellationRequested) {
201237
await vscode.window.showErrorMessage(`Failed to launch testing`, { modal: true });

src/debugTrackerFactory.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import { DebugTracker } from './debugTracker';
44
export class DebugTrackerFactory implements vscode.DebugAdapterTrackerFactory {
55

66
createDebugAdapterTracker(session: vscode.DebugSession): vscode.ProviderResult<vscode.DebugAdapterTracker> {
7+
if (session.configuration.name.split(':')[0] === 'LocalTests.Preload') {
8+
// No need to track the debug session which preloads the UT classes
9+
return undefined;
10+
}
711
return new DebugTracker(session);
812
}
913
}

0 commit comments

Comments
 (0)