/* eslint-disable @typescript-eslint/no-explicit-any */
/*---------------------------------------------------------
 * Copyright 2021 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

import { ChildProcess, ChildProcessWithoutNullStreams, spawn } from 'child_process';
import stream = require('stream');
import vscode = require('vscode');
import { OutputEvent, TerminatedEvent } from 'vscode-debugadapter';
import getPort = require('get-port');
import path = require('path');
import * as fs from 'fs';
import * as net from 'net';
import { DebugProtocol } from 'vscode-debugprotocol';
import { getWorkspaceFolderPath } from './util';
import { getEnvPath, getBinPathFromEnvVar } from './utils/pathUtils';
import { GoExtensionContext } from './context';
import { createRegisterCommand } from './commands';

export function activate(ctx: vscode.ExtensionContext, goCtx: GoExtensionContext) {
	const debugOutputChannel = vscode.window.createOutputChannel('Go Debug', { log: true });
	ctx.subscriptions.push(debugOutputChannel);

	const factory = new GoDebugAdapterDescriptorFactory(debugOutputChannel);
	ctx.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('go', factory));
	if ('dispose' in factory) {
		ctx.subscriptions.push(factory);
	}

	const tracker = new GoDebugAdapterTrackerFactory(debugOutputChannel);
	ctx.subscriptions.push(vscode.debug.registerDebugAdapterTrackerFactory('go', tracker));
	if ('dispose' in tracker) {
		ctx.subscriptions.push(tracker);
	}

	const registerCommand = createRegisterCommand(ctx, goCtx);
	registerCommand('go.debug.toggleHideSystemGoroutines', () => toggleHideSystemGoroutines);
}

class GoDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
	constructor(private outputChannel: vscode.LogOutputChannel) {}

	public createDebugAdapterDescriptor(
		session: vscode.DebugSession,
		executable: vscode.DebugAdapterExecutable | undefined
	): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
		if (session.configuration.debugAdapter === 'dlv-dap') {
			return this.createDebugAdapterDescriptorDlvDap(session.configuration);
		}
		return executable;
	}

	public async dispose() {
		console.log('GoDebugAdapterDescriptorFactory.dispose');
	}

	private async createDebugAdapterDescriptorDlvDap(
		configuration: vscode.DebugConfiguration
	): Promise<vscode.ProviderResult<vscode.DebugAdapterDescriptor>> {
		const logger = this.outputChannel;
		logger.debug(`Config: ${JSON.stringify(configuration)}`);
		if (configuration.port) {
			const host = configuration.host ?? '127.0.0.1';
			logger.info(`Connecting to DAP server at ${host}:${configuration.port}`);
			return new vscode.DebugAdapterServer(configuration.port, host);
		}
		const d = new DelveDAPOutputAdapter(configuration, logger);
		return new vscode.DebugAdapterInlineImplementation(d);
	}
}

class GoDebugAdapterTrackerFactory implements vscode.DebugAdapterTrackerFactory {
	constructor(private outputChannel: vscode.LogOutputChannel) {}

	createDebugAdapterTracker(session: vscode.DebugSession) {
		const logger = this.outputChannel;
		let requestsSent = 0;
		let responsesReceived = 0;
		return {
			onWillStartSession: () =>
				logger.debug(`session ${session.id} will start with ${JSON.stringify(session.configuration)}`),
			onWillReceiveMessage: (message: any) => {
				logger.trace(`client -> ${JSON.stringify(message)}`);
				requestsSent++;
			},
			onDidSendMessage: (message: any) => {
				logger.trace(`client  <- ${JSON.stringify(message)}`);
				responsesReceived++;
			},
			onError: (error: Error) => logger.error(`error: ${error}`),
			onWillStopSession: () => {
				if (
					session.configuration.debugAdapter === 'dlv-dap' &&
					session.configuration.mode === 'remote' &&
					requestsSent > 0 &&
					responsesReceived === 0 // happens when the rpc server doesn't understand DAP
				) {
					const err =
						'Expected to connect to external `dlv --headless` server @ v1.7.3 or later via DAP. Older versions fail with "error layer=rpc rpc:invalid character \'C\' looking for beginning of value" logged to the terminal.\n';
					logger.warn(err);
					vscode.window.showErrorMessage(err);
				}
				logger.debug(`session ${session.id} will stop\n`);
			},
			onExit: (code: number | undefined, signal: string | undefined) =>
				logger.info(`debug adapter exited: (code: ${code}, signal: ${signal})`)
		};
	}

	dispose() {}
}

const TWO_CRLF = '\r\n\r\n';

type ILogger = Pick<vscode.LogOutputChannel, 'error' | 'info' | 'debug' | 'trace'>;

// Proxies DebugProtocolMessage exchanges between VSCode and a remote
// process or server connected through a duplex stream, after its
// start method is called.
export class ProxyDebugAdapter implements vscode.DebugAdapter {
	private messageEmitter = new vscode.EventEmitter<vscode.DebugProtocolMessage>();
	// connection from/to server (= dlv dap)
	private readable?: stream.Readable;
	private writable?: stream.Writable;
	protected logger: ILogger;
	private terminated = false;

	constructor(logger: ILogger) {
		this.logger = logger;
		this.onDidSendMessage = this.messageEmitter.event;
	}

	// Implement vscode.DebugAdapter (VSCodeDebugAdapter) interface.
	// Client will call handleMessage to send messages, and
	// listen on onDidSendMessage to receive messages.
	onDidSendMessage: vscode.Event<vscode.DebugProtocolMessage>;
	async handleMessage(message: vscode.DebugProtocolMessage): Promise<void> {
		await this.sendMessageToServer(message);
	}

	// Methods for proxying.
	protected sendMessageToClient(msg: vscode.DebugProtocolMessage) {
		this.messageEmitter.fire(msg);
	}
	protected sendMessageToServer(message: vscode.DebugProtocolMessage): void {
		const json = JSON.stringify(message) ?? '';
		if (this.writable) {
			this.writable.write(
				`Content-Length: ${Buffer.byteLength(json, 'utf8')}${TWO_CRLF}${json}`,
				'utf8',
				(err) => {
					if (err) {
						this.logger?.error(`error sending message: ${err}`);
						this.sendMessageToClient(new TerminatedEvent());
					}
				}
			);
		} else {
			this.logger?.error(`stream is closed; dropping ${json}`);
		}
	}

	public async start(readable: stream.Readable, writable: stream.Writable) {
		if (this.readable || this.writable) {
			throw new Error('start was called more than once');
		}
		this.readable = readable;
		this.writable = writable;
		this.readable.on('data', (data: Buffer) => {
			this.handleDataFromServer(data);
		});
		this.readable.once('close', () => {
			this.readable = undefined;
		});
		this.readable.on('error', (err) => {
			if (this.terminated) {
				return;
			}
			this.terminated = true;

			if (err) {
				this.logger?.error(`connection error: ${err}`);
				this.sendMessageToClient(new OutputEvent(`connection error: ${err}\n`, 'console'));
			}
			this.sendMessageToClient(new TerminatedEvent());
		});
	}

	async dispose() {
		this.writable?.end(); // no more write.
	}

	private rawData = Buffer.alloc(0);
	private contentLength = -1;
	// Implements parsing of the DAP protocol. We cannot use ProtocolClient
	// from the vscode-debugadapter package, because it's not exported and
	// is not meant for external usage.
	// See https://github.com/microsoft/vscode-debugadapter-node/issues/232
	private handleDataFromServer(data: Buffer): void {
		this.rawData = Buffer.concat([this.rawData, data]);

		// eslint-disable-next-line no-constant-condition
		while (true) {
			if (this.contentLength >= 0) {
				if (this.rawData.length >= this.contentLength) {
					const message = this.rawData.toString('utf8', 0, this.contentLength);
					this.rawData = this.rawData.slice(this.contentLength);
					this.contentLength = -1;
					if (message.length > 0) {
						const rawMessage = JSON.parse(message);
						this.sendMessageToClient(rawMessage);
					}
					continue; // there may be more complete messages to process
				}
			} else {
				const idx = this.rawData.indexOf(TWO_CRLF);
				if (idx !== -1) {
					const header = this.rawData.toString('utf8', 0, idx);
					const lines = header.split('\r\n');
					for (const line of lines) {
						const pair = line.split(/: +/);
						if (pair[0] === 'Content-Length') {
							this.contentLength = +pair[1];
						}
					}
					this.rawData = this.rawData.slice(idx + TWO_CRLF.length);
					continue;
				}
			}
			break;
		}
	}
}

// DelveDAPOutputAdapter is a ProxyDebugAdapter that proxies between
// VSCode and a dlv dap process spawned and managed by this adapter.
// It turns the process's stdout/stderrr into OutputEvent.
export class DelveDAPOutputAdapter extends ProxyDebugAdapter {
	constructor(private configuration: vscode.DebugConfiguration, logger: ILogger) {
		super(logger);
	}

	private connected?: Promise<{ connected: boolean; reason?: any }>;
	private dlvDapServer?: ChildProcess;
	private socket?: net.Socket;
	private terminatedOnError = false;

	protected sendMessageToClient(message: vscode.DebugProtocolMessage) {
		const m = message as any;
		if (m.type === 'request') {
			this.logger.debug(`do not forward reverse request: dropping ${JSON.stringify(m)}`);
			return;
		}

		super.sendMessageToClient(message);
	}

	protected async sendMessageToServer(message: vscode.DebugProtocolMessage): Promise<void> {
		const m = message as any;
		if (m.type === 'response') {
			this.logger.debug(`do not forward reverse request response: dropping ${JSON.stringify(m)}`);
			return;
		}

		if (!this.connected) {
			if (m.type === 'request' && m.command === 'initialize') {
				this.connected = this.launchDelveDAP();
			} else {
				this.connected = Promise.resolve({
					connected: false,
					reason: `the first message must be an initialize request, got ${JSON.stringify(m)}`
				});
			}
		}
		const { connected, reason } = await this.connected;
		if (connected) {
			super.sendMessageToServer(message);
			return;
		}
		const errMsg = `Couldn't start dlv dap:\n${reason}`;
		if (this.terminatedOnError) {
			this.terminatedOnError = true;
			this.outputEvent('stderr', errMsg);
			this.sendMessageToClient(new TerminatedEvent());
		}
		if (m.type === 'request') {
			const req = message as DebugProtocol.Request;
			this.sendMessageToClient({
				seq: 0,
				type: 'response',
				request_seq: req.seq,
				success: false,
				command: req.command,
				message: errMsg
			});
		}
	}

	async dispose(timeoutMS?: number) {
		// NOTE: OutputEvents from here may not show up in DEBUG CONSOLE
		// because the debug session is terminating.
		await super.dispose();
		if (!this.dlvDapServer) {
			return;
		}
		if (this.connected === undefined) {
			return;
		}
		this.connected = undefined;

		const dlvDapServer = this.dlvDapServer;
		this.dlvDapServer = undefined;
		if (!dlvDapServer) {
			return;
		}
		if (dlvDapServer.exitCode !== null) {
			this.logger?.info(
				`dlv dap process(${dlvDapServer.pid}) already exited (exit code: ${dlvDapServer.exitCode})`
			);
			return;
		}
		await new Promise<void>((resolve) => {
			if (timeoutMS === undefined || timeoutMS < 0) {
				timeoutMS = 1_000;
			}
			const exitTimeoutToken = setTimeout(() => {
				this.logger?.error(`dlv dap process (${dlvDapServer.pid}) isn't responding. Killing...`);
				dlvDapServer.kill('SIGINT'); // Don't use treekill but let dlv handle cleaning up the child processes.
			}, timeoutMS);
			dlvDapServer.on('exit', (code, signal) => {
				clearTimeout(exitTimeoutToken);
				if (code || signal) {
					this.logger?.error(
						`dlv dap process(${dlvDapServer.pid}) exited (exit code: ${code} signal: ${signal})`
					);
				}
				resolve();
			});
		});
	}

	private async launchDelveDAP() {
		try {
			const { dlvDapServer, socket } = await this.startDapServer(this.configuration);

			this.dlvDapServer = dlvDapServer;
			this.socket = socket;
			this.start(this.socket, this.socket);
		} catch (err) {
			return { connected: false, reason: err };
		}
		this.logger?.debug(`Running dlv dap server: pid=${this.dlvDapServer?.pid}`);
		return { connected: true };
	}

	protected outputEvent(dest: string, output: string, data?: any) {
		this.sendMessageToClient(new OutputEvent(output, dest, data));
	}

	async startDapServer(
		configuration: vscode.DebugConfiguration
	): Promise<{ dlvDapServer?: ChildProcess; socket: net.Socket }> {
		const log = (msg: string) => this.outputEvent('stdout', msg);
		const logErr = (msg: string) => this.outputEvent('stderr', msg);
		const logConsole = (msg: string) => {
			this.outputEvent('console', msg);
			// Some log messages generated after vscode stops the debug session
			// may not appear in the DEBUG CONSOLE. For easier debugging, log
			// the messages through the logger that prints to Go Debug output
			// channel.
			this.logger?.trace(msg);
		};

		// If a port has been specified, assume there is an already
		// running dap server to connect to. Otherwise, we start the dlv dap server.
		const dlvExternallyLaunched = !!configuration.port;

		if (
			!dlvExternallyLaunched &&
			(configuration.console === 'integratedTerminal' || configuration.console === 'externalTerminal')
		) {
			return this.startDAPServerWithClientAddrFlag(configuration, logErr);
		}
		const host = configuration.host || '127.0.0.1';
		const port = configuration.port || (await getPort());

		const dlvDapServer = dlvExternallyLaunched
			? undefined
			: await spawnDlvDapServerProcess(configuration, host, port, log, logErr, logConsole);

		const socket = await new Promise<net.Socket>((resolve, reject) => {
			// eslint-disable-next-line prefer-const
			let timer: NodeJS.Timeout;
			const s = net.createConnection(port, host, () => {
				clearTimeout(timer);
				resolve(s);
			});
			timer = setTimeout(() => {
				reject('connection timeout');
				s?.destroy();
			}, 1000);
		});

		return { dlvDapServer, socket };
	}

	async startDAPServerWithClientAddrFlag(
		launchAttachArgs: vscode.DebugConfiguration,
		logErr: (msg: string) => void
	): Promise<{ dlvDapServer?: ChildProcessWithoutNullStreams; socket: net.Socket }> {
		// This is called only when launchAttachArgs.console === 'integratedTerminal' | 'externalTerminal' currently.
		const console = (launchAttachArgs as any).console === 'externalTerminal' ? 'external' : 'integrated';

		const { dlvArgs, dlvPath, dir, env } = getSpawnConfig(launchAttachArgs, logErr);

		// logDest - unlike startDAPServer that relies on piping log messages to a file descriptor
		// using --log-dest, we can pass the user-specified logDest directly to the flag.
		const logDest = launchAttachArgs.logDest;
		if (logDest) {
			dlvArgs.push(`--log-dest=${logDest}`);
		}

		dlvArgs.unshift(dlvPath);

		if (launchAttachArgs.asRoot === true && process.platform !== 'win32') {
			const sudo = getSudo();
			if (sudo) {
				dlvArgs.unshift(sudo);
			} else {
				throw new Error('Failed to find "sudo" utility');
			}
		}

		try {
			const port = await getPort();
			const rendezvousServerPromise = waitForDAPServer(port, 30_000, this.logger);

			dlvArgs.push(`--client-addr=:${port}`);

			super.sendMessageToClient({
				seq: 0,
				type: 'request',
				command: 'runInTerminal',
				arguments: {
					kind: console,
					title: `Go Debug Terminal (${launchAttachArgs.name})`,
					cwd: dir,
					args: dlvArgs,
					env: env
				}
			});
			const socket = await rendezvousServerPromise;
			return { socket };
		} catch (err) {
			logErr(`Failed to launch dlv: ${err}`);
			throw new Error('cannot launch dlv dap. See DEBUG CONSOLE');
		}
	}
}

let sudoPath: string | null | undefined = undefined;
function getSudo(): string | null {
	if (sudoPath === undefined) {
		sudoPath = getBinPathFromEnvVar('sudo', getEnvPath(), false);
	}
	return sudoPath;
}

function waitForDAPServer(port: number, timeoutMs: number, logger: ILogger): Promise<net.Socket> {
	return new Promise((resolve, reject) => {
		// eslint-disable-next-line prefer-const
		let s: net.Server | undefined;
		const timeoutToken = setTimeout(() => {
			if (s?.listening) {
				s.close();
			}
			reject(new Error('timed out while waiting for DAP in reverse mode to connect'));
		}, timeoutMs);

		s = net.createServer({ pauseOnConnect: true }, (socket) => {
			logger.debug(
				`connected: ${port} (remote: ${socket.remoteAddress}:${socket.remotePort} local: ${socket.localAddress}:${socket.localPort})`
			);
			clearTimeout(timeoutToken);
			s?.close(); // accept no more connection
			socket.resume();
			resolve(socket);
		});
		s.on('error', (err) => {
			logger.error(`connection error ${err}`);
			reject(err);
		});
		s.maxConnections = 1;
		s.listen(port);
	});
}

function spawnDlvDapServerProcess(
	launchAttachArgs: vscode.DebugConfiguration,
	host: string,
	port: number,
	log: (msg: string) => void,
	logErr: (msg: string) => void,
	logConsole: (msg: string) => void
): Promise<ChildProcess> {
	const { dlvArgs, dlvPath, dir, env } = getSpawnConfig(launchAttachArgs, logErr);
	// env does not include process.env. Construct the new env for process spawning
	// by combining process.env.
	const envForSpawn = env ? Object.assign({}, process.env, env) : undefined;

	dlvArgs.push(`--listen=${host}:${port}`);

	const onWindows = process.platform === 'win32';

	if (!onWindows) {
		dlvArgs.push('--log-dest=3');
	}

	const logDest = launchAttachArgs.logDest;
	if (typeof logDest === 'number') {
		logErr(`Using a file descriptor for 'logDest' (${logDest}) is not allowed.\n`);
		throw new Error('Using a file descriptor for `logDest` is not allowed.');
	}
	if (logDest && !path.isAbsolute(logDest)) {
		logErr(
			`Using a relative path for 'logDest' (${logDest}) is not allowed.\nSee https://code.visualstudio.com/docs/editor/variables-reference if you want workspace-relative path.\n`
		);
		throw new Error('Using a relative path for `logDest` is not allowed');
	}
	if (logDest && onWindows) {
		logErr(
			'Using `logDest` or `--log-dest` is not supported on windows yet. See https://github.com/golang/vscode-go/issues/1472.'
		);
		throw new Error('Using `logDest` on windows is not allowed');
	}

	const logDestStream = logDest ? fs.createWriteStream(logDest) : undefined;

	logConsole(`Starting: ${dlvPath} ${dlvArgs.join(' ')} from ${dir}\n`);

	// TODO(hyangah): In module-module workspace mode, the program should be build in the super module directory
	// where go.work (gopls.mod) file is present. Where dlv runs determines the build directory currently. Two options:
	//  1) launch dlv in the super-module module directory and adjust launchArgs.cwd (--wd).
	//  2) introduce a new buildDir launch attribute.
	return new Promise<ChildProcess>((resolve, reject) => {
		const p = spawn(dlvPath, dlvArgs, {
			cwd: dir,
			env: envForSpawn,
			stdio: onWindows ? ['pipe', 'pipe', 'pipe'] : ['pipe', 'pipe', 'pipe', 'pipe'] // --log-dest=3 if !onWindows.
		});
		let started = false;
		const timeoutToken: NodeJS.Timer = setTimeout(() => {
			logConsole(`Delve DAP server (PID: ${p.pid}) is not responding`);
			reject(new Error('timed out while waiting for DAP server to start'));
		}, 30_000);

		const stopWaitingForServerToStart = () => {
			clearTimeout(timeoutToken);
			started = true;
			resolve(p);
		};

		p.stdout.on('data', (chunk) => {
			const msg = chunk.toString();
			if (!started && msg.startsWith('DAP server listening at:')) {
				stopWaitingForServerToStart();
			}
			log(msg);
		});
		p.stderr.on('data', (chunk) => {
			logErr(chunk.toString());
		});
		p.stdio[3]?.on('data', (chunk) => {
			const msg = chunk.toString();
			if (!started && msg.startsWith('DAP server listening at:')) {
				stopWaitingForServerToStart();
			}
			if (logDestStream) {
				// always false on windows.
				// write to the specified file.
				logDestStream?.write(chunk, (err) => {
					if (err) {
						logConsole(`Error writing to ${logDest}: ${err}, log may be incomplete.`);
					}
				});
			} else {
				logConsole(msg);
			}
		});
		p.stdio[3]?.on('close', () => {
			// always false on windows.
			logDestStream?.end();
		});

		p.on('close', (code, signal) => {
			// TODO: should we watch 'exit' instead?

			// NOTE: log messages here may not appear in DEBUG CONSOLE if the termination of
			// the process was triggered by debug adapter's dispose when dlv dap doesn't
			// respond to disconnect on time. In that case, it's possible that the session
			// is in the middle of teardown and DEBUG CONSOLE isn't accessible. Check
			// Go Debug output channel.
			if (typeof code === 'number') {
				// The process exited on its own.
				logConsole(`dlv dap (${p.pid}) exited with code: ${code}\n`);
			} else if (code === null && signal) {
				logConsole(`dlv dap (${p.pid}) was killed by signal: ${signal}\n`);
			} else {
				logConsole(`dlv dap (${p.pid}) terminated with code: ${code} signal: ${signal}\n`);
			}
		});
		p.on('error', (err) => {
			if (err) {
				logConsole(`Error: ${err}\n`);
			}
		});
	});
}

// getSpawnConfig returns the dlv args, directory, and dlv path necessary to spawn the dlv command.
// It also returns `env` that is the additional environment variables users want to run the dlv
// and the debuggee (i.e., go.toolsEnvVars, launch configuration's env and envFile) with.
function getSpawnConfig(launchAttachArgs: vscode.DebugConfiguration, logErr: (msg: string) => void) {
	// launchArgsEnv is user-requested env vars (envFiles + env + toolsEnvVars).
	const env = launchAttachArgs.env;
	const dlvPath = launchAttachArgs.dlvToolPath ?? 'dlv';

	if (!fs.existsSync(dlvPath)) {
		const envPath = getEnvPath();
		logErr(
			`Couldn't find ${dlvPath} at the Go tools path, ${process.env['GOPATH']}${
				env['GOPATH'] ? ', ' + env['GOPATH'] : ''
			} or ${envPath}\n` +
				'Follow the setup instruction in https://github.com/golang/vscode-go/blob/master/docs/debugging.md#getting-started.\n'
		);
		throw new Error('Cannot find Delve debugger (dlv dap)');
	}
	let dir = getWorkspaceFolderPath();
	if (launchAttachArgs.request === 'launch' && launchAttachArgs['__buildDir']) {
		// __buildDir is the directory determined during resolving debug config
		dir = launchAttachArgs['__buildDir'];
	}

	const dlvArgs = new Array<string>();
	dlvArgs.push('dap');

	// When duplicate flags are specified,
	// dlv doesn't mind but accepts the last flag value.
	if (launchAttachArgs.dlvFlags && launchAttachArgs.dlvFlags.length > 0) {
		dlvArgs.push(...launchAttachArgs.dlvFlags);
	}
	if (launchAttachArgs.showLog) {
		dlvArgs.push('--log=' + launchAttachArgs.showLog.toString());
		// Only add the log output flag if we have already added the log flag.
		// Otherwise, delve complains.
		if (launchAttachArgs.logOutput) {
			dlvArgs.push('--log-output=' + launchAttachArgs.logOutput);
		}
	}
	return { dlvArgs, dlvPath, dir, env };
}

// toggleHideSystemGoroutineCustomRequest is a helper function extracted
// for testing the command.
export async function toggleHideSystemGoroutinesCustomRequest(
	// eslint-disable-next-line @typescript-eslint/no-explicit-any
	cr: (command: string, args?: any) => Thenable<any>
) {
	const debugConsole = vscode.debug.activeDebugConsole;
	try {
		const response = await cr('evaluate', {
			expression: 'dlv config -list hideSystemGoroutines',
			context: 'context'
		});
		let update = 'false';
		if (response?.result?.indexOf('false') >= 0) {
			update = 'true';
		}
		await cr('evaluate', {
			expression: `dlv config hideSystemGoroutines ${update}`,
			context: 'context'
		});
	} catch (err) {
		if (err instanceof Error && err.message.indexOf('debuggee is running') >= 0) {
			debugConsole.appendLine('Cannot toggle hideSystemGoroutines while debuggee is running');
			return;
		}
		debugConsole.appendLine(`Error toggling hideSystemGoroutines: ${err}`);
	}
}

const toggleHideSystemGoroutines = () => {
	const ds = vscode.debug.activeDebugSession;
	if (ds) {
		toggleHideSystemGoroutinesCustomRequest((command, args) => {
			return ds.customRequest(command, args);
		});
	}
};
