fix.go 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  1. // Copyright 2013 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package imports
  5. import (
  6. "bytes"
  7. "context"
  8. "fmt"
  9. "go/ast"
  10. "go/build"
  11. "go/parser"
  12. "go/token"
  13. "io/ioutil"
  14. "log"
  15. "os"
  16. "os/exec"
  17. "path"
  18. "path/filepath"
  19. "sort"
  20. "strconv"
  21. "strings"
  22. "sync"
  23. "time"
  24. "unicode"
  25. "unicode/utf8"
  26. "golang.org/x/tools/go/ast/astutil"
  27. "golang.org/x/tools/go/packages"
  28. "golang.org/x/tools/internal/gopathwalk"
  29. )
  30. // Debug controls verbose logging.
  31. var Debug = false
  32. // LocalPrefix is a comma-separated string of import path prefixes, which, if
  33. // set, instructs Process to sort the import paths with the given prefixes
  34. // into another group after 3rd-party packages.
  35. var LocalPrefix string
  36. func localPrefixes() []string {
  37. if LocalPrefix != "" {
  38. return strings.Split(LocalPrefix, ",")
  39. }
  40. return nil
  41. }
  42. // importToGroup is a list of functions which map from an import path to
  43. // a group number.
  44. var importToGroup = []func(importPath string) (num int, ok bool){
  45. func(importPath string) (num int, ok bool) {
  46. for _, p := range localPrefixes() {
  47. if strings.HasPrefix(importPath, p) || strings.TrimSuffix(p, "/") == importPath {
  48. return 3, true
  49. }
  50. }
  51. return
  52. },
  53. func(importPath string) (num int, ok bool) {
  54. if strings.HasPrefix(importPath, "appengine") {
  55. return 2, true
  56. }
  57. return
  58. },
  59. func(importPath string) (num int, ok bool) {
  60. if strings.Contains(importPath, ".") {
  61. return 1, true
  62. }
  63. return
  64. },
  65. }
  66. func importGroup(importPath string) int {
  67. for _, fn := range importToGroup {
  68. if n, ok := fn(importPath); ok {
  69. return n
  70. }
  71. }
  72. return 0
  73. }
  74. // An importInfo represents a single import statement.
  75. type importInfo struct {
  76. importPath string // import path, e.g. "crypto/rand".
  77. name string // import name, e.g. "crand", or "" if none.
  78. }
  79. // A packageInfo represents what's known about a package.
  80. type packageInfo struct {
  81. name string // real package name, if known.
  82. exports map[string]bool // known exports.
  83. }
  84. // parseOtherFiles parses all the Go files in srcDir except filename, including
  85. // test files if filename looks like a test.
  86. func parseOtherFiles(fset *token.FileSet, srcDir, filename string) []*ast.File {
  87. // This could use go/packages but it doesn't buy much, and it fails
  88. // with https://golang.org/issue/26296 in LoadFiles mode in some cases.
  89. considerTests := strings.HasSuffix(filename, "_test.go")
  90. fileBase := filepath.Base(filename)
  91. packageFileInfos, err := ioutil.ReadDir(srcDir)
  92. if err != nil {
  93. return nil
  94. }
  95. var files []*ast.File
  96. for _, fi := range packageFileInfos {
  97. if fi.Name() == fileBase || !strings.HasSuffix(fi.Name(), ".go") {
  98. continue
  99. }
  100. if !considerTests && strings.HasSuffix(fi.Name(), "_test.go") {
  101. continue
  102. }
  103. f, err := parser.ParseFile(fset, filepath.Join(srcDir, fi.Name()), nil, 0)
  104. if err != nil {
  105. continue
  106. }
  107. files = append(files, f)
  108. }
  109. return files
  110. }
  111. // addGlobals puts the names of package vars into the provided map.
  112. func addGlobals(f *ast.File, globals map[string]bool) {
  113. for _, decl := range f.Decls {
  114. genDecl, ok := decl.(*ast.GenDecl)
  115. if !ok {
  116. continue
  117. }
  118. for _, spec := range genDecl.Specs {
  119. valueSpec, ok := spec.(*ast.ValueSpec)
  120. if !ok {
  121. continue
  122. }
  123. globals[valueSpec.Names[0].Name] = true
  124. }
  125. }
  126. }
  127. // collectReferences builds a map of selector expressions, from
  128. // left hand side (X) to a set of right hand sides (Sel).
  129. func collectReferences(f *ast.File) references {
  130. refs := references{}
  131. var visitor visitFn
  132. visitor = func(node ast.Node) ast.Visitor {
  133. if node == nil {
  134. return visitor
  135. }
  136. switch v := node.(type) {
  137. case *ast.SelectorExpr:
  138. xident, ok := v.X.(*ast.Ident)
  139. if !ok {
  140. break
  141. }
  142. if xident.Obj != nil {
  143. // If the parser can resolve it, it's not a package ref.
  144. break
  145. }
  146. if !ast.IsExported(v.Sel.Name) {
  147. // Whatever this is, it's not exported from a package.
  148. break
  149. }
  150. pkgName := xident.Name
  151. r := refs[pkgName]
  152. if r == nil {
  153. r = make(map[string]bool)
  154. refs[pkgName] = r
  155. }
  156. r[v.Sel.Name] = true
  157. }
  158. return visitor
  159. }
  160. ast.Walk(visitor, f)
  161. return refs
  162. }
  163. // collectImports returns all the imports in f, keyed by their package name as
  164. // determined by pathToName. Unnamed imports (., _) and "C" are ignored.
  165. func collectImports(f *ast.File) []*importInfo {
  166. var imports []*importInfo
  167. for _, imp := range f.Imports {
  168. var name string
  169. if imp.Name != nil {
  170. name = imp.Name.Name
  171. }
  172. if imp.Path.Value == `"C"` || name == "_" || name == "." {
  173. continue
  174. }
  175. path := strings.Trim(imp.Path.Value, `"`)
  176. imports = append(imports, &importInfo{
  177. name: name,
  178. importPath: path,
  179. })
  180. }
  181. return imports
  182. }
  183. // findMissingImport searches pass's candidates for an import that provides
  184. // pkg, containing all of syms.
  185. func (p *pass) findMissingImport(pkg string, syms map[string]bool) *importInfo {
  186. for _, candidate := range p.candidates {
  187. pkgInfo, ok := p.knownPackages[candidate.importPath]
  188. if !ok {
  189. continue
  190. }
  191. if p.importIdentifier(candidate) != pkg {
  192. continue
  193. }
  194. allFound := true
  195. for right := range syms {
  196. if !pkgInfo.exports[right] {
  197. allFound = false
  198. break
  199. }
  200. }
  201. if allFound {
  202. return candidate
  203. }
  204. }
  205. return nil
  206. }
  207. // references is set of references found in a Go file. The first map key is the
  208. // left hand side of a selector expression, the second key is the right hand
  209. // side, and the value should always be true.
  210. type references map[string]map[string]bool
  211. // A pass contains all the inputs and state necessary to fix a file's imports.
  212. // It can be modified in some ways during use; see comments below.
  213. type pass struct {
  214. // Inputs. These must be set before a call to load, and not modified after.
  215. fset *token.FileSet // fset used to parse f and its siblings.
  216. f *ast.File // the file being fixed.
  217. srcDir string // the directory containing f.
  218. fixEnv *fixEnv // the environment to use for go commands, etc.
  219. loadRealPackageNames bool // if true, load package names from disk rather than guessing them.
  220. otherFiles []*ast.File // sibling files.
  221. // Intermediate state, generated by load.
  222. existingImports map[string]*importInfo
  223. allRefs references
  224. missingRefs references
  225. // Inputs to fix. These can be augmented between successive fix calls.
  226. lastTry bool // indicates that this is the last call and fix should clean up as best it can.
  227. candidates []*importInfo // candidate imports in priority order.
  228. knownPackages map[string]*packageInfo // information about all known packages.
  229. }
  230. // loadPackageNames saves the package names for everything referenced by imports.
  231. func (p *pass) loadPackageNames(imports []*importInfo) error {
  232. var unknown []string
  233. for _, imp := range imports {
  234. if _, ok := p.knownPackages[imp.importPath]; ok {
  235. continue
  236. }
  237. unknown = append(unknown, imp.importPath)
  238. }
  239. names, err := p.fixEnv.getResolver().loadPackageNames(unknown, p.srcDir)
  240. if err != nil {
  241. return err
  242. }
  243. for path, name := range names {
  244. p.knownPackages[path] = &packageInfo{
  245. name: name,
  246. exports: map[string]bool{},
  247. }
  248. }
  249. return nil
  250. }
  251. // importIdentifier returns the identifier that imp will introduce. It will
  252. // guess if the package name has not been loaded, e.g. because the source
  253. // is not available.
  254. func (p *pass) importIdentifier(imp *importInfo) string {
  255. if imp.name != "" {
  256. return imp.name
  257. }
  258. known := p.knownPackages[imp.importPath]
  259. if known != nil && known.name != "" {
  260. return known.name
  261. }
  262. return importPathToAssumedName(imp.importPath)
  263. }
  264. // load reads in everything necessary to run a pass, and reports whether the
  265. // file already has all the imports it needs. It fills in p.missingRefs with the
  266. // file's missing symbols, if any, or removes unused imports if not.
  267. func (p *pass) load() bool {
  268. p.knownPackages = map[string]*packageInfo{}
  269. p.missingRefs = references{}
  270. p.existingImports = map[string]*importInfo{}
  271. // Load basic information about the file in question.
  272. p.allRefs = collectReferences(p.f)
  273. // Load stuff from other files in the same package:
  274. // global variables so we know they don't need resolving, and imports
  275. // that we might want to mimic.
  276. globals := map[string]bool{}
  277. for _, otherFile := range p.otherFiles {
  278. // Don't load globals from files that are in the same directory
  279. // but a different package. Using them to suggest imports is OK.
  280. if p.f.Name.Name == otherFile.Name.Name {
  281. addGlobals(otherFile, globals)
  282. }
  283. p.candidates = append(p.candidates, collectImports(otherFile)...)
  284. }
  285. // Resolve all the import paths we've seen to package names, and store
  286. // f's imports by the identifier they introduce.
  287. imports := collectImports(p.f)
  288. if p.loadRealPackageNames {
  289. err := p.loadPackageNames(append(imports, p.candidates...))
  290. if err != nil {
  291. if Debug {
  292. log.Printf("loading package names: %v", err)
  293. }
  294. return false
  295. }
  296. }
  297. for _, imp := range imports {
  298. p.existingImports[p.importIdentifier(imp)] = imp
  299. }
  300. // Find missing references.
  301. for left, rights := range p.allRefs {
  302. if globals[left] {
  303. continue
  304. }
  305. _, ok := p.existingImports[left]
  306. if !ok {
  307. p.missingRefs[left] = rights
  308. continue
  309. }
  310. }
  311. if len(p.missingRefs) != 0 {
  312. return false
  313. }
  314. return p.fix()
  315. }
  316. // fix attempts to satisfy missing imports using p.candidates. If it finds
  317. // everything, or if p.lastTry is true, it adds the imports it found,
  318. // removes anything unused, and returns true.
  319. func (p *pass) fix() bool {
  320. // Find missing imports.
  321. var selected []*importInfo
  322. for left, rights := range p.missingRefs {
  323. if imp := p.findMissingImport(left, rights); imp != nil {
  324. selected = append(selected, imp)
  325. }
  326. }
  327. if !p.lastTry && len(selected) != len(p.missingRefs) {
  328. return false
  329. }
  330. // Found everything, or giving up. Add the new imports and remove any unused.
  331. for _, imp := range p.existingImports {
  332. // We deliberately ignore globals here, because we can't be sure
  333. // they're in the same package. People do things like put multiple
  334. // main packages in the same directory, and we don't want to
  335. // remove imports if they happen to have the same name as a var in
  336. // a different package.
  337. if _, ok := p.allRefs[p.importIdentifier(imp)]; !ok {
  338. astutil.DeleteNamedImport(p.fset, p.f, imp.name, imp.importPath)
  339. }
  340. }
  341. for _, imp := range selected {
  342. astutil.AddNamedImport(p.fset, p.f, imp.name, imp.importPath)
  343. }
  344. if p.loadRealPackageNames {
  345. for _, imp := range p.f.Imports {
  346. if imp.Name != nil {
  347. continue
  348. }
  349. path := strings.Trim(imp.Path.Value, `""`)
  350. ident := p.importIdentifier(&importInfo{importPath: path})
  351. if ident != importPathToAssumedName(path) {
  352. imp.Name = &ast.Ident{Name: ident, NamePos: imp.Pos()}
  353. }
  354. }
  355. }
  356. return true
  357. }
  358. // assumeSiblingImportsValid assumes that siblings' use of packages is valid,
  359. // adding the exports they use.
  360. func (p *pass) assumeSiblingImportsValid() {
  361. for _, f := range p.otherFiles {
  362. refs := collectReferences(f)
  363. imports := collectImports(f)
  364. importsByName := map[string]*importInfo{}
  365. for _, imp := range imports {
  366. importsByName[p.importIdentifier(imp)] = imp
  367. }
  368. for left, rights := range refs {
  369. if imp, ok := importsByName[left]; ok {
  370. if _, ok := stdlib[imp.importPath]; ok {
  371. // We have the stdlib in memory; no need to guess.
  372. rights = stdlib[imp.importPath]
  373. }
  374. p.addCandidate(imp, &packageInfo{
  375. // no name; we already know it.
  376. exports: rights,
  377. })
  378. }
  379. }
  380. }
  381. }
  382. // addCandidate adds a candidate import to p, and merges in the information
  383. // in pkg.
  384. func (p *pass) addCandidate(imp *importInfo, pkg *packageInfo) {
  385. p.candidates = append(p.candidates, imp)
  386. if existing, ok := p.knownPackages[imp.importPath]; ok {
  387. if existing.name == "" {
  388. existing.name = pkg.name
  389. }
  390. for export := range pkg.exports {
  391. existing.exports[export] = true
  392. }
  393. } else {
  394. p.knownPackages[imp.importPath] = pkg
  395. }
  396. }
  397. // fixImports adds and removes imports from f so that all its references are
  398. // satisfied and there are no unused imports.
  399. //
  400. // This is declared as a variable rather than a function so goimports can
  401. // easily be extended by adding a file with an init function.
  402. var fixImports = fixImportsDefault
  403. func fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *fixEnv) error {
  404. abs, err := filepath.Abs(filename)
  405. if err != nil {
  406. return err
  407. }
  408. srcDir := filepath.Dir(abs)
  409. if Debug {
  410. log.Printf("fixImports(filename=%q), abs=%q, srcDir=%q ...", filename, abs, srcDir)
  411. }
  412. // First pass: looking only at f, and using the naive algorithm to
  413. // derive package names from import paths, see if the file is already
  414. // complete. We can't add any imports yet, because we don't know
  415. // if missing references are actually package vars.
  416. p := &pass{fset: fset, f: f, srcDir: srcDir}
  417. if p.load() {
  418. return nil
  419. }
  420. otherFiles := parseOtherFiles(fset, srcDir, filename)
  421. // Second pass: add information from other files in the same package,
  422. // like their package vars and imports.
  423. p.otherFiles = otherFiles
  424. if p.load() {
  425. return nil
  426. }
  427. // Now we can try adding imports from the stdlib.
  428. p.assumeSiblingImportsValid()
  429. addStdlibCandidates(p, p.missingRefs)
  430. if p.fix() {
  431. return nil
  432. }
  433. // Third pass: get real package names where we had previously used
  434. // the naive algorithm. This is the first step that will use the
  435. // environment, so we provide it here for the first time.
  436. p = &pass{fset: fset, f: f, srcDir: srcDir, fixEnv: env}
  437. p.loadRealPackageNames = true
  438. p.otherFiles = otherFiles
  439. if p.load() {
  440. return nil
  441. }
  442. addStdlibCandidates(p, p.missingRefs)
  443. p.assumeSiblingImportsValid()
  444. if p.fix() {
  445. return nil
  446. }
  447. // Go look for candidates in $GOPATH, etc. We don't necessarily load
  448. // the real exports of sibling imports, so keep assuming their contents.
  449. if err := addExternalCandidates(p, p.missingRefs, filename); err != nil {
  450. return err
  451. }
  452. p.lastTry = true
  453. p.fix()
  454. return nil
  455. }
  456. // fixEnv contains environment variables and settings that affect the use of
  457. // the go command, the go/build package, etc.
  458. type fixEnv struct {
  459. // If non-empty, these will be used instead of the
  460. // process-wide values.
  461. GOPATH, GOROOT, GO111MODULE, GOPROXY, GOFLAGS string
  462. WorkingDir string
  463. // If true, use go/packages regardless of the environment.
  464. ForceGoPackages bool
  465. resolver resolver
  466. }
  467. func (e *fixEnv) env() []string {
  468. env := os.Environ()
  469. add := func(k, v string) {
  470. if v != "" {
  471. env = append(env, k+"="+v)
  472. }
  473. }
  474. add("GOPATH", e.GOPATH)
  475. add("GOROOT", e.GOROOT)
  476. add("GO111MODULE", e.GO111MODULE)
  477. add("GOPROXY", e.GOPROXY)
  478. add("GOFLAGS", e.GOFLAGS)
  479. if e.WorkingDir != "" {
  480. add("PWD", e.WorkingDir)
  481. }
  482. return env
  483. }
  484. func (e *fixEnv) getResolver() resolver {
  485. if e.resolver != nil {
  486. return e.resolver
  487. }
  488. if e.ForceGoPackages {
  489. return &goPackagesResolver{env: e}
  490. }
  491. out, err := e.invokeGo("env", "GOMOD")
  492. if err != nil || len(bytes.TrimSpace(out.Bytes())) == 0 {
  493. return &gopathResolver{env: e}
  494. }
  495. return &moduleResolver{env: e}
  496. }
  497. func (e *fixEnv) newPackagesConfig(mode packages.LoadMode) *packages.Config {
  498. return &packages.Config{
  499. Mode: mode,
  500. Dir: e.WorkingDir,
  501. Env: e.env(),
  502. }
  503. }
  504. func (e *fixEnv) buildContext() *build.Context {
  505. ctx := build.Default
  506. ctx.GOROOT = e.GOROOT
  507. ctx.GOPATH = e.GOPATH
  508. return &ctx
  509. }
  510. func (e *fixEnv) invokeGo(args ...string) (*bytes.Buffer, error) {
  511. cmd := exec.Command("go", args...)
  512. stdout := &bytes.Buffer{}
  513. stderr := &bytes.Buffer{}
  514. cmd.Stdout = stdout
  515. cmd.Stderr = stderr
  516. cmd.Env = e.env()
  517. cmd.Dir = e.WorkingDir
  518. if Debug {
  519. defer func(start time.Time) { log.Printf("%s for %v", time.Since(start), cmdDebugStr(cmd)) }(time.Now())
  520. }
  521. if err := cmd.Run(); err != nil {
  522. return nil, fmt.Errorf("running go: %v (stderr:\n%s)", err, stderr)
  523. }
  524. return stdout, nil
  525. }
  526. func cmdDebugStr(cmd *exec.Cmd) string {
  527. env := make(map[string]string)
  528. for _, kv := range cmd.Env {
  529. split := strings.Split(kv, "=")
  530. k, v := split[0], split[1]
  531. env[k] = v
  532. }
  533. 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)
  534. }
  535. func addStdlibCandidates(pass *pass, refs references) {
  536. add := func(pkg string) {
  537. pass.addCandidate(
  538. &importInfo{importPath: pkg},
  539. &packageInfo{name: path.Base(pkg), exports: stdlib[pkg]})
  540. }
  541. for left := range refs {
  542. if left == "rand" {
  543. // Make sure we try crypto/rand before math/rand.
  544. add("crypto/rand")
  545. add("math/rand")
  546. continue
  547. }
  548. for importPath := range stdlib {
  549. if path.Base(importPath) == left {
  550. add(importPath)
  551. }
  552. }
  553. }
  554. }
  555. // A resolver does the build-system-specific parts of goimports.
  556. type resolver interface {
  557. // loadPackageNames loads the package names in importPaths.
  558. loadPackageNames(importPaths []string, srcDir string) (map[string]string, error)
  559. // scan finds (at least) the packages satisfying refs. The returned slice is unordered.
  560. scan(refs references) ([]*pkg, error)
  561. }
  562. // gopathResolver implements resolver for GOPATH and module workspaces using go/packages.
  563. type goPackagesResolver struct {
  564. env *fixEnv
  565. }
  566. func (r *goPackagesResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {
  567. cfg := r.env.newPackagesConfig(packages.LoadFiles)
  568. pkgs, err := packages.Load(cfg, importPaths...)
  569. if err != nil {
  570. return nil, err
  571. }
  572. names := map[string]string{}
  573. for _, pkg := range pkgs {
  574. names[VendorlessPath(pkg.PkgPath)] = pkg.Name
  575. }
  576. // We may not have found all the packages. Guess the rest.
  577. for _, path := range importPaths {
  578. if _, ok := names[path]; ok {
  579. continue
  580. }
  581. names[path] = importPathToAssumedName(path)
  582. }
  583. return names, nil
  584. }
  585. func (r *goPackagesResolver) scan(refs references) ([]*pkg, error) {
  586. var loadQueries []string
  587. for pkgName := range refs {
  588. loadQueries = append(loadQueries, "iamashamedtousethedisabledqueryname="+pkgName)
  589. }
  590. sort.Strings(loadQueries)
  591. cfg := r.env.newPackagesConfig(packages.LoadFiles)
  592. goPackages, err := packages.Load(cfg, loadQueries...)
  593. if err != nil {
  594. return nil, err
  595. }
  596. var scan []*pkg
  597. for _, goPackage := range goPackages {
  598. scan = append(scan, &pkg{
  599. dir: filepath.Dir(goPackage.CompiledGoFiles[0]),
  600. importPathShort: VendorlessPath(goPackage.PkgPath),
  601. goPackage: goPackage,
  602. })
  603. }
  604. return scan, nil
  605. }
  606. func addExternalCandidates(pass *pass, refs references, filename string) error {
  607. dirScan, err := pass.fixEnv.getResolver().scan(refs)
  608. if err != nil {
  609. return err
  610. }
  611. // Search for imports matching potential package references.
  612. type result struct {
  613. imp *importInfo
  614. pkg *packageInfo
  615. }
  616. results := make(chan result, len(refs))
  617. ctx, cancel := context.WithCancel(context.TODO())
  618. var wg sync.WaitGroup
  619. defer func() {
  620. cancel()
  621. wg.Wait()
  622. }()
  623. var (
  624. firstErr error
  625. firstErrOnce sync.Once
  626. )
  627. for pkgName, symbols := range refs {
  628. wg.Add(1)
  629. go func(pkgName string, symbols map[string]bool) {
  630. defer wg.Done()
  631. found, err := findImport(ctx, pass.fixEnv, dirScan, pkgName, symbols, filename)
  632. if err != nil {
  633. firstErrOnce.Do(func() {
  634. firstErr = err
  635. cancel()
  636. })
  637. return
  638. }
  639. if found == nil {
  640. return // No matching package.
  641. }
  642. imp := &importInfo{
  643. importPath: found.importPathShort,
  644. }
  645. pkg := &packageInfo{
  646. name: pkgName,
  647. exports: symbols,
  648. }
  649. results <- result{imp, pkg}
  650. }(pkgName, symbols)
  651. }
  652. go func() {
  653. wg.Wait()
  654. close(results)
  655. }()
  656. for result := range results {
  657. pass.addCandidate(result.imp, result.pkg)
  658. }
  659. return firstErr
  660. }
  661. // notIdentifier reports whether ch is an invalid identifier character.
  662. func notIdentifier(ch rune) bool {
  663. return !('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' ||
  664. '0' <= ch && ch <= '9' ||
  665. ch == '_' ||
  666. ch >= utf8.RuneSelf && (unicode.IsLetter(ch) || unicode.IsDigit(ch)))
  667. }
  668. // importPathToAssumedName returns the assumed package name of an import path.
  669. // It does this using only string parsing of the import path.
  670. // It picks the last element of the path that does not look like a major
  671. // version, and then picks the valid identifier off the start of that element.
  672. // It is used to determine if a local rename should be added to an import for
  673. // clarity.
  674. // This function could be moved to a standard package and exported if we want
  675. // for use in other tools.
  676. func importPathToAssumedName(importPath string) string {
  677. base := path.Base(importPath)
  678. if strings.HasPrefix(base, "v") {
  679. if _, err := strconv.Atoi(base[1:]); err == nil {
  680. dir := path.Dir(importPath)
  681. if dir != "." {
  682. base = path.Base(dir)
  683. }
  684. }
  685. }
  686. base = strings.TrimPrefix(base, "go-")
  687. if i := strings.IndexFunc(base, notIdentifier); i >= 0 {
  688. base = base[:i]
  689. }
  690. return base
  691. }
  692. // gopathResolver implements resolver for GOPATH workspaces.
  693. type gopathResolver struct {
  694. env *fixEnv
  695. }
  696. func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {
  697. names := map[string]string{}
  698. for _, path := range importPaths {
  699. names[path] = importPathToName(r.env, path, srcDir)
  700. }
  701. return names, nil
  702. }
  703. // importPathToNameGoPath finds out the actual package name, as declared in its .go files.
  704. // If there's a problem, it returns "".
  705. func importPathToName(env *fixEnv, importPath, srcDir string) (packageName string) {
  706. // Fast path for standard library without going to disk.
  707. if _, ok := stdlib[importPath]; ok {
  708. return path.Base(importPath) // stdlib packages always match their paths.
  709. }
  710. buildPkg, err := env.buildContext().Import(importPath, srcDir, build.FindOnly)
  711. if err != nil {
  712. return ""
  713. }
  714. pkgName, err := packageDirToName(buildPkg.Dir)
  715. if err != nil {
  716. return ""
  717. }
  718. return pkgName
  719. }
  720. // packageDirToName is a faster version of build.Import if
  721. // the only thing desired is the package name. It uses build.FindOnly
  722. // to find the directory and then only parses one file in the package,
  723. // trusting that the files in the directory are consistent.
  724. func packageDirToName(dir string) (packageName string, err error) {
  725. d, err := os.Open(dir)
  726. if err != nil {
  727. return "", err
  728. }
  729. names, err := d.Readdirnames(-1)
  730. d.Close()
  731. if err != nil {
  732. return "", err
  733. }
  734. sort.Strings(names) // to have predictable behavior
  735. var lastErr error
  736. var nfile int
  737. for _, name := range names {
  738. if !strings.HasSuffix(name, ".go") {
  739. continue
  740. }
  741. if strings.HasSuffix(name, "_test.go") {
  742. continue
  743. }
  744. nfile++
  745. fullFile := filepath.Join(dir, name)
  746. fset := token.NewFileSet()
  747. f, err := parser.ParseFile(fset, fullFile, nil, parser.PackageClauseOnly)
  748. if err != nil {
  749. lastErr = err
  750. continue
  751. }
  752. pkgName := f.Name.Name
  753. if pkgName == "documentation" {
  754. // Special case from go/build.ImportDir, not
  755. // handled by ctx.MatchFile.
  756. continue
  757. }
  758. if pkgName == "main" {
  759. // Also skip package main, assuming it's a +build ignore generator or example.
  760. // Since you can't import a package main anyway, there's no harm here.
  761. continue
  762. }
  763. return pkgName, nil
  764. }
  765. if lastErr != nil {
  766. return "", lastErr
  767. }
  768. return "", fmt.Errorf("no importable package found in %d Go files", nfile)
  769. }
  770. type pkg struct {
  771. goPackage *packages.Package
  772. dir string // absolute file path to pkg directory ("/usr/lib/go/src/net/http")
  773. importPathShort string // vendorless import path ("net/http", "a/b")
  774. }
  775. type pkgDistance struct {
  776. pkg *pkg
  777. distance int // relative distance to target
  778. }
  779. // byDistanceOrImportPathShortLength sorts by relative distance breaking ties
  780. // on the short import path length and then the import string itself.
  781. type byDistanceOrImportPathShortLength []pkgDistance
  782. func (s byDistanceOrImportPathShortLength) Len() int { return len(s) }
  783. func (s byDistanceOrImportPathShortLength) Less(i, j int) bool {
  784. di, dj := s[i].distance, s[j].distance
  785. if di == -1 {
  786. return false
  787. }
  788. if dj == -1 {
  789. return true
  790. }
  791. if di != dj {
  792. return di < dj
  793. }
  794. vi, vj := s[i].pkg.importPathShort, s[j].pkg.importPathShort
  795. if len(vi) != len(vj) {
  796. return len(vi) < len(vj)
  797. }
  798. return vi < vj
  799. }
  800. func (s byDistanceOrImportPathShortLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  801. func distance(basepath, targetpath string) int {
  802. p, err := filepath.Rel(basepath, targetpath)
  803. if err != nil {
  804. return -1
  805. }
  806. if p == "." {
  807. return 0
  808. }
  809. return strings.Count(p, string(filepath.Separator)) + 1
  810. }
  811. func (r *gopathResolver) scan(_ references) ([]*pkg, error) {
  812. dupCheck := make(map[string]bool)
  813. var result []*pkg
  814. var mu sync.Mutex
  815. add := func(root gopathwalk.Root, dir string) {
  816. mu.Lock()
  817. defer mu.Unlock()
  818. if _, dup := dupCheck[dir]; dup {
  819. return
  820. }
  821. dupCheck[dir] = true
  822. importpath := filepath.ToSlash(dir[len(root.Path)+len("/"):])
  823. result = append(result, &pkg{
  824. importPathShort: VendorlessPath(importpath),
  825. dir: dir,
  826. })
  827. }
  828. gopathwalk.Walk(gopathwalk.SrcDirsRoots(r.env.buildContext()), add, gopathwalk.Options{Debug: Debug, ModulesEnabled: false})
  829. return result, nil
  830. }
  831. // VendorlessPath returns the devendorized version of the import path ipath.
  832. // For example, VendorlessPath("foo/bar/vendor/a/b") returns "a/b".
  833. func VendorlessPath(ipath string) string {
  834. // Devendorize for use in import statement.
  835. if i := strings.LastIndex(ipath, "/vendor/"); i >= 0 {
  836. return ipath[i+len("/vendor/"):]
  837. }
  838. if strings.HasPrefix(ipath, "vendor/") {
  839. return ipath[len("vendor/"):]
  840. }
  841. return ipath
  842. }
  843. // loadExports returns the set of exported symbols in the package at dir.
  844. // It returns nil on error or if the package name in dir does not match expectPackage.
  845. func loadExports(ctx context.Context, env *fixEnv, expectPackage string, pkg *pkg) (map[string]bool, error) {
  846. if Debug {
  847. log.Printf("loading exports in dir %s (seeking package %s)", pkg.dir, expectPackage)
  848. }
  849. if pkg.goPackage != nil {
  850. exports := map[string]bool{}
  851. fset := token.NewFileSet()
  852. for _, fname := range pkg.goPackage.CompiledGoFiles {
  853. f, err := parser.ParseFile(fset, fname, nil, 0)
  854. if err != nil {
  855. return nil, fmt.Errorf("parsing %s: %v", fname, err)
  856. }
  857. for name := range f.Scope.Objects {
  858. if ast.IsExported(name) {
  859. exports[name] = true
  860. }
  861. }
  862. }
  863. return exports, nil
  864. }
  865. exports := make(map[string]bool)
  866. // Look for non-test, buildable .go files which could provide exports.
  867. all, err := ioutil.ReadDir(pkg.dir)
  868. if err != nil {
  869. return nil, err
  870. }
  871. var files []os.FileInfo
  872. for _, fi := range all {
  873. name := fi.Name()
  874. if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
  875. continue
  876. }
  877. match, err := env.buildContext().MatchFile(pkg.dir, fi.Name())
  878. if err != nil || !match {
  879. continue
  880. }
  881. files = append(files, fi)
  882. }
  883. if len(files) == 0 {
  884. return nil, fmt.Errorf("dir %v contains no buildable, non-test .go files", pkg.dir)
  885. }
  886. fset := token.NewFileSet()
  887. for _, fi := range files {
  888. select {
  889. case <-ctx.Done():
  890. return nil, ctx.Err()
  891. default:
  892. }
  893. fullFile := filepath.Join(pkg.dir, fi.Name())
  894. f, err := parser.ParseFile(fset, fullFile, nil, 0)
  895. if err != nil {
  896. return nil, fmt.Errorf("parsing %s: %v", fullFile, err)
  897. }
  898. pkgName := f.Name.Name
  899. if pkgName == "documentation" {
  900. // Special case from go/build.ImportDir, not
  901. // handled by MatchFile above.
  902. continue
  903. }
  904. if pkgName != expectPackage {
  905. return nil, fmt.Errorf("scan of dir %v is not expected package %v (actually %v)", pkg.dir, expectPackage, pkgName)
  906. }
  907. for name := range f.Scope.Objects {
  908. if ast.IsExported(name) {
  909. exports[name] = true
  910. }
  911. }
  912. }
  913. if Debug {
  914. exportList := make([]string, 0, len(exports))
  915. for k := range exports {
  916. exportList = append(exportList, k)
  917. }
  918. sort.Strings(exportList)
  919. log.Printf("loaded exports in dir %v (package %v): %v", pkg.dir, expectPackage, strings.Join(exportList, ", "))
  920. }
  921. return exports, nil
  922. }
  923. // findImport searches for a package with the given symbols.
  924. // If no package is found, findImport returns ("", false, nil)
  925. func findImport(ctx context.Context, env *fixEnv, dirScan []*pkg, pkgName string, symbols map[string]bool, filename string) (*pkg, error) {
  926. pkgDir, err := filepath.Abs(filename)
  927. if err != nil {
  928. return nil, err
  929. }
  930. pkgDir = filepath.Dir(pkgDir)
  931. // Find candidate packages, looking only at their directory names first.
  932. var candidates []pkgDistance
  933. for _, pkg := range dirScan {
  934. if pkgIsCandidate(filename, pkgName, pkg) {
  935. candidates = append(candidates, pkgDistance{
  936. pkg: pkg,
  937. distance: distance(pkgDir, pkg.dir),
  938. })
  939. }
  940. }
  941. // Sort the candidates by their import package length,
  942. // assuming that shorter package names are better than long
  943. // ones. Note that this sorts by the de-vendored name, so
  944. // there's no "penalty" for vendoring.
  945. sort.Sort(byDistanceOrImportPathShortLength(candidates))
  946. if Debug {
  947. for i, c := range candidates {
  948. log.Printf("%s candidate %d/%d: %v in %v", pkgName, i+1, len(candidates), c.pkg.importPathShort, c.pkg.dir)
  949. }
  950. }
  951. // Collect exports for packages with matching names.
  952. rescv := make([]chan *pkg, len(candidates))
  953. for i := range candidates {
  954. rescv[i] = make(chan *pkg, 1)
  955. }
  956. const maxConcurrentPackageImport = 4
  957. loadExportsSem := make(chan struct{}, maxConcurrentPackageImport)
  958. ctx, cancel := context.WithCancel(ctx)
  959. var wg sync.WaitGroup
  960. defer func() {
  961. cancel()
  962. wg.Wait()
  963. }()
  964. wg.Add(1)
  965. go func() {
  966. defer wg.Done()
  967. for i, c := range candidates {
  968. select {
  969. case loadExportsSem <- struct{}{}:
  970. case <-ctx.Done():
  971. return
  972. }
  973. wg.Add(1)
  974. go func(c pkgDistance, resc chan<- *pkg) {
  975. defer func() {
  976. <-loadExportsSem
  977. wg.Done()
  978. }()
  979. exports, err := loadExports(ctx, env, pkgName, c.pkg)
  980. if err != nil {
  981. if Debug {
  982. log.Printf("loading exports in dir %s (seeking package %s): %v", c.pkg.dir, pkgName, err)
  983. }
  984. resc <- nil
  985. return
  986. }
  987. // If it doesn't have the right
  988. // symbols, send nil to mean no match.
  989. for symbol := range symbols {
  990. if !exports[symbol] {
  991. resc <- nil
  992. return
  993. }
  994. }
  995. resc <- c.pkg
  996. }(c, rescv[i])
  997. }
  998. }()
  999. for _, resc := range rescv {
  1000. pkg := <-resc
  1001. if pkg == nil {
  1002. continue
  1003. }
  1004. return pkg, nil
  1005. }
  1006. return nil, nil
  1007. }
  1008. // pkgIsCandidate reports whether pkg is a candidate for satisfying the
  1009. // finding which package pkgIdent in the file named by filename is trying
  1010. // to refer to.
  1011. //
  1012. // This check is purely lexical and is meant to be as fast as possible
  1013. // because it's run over all $GOPATH directories to filter out poor
  1014. // candidates in order to limit the CPU and I/O later parsing the
  1015. // exports in candidate packages.
  1016. //
  1017. // filename is the file being formatted.
  1018. // pkgIdent is the package being searched for, like "client" (if
  1019. // searching for "client.New")
  1020. func pkgIsCandidate(filename, pkgIdent string, pkg *pkg) bool {
  1021. // Check "internal" and "vendor" visibility:
  1022. if !canUse(filename, pkg.dir) {
  1023. return false
  1024. }
  1025. // Speed optimization to minimize disk I/O:
  1026. // the last two components on disk must contain the
  1027. // package name somewhere.
  1028. //
  1029. // This permits mismatch naming like directory
  1030. // "go-foo" being package "foo", or "pkg.v3" being "pkg",
  1031. // or directory "google.golang.org/api/cloudbilling/v1"
  1032. // being package "cloudbilling", but doesn't
  1033. // permit a directory "foo" to be package
  1034. // "bar", which is strongly discouraged
  1035. // anyway. There's no reason goimports needs
  1036. // to be slow just to accommodate that.
  1037. lastTwo := lastTwoComponents(pkg.importPathShort)
  1038. if strings.Contains(lastTwo, pkgIdent) {
  1039. return true
  1040. }
  1041. if hasHyphenOrUpperASCII(lastTwo) && !hasHyphenOrUpperASCII(pkgIdent) {
  1042. lastTwo = lowerASCIIAndRemoveHyphen(lastTwo)
  1043. if strings.Contains(lastTwo, pkgIdent) {
  1044. return true
  1045. }
  1046. }
  1047. return false
  1048. }
  1049. func hasHyphenOrUpperASCII(s string) bool {
  1050. for i := 0; i < len(s); i++ {
  1051. b := s[i]
  1052. if b == '-' || ('A' <= b && b <= 'Z') {
  1053. return true
  1054. }
  1055. }
  1056. return false
  1057. }
  1058. func lowerASCIIAndRemoveHyphen(s string) (ret string) {
  1059. buf := make([]byte, 0, len(s))
  1060. for i := 0; i < len(s); i++ {
  1061. b := s[i]
  1062. switch {
  1063. case b == '-':
  1064. continue
  1065. case 'A' <= b && b <= 'Z':
  1066. buf = append(buf, b+('a'-'A'))
  1067. default:
  1068. buf = append(buf, b)
  1069. }
  1070. }
  1071. return string(buf)
  1072. }
  1073. // canUse reports whether the package in dir is usable from filename,
  1074. // respecting the Go "internal" and "vendor" visibility rules.
  1075. func canUse(filename, dir string) bool {
  1076. // Fast path check, before any allocations. If it doesn't contain vendor
  1077. // or internal, it's not tricky:
  1078. // Note that this can false-negative on directories like "notinternal",
  1079. // but we check it correctly below. This is just a fast path.
  1080. if !strings.Contains(dir, "vendor") && !strings.Contains(dir, "internal") {
  1081. return true
  1082. }
  1083. dirSlash := filepath.ToSlash(dir)
  1084. if !strings.Contains(dirSlash, "/vendor/") && !strings.Contains(dirSlash, "/internal/") && !strings.HasSuffix(dirSlash, "/internal") {
  1085. return true
  1086. }
  1087. // Vendor or internal directory only visible from children of parent.
  1088. // That means the path from the current directory to the target directory
  1089. // can contain ../vendor or ../internal but not ../foo/vendor or ../foo/internal
  1090. // or bar/vendor or bar/internal.
  1091. // After stripping all the leading ../, the only okay place to see vendor or internal
  1092. // is at the very beginning of the path.
  1093. absfile, err := filepath.Abs(filename)
  1094. if err != nil {
  1095. return false
  1096. }
  1097. absdir, err := filepath.Abs(dir)
  1098. if err != nil {
  1099. return false
  1100. }
  1101. rel, err := filepath.Rel(absfile, absdir)
  1102. if err != nil {
  1103. return false
  1104. }
  1105. relSlash := filepath.ToSlash(rel)
  1106. if i := strings.LastIndex(relSlash, "../"); i >= 0 {
  1107. relSlash = relSlash[i+len("../"):]
  1108. }
  1109. return !strings.Contains(relSlash, "/vendor/") && !strings.Contains(relSlash, "/internal/") && !strings.HasSuffix(relSlash, "/internal")
  1110. }
  1111. // lastTwoComponents returns at most the last two path components
  1112. // of v, using either / or \ as the path separator.
  1113. func lastTwoComponents(v string) string {
  1114. nslash := 0
  1115. for i := len(v) - 1; i >= 0; i-- {
  1116. if v[i] == '/' || v[i] == '\\' {
  1117. nslash++
  1118. if nslash == 2 {
  1119. return v[i:]
  1120. }
  1121. }
  1122. }
  1123. return v
  1124. }
  1125. type visitFn func(node ast.Node) ast.Visitor
  1126. func (fn visitFn) Visit(node ast.Node) ast.Visitor {
  1127. return fn(node)
  1128. }