go/packages: splitting the scratch fields out of Package
This makes Package a struct we can re-use in other places/algorithms. Change-Id: I2e095a624bf44223319ba1ea3d60deb727b38f81 Reviewed-on: https://go-review.googlesource.com/124855 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
		
							parent
							
								
									96ee42108a
								
							
						
					
					
						commit
						ded554d068
					
				| 
						 | 
					@ -31,7 +31,7 @@ type GoTooOldError struct {
 | 
				
			||||||
// golistPackages uses the "go list" command to expand the
 | 
					// golistPackages uses the "go list" command to expand the
 | 
				
			||||||
// pattern words and return metadata for the specified packages.
 | 
					// pattern words and return metadata for the specified packages.
 | 
				
			||||||
// dir may be "" and env may be nil, as per os/exec.Command.
 | 
					// dir may be "" and env may be nil, as per os/exec.Command.
 | 
				
			||||||
func golistPackages(ctx context.Context, dir string, env []string, cgo, export, tests bool, words []string) ([]*Package, error) {
 | 
					func golistPackages(ctx context.Context, dir string, env []string, cgo, export, tests bool, words []string) ([]*loaderPackage, error) {
 | 
				
			||||||
	// Fields must match go list;
 | 
						// Fields must match go list;
 | 
				
			||||||
	// see $GOROOT/src/cmd/go/internal/load/pkg.go.
 | 
						// see $GOROOT/src/cmd/go/internal/load/pkg.go.
 | 
				
			||||||
	type jsonPackage struct {
 | 
						type jsonPackage struct {
 | 
				
			||||||
| 
						 | 
					@ -73,7 +73,7 @@ func golistPackages(ctx context.Context, dir string, env []string, cgo, export,
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Decode the JSON and convert it to Package form.
 | 
						// Decode the JSON and convert it to Package form.
 | 
				
			||||||
	var result []*Package
 | 
						var result []*loaderPackage
 | 
				
			||||||
	for dec := json.NewDecoder(buf); dec.More(); {
 | 
						for dec := json.NewDecoder(buf); dec.More(); {
 | 
				
			||||||
		p := new(jsonPackage)
 | 
							p := new(jsonPackage)
 | 
				
			||||||
		if err := dec.Decode(p); err != nil {
 | 
							if err := dec.Decode(p); err != nil {
 | 
				
			||||||
| 
						 | 
					@ -152,12 +152,14 @@ func golistPackages(ctx context.Context, dir string, env []string, cgo, export,
 | 
				
			||||||
			imports[id] = id // identity import
 | 
								imports[id] = id // identity import
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pkg := &Package{
 | 
							pkg := &loaderPackage{
 | 
				
			||||||
 | 
								Package: &Package{
 | 
				
			||||||
				ID:        id,
 | 
									ID:        id,
 | 
				
			||||||
				Name:      p.Name,
 | 
									Name:      p.Name,
 | 
				
			||||||
				PkgPath:   pkgpath,
 | 
									PkgPath:   pkgpath,
 | 
				
			||||||
				Srcs:      absJoin(p.Dir, p.GoFiles, p.CgoFiles),
 | 
									Srcs:      absJoin(p.Dir, p.GoFiles, p.CgoFiles),
 | 
				
			||||||
				OtherSrcs: absJoin(p.Dir, p.SFiles, p.CFiles),
 | 
									OtherSrcs: absJoin(p.Dir, p.SFiles, p.CFiles),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
			imports:  imports,
 | 
								imports:  imports,
 | 
				
			||||||
			export:   export,
 | 
								export:   export,
 | 
				
			||||||
			indirect: p.DepOnly,
 | 
								indirect: p.DepOnly,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -229,9 +229,11 @@ type Package struct {
 | 
				
			||||||
	// It is set only when Files is set.
 | 
						// It is set only when Files is set.
 | 
				
			||||||
	// All packages loaded together share a single Fset.
 | 
						// All packages loaded together share a single Fset.
 | 
				
			||||||
	Fset *token.FileSet
 | 
						Fset *token.FileSet
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// ---- temporary state ----
 | 
					// loaderPackage augments Package with state used during the loading phase
 | 
				
			||||||
	// the Package struct should be pure exported data.
 | 
					type loaderPackage struct {
 | 
				
			||||||
 | 
						*Package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// export holds the path to the export data file
 | 
						// export holds the path to the export data file
 | 
				
			||||||
	// for this package, if mode == TypeCheck.
 | 
						// for this package, if mode == TypeCheck.
 | 
				
			||||||
| 
						 | 
					@ -255,6 +257,7 @@ func (lpkg *Package) String() string { return lpkg.ID }
 | 
				
			||||||
type loader struct {
 | 
					type loader struct {
 | 
				
			||||||
	mode mode
 | 
						mode mode
 | 
				
			||||||
	cgo  bool
 | 
						cgo  bool
 | 
				
			||||||
 | 
						pkgs map[string]*loaderPackage
 | 
				
			||||||
	Options
 | 
						Options
 | 
				
			||||||
	exportMu sync.Mutex // enforces mutual exclusion of exportdata operations
 | 
						exportMu sync.Mutex // enforces mutual exclusion of exportdata operations
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -306,10 +309,10 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pkgs := make(map[string]*Package)
 | 
						ld.pkgs = make(map[string]*loaderPackage)
 | 
				
			||||||
	var initial []*Package
 | 
						var initial []*loaderPackage
 | 
				
			||||||
	for _, pkg := range list {
 | 
						for _, pkg := range list {
 | 
				
			||||||
		pkgs[pkg.ID] = pkg
 | 
							ld.pkgs[pkg.ID] = pkg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Record the set of initial packages
 | 
							// Record the set of initial packages
 | 
				
			||||||
		// corresponding to the patterns.
 | 
							// corresponding to the patterns.
 | 
				
			||||||
| 
						 | 
					@ -321,7 +324,7 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(pkgs) == 0 {
 | 
						if len(ld.pkgs) == 0 {
 | 
				
			||||||
		return nil, fmt.Errorf("packages not found")
 | 
							return nil, fmt.Errorf("packages not found")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -343,9 +346,9 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
 | 
				
			||||||
	// visit returns whether the package is initial or has a transitive
 | 
						// visit returns whether the package is initial or has a transitive
 | 
				
			||||||
	// dependency on an initial package. These are the only packages
 | 
						// dependency on an initial package. These are the only packages
 | 
				
			||||||
	// for which we load source code in typeCheck mode.
 | 
						// for which we load source code in typeCheck mode.
 | 
				
			||||||
	var stack []*Package
 | 
						var stack []*loaderPackage
 | 
				
			||||||
	var visit func(lpkg *Package) bool
 | 
						var visit func(lpkg *loaderPackage) bool
 | 
				
			||||||
	visit = func(lpkg *Package) bool {
 | 
						visit = func(lpkg *loaderPackage) bool {
 | 
				
			||||||
		switch lpkg.color {
 | 
							switch lpkg.color {
 | 
				
			||||||
		case black:
 | 
							case black:
 | 
				
			||||||
			return lpkg.needsrc
 | 
								return lpkg.needsrc
 | 
				
			||||||
| 
						 | 
					@ -358,7 +361,7 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
 | 
				
			||||||
		imports := make(map[string]*Package)
 | 
							imports := make(map[string]*Package)
 | 
				
			||||||
		for importPath, id := range lpkg.imports {
 | 
							for importPath, id := range lpkg.imports {
 | 
				
			||||||
			var importErr error
 | 
								var importErr error
 | 
				
			||||||
			imp := pkgs[id]
 | 
								imp := ld.pkgs[id]
 | 
				
			||||||
			if imp == nil {
 | 
								if imp == nil {
 | 
				
			||||||
				// (includes package "C" when DisableCgo)
 | 
									// (includes package "C" when DisableCgo)
 | 
				
			||||||
				importErr = fmt.Errorf("missing package: %q", id)
 | 
									importErr = fmt.Errorf("missing package: %q", id)
 | 
				
			||||||
| 
						 | 
					@ -376,7 +379,7 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
 | 
				
			||||||
			if visit(imp) {
 | 
								if visit(imp) {
 | 
				
			||||||
				lpkg.needsrc = true
 | 
									lpkg.needsrc = true
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			imports[importPath] = imp
 | 
								imports[importPath] = imp.Package
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		lpkg.imports = nil // no longer needed
 | 
							lpkg.imports = nil // no longer needed
 | 
				
			||||||
		lpkg.Imports = imports
 | 
							lpkg.Imports = imports
 | 
				
			||||||
| 
						 | 
					@ -398,7 +401,7 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
 | 
				
			||||||
		var wg sync.WaitGroup
 | 
							var wg sync.WaitGroup
 | 
				
			||||||
		for _, lpkg := range initial {
 | 
							for _, lpkg := range initial {
 | 
				
			||||||
			wg.Add(1)
 | 
								wg.Add(1)
 | 
				
			||||||
			go func(lpkg *Package) {
 | 
								go func(lpkg *loaderPackage) {
 | 
				
			||||||
				ld.loadRecursive(lpkg)
 | 
									ld.loadRecursive(lpkg)
 | 
				
			||||||
				wg.Done()
 | 
									wg.Done()
 | 
				
			||||||
			}(lpkg)
 | 
								}(lpkg)
 | 
				
			||||||
| 
						 | 
					@ -406,7 +409,11 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
 | 
				
			||||||
		wg.Wait()
 | 
							wg.Wait()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return initial, nil
 | 
						result := make([]*Package, len(initial))
 | 
				
			||||||
 | 
						for i, lpkg := range initial {
 | 
				
			||||||
 | 
							result[i] = lpkg.Package
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return result, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// loadRecursive loads, parses, and type-checks the specified package and its
 | 
					// loadRecursive loads, parses, and type-checks the specified package and its
 | 
				
			||||||
| 
						 | 
					@ -414,13 +421,14 @@ func (ld *loader) load(patterns ...string) ([]*Package, error) {
 | 
				
			||||||
// It is atomic and idempotent.
 | 
					// It is atomic and idempotent.
 | 
				
			||||||
// Precondition: ld.mode != Metadata.
 | 
					// Precondition: ld.mode != Metadata.
 | 
				
			||||||
// In typeCheck mode, only needsrc packages are loaded.
 | 
					// In typeCheck mode, only needsrc packages are loaded.
 | 
				
			||||||
func (ld *loader) loadRecursive(lpkg *Package) {
 | 
					func (ld *loader) loadRecursive(lpkg *loaderPackage) {
 | 
				
			||||||
	lpkg.loadOnce.Do(func() {
 | 
						lpkg.loadOnce.Do(func() {
 | 
				
			||||||
		// Load the direct dependencies, in parallel.
 | 
							// Load the direct dependencies, in parallel.
 | 
				
			||||||
		var wg sync.WaitGroup
 | 
							var wg sync.WaitGroup
 | 
				
			||||||
		for _, imp := range lpkg.Imports {
 | 
							for _, ipkg := range lpkg.Imports {
 | 
				
			||||||
 | 
								imp := ld.pkgs[ipkg.ID]
 | 
				
			||||||
			wg.Add(1)
 | 
								wg.Add(1)
 | 
				
			||||||
			go func(imp *Package) {
 | 
								go func(imp *loaderPackage) {
 | 
				
			||||||
				ld.loadRecursive(imp)
 | 
									ld.loadRecursive(imp)
 | 
				
			||||||
				wg.Done()
 | 
									wg.Done()
 | 
				
			||||||
			}(imp)
 | 
								}(imp)
 | 
				
			||||||
| 
						 | 
					@ -436,7 +444,7 @@ func (ld *loader) loadRecursive(lpkg *Package) {
 | 
				
			||||||
// It must be called only once per Package,
 | 
					// It must be called only once per Package,
 | 
				
			||||||
// after immediate dependencies are loaded.
 | 
					// after immediate dependencies are loaded.
 | 
				
			||||||
// Precondition: ld.mode != Metadata.
 | 
					// Precondition: ld.mode != Metadata.
 | 
				
			||||||
func (ld *loader) loadPackage(lpkg *Package) {
 | 
					func (ld *loader) loadPackage(lpkg *loaderPackage) {
 | 
				
			||||||
	if lpkg.PkgPath == "unsafe" {
 | 
						if lpkg.PkgPath == "unsafe" {
 | 
				
			||||||
		// Fill in the blanks to avoid surprises.
 | 
							// Fill in the blanks to avoid surprises.
 | 
				
			||||||
		lpkg.Type = types.Unsafe
 | 
							lpkg.Type = types.Unsafe
 | 
				
			||||||
| 
						 | 
					@ -494,8 +502,8 @@ func (ld *loader) loadPackage(lpkg *Package) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// The imports map is keyed by import path.
 | 
							// The imports map is keyed by import path.
 | 
				
			||||||
		imp := lpkg.Imports[path]
 | 
							ipkg := lpkg.Imports[path]
 | 
				
			||||||
		if imp == nil {
 | 
							if ipkg == nil {
 | 
				
			||||||
			if err := lpkg.importErrors[path]; err != nil {
 | 
								if err := lpkg.importErrors[path]; err != nil {
 | 
				
			||||||
				return nil, err
 | 
									return nil, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -505,9 +513,10 @@ func (ld *loader) loadPackage(lpkg *Package) {
 | 
				
			||||||
			// used to supply alternative file contents.
 | 
								// used to supply alternative file contents.
 | 
				
			||||||
			return nil, fmt.Errorf("no metadata for %s", path)
 | 
								return nil, fmt.Errorf("no metadata for %s", path)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if imp.Type != nil && imp.Type.Complete() {
 | 
							if ipkg.Type != nil && ipkg.Type.Complete() {
 | 
				
			||||||
			return imp.Type, nil
 | 
								return ipkg.Type, nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							imp := ld.pkgs[ipkg.ID]
 | 
				
			||||||
		if ld.mode == typeCheck && !imp.needsrc {
 | 
							if ld.mode == typeCheck && !imp.needsrc {
 | 
				
			||||||
			return ld.loadFromExportData(imp)
 | 
								return ld.loadFromExportData(imp)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -611,7 +620,7 @@ func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// loadFromExportData returns type information for the specified
 | 
					// loadFromExportData returns type information for the specified
 | 
				
			||||||
// package, loading it from an export data file on the first request.
 | 
					// package, loading it from an export data file on the first request.
 | 
				
			||||||
func (ld *loader) loadFromExportData(lpkg *Package) (*types.Package, error) {
 | 
					func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error) {
 | 
				
			||||||
	if lpkg.PkgPath == "" {
 | 
						if lpkg.PkgPath == "" {
 | 
				
			||||||
		log.Fatalf("internal error: Package %s has no PkgPath", lpkg)
 | 
							log.Fatalf("internal error: Package %s has no PkgPath", lpkg)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -689,10 +698,10 @@ func (ld *loader) loadFromExportData(lpkg *Package) (*types.Package, error) {
 | 
				
			||||||
	// get-or-create a package instead of a map.
 | 
						// get-or-create a package instead of a map.
 | 
				
			||||||
	//
 | 
						//
 | 
				
			||||||
	view := make(map[string]*types.Package) // view seen by gcexportdata
 | 
						view := make(map[string]*types.Package) // view seen by gcexportdata
 | 
				
			||||||
	seen := make(map[*Package]bool)         // all visited packages
 | 
						seen := make(map[*loaderPackage]bool)   // all visited packages
 | 
				
			||||||
	var copyback []*Package                 // candidates for copying back to global cache
 | 
						var copyback []*loaderPackage           // candidates for copying back to global cache
 | 
				
			||||||
	var visit func(p *Package)
 | 
						var visit func(p *loaderPackage)
 | 
				
			||||||
	visit = func(p *Package) {
 | 
						visit = func(p *loaderPackage) {
 | 
				
			||||||
		if !seen[p] {
 | 
							if !seen[p] {
 | 
				
			||||||
			seen[p] = true
 | 
								seen[p] = true
 | 
				
			||||||
			if p.Type != nil {
 | 
								if p.Type != nil {
 | 
				
			||||||
| 
						 | 
					@ -701,7 +710,7 @@ func (ld *loader) loadFromExportData(lpkg *Package) (*types.Package, error) {
 | 
				
			||||||
				copyback = append(copyback, p)
 | 
									copyback = append(copyback, p)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			for _, p := range p.Imports {
 | 
								for _, p := range p.Imports {
 | 
				
			||||||
				visit(p)
 | 
									visit(ld.pkgs[p.ID])
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue