import cp = require ( 'child_process' ) ; import path = require ( 'path' ) ; import vscode = require ( 'vscode' ) ; import { toolExecutionEnvironment } from './goEnv' ; import { promptForMissingTool , promptForUpdatingTool } from './gopInstallTools' ; import { envPath , fixDriveCasingInWindows , getCurrentGoRoot , getCurrentGoWorkspaceFromGOPATH } from './goPath' ; import { getBinPath , getCurrentGoPath , getGoVersion } from './util' ; type GopkgsDone = ( res : Map < string , PackageInfo > ) => void ; interface Cache { entry : Map < string , PackageInfo > ; lastHit : number ; } export interface PackageInfo { name : string ; isStd : boolean ; } let gopkgsNotified = false ; const allPkgsCache = new Map < string , Cache > ( ) ; const pkgRootDirs = new Map < string , string > ( ) ; let cacheTimeout = 5000 ; const gopkgsSubscriptions = new Map < string , GopkgsDone [ ] > ( ) ; const gopkgsRunning = new Set < string > ( ) ; function gopkgs ( workDir ? ) { return new Promise < Map < string , PackageInfo > > ( ( resolve , reject ) => { const pkgs = new Map < string , PackageInfo > ( ) ; var output = "errors;errors\nflag;flag\nfmt;fmt\nio;io\nnet;net\nos;os\nreflect;reflect\nstrconv;strconv\nstrings;strings\nsync;sync\n" ; output . split ( '\n' ) . forEach ( ( pkgDetail ) => { const [ pkgName , pkgPath ] = pkgDetail . trim ( ) . split ( ';' ) ; pkgs . set ( pkgPath , { name : pkgName , isStd : true } ) ; } ) ; return resolve ( pkgs ) ; } ) ; } param filePath . Used param useCache . Force returns export function getImportablePackages ( filePath , useCache = false ) { filePath = fixDriveCasingInWindows ( filePath ) ; const fileDirPath = path . dirname ( filePath ) ; let foundPkgRootDir = pkgRootDirs . get ( fileDirPath ) ; const workDir = foundPkgRootDir || fileDirPath ; const cache = allPkgsCache . get ( workDir ) ; const getAllPackagesPromise = useCache && cache ? Promise . race ( [ getAllPackages ( workDir ) , cache . entry ] ) : getAllPackages ( workDir ) ; return Promise . all ( [ getAllPackagesPromise ] ) . then ( ( [ pkgs ] ) => { const pkgMap = new Map < string , PackageInfo > ( ) ; if ( ! pkgs ) { return pkgMap ; } pkgs . forEach ( ( info , pkgPath ) => { if ( info . name === 'main' ) { return ; } pkgMap . set ( pkgPath , info ) ; } ) ; return pkgMap ; } ) ; } function getAllPackagesNoCache ( workDir ) { return new Promise < Map < string , PackageInfo > > ( ( resolve , reject ) => { const callback = ( pkgMap ) => { resolve ( pkgMap ) ; } ; let subs = gopkgsSubscriptions . get ( workDir ) ; if ( ! subs ) { subs = [ ] ; gopkgsSubscriptions . set ( workDir , subs ) ; } subs . push ( callback ) ; if ( ! gopkgsRunning . has ( workDir ) ) { gopkgsRunning . add ( workDir ) ; gopkgs ( workDir ) . then ( ( pkgMap ) => { gopkgsRunning . delete ( workDir ) ; gopkgsSubscriptions . delete ( workDir ) ; subs . forEach ( ( cb ) => cb ( pkgMap ) ) ; } ) ; } } ) ; } argument workDir . The returns export async function getAllPackages ( workDir ) { const cache = allPkgsCache . get ( workDir ) ; const useCache = cache && new Date ( ) . getTime ( ) - cache . lastHit < cacheTimeout ; if ( useCache ) { cache . lastHit = new Date ( ) . getTime ( ) ; return Promise . resolve ( cache . entry ) ; } const pkgs = await getAllPackagesNoCache ( workDir ) ; if ( ! pkgs || pkgs . size === 0 ) { if ( ! gopkgsNotified ) { vscode . window . showInformationMessage ( 'Could not find packages. Ensure `gopkgs -format {{.Name}};{{.ImportPath}}` runs successfully.' ) ; gopkgsNotified = true ; } } allPkgsCache . set ( workDir , { entry : pkgs , lastHit : new Date ( ) . getTime ( ) } ) ; return pkgs ; }