// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package packages

// See doc.go for package documentation and implementation notes.

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	
	
	
	
	
)

// A LoadMode controls the amount of detail to return when loading.
// The bits below can be combined to specify which fields should be
// filled in the result packages.
// The zero value is a special case, equivalent to combining
// the NeedName, NeedFiles, and NeedCompiledGoFiles bits.
// ID and Errors (if present) will always be filled.
// Load may return more information than requested.
type LoadMode int

const (
	// NeedName adds Name and PkgPath.
	NeedName LoadMode = 1 << iota

	// NeedFiles adds GoFiles and OtherFiles.
	NeedFiles

	// NeedCompiledGoFiles adds CompiledGoFiles.
	NeedCompiledGoFiles

	// NeedImports adds Imports. If NeedDeps is not set, the Imports field will contain
	// "placeholder" Packages with only the ID set.
	NeedImports

	// NeedDeps adds the fields requested by the LoadMode in the packages in Imports.
	NeedDeps

	// NeedExportFile adds ExportFile.
	NeedExportFile

	// NeedTypes adds Types, Fset, and IllTyped.
	NeedTypes

	// NeedSyntax adds Syntax.
	NeedSyntax

	// NeedTypesInfo adds TypesInfo.
	NeedTypesInfo

	// NeedTypesSizes adds TypesSizes.
	NeedTypesSizes

	// needInternalDepsErrors adds the internal deps errors field for use by gopls.
	needInternalDepsErrors

	// needInternalForTest adds the internal forTest field.
	// Tests must also be set on the context for this field to be populated.
	needInternalForTest

	// typecheckCgo enables full support for type checking cgo. Requires Go 1.15+.
	// Modifies CompiledGoFiles and Types, and has no effect on its own.
	typecheckCgo

	// NeedModule adds Module.
	NeedModule

	// NeedEmbedFiles adds EmbedFiles.
	NeedEmbedFiles

	// NeedEmbedPatterns adds EmbedPatterns.
	NeedEmbedPatterns
)

const (
	// Deprecated: LoadFiles exists for historical compatibility
	// and should not be used. Please directly specify the needed fields using the Need values.
	LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles

	// Deprecated: LoadImports exists for historical compatibility
	// and should not be used. Please directly specify the needed fields using the Need values.
	LoadImports = LoadFiles | NeedImports

	// Deprecated: LoadTypes exists for historical compatibility
	// and should not be used. Please directly specify the needed fields using the Need values.
	LoadTypes = LoadImports | NeedTypes | NeedTypesSizes

	// Deprecated: LoadSyntax exists for historical compatibility
	// and should not be used. Please directly specify the needed fields using the Need values.
	LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo

	// Deprecated: LoadAllSyntax exists for historical compatibility
	// and should not be used. Please directly specify the needed fields using the Need values.
	LoadAllSyntax = LoadSyntax | NeedDeps

	// Deprecated: NeedExportsFile is a historical misspelling of NeedExportFile.
	NeedExportsFile = NeedExportFile
)

// A Config specifies details about how packages should be loaded.
// The zero value is a valid configuration.
// Calls to Load do not modify this struct.
type Config struct {
	// Mode controls the level of information returned for each package.
	Mode LoadMode

	// Context specifies the context for the load operation.
	// If the context is cancelled, the loader may stop early
	// and return an ErrCancelled error.
	// If Context is nil, the load cannot be cancelled.
	Context context.Context

	// Logf is the logger for the config.
	// If the user provides a logger, debug logging is enabled.
	// If the GOPACKAGESDEBUG environment variable is set to true,
	// but the logger is nil, default to log.Printf.
	Logf func(format string, args ...interface{})

	// Dir is the directory in which to run the build system's query tool
	// that provides information about the packages.
	// If Dir is empty, the tool is run in the current directory.
	Dir string

	// Env is the environment to use when invoking the build system's query tool.
	// If Env is nil, the current environment is used.
	// As in os/exec's Cmd, only the last value in the slice for
	// each environment key is used. To specify the setting of only
	// a few variables, append to the current environment, as in:
	//
	//	opt.Env = append(os.Environ(), "GOOS=plan9", "GOARCH=386")
	//
	Env []string

	// gocmdRunner guards go command calls from concurrency errors.
	gocmdRunner *gocommand.Runner

	// BuildFlags is a list of command-line flags to be passed through to
	// the build system's query tool.
	BuildFlags []string

	// modFile will be used for -modfile in go command invocations.
	modFile string

	// modFlag will be used for -modfile in go command invocations.
	modFlag string

	// Fset provides source position information for syntax trees and types.
	// If Fset is nil, Load will use a new fileset, but preserve Fset's value.
	Fset *token.FileSet

	// ParseFile is called to read and parse each file
	// when preparing a package's type-checked syntax tree.
	// It must be safe to call ParseFile simultaneously from multiple goroutines.
	// If ParseFile is nil, the loader will uses parser.ParseFile.
	//
	// ParseFile should parse the source from src and use filename only for
	// recording position information.
	//
	// An application may supply a custom implementation of ParseFile
	// to change the effective file contents or the behavior of the parser,
	// or to modify the syntax tree. For example, selectively eliminating
	// unwanted function bodies can significantly accelerate type checking.
	ParseFile func(fset *token.FileSet, filename string, src []byte) (*ast.File, error)

	// If Tests is set, the loader includes not just the packages
	// matching a particular pattern but also any related test packages,
	// including test-only variants of the package and the test executable.
	//
	// For example, when using the go command, loading "fmt" with Tests=true
	// returns four packages, with IDs "fmt" (the standard package),
	// "fmt [fmt.test]" (the package as compiled for the test),
	// "fmt_test" (the test functions from source files in package fmt_test),
	// and "fmt.test" (the test binary).
	//
	// In build systems with explicit names for tests,
	// setting Tests may have no effect.
	Tests bool

	// Overlay provides a mapping of absolute file paths to file contents.
	// If the file with the given path already exists, the parser will use the
	// alternative file contents provided by the map.
	//
	// Overlays provide incomplete support for when a given file doesn't
	// already exist on disk. See the package doc above for more details.
	Overlay map[string][]byte
}

