mirror of
https://github.com/golang/go
synced 2024-11-18 23:34:45 -07:00
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,15 +152,17 @@ 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{
|
||||||
ID: id,
|
Package: &Package{
|
||||||
Name: p.Name,
|
ID: id,
|
||||||
PkgPath: pkgpath,
|
Name: p.Name,
|
||||||
Srcs: absJoin(p.Dir, p.GoFiles, p.CgoFiles),
|
PkgPath: pkgpath,
|
||||||
OtherSrcs: absJoin(p.Dir, p.SFiles, p.CFiles),
|
Srcs: absJoin(p.Dir, p.GoFiles, p.CgoFiles),
|
||||||
imports: imports,
|
OtherSrcs: absJoin(p.Dir, p.SFiles, p.CFiles),
|
||||||
export: export,
|
},
|
||||||
indirect: p.DepOnly,
|
imports: imports,
|
||||||
|
export: export,
|
||||||
|
indirect: p.DepOnly,
|
||||||
}
|
}
|
||||||
result = append(result, pkg)
|
result = append(result, pkg)
|
||||||
}
|
}
|
||||||
|
@ -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
Block a user