/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-case-declarations */
/* eslint-disable eqeqeq */
/* eslint-disable no-useless-escape */
/* eslint-disable no-async-promise-executor */
/* eslint-disable @typescript-eslint/no-explicit-any */
/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

import { ChildProcess, execFile, spawn, spawnSync } from 'child_process';
import { EventEmitter } from 'events';
import * as fs from 'fs';
import { existsSync, lstatSync } from 'fs';
import * as glob from 'glob';
import { Client, RPCConnection } from 'json-rpc2';
import * as os from 'os';
import * as path from 'path';
import * as util from 'util';
import {
	ContinuedEvent,
	DebugSession,
	ErrorDestination,
	Handles,
	InitializedEvent,
	logger,
	Logger,
	LoggingDebugSession,
	OutputEvent,
	Scope,
	Source,
	StackFrame,
	StoppedEvent,
	TerminatedEvent,
	Thread
} from 'vscode-debugadapter';
import { DebugProtocol } from 'vscode-debugprotocol';
import { parseEnvFiles } from '../utils/envUtils';
import {
	correctBinname,
	envPath,
	expandFilePathInOutput,
	fixDriveCasingInWindows,
	getBinPathWithPreferredGopathGoroot,
	getCurrentGoWorkspaceFromGOPATH,
	getInferredGopath
} from '../utils/pathUtils';
import { killProcessTree } from '../utils/processUtils';

const fsAccess = util.promisify(fs.access);
const fsUnlink = util.promisify(fs.unlink);

// This enum should stay in sync with https://golang.org/pkg/reflect/#Kind

enum GoReflectKind {
	Invalid = 0,
	Bool,
	Int,
	Int8,
	Int16,
	Int32,
	Int64,
	Uint,
	Uint8,
	Uint16,
	Uint32,
	Uint64,
	Uintptr,
	Float32,
	Float64,
	Complex64,
	Complex128,
	Array,
	Chan,
	Func,
	Interface,
	Map,
	Ptr,
	Slice,
	String,
	Struct,
	UnsafePointer
}

// These types should stay in sync with:
// https://github.com/go-delve/delve/blob/master/service/api/types.go

interface CommandOut {
	State: DebuggerState;
}

interface DebuggerState {
	exited: boolean;
	exitStatus: number;
	currentThread: DebugThread;
	currentGoroutine: DebugGoroutine;
	Running: boolean;
	Threads: DebugThread[];
	NextInProgress: boolean;
}

export interface PackageBuildInfo {
	ImportPath: string;
	DirectoryPath: string;
	Files: string[];
}

export interface ListPackagesBuildInfoOut {
	List: PackageBuildInfo[];
}

export interface ListSourcesOut {
	Sources: string[];
}

interface CreateBreakpointOut {
	Breakpoint: DebugBreakpoint;
}

interface GetVersionOut {
	DelveVersion: string;
	APIVersion: number;
}

interface DebugBreakpoint {
	addr: number;
	continue: boolean;
	file: string;
	functionName?: string;
	goroutine: boolean;
	id: number;
	name: string;
	line: number;
	stacktrace: number;
	variables?: DebugVariable[];
	loadArgs?: LoadConfig;
	loadLocals?: LoadConfig;
	cond?: string;
}

interface LoadConfig {
	// FollowPointers requests pointers to be automatically dereferenced.
	followPointers: boolean;
	// MaxVariableRecurse is how far to recurse when evaluating nested types.
	maxVariableRecurse: number;
	// MaxStringLen is the maximum number of bytes read from a string
	maxStringLen: number;
	// MaxArrayValues is the maximum number of elements read from an array, a slice or a map.
	maxArrayValues: number;
	// MaxStructFields is the maximum number of fields read from a struct, -1 will read all fields.
	maxStructFields: number;
}

interface DebugThread {
	file: string;
	id: number;
	line: number;
	pc: number;
	goroutineID: number;
	breakPoint: DebugBreakpoint;
	breakPointInfo: {};
	function?: DebugFunction;
	ReturnValues: DebugVariable[];
}

interface StacktraceOut {
	Locations: DebugLocation[];
}

interface DebugLocation {
	pc: number;
	file: string;
	line: number;
	function: DebugFunction;
}

interface DebugFunction {
	name: string;
	value: number;
	type: number;
	goType: number;
	args: DebugVariable[];
	locals: DebugVariable[];
	optimized: boolean;
}

interface ListVarsOut {
	Variables: DebugVariable[];
}

interface ListFunctionArgsOut {
	Args: DebugVariable[];
}

interface EvalOut {
	Variable: DebugVariable;
}

enum GoVariableFlags {
	VariableEscaped = 1,
	VariableShadowed = 2,
	VariableConstant = 4,
	VariableArgument = 8,
	VariableReturnArgument = 16,
	VariableFakeAddress = 32
}

interface DebugVariable {
	// DebugVariable corresponds to api.Variable in Delve API.
	// https://github.com/go-delve/delve/blob/328cf87808822693dc611591519689dcd42696a3/service/api/types.go#L239-L284
	name: string;
	addr: number;
	type: string;
	realType: string;
	kind: GoReflectKind;
	flags: GoVariableFlags;
	onlyAddr: boolean;
	DeclLine: number;
	value: string;
	len: number;
	cap: number;
	children: DebugVariable[];
	unreadable: string;
	fullyQualifiedName: string;
	base: number;
}

interface ListGoroutinesOut {
	Goroutines: DebugGoroutine[];
}

interface DebugGoroutine {
	id: number;
	currentLoc: DebugLocation;
	userCurrentLoc: DebugLocation;
	goStatementLoc: DebugLocation;
}

interface DebuggerCommand {
	name: string;
	threadID?: number;
	goroutineID?: number;
}

interface ListBreakpointsOut {
	Breakpoints: DebugBreakpoint[];
}

interface RestartOut {
	DiscardedBreakpoints: DiscardedBreakpoint[];
}

interface DiscardedBreakpoint {
	breakpoint: DebugBreakpoint;
	reason: string;
}

// Unrecovered panic and fatal throw breakpoint IDs taken from delve:
// https://github.com/go-delve/delve/blob/f90134eb4db1c423e24fddfbc6eff41b288e6297/pkg/proc/breakpoints.go#L11-L21
// UnrecoveredPanic is the name given to the unrecovered panic breakpoint.
const unrecoveredPanicID = -1;
// FatalThrow is the name given to the breakpoint triggered when the target
// process dies because of a fatal runtime error.
const fatalThrowID = -2;

// This interface should always match the schema found in `package.json`.
interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
	request: 'launch';
	[key: string]: any;
	program: string;
	stopOnEntry?: boolean;
	dlvFlags?: string[];
	args?: string[];
	showLog?: boolean;
	logOutput?: string;
	cwd?: string;
	env?: { [key: string]: string };
	mode?: 'auto' | 'debug' | 'remote' | 'test' | 'exec';
	remotePath?: string;
	port?: number;
	host?: string;
	buildFlags?: string;
	init?: string;
	// trace, info, warn are to match goLogging.
	// In practice, this adapter handles only verbose, log, and error
	//  verbose === trace,
	//  log === info === warn,
	//  error
	trace?: 'verbose' | 'trace' | 'info' | 'log' | 'warn' | 'error';
	backend?: string;
	output?: string;
	substitutePath?: { from: string; to: string }[];
	/** Delve LoadConfig parameters */
	dlvLoadConfig?: LoadConfig;
	dlvToolPath: string;
	/** Delve Version */
	apiVersion: number;
	/** Delve maximum stack trace depth */
	stackTraceDepth: number;

	showGlobalVariables?: boolean;
	packagePathToGoModPathMap: { [key: string]: string };

	/** Optional path to .env file. */
	// TODO: deprecate .env file processing from DA.
	// We expect the extension processes .env files
	// and send the information to DA using the 'env' property.
	envFile?: string | string[];
}

interface AttachRequestArguments extends DebugProtocol.AttachRequestArguments {
	request: 'attach';
	processId?: number;
	stopOnEntry?: boolean;
	dlvFlags?: string[];
	showLog?: boolean;
	logOutput?: string;
	cwd?: string;
	mode?: 'local' | 'remote';
	remotePath?: string;
	port?: number;
	host?: string;
	trace?: 'verbose' | 'trace' | 'info' | 'log' | 'warn' | 'error';
	backend?: string;
	substitutePath?: { from: string; to: string }[];
	/** Delve LoadConfig parameters */
	dlvLoadConfig?: LoadConfig;
	dlvToolPath: string;
	/** Delve Version */
	apiVersion: number;
	/** Delve maximum stack trace depth */
	stackTraceDepth: number;

	showGlobalVariables?: boolean;
}

process.on('uncaughtException', (err: any) => {
	const errMessage = err && (err.stack || err.message);
	logger.error(`Unhandled error in debug adapter: ${errMessage}`);
	throw err;
});

function logArgsToString(args: any[]): string {
	return args
		.map((arg) => {
			return typeof arg === 'string' ? arg : JSON.stringify(arg);
		})
		.join(' ');
}

function log(...args: any[]) {
	logger.warn(logArgsToString(args));
}

function logError(...args: any[]) {
	logger.error(logArgsToString(args));
}

export function findPathSeparator(filePath: string) {
	return filePath && filePath.includes('\\') ? '\\' : '/';
}

// Comparing two different file paths while ignoring any different path separators.
function compareFilePathIgnoreSeparator(firstFilePath: string, secondFilePath: string): boolean {
	const firstSeparator = findPathSeparator(firstFilePath);
	const secondSeparator = findPathSeparator(secondFilePath);
	if (firstSeparator === secondSeparator) {
		return firstFilePath === secondFilePath;
	}
	return firstFilePath === secondFilePath.split(secondSeparator).join(firstSeparator);
}

export function escapeGoModPath(filePath: string) {
	return filePath.replace(/[A-Z]/g, (match: string) => `!${match.toLocaleLowerCase()}`);
}

function normalizePath(filePath: string) {
	if (process.platform === 'win32') {
		const pathSeparator = findPathSeparator(filePath);
		filePath = path.normalize(filePath);
		// Normalize will replace everything with backslash on Windows.
		filePath = filePath.replace(/\\/g, pathSeparator);
		return fixDriveCasingInWindows(filePath);
	}
	return filePath;
}

// normalizeSeparators will prepare the filepath for comparison in mapping from
// local to debugger path and from debugger path to local path. All separators are
// replaced with '/', and the drive name is capitalized for windows paths.
// Exported for testing
export function normalizeSeparators(filePath: string): string {
	// Although the current machine may not be running windows,
	// the remote machine may be and we need to fix the drive
	// casing.
	// This is a workaround for issue in https://github.com/Microsoft/vscode/issues/9448#issuecomment-244804026
	if (filePath.indexOf(':') === 1) {
		filePath = filePath.substr(0, 1).toUpperCase() + filePath.substr(1);
	}
	return filePath.replace(/\/|\\/g, '/');
}

function getBaseName(filePath: string) {
	return filePath.includes('/') ? path.basename(filePath) : path.win32.basename(filePath);
}

export class Delve {
	public program: string;
	public remotePath: string;
	public loadConfig: LoadConfig;
	public connection: Promise<RPCConnection | null>; // null if connection isn't necessary (e.g. noDebug mode)
	public onstdout: (str: string) => void;
	public onstderr: (str: string) => void;
	public onclose: (code: number) => void;
	public noDebug: boolean;
	public isApiV1: boolean;
	public dlvEnv: any;
	public stackTraceDepth: number;
	public isRemoteDebugging: boolean;
	public goroot: string;
	public delveConnectionClosed = false;
	private localDebugeePath: string | undefined;
	private debugProcess: ChildProcess;
	private request: 'attach' | 'launch';