// driver is the type for functions that query the build system for the
// packages named by the patterns.
type driver func(cfg *Config, patterns ...string) (*driverResponse, error)

// driverResponse contains the results for a driver query.
type driverResponse struct {
	// NotHandled is returned if the request can't be handled by the current
	// driver. If an external driver returns a response with NotHandled, the
	// rest of the driverResponse is ignored, and go/packages will fallback
	// to the next driver. If go/packages is extended in the future to support
	// lists of multiple drivers, go/packages will fall back to the next driver.
	NotHandled bool

	// Sizes, if not nil, is the types.Sizes to use when type checking.
	Sizes *types.StdSizes

	// Roots is the set of package IDs that make up the root packages.
	// We have to encode this separately because when we encode a single package
	// we cannot know if it is one of the roots as that requires knowledge of the
	// graph it is part of.
	Roots []string `json:",omitempty"`

	// Packages is the full set of packages in the graph.
	// The packages are not connected into a graph.
	// The Imports if populated will be stubs that only have their ID set.
	// Imports will be connected and then type and syntax information added in a
	// later pass (see refine).
	Packages []*Package

	// GoVersion is the minor version number used by the driver
	// (e.g. the go command on the PATH) when selecting .go files.
	// Zero means unknown.
	GoVersion int
}

// Load loads and returns the Go packages named by the given patterns.
//
// Config specifies loading options;
// nil behaves the same as an empty Config.
//
// Load returns an error if any of the patterns was invalid
// as defined by the underlying build system.
// It may return an empty list of packages without an error,
// for instance for an empty expansion of a valid wildcard.
// Errors associated with a particular package are recorded in the
// corresponding Package's Errors list, and do not cause Load to
// return an error. Clients may need to handle such errors before
// proceeding with further analysis. The PrintErrors function is
// provided for convenient display of all errors.
func ( *Config,  ...string) ([]*Package, error) {
	 := newLoader()
	,  := defaultDriver(&.Config, ...)
	if  != nil {
		return nil, 
	}
	.sizes = .Sizes
	return .refine()
}

// defaultDriver is a driver that implements go/packages' fallback behavior.
// It will try to request to an external driver, if one exists. If there's
// no external driver, or the driver returns a response with NotHandled set,
// defaultDriver will fall back to the go list driver.
func ( *Config,  ...string) (*driverResponse, error) {
	 := findExternalDriver()
	if  == nil {
		 = goListDriver
	}
	,  := (, ...)
	if  != nil {
		return , 
	} else if .NotHandled {
		return goListDriver(, ...)
	}
	return , nil
}

