some deletions
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / mvdan.cc / gofumpt@v0.0.0-20200802201014-ab5a8192947d / gofumports / internal / imports / fix.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/mvdan.cc/gofumpt@v0.0.0-20200802201014-ab5a8192947d/gofumports/internal/imports/fix.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/mvdan.cc/gofumpt@v0.0.0-20200802201014-ab5a8192947d/gofumports/internal/imports/fix.go
deleted file mode 100644 (file)
index 9486349..0000000
+++ /dev/null
@@ -1,1623 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package imports
-
-import (
-       "bytes"
-       "context"
-       "encoding/json"
-       "fmt"
-       "go/ast"
-       "go/build"
-       "go/parser"
-       "go/token"
-       "io/ioutil"
-       "os"
-       "path"
-       "path/filepath"
-       "reflect"
-       "sort"
-       "strconv"
-       "strings"
-       "sync"
-       "unicode"
-       "unicode/utf8"
-
-       "golang.org/x/tools/go/ast/astutil"
-       "mvdan.cc/gofumpt/gofumports/internal/gocommand"
-       "mvdan.cc/gofumpt/gofumports/internal/gopathwalk"
-)
-
-// importToGroup is a list of functions which map from an import path to
-// a group number.
-var importToGroup = []func(env *ProcessEnv, importPath string) (num int, ok bool){
-       func(env *ProcessEnv, importPath string) (num int, ok bool) {
-               if env.LocalPrefix == "" {
-                       return
-               }
-               for _, p := range strings.Split(env.LocalPrefix, ",") {
-                       if strings.HasPrefix(importPath, p) || strings.TrimSuffix(p, "/") == importPath {
-                               return 3, true
-                       }
-               }
-               return
-       },
-       func(_ *ProcessEnv, importPath string) (num int, ok bool) {
-               if strings.HasPrefix(importPath, "appengine") {
-                       return 2, true
-               }
-               return
-       },
-       func(_ *ProcessEnv, importPath string) (num int, ok bool) {
-               firstComponent := strings.Split(importPath, "/")[0]
-               if strings.Contains(firstComponent, ".") {
-                       return 1, true
-               }
-               return
-       },
-}
-
-func importGroup(env *ProcessEnv, importPath string) int {
-       for _, fn := range importToGroup {
-               if n, ok := fn(env, importPath); ok {
-                       return n
-               }
-       }
-       return 0
-}
-
-type ImportFixType int
-
-const (
-       AddImport ImportFixType = iota
-       DeleteImport
-       SetImportName
-)
-
-type ImportFix struct {
-       // StmtInfo represents the import statement this fix will add, remove, or change.
-       StmtInfo ImportInfo
-       // 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
-       Relevance int // see pkg
-}
-
-// An ImportInfo represents a single import statement.
-type ImportInfo struct {
-       ImportPath string // import path, e.g. "crypto/rand".
-       Name       string // import name, e.g. "crand", or "" if none.
-}
-
-// A packageInfo represents what's known about a package.
-type packageInfo struct {
-       name    string          // real package name, if known.
-       exports map[string]bool // known exports.
-}
-
-// parseOtherFiles parses all the Go files in srcDir except filename, including
-// test files if filename looks like a test.
-func parseOtherFiles(fset *token.FileSet, srcDir, filename string) []*ast.File {
-       // This could use go/packages but it doesn't buy much, and it fails
-       // with https://golang.org/issue/26296 in LoadFiles mode in some cases.
-       considerTests := strings.HasSuffix(filename, "_test.go")
-
-       fileBase := filepath.Base(filename)
-       packageFileInfos, err := ioutil.ReadDir(srcDir)
-       if err != nil {
-               return nil
-       }
-
-       var files []*ast.File
-       for _, fi := range packageFileInfos {
-               if fi.Name() == fileBase || !strings.HasSuffix(fi.Name(), ".go") {
-                       continue
-               }
-               if !considerTests && strings.HasSuffix(fi.Name(), "_test.go") {
-                       continue
-               }
-
-               f, err := parser.ParseFile(fset, filepath.Join(srcDir, fi.Name()), nil, 0)
-               if err != nil {
-                       continue
-               }
-
-               files = append(files, f)
-       }
-
-       return files
-}
-
-// addGlobals puts the names of package vars into the provided map.
-func addGlobals(f *ast.File, globals map[string]bool) {
-       for _, decl := range f.Decls {
-               genDecl, ok := decl.(*ast.GenDecl)
-               if !ok {
-                       continue
-               }
-
-               for _, spec := range genDecl.Specs {
-                       valueSpec, ok := spec.(*ast.ValueSpec)
-                       if !ok {
-                               continue
-                       }
-                       globals[valueSpec.Names[0].Name] = true
-               }
-       }
-}
-
-// collectReferences builds a map of selector expressions, from
-// left hand side (X) to a set of right hand sides (Sel).
-func collectReferences(f *ast.File) references {
-       refs := references{}
-
-       var visitor visitFn
-       visitor = func(node ast.Node) ast.Visitor {
-               if node == nil {
-                       return visitor
-               }
-               switch v := node.(type) {
-               case *ast.SelectorExpr:
-                       xident, ok := v.X.(*ast.Ident)
-                       if !ok {
-                               break
-                       }
-                       if xident.Obj != nil {
-                               // If the parser can resolve it, it's not a package ref.
-                               break
-                       }
-                       if !ast.IsExported(v.Sel.Name) {
-                               // Whatever this is, it's not exported from a package.
-                               break
-                       }
-                       pkgName := xident.Name
-                       r := refs[pkgName]
-                       if r == nil {
-                               r = make(map[string]bool)
-                               refs[pkgName] = r
-                       }
-                       r[v.Sel.Name] = true
-               }
-               return visitor
-       }
-       ast.Walk(visitor, f)
-       return refs
-}
-
-// collectImports returns all the imports in f.
-// Unnamed imports (., _) and "C" are ignored.
-func collectImports(f *ast.File) []*ImportInfo {
-       var imports []*ImportInfo
-       for _, imp := range f.Imports {
-               var name string
-               if imp.Name != nil {
-                       name = imp.Name.Name
-               }
-               if imp.Path.Value == `"C"` || name == "_" || name == "." {
-                       continue
-               }
-               path := strings.Trim(imp.Path.Value, `"`)
-               imports = append(imports, &ImportInfo{
-                       Name:       name,
-                       ImportPath: path,
-               })
-       }
-       return imports
-}
-
-// findMissingImport searches pass's candidates for an import that provides
-// pkg, containing all of syms.
-func (p *pass) findMissingImport(pkg string, syms map[string]bool) *ImportInfo {
-       for _, candidate := range p.candidates {
-               pkgInfo, ok := p.knownPackages[candidate.ImportPath]
-               if !ok {
-                       continue
-               }
-               if p.importIdentifier(candidate) != pkg {
-                       continue
-               }
-
-               allFound := true
-               for right := range syms {
-                       if !pkgInfo.exports[right] {
-                               allFound = false
-                               break
-                       }
-               }
-
-               if allFound {
-                       return candidate
-               }
-       }
-       return nil
-}
-
-// references is set of references found in a Go file. The first map key is the
-// left hand side of a selector expression, the second key is the right hand
-// side, and the value should always be true.
-type references map[string]map[string]bool
-
-// A pass contains all the inputs and state necessary to fix a file's imports.
-// It can be modified in some ways during use; see comments below.
-type pass struct {
-       // Inputs. These must be set before a call to load, and not modified after.
-       fset                 *token.FileSet // fset used to parse f and its siblings.
-       f                    *ast.File      // the file being fixed.
-       srcDir               string         // the directory containing f.
-       env                  *ProcessEnv    // the environment to use for go commands, etc.
-       loadRealPackageNames bool           // if true, load package names from disk rather than guessing them.
-       otherFiles           []*ast.File    // sibling files.
-
-       // Intermediate state, generated by load.
-       existingImports map[string]*ImportInfo
-       allRefs         references
-       missingRefs     references
-
-       // Inputs to fix. These can be augmented between successive fix calls.
-       lastTry       bool                    // indicates that this is the last call and fix should clean up as best it can.
-       candidates    []*ImportInfo           // candidate imports in priority order.
-       knownPackages map[string]*packageInfo // information about all known packages.
-}
-
-// loadPackageNames saves the package names for everything referenced by imports.
-func (p *pass) loadPackageNames(imports []*ImportInfo) error {
-       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))
-               }()
-       }
-       var unknown []string
-       for _, imp := range imports {
-               if _, ok := p.knownPackages[imp.ImportPath]; ok {
-                       continue
-               }
-               unknown = append(unknown, imp.ImportPath)
-       }
-
-       names, err := p.env.GetResolver().loadPackageNames(unknown, p.srcDir)
-       if err != nil {
-               return err
-       }
-
-       for path, name := range names {
-               p.knownPackages[path] = &packageInfo{
-                       name:    name,
-                       exports: map[string]bool{},
-               }
-       }
-       return nil
-}
-
-// importIdentifier returns the identifier that imp will introduce. It will
-// guess if the package name has not been loaded, e.g. because the source
-// is not available.
-func (p *pass) importIdentifier(imp *ImportInfo) string {
-       if imp.Name != "" {
-               return imp.Name
-       }
-       known := p.knownPackages[imp.ImportPath]
-       if known != nil && known.name != "" {
-               return known.name
-       }
-       return ImportPathToAssumedName(imp.ImportPath)
-}
-
-// load reads in everything necessary to run a pass, and reports whether the
-// file already has all the imports it needs. It fills in p.missingRefs with the
-// file's missing symbols, if any, or removes unused imports if not.
-func (p *pass) load() ([]*ImportFix, bool) {
-       p.knownPackages = map[string]*packageInfo{}
-       p.missingRefs = references{}
-       p.existingImports = map[string]*ImportInfo{}
-
-       // Load basic information about the file in question.
-       p.allRefs = collectReferences(p.f)
-
-       // Load stuff from other files in the same package:
-       // global variables so we know they don't need resolving, and imports
-       // that we might want to mimic.
-       globals := map[string]bool{}
-       for _, otherFile := range p.otherFiles {
-               // Don't load globals from files that are in the same directory
-               // but a different package. Using them to suggest imports is OK.
-               if p.f.Name.Name == otherFile.Name.Name {
-                       addGlobals(otherFile, globals)
-               }
-               p.candidates = append(p.candidates, collectImports(otherFile)...)
-       }
-
-       // Resolve all the import paths we've seen to package names, and store
-       // f's imports by the identifier they introduce.
-       imports := collectImports(p.f)
-       if p.loadRealPackageNames {
-               err := p.loadPackageNames(append(imports, p.candidates...))
-               if err != nil {
-                       if p.env.Logf != nil {
-                               p.env.Logf("loading package names: %v", err)
-                       }
-                       return nil, false
-               }
-       }
-       for _, imp := range imports {
-               p.existingImports[p.importIdentifier(imp)] = imp
-       }
-
-       // Find missing references.
-       for left, rights := range p.allRefs {
-               if globals[left] {
-                       continue
-               }
-               _, ok := p.existingImports[left]
-               if !ok {
-                       p.missingRefs[left] = rights
-                       continue
-               }
-       }
-       if len(p.missingRefs) != 0 {
-               return nil, false
-       }
-
-       return p.fix()
-}
-
-// fix attempts to satisfy missing imports using p.candidates. If it finds
-// everything, or if p.lastTry is true, it updates fixes to add the imports it found,
-// delete anything unused, and update import names, and returns true.
-func (p *pass) fix() ([]*ImportFix, bool) {
-       // Find missing imports.
-       var selected []*ImportInfo
-       for left, rights := range p.missingRefs {
-               if imp := p.findMissingImport(left, rights); imp != nil {
-                       selected = append(selected, imp)
-               }
-       }
-
-       if !p.lastTry && len(selected) != len(p.missingRefs) {
-               return nil, false
-       }
-
-       // Found everything, or giving up. Add the new imports and remove any unused.
-       var fixes []*ImportFix
-       for _, imp := range p.existingImports {
-               // We deliberately ignore globals here, because we can't be sure
-               // they're in the same package. People do things like put multiple
-               // main packages in the same directory, and we don't want to
-               // remove imports if they happen to have the same name as a var in
-               // a different package.
-               if _, ok := p.allRefs[p.importIdentifier(imp)]; !ok {
-                       fixes = append(fixes, &ImportFix{
-                               StmtInfo:  *imp,
-                               IdentName: p.importIdentifier(imp),
-                               FixType:   DeleteImport,
-                       })
-                       continue
-               }
-
-               // An existing import may need to update its import name to be correct.
-               if name := p.importSpecName(imp); name != imp.Name {
-                       fixes = append(fixes, &ImportFix{
-                               StmtInfo: ImportInfo{
-                                       Name:       name,
-                                       ImportPath: imp.ImportPath,
-                               },
-                               IdentName: p.importIdentifier(imp),
-                               FixType:   SetImportName,
-                       })
-               }
-       }
-
-       for _, imp := range selected {
-               fixes = append(fixes, &ImportFix{
-                       StmtInfo: ImportInfo{
-                               Name:       p.importSpecName(imp),
-                               ImportPath: imp.ImportPath,
-                       },
-                       IdentName: p.importIdentifier(imp),
-                       FixType:   AddImport,
-               })
-       }
-
-       return fixes, true
-}
-
-// importSpecName gets the import name of imp in the import spec.
-//
-// When the import identifier matches the assumed import name, the import name does
-// not appear in the import spec.
-func (p *pass) importSpecName(imp *ImportInfo) string {
-       // If we did not load the real package names, or the name is already set,
-       // we just return the existing name.
-       if !p.loadRealPackageNames || imp.Name != "" {
-               return imp.Name
-       }
-
-       ident := p.importIdentifier(imp)
-       if ident == ImportPathToAssumedName(imp.ImportPath) {
-               return "" // ident not needed since the assumed and real names are the same.
-       }
-       return ident
-}
-
-// apply will perform the fixes on f in order.
-func apply(fset *token.FileSet, f *ast.File, fixes []*ImportFix) {
-       for _, fix := range fixes {
-               switch fix.FixType {
-               case DeleteImport:
-                       astutil.DeleteNamedImport(fset, f, fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
-               case AddImport:
-                       astutil.AddNamedImport(fset, f, fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
-               case SetImportName:
-                       // Find the matching import path and change the name.
-                       for _, spec := range f.Imports {
-                               path := strings.Trim(spec.Path.Value, `"`)
-                               if path == fix.StmtInfo.ImportPath {
-                                       spec.Name = &ast.Ident{
-                                               Name:    fix.StmtInfo.Name,
-                                               NamePos: spec.Pos(),
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-// assumeSiblingImportsValid assumes that siblings' use of packages is valid,
-// adding the exports they use.
-func (p *pass) assumeSiblingImportsValid() {
-       for _, f := range p.otherFiles {
-               refs := collectReferences(f)
-               imports := collectImports(f)
-               importsByName := map[string]*ImportInfo{}
-               for _, imp := range imports {
-                       importsByName[p.importIdentifier(imp)] = imp
-               }
-               for left, rights := range refs {
-                       if imp, ok := importsByName[left]; ok {
-                               if m, ok := stdlib[imp.ImportPath]; ok {
-                                       // We have the stdlib in memory; no need to guess.
-                                       rights = copyExports(m)
-                               }
-                               p.addCandidate(imp, &packageInfo{
-                                       // no name; we already know it.
-                                       exports: rights,
-                               })
-                       }
-               }
-       }
-}
-
-// addCandidate adds a candidate import to p, and merges in the information
-// in pkg.
-func (p *pass) addCandidate(imp *ImportInfo, pkg *packageInfo) {
-       p.candidates = append(p.candidates, imp)
-       if existing, ok := p.knownPackages[imp.ImportPath]; ok {
-               if existing.name == "" {
-                       existing.name = pkg.name
-               }
-               for export := range pkg.exports {
-                       existing.exports[export] = true
-               }
-       } else {
-               p.knownPackages[imp.ImportPath] = pkg
-       }
-}
-
-// fixImports adds and removes imports from f so that all its references are
-// satisfied and there are no unused imports.
-//
-// This is declared as a variable rather than a function so goimports can
-// easily be extended by adding a file with an init function.
-var fixImports = fixImportsDefault
-
-func fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) error {
-       fixes, err := getFixes(fset, f, filename, env)
-       if err != nil {
-               return err
-       }
-       apply(fset, f, fixes)
-       return err
-}
-
-// getFixes gets the import fixes that need to be made to f in order to fix the imports.
-// It does not modify the ast.
-func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) ([]*ImportFix, error) {
-       abs, err := filepath.Abs(filename)
-       if err != nil {
-               return nil, err
-       }
-       srcDir := filepath.Dir(abs)
-       if env.Logf != nil {
-               env.Logf("fixImports(filename=%q), abs=%q, srcDir=%q ...", filename, abs, srcDir)
-       }
-
-       // First pass: looking only at f, and using the naive algorithm to
-       // 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, env: env}
-       if fixes, done := p.load(); done {
-               return fixes, nil
-       }
-
-       otherFiles := parseOtherFiles(fset, srcDir, filename)
-
-       // Second pass: add information from other files in the same package,
-       // like their package vars and imports.
-       p.otherFiles = otherFiles
-       if fixes, done := p.load(); done {
-               return fixes, nil
-       }
-
-       // Now we can try adding imports from the stdlib.
-       p.assumeSiblingImportsValid()
-       addStdlibCandidates(p, p.missingRefs)
-       if fixes, done := p.fix(); done {
-               return fixes, nil
-       }
-
-       // Third pass: get real package names where we had previously used
-       // the naive algorithm.
-       p = &pass{fset: fset, f: f, srcDir: srcDir, env: env}
-       p.loadRealPackageNames = true
-       p.otherFiles = otherFiles
-       if fixes, done := p.load(); done {
-               return fixes, nil
-       }
-
-       addStdlibCandidates(p, p.missingRefs)
-       p.assumeSiblingImportsValid()
-       if fixes, done := p.fix(); done {
-               return fixes, nil
-       }
-
-       // Go look for candidates in $GOPATH, etc. We don't necessarily load
-       // the real exports of sibling imports, so keep assuming their contents.
-       if err := addExternalCandidates(p, p.missingRefs, filename); err != nil {
-               return nil, err
-       }
-
-       p.lastTry = true
-       fixes, _ := p.fix()
-       return fixes, nil
-}
-
-// Highest relevance, used for the standard library. Chosen arbitrarily to
-// match pre-existing gopls code.
-const MaxRelevance = 7
-
-// 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, exports := range stdlib {
-               p := &pkg{
-                       dir:             filepath.Join(env.goroot(), "src", importPath),
-                       importPathShort: importPath,
-                       packageName:     path.Base(importPath),
-                       relevance:       MaxRelevance,
-               }
-               if notSelf(p) && wrappedCallback.packageNameLoaded(p) {
-                       wrappedCallback.exportsLoaded(p, exports)
-               }
-       }
-
-       var mu sync.Mutex
-       dupCheck := map[string]struct{}{}
-
-       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)
-}
-
-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
-}
-
-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 {
-               return pkg.packageName
-       }
-       return ""
-}
-
-// getAllCandidates gets all of the candidates to be imported, regardless of if they are needed.
-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
-               },
-       }
-       return getCandidatePkgs(ctx, callback, filename, filePkg, env)
-}
-
-// A PackageExport is a package and its exports.
-type PackageExport struct {
-       Fix     *ImportFix
-       Exports []string
-}
-
-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,
-                       })
-               },
-       }
-       return getCandidatePkgs(ctx, callback, filename, filePkg, env)
-}
-
-var RequiredGoEnvVars = []string{"GO111MODULE", "GOFLAGS", "GOINSECURE", "GOMOD", "GOMODCACHE", "GONOPROXY", "GONOSUMDB", "GOPATH", "GOPROXY", "GOROOT", "GOSUMDB"}
-
-// ProcessEnv contains environment variables and settings that affect the use of
-// the go command, the go/build package, etc.
-type ProcessEnv struct {
-       LocalPrefix string
-
-       GocmdRunner *gocommand.Runner
-
-       BuildFlags []string
-
-       // Env overrides the OS environment, and can be used to specify
-       // GOPROXY, GO111MODULE, etc. PATH cannot be set here, because
-       // exec.Command will not honor it.
-       // Specifying all of RequiredGoEnvVars avoids a call to `go env`.
-       Env map[string]string
-
-       WorkingDir string
-
-       // If Logf is non-nil, debug logging is enabled through this function.
-       Logf func(format string, args ...interface{})
-
-       resolver Resolver
-}
-
-func (e *ProcessEnv) goroot() string {
-       return e.mustGetEnv("GOROOT")
-}
-
-func (e *ProcessEnv) gopath() string {
-       return e.mustGetEnv("GOPATH")
-}
-
-func (e *ProcessEnv) mustGetEnv(k string) string {
-       v, ok := e.Env[k]
-       if !ok {
-               panic(fmt.Sprintf("%v not set in evaluated environment", k))
-       }
-       return v
-}
-
-// CopyConfig copies the env's configuration into a new env.
-func (e *ProcessEnv) CopyConfig() *ProcessEnv {
-       copy := *e
-       copy.resolver = nil
-       return &copy
-}
-
-func (e *ProcessEnv) init() error {
-       foundAllRequired := true
-       for _, k := range RequiredGoEnvVars {
-               if _, ok := e.Env[k]; !ok {
-                       foundAllRequired = false
-                       break
-               }
-       }
-       if foundAllRequired {
-               return nil
-       }
-
-       if e.Env == nil {
-               e.Env = map[string]string{}
-       }
-
-       goEnv := map[string]string{}
-       stdout, err := e.invokeGo(context.TODO(), "env", append([]string{"-json"}, RequiredGoEnvVars...)...)
-       if err != nil {
-               return err
-       }
-       if err := json.Unmarshal(stdout.Bytes(), &goEnv); err != nil {
-               return err
-       }
-       for k, v := range goEnv {
-               e.Env[k] = v
-       }
-       return nil
-}
-
-func (e *ProcessEnv) env() []string {
-       var env []string // the gocommand package will prepend os.Environ.
-       for k, v := range e.Env {
-               env = append(env, k+"="+v)
-       }
-       return env
-}
-
-func (e *ProcessEnv) GetResolver() Resolver {
-       if e.resolver != nil {
-               return e.resolver
-       }
-       if len(e.Env["GOMOD"]) == 0 {
-               e.resolver = newGopathResolver(e)
-               return e.resolver
-       }
-       e.resolver = newModuleResolver(e)
-       return e.resolver
-}
-
-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 Dir field
-       // (see golang.org/issue/34860).
-       // Populate it only if present.
-       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(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,
-       }
-       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},
-                       &packageInfo{name: path.Base(pkg), exports: exports})
-       }
-       for left := range refs {
-               if left == "rand" {
-                       // Make sure we try crypto/rand before math/rand.
-                       add("crypto/rand")
-                       add("math/rand")
-                       continue
-               }
-               for importPath := range stdlib {
-                       if path.Base(importPath) == left {
-                               add(importPath)
-                       }
-               }
-       }
-}
-
-// A Resolver does the build-system-specific parts of goimports.
-type Resolver interface {
-       // loadPackageNames loads the package names in importPaths.
-       loadPackageNames(importPaths []string, srcDir string) (map[string]string, 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, includeTest bool) (string, []string, error)
-       // scoreImportPath returns the relevance for an import path.
-       scoreImportPath(ctx context.Context, path string) int
-
-       ClearForNewScan()
-}
-
-// 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 {
-       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
-       }
-
-       // Search for imports matching potential package references.
-       type result struct {
-               imp *ImportInfo
-               pkg *packageInfo
-       }
-       results := make(chan result, len(refs))
-
-       ctx, cancel := context.WithCancel(context.TODO())
-       var wg sync.WaitGroup
-       defer func() {
-               cancel()
-               wg.Wait()
-       }()
-       var (
-               firstErr     error
-               firstErrOnce sync.Once
-       )
-       for pkgName, symbols := range refs {
-               wg.Add(1)
-               go func(pkgName string, symbols map[string]bool) {
-                       defer wg.Done()
-
-                       found, err := findImport(ctx, pass, found[pkgName], pkgName, symbols, filename)
-                       if err != nil {
-                               firstErrOnce.Do(func() {
-                                       firstErr = err
-                                       cancel()
-                               })
-                               return
-                       }
-
-                       if found == nil {
-                               return // No matching package.
-                       }
-
-                       imp := &ImportInfo{
-                               ImportPath: found.importPathShort,
-                       }
-
-                       pkg := &packageInfo{
-                               name:    pkgName,
-                               exports: symbols,
-                       }
-                       results <- result{imp, pkg}
-               }(pkgName, symbols)
-       }
-       go func() {
-               wg.Wait()
-               close(results)
-       }()
-
-       for result := range results {
-               pass.addCandidate(result.imp, result.pkg)
-       }
-       return firstErr
-}
-
-// notIdentifier reports whether ch is an invalid identifier character.
-func notIdentifier(ch rune) bool {
-       return !('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' ||
-               '0' <= ch && ch <= '9' ||
-               ch == '_' ||
-               ch >= utf8.RuneSelf && (unicode.IsLetter(ch) || unicode.IsDigit(ch)))
-}
-
-// 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.
-// It is used to determine if a local rename should be added to an import for
-// 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 {
-       base := path.Base(importPath)
-       if strings.HasPrefix(base, "v") {
-               if _, err := strconv.Atoi(base[1:]); err == nil {
-                       dir := path.Dir(importPath)
-                       if dir != "." {
-                               base = path.Base(dir)
-                       }
-               }
-       }
-       base = strings.TrimPrefix(base, "go-")
-       if i := strings.IndexFunc(base, notIdentifier); i >= 0 {
-               base = base[:i]
-       }
-       return base
-}
-
-// gopathResolver implements resolver for GOPATH workspaces.
-type gopathResolver struct {
-       env      *ProcessEnv
-       walked   bool
-       cache    *dirInfoCache
-       scanSema chan struct{} // scanSema prevents concurrent scans.
-}
-
-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.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) {
-       names := map[string]string{}
-       for _, path := range importPaths {
-               names[path] = importPathToName(r.env, path, srcDir)
-       }
-       return names, nil
-}
-
-// importPathToName finds out the actual package name, as declared in its .go files.
-// If there's a problem, it returns "".
-func importPathToName(env *ProcessEnv, importPath, srcDir string) (packageName string) {
-       // Fast path for standard library without going to disk.
-       if _, ok := stdlib[importPath]; ok {
-               return path.Base(importPath) // stdlib packages always match their paths.
-       }
-
-       buildPkg, err := env.buildContext().Import(importPath, srcDir, build.FindOnly)
-       if err != nil {
-               return ""
-       }
-       pkgName, err := packageDirToName(buildPkg.Dir)
-       if err != nil {
-               return ""
-       }
-       return pkgName
-}
-
-// packageDirToName is a faster version of build.Import if
-// the only thing desired is the package name. Given a directory,
-// packageDirToName then only parses one file in the package,
-// trusting that the files in the directory are consistent.
-func packageDirToName(dir string) (packageName string, err error) {
-       d, err := os.Open(dir)
-       if err != nil {
-               return "", err
-       }
-       names, err := d.Readdirnames(-1)
-       d.Close()
-       if err != nil {
-               return "", err
-       }
-       sort.Strings(names) // to have predictable behavior
-       var lastErr error
-       var nfile int
-       for _, name := range names {
-               if !strings.HasSuffix(name, ".go") {
-                       continue
-               }
-               if strings.HasSuffix(name, "_test.go") {
-                       continue
-               }
-               nfile++
-               fullFile := filepath.Join(dir, name)
-
-               fset := token.NewFileSet()
-               f, err := parser.ParseFile(fset, fullFile, nil, parser.PackageClauseOnly)
-               if err != nil {
-                       lastErr = err
-                       continue
-               }
-               pkgName := f.Name.Name
-               if pkgName == "documentation" {
-                       // Special case from go/build.ImportDir, not
-                       // handled by ctx.MatchFile.
-                       continue
-               }
-               if pkgName == "main" {
-                       // Also skip package main, assuming it's a +build ignore generator or example.
-                       // Since you can't import a package main anyway, there's no harm here.
-                       continue
-               }
-               return pkgName, nil
-       }
-       if lastErr != nil {
-               return "", lastErr
-       }
-       return "", fmt.Errorf("no importable package found in %d Go files", nfile)
-}
-
-type pkg struct {
-       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
-       relevance       int    // a weakly-defined score of how relevant a package is. 0 is most relevant.
-}
-
-type pkgDistance struct {
-       pkg      *pkg
-       distance int // relative distance to target
-}
-
-// byDistanceOrImportPathShortLength sorts by relative distance breaking ties
-// on the short import path length and then the import string itself.
-type byDistanceOrImportPathShortLength []pkgDistance
-
-func (s byDistanceOrImportPathShortLength) Len() int { return len(s) }
-func (s byDistanceOrImportPathShortLength) Less(i, j int) bool {
-       di, dj := s[i].distance, s[j].distance
-       if di == -1 {
-               return false
-       }
-       if dj == -1 {
-               return true
-       }
-       if di != dj {
-               return di < dj
-       }
-
-       vi, vj := s[i].pkg.importPathShort, s[j].pkg.importPathShort
-       if len(vi) != len(vj) {
-               return len(vi) < len(vj)
-       }
-       return vi < vj
-}
-func (s byDistanceOrImportPathShortLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-
-func distance(basepath, targetpath string) int {
-       p, err := filepath.Rel(basepath, targetpath)
-       if err != nil {
-               return -1
-       }
-       if p == "." {
-               return 0
-       }
-       return strings.Count(p, string(filepath.Separator)) + 1
-}
-
-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.
-               if _, ok := r.cache.Load(dir); ok {
-                       return
-               }
-
-               importpath := filepath.ToSlash(dir[len(root.Path)+len("/"):])
-               info := directoryPackageInfo{
-                       status:                 directoryScanned,
-                       dir:                    dir,
-                       rootType:               root.Type,
-                       nonCanonicalImportPath: VendorlessPath(importpath),
-               }
-               r.cache.Store(dir, info)
-       }
-       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:             info.dir,
-                       relevance:       MaxRelevance - 1,
-               }
-               if info.rootType == gopathwalk.RootGOROOT {
-                       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)
-               }
-       }
-       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 (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
-       for _, root := range roots {
-               if !include(root) {
-                       continue
-               }
-               result = append(result, root)
-       }
-       return result
-}
-
-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, includeTest)
-}
-
-// VendorlessPath returns the devendorized version of the import path ipath.
-// For example, VendorlessPath("foo/bar/vendor/a/b") returns "a/b".
-func VendorlessPath(ipath string) string {
-       // Devendorize for use in import statement.
-       if i := strings.LastIndex(ipath, "/vendor/"); i >= 0 {
-               return ipath[i+len("/vendor/"):]
-       }
-       if strings.HasPrefix(ipath, "vendor/") {
-               return ipath[len("vendor/"):]
-       }
-       return ipath
-}
-
-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.
-       all, err := ioutil.ReadDir(dir)
-       if err != nil {
-               return "", nil, err
-       }
-       var files []os.FileInfo
-       for _, fi := range all {
-               name := fi.Name()
-               if !strings.HasSuffix(name, ".go") || (!includeTest && strings.HasSuffix(name, "_test.go")) {
-                       continue
-               }
-               match, err := env.buildContext().MatchFile(dir, fi.Name())
-               if err != nil || !match {
-                       continue
-               }
-               files = append(files, fi)
-       }
-
-       if len(files) == 0 {
-               return "", nil, fmt.Errorf("dir %v contains no buildable, non-test .go files", dir)
-       }
-
-       var pkgName string
-       fset := token.NewFileSet()
-       for _, fi := range files {
-               select {
-               case <-ctx.Done():
-                       return "", nil, ctx.Err()
-               default:
-               }
-
-               fullFile := filepath.Join(dir, fi.Name())
-               f, err := parser.ParseFile(fset, fullFile, nil, 0)
-               if err != nil {
-                       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) {
-                               exports = append(exports, name)
-                       }
-               }
-       }
-
-       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, ", "))
-       }
-       return pkgName, exports, nil
-}
-
-// 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, 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.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)
-       }
-       const maxConcurrentPackageImport = 4
-       loadExportsSem := make(chan struct{}, maxConcurrentPackageImport)
-
-       ctx, cancel := context.WithCancel(ctx)
-       var wg sync.WaitGroup
-       defer func() {
-               cancel()
-               wg.Wait()
-       }()
-
-       wg.Add(1)
-       go func() {
-               defer wg.Done()
-               for i, c := range candidates {
-                       select {
-                       case loadExportsSem <- struct{}{}:
-                       case <-ctx.Done():
-                               return
-                       }
-
-                       wg.Add(1)
-                       go func(c pkgDistance, resc chan<- *pkg) {
-                               defer func() {
-                                       <-loadExportsSem
-                                       wg.Done()
-                               }()
-
-                               if pass.env.Logf != nil {
-                                       pass.env.Logf("loading exports in dir %s (seeking package %s)", c.pkg.dir, pkgName)
-                               }
-                               // 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.Logf != nil {
-                                               pass.env.Logf("loading exports in dir %s (seeking package %s): %v", c.pkg.dir, pkgName, err)
-                                       }
-                                       resc <- nil
-                                       return
-                               }
-
-                               exportsMap := make(map[string]bool, len(exports))
-                               for _, sym := range exports {
-                                       exportsMap[sym] = true
-                               }
-
-                               // If it doesn't have the right
-                               // symbols, send nil to mean no match.
-                               for symbol := range symbols {
-                                       if !exportsMap[symbol] {
-                                               resc <- nil
-                                               return
-                                       }
-                               }
-                               resc <- c.pkg
-                       }(c, rescv[i])
-               }
-       }()
-
-       for _, resc := range rescv {
-               pkg := <-resc
-               if pkg == nil {
-                       continue
-               }
-               return pkg, nil
-       }
-       return nil, nil
-}
-
-// 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.
-//
-// This check is purely lexical and is meant to be as fast as possible
-// because it's run over all $GOPATH directories to filter out poor
-// candidates in order to limit the CPU and I/O later parsing the
-// exports in candidate packages.
-//
-// filename is the file being formatted.
-// pkgIdent is the package being searched for, like "client" (if
-// searching for "client.New")
-func pkgIsCandidate(filename string, refs references, pkg *pkg) bool {
-       // Check "internal" and "vendor" visibility:
-       if !canUse(filename, pkg.dir) {
-               return false
-       }
-
-       // Speed optimization to minimize disk I/O:
-       // the last two components on disk must contain the
-       // package name somewhere.
-       //
-       // This permits mismatch naming like directory
-       // "go-foo" being package "foo", or "pkg.v3" being "pkg",
-       // or directory "google.golang.org/api/cloudbilling/v1"
-       // being package "cloudbilling", but doesn't
-       // permit a directory "foo" to be package
-       // "bar", which is strongly discouraged
-       // anyway. There's no reason goimports needs
-       // to be slow just to accommodate that.
-       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
-}
-
-func hasHyphenOrUpperASCII(s string) bool {
-       for i := 0; i < len(s); i++ {
-               b := s[i]
-               if b == '-' || ('A' <= b && b <= 'Z') {
-                       return true
-               }
-       }
-       return false
-}
-
-func lowerASCIIAndRemoveHyphen(s string) (ret string) {
-       buf := make([]byte, 0, len(s))
-       for i := 0; i < len(s); i++ {
-               b := s[i]
-               switch {
-               case b == '-':
-                       continue
-               case 'A' <= b && b <= 'Z':
-                       buf = append(buf, b+('a'-'A'))
-               default:
-                       buf = append(buf, b)
-               }
-       }
-       return string(buf)
-}
-
-// canUse reports whether the package in dir is usable from filename,
-// respecting the Go "internal" and "vendor" visibility rules.
-func canUse(filename, dir string) bool {
-       // Fast path check, before any allocations. If it doesn't contain vendor
-       // or internal, it's not tricky:
-       // Note that this can false-negative on directories like "notinternal",
-       // but we check it correctly below. This is just a fast path.
-       if !strings.Contains(dir, "vendor") && !strings.Contains(dir, "internal") {
-               return true
-       }
-
-       dirSlash := filepath.ToSlash(dir)
-       if !strings.Contains(dirSlash, "/vendor/") && !strings.Contains(dirSlash, "/internal/") && !strings.HasSuffix(dirSlash, "/internal") {
-               return true
-       }
-       // Vendor or internal directory only visible from children of parent.
-       // That means the path from the current directory to the target directory
-       // can contain ../vendor or ../internal but not ../foo/vendor or ../foo/internal
-       // or bar/vendor or bar/internal.
-       // After stripping all the leading ../, the only okay place to see vendor or internal
-       // is at the very beginning of the path.
-       absfile, err := filepath.Abs(filename)
-       if err != nil {
-               return false
-       }
-       absdir, err := filepath.Abs(dir)
-       if err != nil {
-               return false
-       }
-       rel, err := filepath.Rel(absfile, absdir)
-       if err != nil {
-               return false
-       }
-       relSlash := filepath.ToSlash(rel)
-       if i := strings.LastIndex(relSlash, "../"); i >= 0 {
-               relSlash = relSlash[i+len("../"):]
-       }
-       return !strings.Contains(relSlash, "/vendor/") && !strings.Contains(relSlash, "/internal/") && !strings.HasSuffix(relSlash, "/internal")
-}
-
-// lastTwoComponents returns at most the last two path components
-// of v, using either / or \ as the path separator.
-func lastTwoComponents(v string) string {
-       nslash := 0
-       for i := len(v) - 1; i >= 0; i-- {
-               if v[i] == '/' || v[i] == '\\' {
-                       nslash++
-                       if nslash == 2 {
-                               return v[i:]
-                       }
-               }
-       }
-       return v
-}
-
-type visitFn func(node ast.Node) ast.Visitor
-
-func (fn visitFn) Visit(node ast.Node) ast.Visitor {
-       return fn(node)
-}
-
-func copyExports(pkg []string) map[string]bool {
-       m := make(map[string]bool, len(pkg))
-       for _, v := range pkg {
-               m[v] = true
-       }
-       return m
-}