	constructor(launchArgs: LaunchRequestArguments | AttachRequestArguments, program: string) {
		this.request = launchArgs.request;
		this.program = normalizePath(program);
		this.remotePath = launchArgs.remotePath;
		this.isApiV1 = false;
		if (typeof launchArgs.apiVersion === 'number') {
			this.isApiV1 = launchArgs.apiVersion === 1;
		}
		this.stackTraceDepth = typeof launchArgs.stackTraceDepth === 'number' ? launchArgs.stackTraceDepth : 50;
		this.connection = new Promise(async (resolve, reject) => {
			const mode = launchArgs.mode;
			let dlvCwd = path.dirname(program);
			let serverRunning = false;
			const dlvArgs = new Array<string>();

			// Get default LoadConfig values according to delve API:
			// https://github.com/go-delve/delve/blob/c5c41f635244a22d93771def1c31cf1e0e9a2e63/service/rpc1/server.go#L13
			// https://github.com/go-delve/delve/blob/c5c41f635244a22d93771def1c31cf1e0e9a2e63/service/rpc2/server.go#L423
			this.loadConfig = launchArgs.dlvLoadConfig || {
				followPointers: true,
				maxVariableRecurse: 1,
				maxStringLen: 64,
				maxArrayValues: 64,
				maxStructFields: -1
			};

			if (mode === 'remote') {
				log(`Start remote debugging: connecting ${launchArgs.host}:${launchArgs.port}`);
				this.debugProcess = null;
				this.isRemoteDebugging = true;
				this.goroot = await queryGOROOT(dlvCwd, process.env);
				serverRunning = true; // assume server is running when in remote mode
				connectClient(launchArgs.port, launchArgs.host, this.onclose);
				return;
			}
			this.isRemoteDebugging = false;
			let env: NodeJS.ProcessEnv;
			if (launchArgs.request === 'launch') {
				let isProgramDirectory = false;
				// Validations on the program
				if (!program) {
					return reject('The program attribute is missing in the debug configuration in launch.json');
				}
				try {
					const pstats = lstatSync(program);
					if (pstats.isDirectory()) {
						if (mode === 'exec') {
							logError(`The program "${program}" must not be a directory in exec mode`);
							return reject('The program attribute must be an executable in exec mode');
						}
						dlvCwd = program;
						isProgramDirectory = true;
					} else if (mode !== 'exec' && path.extname(program) !== '.go') {
						logError(`The program "${program}" must be a valid go file in debug mode`);
						return reject('The program attribute must be a directory or .go file in debug mode');
					}
				} catch (e) {
					logError(`The program "${program}" does not exist: ${e}`);
					return reject('The program attribute must point to valid directory, .go file or executable.');
				}

				// read env from disk and merge into env variables
				try {
					const fileEnvs = parseEnvFiles(launchArgs.envFile);
					const launchArgsEnv = launchArgs.env || {};
					env = Object.assign({}, process.env, fileEnvs, launchArgsEnv);
				} catch (e) {
					return reject(`failed to process 'envFile' and 'env' settings: ${e}`);
				}

				const dirname = isProgramDirectory ? program : path.dirname(program);
				if (!env['GOPATH'] && (mode === 'debug' || mode === 'test')) {
					// If no GOPATH is set, then infer it from the file/package path
					// Not applicable to exec mode in which case `program` need not point to source code under GOPATH
					env['GOPATH'] = getInferredGopath(dirname) || env['GOPATH'];
				}
				this.dlvEnv = env;
				this.goroot = await queryGOROOT(dlvCwd, env);

				log(`Using GOPATH: ${env['GOPATH']}`);
				log(`Using GOROOT: ${this.goroot}`);
				log(`Using PATH: ${env['PATH']}`);
				if (launchArgs.noDebug) {
					if (mode === 'debug') {
						this.noDebug = true;
						const build = ['build'];
						const output = path.join(os.tmpdir(), correctBinname('out'));
						build.push(`-o=${output}`);

						const buildOptions: { [key: string]: any } = { cwd: dirname, env };
						if (launchArgs.buildFlags) {
							build.push(launchArgs.buildFlags);
						}

						if (isProgramDirectory) {
							build.push('.');
						} else {
							build.push(program);
						}

						const goExe = getBinPathWithPreferredGopathGoroot('go', []);
						log(`Current working directory: ${dirname}`);
						log(`Building: ${goExe} ${build.join(' ')}`);

						// Use spawnSync to ensure that the binary exists before running it.
						const buffer = spawnSync(goExe, build, buildOptions);
						if (buffer.stderr && buffer.stderr.length > 0) {
							const str = buffer.stderr.toString();
							if (this.onstderr) {
								this.onstderr(str);
							}
						}
						if (buffer.stdout && buffer.stdout.length > 0) {
							const str = buffer.stdout.toString();
							if (this.onstdout) {
								this.onstdout(str);
							}
						}
						if (buffer.status) {
							logError(`Build process exiting with code: ${buffer.status} signal: ${buffer.signal}`);
							if (this.onclose) {
								this.onclose(buffer.status);
							}
						} else {
							log(`Build process exiting normally ${buffer.signal}`);
						}
						if (buffer.error) {
							reject(buffer.error);
						}

						// Run the built binary
						let wd = dirname;
						if (launchArgs.cwd) {
							wd = launchArgs.cwd;
						}
						const runOptions: { [key: string]: any } = { cwd: wd, env };

						const run = [];
						if (launchArgs.args) {
							run.push(...launchArgs.args);
						}

						log(`Current working directory: ${wd}`);
						log(`Running: ${output} ${run.join(' ')}`);

						this.debugProcess = spawn(output, run, runOptions);
						this.debugProcess.stderr.on('data', (chunk) => {
							const str = chunk.toString();
							if (this.onstderr) {
								this.onstderr(str);
							}
						});
						this.debugProcess.stdout.on('data', (chunk) => {
							const str = chunk.toString();
							if (this.onstdout) {
								this.onstdout(str);
							}
						});
						this.debugProcess.on('close', (code) => {
							if (code) {
								logError(`Process exiting with code: ${code} signal: ${this.debugProcess.killed}`);
							} else {
								log(`Process exiting normally ${this.debugProcess.killed}`);
							}
							if (this.onclose) {
								this.onclose(code);
							}
						});
						this.debugProcess.on('error', (err) => {
							reject(err);
						});

						resolve(null);
						return;
					}
				}
				this.noDebug = false;

				if (!existsSync(launchArgs.dlvToolPath)) {
					log(
						`Couldn't find dlv at the Go tools path, ${process.env['GOPATH']}${
							env['GOPATH'] ? ', ' + env['GOPATH'] : ''
						} or ${envPath}`
					);
					return reject(
						'Cannot find Delve debugger. Install from https://github.com/go-delve/delve & ensure it is in your Go tools path, "GOPATH/bin" or "PATH".'
					);
				}

				const currentGOWorkspace = getCurrentGoWorkspaceFromGOPATH(env['GOPATH'], dirname);
				if (!launchArgs.packagePathToGoModPathMap) {
					launchArgs.packagePathToGoModPathMap = {};
				}
				dlvArgs.push(mode || 'debug');
				if (mode === 'exec' || (mode === 'debug' && !isProgramDirectory)) {
					dlvArgs.push(program);
				} else if (currentGOWorkspace && !launchArgs.packagePathToGoModPathMap[dirname]) {
					dlvArgs.push(dirname.substr(currentGOWorkspace.length + 1));
				}
				// add user-specified dlv flags first. When duplicate flags are specified,
				// dlv doesn't mind but accepts the last flag value.
				if (launchArgs.dlvFlags && launchArgs.dlvFlags.length > 0) {
					dlvArgs.push(...launchArgs.dlvFlags);
				}
				dlvArgs.push('--headless=true', `--listen=${launchArgs.host}:${launchArgs.port}`);
				if (!this.isApiV1) {
					dlvArgs.push('--api-version=2');
				}

				if (launchArgs.showLog) {
					dlvArgs.push('--log=' + launchArgs.showLog.toString());
					// Only add the log output flag if we have already added the log flag.
					// Otherwise, delve complains.
					if (launchArgs.logOutput) {
						dlvArgs.push('--log-output=' + launchArgs.logOutput);
					}
				}
				if (launchArgs.cwd) {
					dlvArgs.push('--wd=' + launchArgs.cwd);
				}
				if (launchArgs.buildFlags) {
					dlvArgs.push('--build-flags=' + launchArgs.buildFlags);
				}
				if (launchArgs.backend) {
					dlvArgs.push('--backend=' + launchArgs.backend);
				}
				if (launchArgs.output && (mode === 'debug' || mode === 'test')) {
					dlvArgs.push('--output=' + launchArgs.output);
				}
				if (launchArgs.args && launchArgs.args.length > 0) {
					dlvArgs.push('--', ...launchArgs.args);
				}
				this.localDebugeePath = this.getLocalDebugeePath(launchArgs.output);
			} else if (launchArgs.request === 'attach') {
				if (!launchArgs.processId) {
					return reject('Missing process ID');
				}

				if (!existsSync(launchArgs.dlvToolPath)) {
					return reject(
						'Cannot find Delve debugger. Install from https://github.com/go-delve/delve & ensure it is in your Go tools path, "GOPATH/bin" or "PATH".'
					);
				}

				dlvArgs.push('attach', `${launchArgs.processId}`);
				// add user-specified dlv flags first. When duplicate flags are specified,
				// dlv doesn't mind but accepts the last flag value.
				if (launchArgs.dlvFlags && launchArgs.dlvFlags.length > 0) {
					dlvArgs.push(...launchArgs.dlvFlags);
				}
				dlvArgs.push('--headless=true', '--listen=' + launchArgs.host + ':' + launchArgs.port.toString());
				if (!this.isApiV1) {
					dlvArgs.push('--api-version=2');
				}

				if (launchArgs.showLog) {
					dlvArgs.push('--log=' + launchArgs.showLog.toString());
				}
				if (launchArgs.logOutput) {
					dlvArgs.push('--log-output=' + launchArgs.logOutput);
				}
				if (launchArgs.cwd) {
					dlvArgs.push('--wd=' + launchArgs.cwd);
				}
				if (launchArgs.backend) {
					dlvArgs.push('--backend=' + launchArgs.backend);
				}
			}

			log(`Current working directory: ${dlvCwd}`);
			log(`Running: ${launchArgs.dlvToolPath} ${dlvArgs.join(' ')}`);

			this.debugProcess = spawn(launchArgs.dlvToolPath, dlvArgs, {
				cwd: dlvCwd,
				env
			});

			function connectClient(port: number, host: string, onClose?: Delve['onclose']) {
				// Add a slight delay to avoid issues on Linux with
				// Delve failing calls made shortly after connection.
				setTimeout(() => {
					const conn = Client.$create(port, host).connectSocket();

					conn.on('connect', () => resolve(conn))
						.on('error', reject)
						.on('close', (hadError) => {
							logError('Socket connection to remote was closed');
							onClose?.(hadError ? 1 : 0);
						});
				}, 200);
			}

			this.debugProcess.stderr.on('data', (chunk) => {
				const str = chunk.toString();
				if (this.onstderr) {
					this.onstderr(str);
				}
			});
			this.debugProcess.stdout.on('data', (chunk) => {
				const str = chunk.toString();
				if (this.onstdout) {
					this.onstdout(str);
				}
				if (!serverRunning) {
					serverRunning = true;
					connectClient(launchArgs.port, launchArgs.host, this.onclose);
				}
			});
			this.debugProcess.on('close', (code) => {
				// TODO: Report `dlv` crash to user.
				logError('Process exiting with code: ' + code);
				if (this.onclose) {
					this.onclose(code);
				}
			});
			this.debugProcess.on('error', (err) => {
				reject(err);
			});
		});
	}

	public call<T>(command: string, args: any[], callback: (err: Error, results: T) => void) {
		this.connection.then(
			(conn) => {
				conn.call('RPCServer.' + command, args, callback);
			},
			(err) => {
				callback(err, null);
			}
		);
	}

	public callPromise<T>(command: string, args: any[]): Thenable<T> {
		return new Promise<T>((resolve, reject) => {
			this.connection.then(
				(conn) => {
					conn.call<T>(`RPCServer.${command}`, args, (err, res) => {
						return err ? reject(err) : resolve(res);
					});
				},
				(err) => {
					reject(err);
				}
			);
		});
	}