// A Package describes a loaded Go package.
type Package struct {
	// ID is a unique identifier for a package,
	// in a syntax provided by the underlying build system.
	//
	// Because the syntax varies based on the build system,
	// clients should treat IDs as opaque and not attempt to
	// interpret them.
	ID string

	// Name is the package name as it appears in the package source code.
	Name string

	// PkgPath is the package path as used by the go/types package.
	PkgPath string

	// Errors contains any errors encountered querying the metadata
	// of the package, or while parsing or type-checking its files.
	Errors []Error

	// TypeErrors contains the subset of errors produced during type checking.
	TypeErrors []types.Error

	// GoFiles lists the absolute file paths of the package's Go source files.
	GoFiles []string

	// CompiledGoFiles lists the absolute file paths of the package's source
	// files that are suitable for type checking.
	// This may differ from GoFiles if files are processed before compilation.
	CompiledGoFiles []string

	// OtherFiles lists the absolute file paths of the package's non-Go source files,
	// including assembly, C, C++, Fortran, Objective-C, SWIG, and so on.
	OtherFiles []string

	// EmbedFiles lists the absolute file paths of the package's files
	// embedded with go:embed.
	EmbedFiles []string

	// EmbedPatterns lists the absolute file patterns of the package's
	// files embedded with go:embed.
	EmbedPatterns []string

	// IgnoredFiles lists source files that are not part of the package
	// using the current build configuration but that might be part of
	// the package using other build configurations.
	IgnoredFiles []string

	// ExportFile is the absolute path to a file containing type
	// information for the package as provided by the build system.
	ExportFile string

	// Imports maps import paths appearing in the package's Go source files
	// to corresponding loaded Packages.
	Imports map[string]*Package

	// Types provides type information for the package.
	// The NeedTypes LoadMode bit sets this field for packages matching the
	// patterns; type information for dependencies may be missing or incomplete,
	// unless NeedDeps and NeedImports are also set.
	Types *types.Package

	// Fset provides position information for Types, TypesInfo, and Syntax.
	// It is set only when Types is set.
	Fset *token.FileSet

	// IllTyped indicates whether the package or any dependency contains errors.
	// It is set only when Types is set.
	IllTyped bool

	// Syntax is the package's syntax trees, for the files listed in CompiledGoFiles.
	//
	// The NeedSyntax LoadMode bit populates this field for packages matching the patterns.
	// If NeedDeps and NeedImports are also set, this field will also be populated
	// for dependencies.
	//
	// Syntax is kept in the same order as CompiledGoFiles, with the caveat that nils are
	// removed.  If parsing returned nil, Syntax may be shorter than CompiledGoFiles.
	Syntax []*ast.File

	// TypesInfo provides type information about the package's syntax trees.
	// It is set only when Syntax is set.
	TypesInfo *types.Info

	// TypesSizes provides the effective size function for types in TypesInfo.
	TypesSizes types.Sizes

	// forTest is the package under test, if any.
	forTest string

	// depsErrors is the DepsErrors field from the go list response, if any.
	depsErrors []*packagesinternal.PackageError

	// module is the module information for the package if it exists.
	Module *Module
}

// Module provides module information for a package.
type Module struct {
	Path      string       // module path
	Version   string       // module version
	Replace   *Module      // replaced by this module
	Time      *time.Time   // time version was created
	Main      bool         // is this the main module?
	Indirect  bool         // is this module only an indirect dependency of main module?
	Dir       string       // directory holding files for this module, if any
	GoMod     string       // path to go.mod file used when loading this module, if any
	GoVersion string       // go version used in module
	Error     *ModuleError // error loading module
}

// ModuleError holds errors loading a module.
type ModuleError struct {
	Err string // the error itself
}

func () {
	packagesinternal.GetForTest = func( interface{}) string {
		return .(*Package).forTest
	}
	packagesinternal.GetDepsErrors = func( interface{}) []*packagesinternal.PackageError {
		return .(*Package).depsErrors
	}
	packagesinternal.GetGoCmdRunner = func( interface{}) *gocommand.Runner {
		return .(*Config).gocmdRunner
	}
	packagesinternal.SetGoCmdRunner = func( interface{},  *gocommand.Runner) {
		.(*Config).gocmdRunner = 
	}
	packagesinternal.SetModFile = func( interface{},  string) {
		.(*Config).modFile = 
	}
	packagesinternal.SetModFlag = func( interface{},  string) {
		.(*Config).modFlag = 
	}
	packagesinternal.TypecheckCgo = int(typecheckCgo)
	packagesinternal.DepsErrors = int(needInternalDepsErrors)
	packagesinternal.ForTest = int(needInternalForTest)
}

// An Error describes a problem with a package's metadata, syntax, or types.
type Error struct {
	Pos  string // "file:line:col" or "file:line" or "" or "-"
	Msg  string
	Kind ErrorKind
}

// ErrorKind describes the source of the error, allowing the user to
// differentiate between errors generated by the driver, the parser, or the
// type-checker.
type ErrorKind int

const (
	UnknownError ErrorKind = iota
	ListError
	ParseError
	TypeError
)

func ( Error) () string {
	 := .Pos
	if  == "" {
		 = "-" // like token.Position{}.String()
	}
	return  + ": " + .Msg
}

// flatPackage is the JSON form of Package
// It drops all the type and syntax fields, and transforms the Imports
//
// TODO(adonovan): identify this struct with Package, effectively
// publishing the JSON protocol.
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"`
	EmbedFiles      []string          `json:",omitempty"`
	EmbedPatterns   []string          `json:",omitempty"`
	IgnoredFiles    []string          `json:",omitempty"`
	ExportFile      string            `json:",omitempty"`
	Imports         map[string]string `json:",omitempty"`
}

