go/packages: determine sizes by calling go list

This is more reliable than looking in the environment.

Change-Id: I96c093b89faaece6b6256eefb4a4aac4d66b9cc9
Reviewed-on: https://go-review.googlesource.com/c/146757
Run-TryBot: Michael Matloob <matloob@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
Michael Matloob 2018-11-01 15:45:26 -04:00
parent e504f914a8
commit 78dc5bac0c
2 changed files with 36 additions and 14 deletions

View File

@ -8,6 +8,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"go/types"
"io/ioutil"
"log"
"os"
@ -36,6 +37,17 @@ type goTooOldError struct {
// the build system package structure.
// See driver for more details.
func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
var sizes types.Sizes
var sizeserr error
var sizeswg sync.WaitGroup
if cfg.Mode >= LoadTypes {
sizeswg.Add(1)
go func() {
sizes, sizeserr = getSizes(cfg)
sizeswg.Done()
}()
}
// Determine files requested in contains patterns
var containFiles []string
var packagesNamed []string
@ -109,6 +121,12 @@ extractQueries:
response = &driverResponse{}
}
sizeswg.Wait()
if sizeserr != nil {
return nil, sizeserr
}
response.Sizes = sizes
if len(containFiles) == 0 && len(packagesNamed) == 0 {
return response, nil
}
@ -328,6 +346,18 @@ func runNamedQueries(cfg *Config, driver driver, addPkg func(*Package), queries
return results, nil
}
func getSizes(cfg *Config) (types.Sizes, error) {
stdout, err := invokeGo(cfg, "env", "GOARCH") // TODO(matloob): perhaps merge this call with the roots call?
if err != nil {
return nil, err
}
goarch := strings.TrimSpace(stdout.String())
// Assume "gc" because SizesFor doesn't respond to other compilers.
// TODO(matloob): add support for gccgo as needed.
return types.SizesFor("gc", goarch), nil
}
// roots selects the appropriate paths to walk based on the passed-in configuration,
// particularly the environment and the presence of a go.mod in cfg.Dir's parents.
func roots(cfg *Config) ([]gopathwalk.Root, string, error) {

View File

@ -19,8 +19,6 @@ import (
"log"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"golang.org/x/tools/go/gcexportdata"
@ -139,6 +137,9 @@ type driver func(cfg *Config, patterns ...string) (*driverResponse, error)
// driverResponse contains the results for a driver query.
type driverResponse struct {
// Sizes, if not nil, is the types.Sizes to use when type checking.
Sizes types.Sizes
// 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
@ -173,6 +174,7 @@ func Load(cfg *Config, patterns ...string) ([]*Package, error) {
if err != nil {
return nil, err
}
l.sizes = response.Sizes
return l.refine(response.Roots, response.Packages...)
}
@ -367,6 +369,7 @@ type loaderPackage struct {
type loader struct {
pkgs map[string]*loaderPackage
Config
sizes types.Sizes
exportMu sync.Mutex // enforces mutual exclusion of exportdata operations
}
@ -692,17 +695,6 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
panic("unreachable")
})
// This is only an approximation.
// TODO(adonovan): derive Sizes from the underlying build system.
goarch := runtime.GOARCH
const goarchPrefix = "GOARCH="
for _, e := range ld.Config.Env {
if strings.HasPrefix(e, goarchPrefix) {
goarch = e[len(goarchPrefix):]
}
}
sizes := types.SizesFor("gc", goarch)
// type-check
tc := &types.Config{
Importer: importer,
@ -713,7 +705,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
IgnoreFuncBodies: ld.Mode < LoadAllSyntax && !lpkg.initial,
Error: appendError,
Sizes: sizes,
Sizes: ld.sizes,
}
types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)