	/**
	 * Returns the current state of the delve debugger.
	 * This method does not block delve and should return immediately.
	 */
	public async getDebugState(): Promise<DebuggerState> {
		// If a program is launched with --continue, the program is running
		// before we can run attach. So we would need to check the state.
		// We use NonBlocking so the call would return immediately.
		const callResult = await this.callPromise<DebuggerState | CommandOut>('State', [{ NonBlocking: true }]);
		return this.isApiV1 ? <DebuggerState>callResult : (<CommandOut>callResult).State;
	}

	/**
	 * Closing a debugging session follows different approaches for launch vs attach debugging.
	 *
	 * For launch without debugging, we kill the process since the extension started the `go run` process.
	 *
	 * For launch debugging, since the extension starts the delve process, the extension should close it as well.
	 * To gracefully clean up the assets created by delve, we send the Detach request with kill option set to true.
	 *
	 * For attach debugging there are two scenarios; attaching to a local process by ID or connecting to a
	 * remote delve server.  For attach-local we start the delve process so will also terminate it however we
	 * detach from the debugee without killing it.  For attach-remote we only close the client connection,
	 * but do not terminate the remote server.
	 *
	 * For local debugging, the only way to detach from delve when it is running a program is to send a Halt request first.
	 * Since the Halt request might sometimes take too long to complete, we have a timer in place to forcefully kill
	 * the debug process and clean up the assets in case of local debugging
	 */
	public async close(): Promise<void> {
		const forceCleanup = async () => {
			log(`killing debugee (pid: ${this.debugProcess.pid})...`);
			await killProcessTree(this.debugProcess, log);
			await removeFile(this.localDebugeePath);
		};

		if (this.noDebug) {
			// delve isn't running so no need to halt
			await forceCleanup();
			return Promise.resolve();
		}
		const isLocalDebugging: boolean = this.request === 'launch' && !!this.debugProcess;

		return new Promise(async (resolve) => {
			this.delveConnectionClosed = true;

			// For remote debugging, we want to leave the remote dlv server running,
			// so instead of killing it via halt+detach, we just close the network connection.
			// See https://www.github.com/go-delve/delve/issues/1587
			if (this.isRemoteDebugging) {
				log('Remote Debugging: close dlv connection.');
				const rpcConnection = await this.connection;
				// tslint:disable-next-line no-any
				(rpcConnection as any)['conn']['end']();
				return resolve();
			}
			const timeoutToken: NodeJS.Timer =
				isLocalDebugging &&
				setTimeout(async () => {
					log('Killing debug process manually as we could not halt delve in time');
					await forceCleanup();
					resolve();
				}, 1000);

			let haltErrMsg: string;
			try {
				log('HaltRequest');
				await this.callPromise('Command', [{ name: 'halt' }]);
			} catch (err) {
				log('HaltResponse');
				haltErrMsg = err ? err.toString() : '';
				log(`Failed to halt - ${haltErrMsg}`);
			}
			clearTimeout(timeoutToken);

			const targetHasExited: boolean = haltErrMsg && haltErrMsg.endsWith('has exited with status 0');
			const shouldDetach: boolean = !haltErrMsg || targetHasExited;
			let shouldForceClean: boolean = !shouldDetach && isLocalDebugging;
			if (shouldDetach) {
				log('DetachRequest');
				try {
					await this.callPromise('Detach', [this.isApiV1 ? true : { Kill: isLocalDebugging }]);
				} catch (err) {
					log('DetachResponse');
					logError(`Failed to detach - ${err.toString() || ''}`);
					shouldForceClean = isLocalDebugging;
				}
			}
			if (shouldForceClean) {
				await forceCleanup();
			}
			return resolve();
		});
	}

	private getLocalDebugeePath(output: string | undefined): string {
		const configOutput = output || 'debug';
		return path.isAbsolute(configOutput) ? configOutput : path.resolve(this.program, configOutput);
	}
}

export class GoDebugSession extends LoggingDebugSession {
	private variableHandles: Handles<DebugVariable>;
	private breakpoints: Map<string, DebugBreakpoint[]>;
	// Editing breakpoints requires halting delve, skip sending Stop Event to VS Code in such cases
	private skipStopEventOnce: boolean;
	private overrideStopReason: string;
	private debugState: DebuggerState;
	private delve: Delve;
	private localPathSeparator: string;
	private remotePathSeparator: string;
	private stackFrameHandles: Handles<[number, number]>;
	private packageInfo = new Map<string, string>();
	private stopOnEntry: boolean;
	private logLevel: Logger.LogLevel = Logger.LogLevel.Error;
	private readonly initdone = 'initdone·';
	private remoteSourcesAndPackages = new RemoteSourcesAndPackages();
	private localToRemotePathMapping = new Map<string, string>();
	private remoteToLocalPathMapping = new Map<string, string>();

	// TODO(suzmue): Use delve's implementation of substitute-path.
	private substitutePath: { from: string; to: string }[];

	private showGlobalVariables = false;

	private continueEpoch = 0;
	private continueRequestRunning = false;
	private nextEpoch = 0;
	private nextRequestRunning = false;
	public constructor(debuggerLinesStartAt1: boolean, isServer = false, readonly fileSystem = fs) {
		super('', debuggerLinesStartAt1, isServer);
		this.variableHandles = new Handles<DebugVariable>();
		this.skipStopEventOnce = false;
		this.overrideStopReason = '';
		this.stopOnEntry = false;
		this.debugState = null;
		this.delve = null;
		this.breakpoints = new Map<string, DebugBreakpoint[]>();
		this.stackFrameHandles = new Handles<[number, number]>();
	}

	protected initializeRequest(
		response: DebugProtocol.InitializeResponse,
		args: DebugProtocol.InitializeRequestArguments
	): void {
		log('InitializeRequest');
		// Set the capabilities that this debug adapter supports.
		response.body.supportsConditionalBreakpoints = true;
		response.body.supportsConfigurationDoneRequest = true;
		response.body.supportsSetVariable = true;
		this.sendResponse(response);
		log('InitializeResponse');
	}