// MarshalJSON returns the Package in its JSON form.
// For the most part, the structure fields are written out unmodified, and
// the type and syntax fields are skipped.
// The imports are written out as just a map of path to package id.
// The errors are written using a custom type that tries to preserve the
// structure of error types we know about.
//
// This method exists to enable support for additional build systems.  It is
// not intended for use by clients of the API and we may change the format.
func ( *Package) () ([]byte, error) {
	 := &flatPackage{
		ID:              .ID,
		Name:            .Name,
		PkgPath:         .PkgPath,
		Errors:          .Errors,
		GoFiles:         .GoFiles,
		CompiledGoFiles: .CompiledGoFiles,
		OtherFiles:      .OtherFiles,
		EmbedFiles:      .EmbedFiles,
		EmbedPatterns:   .EmbedPatterns,
		IgnoredFiles:    .IgnoredFiles,
		ExportFile:      .ExportFile,
	}
	if len(.Imports) > 0 {
		.Imports = make(map[string]string, len(.Imports))
		for ,  := range .Imports {
			.Imports[] = .ID
		}
	}
	return json.Marshal()
}

// UnmarshalJSON reads in a Package from its JSON format.
// See MarshalJSON for details about the format accepted.
func ( *Package) ( []byte) error {
	 := &flatPackage{}
	if  := json.Unmarshal(, &);  != nil {
		return 
	}
	* = Package{
		ID:              .ID,
		Name:            .Name,
		PkgPath:         .PkgPath,
		Errors:          .Errors,
		GoFiles:         .GoFiles,
		CompiledGoFiles: .CompiledGoFiles,
		OtherFiles:      .OtherFiles,
		EmbedFiles:      .EmbedFiles,
		EmbedPatterns:   .EmbedPatterns,
		ExportFile:      .ExportFile,
	}
	if len(.Imports) > 0 {
		.Imports = make(map[string]*Package, len(.Imports))
		for ,  := range .Imports {
			.Imports[] = &Package{ID: }
		}
	}
	return nil
}

func ( *Package) () string { return .ID }

// loaderPackage augments Package with state used during the loading phase
type loaderPackage struct {
	*Package
	importErrors map[string]error // maps each bad import to its error
	loadOnce     sync.Once
	color        uint8 // for cycle detection
	needsrc      bool  // load from source (Mode >= LoadTypes)
	needtypes    bool  // type information is either requested or depended on
	initial      bool  // package was matched by a pattern
	goVersion    int   // minor version number of go command on PATH
}

// loader holds the working state of a single call to load.
type loader struct {
	pkgs map[string]*loaderPackage
	Config
	sizes        types.Sizes
	parseCache   map[string]*parseValue
	parseCacheMu sync.Mutex
	exportMu     sync.Mutex // enforces mutual exclusion of exportdata operations

	// Config.Mode contains the implied mode (see impliedLoadMode).
	// Implied mode contains all the fields we need the data for.
	// In requestedMode there are the actually requested fields.
	// We'll zero them out before returning packages to the user.
	// This makes it easier for us to get the conditions where
	// we need certain modes right.
	requestedMode LoadMode
}

type parseValue struct {
	f     *ast.File
	err   error
	ready chan struct{}
}

func ( *Config) *loader {
	 := &loader{
		parseCache: map[string]*parseValue{},
	}
	if  != nil {
		.Config = *
		// If the user has provided a logger, use it.
		.Config.Logf = .Logf
	}
	if .Config.Logf == nil {
		// If the GOPACKAGESDEBUG environment variable is set to true,
		// but the user has not provided a logger, default to log.Printf.
		if debug {
			.Config.Logf = log.Printf
		} else {
			.Config.Logf = func( string,  ...interface{}) {}
		}
	}
	if .Config.Mode == 0 {
		.Config.Mode = NeedName | NeedFiles | NeedCompiledGoFiles // Preserve zero behavior of Mode for backwards compatibility.
	}
	if .Config.Env == nil {
		.Config.Env = os.Environ()
	}
	if .Config.gocmdRunner == nil {
		.Config.gocmdRunner = &gocommand.Runner{}
	}
	if .Context == nil {
		.Context = context.Background()
	}
	if .Dir == "" {
		if ,  := os.Getwd();  == nil {
			.Dir = 
		}
	}

	// Save the actually requested fields. We'll zero them out before returning packages to the user.
	.requestedMode = .Mode
	.Mode = impliedLoadMode(.Mode)

	if .Mode&NeedTypes != 0 || .Mode&NeedSyntax != 0 {
		if .Fset == nil {
			.Fset = token.NewFileSet()
		}

		// ParseFile is required even in LoadTypes mode
		// because we load source if export data is missing.
		if .ParseFile == nil {
			.ParseFile = func( *token.FileSet,  string,  []byte) (*ast.File, error) {
				const  = parser.AllErrors | parser.ParseComments
				return parser.ParseFile(, , , )
			}
		}
	}

	return 
}

