async function goListPkgs()

in src/goPackages.ts [49:109]


async function goListPkgs(workDir?: string): Promise<Map<string, PackageInfo>> {
	const pkgs = new Map<string, PackageInfo>();

	if (workDir) {
		workDir = fixDriveCasingInWindows(workDir);
	}

	const goBin = getBinPath('go');
	if (!goBin) {
		vscode.window.showErrorMessage(
			`Failed to run "go list" to fetch packages as the "go" binary cannot be found in either GOROOT(${getCurrentGoRoot()}) or PATH(${getEnvPath()})`
		);
		return pkgs;
	}
	const t0 = Date.now();

	const args = ['list', '-e', '-f', '{{.Name}};{{.ImportPath}};{{.Dir}}', 'std', 'all'];
	const env = toolExecutionEnvironment();
	const execFile = promisify(cp.execFile);
	try {
		const { stdout, stderr } = await execFile(goBin, args, { env, cwd: workDir });
		if (stderr) {
			throw stderr;
		}
		const goroot = getCurrentGoRoot();
		stdout.split('\n').forEach((pkgDetail) => {
			if (!pkgDetail || !pkgDetail.trim() || pkgDetail.indexOf(';') === -1) {
				return;
			}
			const [pkgName, pkgPath, pkgDir] = pkgDetail.trim().split(';');
			const pkgDirNormalized = fixDriveCasingInWindows(pkgDir);
			// goListPkgs are used to retrieve packages importable from packages under workDir.
			// Vendored packages outside the workDir, thus, do not qualify.
			// (equivalent to `gopkgs -workDir`)
			// Remove vendored packages if it's outside the current workDir (e.g. vendor of Go project's src/ and src/cmd)
			if (workDir) {
				const vendorIdx = pkgDirNormalized.indexOf('/vendor/');
				if (
					vendorIdx !== -1 &&
					// Both workDir (from vscode file path) and pkgDir (from go list -f {{.Dir}}) are absolute.
					!workDir.startsWith(pkgDirNormalized.substring(0, vendorIdx))
				) {
					return;
				}
			}
			pkgs.set(pkgPath, {
				name: pkgName,
				isStd: goroot === null ? false : pkgDir.startsWith(goroot)
			});
		});
	} catch (err) {
		vscode.window.showErrorMessage(
			`Running go list failed with "${err}"\nCheck if you can run \`go ${args.join(
				' '
			)}\` in a terminal successfully.`
		);
	}
	const timeTaken = Date.now() - t0;
	cacheTimeout = timeTaken > 5000 ? timeTaken : 5000;
	return pkgs;
}