	protected launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments): void {
		log('LaunchRequest');
		if (!args.program) {
			this.sendErrorResponse(
				response,
				3000,
				'Failed to continue: The program attribute is missing in the debug configuration in launch.json'
			);
			return;
		}
		this.initLaunchAttachRequest(response, args);
	}

	protected attachRequest(response: DebugProtocol.AttachResponse, args: AttachRequestArguments): void {
		log('AttachRequest');
		if (args.mode === 'local' && !args.processId) {
			this.sendErrorResponse(
				response,
				3000,
				'Failed to continue: the processId attribute is missing in the debug configuration in launch.json'
			);
		} else if (args.mode === 'remote' && !args.port) {
			this.sendErrorResponse(
				response,
				3000,
				'Failed to continue: the port attribute is missing in the debug configuration in launch.json'
			);
		}
		this.initLaunchAttachRequest(response, args);
	}

	protected async disconnectRequest(
		response: DebugProtocol.DisconnectResponse,
		args: DebugProtocol.DisconnectArguments
	): Promise<void> {
		log('DisconnectRequest');
		if (this.delve) {
			// Since users want to reset when they issue a disconnect request,
			// we should have a timeout in case disconnectRequestHelper hangs.
			await Promise.race([
				this.disconnectRequestHelper(response, args),
				new Promise<void>((resolve) =>
					setTimeout(() => {
						log('DisconnectRequestHelper timed out after 5s.');
						resolve();
					}, 5_000)
				)
			]);
		}

		this.shutdownProtocolServer(response, args);
		log('DisconnectResponse');
	}

	protected async disconnectRequestHelper(
		response: DebugProtocol.DisconnectResponse,
		args: DebugProtocol.DisconnectArguments
	): Promise<void> {
		// There is a chance that a second disconnectRequest can come through
		// if users click detach multiple times. In that case, we want to
		// guard against talking to the closed Delve connection.
		// Note: this does not completely guard against users attempting to
		// disconnect multiple times when a disconnect request is still running.
		// The order of the execution may results in strange states that don't allow
		// the delve connection to fully disconnect.
		if (this.delve.delveConnectionClosed) {
			log("Skip disconnectRequestHelper as Delve's connection is already closed.");
			return;
		}

		// For remote process, we have to issue a continue request
		// before disconnecting.
		if (this.delve.isRemoteDebugging) {
			if (!(await this.isDebuggeeRunning())) {
				log("Issuing a continue command before closing Delve's connection as the debuggee is not running.");
				this.continue();
			}
		}
		log('Closing Delve.');
		await this.delve.close();
	}

	protected async configurationDoneRequest(
		response: DebugProtocol.ConfigurationDoneResponse,
		args: DebugProtocol.ConfigurationDoneArguments
	): Promise<void> {
		log('ConfigurationDoneRequest');
		if (this.stopOnEntry) {
			this.sendEvent(new StoppedEvent('entry', 1));
			log('StoppedEvent("entry")');
		} else if (!(await this.isDebuggeeRunning())) {
			log('Changing DebugState from Halted to Running');
			this.continue();
		}
		this.sendResponse(response);
		log('ConfigurationDoneResponse', response);
	}

	/**
	 * Given a potential list of paths in potentialPaths array, we will
	 * find the path that has the longest suffix matching filePath.
	 * For example, if filePath is /usr/local/foo/bar/main.go
	 * and potentialPaths are abc/xyz/main.go, bar/main.go
	 * then bar/main.go will be the result.
	 * NOTE: This function assumes that potentialPaths array only contains
	 * files with the same base names as filePath.
	 */
	protected findPathWithBestMatchingSuffix(filePath: string, potentialPaths: string[]): string | undefined {
		if (!potentialPaths?.length) {
			return;
		}

		if (potentialPaths.length === 1) {
			return potentialPaths[0];
		}

		const filePathSegments = filePath.split(/\/|\\/).reverse();
		let bestPathSoFar = potentialPaths[0];
		let bestSegmentsCount = 0;
		for (const potentialPath of potentialPaths) {
			const potentialPathSegments = potentialPath.split(/\/|\\/).reverse();
			let i = 0;
			for (
				;
				i < filePathSegments.length &&
				i < potentialPathSegments.length &&
				filePathSegments[i] === potentialPathSegments[i];
				i++
			) {
				if (i > bestSegmentsCount) {
					bestSegmentsCount = i;
					bestPathSoFar = potentialPath;
				}
			}
		}
		return bestPathSoFar;
	}

	/**
	 * Given a local path, try to find matching file in the remote machine
	 * using remote sources and remote packages info that we get from Delve.
	 * The result would be cached in localToRemotePathMapping.
	 */
	protected inferRemotePathFromLocalPath(localPath: string): string | undefined {
		if (this.localToRemotePathMapping.has(localPath)) {
			return this.localToRemotePathMapping.get(localPath);
		}

		const fileName = getBaseName(localPath);
		const potentialMatchingRemoteFiles = this.remoteSourcesAndPackages.remoteSourceFilesNameGrouping.get(fileName);
		const bestMatchingRemoteFile = this.findPathWithBestMatchingSuffix(localPath, potentialMatchingRemoteFiles);
		if (!bestMatchingRemoteFile) {
			return;
		}

		this.localToRemotePathMapping.set(localPath, bestMatchingRemoteFile);
		return bestMatchingRemoteFile;
	}

	protected async toDebuggerPath(filePath: string): Promise<string> {
		if (this.substitutePath.length === 0) {
			if (this.delve.isRemoteDebugging) {
				// The user trusts us to infer the remote path mapping!
				await this.initializeRemotePackagesAndSources();
				const matchedRemoteFile = this.inferRemotePathFromLocalPath(filePath);
				if (matchedRemoteFile) {
					return matchedRemoteFile;
				}
			}

			return this.convertClientPathToDebugger(filePath);
		}

		// The filePath may have a different path separator than the localPath
		// So, update it to use the same separator for ease in path replacement.
		filePath = normalizeSeparators(filePath);
		let substitutedPath = filePath;
		let substituteRule: { from: string; to: string };
		this.substitutePath.forEach((value) => {
			if (filePath.startsWith(value.from)) {
				if (substituteRule) {
					log(
						`Substitutition rule ${value.from}:${value.to} applies to local path ${filePath} but it was already mapped to debugger path using rule ${substituteRule.from}:${substituteRule.to}`
					);
					return;
				}
				substitutedPath = filePath.replace(value.from, value.to);
				substituteRule = { from: value.from, to: value.to };
			}
		});
		filePath = substitutedPath;

		return (filePath = filePath.replace(/\/|\\/g, this.remotePathSeparator));
	}

	/**
	 * Given a remote path, try to infer the matching local path.
	 * We attempt to find the path in local Go packages as well as workspaceFolder.
	 * Cache the result in remoteToLocalPathMapping.
	 */
	protected inferLocalPathFromRemotePath(remotePath: string): string | undefined {
		// Don't try to infer a path for a file that does not exist
		if (remotePath === '') {
			return remotePath;
		}

		if (this.remoteToLocalPathMapping.has(remotePath)) {
			return this.remoteToLocalPathMapping.get(remotePath);
		}

		const convertedLocalPackageFile = this.inferLocalPathFromRemoteGoPackage(remotePath);
		if (convertedLocalPackageFile) {
			this.remoteToLocalPathMapping.set(remotePath, convertedLocalPackageFile);
			return convertedLocalPackageFile;
		}

		// If we cannot find the path in packages, most likely it will be in the current directory.
		const fileName = getBaseName(remotePath);
		const globSync = glob.sync(fileName, {
			matchBase: true,
			cwd: this.delve.program
		});
		const bestMatchingLocalPath = this.findPathWithBestMatchingSuffix(remotePath, globSync);
		if (bestMatchingLocalPath) {
			const fullLocalPath = path.join(this.delve.program, bestMatchingLocalPath);
			this.remoteToLocalPathMapping.set(remotePath, fullLocalPath);
			return fullLocalPath;
		}
	}

	/**
	 * Given a remote path, we attempt to infer the local path by first checking
	 * if it is in any remote packages. If so, then we attempt to find the matching
	 * local package and find the local path from there.
	 */
	protected inferLocalPathFromRemoteGoPackage(remotePath: string): string | undefined {
		const remotePackage = this.remoteSourcesAndPackages.remotePackagesBuildInfo.find((buildInfo) =>
			remotePath.startsWith(buildInfo.DirectoryPath)
		);
		// Since we know pathToConvert exists in a remote package, we can try to find
		// that same package in the local client. We can use import path to search for the package.
		if (!remotePackage) {
			return;
		}

		if (!this.remotePathSeparator) {
			this.remotePathSeparator = findPathSeparator(remotePackage.DirectoryPath);
		}

		// Escaping package path.
		// It seems like sometimes Delve don't escape the path properly
		// so we should do it.
		remotePath = escapeGoModPath(remotePath);
		const escapedImportPath = escapeGoModPath(remotePackage.ImportPath);

		// The remotePackage.DirectoryPath should be something like
		// <gopath|goroot|source>/<import-path>/xyz...
		// Directory Path can be like "/go/pkg/mod/github.com/google/go-cmp@v0.4.0/cmp"
		// and Import Path can be like "github.com/google/go-cmp/cmp"
		// and Remote Path "/go/pkg/mod/github.com/google/go-cmp@v0.4.0/cmp/blah.go"
		const importPathIndex = remotePath.replace(/@v\d+\.\d+\.\d+[^\/]*/, '').indexOf(escapedImportPath);
		if (importPathIndex < 0) {
			return;
		}

		const relativeRemotePath = remotePath
			.substr(importPathIndex)
			.split(this.remotePathSeparator)
			.join(this.localPathSeparator);
		const pathToConvertWithLocalSeparator = remotePath
			.split(this.remotePathSeparator)
			.join(this.localPathSeparator);

		// Scenario 1: The package is inside the current working directory.
		const localWorkspacePath = path.join(this.delve.program, relativeRemotePath);
		if (this.fileSystem.existsSync(localWorkspacePath)) {
			return localWorkspacePath;
		}

		// Scenario 2: The package is inside GOPATH.
		const localGoPathImportPath = this.inferLocalPathInGoPathFromRemoteGoPackage(
			pathToConvertWithLocalSeparator,
			relativeRemotePath
		);
		if (localGoPathImportPath) {
			return localGoPathImportPath;
		}

		// Scenario 3: The package is inside GOROOT.
		return this.inferLocalPathInGoRootFromRemoteGoPackage(pathToConvertWithLocalSeparator, relativeRemotePath);
	}

	/**
	 * Given a remotePath, check whether the file path exists in $GOROOT/src.
	 * Return the path if it exists.
	 * We are assuming that remotePath is of the form <prefix>/src/<suffix>.
	 */
	protected inferLocalPathInGoRootFromRemoteGoPackage(
		remotePathWithLocalSeparator: string,
		relativeRemotePath: string
	): string | undefined {
		const srcIndex = remotePathWithLocalSeparator.indexOf(
			`${this.localPathSeparator}src${this.localPathSeparator}`
		);
		const goroot = this.getGOROOT();
		const localGoRootImportPath = path.join(
			goroot,
			srcIndex >= 0 ? remotePathWithLocalSeparator.substr(srcIndex) : path.join('src', relativeRemotePath)
		);
		if (this.fileSystem.existsSync(localGoRootImportPath)) {
			return localGoRootImportPath;
		}
	}

	/**
	 * Given a remotePath, check whether the file path exists in $GOPATH.
	 * This can be either in $GOPATH/pkg/mod or $GOPATH/src. If so, return that path.
	 * remotePath can be something like /usr/local/gopath/src/hello-world/main.go
	 * and relativeRemotePath should be hello-world/main.go. In other words,
	 * relativeRemotePath is a relative version of remotePath starting
	 * from the import path of the module.
	 */
	protected inferLocalPathInGoPathFromRemoteGoPackage(
		remotePathWithLocalSeparator: string,
		relativeRemotePath: string
	): string | undefined {
		// Scenario 1: The package is inside $GOPATH/pkg/mod.
		const gopath = (process.env['GOPATH'] || '').split(path.delimiter)[0];

		const indexGoModCache = remotePathWithLocalSeparator.indexOf(
			`${this.localPathSeparator}pkg${this.localPathSeparator}mod${this.localPathSeparator}`
		);
		const localGoPathImportPath = path.join(
			gopath,
			indexGoModCache >= 0
				? remotePathWithLocalSeparator.substr(indexGoModCache)
				: path.join('pkg', 'mod', relativeRemotePath)
		);
		if (this.fileSystem.existsSync(localGoPathImportPath)) {
			return localGoPathImportPath;
		}

		// Scenario 2: The file is in a package in $GOPATH/src.
		const localGoPathSrcPath = path.join(
			gopath,
			'src',
			relativeRemotePath.split(this.remotePathSeparator).join(this.localPathSeparator)
		);
		if (this.fileSystem.existsSync(localGoPathSrcPath)) {
			return localGoPathSrcPath;
		}
	}

	/**
	 * This functions assumes that remote packages and paths information
	 * have been initialized.
	 */
	protected toLocalPath(pathToConvert: string): string {
		if (this.substitutePath.length === 0) {
			// User trusts use to infer the path
			if (this.delve.isRemoteDebugging) {
				const inferredPath = this.inferLocalPathFromRemotePath(pathToConvert);
				if (inferredPath) {
					return inferredPath;
				}
			}

			return this.convertDebuggerPathToClient(pathToConvert);
		}

		// If there is a substitutePath mapping, then we replace the path.
		pathToConvert = normalizeSeparators(pathToConvert);
		let substitutedPath = pathToConvert;
		let substituteRule: { from: string; to: string };
		this.substitutePath.forEach((value) => {
			if (pathToConvert.startsWith(value.to)) {
				if (substituteRule) {
					log(
						`Substitutition rule ${value.from}:${value.to} applies to debugger path ${pathToConvert} but it was already mapped to local path using rule ${substituteRule.from}:${substituteRule.to}`
					);
					return;
				}
				substitutedPath = pathToConvert.replace(value.to, value.from);
				substituteRule = { from: value.from, to: value.to };
			}
		});
		pathToConvert = substitutedPath;

		// When the pathToConvert is under GOROOT or Go module cache, replace path appropriately
		if (!substituteRule) {
			// Fix for https://github.com/Microsoft/vscode-go/issues/1178
			const index = pathToConvert.indexOf(`${this.remotePathSeparator}src${this.remotePathSeparator}`);
			const goroot = this.getGOROOT();
			if (goroot && index > 0) {
				return path.join(goroot, pathToConvert.substr(index));
			}

			const indexGoModCache = pathToConvert.indexOf(
				`${this.remotePathSeparator}pkg${this.remotePathSeparator}mod${this.remotePathSeparator}`
			);
			const gopath = (process.env['GOPATH'] || '').split(path.delimiter)[0];

			if (gopath && indexGoModCache > 0) {
				return path.join(
					gopath,
					pathToConvert.substr(indexGoModCache).split(this.remotePathSeparator).join(this.localPathSeparator)
				);
			}
		}
		return pathToConvert.split(this.remotePathSeparator).join(this.localPathSeparator);
	}

	protected async setBreakPointsRequest(
		response: DebugProtocol.SetBreakpointsResponse,
		args: DebugProtocol.SetBreakpointsArguments
	): Promise<void> {
		log('SetBreakPointsRequest');
		if (!(await this.isDebuggeeRunning())) {
			log('Debuggee is not running. Setting breakpoints without halting.');
			await this.setBreakPoints(response, args);
		} else {
			// Skip stop event if a continue request is running.
			this.skipStopEventOnce = this.continueRequestRunning;
			const haltedDuringNext = this.nextRequestRunning;
			if (haltedDuringNext) {
				this.overrideStopReason = 'next cancelled';
			}

			log(`Halting before setting breakpoints. SkipStopEventOnce is ${this.skipStopEventOnce}.`);
			this.delve.callPromise('Command', [{ name: 'halt' }]).then(
				() => {
					return this.setBreakPoints(response, args).then(() => {
						// We do not want to continue if it was running a next request, since the
						// request was automatically cancelled.
						if (haltedDuringNext) {
							// Send an output event containing a warning that next was cancelled.
							const warning =
								"Setting breakpoints during 'next', 'step in' or 'step out' halted delve and cancelled the next request";
							this.sendEvent(new OutputEvent(warning, 'stderr'));
							return;
						}
						return this.continue(true).then(null, (err) => {
							this.logDelveError(err, 'Failed to continue delve after halting it to set breakpoints');
						});
					});
				},
				(err) => {
					this.skipStopEventOnce = false;
					this.logDelveError(err, 'Failed to halt delve before attempting to set breakpoint');
					return this.sendErrorResponse(
						response,
						2008,
						'Failed to halt delve before attempting to set breakpoint: "{e}"',
						{ e: err.toString() }
					);
				}
			);
		}
	}

	protected async threadsRequest(response: DebugProtocol.ThreadsResponse): Promise<void> {
		if (await this.isDebuggeeRunning()) {
			// Thread request to delve is synchronous and will block if a previous async continue request didn't return
			response.body = { threads: [new Thread(1, 'Dummy')] };
			return this.sendResponse(response);
		} else if (this.debugState && this.debugState.exited) {
			// If the program exits very quickly, the initial threadsRequest will complete after it has exited.
			// A TerminatedEvent has already been sent. d
			response.body = { threads: [] };
			return this.sendResponse(response);
		}
		log('ThreadsRequest');
		this.delve.call<DebugGoroutine[] | ListGoroutinesOut>('ListGoroutines', [], (err, out) => {
			if (this.debugState && this.debugState.exited) {
				// If the program exits very quickly, the initial threadsRequest will complete after it has exited.
				// A TerminatedEvent has already been sent. Ignore the err returned in this case.
				response.body = { threads: [] };
				return this.sendResponse(response);
			}

			if (err) {
				this.logDelveError(err, 'Failed to get threads');
				return this.sendErrorResponse(response, 2003, 'Unable to display threads: "{e}"', {
					e: err.toString()
				});
			}
			const goroutines = this.delve.isApiV1 ? <DebugGoroutine[]>out : (<ListGoroutinesOut>out).Goroutines;
			log('goroutines', goroutines);
			const threads = goroutines.map(
				(goroutine) =>
					new Thread(
						goroutine.id,
						goroutine.userCurrentLoc.function
							? goroutine.userCurrentLoc.function.name
							: goroutine.userCurrentLoc.file + '@' + goroutine.userCurrentLoc.line
					)
			);
			if (threads.length === 0) {
				threads.push(new Thread(1, 'Dummy'));
			}
			response.body = { threads };
			this.sendResponse(response);
			log('ThreadsResponse', threads);
		});
	}

	protected async stackTraceRequest(
		response: DebugProtocol.StackTraceResponse,
		args: DebugProtocol.StackTraceArguments
	): Promise<void> {
		log('StackTraceRequest');
		// For normal VSCode, this request doesn't get invoked when we send a Dummy thread
		// in the scenario where the debuggee is running.
		// For Theia, however, this does get invoked and so we should just send an error
		// response that we cannot get the stack trace at this point since the debugggee is running.
		if (await this.isDebuggeeRunning()) {
			this.sendErrorResponse(response, 2004, 'Unable to produce stack trace as the debugger is running');
			return;
		}

		// delve does not support frame paging, so we ask for a large depth
		const goroutineId = args.threadId;
		const stackTraceIn = { id: goroutineId, depth: this.delve.stackTraceDepth };
		if (!this.delve.isApiV1) {
			Object.assign(stackTraceIn, { full: false, cfg: this.delve.loadConfig });
		}
		this.delve.call<DebugLocation[] | StacktraceOut>(
			this.delve.isApiV1 ? 'StacktraceGoroutine' : 'Stacktrace',
			[stackTraceIn],
			async (err, out) => {
				if (err) {
					this.logDelveError(err, 'Failed to produce stacktrace');
					return this.sendErrorResponse(
						response,
						2004,
						'Unable to produce stack trace: "{e}"',
						{ e: err.toString() },
						// Disable showUser pop-up since errors already show up under the CALL STACK pane
						null
					);
				}
				const locations = this.delve.isApiV1 ? <DebugLocation[]>out : (<StacktraceOut>out).Locations;
				log('locations', locations);

				if (this.delve.isRemoteDebugging) {
					await this.initializeRemotePackagesAndSources();
				}

				let stackFrames = locations.map((location, frameId) => {
					const uniqueStackFrameId = this.stackFrameHandles.create([goroutineId, frameId]);
					return new StackFrame(
						uniqueStackFrameId,
						location.function ? location.function.name : '<unknown>',
						location.file === '<autogenerated>'
							? null
							: new Source(path.basename(location.file), this.toLocalPath(location.file)),
						location.line,
						0
					);
				});
				if (args.startFrame > 0) {
					stackFrames = stackFrames.slice(args.startFrame);
				}
				if (args.levels > 0) {
					stackFrames = stackFrames.slice(0, args.levels);
				}
				response.body = { stackFrames, totalFrames: locations.length };
				this.sendResponse(response);
				log('StackTraceResponse');
			}
		);
	}

	protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void {
		log('ScopesRequest');
		// TODO(polinasok): this.stackFrameHandles.get should succeed as long as DA
		// clients behaves well. Find the documentation around stack frame management
		// and in case of a failure caused by misbehavior, consider to indicate it
		// in the error response.
		const [goroutineId, frameId] = this.stackFrameHandles.get(args.frameId);
		const listLocalVarsIn = { goroutineID: goroutineId, frame: frameId };
		this.delve.call<DebugVariable[] | ListVarsOut>(
			'ListLocalVars',
			this.delve.isApiV1 ? [listLocalVarsIn] : [{ scope: listLocalVarsIn, cfg: this.delve.loadConfig }],
			(err, out) => {
				if (err) {
					this.logDelveError(err, 'Failed to get list local variables');
					return this.sendErrorResponse(response, 2005, 'Unable to list locals: "{e}"', {
						e: err.toString()
					});
				}
				const locals = this.delve.isApiV1 ? <DebugVariable[]>out : (<ListVarsOut>out).Variables;
				log('locals', locals);
				this.addFullyQualifiedName(locals);
				const listLocalFunctionArgsIn = { goroutineID: goroutineId, frame: frameId };
				this.delve.call<DebugVariable[] | ListFunctionArgsOut>(
					'ListFunctionArgs',
					this.delve.isApiV1
						? [listLocalFunctionArgsIn]
						: [{ scope: listLocalFunctionArgsIn, cfg: this.delve.loadConfig }],
					(listFunctionErr, outArgs) => {
						if (listFunctionErr) {
							this.logDelveError(listFunctionErr, 'Failed to list function args');
							return this.sendErrorResponse(response, 2006, 'Unable to list args: "{e}"', {
								e: listFunctionErr.toString()
							});
						}
						const vars = this.delve.isApiV1
							? <DebugVariable[]>outArgs
							: (<ListFunctionArgsOut>outArgs).Args;
						log('functionArgs', vars);
						this.addFullyQualifiedName(vars);
						vars.push(...locals);
						// annotate shadowed variables in parentheses
						const shadowedVars = new Map<string, Array<number>>();
						for (let i = 0; i < vars.length; ++i) {
							if ((vars[i].flags & GoVariableFlags.VariableShadowed) === 0) {
								continue;
							}
							const varName = vars[i].name;
							if (!shadowedVars.has(varName)) {
								const indices = new Array<number>();
								indices.push(i);
								shadowedVars.set(varName, indices);
							} else {
								shadowedVars.get(varName).push(i);
							}
						}
						for (const svIndices of shadowedVars.values()) {
							// sort by declared line number in descending order
							svIndices.sort((lhs: number, rhs: number) => {
								return vars[rhs].DeclLine - vars[lhs].DeclLine;
							});
							// enclose in parentheses, one pair per scope
							for (let scope = 0; scope < svIndices.length; ++scope) {
								const svIndex = svIndices[scope];
								// start at -1 so scope of 0 has one pair of parens
								for (let count = -1; count < scope; ++count) {
									vars[svIndex].name = `(${vars[svIndex].name})`;
								}
							}
						}
						const scopes = new Array<Scope>();
						const localVariables: DebugVariable = {
							name: 'Local',
							addr: 0,
							type: '',
							realType: '',
							kind: 0,
							flags: 0,
							onlyAddr: false,
							DeclLine: 0,
							value: '',
							len: 0,
							cap: 0,
							children: vars,
							unreadable: '',
							fullyQualifiedName: '',
							base: 0
						};

						scopes.push(new Scope('Local', this.variableHandles.create(localVariables), false));
						response.body = { scopes };

						if (!this.showGlobalVariables) {
							this.sendResponse(response);
							log('ScopesResponse');
							return;
						}

						this.getPackageInfo(this.debugState).then((packageName) => {
							if (!packageName) {
								this.sendResponse(response);
								log('ScopesResponse');
								return;
							}
							const filter = `^${packageName}\\.`;
							this.delve.call<DebugVariable[] | ListVarsOut>(
								'ListPackageVars',
								this.delve.isApiV1 ? [filter] : [{ filter, cfg: this.delve.loadConfig }],
								(listPkgVarsErr, listPkgVarsOut) => {
									if (listPkgVarsErr) {
										this.logDelveError(listPkgVarsErr, 'Failed to list global vars');
										return this.sendErrorResponse(
											response,
											2007,
											'Unable to list global vars: "{e}"',
											{ e: listPkgVarsErr.toString() }
										);
									}
									const globals = this.delve.isApiV1
										? <DebugVariable[]>listPkgVarsOut
										: (<ListVarsOut>listPkgVarsOut).Variables;
									let initdoneIndex = -1;
									for (let i = 0; i < globals.length; i++) {
										globals[i].name = globals[i].name.substr(packageName.length + 1);
										if (initdoneIndex === -1 && globals[i].name === this.initdone) {
											initdoneIndex = i;
										}
									}
									if (initdoneIndex > -1) {
										globals.splice(initdoneIndex, 1);
									}
									log('global vars', globals);

									const globalVariables: DebugVariable = {
										name: 'Global',
										addr: 0,
										type: '',
										realType: '',
										kind: 0,
										flags: 0,
										onlyAddr: false,
										DeclLine: 0,
										value: '',
										len: 0,
										cap: 0,
										children: globals,
										unreadable: '',
										fullyQualifiedName: '',
										base: 0
									};
									scopes.push(
										new Scope('Global', this.variableHandles.create(globalVariables), false)
									);
									this.sendResponse(response);
									log('ScopesResponse');
								}
							);
						});
					}
				);
			}
		);
	}

	protected variablesRequest(
		response: DebugProtocol.VariablesResponse,
		args: DebugProtocol.VariablesArguments
	): void {
		log('VariablesRequest');
		const vari = this.variableHandles.get(args.variablesReference);
		let variablesPromise: Promise<DebugProtocol.Variable[]>;
		const loadChildren = async (exp: string, v: DebugVariable) => {
			// from https://github.com/go-delve/delve/blob/master/Documentation/api/ClientHowto.md#looking-into-variables
			if (
				(v.kind === GoReflectKind.Struct && v.len > v.children.length) ||
				(v.kind === GoReflectKind.Interface && v.children.length > 0 && v.children[0].onlyAddr === true)
			) {
				await this.evaluateRequestImpl({ expression: exp }).then(
					(result) => {
						const variable = this.delve.isApiV1 ? <DebugVariable>result : (<EvalOut>result).Variable;
						v.children = variable.children;
					},
					(err) => this.logDelveError(err, 'Failed to evaluate expression')
				);
			}
		};
		// expressions passed to loadChildren defined per
		// https://github.com/go-delve/delve/blob/master/Documentation/api/ClientHowto.md#loading-more-of-a-variable
		if (vari.kind === GoReflectKind.Array || vari.kind === GoReflectKind.Slice) {
			variablesPromise = Promise.all(
				vari.children.map((v, i) => {
					return loadChildren(`*(*"${v.type}")(${v.addr})`, v).then(
						(): DebugProtocol.Variable => {
							const { result, variablesReference } = this.convertDebugVariableToProtocolVariable(v);
							return {
								name: '[' + i + ']',
								value: result,
								evaluateName: vari.fullyQualifiedName + '[' + i + ']',
								variablesReference
							};
						}
					);
				})
			);
		} else if (vari.kind === GoReflectKind.Map) {
			variablesPromise = Promise.all(
				vari.children
					.map((_, i) => {
						// even indices are map keys, odd indices are values
						if (i % 2 === 0 && i + 1 < vari.children.length) {
							const mapKey = this.convertDebugVariableToProtocolVariable(vari.children[i]);
							return loadChildren(
								`${vari.fullyQualifiedName}.${vari.name}[${mapKey.result}]`,
								vari.children[i + 1]
							).then(() => {
								const mapValue = this.convertDebugVariableToProtocolVariable(vari.children[i + 1]);
								return {
									name: mapKey.result,
									value: mapValue.result,
									evaluateName: vari.fullyQualifiedName + '[' + mapKey.result + ']',
									variablesReference: mapValue.variablesReference
								};
							});
						}
					})
					.filter((v) => v != null) // remove the null values created by combining keys and values
			);
		} else {
			variablesPromise = Promise.all(
				vari.children.map((v) => {
					return loadChildren(`*(*"${v.type}")(${v.addr})`, v).then(
						(): DebugProtocol.Variable => {
							const { result, variablesReference } = this.convertDebugVariableToProtocolVariable(v);

							return {
								name: v.name,
								value: result,
								evaluateName: v.fullyQualifiedName,
								variablesReference
							};
						}
					);
				})
			);
		}
		variablesPromise.then((variables) => {
			response.body = { variables };
			this.sendResponse(response);
			log('VariablesResponse', JSON.stringify(variables, null, ' '));
		});
	}

	protected continueRequest(response: DebugProtocol.ContinueResponse): void {
		log('ContinueRequest');
		this.continue();
		this.sendResponse(response);
		log('ContinueResponse');
	}

	protected nextRequest(response: DebugProtocol.NextResponse): void {
		this.nextEpoch++;
		const closureEpoch = this.nextEpoch;
		this.nextRequestRunning = true;

		log('NextRequest');
		this.delve.call<DebuggerState | CommandOut>('Command', [{ name: 'next' }], (err, out) => {
			if (closureEpoch === this.continueEpoch) {
				this.nextRequestRunning = false;
			}

			if (err) {
				this.logDelveError(err, 'Failed to next');
			}
			const state = this.delve.isApiV1 ? <DebuggerState>out : (<CommandOut>out).State;
			log('next state', state);
			this.debugState = state;
			this.handleReenterDebug('step');
		});
		// All threads are resumed on a next request
		this.sendEvent(new ContinuedEvent(1, true));
		this.sendResponse(response);
		log('NextResponse');
	}

	protected stepInRequest(response: DebugProtocol.StepInResponse): void {
		this.nextEpoch++;
		const closureEpoch = this.nextEpoch;
		this.nextRequestRunning = true;

		log('StepInRequest');
		this.delve.call<DebuggerState | CommandOut>('Command', [{ name: 'step' }], (err, out) => {
			if (closureEpoch === this.continueEpoch) {
				this.nextRequestRunning = false;
			}

			if (err) {
				this.logDelveError(err, 'Failed to step in');
			}
			const state = this.delve.isApiV1 ? <DebuggerState>out : (<CommandOut>out).State;
			log('stop state', state);
			this.debugState = state;
			this.handleReenterDebug('step');
		});
		// All threads are resumed on a step in request
		this.sendEvent(new ContinuedEvent(1, true));
		this.sendResponse(response);
		log('StepInResponse');
	}

	protected stepOutRequest(response: DebugProtocol.StepOutResponse): void {
		this.nextEpoch++;
		const closureEpoch = this.nextEpoch;
		this.nextRequestRunning = true;

		log('StepOutRequest');
		this.delve.call<DebuggerState | CommandOut>('Command', [{ name: 'stepOut' }], (err, out) => {
			if (closureEpoch === this.continueEpoch) {
				this.nextRequestRunning = false;
			}

			if (err) {
				this.logDelveError(err, 'Failed to step out');
			}
			const state = this.delve.isApiV1 ? <DebuggerState>out : (<CommandOut>out).State;
			log('stepout state', state);
			this.debugState = state;
			this.handleReenterDebug('step');
		});
		// All threads are resumed on a step out request
		this.sendEvent(new ContinuedEvent(1, true));
		this.sendResponse(response);
		log('StepOutResponse');
	}

	protected pauseRequest(response: DebugProtocol.PauseResponse): void {
		log('PauseRequest');
		this.delve.call<DebuggerState | CommandOut>('Command', [{ name: 'halt' }], (err, out) => {
			if (err) {
				this.logDelveError(err, 'Failed to halt');
				return this.sendErrorResponse(response, 2010, 'Unable to halt execution: "{e}"', {
					e: err.toString()
				});
			}
			const state = this.delve.isApiV1 ? <DebuggerState>out : (<CommandOut>out).State;
			log('pause state', state);
			this.debugState = state;
			this.handleReenterDebug('pause');
		});
		this.sendResponse(response);
		log('PauseResponse');
	}

	// evaluateRequest is used both for the traditional expression evaluation
	// (https://github.com/go-delve/delve/blob/master/Documentation/cli/expr.md) and
	// for the 'call' command support.
	// If the args.expression starts with the 'call' keyword followed by an expression that looks
	// like a function call, the request is interpreted as a 'call' command request,
	// and otherwise, interpreted as `print` command equivalent with RPCServer.Eval.
	protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void {
		log('EvaluateRequest');
		// Captures pattern that looks like the expression that starts with `call<space>`
		// command call. This is supported only with APIv2.
		const isCallCommand = args.expression.match(/^\s*call\s+\S+/);
		if (!this.delve.isApiV1 && isCallCommand) {
			this.evaluateCallImpl(args).then(
				(out) => {
					const state = (<CommandOut>out).State;
					const returnValues = state?.currentThread?.ReturnValues ?? [];
					switch (returnValues.length) {
						case 0:
							response.body = { result: '', variablesReference: 0 };
							break;
						case 1:
							response.body = this.convertDebugVariableToProtocolVariable(returnValues[0]);
							break;
						default:
							// Go function can return multiple return values while
							// DAP EvaluateResponse assumes a single result with possibly
							// multiple children. So, create a fake DebugVariable
							// that has all the results as children.
							const returnResults = this.wrapReturnVars(returnValues);
							response.body = this.convertDebugVariableToProtocolVariable(returnResults);
							break;
					}
					this.sendResponse(response);
					log('EvaluateCallResponse');
				},
				(err) => {
					this.sendErrorResponse(
						response,
						2009,
						'Unable to complete call: "{e}"',
						{
							e: err.toString()
						},
						args.context === 'watch' ? null : ErrorDestination.User
					);
				}
			);
			return;
		}
		// Now handle it as a conventional evaluateRequest.
		this.evaluateRequestImpl(args).then(
			(out) => {
				const variable = this.delve.isApiV1 ? <DebugVariable>out : (<EvalOut>out).Variable;
				// #2326: Set the fully qualified name for variable mapping
				variable.fullyQualifiedName = variable.name;
				response.body = this.convertDebugVariableToProtocolVariable(variable);
				this.sendResponse(response);
				log('EvaluateResponse');
			},
			(err) => {
				// No need to repeatedly show the error pop-up when expressions
				// are continiously reevaluated in the Watch panel, which
				// already displays errors.
				this.sendErrorResponse(
					response,
					2009,
					'Unable to eval expression: "{e}"',
					{
						e: err.toString()
					},
					args.context === 'watch' ? null : ErrorDestination.User
				);
			}
		);
	}

	protected setVariableRequest(
		response: DebugProtocol.SetVariableResponse,
		args: DebugProtocol.SetVariableArguments
	): void {
		log('SetVariableRequest');
		const scope = {
			goroutineID: this.debugState.currentGoroutine.id
		};
		const setSymbolArgs = {
			Scope: scope,
			Symbol: args.name,
			Value: args.value
		};
		this.delve.call(this.delve.isApiV1 ? 'SetSymbol' : 'Set', [setSymbolArgs], (err) => {
			if (err) {
				const errMessage = `Failed to set variable: ${err.toString()}`;
				this.logDelveError(err, 'Failed to set variable');
				return this.sendErrorResponse(response, 2010, errMessage);
			}
			response.body = { value: args.value };
			this.sendResponse(response);
			log('SetVariableResponse');
		});
	}

	private getGOROOT(): string {
		if (this.delve && this.delve.goroot) {
			return this.delve.goroot;
		}
		return process.env['GOROOT'] || '';
		// this is a workaround to keep the tests in integration/goDebug.test.ts running.
		// The tests synthesize a bogus Delve instance.
	}

	// contains common code for launch and attach debugging initialization
	private initLaunchAttachRequest(
		response: DebugProtocol.LaunchResponse,
		args: LaunchRequestArguments | AttachRequestArguments
	) {
		this.logLevel =
			args.trace === 'verbose' || args.trace === 'trace'
				? Logger.LogLevel.Verbose
				: args.trace === 'log' || args.trace === 'info' || args.trace === 'warn'
				? Logger.LogLevel.Log
				: Logger.LogLevel.Error;
		const logPath =
			this.logLevel !== Logger.LogLevel.Error ? path.join(os.tmpdir(), 'vscode-go-debug.txt') : undefined;
		logger.setup(this.logLevel, logPath);

		if (typeof args.showGlobalVariables === 'boolean') {
			this.showGlobalVariables = args.showGlobalVariables;
		}
		if (args.stopOnEntry) {
			this.stopOnEntry = args.stopOnEntry;
		}
		if (!args.port) {
			args.port = random(2000, 50000);
		}
		if (!args.host) {
			args.host = '127.0.0.1';
		}

		let localPath: string;
		if (args.request === 'attach') {
			localPath = args.cwd;
		} else if (args.request === 'launch') {
			localPath = args.program;
		}
		if (!args.remotePath) {
			// too much code relies on remotePath never being null
			args.remotePath = '';
		}

		this.localPathSeparator = findPathSeparator(localPath);
		this.substitutePath = [];
		if (args.remotePath.length > 0) {
			this.remotePathSeparator = findPathSeparator(args.remotePath);

			const llist = localPath.split(/\/|\\/).reverse();
			const rlist = args.remotePath.split(/\/|\\/).reverse();
			let i = 0;
			for (; i < llist.length; i++) {
				if (llist[i] !== rlist[i] || llist[i] === 'src') {
					break;
				}
			}

			if (i) {
				localPath = llist.reverse().slice(0, -i).join(this.localPathSeparator) + this.localPathSeparator;
				args.remotePath =
					rlist.reverse().slice(0, -i).join(this.remotePathSeparator) + this.remotePathSeparator;
			} else if (
				args.remotePath.length > 1 &&
				(args.remotePath.endsWith('\\') || args.remotePath.endsWith('/'))
			) {
				args.remotePath = args.remotePath.substring(0, args.remotePath.length - 1);
			}

			// Make the remotePath mapping the first one in substitutePath
			// so that it will take precedence over the other mappings.
			this.substitutePath.push({
				from: normalizeSeparators(localPath),
				to: normalizeSeparators(args.remotePath)
			});
		}

		if (args.substitutePath) {
			args.substitutePath.forEach((value) => {
				if (!this.remotePathSeparator) {
					this.remotePathSeparator = findPathSeparator(value.to);
				}
				this.substitutePath.push({
					from: normalizeSeparators(value.from),
					to: normalizeSeparators(value.to)
				});
			});
		}

		// Launch the Delve debugger on the program
		this.delve = new Delve(args, localPath);
		this.delve.onstdout = (str: string) => {
			this.sendEvent(new OutputEvent(str, 'stdout'));
		};
		this.delve.onstderr = (str: string) => {
			if (localPath.length > 0) {
				str = expandFilePathInOutput(str, localPath);
			}
			this.sendEvent(new OutputEvent(str, 'stderr'));
		};
		this.delve.onclose = (code) => {
			if (code !== 0) {
				this.sendErrorResponse(response, 3000, 'Failed to continue: Check the debug console for details.');
			}
			log('Sending TerminatedEvent as delve is closed');
			this.sendEvent(new TerminatedEvent());
		};

		this.delve.connection.then(
			() => {
				if (!this.delve.noDebug) {
					this.delve.call<GetVersionOut>('GetVersion', [], (err, out) => {
						if (err) {
							logError(err);
							return this.sendErrorResponse(
								response,
								2001,
								'Failed to get remote server version: "{e}"',
								{ e: err.toString() }
							);
						}
						const clientVersion = this.delve.isApiV1 ? 1 : 2;
						if (out.APIVersion !== clientVersion) {
							const errorMessage = `The remote server is running on delve v${out.APIVersion} API and the client is running v${clientVersion} API. Change the version used on the client by using the property "apiVersion" in your launch.json file.`;
							logError(errorMessage);
							return this.sendErrorResponse(response, 3000, errorMessage);
						}
					});

					this.sendEvent(new InitializedEvent());
					log('InitializeEvent');
				}
				this.sendResponse(response);
			},
			(err) => {
				this.sendErrorResponse(response, 3000, 'Failed to continue: "{e}"', {
					e: err.toString()
				});
				log('ContinueResponse');
			}
		);
	}

	/**
	 * Initializing remote packages and sources.
	 * We use event model to prevent race conditions.
	 */
	private async initializeRemotePackagesAndSources(): Promise<void> {
		if (this.remoteSourcesAndPackages.initializedRemoteSourceFiles) {
			return;
		}

		if (!this.remoteSourcesAndPackages.initializingRemoteSourceFiles) {
			try {
				await this.remoteSourcesAndPackages.initializeRemotePackagesAndSources(this.delve);
			} catch (error) {
				log(`Failing to initialize remote sources: ${error}`);
			}
			return;
		}

		if (this.remoteSourcesAndPackages.initializingRemoteSourceFiles) {
			try {
				await new Promise<void>((resolve) => {
					this.remoteSourcesAndPackages.on(RemoteSourcesAndPackages.INITIALIZED, () => {
						resolve();
					});
				});
			} catch (error) {
				log(`Failing to initialize remote sources: ${error}`);
			}
		}
	}

	private async setBreakPoints(
		response: DebugProtocol.SetBreakpointsResponse,
		args: DebugProtocol.SetBreakpointsArguments
	): Promise<void> {
		const file = normalizePath(args.source.path);
		if (!this.breakpoints.get(file)) {
			this.breakpoints.set(file, []);
		}
		const remoteFile = await this.toDebuggerPath(file);

		return Promise.all(
			this.breakpoints.get(file).map((existingBP) => {
				log('Clearing: ' + existingBP.id);
				return this.delve.callPromise('ClearBreakpoint', [
					this.delve.isApiV1 ? existingBP.id : { Id: existingBP.id }
				]);
			})
		)
			.then(() => {
				log('All cleared');
				let existingBreakpoints: DebugBreakpoint[] | undefined;
				return Promise.all(
					args.breakpoints.map((breakpoint) => {
						if (this.delve.remotePath.length === 0) {
							log('Creating on: ' + file + ':' + breakpoint.line);
						} else {
							log('Creating on: ' + file + ' (' + remoteFile + ') :' + breakpoint.line);
						}
						const breakpointIn = <DebugBreakpoint>{};
						breakpointIn.file = remoteFile;
						breakpointIn.line = breakpoint.line;
						breakpointIn.loadArgs = this.delve.loadConfig;
						breakpointIn.loadLocals = this.delve.loadConfig;
						breakpointIn.cond = breakpoint.condition;
						return this.delve
							.callPromise('CreateBreakpoint', [
								this.delve.isApiV1 ? breakpointIn : { Breakpoint: breakpointIn }
							])
							.then(null, async (err) => {
								// Delve does not seem to support error code at this time.
								// TODO(quoct): Follow up with delve team.
								if (err.toString().startsWith('Breakpoint exists at')) {
									log('Encounter existing breakpoint: ' + breakpointIn);
									// We need to call listbreakpoints to find the ID.
									// Otherwise, we would not be able to clear the breakpoints.
									if (!existingBreakpoints) {
										try {
											const listBreakpointsResponse = await this.delve.callPromise<
												ListBreakpointsOut | DebugBreakpoint[]
											>('ListBreakpoints', this.delve.isApiV1 ? [] : [{}]);
											existingBreakpoints = this.delve.isApiV1
												? (listBreakpointsResponse as DebugBreakpoint[])
												: (listBreakpointsResponse as ListBreakpointsOut).Breakpoints;
										} catch (error) {
											log('Error listing breakpoints: ' + error.toString());
											return null;
										}
									}

									// Make sure that we compare the file names with the same separators.
									const matchedBreakpoint = existingBreakpoints.find(
										(existingBreakpoint) =>
											existingBreakpoint.line === breakpointIn.line &&
											compareFilePathIgnoreSeparator(existingBreakpoint.file, breakpointIn.file)
									);

									if (!matchedBreakpoint) {
										log(`Cannot match breakpoint ${breakpointIn} with existing breakpoints.`);
										return null;
									}
									return this.delve.isApiV1 ? matchedBreakpoint : { Breakpoint: matchedBreakpoint };
								}
								log('Error on CreateBreakpoint: ' + err.toString());
								return null;
							});
					})
				);
			})
			.then((newBreakpoints) => {
				let convertedBreakpoints: DebugBreakpoint[];
				if (!this.delve.isApiV1) {
					// Unwrap breakpoints from v2 apicall
					convertedBreakpoints = newBreakpoints.map((bp, i) => {
						return bp ? (bp as CreateBreakpointOut).Breakpoint : null;
					});
				} else {
					convertedBreakpoints = newBreakpoints as DebugBreakpoint[];
				}

				log('All set:' + JSON.stringify(newBreakpoints));
				const breakpoints = convertedBreakpoints.map((bp, i) => {
					if (bp) {
						return { verified: true, line: bp.line };
					} else {
						return { verified: false, line: args.lines[i] };
					}
				});
				this.breakpoints.set(
					file,
					convertedBreakpoints.filter((x) => !!x)
				);
				return breakpoints;
			})
			.then(
				(breakpoints) => {
					response.body = { breakpoints };
					this.sendResponse(response);
					log('SetBreakPointsResponse');
				},
				(err) => {
					this.sendErrorResponse(response, 2002, 'Failed to set breakpoint: "{e}"', {
						e: err.toString()
					});
					logError(err);
				}
			);
	}

	private async getPackageInfo(debugState: DebuggerState): Promise<string | void> {
		if (!debugState.currentThread || !debugState.currentThread.file) {
			return Promise.resolve(null);
		}
		if (this.delve.isRemoteDebugging) {
			await this.initializeRemotePackagesAndSources();
		}
		const dir = path.dirname(
			this.delve.remotePath.length || this.delve.isRemoteDebugging
				? this.toLocalPath(debugState.currentThread.file)
				: debugState.currentThread.file
		);
		if (this.packageInfo.has(dir)) {
			return Promise.resolve(this.packageInfo.get(dir));
		}
		return new Promise((resolve) => {
			execFile(
				getBinPathWithPreferredGopathGoroot('go', []),
				['list', '-f', '{{.Name}} {{.ImportPath}}'],
				{ cwd: dir, env: this.delve.dlvEnv },
				(err, stdout, stderr) => {
					if (err || stderr || !stdout) {
						logError(`go list failed on ${dir}: ${stderr || err}`);
						return resolve();
					}
					if (stdout.split('\n').length !== 2) {
						logError(`Cannot determine package for ${dir}`);
						return resolve();
					}
					const spaceIndex = stdout.indexOf(' ');
					const result = stdout.substr(0, spaceIndex) === 'main' ? 'main' : stdout.substr(spaceIndex).trim();
					this.packageInfo.set(dir, result);
					resolve(result);
				}
			);
		});
	}

	// Go might return more than one result while DAP and VS Code do not support
	// such scenario but assume one single result. So, wrap all return variables
	// in one made-up, nameless, invalid variable. This is similar to how scopes
	// are represented. This assumes the vars are the ordered list of return
	// values from a function call.
	private wrapReturnVars(vars: DebugVariable[]): DebugVariable {
		// VS Code uses the value property of the DebugVariable
		// when displaying it. So let's formulate it in a user friendly way
		// as if they look like a list of multiple values.
		// Note: we use only convertDebugVariableToProtocolVariable's result,
		// which means we will leak the variable references until the handle
		// map is cleared. Assuming the number of return parameters is handful,
		// this waste shouldn't be significant.
		const values = vars.map((v) => this.convertDebugVariableToProtocolVariable(v).result) || [];
		return {
			value: values.join(', '),
			kind: GoReflectKind.Invalid,
			flags: GoVariableFlags.VariableFakeAddress | GoVariableFlags.VariableReturnArgument,
			children: vars,

			// DebugVariable requires the following fields.
			name: '',
			addr: 0,
			type: '',
			realType: '',
			onlyAddr: false,
			DeclLine: 0,
			len: 0,
			cap: 0,
			unreadable: '',
			base: 0,
			fullyQualifiedName: ''
		};
	}

	private convertDebugVariableToProtocolVariable(v: DebugVariable): { result: string; variablesReference: number } {
		if (v.kind === GoReflectKind.UnsafePointer) {
			return {
				result: `unsafe.Pointer(0x${v.children[0].addr.toString(16)})`,
				variablesReference: 0
			};
		} else if (v.kind === GoReflectKind.Ptr) {
			if (v.children[0].addr === 0) {
				return {
					result: 'nil <' + v.type + '>',
					variablesReference: 0
				};
			} else if (v.children[0].type === 'void') {
				return {
					result: 'void',
					variablesReference: 0
				};
			} else {
				if (v.children[0].children.length > 0) {
					// Generate correct fullyQualified names for variable expressions
					v.children[0].fullyQualifiedName = v.fullyQualifiedName;
					v.children[0].children.forEach((child) => {
						child.fullyQualifiedName = v.fullyQualifiedName + '.' + child.name;
					});
				}
				return {
					result: `<${v.type}>(0x${v.children[0].addr.toString(16)})`,
					variablesReference: v.children.length > 0 ? this.variableHandles.create(v) : 0
				};
			}
		} else if (v.kind === GoReflectKind.Slice) {
			if (v.base === 0) {
				return {
					result: 'nil <' + v.type + '>',
					variablesReference: 0
				};
			}
			return {
				result: '<' + v.type + '> (length: ' + v.len + ', cap: ' + v.cap + ')',
				variablesReference: this.variableHandles.create(v)
			};
		} else if (v.kind === GoReflectKind.Map) {
			if (v.base === 0) {
				return {
					result: 'nil <' + v.type + '>',
					variablesReference: 0
				};
			}
			return {
				result: '<' + v.type + '> (length: ' + v.len + ')',
				variablesReference: this.variableHandles.create(v)
			};
		} else if (v.kind === GoReflectKind.Array) {
			return {
				result: '<' + v.type + '>',
				variablesReference: this.variableHandles.create(v)
			};
		} else if (v.kind === GoReflectKind.String) {
			let val = v.value;
			const byteLength = Buffer.byteLength(val || '');
			if (v.value && byteLength < v.len) {
				val += `...+${v.len - byteLength} more`;
			}
			return {
				result: v.unreadable ? '<' + v.unreadable + '>' : '"' + val + '"',
				variablesReference: 0
			};
		} else if (v.kind === GoReflectKind.Interface) {
			if (v.addr === 0) {
				// an escaped interface variable that points to nil, this shouldn't
				// happen in normal code but can happen if the variable is out of scope.
				return {
					result: 'nil',
					variablesReference: 0
				};
			}

			if (v.children.length === 0) {
				// Shouldn't happen, but to be safe.
				return {
					result: 'nil',
					variablesReference: 0
				};
			}
			const child = v.children[0];
			if (child.kind === GoReflectKind.Invalid && child.addr === 0) {
				return {
					result: `nil <${v.type}>`,
					variablesReference: 0
				};
			}
			return {
				// TODO(hyangah): v.value will be useless. consider displaying more info from the child.
				// https://github.com/go-delve/delve/blob/930fa3b/service/api/prettyprint.go#L106-L124
				result: v.value || `<${v.type}(${child.type})>)`,
				variablesReference: v.children?.length > 0 ? this.variableHandles.create(v) : 0
			};
		} else {
			// Default case - structs
			if (v.children.length > 0) {
				// Generate correct fullyQualified names for variable expressions
				v.children.forEach((child) => {
					child.fullyQualifiedName = v.fullyQualifiedName + '.' + child.name;
				});
			}
			return {
				result: v.value || '<' + v.type + '>',
				variablesReference: v.children.length > 0 ? this.variableHandles.create(v) : 0
			};
		}
	}

	private cleanupHandles(): void {
		this.variableHandles.reset();
		this.stackFrameHandles.reset();
	}

	private handleReenterDebug(reason: string): void {
		log(`handleReenterDebug(${reason}).`);
		this.cleanupHandles();

		if (this.debugState.exited) {
			this.sendEvent(new TerminatedEvent());
			log('TerminatedEvent');
		} else {
			// Delve blocks on continue and does not support events, so there is no way to
			// refresh the list of goroutines while the program is running. And when the program is
			// stopped, the development tool will issue a threads request and update the list of
			// threads in the UI even without the optional thread events. Therefore, instead of
			// analyzing all goroutines here, only retrieve the current one.
			// TODO(polina): validate the assumption in this code that the first goroutine
			// is the current one. So far it appears to me that this is always the main goroutine
			// with id 1.
			this.delve.call<DebugGoroutine[] | ListGoroutinesOut>('ListGoroutines', [{ count: 1 }], (err, out) => {
				if (err) {
					this.logDelveError(err, 'Failed to get threads');
				}
				const goroutines = this.delve.isApiV1 ? <DebugGoroutine[]>out : (<ListGoroutinesOut>out).Goroutines;
				if (!this.debugState.currentGoroutine && goroutines.length > 0) {
					this.debugState.currentGoroutine = goroutines[0];
				}

				if (this.skipStopEventOnce) {
					log(
						`Skipping stop event for ${reason}. The current Go routines is ${this.debugState?.currentGoroutine}.`
					);
					this.skipStopEventOnce = false;
					return;
				}

				if (this.overrideStopReason?.length > 0) {
					reason = this.overrideStopReason;
					this.overrideStopReason = '';
				}

				const stoppedEvent = new StoppedEvent(reason, this.debugState.currentGoroutine.id);
				(<any>stoppedEvent.body).allThreadsStopped = true;
				this.sendEvent(stoppedEvent);
				log('StoppedEvent("' + reason + '")');
			});
		}
	}

	// Returns true if the debuggee is running.
	// The call getDebugState is non-blocking so it should return
	// almost instantaneously. However, if we run into some errors,
	// we will fall back to the internal tracking of the debug state.
	// TODO: If Delve is not in multi-client state, we can simply
	// track the running state with continueRequestRunning internally
	// instead of issuing a getDebugState call to Delve. Perhaps we want to
	// do that to improve performance in the future.
	private async isDebuggeeRunning(): Promise<boolean> {
		if (this.debugState && this.debugState.exited) {
			return false;
		}
		try {
			this.debugState = await this.delve.getDebugState();
			return this.debugState.Running;
		} catch (error) {
			this.logDelveError(error, 'Failed to get state');
			// Fall back to the internal tracking.
			return this.continueRequestRunning || this.nextRequestRunning;
		}
	}

	private shutdownProtocolServer(
		response: DebugProtocol.DisconnectResponse,
		args: DebugProtocol.DisconnectArguments
	): void {
		log('DisconnectRequest to parent to shut down protocol server.');
		super.disconnectRequest(response, args);
	}

	private continue(calledWhenSettingBreakpoint?: boolean): Thenable<void> {
		this.continueEpoch++;
		const closureEpoch = this.continueEpoch;
		this.continueRequestRunning = true;

		const callback = (out: any) => {
			if (closureEpoch === this.continueEpoch) {
				this.continueRequestRunning = false;
			}
			const state = this.delve.isApiV1 ? <DebuggerState>out : (<CommandOut>out).State;
			log('continue state', state);
			this.debugState = state;

			let reason = 'breakpoint';
			// Check if the current thread was stopped on 'panic' or 'fatal error'.
			if (!!state.currentThread && !!state.currentThread.breakPoint) {
				const bp = state.currentThread.breakPoint;
				if (bp.id === unrecoveredPanicID) {
					// If the breakpoint is actually caused by a panic,
					// we want to return on "panic".
					reason = 'panic';
				} else if (bp.id === fatalThrowID) {
					// If the breakpoint is actually caused by a fatal throw,
					// we want to return on "fatal error".
					reason = 'fatal error';
				}
			}
			this.handleReenterDebug(reason);
		};

		// If called when setting breakpoint internally, we want the error to bubble up.
		let errorCallback = null;
		if (!calledWhenSettingBreakpoint) {
			errorCallback = (err: any) => {
				if (err) {
					this.logDelveError(err, 'Failed to continue');
				}
				this.handleReenterDebug('breakpoint');
				throw err;
			};
		}

		return this.delve.callPromise('Command', [{ name: 'continue' }]).then(callback, errorCallback);
	}

	// evaluateCallImpl expects args.expression starts with the 'call ' command.
	private evaluateCallImpl(args: DebugProtocol.EvaluateArguments): Thenable<DebuggerState | CommandOut> {
		const callExpr = args.expression.trimLeft().slice('call '.length);
		// if args.frameID is 'not specified', expression is evaluated in the global scope, according to DAP.
		// default to the topmost stack frame of the current goroutine
		let goroutineId = -1;
		let frameId = 0;
		if (args.frameId) {
			[goroutineId, frameId] = this.stackFrameHandles.get(args.frameId, [goroutineId, frameId]);
		}
		// See https://github.com/go-delve/delve/blob/328cf87808822693dc611591519689dcd42696a3/service/api/types.go#L321-L350
		// for the command args for function call.
		const returnValue = this.delve
			.callPromise<DebuggerState | CommandOut>('Command', [
				{
					name: 'call',
					goroutineID: goroutineId,
					returnInfoLoadConfig: this.delve.loadConfig,
					expr: callExpr,
					unsafe: false
				}
			])
			.then(
				(val) => val,
				(err) => {
					logError(
						'Failed to call function: ',
						JSON.stringify(callExpr, null, ' '),
						'\n\rCall error:',
						err.toString()
					);
					return Promise.reject(err);
				}
			);
		return returnValue;
	}

	private evaluateRequestImpl(args: DebugProtocol.EvaluateArguments): Thenable<EvalOut | DebugVariable> {
		// default to the topmost stack frame of the current goroutine
		let goroutineId = -1;
		let frameId = 0;
		// args.frameId won't be specified when evaluating global vars
		if (args.frameId) {
			[goroutineId, frameId] = this.stackFrameHandles.get(args.frameId, [goroutineId, frameId]);
		}
		const scope = {
			goroutineID: goroutineId,
			frame: frameId
		};
		const apiV1Args = {
			symbol: args.expression,
			scope
		};
		const apiV2Args = {
			Expr: args.expression,
			Scope: scope,
			Cfg: this.delve.loadConfig
		};
		const evalSymbolArgs = this.delve.isApiV1 ? apiV1Args : apiV2Args;
		const returnValue = this.delve
			.callPromise<EvalOut | DebugVariable>(this.delve.isApiV1 ? 'EvalSymbol' : 'Eval', [evalSymbolArgs])
			.then(
				(val) => val,
				(err) => {
					log(
						'Failed to eval expression: ',
						JSON.stringify(evalSymbolArgs, null, ' '),
						'\n\rEval error:',
						err.toString()
					);
					return Promise.reject(err);
				}
			);
		return returnValue;
	}

	private addFullyQualifiedName(variables: DebugVariable[]) {
		variables.forEach((local) => {
			local.fullyQualifiedName = local.name;
			local.children.forEach((child) => {
				child.fullyQualifiedName = local.name;
			});
		});
	}

	private logDelveError(err: any, message: string) {
		if (err === undefined) {
			return;
		}

		let errorMessage = err.toString();
		// Use a more user friendly message for an unpropagated SIGSEGV (EXC_BAD_ACCESS)
		// signal that delve is unable to send back to the target process to be
		// handled as a panic.
		// https://github.com/microsoft/vscode-go/issues/1903#issuecomment-460126884
		// https://github.com/go-delve/delve/issues/852
		// This affects macOS only although we're agnostic of the OS at this stage.
		if (errorMessage === 'bad access') {
			// Reuse the panic message from the Go runtime.
			errorMessage =
				'runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation]\nUnable to propogate EXC_BAD_ACCESS signal to target process and panic (see https://github.com/go-delve/delve/issues/852)';
		}

		logError(message + ' - ' + errorMessage);
		this.dumpStacktrace();
	}

	private async dumpStacktrace() {
		// Get current goroutine
		// Debugger may be stopped at this point but we still can (and need) to obtain state and stacktrace
		let goroutineId = 0;
		try {
			this.debugState = await this.delve.getDebugState();
			// In some fault scenarios there may not be a currentGoroutine available from the debugger state
			// Use the current thread
			if (!this.debugState.currentGoroutine) {
				goroutineId = this.debugState.currentThread.goroutineID;
			} else {
				goroutineId = this.debugState.currentGoroutine.id;
			}
		} catch (error) {
			logError('dumpStacktrace - Failed to get debugger state ' + error);
		}

		// Get goroutine stacktrace
		const stackTraceIn = { id: goroutineId, depth: this.delve.stackTraceDepth };
		if (!this.delve.isApiV1) {
			Object.assign(stackTraceIn, { full: false, cfg: this.delve.loadConfig });
		}
		this.delve.call<DebugLocation[] | StacktraceOut>(
			this.delve.isApiV1 ? 'StacktraceGoroutine' : 'Stacktrace',
			[stackTraceIn],
			(err, out) => {
				if (err) {
					logError('dumpStacktrace: Failed to produce stack trace' + err);
					return;
				}
				const locations = this.delve.isApiV1 ? <DebugLocation[]>out : (<StacktraceOut>out).Locations;
				log('locations', locations);
				const stackFrames = locations.map((location, frameId) => {
					const uniqueStackFrameId = this.stackFrameHandles.create([goroutineId, frameId]);
					return new StackFrame(
						uniqueStackFrameId,
						location.function ? location.function.name : '<unknown>',
						location.file === '<autogenerated>'
							? null
							: new Source(path.basename(location.file), this.toLocalPath(location.file)),
						location.line,
						0
					);
				});

				// Dump stacktrace into error logger
				logError(`Last known immediate stacktrace (goroutine id ${goroutineId}):`);
				let output = '';
				stackFrames.forEach((stackFrame) => {
					output = output.concat(`\t${stackFrame.source.path}:${stackFrame.line}\n`);
					if (stackFrame.name) {
						output = output.concat(`\t\t${stackFrame.name}\n`);
					}
				});
				logError(output);
			}
		);
	}
}

// Class for fetching remote sources and packages
// in the remote program using Delve.
// tslint:disable-next-line:max-classes-per-file
export class RemoteSourcesAndPackages extends EventEmitter {
	public static readonly INITIALIZED = 'INITIALIZED';

	public initializingRemoteSourceFiles = false;
	public initializedRemoteSourceFiles = false;

	public remotePackagesBuildInfo: PackageBuildInfo[] = [];
	public remoteSourceFiles: string[] = [];
	public remoteSourceFilesNameGrouping = new Map<string, string[]>();

	/**
	 * Initialize and fill out remote packages build info and remote source files.
	 * Emits the INITIALIZED event once initialization is complete.
	 */
	public async initializeRemotePackagesAndSources(delve: Delve): Promise<void> {
		this.initializingRemoteSourceFiles = true;

		try {
			// ListPackagesBuildInfo is not available on V1.
			if (!delve.isApiV1 && this.remotePackagesBuildInfo.length === 0) {
				const packagesBuildInfoResponse: ListPackagesBuildInfoOut = await delve.callPromise(
					'ListPackagesBuildInfo',
					[{ IncludeFiles: true }]
				);
				if (packagesBuildInfoResponse && packagesBuildInfoResponse.List) {
					this.remotePackagesBuildInfo = packagesBuildInfoResponse.List;
				}
			}

			// List sources will return all the source files used by Delve.
			if (delve.isApiV1) {
				this.remoteSourceFiles = await delve.callPromise('ListSources', []);
			} else {
				const listSourcesResponse: ListSourcesOut = await delve.callPromise('ListSources', [{}]);
				if (listSourcesResponse && listSourcesResponse.Sources) {
					this.remoteSourceFiles = listSourcesResponse.Sources;
				}
			}

			// Group the source files by name for easy searching later.
			this.remoteSourceFiles = this.remoteSourceFiles.filter((sourceFile) => !sourceFile.startsWith('<'));
			this.remoteSourceFiles.forEach((sourceFile) => {
				const fileName = getBaseName(sourceFile);
				if (!this.remoteSourceFilesNameGrouping.has(fileName)) {
					this.remoteSourceFilesNameGrouping.set(fileName, []);
				}
				this.remoteSourceFilesNameGrouping.get(fileName).push(sourceFile);
			});
		} catch (error) {
			logError(`Failed to initialize remote sources and packages: ${error && error.message}`);
		} finally {
			this.emit(RemoteSourcesAndPackages.INITIALIZED);
			this.initializedRemoteSourceFiles = true;
		}
	}
}

function random(low: number, high: number): number {
	return Math.floor(Math.random() * (high - low) + low);
}

async function removeFile(filePath: string): Promise<void> {
	try {
		const fileExists = await fsAccess(filePath)
			.then(() => true)
			.catch(() => false);
		if (filePath && fileExists) {
			await fsUnlink(filePath);
		}
	} catch (e) {
		logError(`Potentially failed remove file: ${filePath} - ${e.toString() || ''}`);
	}
}

// queryGOROOT returns `go env GOROOT`.
function queryGOROOT(cwd: any, env: any): Promise<string> {
	return new Promise<string>((resolve) => {
		execFile(
			getBinPathWithPreferredGopathGoroot('go', []),
			['env', 'GOROOT'],
			{ cwd, env },
			(err, stdout, stderr) => {
				if (err) {
					return resolve('');
				}
				return resolve(stdout.trim());
			}
		);
	});
}

DebugSession.run(GoDebugSession);