// refine connects the supplied packages into a graph and then adds type and
// and syntax information as requested by the LoadMode.
func ( *loader) ( *driverResponse) ([]*Package, error) {
	 := .Roots
	 := make(map[string]int, len())
	for ,  := range  {
		[] = 
	}
	.pkgs = make(map[string]*loaderPackage)
	// first pass, fixup and build the map and roots
	var  = make([]*loaderPackage, len())
	for ,  := range .Packages {
		 := -1
		if ,  := [.ID];  {
			 = 
		}

		// Overlays can invalidate export data.
		// TODO(matloob): make this check fine-grained based on dependencies on overlaid files
		 := len(.Overlay) > 0 || .ExportFile == "" && .PkgPath != "unsafe"
		// This package needs type information if the caller requested types and the package is
		// either a root, or it's a non-root and the user requested dependencies ...
		 := (.Mode&NeedTypes|NeedTypesInfo != 0 && ( >= 0 || .Mode&NeedDeps != 0))
		// This package needs source if the call requested source (or types info, which implies source)
		// and the package is either a root, or itas a non- root and the user requested dependencies...
		 := ((.Mode&(NeedSyntax|NeedTypesInfo) != 0 && ( >= 0 || .Mode&NeedDeps != 0)) ||
			// ... or if we need types and the exportData is invalid. We fall back to (incompletely)
			// typechecking packages from source if they fail to compile.
			(.Mode&(NeedTypes|NeedTypesInfo) != 0 && )) && .PkgPath != "unsafe"
		 := &loaderPackage{
			Package:   ,
			needtypes: ,
			needsrc:   ,
			goVersion: .GoVersion,
		}
		.pkgs[.ID] = 
		if  >= 0 {
			[] = 
			.initial = true
		}
	}
	for ,  := range  {
		if [] == nil {
			return nil, fmt.Errorf("root package %v is missing", )
		}
	}

	// Materialize the import graph.

	const (
		 = 0 // new
		  = 1 // in progress
		 = 2 // complete
	)

	// visit traverses the import graph, depth-first,
	// and materializes the graph as Packages.Imports.
	//
	// Valid imports are saved in the Packages.Import map.
	// Invalid imports (cycles and missing nodes) are saved in the importErrors map.
	// Thus, even in the presence of both kinds of errors, the Import graph remains a DAG.
	//
	// visit returns whether the package needs src or has a transitive
	// dependency on a package that does. These are the only packages
	// for which we load source code.
	var  []*loaderPackage
	var  func( *loaderPackage) bool
	var  []*loaderPackage
	 = func( *loaderPackage) bool {
		switch .color {
		case :
			return .needsrc
		case :
			panic("internal error: grey node")
		}
		.color = 
		 = append(, ) // push
		 := .Imports       // the structure form has only stubs with the ID in the Imports
		// If NeedImports isn't set, the imports fields will all be zeroed out.
		if .Mode&NeedImports != 0 {
			.Imports = make(map[string]*Package, len())
			for ,  := range  {
				var  error
				 := .pkgs[.ID]
				if  == nil {
					// (includes package "C" when DisableCgo)
					 = fmt.Errorf("missing package: %q", .ID)
				} else if .color ==  {
					 = fmt.Errorf("import cycle: %s", )
				}
				if  != nil {
					if .importErrors == nil {
						.importErrors = make(map[string]error)
					}
					.importErrors[] = 
					continue
				}

				if () {
					.needsrc = true
				}
				.Imports[] = .Package
			}
		}
		if .needsrc {
			 = append(, )
		}
		if .Mode&NeedTypesSizes != 0 {
			.TypesSizes = .sizes
		}
		 = [:len()-1] // pop
		.color = 

		return .needsrc
	}

	if .Mode&NeedImports == 0 {
		// We do this to drop the stub import packages that we are not even going to try to resolve.
		for ,  := range  {
			.Imports = nil
		}
	} else {
		// For each initial package, create its import DAG.
		for ,  := range  {
			()
		}
	}
	if .Mode&NeedImports != 0 && .Mode&NeedTypes != 0 {
		for ,  := range  {
			// Complete type information is required for the
			// immediate dependencies of each source package.
			for ,  := range .Imports {
				 := .pkgs[.ID]
				.needtypes = true
			}
		}
	}
	// Load type data and syntax if needed, starting at
	// the initial packages (roots of the import DAG).
	if .Mode&NeedTypes != 0 || .Mode&NeedSyntax != 0 {
		var  sync.WaitGroup
		for ,  := range  {
			.Add(1)
			go func( *loaderPackage) {
				.loadRecursive()
				.Done()
			}()
		}
		.Wait()
	}

	 := make([]*Package, len())
	for ,  := range  {
		[] = .Package
	}
	for  := range .pkgs {
		// Clear all unrequested fields,
		// to catch programs that use more than they request.
		if .requestedMode&NeedName == 0 {
			.pkgs[].Name = ""
			.pkgs[].PkgPath = ""
		}
		if .requestedMode&NeedFiles == 0 {
			.pkgs[].GoFiles = nil
			.pkgs[].OtherFiles = nil
			.pkgs[].IgnoredFiles = nil
		}
		if .requestedMode&NeedEmbedFiles == 0 {
			.pkgs[].EmbedFiles = nil
		}
		if .requestedMode&NeedEmbedPatterns == 0 {
			.pkgs[].EmbedPatterns = nil
		}
		if .requestedMode&NeedCompiledGoFiles == 0 {
			.pkgs[].CompiledGoFiles = nil
		}
		if .requestedMode&NeedImports == 0 {
			.pkgs[].Imports = nil
		}
		if .requestedMode&NeedExportFile == 0 {
			.pkgs[].ExportFile = ""
		}
		if .requestedMode&NeedTypes == 0 {
			.pkgs[].Types = nil
			.pkgs[].Fset = nil
			.pkgs[].IllTyped = false
		}
		if .requestedMode&NeedSyntax == 0 {
			.pkgs[].Syntax = nil
		}
		if .requestedMode&NeedTypesInfo == 0 {
			.pkgs[].TypesInfo = nil
		}
		if .requestedMode&NeedTypesSizes == 0 {
			.pkgs[].TypesSizes = nil
		}
		if .requestedMode&NeedModule == 0 {
			.pkgs[].Module = nil
		}
	}

	return , nil
}

