rm defaultDriverEx
This commit is contained in:
@@ -106,8 +106,7 @@ func Do(args []string, conf *Config) {
|
|||||||
|
|
||||||
prog := llssa.NewProgram(nil)
|
prog := llssa.NewProgram(nil)
|
||||||
sizes := prog.TypeSizes
|
sizes := prog.TypeSizes
|
||||||
// dedup := packages.NewDeduper()
|
dedup := packages.NewDeduper()
|
||||||
dedup := (*packages.Deduper)(nil)
|
|
||||||
|
|
||||||
if patterns == nil {
|
if patterns == nil {
|
||||||
patterns = []string{"."}
|
patterns = []string{"."}
|
||||||
|
|||||||
@@ -17,14 +17,12 @@
|
|||||||
package packages
|
package packages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/types"
|
"go/types"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -59,12 +57,6 @@ const (
|
|||||||
// Calls to Load do not modify this struct.
|
// Calls to Load do not modify this struct.
|
||||||
type Config = packages.Config
|
type Config = packages.Config
|
||||||
|
|
||||||
func setGoListOverlayFile(cfg *Config, val string) {
|
|
||||||
// TODO(xsw): suppose that the field is at the end of the struct
|
|
||||||
ptr := uintptr(unsafe.Pointer(cfg)) + (unsafe.Sizeof(*cfg) - unsafe.Sizeof(val))
|
|
||||||
*(*string)(unsafe.Pointer(ptr)) = val
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Package describes a loaded Go package.
|
// A Package describes a loaded Go package.
|
||||||
type Package = packages.Package
|
type Package = packages.Package
|
||||||
|
|
||||||
@@ -86,127 +78,15 @@ type loader struct {
|
|||||||
requestedMode LoadMode
|
requestedMode LoadMode
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deduper wraps a DriverResponse, deduplicating its contents.
|
|
||||||
type Deduper struct {
|
type Deduper struct {
|
||||||
seenRoots map[string]bool
|
|
||||||
seenPackages map[string]*Package
|
|
||||||
dr *packages.DriverResponse // TODO(xsw): ensure offset of dr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:linkname NewDeduper golang.org/x/tools/go/packages.newDeduper
|
func NewDeduper() *Deduper {
|
||||||
func NewDeduper() *Deduper
|
return nil
|
||||||
|
|
||||||
//go:linkname addAll golang.org/x/tools/go/packages.(*responseDeduper).addAll
|
|
||||||
func addAll(r *Deduper, dr *packages.DriverResponse)
|
|
||||||
|
|
||||||
func mergeResponsesEx(dedup *Deduper, responses ...*packages.DriverResponse) *packages.DriverResponse {
|
|
||||||
if len(responses) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if dedup == nil {
|
|
||||||
dedup = NewDeduper()
|
|
||||||
}
|
|
||||||
response := dedup
|
|
||||||
response.dr.NotHandled = false
|
|
||||||
response.dr.Compiler = responses[0].Compiler
|
|
||||||
response.dr.Arch = responses[0].Arch
|
|
||||||
response.dr.GoVersion = responses[0].GoVersion
|
|
||||||
for _, v := range responses {
|
|
||||||
addAll(response, v)
|
|
||||||
}
|
|
||||||
return response.dr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// driver is the type for functions that query the build system for the
|
//go:linkname defaultDriver golang.org/x/tools/go/packages.defaultDriver
|
||||||
// packages named by the patterns.
|
func defaultDriver(cfg *Config, patterns ...string) (*packages.DriverResponse, bool, error)
|
||||||
type driver func(cfg *Config, patterns ...string) (*packages.DriverResponse, error)
|
|
||||||
|
|
||||||
func callDriverOnChunksEx(dedup *Deduper, driver driver, cfg *Config, chunks [][]string) (*packages.DriverResponse, error) {
|
|
||||||
if len(chunks) == 0 {
|
|
||||||
return driver(cfg)
|
|
||||||
}
|
|
||||||
responses := make([]*packages.DriverResponse, len(chunks))
|
|
||||||
errNotHandled := errors.New("driver returned NotHandled")
|
|
||||||
var g errgroup.Group
|
|
||||||
for i, chunk := range chunks {
|
|
||||||
i := i
|
|
||||||
chunk := chunk
|
|
||||||
g.Go(func() (err error) {
|
|
||||||
responses[i], err = driver(cfg, chunk...)
|
|
||||||
if responses[i] != nil && responses[i].NotHandled {
|
|
||||||
err = errNotHandled
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if err := g.Wait(); err != nil {
|
|
||||||
if errors.Is(err, errNotHandled) {
|
|
||||||
return &packages.DriverResponse{NotHandled: true}, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return mergeResponsesEx(dedup, responses...), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname splitIntoChunks golang.org/x/tools/go/packages.splitIntoChunks
|
|
||||||
func splitIntoChunks(patterns []string, argMax int) ([][]string, error)
|
|
||||||
|
|
||||||
//go:linkname findExternalDriver golang.org/x/tools/go/packages.findExternalDriver
|
|
||||||
func findExternalDriver(cfg *Config) driver
|
|
||||||
|
|
||||||
//go:linkname goListDriver golang.org/x/tools/go/packages.goListDriver
|
|
||||||
func goListDriver(cfg *Config, patterns ...string) (_ *packages.DriverResponse, err error)
|
|
||||||
|
|
||||||
//go:linkname writeOverlays golang.org/x/tools/internal/gocommand.WriteOverlays
|
|
||||||
func writeOverlays(overlay map[string][]byte) (filename string, cleanup func(), err error)
|
|
||||||
|
|
||||||
func defaultDriverEx(dedup *Deduper, cfg *Config, patterns ...string) (*packages.DriverResponse, bool, error) {
|
|
||||||
const (
|
|
||||||
// windowsArgMax specifies the maximum command line length for
|
|
||||||
// the Windows' CreateProcess function.
|
|
||||||
windowsArgMax = 32767
|
|
||||||
// maxEnvSize is a very rough estimation of the maximum environment
|
|
||||||
// size of a user.
|
|
||||||
maxEnvSize = 16384
|
|
||||||
// safeArgMax specifies the maximum safe command line length to use
|
|
||||||
// by the underlying driver excl. the environment. We choose the Windows'
|
|
||||||
// ARG_MAX as the starting point because it's one of the lowest ARG_MAX
|
|
||||||
// constants out of the different supported platforms,
|
|
||||||
// e.g., https://www.in-ulm.de/~mascheck/various/argmax/#results.
|
|
||||||
safeArgMax = windowsArgMax - maxEnvSize
|
|
||||||
)
|
|
||||||
chunks, err := splitIntoChunks(patterns, safeArgMax)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if driver := findExternalDriver(cfg); driver != nil {
|
|
||||||
response, err := callDriverOnChunksEx(dedup, driver, cfg, chunks)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
} else if !response.NotHandled {
|
|
||||||
return response, true, nil
|
|
||||||
}
|
|
||||||
// (fall through)
|
|
||||||
}
|
|
||||||
|
|
||||||
// go list fallback
|
|
||||||
//
|
|
||||||
// Write overlays once, as there are many calls
|
|
||||||
// to 'go list' (one per chunk plus others too).
|
|
||||||
overlay, cleanupOverlay, err := writeOverlays(cfg.Overlay)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
defer cleanupOverlay()
|
|
||||||
setGoListOverlayFile(cfg, overlay)
|
|
||||||
|
|
||||||
response, err := callDriverOnChunksEx(dedup, goListDriver, cfg, chunks)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
return response, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname newLoader golang.org/x/tools/go/packages.newLoader
|
//go:linkname newLoader golang.org/x/tools/go/packages.newLoader
|
||||||
func newLoader(cfg *Config) *loader
|
func newLoader(cfg *Config) *loader
|
||||||
@@ -230,7 +110,7 @@ func refine(ld *loader, response *packages.DriverResponse) ([]*Package, error)
|
|||||||
// provided for convenient display of all errors.
|
// provided for convenient display of all errors.
|
||||||
func LoadEx(dedup *Deduper, sizes func(types.Sizes) types.Sizes, cfg *Config, patterns ...string) ([]*Package, error) {
|
func LoadEx(dedup *Deduper, sizes func(types.Sizes) types.Sizes, cfg *Config, patterns ...string) ([]*Package, error) {
|
||||||
ld := newLoader(cfg)
|
ld := newLoader(cfg)
|
||||||
response, external, err := defaultDriverEx(dedup, &ld.Config, patterns...)
|
response, external, err := defaultDriver(&ld.Config, patterns...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user