mirror of
https://github.com/TECHNOFAB11/zfs-localpv.git
synced 2025-12-13 06:50:10 +01:00
refact(deps): bump k8s and client-go deps to version v0.20.2 (#294)
Signed-off-by: prateekpandey14 <prateek.pandey@mayadata.io>
This commit is contained in:
parent
533e17a9aa
commit
b1aa6ab51a
2196 changed files with 306727 additions and 251810 deletions
673
vendor/golang.org/x/tools/internal/imports/fix.go
generated
vendored
673
vendor/golang.org/x/tools/internal/imports/fix.go
generated
vendored
|
|
@ -14,7 +14,6 @@ import (
|
|||
"go/token"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
|
@ -22,12 +21,11 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"golang.org/x/tools/internal/gocommand"
|
||||
"golang.org/x/tools/internal/gopathwalk"
|
||||
)
|
||||
|
||||
|
|
@ -52,7 +50,8 @@ var importToGroup = []func(env *ProcessEnv, importPath string) (num int, ok bool
|
|||
return
|
||||
},
|
||||
func(_ *ProcessEnv, importPath string) (num int, ok bool) {
|
||||
if strings.Contains(importPath, ".") {
|
||||
firstComponent := strings.Split(importPath, "/")[0]
|
||||
if strings.Contains(firstComponent, ".") {
|
||||
return 1, true
|
||||
}
|
||||
return
|
||||
|
|
@ -82,7 +81,8 @@ type ImportFix struct {
|
|||
// IdentName is the identifier that this fix will add or remove.
|
||||
IdentName string
|
||||
// FixType is the type of fix this is (AddImport, DeleteImport, SetImportName).
|
||||
FixType ImportFixType
|
||||
FixType ImportFixType
|
||||
Relevance int // see pkg
|
||||
}
|
||||
|
||||
// An ImportInfo represents a single import statement.
|
||||
|
|
@ -263,7 +263,7 @@ type pass struct {
|
|||
|
||||
// loadPackageNames saves the package names for everything referenced by imports.
|
||||
func (p *pass) loadPackageNames(imports []*ImportInfo) error {
|
||||
if p.env.Debug {
|
||||
if p.env.Logf != nil {
|
||||
p.env.Logf("loading package names for %v packages", len(imports))
|
||||
defer func() {
|
||||
p.env.Logf("done loading package names for %v packages", len(imports))
|
||||
|
|
@ -302,7 +302,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string {
|
|||
if known != nil && known.name != "" {
|
||||
return known.name
|
||||
}
|
||||
return importPathToAssumedName(imp.ImportPath)
|
||||
return ImportPathToAssumedName(imp.ImportPath)
|
||||
}
|
||||
|
||||
// load reads in everything necessary to run a pass, and reports whether the
|
||||
|
|
@ -335,7 +335,7 @@ func (p *pass) load() ([]*ImportFix, bool) {
|
|||
if p.loadRealPackageNames {
|
||||
err := p.loadPackageNames(append(imports, p.candidates...))
|
||||
if err != nil {
|
||||
if p.env.Debug {
|
||||
if p.env.Logf != nil {
|
||||
p.env.Logf("loading package names: %v", err)
|
||||
}
|
||||
return nil, false
|
||||
|
|
@ -435,7 +435,7 @@ func (p *pass) importSpecName(imp *ImportInfo) string {
|
|||
}
|
||||
|
||||
ident := p.importIdentifier(imp)
|
||||
if ident == importPathToAssumedName(imp.ImportPath) {
|
||||
if ident == ImportPathToAssumedName(imp.ImportPath) {
|
||||
return "" // ident not needed since the assumed and real names are the same.
|
||||
}
|
||||
return ident
|
||||
|
|
@ -529,7 +529,7 @@ func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv
|
|||
return nil, err
|
||||
}
|
||||
srcDir := filepath.Dir(abs)
|
||||
if env.Debug {
|
||||
if env.Logf != nil {
|
||||
env.Logf("fixImports(filename=%q), abs=%q, srcDir=%q ...", filename, abs, srcDir)
|
||||
}
|
||||
|
||||
|
|
@ -537,7 +537,7 @@ func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv
|
|||
// derive package names from import paths, see if the file is already
|
||||
// complete. We can't add any imports yet, because we don't know
|
||||
// if missing references are actually package vars.
|
||||
p := &pass{fset: fset, f: f, srcDir: srcDir}
|
||||
p := &pass{fset: fset, f: f, srcDir: srcDir, env: env}
|
||||
if fixes, done := p.load(); done {
|
||||
return fixes, nil
|
||||
}
|
||||
|
|
@ -559,8 +559,7 @@ func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv
|
|||
}
|
||||
|
||||
// Third pass: get real package names where we had previously used
|
||||
// the naive algorithm. This is the first step that will use the
|
||||
// environment, so we provide it here for the first time.
|
||||
// the naive algorithm.
|
||||
p = &pass{fset: fset, f: f, srcDir: srcDir, env: env}
|
||||
p.loadRealPackageNames = true
|
||||
p.otherFiles = otherFiles
|
||||
|
|
@ -585,89 +584,127 @@ func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv
|
|||
return fixes, nil
|
||||
}
|
||||
|
||||
// getCandidatePkgs returns the list of pkgs that are accessible from filename,
|
||||
// optionall filtered to only packages named pkgName.
|
||||
func getCandidatePkgs(pkgName, filename string, env *ProcessEnv) ([]*pkg, error) {
|
||||
// TODO(heschi): filter out current package. (Don't forget x_test can import x.)
|
||||
// Highest relevance, used for the standard library. Chosen arbitrarily to
|
||||
// match pre-existing gopls code.
|
||||
const MaxRelevance = 7
|
||||
|
||||
var result []*pkg
|
||||
// getCandidatePkgs works with the passed callback to find all acceptable packages.
|
||||
// It deduplicates by import path, and uses a cached stdlib rather than reading
|
||||
// from disk.
|
||||
func getCandidatePkgs(ctx context.Context, wrappedCallback *scanCallback, filename, filePkg string, env *ProcessEnv) error {
|
||||
notSelf := func(p *pkg) bool {
|
||||
return p.packageName != filePkg || p.dir != filepath.Dir(filename)
|
||||
}
|
||||
// Start off with the standard library.
|
||||
for importPath := range stdlib {
|
||||
if pkgName != "" && path.Base(importPath) != pkgName {
|
||||
continue
|
||||
}
|
||||
result = append(result, &pkg{
|
||||
for importPath, exports := range stdlib {
|
||||
p := &pkg{
|
||||
dir: filepath.Join(env.GOROOT, "src", importPath),
|
||||
importPathShort: importPath,
|
||||
packageName: path.Base(importPath),
|
||||
relevance: 0,
|
||||
})
|
||||
}
|
||||
|
||||
// Exclude goroot results -- getting them is relatively expensive, not cached,
|
||||
// and generally redundant with the in-memory version.
|
||||
exclude := []gopathwalk.RootType{gopathwalk.RootGOROOT}
|
||||
// Only the go/packages resolver uses the first argument, and nobody uses that resolver.
|
||||
scannedPkgs, err := env.GetResolver().scan(nil, true, exclude)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
relevance: MaxRelevance,
|
||||
}
|
||||
if notSelf(p) && wrappedCallback.packageNameLoaded(p) {
|
||||
wrappedCallback.exportsLoaded(p, exports)
|
||||
}
|
||||
}
|
||||
|
||||
var mu sync.Mutex
|
||||
dupCheck := map[string]struct{}{}
|
||||
for _, pkg := range scannedPkgs {
|
||||
if pkgName != "" && pkg.packageName != pkgName {
|
||||
continue
|
||||
}
|
||||
if !canUse(filename, pkg.dir) {
|
||||
continue
|
||||
}
|
||||
if _, ok := dupCheck[pkg.importPathShort]; ok {
|
||||
continue
|
||||
}
|
||||
dupCheck[pkg.importPathShort] = struct{}{}
|
||||
result = append(result, pkg)
|
||||
|
||||
scanFilter := &scanCallback{
|
||||
rootFound: func(root gopathwalk.Root) bool {
|
||||
// Exclude goroot results -- getting them is relatively expensive, not cached,
|
||||
// and generally redundant with the in-memory version.
|
||||
return root.Type != gopathwalk.RootGOROOT && wrappedCallback.rootFound(root)
|
||||
},
|
||||
dirFound: wrappedCallback.dirFound,
|
||||
packageNameLoaded: func(pkg *pkg) bool {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if _, ok := dupCheck[pkg.importPathShort]; ok {
|
||||
return false
|
||||
}
|
||||
dupCheck[pkg.importPathShort] = struct{}{}
|
||||
return notSelf(pkg) && wrappedCallback.packageNameLoaded(pkg)
|
||||
},
|
||||
exportsLoaded: func(pkg *pkg, exports []string) {
|
||||
// If we're an x_test, load the package under test's test variant.
|
||||
if strings.HasSuffix(filePkg, "_test") && pkg.dir == filepath.Dir(filename) {
|
||||
var err error
|
||||
_, exports, err = loadExportsFromFiles(ctx, env, pkg.dir, true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
wrappedCallback.exportsLoaded(pkg, exports)
|
||||
},
|
||||
}
|
||||
return env.GetResolver().scan(ctx, scanFilter)
|
||||
}
|
||||
|
||||
// Sort first by relevance, then by package name, with import path as a tiebreaker.
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
pi, pj := result[i], result[j]
|
||||
if pi.relevance != pj.relevance {
|
||||
return pi.relevance < pj.relevance
|
||||
}
|
||||
if pi.packageName != pj.packageName {
|
||||
return pi.packageName < pj.packageName
|
||||
}
|
||||
return pi.importPathShort < pj.importPathShort
|
||||
})
|
||||
func ScoreImportPaths(ctx context.Context, env *ProcessEnv, paths []string) map[string]int {
|
||||
result := make(map[string]int)
|
||||
for _, path := range paths {
|
||||
result[path] = env.GetResolver().scoreImportPath(ctx, path)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
return result, nil
|
||||
func PrimeCache(ctx context.Context, env *ProcessEnv) error {
|
||||
// Fully scan the disk for directories, but don't actually read any Go files.
|
||||
callback := &scanCallback{
|
||||
rootFound: func(gopathwalk.Root) bool {
|
||||
return true
|
||||
},
|
||||
dirFound: func(pkg *pkg) bool {
|
||||
return false
|
||||
},
|
||||
packageNameLoaded: func(pkg *pkg) bool {
|
||||
return false
|
||||
},
|
||||
}
|
||||
return getCandidatePkgs(ctx, callback, "", "", env)
|
||||
}
|
||||
|
||||
func candidateImportName(pkg *pkg) string {
|
||||
if importPathToAssumedName(pkg.importPathShort) != pkg.packageName {
|
||||
if ImportPathToAssumedName(pkg.importPathShort) != pkg.packageName {
|
||||
return pkg.packageName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// getAllCandidates gets all of the candidates to be imported, regardless of if they are needed.
|
||||
func getAllCandidates(filename string, env *ProcessEnv) ([]ImportFix, error) {
|
||||
pkgs, err := getCandidatePkgs("", filename, env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func getAllCandidates(ctx context.Context, wrapped func(ImportFix), searchPrefix, filename, filePkg string, env *ProcessEnv) error {
|
||||
callback := &scanCallback{
|
||||
rootFound: func(gopathwalk.Root) bool {
|
||||
return true
|
||||
},
|
||||
dirFound: func(pkg *pkg) bool {
|
||||
if !canUse(filename, pkg.dir) {
|
||||
return false
|
||||
}
|
||||
// Try the assumed package name first, then a simpler path match
|
||||
// in case of packages named vN, which are not uncommon.
|
||||
return strings.HasPrefix(ImportPathToAssumedName(pkg.importPathShort), searchPrefix) ||
|
||||
strings.HasPrefix(path.Base(pkg.importPathShort), searchPrefix)
|
||||
},
|
||||
packageNameLoaded: func(pkg *pkg) bool {
|
||||
if !strings.HasPrefix(pkg.packageName, searchPrefix) {
|
||||
return false
|
||||
}
|
||||
wrapped(ImportFix{
|
||||
StmtInfo: ImportInfo{
|
||||
ImportPath: pkg.importPathShort,
|
||||
Name: candidateImportName(pkg),
|
||||
},
|
||||
IdentName: pkg.packageName,
|
||||
FixType: AddImport,
|
||||
Relevance: pkg.relevance,
|
||||
})
|
||||
return false
|
||||
},
|
||||
}
|
||||
result := make([]ImportFix, 0, len(pkgs))
|
||||
for _, pkg := range pkgs {
|
||||
result = append(result, ImportFix{
|
||||
StmtInfo: ImportInfo{
|
||||
ImportPath: pkg.importPathShort,
|
||||
Name: candidateImportName(pkg),
|
||||
},
|
||||
IdentName: pkg.packageName,
|
||||
FixType: AddImport,
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
return getCandidatePkgs(ctx, callback, filename, filePkg, env)
|
||||
}
|
||||
|
||||
// A PackageExport is a package and its exports.
|
||||
|
|
@ -676,64 +713,63 @@ type PackageExport struct {
|
|||
Exports []string
|
||||
}
|
||||
|
||||
func getPackageExports(completePackage, filename string, env *ProcessEnv) ([]PackageExport, error) {
|
||||
pkgs, err := getCandidatePkgs(completePackage, filename, env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func getPackageExports(ctx context.Context, wrapped func(PackageExport), searchPkg, filename, filePkg string, env *ProcessEnv) error {
|
||||
callback := &scanCallback{
|
||||
rootFound: func(gopathwalk.Root) bool {
|
||||
return true
|
||||
},
|
||||
dirFound: func(pkg *pkg) bool {
|
||||
return pkgIsCandidate(filename, references{searchPkg: nil}, pkg)
|
||||
},
|
||||
packageNameLoaded: func(pkg *pkg) bool {
|
||||
return pkg.packageName == searchPkg
|
||||
},
|
||||
exportsLoaded: func(pkg *pkg, exports []string) {
|
||||
sort.Strings(exports)
|
||||
wrapped(PackageExport{
|
||||
Fix: &ImportFix{
|
||||
StmtInfo: ImportInfo{
|
||||
ImportPath: pkg.importPathShort,
|
||||
Name: candidateImportName(pkg),
|
||||
},
|
||||
IdentName: pkg.packageName,
|
||||
FixType: AddImport,
|
||||
Relevance: pkg.relevance,
|
||||
},
|
||||
Exports: exports,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
results := make([]PackageExport, 0, len(pkgs))
|
||||
for _, pkg := range pkgs {
|
||||
fix := &ImportFix{
|
||||
StmtInfo: ImportInfo{
|
||||
ImportPath: pkg.importPathShort,
|
||||
Name: candidateImportName(pkg),
|
||||
},
|
||||
IdentName: pkg.packageName,
|
||||
FixType: AddImport,
|
||||
}
|
||||
var exports []string
|
||||
if e, ok := stdlib[pkg.importPathShort]; ok {
|
||||
exports = e
|
||||
} else {
|
||||
exports, err = loadExportsForPackage(context.Background(), env, completePackage, pkg)
|
||||
if err != nil {
|
||||
if env.Debug {
|
||||
env.Logf("while completing %q, error loading exports from %q: %v", completePackage, pkg.importPathShort, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
sort.Strings(exports)
|
||||
results = append(results, PackageExport{
|
||||
Fix: fix,
|
||||
Exports: exports,
|
||||
})
|
||||
}
|
||||
|
||||
return results, nil
|
||||
return getCandidatePkgs(ctx, callback, filename, filePkg, env)
|
||||
}
|
||||
|
||||
// ProcessEnv contains environment variables and settings that affect the use of
|
||||
// the go command, the go/build package, etc.
|
||||
type ProcessEnv struct {
|
||||
LocalPrefix string
|
||||
Debug bool
|
||||
|
||||
GocmdRunner *gocommand.Runner
|
||||
|
||||
BuildFlags []string
|
||||
|
||||
// If non-empty, these will be used instead of the
|
||||
// process-wide values.
|
||||
GOPATH, GOROOT, GO111MODULE, GOPROXY, GOFLAGS, GOSUMDB string
|
||||
WorkingDir string
|
||||
|
||||
// If true, use go/packages regardless of the environment.
|
||||
ForceGoPackages bool
|
||||
|
||||
// Logf is the default logger for the ProcessEnv.
|
||||
// If Logf is non-nil, debug logging is enabled through this function.
|
||||
Logf func(format string, args ...interface{})
|
||||
|
||||
resolver Resolver
|
||||
}
|
||||
|
||||
// CopyConfig copies the env's configuration into a new env.
|
||||
func (e *ProcessEnv) CopyConfig() *ProcessEnv {
|
||||
copy := *e
|
||||
copy.resolver = nil
|
||||
return ©
|
||||
}
|
||||
|
||||
func (e *ProcessEnv) env() []string {
|
||||
env := os.Environ()
|
||||
add := func(k, v string) {
|
||||
|
|
@ -757,73 +793,55 @@ func (e *ProcessEnv) GetResolver() Resolver {
|
|||
if e.resolver != nil {
|
||||
return e.resolver
|
||||
}
|
||||
if e.ForceGoPackages {
|
||||
e.resolver = &goPackagesResolver{env: e}
|
||||
return e.resolver
|
||||
}
|
||||
|
||||
out, err := e.invokeGo("env", "GOMOD")
|
||||
out, err := e.invokeGo(context.TODO(), "env", "GOMOD")
|
||||
if err != nil || len(bytes.TrimSpace(out.Bytes())) == 0 {
|
||||
e.resolver = &gopathResolver{env: e}
|
||||
e.resolver = newGopathResolver(e)
|
||||
return e.resolver
|
||||
}
|
||||
e.resolver = &ModuleResolver{env: e}
|
||||
e.resolver = newModuleResolver(e)
|
||||
return e.resolver
|
||||
}
|
||||
|
||||
func (e *ProcessEnv) newPackagesConfig(mode packages.LoadMode) *packages.Config {
|
||||
return &packages.Config{
|
||||
Mode: mode,
|
||||
Dir: e.WorkingDir,
|
||||
Env: e.env(),
|
||||
}
|
||||
}
|
||||
|
||||
func (e *ProcessEnv) buildContext() *build.Context {
|
||||
ctx := build.Default
|
||||
ctx.GOROOT = e.GOROOT
|
||||
ctx.GOPATH = e.GOPATH
|
||||
|
||||
// As of Go 1.14, build.Context has a WorkingDir field
|
||||
// As of Go 1.14, build.Context has a Dir field
|
||||
// (see golang.org/issue/34860).
|
||||
// Populate it only if present.
|
||||
if wd := reflect.ValueOf(&ctx).Elem().FieldByName("WorkingDir"); wd.IsValid() && wd.Kind() == reflect.String {
|
||||
wd.SetString(e.WorkingDir)
|
||||
rc := reflect.ValueOf(&ctx).Elem()
|
||||
dir := rc.FieldByName("Dir")
|
||||
if !dir.IsValid() {
|
||||
// Working drafts of Go 1.14 named the field "WorkingDir" instead.
|
||||
// TODO(bcmills): Remove this case after the Go 1.14 beta has been released.
|
||||
dir = rc.FieldByName("WorkingDir")
|
||||
}
|
||||
if dir.IsValid() && dir.Kind() == reflect.String {
|
||||
dir.SetString(e.WorkingDir)
|
||||
}
|
||||
|
||||
return &ctx
|
||||
}
|
||||
|
||||
func (e *ProcessEnv) invokeGo(args ...string) (*bytes.Buffer, error) {
|
||||
cmd := exec.Command("go", args...)
|
||||
stdout := &bytes.Buffer{}
|
||||
stderr := &bytes.Buffer{}
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
cmd.Env = e.env()
|
||||
cmd.Dir = e.WorkingDir
|
||||
|
||||
if e.Debug {
|
||||
defer func(start time.Time) { e.Logf("%s for %v", time.Since(start), cmdDebugStr(cmd)) }(time.Now())
|
||||
func (e *ProcessEnv) invokeGo(ctx context.Context, verb string, args ...string) (*bytes.Buffer, error) {
|
||||
inv := gocommand.Invocation{
|
||||
Verb: verb,
|
||||
Args: args,
|
||||
BuildFlags: e.BuildFlags,
|
||||
Env: e.env(),
|
||||
Logf: e.Logf,
|
||||
WorkingDir: e.WorkingDir,
|
||||
}
|
||||
if err := cmd.Run(); err != nil {
|
||||
return nil, fmt.Errorf("running go: %v (stderr:\n%s)", err, stderr)
|
||||
}
|
||||
return stdout, nil
|
||||
}
|
||||
|
||||
func cmdDebugStr(cmd *exec.Cmd) string {
|
||||
env := make(map[string]string)
|
||||
for _, kv := range cmd.Env {
|
||||
split := strings.Split(kv, "=")
|
||||
k, v := split[0], split[1]
|
||||
env[k] = v
|
||||
}
|
||||
|
||||
return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v go %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], cmd.Args)
|
||||
return e.GocmdRunner.Run(ctx, inv)
|
||||
}
|
||||
|
||||
func addStdlibCandidates(pass *pass, refs references) {
|
||||
add := func(pkg string) {
|
||||
// Prevent self-imports.
|
||||
if path.Base(pkg) == pass.f.Name.Name && filepath.Join(pass.env.GOROOT, "src", pkg) == pass.srcDir {
|
||||
return
|
||||
}
|
||||
exports := copyExports(stdlib[pkg])
|
||||
pass.addCandidate(
|
||||
&ImportInfo{ImportPath: pkg},
|
||||
|
|
@ -848,94 +866,65 @@ func addStdlibCandidates(pass *pass, refs references) {
|
|||
type Resolver interface {
|
||||
// loadPackageNames loads the package names in importPaths.
|
||||
loadPackageNames(importPaths []string, srcDir string) (map[string]string, error)
|
||||
// scan finds (at least) the packages satisfying refs. If loadNames is true,
|
||||
// package names will be set on the results, and dirs whose package name
|
||||
// could not be determined will be excluded.
|
||||
scan(refs references, loadNames bool, exclude []gopathwalk.RootType) ([]*pkg, error)
|
||||
// scan works with callback to search for packages. See scanCallback for details.
|
||||
scan(ctx context.Context, callback *scanCallback) error
|
||||
// loadExports returns the set of exported symbols in the package at dir.
|
||||
// loadExports may be called concurrently.
|
||||
loadExports(ctx context.Context, pkg *pkg) (string, []string, error)
|
||||
loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error)
|
||||
// scoreImportPath returns the relevance for an import path.
|
||||
scoreImportPath(ctx context.Context, path string) int
|
||||
|
||||
ClearForNewScan()
|
||||
}
|
||||
|
||||
// gopackagesResolver implements resolver for GOPATH and module workspaces using go/packages.
|
||||
type goPackagesResolver struct {
|
||||
env *ProcessEnv
|
||||
}
|
||||
|
||||
func (r *goPackagesResolver) ClearForNewScan() {}
|
||||
|
||||
func (r *goPackagesResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {
|
||||
if len(importPaths) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
cfg := r.env.newPackagesConfig(packages.LoadFiles)
|
||||
pkgs, err := packages.Load(cfg, importPaths...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
names := map[string]string{}
|
||||
for _, pkg := range pkgs {
|
||||
names[VendorlessPath(pkg.PkgPath)] = pkg.Name
|
||||
}
|
||||
// We may not have found all the packages. Guess the rest.
|
||||
for _, path := range importPaths {
|
||||
if _, ok := names[path]; ok {
|
||||
continue
|
||||
}
|
||||
names[path] = importPathToAssumedName(path)
|
||||
}
|
||||
return names, nil
|
||||
|
||||
}
|
||||
|
||||
func (r *goPackagesResolver) scan(refs references, _ bool, _ []gopathwalk.RootType) ([]*pkg, error) {
|
||||
var loadQueries []string
|
||||
for pkgName := range refs {
|
||||
loadQueries = append(loadQueries, "iamashamedtousethedisabledqueryname="+pkgName)
|
||||
}
|
||||
sort.Strings(loadQueries)
|
||||
cfg := r.env.newPackagesConfig(packages.LoadFiles)
|
||||
goPackages, err := packages.Load(cfg, loadQueries...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var scan []*pkg
|
||||
for _, goPackage := range goPackages {
|
||||
scan = append(scan, &pkg{
|
||||
dir: filepath.Dir(goPackage.CompiledGoFiles[0]),
|
||||
importPathShort: VendorlessPath(goPackage.PkgPath),
|
||||
goPackage: goPackage,
|
||||
packageName: goPackage.Name,
|
||||
})
|
||||
}
|
||||
return scan, nil
|
||||
}
|
||||
|
||||
func (r *goPackagesResolver) loadExports(ctx context.Context, pkg *pkg) (string, []string, error) {
|
||||
if pkg.goPackage == nil {
|
||||
return "", nil, fmt.Errorf("goPackage not set")
|
||||
}
|
||||
var exports []string
|
||||
fset := token.NewFileSet()
|
||||
for _, fname := range pkg.goPackage.CompiledGoFiles {
|
||||
f, err := parser.ParseFile(fset, fname, nil, 0)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("parsing %s: %v", fname, err)
|
||||
}
|
||||
for name := range f.Scope.Objects {
|
||||
if ast.IsExported(name) {
|
||||
exports = append(exports, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return pkg.goPackage.Name, exports, nil
|
||||
// A scanCallback controls a call to scan and receives its results.
|
||||
// In general, minor errors will be silently discarded; a user should not
|
||||
// expect to receive a full series of calls for everything.
|
||||
type scanCallback struct {
|
||||
// rootFound is called before scanning a new root dir. If it returns true,
|
||||
// the root will be scanned. Returning false will not necessarily prevent
|
||||
// directories from that root making it to dirFound.
|
||||
rootFound func(gopathwalk.Root) bool
|
||||
// dirFound is called when a directory is found that is possibly a Go package.
|
||||
// pkg will be populated with everything except packageName.
|
||||
// If it returns true, the package's name will be loaded.
|
||||
dirFound func(pkg *pkg) bool
|
||||
// packageNameLoaded is called when a package is found and its name is loaded.
|
||||
// If it returns true, the package's exports will be loaded.
|
||||
packageNameLoaded func(pkg *pkg) bool
|
||||
// exportsLoaded is called when a package's exports have been loaded.
|
||||
exportsLoaded func(pkg *pkg, exports []string)
|
||||
}
|
||||
|
||||
func addExternalCandidates(pass *pass, refs references, filename string) error {
|
||||
dirScan, err := pass.env.GetResolver().scan(refs, false, nil)
|
||||
var mu sync.Mutex
|
||||
found := make(map[string][]pkgDistance)
|
||||
callback := &scanCallback{
|
||||
rootFound: func(gopathwalk.Root) bool {
|
||||
return true // We want everything.
|
||||
},
|
||||
dirFound: func(pkg *pkg) bool {
|
||||
return pkgIsCandidate(filename, refs, pkg)
|
||||
},
|
||||
packageNameLoaded: func(pkg *pkg) bool {
|
||||
if _, want := refs[pkg.packageName]; !want {
|
||||
return false
|
||||
}
|
||||
if pkg.dir == pass.srcDir && pass.f.Name.Name == pkg.packageName {
|
||||
// The candidate is in the same directory and has the
|
||||
// same package name. Don't try to import ourselves.
|
||||
return false
|
||||
}
|
||||
if !canUse(filename, pkg.dir) {
|
||||
return false
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
found[pkg.packageName] = append(found[pkg.packageName], pkgDistance{pkg, distance(pass.srcDir, pkg.dir)})
|
||||
return false // We'll do our own loading after we sort.
|
||||
},
|
||||
}
|
||||
err := pass.env.GetResolver().scan(context.Background(), callback)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -962,7 +951,7 @@ func addExternalCandidates(pass *pass, refs references, filename string) error {
|
|||
go func(pkgName string, symbols map[string]bool) {
|
||||
defer wg.Done()
|
||||
|
||||
found, err := findImport(ctx, pass, dirScan, pkgName, symbols, filename)
|
||||
found, err := findImport(ctx, pass, found[pkgName], pkgName, symbols, filename)
|
||||
|
||||
if err != nil {
|
||||
firstErrOnce.Do(func() {
|
||||
|
|
@ -1006,7 +995,7 @@ func notIdentifier(ch rune) bool {
|
|||
ch >= utf8.RuneSelf && (unicode.IsLetter(ch) || unicode.IsDigit(ch)))
|
||||
}
|
||||
|
||||
// importPathToAssumedName returns the assumed package name of an import path.
|
||||
// ImportPathToAssumedName returns the assumed package name of an import path.
|
||||
// It does this using only string parsing of the import path.
|
||||
// It picks the last element of the path that does not look like a major
|
||||
// version, and then picks the valid identifier off the start of that element.
|
||||
|
|
@ -1014,7 +1003,7 @@ func notIdentifier(ch rune) bool {
|
|||
// clarity.
|
||||
// This function could be moved to a standard package and exported if we want
|
||||
// for use in other tools.
|
||||
func importPathToAssumedName(importPath string) string {
|
||||
func ImportPathToAssumedName(importPath string) string {
|
||||
base := path.Base(importPath)
|
||||
if strings.HasPrefix(base, "v") {
|
||||
if _, err := strconv.Atoi(base[1:]); err == nil {
|
||||
|
|
@ -1033,24 +1022,36 @@ func importPathToAssumedName(importPath string) string {
|
|||
|
||||
// gopathResolver implements resolver for GOPATH workspaces.
|
||||
type gopathResolver struct {
|
||||
env *ProcessEnv
|
||||
cache *dirInfoCache
|
||||
env *ProcessEnv
|
||||
walked bool
|
||||
cache *dirInfoCache
|
||||
scanSema chan struct{} // scanSema prevents concurrent scans.
|
||||
}
|
||||
|
||||
func (r *gopathResolver) init() {
|
||||
if r.cache == nil {
|
||||
r.cache = &dirInfoCache{
|
||||
dirs: map[string]*directoryPackageInfo{},
|
||||
}
|
||||
func newGopathResolver(env *ProcessEnv) *gopathResolver {
|
||||
r := &gopathResolver{
|
||||
env: env,
|
||||
cache: &dirInfoCache{
|
||||
dirs: map[string]*directoryPackageInfo{},
|
||||
listeners: map[*int]cacheListener{},
|
||||
},
|
||||
scanSema: make(chan struct{}, 1),
|
||||
}
|
||||
r.scanSema <- struct{}{}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *gopathResolver) ClearForNewScan() {
|
||||
r.cache = nil
|
||||
<-r.scanSema
|
||||
r.cache = &dirInfoCache{
|
||||
dirs: map[string]*directoryPackageInfo{},
|
||||
listeners: map[*int]cacheListener{},
|
||||
}
|
||||
r.walked = false
|
||||
r.scanSema <- struct{}{}
|
||||
}
|
||||
|
||||
func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {
|
||||
r.init()
|
||||
names := map[string]string{}
|
||||
for _, path := range importPaths {
|
||||
names[path] = importPathToName(r.env, path, srcDir)
|
||||
|
|
@ -1130,7 +1131,6 @@ func packageDirToName(dir string) (packageName string, err error) {
|
|||
}
|
||||
|
||||
type pkg struct {
|
||||
goPackage *packages.Package
|
||||
dir string // absolute file path to pkg directory ("/usr/lib/go/src/net/http")
|
||||
importPathShort string // vendorless import path ("net/http", "a/b")
|
||||
packageName string // package name loaded from source if requested
|
||||
|
|
@ -1178,8 +1178,7 @@ func distance(basepath, targetpath string) int {
|
|||
return strings.Count(p, string(filepath.Separator)) + 1
|
||||
}
|
||||
|
||||
func (r *gopathResolver) scan(_ references, loadNames bool, exclude []gopathwalk.RootType) ([]*pkg, error) {
|
||||
r.init()
|
||||
func (r *gopathResolver) scan(ctx context.Context, callback *scanCallback) error {
|
||||
add := func(root gopathwalk.Root, dir string) {
|
||||
// We assume cached directories have not changed. We can skip them and their
|
||||
// children.
|
||||
|
|
@ -1196,56 +1195,84 @@ func (r *gopathResolver) scan(_ references, loadNames bool, exclude []gopathwalk
|
|||
}
|
||||
r.cache.Store(dir, info)
|
||||
}
|
||||
roots := filterRoots(gopathwalk.SrcDirsRoots(r.env.buildContext()), exclude)
|
||||
gopathwalk.Walk(roots, add, gopathwalk.Options{Debug: r.env.Debug, ModulesEnabled: false})
|
||||
var result []*pkg
|
||||
for _, dir := range r.cache.Keys() {
|
||||
info, ok := r.cache.Load(dir)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if loadNames {
|
||||
var err error
|
||||
info, err = r.cache.CachePackageName(info)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
processDir := func(info directoryPackageInfo) {
|
||||
// Skip this directory if we were not able to get the package information successfully.
|
||||
if scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
p := &pkg{
|
||||
importPathShort: info.nonCanonicalImportPath,
|
||||
dir: dir,
|
||||
relevance: 1,
|
||||
packageName: info.packageName,
|
||||
dir: info.dir,
|
||||
relevance: MaxRelevance - 1,
|
||||
}
|
||||
if info.rootType == gopathwalk.RootGOROOT {
|
||||
p.relevance = 0
|
||||
p.relevance = MaxRelevance
|
||||
}
|
||||
|
||||
if !callback.dirFound(p) {
|
||||
return
|
||||
}
|
||||
var err error
|
||||
p.packageName, err = r.cache.CachePackageName(info)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !callback.packageNameLoaded(p) {
|
||||
return
|
||||
}
|
||||
if _, exports, err := r.loadExports(ctx, p, false); err == nil {
|
||||
callback.exportsLoaded(p, exports)
|
||||
}
|
||||
result = append(result, p)
|
||||
}
|
||||
return result, nil
|
||||
stop := r.cache.ScanAndListen(ctx, processDir)
|
||||
defer stop()
|
||||
// The callback is not necessarily safe to use in the goroutine below. Process roots eagerly.
|
||||
roots := filterRoots(gopathwalk.SrcDirsRoots(r.env.buildContext()), callback.rootFound)
|
||||
// We can't cancel walks, because we need them to finish to have a usable
|
||||
// cache. Instead, run them in a separate goroutine and detach.
|
||||
scanDone := make(chan struct{})
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-r.scanSema:
|
||||
}
|
||||
defer func() { r.scanSema <- struct{}{} }()
|
||||
gopathwalk.Walk(roots, add, gopathwalk.Options{Logf: r.env.Logf, ModulesEnabled: false})
|
||||
close(scanDone)
|
||||
}()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-scanDone:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func filterRoots(roots []gopathwalk.Root, exclude []gopathwalk.RootType) []gopathwalk.Root {
|
||||
func (r *gopathResolver) scoreImportPath(ctx context.Context, path string) int {
|
||||
if _, ok := stdlib[path]; ok {
|
||||
return MaxRelevance
|
||||
}
|
||||
return MaxRelevance - 1
|
||||
}
|
||||
|
||||
func filterRoots(roots []gopathwalk.Root, include func(gopathwalk.Root) bool) []gopathwalk.Root {
|
||||
var result []gopathwalk.Root
|
||||
outer:
|
||||
for _, root := range roots {
|
||||
for _, i := range exclude {
|
||||
if i == root.Type {
|
||||
continue outer
|
||||
}
|
||||
if !include(root) {
|
||||
continue
|
||||
}
|
||||
result = append(result, root)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *gopathResolver) loadExports(ctx context.Context, pkg *pkg) (string, []string, error) {
|
||||
r.init()
|
||||
if info, ok := r.cache.Load(pkg.dir); ok {
|
||||
func (r *gopathResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) {
|
||||
if info, ok := r.cache.Load(pkg.dir); ok && !includeTest {
|
||||
return r.cache.CacheExports(ctx, r.env, info)
|
||||
}
|
||||
return loadExportsFromFiles(ctx, r.env, pkg.dir)
|
||||
return loadExportsFromFiles(ctx, r.env, pkg.dir, includeTest)
|
||||
}
|
||||
|
||||
// VendorlessPath returns the devendorized version of the import path ipath.
|
||||
|
|
@ -1261,7 +1288,7 @@ func VendorlessPath(ipath string) string {
|
|||
return ipath
|
||||
}
|
||||
|
||||
func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string) (string, []string, error) {
|
||||
func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, includeTest bool) (string, []string, error) {
|
||||
var exports []string
|
||||
|
||||
// Look for non-test, buildable .go files which could provide exports.
|
||||
|
|
@ -1272,7 +1299,7 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string) (str
|
|||
var files []os.FileInfo
|
||||
for _, fi := range all {
|
||||
name := fi.Name()
|
||||
if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
|
||||
if !strings.HasSuffix(name, ".go") || (!includeTest && strings.HasSuffix(name, "_test.go")) {
|
||||
continue
|
||||
}
|
||||
match, err := env.buildContext().MatchFile(dir, fi.Name())
|
||||
|
|
@ -1298,13 +1325,20 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string) (str
|
|||
fullFile := filepath.Join(dir, fi.Name())
|
||||
f, err := parser.ParseFile(fset, fullFile, nil, 0)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("parsing %s: %v", fullFile, err)
|
||||
if env.Logf != nil {
|
||||
env.Logf("error parsing %v: %v", fullFile, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if f.Name.Name == "documentation" {
|
||||
// Special case from go/build.ImportDir, not
|
||||
// handled by MatchFile above.
|
||||
continue
|
||||
}
|
||||
if includeTest && strings.HasSuffix(f.Name.Name, "_test") {
|
||||
// x_test package. We want internal test files only.
|
||||
continue
|
||||
}
|
||||
pkgName = f.Name.Name
|
||||
for name := range f.Scope.Objects {
|
||||
if ast.IsExported(name) {
|
||||
|
|
@ -1313,7 +1347,7 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string) (str
|
|||
}
|
||||
}
|
||||
|
||||
if env.Debug {
|
||||
if env.Logf != nil {
|
||||
sortedExports := append([]string(nil), exports...)
|
||||
sort.Strings(sortedExports)
|
||||
env.Logf("loaded exports in dir %v (package %v): %v", dir, pkgName, strings.Join(sortedExports, ", "))
|
||||
|
|
@ -1323,42 +1357,19 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string) (str
|
|||
|
||||
// findImport searches for a package with the given symbols.
|
||||
// If no package is found, findImport returns ("", false, nil)
|
||||
func findImport(ctx context.Context, pass *pass, dirScan []*pkg, pkgName string, symbols map[string]bool, filename string) (*pkg, error) {
|
||||
pkgDir, err := filepath.Abs(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pkgDir = filepath.Dir(pkgDir)
|
||||
|
||||
// Find candidate packages, looking only at their directory names first.
|
||||
var candidates []pkgDistance
|
||||
for _, pkg := range dirScan {
|
||||
if pkg.dir == pkgDir && pass.f.Name.Name == pkgName {
|
||||
// The candidate is in the same directory and has the
|
||||
// same package name. Don't try to import ourselves.
|
||||
continue
|
||||
}
|
||||
if pkgIsCandidate(filename, pkgName, pkg) {
|
||||
candidates = append(candidates, pkgDistance{
|
||||
pkg: pkg,
|
||||
distance: distance(pkgDir, pkg.dir),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgName string, symbols map[string]bool, filename string) (*pkg, error) {
|
||||
// Sort the candidates by their import package length,
|
||||
// assuming that shorter package names are better than long
|
||||
// ones. Note that this sorts by the de-vendored name, so
|
||||
// there's no "penalty" for vendoring.
|
||||
sort.Sort(byDistanceOrImportPathShortLength(candidates))
|
||||
if pass.env.Debug {
|
||||
if pass.env.Logf != nil {
|
||||
for i, c := range candidates {
|
||||
pass.env.Logf("%s candidate %d/%d: %v in %v", pkgName, i+1, len(candidates), c.pkg.importPathShort, c.pkg.dir)
|
||||
}
|
||||
}
|
||||
|
||||
// Collect exports for packages with matching names.
|
||||
|
||||
rescv := make([]chan *pkg, len(candidates))
|
||||
for i := range candidates {
|
||||
rescv[i] = make(chan *pkg, 1)
|
||||
|
|
@ -1390,12 +1401,14 @@ func findImport(ctx context.Context, pass *pass, dirScan []*pkg, pkgName string,
|
|||
wg.Done()
|
||||
}()
|
||||
|
||||
if pass.env.Debug {
|
||||
if pass.env.Logf != nil {
|
||||
pass.env.Logf("loading exports in dir %s (seeking package %s)", c.pkg.dir, pkgName)
|
||||
}
|
||||
exports, err := loadExportsForPackage(ctx, pass.env, pkgName, c.pkg)
|
||||
// If we're an x_test, load the package under test's test variant.
|
||||
includeTest := strings.HasSuffix(pass.f.Name.Name, "_test") && c.pkg.dir == pass.srcDir
|
||||
_, exports, err := pass.env.GetResolver().loadExports(ctx, c.pkg, includeTest)
|
||||
if err != nil {
|
||||
if pass.env.Debug {
|
||||
if pass.env.Logf != nil {
|
||||
pass.env.Logf("loading exports in dir %s (seeking package %s): %v", c.pkg.dir, pkgName, err)
|
||||
}
|
||||
resc <- nil
|
||||
|
|
@ -1430,17 +1443,6 @@ func findImport(ctx context.Context, pass *pass, dirScan []*pkg, pkgName string,
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func loadExportsForPackage(ctx context.Context, env *ProcessEnv, expectPkg string, pkg *pkg) ([]string, error) {
|
||||
pkgName, exports, err := env.GetResolver().loadExports(ctx, pkg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if expectPkg != pkgName {
|
||||
return nil, fmt.Errorf("dir %v is package %v, wanted %v", pkg.dir, pkgName, expectPkg)
|
||||
}
|
||||
return exports, err
|
||||
}
|
||||
|
||||
// pkgIsCandidate reports whether pkg is a candidate for satisfying the
|
||||
// finding which package pkgIdent in the file named by filename is trying
|
||||
// to refer to.
|
||||
|
|
@ -1453,7 +1455,7 @@ func loadExportsForPackage(ctx context.Context, env *ProcessEnv, expectPkg strin
|
|||
// filename is the file being formatted.
|
||||
// pkgIdent is the package being searched for, like "client" (if
|
||||
// searching for "client.New")
|
||||
func pkgIsCandidate(filename, pkgIdent string, pkg *pkg) bool {
|
||||
func pkgIsCandidate(filename string, refs references, pkg *pkg) bool {
|
||||
// Check "internal" and "vendor" visibility:
|
||||
if !canUse(filename, pkg.dir) {
|
||||
return false
|
||||
|
|
@ -1471,17 +1473,18 @@ func pkgIsCandidate(filename, pkgIdent string, pkg *pkg) bool {
|
|||
// "bar", which is strongly discouraged
|
||||
// anyway. There's no reason goimports needs
|
||||
// to be slow just to accommodate that.
|
||||
lastTwo := lastTwoComponents(pkg.importPathShort)
|
||||
if strings.Contains(lastTwo, pkgIdent) {
|
||||
return true
|
||||
}
|
||||
if hasHyphenOrUpperASCII(lastTwo) && !hasHyphenOrUpperASCII(pkgIdent) {
|
||||
lastTwo = lowerASCIIAndRemoveHyphen(lastTwo)
|
||||
for pkgIdent := range refs {
|
||||
lastTwo := lastTwoComponents(pkg.importPathShort)
|
||||
if strings.Contains(lastTwo, pkgIdent) {
|
||||
return true
|
||||
}
|
||||
if hasHyphenOrUpperASCII(lastTwo) && !hasHyphenOrUpperASCII(pkgIdent) {
|
||||
lastTwo = lowerASCIIAndRemoveHyphen(lastTwo)
|
||||
if strings.Contains(lastTwo, pkgIdent) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
|||
62
vendor/golang.org/x/tools/internal/imports/imports.go
generated
vendored
62
vendor/golang.org/x/tools/internal/imports/imports.go
generated
vendored
|
|
@ -11,6 +11,7 @@ package imports
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
|
|
@ -20,12 +21,13 @@ import (
|
|||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
"golang.org/x/tools/internal/gocommand"
|
||||
)
|
||||
|
||||
// Options is golang.org/x/tools/imports.Options with extra internal-only options.
|
||||
|
|
@ -83,42 +85,54 @@ func FixImports(filename string, src []byte, opt *Options) (fixes []*ImportFix,
|
|||
return getFixes(fileSet, file, filename, opt.Env)
|
||||
}
|
||||
|
||||
// ApplyFix will apply all of the fixes to the file and format it.
|
||||
func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options) (formatted []byte, err error) {
|
||||
// ApplyFixes applies all of the fixes to the file and formats it. extraMode
|
||||
// is added in when parsing the file.
|
||||
func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, extraMode parser.Mode) (formatted []byte, err error) {
|
||||
src, opt, err = initialize(filename, src, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Don't use parse() -- we don't care about fragments or statement lists
|
||||
// here, and we need to work with unparseable files.
|
||||
fileSet := token.NewFileSet()
|
||||
file, adjust, err := parse(fileSet, filename, src, opt)
|
||||
if err != nil {
|
||||
parserMode := parser.Mode(0)
|
||||
if opt.Comments {
|
||||
parserMode |= parser.ParseComments
|
||||
}
|
||||
if opt.AllErrors {
|
||||
parserMode |= parser.AllErrors
|
||||
}
|
||||
parserMode |= extraMode
|
||||
|
||||
file, err := parser.ParseFile(fileSet, filename, src, parserMode)
|
||||
if file == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Apply the fixes to the file.
|
||||
apply(fileSet, file, fixes)
|
||||
|
||||
return formatFile(fileSet, file, src, adjust, opt)
|
||||
return formatFile(fileSet, file, src, nil, opt)
|
||||
}
|
||||
|
||||
// GetAllCandidates gets all of the standard library candidate packages to import in
|
||||
// sorted order on import path.
|
||||
func GetAllCandidates(filename string, opt *Options) (pkgs []ImportFix, err error) {
|
||||
_, opt, err = initialize(filename, nil, opt)
|
||||
// GetAllCandidates gets all of the packages starting with prefix that can be
|
||||
// imported by filename, sorted by import path.
|
||||
func GetAllCandidates(ctx context.Context, callback func(ImportFix), searchPrefix, filename, filePkg string, opt *Options) error {
|
||||
_, opt, err := initialize(filename, []byte{}, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
return getAllCandidates(filename, opt.Env)
|
||||
return getAllCandidates(ctx, callback, searchPrefix, filename, filePkg, opt.Env)
|
||||
}
|
||||
|
||||
// GetPackageExports returns all known packages with name pkg and their exports.
|
||||
func GetPackageExports(pkg, filename string, opt *Options) (exports []PackageExport, err error) {
|
||||
_, opt, err = initialize(filename, nil, opt)
|
||||
func GetPackageExports(ctx context.Context, callback func(PackageExport), searchPkg, filename, filePkg string, opt *Options) error {
|
||||
_, opt, err := initialize(filename, []byte{}, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
return getPackageExports(pkg, filename, opt.Env)
|
||||
return getPackageExports(ctx, callback, searchPkg, filename, filePkg, opt.Env)
|
||||
}
|
||||
|
||||
// initialize sets the values for opt and src.
|
||||
|
|
@ -133,16 +147,18 @@ func initialize(filename string, src []byte, opt *Options) ([]byte, *Options, er
|
|||
// Set the env if the user has not provided it.
|
||||
if opt.Env == nil {
|
||||
opt.Env = &ProcessEnv{
|
||||
GOPATH: build.Default.GOPATH,
|
||||
GOROOT: build.Default.GOROOT,
|
||||
GOPATH: build.Default.GOPATH,
|
||||
GOROOT: build.Default.GOROOT,
|
||||
GOFLAGS: os.Getenv("GOFLAGS"),
|
||||
GO111MODULE: os.Getenv("GO111MODULE"),
|
||||
GOPROXY: os.Getenv("GOPROXY"),
|
||||
GOSUMDB: os.Getenv("GOSUMDB"),
|
||||
}
|
||||
}
|
||||
|
||||
// Set the logger if the user has not provided it.
|
||||
if opt.Env.Logf == nil {
|
||||
opt.Env.Logf = log.Printf
|
||||
// Set the gocmdRunner if the user has not provided it.
|
||||
if opt.Env.GocmdRunner == nil {
|
||||
opt.Env.GocmdRunner = &gocommand.Runner{}
|
||||
}
|
||||
|
||||
if src == nil {
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
|
|
|
|||
370
vendor/golang.org/x/tools/internal/imports/mod.go
generated
vendored
370
vendor/golang.org/x/tools/internal/imports/mod.go
generated
vendored
|
|
@ -13,11 +13,10 @@ import (
|
|||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/mod/module"
|
||||
"golang.org/x/tools/internal/gocommand"
|
||||
"golang.org/x/tools/internal/gopathwalk"
|
||||
"golang.org/x/tools/internal/module"
|
||||
"golang.org/x/tools/internal/semver"
|
||||
)
|
||||
|
||||
// ModuleResolver implements resolver for modules using the go command as little
|
||||
|
|
@ -25,32 +24,42 @@ import (
|
|||
type ModuleResolver struct {
|
||||
env *ProcessEnv
|
||||
moduleCacheDir string
|
||||
dummyVendorMod *ModuleJSON // If vendoring is enabled, the pseudo-module that represents the /vendor directory.
|
||||
dummyVendorMod *gocommand.ModuleJSON // If vendoring is enabled, the pseudo-module that represents the /vendor directory.
|
||||
roots []gopathwalk.Root
|
||||
scanSema chan struct{} // scanSema prevents concurrent scans and guards scannedRoots.
|
||||
scannedRoots map[gopathwalk.Root]bool
|
||||
|
||||
Initialized bool
|
||||
Main *ModuleJSON
|
||||
ModsByModPath []*ModuleJSON // All modules, ordered by # of path components in module Path...
|
||||
ModsByDir []*ModuleJSON // ...or Dir.
|
||||
initialized bool
|
||||
main *gocommand.ModuleJSON
|
||||
modsByModPath []*gocommand.ModuleJSON // All modules, ordered by # of path components in module Path...
|
||||
modsByDir []*gocommand.ModuleJSON // ...or Dir.
|
||||
|
||||
// moduleCacheCache stores information about the module cache.
|
||||
moduleCacheCache *dirInfoCache
|
||||
otherCache *dirInfoCache
|
||||
}
|
||||
|
||||
type ModuleJSON struct {
|
||||
Path string // module path
|
||||
Replace *ModuleJSON // replaced by this module
|
||||
Main bool // is this the main module?
|
||||
Dir string // directory holding files for this module, if any
|
||||
GoMod string // path to go.mod file for this module, if any
|
||||
GoVersion string // go version used in module
|
||||
func newModuleResolver(e *ProcessEnv) *ModuleResolver {
|
||||
r := &ModuleResolver{
|
||||
env: e,
|
||||
scanSema: make(chan struct{}, 1),
|
||||
}
|
||||
r.scanSema <- struct{}{}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *ModuleResolver) init() error {
|
||||
if r.Initialized {
|
||||
if r.initialized {
|
||||
return nil
|
||||
}
|
||||
mainMod, vendorEnabled, err := vendorEnabled(r.env)
|
||||
|
||||
inv := gocommand.Invocation{
|
||||
BuildFlags: r.env.BuildFlags,
|
||||
Env: r.env.env(),
|
||||
Logf: r.env.Logf,
|
||||
WorkingDir: r.env.WorkingDir,
|
||||
}
|
||||
mainMod, vendorEnabled, err := gocommand.VendorEnabled(context.TODO(), inv, r.env.GocmdRunner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -58,13 +67,13 @@ func (r *ModuleResolver) init() error {
|
|||
if mainMod != nil && vendorEnabled {
|
||||
// Vendor mode is on, so all the non-Main modules are irrelevant,
|
||||
// and we need to search /vendor for everything.
|
||||
r.Main = mainMod
|
||||
r.dummyVendorMod = &ModuleJSON{
|
||||
r.main = mainMod
|
||||
r.dummyVendorMod = &gocommand.ModuleJSON{
|
||||
Path: "",
|
||||
Dir: filepath.Join(mainMod.Dir, "vendor"),
|
||||
}
|
||||
r.ModsByModPath = []*ModuleJSON{mainMod, r.dummyVendorMod}
|
||||
r.ModsByDir = []*ModuleJSON{mainMod, r.dummyVendorMod}
|
||||
r.modsByModPath = []*gocommand.ModuleJSON{mainMod, r.dummyVendorMod}
|
||||
r.modsByDir = []*gocommand.ModuleJSON{mainMod, r.dummyVendorMod}
|
||||
} else {
|
||||
// Vendor mode is off, so run go list -m ... to find everything.
|
||||
r.initAllMods()
|
||||
|
|
@ -72,79 +81,123 @@ func (r *ModuleResolver) init() error {
|
|||
|
||||
r.moduleCacheDir = filepath.Join(filepath.SplitList(r.env.GOPATH)[0], "/pkg/mod")
|
||||
|
||||
sort.Slice(r.ModsByModPath, func(i, j int) bool {
|
||||
sort.Slice(r.modsByModPath, func(i, j int) bool {
|
||||
count := func(x int) int {
|
||||
return strings.Count(r.ModsByModPath[x].Path, "/")
|
||||
return strings.Count(r.modsByModPath[x].Path, "/")
|
||||
}
|
||||
return count(j) < count(i) // descending order
|
||||
})
|
||||
sort.Slice(r.ModsByDir, func(i, j int) bool {
|
||||
sort.Slice(r.modsByDir, func(i, j int) bool {
|
||||
count := func(x int) int {
|
||||
return strings.Count(r.ModsByDir[x].Dir, "/")
|
||||
return strings.Count(r.modsByDir[x].Dir, "/")
|
||||
}
|
||||
return count(j) < count(i) // descending order
|
||||
})
|
||||
|
||||
r.roots = []gopathwalk.Root{
|
||||
{filepath.Join(r.env.GOROOT, "/src"), gopathwalk.RootGOROOT},
|
||||
}
|
||||
if r.main != nil {
|
||||
r.roots = append(r.roots, gopathwalk.Root{r.main.Dir, gopathwalk.RootCurrentModule})
|
||||
}
|
||||
if vendorEnabled {
|
||||
r.roots = append(r.roots, gopathwalk.Root{r.dummyVendorMod.Dir, gopathwalk.RootOther})
|
||||
} else {
|
||||
addDep := func(mod *gocommand.ModuleJSON) {
|
||||
if mod.Replace == nil {
|
||||
// This is redundant with the cache, but we'll skip it cheaply enough.
|
||||
r.roots = append(r.roots, gopathwalk.Root{mod.Dir, gopathwalk.RootModuleCache})
|
||||
} else {
|
||||
r.roots = append(r.roots, gopathwalk.Root{mod.Dir, gopathwalk.RootOther})
|
||||
}
|
||||
}
|
||||
// Walk dependent modules before scanning the full mod cache, direct deps first.
|
||||
for _, mod := range r.modsByModPath {
|
||||
if !mod.Indirect && !mod.Main {
|
||||
addDep(mod)
|
||||
}
|
||||
}
|
||||
for _, mod := range r.modsByModPath {
|
||||
if mod.Indirect && !mod.Main {
|
||||
addDep(mod)
|
||||
}
|
||||
}
|
||||
r.roots = append(r.roots, gopathwalk.Root{r.moduleCacheDir, gopathwalk.RootModuleCache})
|
||||
}
|
||||
|
||||
r.scannedRoots = map[gopathwalk.Root]bool{}
|
||||
if r.moduleCacheCache == nil {
|
||||
r.moduleCacheCache = &dirInfoCache{
|
||||
dirs: map[string]*directoryPackageInfo{},
|
||||
dirs: map[string]*directoryPackageInfo{},
|
||||
listeners: map[*int]cacheListener{},
|
||||
}
|
||||
}
|
||||
if r.otherCache == nil {
|
||||
r.otherCache = &dirInfoCache{
|
||||
dirs: map[string]*directoryPackageInfo{},
|
||||
dirs: map[string]*directoryPackageInfo{},
|
||||
listeners: map[*int]cacheListener{},
|
||||
}
|
||||
}
|
||||
r.Initialized = true
|
||||
r.initialized = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ModuleResolver) initAllMods() error {
|
||||
stdout, err := r.env.invokeGo("list", "-m", "-json", "...")
|
||||
stdout, err := r.env.invokeGo(context.TODO(), "list", "-m", "-json", "...")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for dec := json.NewDecoder(stdout); dec.More(); {
|
||||
mod := &ModuleJSON{}
|
||||
mod := &gocommand.ModuleJSON{}
|
||||
if err := dec.Decode(mod); err != nil {
|
||||
return err
|
||||
}
|
||||
if mod.Dir == "" {
|
||||
if r.env.Debug {
|
||||
if r.env.Logf != nil {
|
||||
r.env.Logf("module %v has not been downloaded and will be ignored", mod.Path)
|
||||
}
|
||||
// Can't do anything with a module that's not downloaded.
|
||||
continue
|
||||
}
|
||||
r.ModsByModPath = append(r.ModsByModPath, mod)
|
||||
r.ModsByDir = append(r.ModsByDir, mod)
|
||||
// golang/go#36193: the go command doesn't always clean paths.
|
||||
mod.Dir = filepath.Clean(mod.Dir)
|
||||
r.modsByModPath = append(r.modsByModPath, mod)
|
||||
r.modsByDir = append(r.modsByDir, mod)
|
||||
if mod.Main {
|
||||
r.Main = mod
|
||||
r.main = mod
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ModuleResolver) ClearForNewScan() {
|
||||
<-r.scanSema
|
||||
r.scannedRoots = map[gopathwalk.Root]bool{}
|
||||
r.otherCache = &dirInfoCache{
|
||||
dirs: map[string]*directoryPackageInfo{},
|
||||
dirs: map[string]*directoryPackageInfo{},
|
||||
listeners: map[*int]cacheListener{},
|
||||
}
|
||||
r.scanSema <- struct{}{}
|
||||
}
|
||||
|
||||
func (r *ModuleResolver) ClearForNewMod() {
|
||||
env := r.env
|
||||
<-r.scanSema
|
||||
*r = ModuleResolver{
|
||||
env: env,
|
||||
env: r.env,
|
||||
moduleCacheCache: r.moduleCacheCache,
|
||||
otherCache: r.otherCache,
|
||||
scanSema: r.scanSema,
|
||||
}
|
||||
r.init()
|
||||
r.scanSema <- struct{}{}
|
||||
}
|
||||
|
||||
// findPackage returns the module and directory that contains the package at
|
||||
// the given import path, or returns nil, "" if no module is in scope.
|
||||
func (r *ModuleResolver) findPackage(importPath string) (*ModuleJSON, string) {
|
||||
func (r *ModuleResolver) findPackage(importPath string) (*gocommand.ModuleJSON, string) {
|
||||
// This can't find packages in the stdlib, but that's harmless for all
|
||||
// the existing code paths.
|
||||
for _, m := range r.ModsByModPath {
|
||||
for _, m := range r.modsByModPath {
|
||||
if !strings.HasPrefix(importPath, m.Path) {
|
||||
continue
|
||||
}
|
||||
|
|
@ -211,7 +264,7 @@ func (r *ModuleResolver) cacheKeys() []string {
|
|||
}
|
||||
|
||||
// cachePackageName caches the package name for a dir already in the cache.
|
||||
func (r *ModuleResolver) cachePackageName(info directoryPackageInfo) (directoryPackageInfo, error) {
|
||||
func (r *ModuleResolver) cachePackageName(info directoryPackageInfo) (string, error) {
|
||||
if info.rootType == gopathwalk.RootModuleCache {
|
||||
return r.moduleCacheCache.CachePackageName(info)
|
||||
}
|
||||
|
|
@ -227,7 +280,7 @@ func (r *ModuleResolver) cacheExports(ctx context.Context, env *ProcessEnv, info
|
|||
|
||||
// findModuleByDir returns the module that contains dir, or nil if no such
|
||||
// module is in scope.
|
||||
func (r *ModuleResolver) findModuleByDir(dir string) *ModuleJSON {
|
||||
func (r *ModuleResolver) findModuleByDir(dir string) *gocommand.ModuleJSON {
|
||||
// This is quite tricky and may not be correct. dir could be:
|
||||
// - a package in the main module.
|
||||
// - a replace target underneath the main module's directory.
|
||||
|
|
@ -238,7 +291,7 @@ func (r *ModuleResolver) findModuleByDir(dir string) *ModuleJSON {
|
|||
// - in /vendor/ in -mod=vendor mode.
|
||||
// - nested module? Dunno.
|
||||
// Rumor has it that replace targets cannot contain other replace targets.
|
||||
for _, m := range r.ModsByDir {
|
||||
for _, m := range r.modsByDir {
|
||||
if !strings.HasPrefix(dir, m.Dir) {
|
||||
continue
|
||||
}
|
||||
|
|
@ -254,7 +307,7 @@ func (r *ModuleResolver) findModuleByDir(dir string) *ModuleJSON {
|
|||
|
||||
// dirIsNestedModule reports if dir is contained in a nested module underneath
|
||||
// mod, not actually in mod.
|
||||
func (r *ModuleResolver) dirIsNestedModule(dir string, mod *ModuleJSON) bool {
|
||||
func (r *ModuleResolver) dirIsNestedModule(dir string, mod *gocommand.ModuleJSON) bool {
|
||||
if !strings.HasPrefix(dir, mod.Dir) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -333,41 +386,49 @@ func (r *ModuleResolver) loadPackageNames(importPaths []string, srcDir string) (
|
|||
return names, nil
|
||||
}
|
||||
|
||||
func (r *ModuleResolver) scan(_ references, loadNames bool, exclude []gopathwalk.RootType) ([]*pkg, error) {
|
||||
func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error {
|
||||
if err := r.init(); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Walk GOROOT, GOPATH/pkg/mod, and the main module.
|
||||
roots := []gopathwalk.Root{
|
||||
{filepath.Join(r.env.GOROOT, "/src"), gopathwalk.RootGOROOT},
|
||||
}
|
||||
if r.Main != nil {
|
||||
roots = append(roots, gopathwalk.Root{r.Main.Dir, gopathwalk.RootCurrentModule})
|
||||
}
|
||||
if r.dummyVendorMod != nil {
|
||||
roots = append(roots, gopathwalk.Root{r.dummyVendorMod.Dir, gopathwalk.RootOther})
|
||||
} else {
|
||||
roots = append(roots, gopathwalk.Root{r.moduleCacheDir, gopathwalk.RootModuleCache})
|
||||
// Walk replace targets, just in case they're not in any of the above.
|
||||
for _, mod := range r.ModsByModPath {
|
||||
if mod.Replace != nil {
|
||||
roots = append(roots, gopathwalk.Root{mod.Dir, gopathwalk.RootOther})
|
||||
}
|
||||
processDir := func(info directoryPackageInfo) {
|
||||
// Skip this directory if we were not able to get the package information successfully.
|
||||
if scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {
|
||||
return
|
||||
}
|
||||
pkg, err := r.canonicalize(info)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !callback.dirFound(pkg) {
|
||||
return
|
||||
}
|
||||
pkg.packageName, err = r.cachePackageName(info)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !callback.packageNameLoaded(pkg) {
|
||||
return
|
||||
}
|
||||
_, exports, err := r.loadExports(ctx, pkg, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
callback.exportsLoaded(pkg, exports)
|
||||
}
|
||||
|
||||
roots = filterRoots(roots, exclude)
|
||||
// Start processing everything in the cache, and listen for the new stuff
|
||||
// we discover in the walk below.
|
||||
stop1 := r.moduleCacheCache.ScanAndListen(ctx, processDir)
|
||||
defer stop1()
|
||||
stop2 := r.otherCache.ScanAndListen(ctx, processDir)
|
||||
defer stop2()
|
||||
|
||||
var result []*pkg
|
||||
var mu sync.Mutex
|
||||
|
||||
// We assume cached directories have not changed. We can skip them and their
|
||||
// children.
|
||||
// We assume cached directories are fully cached, including all their
|
||||
// children, and have not changed. We can skip them.
|
||||
skip := func(root gopathwalk.Root, dir string) bool {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
info, ok := r.cacheLoad(dir)
|
||||
if !ok {
|
||||
return false
|
||||
|
|
@ -379,44 +440,64 @@ func (r *ModuleResolver) scan(_ references, loadNames bool, exclude []gopathwalk
|
|||
return packageScanned
|
||||
}
|
||||
|
||||
// Add anything new to the cache. We'll process everything in it below.
|
||||
// Add anything new to the cache, and process it if we're still listening.
|
||||
add := func(root gopathwalk.Root, dir string) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
r.cacheStore(r.scanDirForPackage(root, dir))
|
||||
}
|
||||
|
||||
gopathwalk.WalkSkip(roots, add, skip, gopathwalk.Options{Debug: r.env.Debug, ModulesEnabled: true})
|
||||
|
||||
// Everything we already had, and everything new, is now in the cache.
|
||||
for _, dir := range r.cacheKeys() {
|
||||
info, ok := r.cacheLoad(dir)
|
||||
if !ok {
|
||||
continue
|
||||
// r.roots and the callback are not necessarily safe to use in the
|
||||
// goroutine below. Process them eagerly.
|
||||
roots := filterRoots(r.roots, callback.rootFound)
|
||||
// We can't cancel walks, because we need them to finish to have a usable
|
||||
// cache. Instead, run them in a separate goroutine and detach.
|
||||
scanDone := make(chan struct{})
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-r.scanSema:
|
||||
}
|
||||
defer func() { r.scanSema <- struct{}{} }()
|
||||
// We have the lock on r.scannedRoots, and no other scans can run.
|
||||
for _, root := range roots {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Skip this directory if we were not able to get the package information successfully.
|
||||
if scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// If we want package names, make sure the cache has them.
|
||||
if loadNames {
|
||||
var err error
|
||||
if info, err = r.cachePackageName(info); err != nil {
|
||||
if r.scannedRoots[root] {
|
||||
continue
|
||||
}
|
||||
gopathwalk.WalkSkip([]gopathwalk.Root{root}, add, skip, gopathwalk.Options{Logf: r.env.Logf, ModulesEnabled: true})
|
||||
r.scannedRoots[root] = true
|
||||
}
|
||||
|
||||
res, err := r.canonicalize(info)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
result = append(result, res)
|
||||
close(scanDone)
|
||||
}()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-scanDone:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return result, nil
|
||||
func (r *ModuleResolver) scoreImportPath(ctx context.Context, path string) int {
|
||||
if _, ok := stdlib[path]; ok {
|
||||
return MaxRelevance
|
||||
}
|
||||
mod, _ := r.findPackage(path)
|
||||
return modRelevance(mod)
|
||||
}
|
||||
|
||||
func modRelevance(mod *gocommand.ModuleJSON) int {
|
||||
switch {
|
||||
case mod == nil: // out of scope
|
||||
return MaxRelevance - 4
|
||||
case mod.Indirect:
|
||||
return MaxRelevance - 3
|
||||
case !mod.Main:
|
||||
return MaxRelevance - 2
|
||||
default:
|
||||
return MaxRelevance - 1 // main module ties with stdlib
|
||||
}
|
||||
}
|
||||
|
||||
// canonicalize gets the result of canonicalizing the packages using the results
|
||||
|
|
@ -428,15 +509,14 @@ func (r *ModuleResolver) canonicalize(info directoryPackageInfo) (*pkg, error) {
|
|||
importPathShort: info.nonCanonicalImportPath,
|
||||
dir: info.dir,
|
||||
packageName: path.Base(info.nonCanonicalImportPath),
|
||||
relevance: 0,
|
||||
relevance: MaxRelevance,
|
||||
}, nil
|
||||
}
|
||||
|
||||
importPath := info.nonCanonicalImportPath
|
||||
relevance := 2
|
||||
mod := r.findModuleByDir(info.dir)
|
||||
// Check if the directory is underneath a module that's in scope.
|
||||
if mod := r.findModuleByDir(info.dir); mod != nil {
|
||||
relevance = 1
|
||||
if mod != nil {
|
||||
// It is. If dir is the target of a replace directive,
|
||||
// our guessed import path is wrong. Use the real one.
|
||||
if mod.Dir == info.dir {
|
||||
|
|
@ -445,15 +525,16 @@ func (r *ModuleResolver) canonicalize(info directoryPackageInfo) (*pkg, error) {
|
|||
dirInMod := info.dir[len(mod.Dir)+len("/"):]
|
||||
importPath = path.Join(mod.Path, filepath.ToSlash(dirInMod))
|
||||
}
|
||||
} else if info.needsReplace {
|
||||
} else if !strings.HasPrefix(importPath, info.moduleName) {
|
||||
// The module's name doesn't match the package's import path. It
|
||||
// probably needs a replace directive we don't have.
|
||||
return nil, fmt.Errorf("package in %q is not valid without a replace statement", info.dir)
|
||||
}
|
||||
|
||||
res := &pkg{
|
||||
importPathShort: importPath,
|
||||
dir: info.dir,
|
||||
packageName: info.packageName, // may not be populated if the caller didn't ask for it
|
||||
relevance: relevance,
|
||||
relevance: modRelevance(mod),
|
||||
}
|
||||
// We may have discovered a package that has a different version
|
||||
// in scope already. Canonicalize to that one if possible.
|
||||
|
|
@ -463,14 +544,14 @@ func (r *ModuleResolver) canonicalize(info directoryPackageInfo) (*pkg, error) {
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (r *ModuleResolver) loadExports(ctx context.Context, pkg *pkg) (string, []string, error) {
|
||||
func (r *ModuleResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) {
|
||||
if err := r.init(); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
if info, ok := r.cacheLoad(pkg.dir); ok {
|
||||
if info, ok := r.cacheLoad(pkg.dir); ok && !includeTest {
|
||||
return r.cacheExports(ctx, r.env, info)
|
||||
}
|
||||
return loadExportsFromFiles(ctx, r.env, pkg.dir)
|
||||
return loadExportsFromFiles(ctx, r.env, pkg.dir, includeTest)
|
||||
}
|
||||
|
||||
func (r *ModuleResolver) scanDirForPackage(root gopathwalk.Root, dir string) directoryPackageInfo {
|
||||
|
|
@ -488,7 +569,7 @@ func (r *ModuleResolver) scanDirForPackage(root gopathwalk.Root, dir string) dir
|
|||
}
|
||||
switch root.Type {
|
||||
case gopathwalk.RootCurrentModule:
|
||||
importPath = path.Join(r.Main.Path, filepath.ToSlash(subdir))
|
||||
importPath = path.Join(r.main.Path, filepath.ToSlash(subdir))
|
||||
case gopathwalk.RootModuleCache:
|
||||
matches := modCacheRegexp.FindStringSubmatch(subdir)
|
||||
if len(matches) == 0 {
|
||||
|
|
@ -497,9 +578,9 @@ func (r *ModuleResolver) scanDirForPackage(root gopathwalk.Root, dir string) dir
|
|||
err: fmt.Errorf("invalid module cache path: %v", subdir),
|
||||
}
|
||||
}
|
||||
modPath, err := module.DecodePath(filepath.ToSlash(matches[1]))
|
||||
modPath, err := module.UnescapePath(filepath.ToSlash(matches[1]))
|
||||
if err != nil {
|
||||
if r.env.Debug {
|
||||
if r.env.Logf != nil {
|
||||
r.env.Logf("decoding module cache path %q: %v", subdir, err)
|
||||
}
|
||||
return directoryPackageInfo{
|
||||
|
|
@ -516,7 +597,6 @@ func (r *ModuleResolver) scanDirForPackage(root gopathwalk.Root, dir string) dir
|
|||
dir: dir,
|
||||
rootType: root.Type,
|
||||
nonCanonicalImportPath: importPath,
|
||||
needsReplace: false,
|
||||
moduleDir: modDir,
|
||||
moduleName: modName,
|
||||
}
|
||||
|
|
@ -524,14 +604,6 @@ func (r *ModuleResolver) scanDirForPackage(root gopathwalk.Root, dir string) dir
|
|||
// stdlib packages are always in scope, despite the confusing go.mod
|
||||
return result
|
||||
}
|
||||
// Check that this package is not obviously impossible to import.
|
||||
if !strings.HasPrefix(importPath, modName) {
|
||||
// The module's declared path does not match
|
||||
// its expected path. It probably needs a
|
||||
// replace directive we don't have.
|
||||
result.needsReplace = true
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
@ -581,63 +653,3 @@ func modulePath(mod []byte) string {
|
|||
}
|
||||
return "" // missing module path
|
||||
}
|
||||
|
||||
var modFlagRegexp = regexp.MustCompile(`-mod[ =](\w+)`)
|
||||
|
||||
// vendorEnabled indicates if vendoring is enabled.
|
||||
// Inspired by setDefaultBuildMod in modload/init.go
|
||||
func vendorEnabled(env *ProcessEnv) (*ModuleJSON, bool, error) {
|
||||
mainMod, go114, err := getMainModuleAnd114(env)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
matches := modFlagRegexp.FindStringSubmatch(env.GOFLAGS)
|
||||
var modFlag string
|
||||
if len(matches) != 0 {
|
||||
modFlag = matches[1]
|
||||
}
|
||||
if modFlag != "" {
|
||||
// Don't override an explicit '-mod=' argument.
|
||||
return mainMod, modFlag == "vendor", nil
|
||||
}
|
||||
if mainMod == nil || !go114 {
|
||||
return mainMod, false, nil
|
||||
}
|
||||
// Check 1.14's automatic vendor mode.
|
||||
if fi, err := os.Stat(filepath.Join(mainMod.Dir, "vendor")); err == nil && fi.IsDir() {
|
||||
if mainMod.GoVersion != "" && semver.Compare("v"+mainMod.GoVersion, "v1.14") >= 0 {
|
||||
// The Go version is at least 1.14, and a vendor directory exists.
|
||||
// Set -mod=vendor by default.
|
||||
return mainMod, true, nil
|
||||
}
|
||||
}
|
||||
return mainMod, false, nil
|
||||
}
|
||||
|
||||
// getMainModuleAnd114 gets the main module's information and whether the
|
||||
// go command in use is 1.14+. This is the information needed to figure out
|
||||
// if vendoring should be enabled.
|
||||
func getMainModuleAnd114(env *ProcessEnv) (*ModuleJSON, bool, error) {
|
||||
const format = `{{.Path}}
|
||||
{{.Dir}}
|
||||
{{.GoMod}}
|
||||
{{.GoVersion}}
|
||||
{{range context.ReleaseTags}}{{if eq . "go1.14"}}{{.}}{{end}}{{end}}
|
||||
`
|
||||
stdout, err := env.invokeGo("list", "-m", "-f", format)
|
||||
if err != nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
lines := strings.Split(stdout.String(), "\n")
|
||||
if len(lines) < 5 {
|
||||
return nil, false, fmt.Errorf("unexpected stdout: %q", stdout)
|
||||
}
|
||||
mod := &ModuleJSON{
|
||||
Path: lines[0],
|
||||
Dir: lines[1],
|
||||
GoMod: lines[2],
|
||||
GoVersion: lines[3],
|
||||
Main: true,
|
||||
}
|
||||
return mod, lines[4] == "go1.14", nil
|
||||
}
|
||||
|
|
|
|||
95
vendor/golang.org/x/tools/internal/imports/mod_cache.go
generated
vendored
95
vendor/golang.org/x/tools/internal/imports/mod_cache.go
generated
vendored
|
|
@ -49,10 +49,6 @@ type directoryPackageInfo struct {
|
|||
// nonCanonicalImportPath is the package's expected import path. It may
|
||||
// not actually be importable at that path.
|
||||
nonCanonicalImportPath string
|
||||
// needsReplace is true if the nonCanonicalImportPath does not match the
|
||||
// module's declared path, making it impossible to import without a
|
||||
// replace directive.
|
||||
needsReplace bool
|
||||
|
||||
// Module-related information.
|
||||
moduleDir string // The directory that is the module root of this dir.
|
||||
|
|
@ -97,15 +93,86 @@ func (info *directoryPackageInfo) reachedStatus(target directoryPackageStatus) (
|
|||
type dirInfoCache struct {
|
||||
mu sync.Mutex
|
||||
// dirs stores information about packages in directories, keyed by absolute path.
|
||||
dirs map[string]*directoryPackageInfo
|
||||
dirs map[string]*directoryPackageInfo
|
||||
listeners map[*int]cacheListener
|
||||
}
|
||||
|
||||
type cacheListener func(directoryPackageInfo)
|
||||
|
||||
// ScanAndListen calls listener on all the items in the cache, and on anything
|
||||
// newly added. The returned stop function waits for all in-flight callbacks to
|
||||
// finish and blocks new ones.
|
||||
func (d *dirInfoCache) ScanAndListen(ctx context.Context, listener cacheListener) func() {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
// Flushing out all the callbacks is tricky without knowing how many there
|
||||
// are going to be. Setting an arbitrary limit makes it much easier.
|
||||
const maxInFlight = 10
|
||||
sema := make(chan struct{}, maxInFlight)
|
||||
for i := 0; i < maxInFlight; i++ {
|
||||
sema <- struct{}{}
|
||||
}
|
||||
|
||||
cookie := new(int) // A unique ID we can use for the listener.
|
||||
|
||||
// We can't hold mu while calling the listener.
|
||||
d.mu.Lock()
|
||||
var keys []string
|
||||
for key := range d.dirs {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
d.listeners[cookie] = func(info directoryPackageInfo) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-sema:
|
||||
}
|
||||
listener(info)
|
||||
sema <- struct{}{}
|
||||
}
|
||||
d.mu.Unlock()
|
||||
|
||||
stop := func() {
|
||||
cancel()
|
||||
d.mu.Lock()
|
||||
delete(d.listeners, cookie)
|
||||
d.mu.Unlock()
|
||||
for i := 0; i < maxInFlight; i++ {
|
||||
<-sema
|
||||
}
|
||||
}
|
||||
|
||||
// Process the pre-existing keys.
|
||||
for _, k := range keys {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return stop
|
||||
default:
|
||||
}
|
||||
if v, ok := d.Load(k); ok {
|
||||
listener(v)
|
||||
}
|
||||
}
|
||||
|
||||
return stop
|
||||
}
|
||||
|
||||
// Store stores the package info for dir.
|
||||
func (d *dirInfoCache) Store(dir string, info directoryPackageInfo) {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
stored := info // defensive copy
|
||||
d.dirs[dir] = &stored
|
||||
_, old := d.dirs[dir]
|
||||
d.dirs[dir] = &info
|
||||
var listeners []cacheListener
|
||||
for _, l := range d.listeners {
|
||||
listeners = append(listeners, l)
|
||||
}
|
||||
d.mu.Unlock()
|
||||
|
||||
if !old {
|
||||
for _, l := range listeners {
|
||||
l(info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load returns a copy of the directoryPackageInfo for absolute directory dir.
|
||||
|
|
@ -129,17 +196,17 @@ func (d *dirInfoCache) Keys() (keys []string) {
|
|||
return keys
|
||||
}
|
||||
|
||||
func (d *dirInfoCache) CachePackageName(info directoryPackageInfo) (directoryPackageInfo, error) {
|
||||
func (d *dirInfoCache) CachePackageName(info directoryPackageInfo) (string, error) {
|
||||
if loaded, err := info.reachedStatus(nameLoaded); loaded {
|
||||
return info, err
|
||||
return info.packageName, err
|
||||
}
|
||||
if scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {
|
||||
return info, fmt.Errorf("cannot read package name, scan error: %v", err)
|
||||
return "", fmt.Errorf("cannot read package name, scan error: %v", err)
|
||||
}
|
||||
info.packageName, info.err = packageDirToName(info.dir)
|
||||
info.status = nameLoaded
|
||||
d.Store(info.dir, info)
|
||||
return info, info.err
|
||||
return info.packageName, info.err
|
||||
}
|
||||
|
||||
func (d *dirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info directoryPackageInfo) (string, []string, error) {
|
||||
|
|
@ -149,8 +216,8 @@ func (d *dirInfoCache) CacheExports(ctx context.Context, env *ProcessEnv, info d
|
|||
if reached, err := info.reachedStatus(nameLoaded); reached && err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
info.packageName, info.exports, info.err = loadExportsFromFiles(ctx, env, info.dir)
|
||||
if info.err == context.Canceled {
|
||||
info.packageName, info.exports, info.err = loadExportsFromFiles(ctx, env, info.dir, false)
|
||||
if info.err == context.Canceled || info.err == context.DeadlineExceeded {
|
||||
return info.packageName, info.exports, info.err
|
||||
}
|
||||
// The cache structure wants things to proceed linearly. We can skip a
|
||||
|
|
|
|||
87
vendor/golang.org/x/tools/internal/imports/zstdlib.go
generated
vendored
87
vendor/golang.org/x/tools/internal/imports/zstdlib.go
generated
vendored
|
|
@ -415,6 +415,9 @@ var stdlib = map[string][]string{
|
|||
"crypto/tls": []string{
|
||||
"Certificate",
|
||||
"CertificateRequestInfo",
|
||||
"CipherSuite",
|
||||
"CipherSuiteName",
|
||||
"CipherSuites",
|
||||
"Client",
|
||||
"ClientAuthType",
|
||||
"ClientHelloInfo",
|
||||
|
|
@ -434,6 +437,7 @@ var stdlib = map[string][]string{
|
|||
"ECDSAWithP521AndSHA512",
|
||||
"ECDSAWithSHA1",
|
||||
"Ed25519",
|
||||
"InsecureCipherSuites",
|
||||
"Listen",
|
||||
"LoadX509KeyPair",
|
||||
"NewLRUClientSessionCache",
|
||||
|
|
@ -465,6 +469,7 @@ var stdlib = map[string][]string{
|
|||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
|
|
@ -473,6 +478,7 @@ var stdlib = map[string][]string{
|
|||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
||||
"TLS_FALLBACK_SCSV",
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
|
|
@ -698,36 +704,65 @@ var stdlib = map[string][]string{
|
|||
"Attr",
|
||||
"AttrAbstractOrigin",
|
||||
"AttrAccessibility",
|
||||
"AttrAddrBase",
|
||||
"AttrAddrClass",
|
||||
"AttrAlignment",
|
||||
"AttrAllocated",
|
||||
"AttrArtificial",
|
||||
"AttrAssociated",
|
||||
"AttrBaseTypes",
|
||||
"AttrBinaryScale",
|
||||
"AttrBitOffset",
|
||||
"AttrBitSize",
|
||||
"AttrByteSize",
|
||||
"AttrCallAllCalls",
|
||||
"AttrCallAllSourceCalls",
|
||||
"AttrCallAllTailCalls",
|
||||
"AttrCallColumn",
|
||||
"AttrCallDataLocation",
|
||||
"AttrCallDataValue",
|
||||
"AttrCallFile",
|
||||
"AttrCallLine",
|
||||
"AttrCallOrigin",
|
||||
"AttrCallPC",
|
||||
"AttrCallParameter",
|
||||
"AttrCallReturnPC",
|
||||
"AttrCallTailCall",
|
||||
"AttrCallTarget",
|
||||
"AttrCallTargetClobbered",
|
||||
"AttrCallValue",
|
||||
"AttrCalling",
|
||||
"AttrCommonRef",
|
||||
"AttrCompDir",
|
||||
"AttrConstExpr",
|
||||
"AttrConstValue",
|
||||
"AttrContainingType",
|
||||
"AttrCount",
|
||||
"AttrDataBitOffset",
|
||||
"AttrDataLocation",
|
||||
"AttrDataMemberLoc",
|
||||
"AttrDecimalScale",
|
||||
"AttrDecimalSign",
|
||||
"AttrDeclColumn",
|
||||
"AttrDeclFile",
|
||||
"AttrDeclLine",
|
||||
"AttrDeclaration",
|
||||
"AttrDefaultValue",
|
||||
"AttrDefaulted",
|
||||
"AttrDeleted",
|
||||
"AttrDescription",
|
||||
"AttrDigitCount",
|
||||
"AttrDiscr",
|
||||
"AttrDiscrList",
|
||||
"AttrDiscrValue",
|
||||
"AttrDwoName",
|
||||
"AttrElemental",
|
||||
"AttrEncoding",
|
||||
"AttrEndianity",
|
||||
"AttrEntrypc",
|
||||
"AttrEnumClass",
|
||||
"AttrExplicit",
|
||||
"AttrExportSymbols",
|
||||
"AttrExtension",
|
||||
"AttrExternal",
|
||||
"AttrFrameBase",
|
||||
|
|
@ -738,27 +773,47 @@ var stdlib = map[string][]string{
|
|||
"AttrInline",
|
||||
"AttrIsOptional",
|
||||
"AttrLanguage",
|
||||
"AttrLinkageName",
|
||||
"AttrLocation",
|
||||
"AttrLoclistsBase",
|
||||
"AttrLowerBound",
|
||||
"AttrLowpc",
|
||||
"AttrMacroInfo",
|
||||
"AttrMacros",
|
||||
"AttrMainSubprogram",
|
||||
"AttrMutable",
|
||||
"AttrName",
|
||||
"AttrNamelistItem",
|
||||
"AttrNoreturn",
|
||||
"AttrObjectPointer",
|
||||
"AttrOrdering",
|
||||
"AttrPictureString",
|
||||
"AttrPriority",
|
||||
"AttrProducer",
|
||||
"AttrPrototyped",
|
||||
"AttrPure",
|
||||
"AttrRanges",
|
||||
"AttrRank",
|
||||
"AttrRecursive",
|
||||
"AttrReference",
|
||||
"AttrReturnAddr",
|
||||
"AttrRnglistsBase",
|
||||
"AttrRvalueReference",
|
||||
"AttrSegment",
|
||||
"AttrSibling",
|
||||
"AttrSignature",
|
||||
"AttrSmall",
|
||||
"AttrSpecification",
|
||||
"AttrStartScope",
|
||||
"AttrStaticLink",
|
||||
"AttrStmtList",
|
||||
"AttrStrOffsetsBase",
|
||||
"AttrStride",
|
||||
"AttrStrideSize",
|
||||
"AttrStringLength",
|
||||
"AttrStringLengthBitSize",
|
||||
"AttrStringLengthByteSize",
|
||||
"AttrThreadsScaled",
|
||||
"AttrTrampoline",
|
||||
"AttrType",
|
||||
"AttrUpperBound",
|
||||
|
|
@ -772,18 +827,23 @@ var stdlib = map[string][]string{
|
|||
"BoolType",
|
||||
"CharType",
|
||||
"Class",
|
||||
"ClassAddrPtr",
|
||||
"ClassAddress",
|
||||
"ClassBlock",
|
||||
"ClassConstant",
|
||||
"ClassExprLoc",
|
||||
"ClassFlag",
|
||||
"ClassLinePtr",
|
||||
"ClassLocList",
|
||||
"ClassLocListPtr",
|
||||
"ClassMacPtr",
|
||||
"ClassRangeListPtr",
|
||||
"ClassReference",
|
||||
"ClassReferenceAlt",
|
||||
"ClassReferenceSig",
|
||||
"ClassRngList",
|
||||
"ClassRngListsPtr",
|
||||
"ClassStrOffsetsPtr",
|
||||
"ClassString",
|
||||
"ClassStringAlt",
|
||||
"ClassUnknown",
|
||||
|
|
@ -814,9 +874,13 @@ var stdlib = map[string][]string{
|
|||
"Tag",
|
||||
"TagAccessDeclaration",
|
||||
"TagArrayType",
|
||||
"TagAtomicType",
|
||||
"TagBaseType",
|
||||
"TagCallSite",
|
||||
"TagCallSiteParameter",
|
||||
"TagCatchDwarfBlock",
|
||||
"TagClassType",
|
||||
"TagCoarrayType",
|
||||
"TagCommonDwarfBlock",
|
||||
"TagCommonInclusion",
|
||||
"TagCompileUnit",
|
||||
|
|
@ -824,12 +888,15 @@ var stdlib = map[string][]string{
|
|||
"TagConstType",
|
||||
"TagConstant",
|
||||
"TagDwarfProcedure",
|
||||
"TagDynamicType",
|
||||
"TagEntryPoint",
|
||||
"TagEnumerationType",
|
||||
"TagEnumerator",
|
||||
"TagFileType",
|
||||
"TagFormalParameter",
|
||||
"TagFriend",
|
||||
"TagGenericSubrange",
|
||||
"TagImmutableType",
|
||||
"TagImportedDeclaration",
|
||||
"TagImportedModule",
|
||||
"TagImportedUnit",
|
||||
|
|
@ -853,6 +920,7 @@ var stdlib = map[string][]string{
|
|||
"TagRvalueReferenceType",
|
||||
"TagSetType",
|
||||
"TagSharedType",
|
||||
"TagSkeletonUnit",
|
||||
"TagStringType",
|
||||
"TagStructType",
|
||||
"TagSubprogram",
|
||||
|
|
@ -2359,6 +2427,7 @@ var stdlib = map[string][]string{
|
|||
"RawValue",
|
||||
"StructuralError",
|
||||
"SyntaxError",
|
||||
"TagBMPString",
|
||||
"TagBitString",
|
||||
"TagBoolean",
|
||||
"TagEnum",
|
||||
|
|
@ -2787,6 +2856,7 @@ var stdlib = map[string][]string{
|
|||
"IsPredeclared",
|
||||
"Mode",
|
||||
"New",
|
||||
"NewFromFiles",
|
||||
"Note",
|
||||
"Package",
|
||||
"PreserveAST",
|
||||
|
|
@ -3115,6 +3185,11 @@ var stdlib = map[string][]string{
|
|||
"New64",
|
||||
"New64a",
|
||||
},
|
||||
"hash/maphash": []string{
|
||||
"Hash",
|
||||
"MakeSeed",
|
||||
"Seed",
|
||||
},
|
||||
"html": []string{
|
||||
"EscapeString",
|
||||
"UnescapeString",
|
||||
|
|
@ -3367,6 +3442,7 @@ var stdlib = map[string][]string{
|
|||
"Ldate",
|
||||
"Llongfile",
|
||||
"Lmicroseconds",
|
||||
"Lmsgprefix",
|
||||
"Logger",
|
||||
"Lshortfile",
|
||||
"LstdFlags",
|
||||
|
|
@ -3443,6 +3519,7 @@ var stdlib = map[string][]string{
|
|||
"Exp",
|
||||
"Exp2",
|
||||
"Expm1",
|
||||
"FMA",
|
||||
"Float32bits",
|
||||
"Float32frombits",
|
||||
"Float64bits",
|
||||
|
|
@ -3567,6 +3644,9 @@ var stdlib = map[string][]string{
|
|||
"OnesCount32",
|
||||
"OnesCount64",
|
||||
"OnesCount8",
|
||||
"Rem",
|
||||
"Rem32",
|
||||
"Rem64",
|
||||
"Reverse",
|
||||
"Reverse16",
|
||||
"Reverse32",
|
||||
|
|
@ -5140,7 +5220,10 @@ var stdlib = map[string][]string{
|
|||
"CTL_NET",
|
||||
"CTL_QUERY",
|
||||
"CTRL_BREAK_EVENT",
|
||||
"CTRL_CLOSE_EVENT",
|
||||
"CTRL_C_EVENT",
|
||||
"CTRL_LOGOFF_EVENT",
|
||||
"CTRL_SHUTDOWN_EVENT",
|
||||
"CancelIo",
|
||||
"CancelIoEx",
|
||||
"CertAddCertificateContextToStore",
|
||||
|
|
@ -10112,6 +10195,7 @@ var stdlib = map[string][]string{
|
|||
"Duployan",
|
||||
"Egyptian_Hieroglyphs",
|
||||
"Elbasan",
|
||||
"Elymaic",
|
||||
"Ethiopic",
|
||||
"Extender",
|
||||
"FoldCategory",
|
||||
|
|
@ -10215,6 +10299,7 @@ var stdlib = map[string][]string{
|
|||
"Myanmar",
|
||||
"N",
|
||||
"Nabataean",
|
||||
"Nandinagari",
|
||||
"Nd",
|
||||
"New_Tai_Lue",
|
||||
"Newa",
|
||||
|
|
@ -10224,6 +10309,7 @@ var stdlib = map[string][]string{
|
|||
"Noncharacter_Code_Point",
|
||||
"Number",
|
||||
"Nushu",
|
||||
"Nyiakeng_Puachue_Hmong",
|
||||
"Ogham",
|
||||
"Ol_Chiki",
|
||||
"Old_Hungarian",
|
||||
|
|
@ -10331,6 +10417,7 @@ var stdlib = map[string][]string{
|
|||
"Vai",
|
||||
"Variation_Selector",
|
||||
"Version",
|
||||
"Wancho",
|
||||
"Warang_Citi",
|
||||
"White_Space",
|
||||
"Yi",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue