async debug()

in src/goTest/run.ts [138:223]


	async debug(request: TestRunRequest, token?: CancellationToken, debugTestFunc: Function = debugTestAtCursor) {
		if (!request.include) {
			await vscode.window.showErrorMessage('The Go test explorer does not support debugging multiple tests');
			return;
		}

		const collected = new Map<TestItem, CollectedTest[]>();
		const files = new Set<TestItem>();
		for (const item of request.include) {
			await this.collectTests(item, true, request.exclude || [], collected, files);
		}

		const tests = Array.from(collected.values()).reduce((a, b) => a.concat(b), []);
		if (tests.length > 1) {
			await vscode.window.showErrorMessage('The Go test explorer does not support debugging multiple tests');
			return;
		}

		const test = tests[0].item;
		const { kind, name = '' } = GoTest.parseId(test.id);
		if (!test.uri) return;
		const doc = await vscode.workspace.openTextDocument(test.uri);
		await doc.save();

		const goConfig = getGoConfig(test.uri);
		const getFunctions = kind === 'benchmark' ? getBenchmarkFunctions : getTestFunctions;
		const testFunctions = await getFunctions(this.goCtx, doc, token);

		// TODO Can we get output from the debug session, in order to check for
		// run/pass/fail events?

		const id = `debug #${debugSessionID++} ${name}`;
		const subs: vscode.Disposable[] = [];
		const sessionPromise = new Promise<DebugSession | null>((resolve) => {
			subs.push(
				vscode.debug.onDidStartDebugSession((s) => {
					if (s.configuration.sessionID === id) {
						resolve(s);
						subs.forEach((s) => s.dispose());
					}
				})
			);

			if (token) {
				subs.push(
					token.onCancellationRequested(() => {
						resolve(null);
						subs.forEach((s) => s.dispose());
					})
				);
			}
		});

		const run = this.ctrl.createTestRun(request, `Debug ${name}`);
		if (!testFunctions) return;
		const started = await debugTestFunc(doc, name, testFunctions, goConfig, id);
		if (!started) {
			subs.forEach((s) => s.dispose());
			run.end();
			return;
		}

		const session = await sessionPromise;
		if (!session) {
			run.end();
			return;
		}

		token?.onCancellationRequested(() => vscode.debug.stopDebugging(session));

		await new Promise<void>((resolve) => {
			const sub = vscode.debug.onDidTerminateDebugSession(didTerminateSession);

			token?.onCancellationRequested(() => {
				resolve();
				sub.dispose();
			});

			function didTerminateSession(s: DebugSession) {
				if (s.id !== session?.id) return;
				resolve();
				sub.dispose();
			}
		});
		run.end();
	}