// loadRecursive loads the specified package and its dependencies,
// recursively, in parallel, in topological order.
// It is atomic and idempotent.
// Precondition: ld.Mode&NeedTypes.
func ( *loader) ( *loaderPackage) {
	.loadOnce.Do(func() {
		// Load the direct dependencies, in parallel.
		var  sync.WaitGroup
		for ,  := range .Imports {
			 := .pkgs[.ID]
			.Add(1)
			go func( *loaderPackage) {
				.()
				.Done()
			}()
		}
		.Wait()
		.loadPackage()
	})
}

// loadPackage loads the specified package.
// It must be called only once per Package,
// after immediate dependencies are loaded.
// Precondition: ld.Mode & NeedTypes.
func ( *loader) ( *loaderPackage) {
	if .PkgPath == "unsafe" {
		// Fill in the blanks to avoid surprises.
		.Types = types.Unsafe
		.Fset = .Fset
		.Syntax = []*ast.File{}
		.TypesInfo = new(types.Info)
		.TypesSizes = .sizes
		return
	}

	// Call NewPackage directly with explicit name.
	// This avoids skew between golist and go/types when the files'
	// package declarations are inconsistent.
	.Types = types.NewPackage(.PkgPath, .Name)
	.Fset = .Fset

	// Subtle: we populate all Types fields with an empty Package
	// before loading export data so that export data processing
	// never has to create a types.Package for an indirect dependency,
	// which would then require that such created packages be explicitly
	// inserted back into the Import graph as a final step after export data loading.
	// (Hence this return is after the Types assignment.)
	// The Diamond test exercises this case.
	if !.needtypes && !.needsrc {
		return
	}
	if !.needsrc {
		if  := .loadFromExportData();  != nil {
			.Errors = append(.Errors, Error{
				Pos:  "-",
				Msg:  .Error(),
				Kind: UnknownError, // e.g. can't find/open/parse export data
			})
		}
		return // not a source package, don't get syntax trees
	}

	 := func( error) {
		// Convert various error types into the one true Error.
		var  []Error
		switch err := .(type) {
		case Error:
			// from driver
			 = append(, )

		case *os.PathError:
			// from parser
			 = append(, Error{
				Pos:  .Path + ":1",
				Msg:  .Err.Error(),
				Kind: ParseError,
			})

		case scanner.ErrorList:
			// from parser
			for ,  := range  {
				 = append(, Error{
					Pos:  .Pos.String(),
					Msg:  .Msg,
					Kind: ParseError,
				})
			}

		case types.Error:
			// from type checker
			.TypeErrors = append(.TypeErrors, )
			 = append(, Error{
				Pos:  .Fset.Position(.Pos).String(),
				Msg:  .Msg,
				Kind: TypeError,
			})

		default:
			// unexpected impoverished error from parser?
			 = append(, Error{
				Pos:  "-",
				Msg:  .Error(),
				Kind: UnknownError,
			})

			// If you see this error message, please file a bug.
			log.Printf("internal error: error %q (%T) without position", , )
		}

		.Errors = append(.Errors, ...)
	}

	// If the go command on the PATH is newer than the runtime,
	// then the go/{scanner,ast,parser,types} packages from the
	// standard library may be unable to process the files
	// selected by go list.
	//
	// There is currently no way to downgrade the effective
	// version of the go command (see issue 52078), so we proceed
	// with the newer go command but, in case of parse or type
	// errors, we emit an additional diagnostic.
	//
	// See:
	// - golang.org/issue/52078 (flag to set release tags)
	// - golang.org/issue/50825 (gopls legacy version support)
	// - golang.org/issue/55883 (go/packages confusing error)
	//
	// Should we assert a hard minimum of (currently) go1.16 here?
	var  int
	if ,  := fmt.Sscanf(runtime.Version(), "go1.%d", &);  == nil &&  < .goVersion {
		defer func() {
			if len(.Errors) > 0 {
				(Error{
					Pos:  "-",
					Msg:  fmt.Sprintf("This application uses version go1.%d of the source-processing packages but runs version go1.%d of 'go list'. It may fail to process source files that rely on newer language features. If so, rebuild the application using a newer version of Go.", , .goVersion),
					Kind: UnknownError,
				})
			}
		}()
	}

	if .Config.Mode&NeedTypes != 0 && len(.CompiledGoFiles) == 0 && .ExportFile != "" {
		// The config requested loading sources and types, but sources are missing.
		// Add an error to the package and fall back to loading from export data.
		(Error{"-", fmt.Sprintf("sources missing for package %s", .ID), ParseError})
		_ = .loadFromExportData() // ignore any secondary errors

		return // can't get syntax trees for this package
	}

	,  := .parseFiles(.CompiledGoFiles)
	for ,  := range  {
		()
	}

	.Syntax = 
	if .Config.Mode&NeedTypes == 0 {
		return
	}

	.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),
	}
	typeparams.InitInstanceInfo(.TypesInfo)
	.TypesSizes = .sizes

	 := importerFunc(func( string) (*types.Package, error) {
		if  == "unsafe" {
			return types.Unsafe, nil
		}

		// The imports map is keyed by import path.
		 := .Imports[]
		if  == nil {
			if  := .importErrors[];  != nil {
				return nil, 
			}
			// There was skew between the metadata and the
			// import declarations, likely due to an edit
			// race, or because the ParseFile feature was
			// used to supply alternative file contents.
			return nil, fmt.Errorf("no metadata for %s", )
		}

		if .Types != nil && .Types.Complete() {
			return .Types, nil
		}
		log.Fatalf("internal error: package %q without types was imported from %q", , )
		panic("unreachable")
	})

	// type-check
	 := &types.Config{
		Importer: ,

		// Type-check bodies of functions only in initial packages.
		// Example: for import graph A->B->C and initial packages {A,C},
		// we can ignore function bodies in B.
		IgnoreFuncBodies: .Mode&NeedDeps == 0 && !.initial,

		Error: ,
		Sizes: .sizes,
	}
	if (.Mode & typecheckCgo) != 0 {
		if !typesinternal.SetUsesCgo() {
			(Error{
				Msg:  "typecheckCgo requires Go 1.15+",
				Kind: ListError,
			})
			return
		}
	}
	types.NewChecker(, .Fset, .Types, .TypesInfo).Files(.Syntax)

	.importErrors = nil // no longer needed

	// If !Cgo, the type-checker uses FakeImportC mode, so
	// it doesn't invoke the importer for import "C",
	// nor report an error for the import,
	// or for any undefined C.f reference.
	// We must detect this explicitly and correctly
	// mark the package as IllTyped (by reporting an error).
	// TODO(adonovan): if these errors are annoying,
	// we could just set IllTyped quietly.
	if .FakeImportC {
	:
		for ,  := range .Syntax {
			for ,  := range .Imports {
				if .Path.Value == `"C"` {
					 := types.Error{Fset: .Fset, Pos: .Pos(), Msg: `import "C" ignored`}
					()
					break 
				}
			}
		}
	}

	// Record accumulated errors.
	 := len(.Errors) > 0
	if ! {
		for ,  := range .Imports {
			if .IllTyped {
				 = true
				break
			}
		}
	}
	.IllTyped = 
}

