func (ld *loader) loadPackage(lpkg *loaderPackage) {
	if lpkg.PkgPath == "unsafe" {
		lpkg.Types = types.Unsafe
		lpkg.Fset = ld.Fset
		lpkg.Syntax = []*ast.File{}
		lpkg.TypesInfo = new(types.Info)
		lpkg.TypesSizes = ld.sizes
		return
	}
	lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name)
	lpkg.Fset = ld.Fset
	if !lpkg.needtypes && !lpkg.needsrc {
		return
	}
	if !lpkg.needsrc {
		ld.loadFromExportData(lpkg)
		return  
	}
	appendError := func(err error) {
		var errs []Error
		switch err := err.(type) {
		case Error:
			errs = append(errs, err)
		case *os.PathError:
			errs = append(errs, Error{
				Pos:  err.Path + ":1",
				Msg:  err.Err.Error(),
				Kind: ParseError,
			})
		case scanner.ErrorList:
			for _, err := range err {
				errs = append(errs, Error{
					Pos:  err.Pos.String(),
					Msg:  err.Msg,
					Kind: ParseError,
				})
			}
		case types.Error:
			errs = append(errs, Error{
				Pos:  err.Fset.Position(err.Pos).String(),
				Msg:  err.Msg,
				Kind: TypeError,
			})
		default:
			errs = append(errs, Error{
				Pos:  "-",
				Msg:  err.Error(),
				Kind: UnknownError,
			})
			log.Printf("internal error: error %q (%T) without position", err, err)
		}
		lpkg.Errors = append(lpkg.Errors, errs...)
	}
	if ld.Config.Mode&NeedTypes != 0 && len(lpkg.CompiledGoFiles) == 0 && lpkg.ExportFile != "" {
		appendError(Error{"-", fmt.Sprintf("sources missing for package %s", lpkg.ID), ParseError})
		ld.loadFromExportData(lpkg)
		return  
	}
	files, errs := ld.parseFiles(lpkg.CompiledGoFiles)
	for _, err := range errs {
		appendError(err)
	}
	lpkg.Syntax = files
	if ld.Config.Mode&NeedTypes == 0 {
		return
	}
	lpkg.TypesInfo = &types.Info{
		Types:      make(map[ast.Expr]types.TypeAndValue),
		Defs:       make(map[*ast.Ident]types.Object),
		Uses:       make(map[*ast.Ident]types.Object),
		Implicits:  make(map[ast.Node]types.Object),
		Scopes:     make(map[ast.Node]*types.Scope),
		Selections: make(map[*ast.SelectorExpr]*types.Selection),
	}
	lpkg.TypesSizes = ld.sizes
	importer := importerFunc(func(path string) (*types.Package, error) {
		if path == "unsafe" {
			return types.Unsafe, nil
		}
		ipkg := lpkg.Imports[path]
		if ipkg == nil {
			if err := lpkg.importErrors[path]; err != nil {
				return nil, err
			}
			return nil, fmt.Errorf("no metadata for %s", path)
		}
		if ipkg.Types != nil && ipkg.Types.Complete() {
			return ipkg.Types, nil
		}
		log.Fatalf("internal error: package %q without types was imported from %q", path, lpkg)
		panic("unreachable")
	})
	tc := &types.Config{
		Importer: importer,
		IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial,
		Error: appendError,
		Sizes: ld.sizes,
	}
	if (ld.Mode & typecheckCgo) != 0 {
		if !typesinternal.SetUsesCgo(tc) {
			appendError(Error{
				Msg:  "typecheckCgo requires Go 1.15+",
				Kind: ListError,
			})
			return
		}
	}
	types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)
	lpkg.importErrors = nil  
	if tc.FakeImportC {
	outer:
		for _, f := range lpkg.Syntax {
			for _, imp := range f.Imports {
				if imp.Path.Value == `"C"` {
					err := types.Error{Fset: ld.Fset, Pos: imp.Pos(), Msg: `import "C" ignored`}
					appendError(err)
					break outer
				}
			}
		}
	}
	illTyped := len(lpkg.Errors) > 0
	if !illTyped {
		for _, imp := range lpkg.Imports {
			if imp.IllTyped {
				illTyped = true
				break
			}
		}
	}
	lpkg.IllTyped = illTyped
}
loadPackage loads the specified package.
It must be called only once per Package,
after immediate dependencies are loaded.
Precondition: ld.Mode & NeedTypes.
package packages
import (
	"context"
	"encoding/json"
	"fmt"
	"go/ast"
	"go/parser"
	"go/scanner"
	"go/token"
	"go/types"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"
	"golang.org/x/tools/go/gcexportdata"
	"golang.org/x/tools/internal/gocommand"
	"golang.org/x/tools/internal/packagesinternal"
	"golang.org/x/tools/internal/typesinternal"
)
type LoadMode int
const (
	NeedName LoadMode = 1 << iota
	NeedFiles
	NeedCompiledGoFiles
	NeedImports
	NeedDeps
	NeedExportsFile
	NeedTypes
	NeedSyntax
	NeedTypesInfo
	NeedTypesSizes
	typecheckCgo
	NeedModule
)
const (
	LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles
	LoadImports = LoadFiles | NeedImports
	LoadTypes = LoadImports | NeedTypes | NeedTypesSizes
	LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo
	LoadAllSyntax = LoadSyntax | NeedDeps
)
type Config struct {
	Mode LoadMode
	Context context.Context
	Logf func(format string, args ...interface{})
	Dir string
	Env []string
	gocmdRunner *gocommand.Runner
	BuildFlags []string
	modFile string
	modFlag string
	Fset *token.FileSet
	ParseFile func(fset *token.FileSet, filename string, src []byte) (*ast.File, error)
	Tests bool
	Overlay map[string][]byte
}
type driver func(cfg *Config, patterns ...string) (*driverResponse, error)
type driverResponse struct {
	NotHandled bool
	Sizes *types.StdSizes
	Roots []string `json:",omitempty"`
	Packages []*Package
}
func Load(cfg *Config, patterns ...string) ([]*Package, error) {
	l := newLoader(cfg)
	response, err := defaultDriver(&l.Config, patterns...)
	if err != nil {
		return nil, err
	}
	l.sizes = response.Sizes
	return l.refine(response.Roots, response.Packages...)
}
func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
	driver := findExternalDriver(cfg)
	if driver == nil {
		driver = goListDriver
	}
	response, err := driver(cfg, patterns...)
	if err != nil {
		return response, err
	} else if response.NotHandled {
		return goListDriver(cfg, patterns...)
	}
	return response, nil
}
type Package struct {
	ID string
	Name string
	PkgPath string
	Errors []Error
	GoFiles []string
	CompiledGoFiles []string
	OtherFiles []string
	IgnoredFiles []string
	ExportFile string
	Imports map[string]*Package
	Types *types.Package
	Fset *token.FileSet
	IllTyped bool
	Syntax []*ast.File
	TypesInfo *types.Info
	TypesSizes types.Sizes
	forTest string
	depsErrors []*packagesinternal.PackageError
	Module *Module
}
type Module struct {
	Path      string        
	Version   string        
	Replace   *Module       
	Time      *time.Time    
	Main      bool          
	Indirect  bool          
	Dir       string        
	GoMod     string        
	GoVersion string        
	Error     *ModuleError  
}
type ModuleError struct {
	Err string  
}
func init() {
	packagesinternal.GetForTest = func(p interface{}) string {
		return p.(*Package).forTest
	}
	packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError {
		return p.(*Package).depsErrors
	}
	packagesinternal.GetGoCmdRunner = func(config interface{}) *gocommand.Runner {
		return config.(*Config).gocmdRunner
	}
	packagesinternal.SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) {
		config.(*Config).gocmdRunner = runner
	}
	packagesinternal.SetModFile = func(config interface{}, value string) {
		config.(*Config).modFile = value
	}
	packagesinternal.SetModFlag = func(config interface{}, value string) {
		config.(*Config).modFlag = value
	}
	packagesinternal.TypecheckCgo = int(typecheckCgo)
}
type Error struct {
	Pos  string  
	Msg  string
	Kind ErrorKind
}
type ErrorKind int
const (
	UnknownError ErrorKind = iota
	ListError
	ParseError
	TypeError
)
func (err Error) Error() string {
	pos := err.Pos
	if pos == "" {
		pos = "-"  
	}
	return pos + ": " + err.Msg
}
type flatPackage struct {
	ID              string
	Name            string            `json:",omitempty"`
	PkgPath         string            `json:",omitempty"`
	Errors          []Error           `json:",omitempty"`
	GoFiles         []string          `json:",omitempty"`
	CompiledGoFiles []string          `json:",omitempty"`
	OtherFiles      []string          `json:",omitempty"`
	IgnoredFiles    []string          `json:",omitempty"`
	ExportFile      string            `json:",omitempty"`
	Imports         map[string]string `json:",omitempty"`
}
func (p *Package) MarshalJSON() ([]byte, error) {
	flat := &flatPackage{
		ID:              p.ID,
		Name:            p.Name,
		PkgPath:         p.PkgPath,
		Errors:          p.Errors,
		GoFiles:         p.GoFiles,
		CompiledGoFiles: p.CompiledGoFiles,
		OtherFiles:      p.OtherFiles,
		IgnoredFiles:    p.IgnoredFiles,
		ExportFile:      p.ExportFile,
	}
	if len(p.Imports) > 0 {
		flat.Imports = make(map[string]string, len(p.Imports))
		for path, ipkg := range p.Imports {
			flat.Imports[path] = ipkg.ID
		}
	}
	return json.Marshal(flat)
}
func (p *Package) UnmarshalJSON(b []byte) error {
	flat := &flatPackage{}
	if err := json.Unmarshal(b, &flat); err != nil {
		return err
	}
	*p = Package{
		ID:              flat.ID,
		Name:            flat.Name,
		PkgPath:         flat.PkgPath,
		Errors:          flat.Errors,
		GoFiles:         flat.GoFiles,
		CompiledGoFiles: flat.CompiledGoFiles,
		OtherFiles:      flat.OtherFiles,
		ExportFile:      flat.ExportFile,
	}
	if len(flat.Imports) > 0 {
		p.Imports = make(map[string]*Package, len(flat.Imports))
		for path, id := range flat.Imports {
			p.Imports[path] = &Package{ID: id}
		}
	}
	return nil
}
func (p *Package) String() string { return p.ID }
type loaderPackage struct {
	*Package
	importErrors map[string]error  
	loadOnce     sync.Once
	color        uint8  
	needsrc      bool   
	needtypes    bool   
	initial      bool   
}
type loader struct {
	pkgs map[string]*loaderPackage
	Config
	sizes        types.Sizes
	parseCache   map[string]*parseValue
	parseCacheMu sync.Mutex
	exportMu     sync.Mutex  
	requestedMode LoadMode
}
type parseValue struct {
	f     *ast.File
	err   error
	ready chan struct{}
}
func newLoader(cfg *Config) *loader {
	ld := &loader{
		parseCache: map[string]*parseValue{},
	}
	if cfg != nil {
		ld.Config = *cfg
		ld.Config.Logf = cfg.Logf
	}
	if ld.Config.Logf == nil {
		if debug {
			ld.Config.Logf = log.Printf
		} else {
			ld.Config.Logf = func(format string, args ...interface{}) {}
		}
	}
	if ld.Config.Mode == 0 {
		ld.Config.Mode = NeedName | NeedFiles | NeedCompiledGoFiles  
	}
	if ld.Config.Env == nil {
		ld.Config.Env = os.Environ()
	}
	if ld.Config.gocmdRunner == nil {
		ld.Config.gocmdRunner = &gocommand.Runner{}
	}
	if ld.Context == nil {
		ld.Context = context.Background()
	}
	if ld.Dir == "" {
		if dir, err := os.Getwd(); err == nil {
			ld.Dir = dir
		}
	}
	ld.requestedMode = ld.Mode
	ld.Mode = impliedLoadMode(ld.Mode)
	if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
		if ld.Fset == nil {
			ld.Fset = token.NewFileSet()
		}
		if ld.ParseFile == nil {
			ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
				const mode = parser.AllErrors | parser.ParseComments
				return parser.ParseFile(fset, filename, src, mode)
			}
		}
	}
	return ld
}
func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
	rootMap := make(map[string]int, len(roots))
	for i, root := range roots {
		rootMap[root] = i
	}
	ld.pkgs = make(map[string]*loaderPackage)
	var initial = make([]*loaderPackage, len(roots))
	for _, pkg := range list {
		rootIndex := -1
		if i, found := rootMap[pkg.ID]; found {
			rootIndex = i
		}
		exportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == "" && pkg.PkgPath != "unsafe"
		needtypes := (ld.Mode&NeedTypes|NeedTypesInfo != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0))
		needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) ||
			(ld.Mode&NeedTypes|NeedTypesInfo != 0 && exportDataInvalid)) && pkg.PkgPath != "unsafe"
		lpkg := &loaderPackage{
			Package:   pkg,
			needtypes: needtypes,
			needsrc:   needsrc,
		}
		ld.pkgs[lpkg.ID] = lpkg
		if rootIndex >= 0 {
			initial[rootIndex] = lpkg
			lpkg.initial = true
		}
	}
	for i, root := range roots {
		if initial[i] == nil {
			return nil, fmt.Errorf("root package %v is missing", root)
		}
	}
	const (
		white = 0  
		grey  = 1  
		black = 2  
	)
	var stack []*loaderPackage
	var visit func(lpkg *loaderPackage) bool
	var srcPkgs []*loaderPackage
	visit = func(lpkg *loaderPackage) bool {
		switch lpkg.color {
		case black:
			return lpkg.needsrc
		case grey:
			panic("internal error: grey node")
		}
		lpkg.color = grey
		stack = append(stack, lpkg)  
		stubs := lpkg.Imports        
		if ld.Mode&NeedImports != 0 {
			lpkg.Imports = make(map[string]*Package, len(stubs))
			for importPath, ipkg := range stubs {
				var importErr error
				imp := ld.pkgs[ipkg.ID]
				if imp == nil {
					importErr = fmt.Errorf("missing package: %q", ipkg.ID)
				} else if imp.color == grey {
					importErr = fmt.Errorf("import cycle: %s", stack)
				}
				if importErr != nil {
					if lpkg.importErrors == nil {
						lpkg.importErrors = make(map[string]error)
					}
					lpkg.importErrors[importPath] = importErr
					continue
				}
				if visit(imp) {
					lpkg.needsrc = true
				}
				lpkg.Imports[importPath] = imp.Package
			}
		}
		if lpkg.needsrc {
			srcPkgs = append(srcPkgs, lpkg)
		}
		if ld.Mode&NeedTypesSizes != 0 {
			lpkg.TypesSizes = ld.sizes
		}
		stack = stack[:len(stack)-1]  
		lpkg.color = black
		return lpkg.needsrc
	}
	if ld.Mode&NeedImports == 0 {
		for _, lpkg := range initial {
			lpkg.Imports = nil
		}
	} else {
		for _, lpkg := range initial {
			visit(lpkg)
		}
	}
	if ld.Mode&NeedImports != 0 && ld.Mode&NeedTypes != 0 {
		for _, lpkg := range srcPkgs {
			for _, ipkg := range lpkg.Imports {
				imp := ld.pkgs[ipkg.ID]
				imp.needtypes = true
			}
		}
	}
	if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
		var wg sync.WaitGroup
		for _, lpkg := range initial {
			wg.Add(1)
			go func(lpkg *loaderPackage) {
				ld.loadRecursive(lpkg)
				wg.Done()
			}(lpkg)
		}
		wg.Wait()
	}
	result := make([]*Package, len(initial))
	for i, lpkg := range initial {
		result[i] = lpkg.Package
	}
	for i := range ld.pkgs {
		if ld.requestedMode&NeedName == 0 {
			ld.pkgs[i].Name = ""
			ld.pkgs[i].PkgPath = ""
		}
		if ld.requestedMode&NeedFiles == 0 {
			ld.pkgs[i].GoFiles = nil
			ld.pkgs[i].OtherFiles = nil
			ld.pkgs[i].IgnoredFiles = nil
		}
		if ld.requestedMode&NeedCompiledGoFiles == 0 {
			ld.pkgs[i].CompiledGoFiles = nil
		}
		if ld.requestedMode&NeedImports == 0 {
			ld.pkgs[i].Imports = nil
		}
		if ld.requestedMode&NeedExportsFile == 0 {
			ld.pkgs[i].ExportFile = ""
		}
		if ld.requestedMode&NeedTypes == 0 {
			ld.pkgs[i].Types = nil
			ld.pkgs[i].Fset = nil
			ld.pkgs[i].IllTyped = false
		}
		if ld.requestedMode&NeedSyntax == 0 {
			ld.pkgs[i].Syntax = nil
		}
		if ld.requestedMode&NeedTypesInfo == 0 {
			ld.pkgs[i].TypesInfo = nil
		}
		if ld.requestedMode&NeedTypesSizes == 0 {
			ld.pkgs[i].TypesSizes = nil
		}
		if ld.requestedMode&NeedModule == 0 {
			ld.pkgs[i].Module = nil
		}
	}
	return result, nil
}
func (ld *loader) loadRecursive(lpkg *loaderPackage) {
	lpkg.loadOnce.Do(func() {
		var wg sync.WaitGroup
		for _, ipkg := range lpkg.Imports {
			imp := ld.pkgs[ipkg.ID]
			wg.Add(1)
			go func(imp *loaderPackage) {
				ld.loadRecursive(imp)
				wg.Done()
			}(imp)
		}
		wg.Wait()
		ld.loadPackage(lpkg)
	})
}