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;
}