// An importFunc is an implementation of the single-method
// types.Importer interface based on a function value.
type importerFunc func(path string) (*types.Package, error)

func ( importerFunc) ( string) (*types.Package, error) { return () }

// We use a counting semaphore to limit
// the number of parallel I/O calls per process.
var ioLimit = make(chan bool, 20)

func ( *loader) ( string) (*ast.File, error) {
	.parseCacheMu.Lock()
	,  := .parseCache[]
	if  {
		// cache hit
		.parseCacheMu.Unlock()
		<-.ready
	} else {
		// cache miss
		 = &parseValue{ready: make(chan struct{})}
		.parseCache[] = 
		.parseCacheMu.Unlock()

		var  []byte
		for ,  := range .Config.Overlay {
			if sameFile(, ) {
				 = 
			}
		}
		var  error
		if  == nil {
			ioLimit <- true // wait
			,  = ioutil.ReadFile()
			<-ioLimit // signal
		}
		if  != nil {
			.err = 
		} else {
			.f, .err = .ParseFile(.Fset, , )
		}

		close(.ready)
	}
	return .f, .err
}

// parseFiles reads and parses the Go source files and returns the ASTs
// of the ones that could be at least partially parsed, along with a
// list of I/O and parse errors encountered.
//
// Because files are scanned in parallel, the token.Pos
// positions of the resulting ast.Files are not ordered.
func ( *loader) ( []string) ([]*ast.File, []error) {
	var  sync.WaitGroup
	 := len()
	 := make([]*ast.File, )
	 := make([]error, )
	for ,  := range  {
		if .Config.Context.Err() != nil {
			[] = nil
			[] = .Config.Context.Err()
			continue
		}
		.Add(1)
		go func( int,  string) {
			[], [] = .parseFile()
			.Done()
		}(, )
	}
	.Wait()

	// Eliminate nils, preserving order.
	var  int
	for ,  := range  {
		if  != nil {
			[] = 
			++
		}
	}
	 = [:]

	 = 0
	for ,  := range  {
		if  != nil {
			[] = 
			++
		}
	}
	 = [:]

	return , 
}

// sameFile returns true if x and y have the same basename and denote
// the same file.
func (,  string) bool {
	if  ==  {
		// It could be the case that y doesn't exist.
		// For instance, it may be an overlay file that
		// hasn't been written to disk. To handle that case
		// let x == y through. (We added the exact absolute path
		// string to the CompiledGoFiles list, so the unwritten
		// overlay case implies x==y.)
		return true
	}
	if strings.EqualFold(filepath.Base(), filepath.Base()) { // (optimisation)
		if ,  := os.Stat();  == nil {
			if ,  := os.Stat();  == nil {
				return os.SameFile(, )
			}
		}
	}
	return false
}

// loadFromExportData ensures that type information is present for the specified
// package, loading it from an export data file on the first request.
// On success it sets lpkg.Types to a new Package.
func ( *loader) ( *loaderPackage) error {
	if .PkgPath == "" {
		log.Fatalf("internal error: Package %s has no PkgPath", )
	}

	// Because gcexportdata.Read has the potential to create or
	// modify the types.Package for each node in the transitive
	// closure of dependencies of lpkg, all exportdata operations
	// must be sequential. (Finer-grained locking would require
	// changes to the gcexportdata API.)
	//
	// The exportMu lock guards the lpkg.Types field and the
	// types.Package it points to, for each loaderPackage in the graph.
	//
	// Not all accesses to Package.Pkg need to be protected by exportMu:
	// graph ordering ensures that direct dependencies of source
	// packages are fully loaded before the importer reads their Pkg field.
	.exportMu.Lock()
	defer .exportMu.Unlock()

	if  := .Types;  != nil && .Complete() {
		return nil // cache hit
	}

	.IllTyped = true // fail safe

	if .ExportFile == "" {
		// Errors while building export data will have been printed to stderr.
		return fmt.Errorf("no export data file")
	}
	,  := os.Open(.ExportFile)
	if  != nil {
		return 
	}
	defer .Close()

	// Read gc export data.
	//
	// We don't currently support gccgo export data because all
	// underlying workspaces use the gc toolchain. (Even build
	// systems that support gccgo don't use it for workspace
	// queries.)
	,  := gcexportdata.NewReader()
	if  != nil {
		return fmt.Errorf("reading %s: %v", .ExportFile, )
	}

	// Build the view.
	//
	// The gcexportdata machinery has no concept of package ID.
	// It identifies packages by their PkgPath, which although not
	// globally unique is unique within the scope of one invocation
	// of the linker, type-checker, or gcexportdata.
	//
	// So, we must build a PkgPath-keyed view of the global
	// (conceptually ID-keyed) cache of packages and pass it to
	// gcexportdata. The view must contain every existing
	// package that might possibly be mentioned by the
	// current package---its transitive closure.
	//
	// In loadPackage, we unconditionally create a types.Package for
	// each dependency so that export data loading does not
	// create new ones.
	//
	// TODO(adonovan): it would be simpler and more efficient
	// if the export data machinery invoked a callback to
	// get-or-create a package instead of a map.
	//
	 := make(map[string]*types.Package) // view seen by gcexportdata
	 := make(map[*loaderPackage]bool)   // all visited packages
	var  func( map[string]*Package)
	 = func( map[string]*Package) {
		for ,  := range  {
			 := .pkgs[.ID]
			if ![] {
				[] = true
				[.PkgPath] = .Types
				(.Imports)
			}
		}
	}
	(.Imports)

	 := len() + 1 // adding the self package
	// Parse the export data.
	// (May modify incomplete packages in view but not create new ones.)
	,  := gcexportdata.Read(, .Fset, , .PkgPath)
	if  != nil {
		return fmt.Errorf("reading %s: %v", .ExportFile, )
	}
	if ,  := ["go.shape"];  {
		// Account for the pseudopackage "go.shape" that gets
		// created by generic code.
		++
	}
	if  != len() {
		log.Panicf("golang.org/x/tools/go/packages: unexpected new packages during load of %s", .PkgPath)
	}

	.Types = 
	.IllTyped = false
	return nil
}

// impliedLoadMode returns loadMode with its dependencies.
func ( LoadMode) LoadMode {
	if &(NeedDeps|NeedTypes|NeedTypesInfo) != 0 {
		// All these things require knowing the import graph.
		 |= NeedImports
	}

	return 
}

func ( *Config) bool {
	return .Mode&NeedExportFile != 0 || .Mode&NeedTypes != 0 && .Mode&NeedDeps == 0
}

var _ interface{} = io.Discard // assert build toolchain is go1.16 or later