You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

fix.go 44KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578
  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. "os"
  15. "path"
  16. "path/filepath"
  17. "reflect"
  18. "sort"
  19. "strconv"
  20. "strings"
  21. "sync"
  22. "unicode"
  23. "unicode/utf8"
  24. "golang.org/x/tools/go/ast/astutil"
  25. "golang.org/x/tools/internal/gocommand"
  26. "golang.org/x/tools/internal/gopathwalk"
  27. )
  28. // importToGroup is a list of functions which map from an import path to
  29. // a group number.
  30. var importToGroup = []func(env *ProcessEnv, importPath string) (num int, ok bool){
  31. func(env *ProcessEnv, importPath string) (num int, ok bool) {
  32. if env.LocalPrefix == "" {
  33. return
  34. }
  35. for _, p := range strings.Split(env.LocalPrefix, ",") {
  36. if strings.HasPrefix(importPath, p) || strings.TrimSuffix(p, "/") == importPath {
  37. return 3, true
  38. }
  39. }
  40. return
  41. },
  42. func(_ *ProcessEnv, importPath string) (num int, ok bool) {
  43. if strings.HasPrefix(importPath, "appengine") {
  44. return 2, true
  45. }
  46. return
  47. },
  48. func(_ *ProcessEnv, importPath string) (num int, ok bool) {
  49. if strings.Contains(importPath, ".") {
  50. return 1, true
  51. }
  52. return
  53. },
  54. }
  55. func importGroup(env *ProcessEnv, importPath string) int {
  56. for _, fn := range importToGroup {
  57. if n, ok := fn(env, importPath); ok {
  58. return n
  59. }
  60. }
  61. return 0
  62. }
  63. type ImportFixType int
  64. const (
  65. AddImport ImportFixType = iota
  66. DeleteImport
  67. SetImportName
  68. )
  69. type ImportFix struct {
  70. // StmtInfo represents the import statement this fix will add, remove, or change.
  71. StmtInfo ImportInfo
  72. // IdentName is the identifier that this fix will add or remove.
  73. IdentName string
  74. // FixType is the type of fix this is (AddImport, DeleteImport, SetImportName).
  75. FixType ImportFixType
  76. Relevance int // see pkg
  77. }
  78. // An ImportInfo represents a single import statement.
  79. type ImportInfo struct {
  80. ImportPath string // import path, e.g. "crypto/rand".
  81. Name string // import name, e.g. "crand", or "" if none.
  82. }
  83. // A packageInfo represents what's known about a package.
  84. type packageInfo struct {
  85. name string // real package name, if known.
  86. exports map[string]bool // known exports.
  87. }
  88. // parseOtherFiles parses all the Go files in srcDir except filename, including
  89. // test files if filename looks like a test.
  90. func parseOtherFiles(fset *token.FileSet, srcDir, filename string) []*ast.File {
  91. // This could use go/packages but it doesn't buy much, and it fails
  92. // with https://golang.org/issue/26296 in LoadFiles mode in some cases.
  93. considerTests := strings.HasSuffix(filename, "_test.go")
  94. fileBase := filepath.Base(filename)
  95. packageFileInfos, err := ioutil.ReadDir(srcDir)
  96. if err != nil {
  97. return nil
  98. }
  99. var files []*ast.File
  100. for _, fi := range packageFileInfos {
  101. if fi.Name() == fileBase || !strings.HasSuffix(fi.Name(), ".go") {
  102. continue
  103. }
  104. if !considerTests && strings.HasSuffix(fi.Name(), "_test.go") {
  105. continue
  106. }
  107. f, err := parser.ParseFile(fset, filepath.Join(srcDir, fi.Name()), nil, 0)
  108. if err != nil {
  109. continue
  110. }
  111. files = append(files, f)
  112. }
  113. return files
  114. }
  115. // addGlobals puts the names of package vars into the provided map.
  116. func addGlobals(f *ast.File, globals map[string]bool) {
  117. for _, decl := range f.Decls {
  118. genDecl, ok := decl.(*ast.GenDecl)
  119. if !ok {
  120. continue
  121. }
  122. for _, spec := range genDecl.Specs {
  123. valueSpec, ok := spec.(*ast.ValueSpec)
  124. if !ok {
  125. continue
  126. }
  127. globals[valueSpec.Names[0].Name] = true
  128. }
  129. }
  130. }
  131. // collectReferences builds a map of selector expressions, from
  132. // left hand side (X) to a set of right hand sides (Sel).
  133. func collectReferences(f *ast.File) references {
  134. refs := references{}
  135. var visitor visitFn
  136. visitor = func(node ast.Node) ast.Visitor {
  137. if node == nil {
  138. return visitor
  139. }
  140. switch v := node.(type) {
  141. case *ast.SelectorExpr:
  142. xident, ok := v.X.(*ast.Ident)
  143. if !ok {
  144. break
  145. }
  146. if xident.Obj != nil {
  147. // If the parser can resolve it, it's not a package ref.
  148. break
  149. }
  150. if !ast.IsExported(v.Sel.Name) {
  151. // Whatever this is, it's not exported from a package.
  152. break
  153. }
  154. pkgName := xident.Name
  155. r := refs[pkgName]
  156. if r == nil {
  157. r = make(map[string]bool)
  158. refs[pkgName] = r
  159. }
  160. r[v.Sel.Name] = true
  161. }
  162. return visitor
  163. }
  164. ast.Walk(visitor, f)
  165. return refs
  166. }
  167. // collectImports returns all the imports in f.
  168. // Unnamed imports (., _) and "C" are ignored.
  169. func collectImports(f *ast.File) []*ImportInfo {
  170. var imports []*ImportInfo
  171. for _, imp := range f.Imports {
  172. var name string
  173. if imp.Name != nil {
  174. name = imp.Name.Name
  175. }
  176. if imp.Path.Value == `"C"` || name == "_" || name == "." {
  177. continue
  178. }
  179. path := strings.Trim(imp.Path.Value, `"`)
  180. imports = append(imports, &ImportInfo{
  181. Name: name,
  182. ImportPath: path,
  183. })
  184. }
  185. return imports
  186. }
  187. // findMissingImport searches pass's candidates for an import that provides
  188. // pkg, containing all of syms.
  189. func (p *pass) findMissingImport(pkg string, syms map[string]bool) *ImportInfo {
  190. for _, candidate := range p.candidates {
  191. pkgInfo, ok := p.knownPackages[candidate.ImportPath]
  192. if !ok {
  193. continue
  194. }
  195. if p.importIdentifier(candidate) != pkg {
  196. continue
  197. }
  198. allFound := true
  199. for right := range syms {
  200. if !pkgInfo.exports[right] {
  201. allFound = false
  202. break
  203. }
  204. }
  205. if allFound {
  206. return candidate
  207. }
  208. }
  209. return nil
  210. }
  211. // references is set of references found in a Go file. The first map key is the
  212. // left hand side of a selector expression, the second key is the right hand
  213. // side, and the value should always be true.
  214. type references map[string]map[string]bool
  215. // A pass contains all the inputs and state necessary to fix a file's imports.
  216. // It can be modified in some ways during use; see comments below.
  217. type pass struct {
  218. // Inputs. These must be set before a call to load, and not modified after.
  219. fset *token.FileSet // fset used to parse f and its siblings.
  220. f *ast.File // the file being fixed.
  221. srcDir string // the directory containing f.
  222. env *ProcessEnv // the environment to use for go commands, etc.
  223. loadRealPackageNames bool // if true, load package names from disk rather than guessing them.
  224. otherFiles []*ast.File // sibling files.
  225. // Intermediate state, generated by load.
  226. existingImports map[string]*ImportInfo
  227. allRefs references
  228. missingRefs references
  229. // Inputs to fix. These can be augmented between successive fix calls.
  230. lastTry bool // indicates that this is the last call and fix should clean up as best it can.
  231. candidates []*ImportInfo // candidate imports in priority order.
  232. knownPackages map[string]*packageInfo // information about all known packages.
  233. }
  234. // loadPackageNames saves the package names for everything referenced by imports.
  235. func (p *pass) loadPackageNames(imports []*ImportInfo) error {
  236. if p.env.Logf != nil {
  237. p.env.Logf("loading package names for %v packages", len(imports))
  238. defer func() {
  239. p.env.Logf("done loading package names for %v packages", len(imports))
  240. }()
  241. }
  242. var unknown []string
  243. for _, imp := range imports {
  244. if _, ok := p.knownPackages[imp.ImportPath]; ok {
  245. continue
  246. }
  247. unknown = append(unknown, imp.ImportPath)
  248. }
  249. names, err := p.env.GetResolver().loadPackageNames(unknown, p.srcDir)
  250. if err != nil {
  251. return err
  252. }
  253. for path, name := range names {
  254. p.knownPackages[path] = &packageInfo{
  255. name: name,
  256. exports: map[string]bool{},
  257. }
  258. }
  259. return nil
  260. }
  261. // importIdentifier returns the identifier that imp will introduce. It will
  262. // guess if the package name has not been loaded, e.g. because the source
  263. // is not available.
  264. func (p *pass) importIdentifier(imp *ImportInfo) string {
  265. if imp.Name != "" {
  266. return imp.Name
  267. }
  268. known := p.knownPackages[imp.ImportPath]
  269. if known != nil && known.name != "" {
  270. return known.name
  271. }
  272. return ImportPathToAssumedName(imp.ImportPath)
  273. }
  274. // load reads in everything necessary to run a pass, and reports whether the
  275. // file already has all the imports it needs. It fills in p.missingRefs with the
  276. // file's missing symbols, if any, or removes unused imports if not.
  277. func (p *pass) load() ([]*ImportFix, bool) {
  278. p.knownPackages = map[string]*packageInfo{}
  279. p.missingRefs = references{}
  280. p.existingImports = map[string]*ImportInfo{}
  281. // Load basic information about the file in question.
  282. p.allRefs = collectReferences(p.f)
  283. // Load stuff from other files in the same package:
  284. // global variables so we know they don't need resolving, and imports
  285. // that we might want to mimic.
  286. globals := map[string]bool{}
  287. for _, otherFile := range p.otherFiles {
  288. // Don't load globals from files that are in the same directory
  289. // but a different package. Using them to suggest imports is OK.
  290. if p.f.Name.Name == otherFile.Name.Name {
  291. addGlobals(otherFile, globals)
  292. }
  293. p.candidates = append(p.candidates, collectImports(otherFile)...)
  294. }
  295. // Resolve all the import paths we've seen to package names, and store
  296. // f's imports by the identifier they introduce.
  297. imports := collectImports(p.f)
  298. if p.loadRealPackageNames {
  299. err := p.loadPackageNames(append(imports, p.candidates...))
  300. if err != nil {
  301. if p.env.Logf != nil {
  302. p.env.Logf("loading package names: %v", err)
  303. }
  304. return nil, false
  305. }
  306. }
  307. for _, imp := range imports {
  308. p.existingImports[p.importIdentifier(imp)] = imp
  309. }
  310. // Find missing references.
  311. for left, rights := range p.allRefs {
  312. if globals[left] {
  313. continue
  314. }
  315. _, ok := p.existingImports[left]
  316. if !ok {
  317. p.missingRefs[left] = rights
  318. continue
  319. }
  320. }
  321. if len(p.missingRefs) != 0 {
  322. return nil, false
  323. }
  324. return p.fix()
  325. }
  326. // fix attempts to satisfy missing imports using p.candidates. If it finds
  327. // everything, or if p.lastTry is true, it updates fixes to add the imports it found,
  328. // delete anything unused, and update import names, and returns true.
  329. func (p *pass) fix() ([]*ImportFix, bool) {
  330. // Find missing imports.
  331. var selected []*ImportInfo
  332. for left, rights := range p.missingRefs {
  333. if imp := p.findMissingImport(left, rights); imp != nil {
  334. selected = append(selected, imp)
  335. }
  336. }
  337. if !p.lastTry && len(selected) != len(p.missingRefs) {
  338. return nil, false
  339. }
  340. // Found everything, or giving up. Add the new imports and remove any unused.
  341. var fixes []*ImportFix
  342. for _, imp := range p.existingImports {
  343. // We deliberately ignore globals here, because we can't be sure
  344. // they're in the same package. People do things like put multiple
  345. // main packages in the same directory, and we don't want to
  346. // remove imports if they happen to have the same name as a var in
  347. // a different package.
  348. if _, ok := p.allRefs[p.importIdentifier(imp)]; !ok {
  349. fixes = append(fixes, &ImportFix{
  350. StmtInfo: *imp,
  351. IdentName: p.importIdentifier(imp),
  352. FixType: DeleteImport,
  353. })
  354. continue
  355. }
  356. // An existing import may need to update its import name to be correct.
  357. if name := p.importSpecName(imp); name != imp.Name {
  358. fixes = append(fixes, &ImportFix{
  359. StmtInfo: ImportInfo{
  360. Name: name,
  361. ImportPath: imp.ImportPath,
  362. },
  363. IdentName: p.importIdentifier(imp),
  364. FixType: SetImportName,
  365. })
  366. }
  367. }
  368. for _, imp := range selected {
  369. fixes = append(fixes, &ImportFix{
  370. StmtInfo: ImportInfo{
  371. Name: p.importSpecName(imp),
  372. ImportPath: imp.ImportPath,
  373. },
  374. IdentName: p.importIdentifier(imp),
  375. FixType: AddImport,
  376. })
  377. }
  378. return fixes, true
  379. }
  380. // importSpecName gets the import name of imp in the import spec.
  381. //
  382. // When the import identifier matches the assumed import name, the import name does
  383. // not appear in the import spec.
  384. func (p *pass) importSpecName(imp *ImportInfo) string {
  385. // If we did not load the real package names, or the name is already set,
  386. // we just return the existing name.
  387. if !p.loadRealPackageNames || imp.Name != "" {
  388. return imp.Name
  389. }
  390. ident := p.importIdentifier(imp)
  391. if ident == ImportPathToAssumedName(imp.ImportPath) {
  392. return "" // ident not needed since the assumed and real names are the same.
  393. }
  394. return ident
  395. }
  396. // apply will perform the fixes on f in order.
  397. func apply(fset *token.FileSet, f *ast.File, fixes []*ImportFix) {
  398. for _, fix := range fixes {
  399. switch fix.FixType {
  400. case DeleteImport:
  401. astutil.DeleteNamedImport(fset, f, fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
  402. case AddImport:
  403. astutil.AddNamedImport(fset, f, fix.StmtInfo.Name, fix.StmtInfo.ImportPath)
  404. case SetImportName:
  405. // Find the matching import path and change the name.
  406. for _, spec := range f.Imports {
  407. path := strings.Trim(spec.Path.Value, `"`)
  408. if path == fix.StmtInfo.ImportPath {
  409. spec.Name = &ast.Ident{
  410. Name: fix.StmtInfo.Name,
  411. NamePos: spec.Pos(),
  412. }
  413. }
  414. }
  415. }
  416. }
  417. }
  418. // assumeSiblingImportsValid assumes that siblings' use of packages is valid,
  419. // adding the exports they use.
  420. func (p *pass) assumeSiblingImportsValid() {
  421. for _, f := range p.otherFiles {
  422. refs := collectReferences(f)
  423. imports := collectImports(f)
  424. importsByName := map[string]*ImportInfo{}
  425. for _, imp := range imports {
  426. importsByName[p.importIdentifier(imp)] = imp
  427. }
  428. for left, rights := range refs {
  429. if imp, ok := importsByName[left]; ok {
  430. if m, ok := stdlib[imp.ImportPath]; ok {
  431. // We have the stdlib in memory; no need to guess.
  432. rights = copyExports(m)
  433. }
  434. p.addCandidate(imp, &packageInfo{
  435. // no name; we already know it.
  436. exports: rights,
  437. })
  438. }
  439. }
  440. }
  441. }
  442. // addCandidate adds a candidate import to p, and merges in the information
  443. // in pkg.
  444. func (p *pass) addCandidate(imp *ImportInfo, pkg *packageInfo) {
  445. p.candidates = append(p.candidates, imp)
  446. if existing, ok := p.knownPackages[imp.ImportPath]; ok {
  447. if existing.name == "" {
  448. existing.name = pkg.name
  449. }
  450. for export := range pkg.exports {
  451. existing.exports[export] = true
  452. }
  453. } else {
  454. p.knownPackages[imp.ImportPath] = pkg
  455. }
  456. }
  457. // fixImports adds and removes imports from f so that all its references are
  458. // satisfied and there are no unused imports.
  459. //
  460. // This is declared as a variable rather than a function so goimports can
  461. // easily be extended by adding a file with an init function.
  462. var fixImports = fixImportsDefault
  463. func fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) error {
  464. fixes, err := getFixes(fset, f, filename, env)
  465. if err != nil {
  466. return err
  467. }
  468. apply(fset, f, fixes)
  469. return err
  470. }
  471. // getFixes gets the import fixes that need to be made to f in order to fix the imports.
  472. // It does not modify the ast.
  473. func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) ([]*ImportFix, error) {
  474. abs, err := filepath.Abs(filename)
  475. if err != nil {
  476. return nil, err
  477. }
  478. srcDir := filepath.Dir(abs)
  479. if env.Logf != nil {
  480. env.Logf("fixImports(filename=%q), abs=%q, srcDir=%q ...", filename, abs, srcDir)
  481. }
  482. // First pass: looking only at f, and using the naive algorithm to
  483. // derive package names from import paths, see if the file is already
  484. // complete. We can't add any imports yet, because we don't know
  485. // if missing references are actually package vars.
  486. p := &pass{fset: fset, f: f, srcDir: srcDir, env: env}
  487. if fixes, done := p.load(); done {
  488. return fixes, nil
  489. }
  490. otherFiles := parseOtherFiles(fset, srcDir, filename)
  491. // Second pass: add information from other files in the same package,
  492. // like their package vars and imports.
  493. p.otherFiles = otherFiles
  494. if fixes, done := p.load(); done {
  495. return fixes, nil
  496. }
  497. // Now we can try adding imports from the stdlib.
  498. p.assumeSiblingImportsValid()
  499. addStdlibCandidates(p, p.missingRefs)
  500. if fixes, done := p.fix(); done {
  501. return fixes, nil
  502. }
  503. // Third pass: get real package names where we had previously used
  504. // the naive algorithm.
  505. p = &pass{fset: fset, f: f, srcDir: srcDir, env: env}
  506. p.loadRealPackageNames = true
  507. p.otherFiles = otherFiles
  508. if fixes, done := p.load(); done {
  509. return fixes, nil
  510. }
  511. addStdlibCandidates(p, p.missingRefs)
  512. p.assumeSiblingImportsValid()
  513. if fixes, done := p.fix(); done {
  514. return fixes, nil
  515. }
  516. // Go look for candidates in $GOPATH, etc. We don't necessarily load
  517. // the real exports of sibling imports, so keep assuming their contents.
  518. if err := addExternalCandidates(p, p.missingRefs, filename); err != nil {
  519. return nil, err
  520. }
  521. p.lastTry = true
  522. fixes, _ := p.fix()
  523. return fixes, nil
  524. }
  525. // Highest relevance, used for the standard library. Chosen arbitrarily to
  526. // match pre-existing gopls code.
  527. const MaxRelevance = 7
  528. // getCandidatePkgs works with the passed callback to find all acceptable packages.
  529. // It deduplicates by import path, and uses a cached stdlib rather than reading
  530. // from disk.
  531. func getCandidatePkgs(ctx context.Context, wrappedCallback *scanCallback, filename, filePkg string, env *ProcessEnv) error {
  532. notSelf := func(p *pkg) bool {
  533. return p.packageName != filePkg || p.dir != filepath.Dir(filename)
  534. }
  535. // Start off with the standard library.
  536. for importPath, exports := range stdlib {
  537. p := &pkg{
  538. dir: filepath.Join(env.GOROOT, "src", importPath),
  539. importPathShort: importPath,
  540. packageName: path.Base(importPath),
  541. relevance: MaxRelevance,
  542. }
  543. if notSelf(p) && wrappedCallback.packageNameLoaded(p) {
  544. wrappedCallback.exportsLoaded(p, exports)
  545. }
  546. }
  547. var mu sync.Mutex
  548. dupCheck := map[string]struct{}{}
  549. scanFilter := &scanCallback{
  550. rootFound: func(root gopathwalk.Root) bool {
  551. // Exclude goroot results -- getting them is relatively expensive, not cached,
  552. // and generally redundant with the in-memory version.
  553. return root.Type != gopathwalk.RootGOROOT && wrappedCallback.rootFound(root)
  554. },
  555. dirFound: wrappedCallback.dirFound,
  556. packageNameLoaded: func(pkg *pkg) bool {
  557. mu.Lock()
  558. defer mu.Unlock()
  559. if _, ok := dupCheck[pkg.importPathShort]; ok {
  560. return false
  561. }
  562. dupCheck[pkg.importPathShort] = struct{}{}
  563. return notSelf(pkg) && wrappedCallback.packageNameLoaded(pkg)
  564. },
  565. exportsLoaded: func(pkg *pkg, exports []string) {
  566. // If we're an x_test, load the package under test's test variant.
  567. if strings.HasSuffix(filePkg, "_test") && pkg.dir == filepath.Dir(filename) {
  568. var err error
  569. _, exports, err = loadExportsFromFiles(ctx, env, pkg.dir, true)
  570. if err != nil {
  571. return
  572. }
  573. }
  574. wrappedCallback.exportsLoaded(pkg, exports)
  575. },
  576. }
  577. return env.GetResolver().scan(ctx, scanFilter)
  578. }
  579. func ScoreImportPaths(ctx context.Context, env *ProcessEnv, paths []string) map[string]int {
  580. result := make(map[string]int)
  581. for _, path := range paths {
  582. result[path] = env.GetResolver().scoreImportPath(ctx, path)
  583. }
  584. return result
  585. }
  586. func PrimeCache(ctx context.Context, env *ProcessEnv) error {
  587. // Fully scan the disk for directories, but don't actually read any Go files.
  588. callback := &scanCallback{
  589. rootFound: func(gopathwalk.Root) bool {
  590. return true
  591. },
  592. dirFound: func(pkg *pkg) bool {
  593. return false
  594. },
  595. packageNameLoaded: func(pkg *pkg) bool {
  596. return false
  597. },
  598. }
  599. return getCandidatePkgs(ctx, callback, "", "", env)
  600. }
  601. func candidateImportName(pkg *pkg) string {
  602. if ImportPathToAssumedName(pkg.importPathShort) != pkg.packageName {
  603. return pkg.packageName
  604. }
  605. return ""
  606. }
  607. // getAllCandidates gets all of the candidates to be imported, regardless of if they are needed.
  608. func getAllCandidates(ctx context.Context, wrapped func(ImportFix), searchPrefix, filename, filePkg string, env *ProcessEnv) error {
  609. callback := &scanCallback{
  610. rootFound: func(gopathwalk.Root) bool {
  611. return true
  612. },
  613. dirFound: func(pkg *pkg) bool {
  614. if !canUse(filename, pkg.dir) {
  615. return false
  616. }
  617. // Try the assumed package name first, then a simpler path match
  618. // in case of packages named vN, which are not uncommon.
  619. return strings.HasPrefix(ImportPathToAssumedName(pkg.importPathShort), searchPrefix) ||
  620. strings.HasPrefix(path.Base(pkg.importPathShort), searchPrefix)
  621. },
  622. packageNameLoaded: func(pkg *pkg) bool {
  623. if !strings.HasPrefix(pkg.packageName, searchPrefix) {
  624. return false
  625. }
  626. wrapped(ImportFix{
  627. StmtInfo: ImportInfo{
  628. ImportPath: pkg.importPathShort,
  629. Name: candidateImportName(pkg),
  630. },
  631. IdentName: pkg.packageName,
  632. FixType: AddImport,
  633. Relevance: pkg.relevance,
  634. })
  635. return false
  636. },
  637. }
  638. return getCandidatePkgs(ctx, callback, filename, filePkg, env)
  639. }
  640. // A PackageExport is a package and its exports.
  641. type PackageExport struct {
  642. Fix *ImportFix
  643. Exports []string
  644. }
  645. func getPackageExports(ctx context.Context, wrapped func(PackageExport), searchPkg, filename, filePkg string, env *ProcessEnv) error {
  646. callback := &scanCallback{
  647. rootFound: func(gopathwalk.Root) bool {
  648. return true
  649. },
  650. dirFound: func(pkg *pkg) bool {
  651. return pkgIsCandidate(filename, references{searchPkg: nil}, pkg)
  652. },
  653. packageNameLoaded: func(pkg *pkg) bool {
  654. return pkg.packageName == searchPkg
  655. },
  656. exportsLoaded: func(pkg *pkg, exports []string) {
  657. sort.Strings(exports)
  658. wrapped(PackageExport{
  659. Fix: &ImportFix{
  660. StmtInfo: ImportInfo{
  661. ImportPath: pkg.importPathShort,
  662. Name: candidateImportName(pkg),
  663. },
  664. IdentName: pkg.packageName,
  665. FixType: AddImport,
  666. Relevance: pkg.relevance,
  667. },
  668. Exports: exports,
  669. })
  670. },
  671. }
  672. return getCandidatePkgs(ctx, callback, filename, filePkg, env)
  673. }
  674. // ProcessEnv contains environment variables and settings that affect the use of
  675. // the go command, the go/build package, etc.
  676. type ProcessEnv struct {
  677. LocalPrefix string
  678. BuildFlags []string
  679. // If non-empty, these will be used instead of the
  680. // process-wide values.
  681. GOPATH, GOROOT, GO111MODULE, GOPROXY, GOFLAGS, GOSUMDB string
  682. WorkingDir string
  683. // If Logf is non-nil, debug logging is enabled through this function.
  684. Logf func(format string, args ...interface{})
  685. resolver Resolver
  686. }
  687. // CopyConfig copies the env's configuration into a new env.
  688. func (e *ProcessEnv) CopyConfig() *ProcessEnv {
  689. copy := *e
  690. copy.resolver = nil
  691. return &copy
  692. }
  693. func (e *ProcessEnv) env() []string {
  694. env := os.Environ()
  695. add := func(k, v string) {
  696. if v != "" {
  697. env = append(env, k+"="+v)
  698. }
  699. }
  700. add("GOPATH", e.GOPATH)
  701. add("GOROOT", e.GOROOT)
  702. add("GO111MODULE", e.GO111MODULE)
  703. add("GOPROXY", e.GOPROXY)
  704. add("GOFLAGS", e.GOFLAGS)
  705. add("GOSUMDB", e.GOSUMDB)
  706. if e.WorkingDir != "" {
  707. add("PWD", e.WorkingDir)
  708. }
  709. return env
  710. }
  711. func (e *ProcessEnv) GetResolver() Resolver {
  712. if e.resolver != nil {
  713. return e.resolver
  714. }
  715. out, err := e.invokeGo(context.TODO(), "env", "GOMOD")
  716. if err != nil || len(bytes.TrimSpace(out.Bytes())) == 0 {
  717. e.resolver = newGopathResolver(e)
  718. return e.resolver
  719. }
  720. e.resolver = newModuleResolver(e)
  721. return e.resolver
  722. }
  723. func (e *ProcessEnv) buildContext() *build.Context {
  724. ctx := build.Default
  725. ctx.GOROOT = e.GOROOT
  726. ctx.GOPATH = e.GOPATH
  727. // As of Go 1.14, build.Context has a Dir field
  728. // (see golang.org/issue/34860).
  729. // Populate it only if present.
  730. rc := reflect.ValueOf(&ctx).Elem()
  731. dir := rc.FieldByName("Dir")
  732. if !dir.IsValid() {
  733. // Working drafts of Go 1.14 named the field "WorkingDir" instead.
  734. // TODO(bcmills): Remove this case after the Go 1.14 beta has been released.
  735. dir = rc.FieldByName("WorkingDir")
  736. }
  737. if dir.IsValid() && dir.Kind() == reflect.String {
  738. dir.SetString(e.WorkingDir)
  739. }
  740. return &ctx
  741. }
  742. func (e *ProcessEnv) invokeGo(ctx context.Context, verb string, args ...string) (*bytes.Buffer, error) {
  743. inv := gocommand.Invocation{
  744. Verb: verb,
  745. Args: args,
  746. BuildFlags: e.BuildFlags,
  747. Env: e.env(),
  748. Logf: e.Logf,
  749. WorkingDir: e.WorkingDir,
  750. }
  751. return inv.Run(ctx)
  752. }
  753. func addStdlibCandidates(pass *pass, refs references) {
  754. add := func(pkg string) {
  755. // Prevent self-imports.
  756. if path.Base(pkg) == pass.f.Name.Name && filepath.Join(pass.env.GOROOT, "src", pkg) == pass.srcDir {
  757. return
  758. }
  759. exports := copyExports(stdlib[pkg])
  760. pass.addCandidate(
  761. &ImportInfo{ImportPath: pkg},
  762. &packageInfo{name: path.Base(pkg), exports: exports})
  763. }
  764. for left := range refs {
  765. if left == "rand" {
  766. // Make sure we try crypto/rand before math/rand.
  767. add("crypto/rand")
  768. add("math/rand")
  769. continue
  770. }
  771. for importPath := range stdlib {
  772. if path.Base(importPath) == left {
  773. add(importPath)
  774. }
  775. }
  776. }
  777. }
  778. // A Resolver does the build-system-specific parts of goimports.
  779. type Resolver interface {
  780. // loadPackageNames loads the package names in importPaths.
  781. loadPackageNames(importPaths []string, srcDir string) (map[string]string, error)
  782. // scan works with callback to search for packages. See scanCallback for details.
  783. scan(ctx context.Context, callback *scanCallback) error
  784. // loadExports returns the set of exported symbols in the package at dir.
  785. // loadExports may be called concurrently.
  786. loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error)
  787. // scoreImportPath returns the relevance for an import path.
  788. scoreImportPath(ctx context.Context, path string) int
  789. ClearForNewScan()
  790. }
  791. // A scanCallback controls a call to scan and receives its results.
  792. // In general, minor errors will be silently discarded; a user should not
  793. // expect to receive a full series of calls for everything.
  794. type scanCallback struct {
  795. // rootFound is called before scanning a new root dir. If it returns true,
  796. // the root will be scanned. Returning false will not necessarily prevent
  797. // directories from that root making it to dirFound.
  798. rootFound func(gopathwalk.Root) bool
  799. // dirFound is called when a directory is found that is possibly a Go package.
  800. // pkg will be populated with everything except packageName.
  801. // If it returns true, the package's name will be loaded.
  802. dirFound func(pkg *pkg) bool
  803. // packageNameLoaded is called when a package is found and its name is loaded.
  804. // If it returns true, the package's exports will be loaded.
  805. packageNameLoaded func(pkg *pkg) bool
  806. // exportsLoaded is called when a package's exports have been loaded.
  807. exportsLoaded func(pkg *pkg, exports []string)
  808. }
  809. func addExternalCandidates(pass *pass, refs references, filename string) error {
  810. var mu sync.Mutex
  811. found := make(map[string][]pkgDistance)
  812. callback := &scanCallback{
  813. rootFound: func(gopathwalk.Root) bool {
  814. return true // We want everything.
  815. },
  816. dirFound: func(pkg *pkg) bool {
  817. return pkgIsCandidate(filename, refs, pkg)
  818. },
  819. packageNameLoaded: func(pkg *pkg) bool {
  820. if _, want := refs[pkg.packageName]; !want {
  821. return false
  822. }
  823. if pkg.dir == pass.srcDir && pass.f.Name.Name == pkg.packageName {
  824. // The candidate is in the same directory and has the
  825. // same package name. Don't try to import ourselves.
  826. return false
  827. }
  828. if !canUse(filename, pkg.dir) {
  829. return false
  830. }
  831. mu.Lock()
  832. defer mu.Unlock()
  833. found[pkg.packageName] = append(found[pkg.packageName], pkgDistance{pkg, distance(pass.srcDir, pkg.dir)})
  834. return false // We'll do our own loading after we sort.
  835. },
  836. }
  837. err := pass.env.GetResolver().scan(context.Background(), callback)
  838. if err != nil {
  839. return err
  840. }
  841. // Search for imports matching potential package references.
  842. type result struct {
  843. imp *ImportInfo
  844. pkg *packageInfo
  845. }
  846. results := make(chan result, len(refs))
  847. ctx, cancel := context.WithCancel(context.TODO())
  848. var wg sync.WaitGroup
  849. defer func() {
  850. cancel()
  851. wg.Wait()
  852. }()
  853. var (
  854. firstErr error
  855. firstErrOnce sync.Once
  856. )
  857. for pkgName, symbols := range refs {
  858. wg.Add(1)
  859. go func(pkgName string, symbols map[string]bool) {
  860. defer wg.Done()
  861. found, err := findImport(ctx, pass, found[pkgName], pkgName, symbols, filename)
  862. if err != nil {
  863. firstErrOnce.Do(func() {
  864. firstErr = err
  865. cancel()
  866. })
  867. return
  868. }
  869. if found == nil {
  870. return // No matching package.
  871. }
  872. imp := &ImportInfo{
  873. ImportPath: found.importPathShort,
  874. }
  875. pkg := &packageInfo{
  876. name: pkgName,
  877. exports: symbols,
  878. }
  879. results <- result{imp, pkg}
  880. }(pkgName, symbols)
  881. }
  882. go func() {
  883. wg.Wait()
  884. close(results)
  885. }()
  886. for result := range results {
  887. pass.addCandidate(result.imp, result.pkg)
  888. }
  889. return firstErr
  890. }
  891. // notIdentifier reports whether ch is an invalid identifier character.
  892. func notIdentifier(ch rune) bool {
  893. return !('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' ||
  894. '0' <= ch && ch <= '9' ||
  895. ch == '_' ||
  896. ch >= utf8.RuneSelf && (unicode.IsLetter(ch) || unicode.IsDigit(ch)))
  897. }
  898. // ImportPathToAssumedName returns the assumed package name of an import path.
  899. // It does this using only string parsing of the import path.
  900. // It picks the last element of the path that does not look like a major
  901. // version, and then picks the valid identifier off the start of that element.
  902. // It is used to determine if a local rename should be added to an import for
  903. // clarity.
  904. // This function could be moved to a standard package and exported if we want
  905. // for use in other tools.
  906. func ImportPathToAssumedName(importPath string) string {
  907. base := path.Base(importPath)
  908. if strings.HasPrefix(base, "v") {
  909. if _, err := strconv.Atoi(base[1:]); err == nil {
  910. dir := path.Dir(importPath)
  911. if dir != "." {
  912. base = path.Base(dir)
  913. }
  914. }
  915. }
  916. base = strings.TrimPrefix(base, "go-")
  917. if i := strings.IndexFunc(base, notIdentifier); i >= 0 {
  918. base = base[:i]
  919. }
  920. return base
  921. }
  922. // gopathResolver implements resolver for GOPATH workspaces.
  923. type gopathResolver struct {
  924. env *ProcessEnv
  925. walked bool
  926. cache *dirInfoCache
  927. scanSema chan struct{} // scanSema prevents concurrent scans.
  928. }
  929. func newGopathResolver(env *ProcessEnv) *gopathResolver {
  930. r := &gopathResolver{
  931. env: env,
  932. cache: &dirInfoCache{
  933. dirs: map[string]*directoryPackageInfo{},
  934. listeners: map[*int]cacheListener{},
  935. },
  936. scanSema: make(chan struct{}, 1),
  937. }
  938. r.scanSema <- struct{}{}
  939. return r
  940. }
  941. func (r *gopathResolver) ClearForNewScan() {
  942. <-r.scanSema
  943. r.cache = &dirInfoCache{
  944. dirs: map[string]*directoryPackageInfo{},
  945. listeners: map[*int]cacheListener{},
  946. }
  947. r.walked = false
  948. r.scanSema <- struct{}{}
  949. }
  950. func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) {
  951. names := map[string]string{}
  952. for _, path := range importPaths {
  953. names[path] = importPathToName(r.env, path, srcDir)
  954. }
  955. return names, nil
  956. }
  957. // importPathToName finds out the actual package name, as declared in its .go files.
  958. // If there's a problem, it returns "".
  959. func importPathToName(env *ProcessEnv, importPath, srcDir string) (packageName string) {
  960. // Fast path for standard library without going to disk.
  961. if _, ok := stdlib[importPath]; ok {
  962. return path.Base(importPath) // stdlib packages always match their paths.
  963. }
  964. buildPkg, err := env.buildContext().Import(importPath, srcDir, build.FindOnly)
  965. if err != nil {
  966. return ""
  967. }
  968. pkgName, err := packageDirToName(buildPkg.Dir)
  969. if err != nil {
  970. return ""
  971. }
  972. return pkgName
  973. }
  974. // packageDirToName is a faster version of build.Import if
  975. // the only thing desired is the package name. Given a directory,
  976. // packageDirToName then only parses one file in the package,
  977. // trusting that the files in the directory are consistent.
  978. func packageDirToName(dir string) (packageName string, err error) {
  979. d, err := os.Open(dir)
  980. if err != nil {
  981. return "", err
  982. }
  983. names, err := d.Readdirnames(-1)
  984. d.Close()
  985. if err != nil {
  986. return "", err
  987. }
  988. sort.Strings(names) // to have predictable behavior
  989. var lastErr error
  990. var nfile int
  991. for _, name := range names {
  992. if !strings.HasSuffix(name, ".go") {
  993. continue
  994. }
  995. if strings.HasSuffix(name, "_test.go") {
  996. continue
  997. }
  998. nfile++
  999. fullFile := filepath.Join(dir, name)
  1000. fset := token.NewFileSet()
  1001. f, err := parser.ParseFile(fset, fullFile, nil, parser.PackageClauseOnly)
  1002. if err != nil {
  1003. lastErr = err
  1004. continue
  1005. }
  1006. pkgName := f.Name.Name
  1007. if pkgName == "documentation" {
  1008. // Special case from go/build.ImportDir, not
  1009. // handled by ctx.MatchFile.
  1010. continue
  1011. }
  1012. if pkgName == "main" {
  1013. // Also skip package main, assuming it's a +build ignore generator or example.
  1014. // Since you can't import a package main anyway, there's no harm here.
  1015. continue
  1016. }
  1017. return pkgName, nil
  1018. }
  1019. if lastErr != nil {
  1020. return "", lastErr
  1021. }
  1022. return "", fmt.Errorf("no importable package found in %d Go files", nfile)
  1023. }
  1024. type pkg struct {
  1025. dir string // absolute file path to pkg directory ("/usr/lib/go/src/net/http")
  1026. importPathShort string // vendorless import path ("net/http", "a/b")
  1027. packageName string // package name loaded from source if requested
  1028. relevance int // a weakly-defined score of how relevant a package is. 0 is most relevant.
  1029. }
  1030. type pkgDistance struct {
  1031. pkg *pkg
  1032. distance int // relative distance to target
  1033. }
  1034. // byDistanceOrImportPathShortLength sorts by relative distance breaking ties
  1035. // on the short import path length and then the import string itself.
  1036. type byDistanceOrImportPathShortLength []pkgDistance
  1037. func (s byDistanceOrImportPathShortLength) Len() int { return len(s) }
  1038. func (s byDistanceOrImportPathShortLength) Less(i, j int) bool {
  1039. di, dj := s[i].distance, s[j].distance
  1040. if di == -1 {
  1041. return false
  1042. }
  1043. if dj == -1 {
  1044. return true
  1045. }
  1046. if di != dj {
  1047. return di < dj
  1048. }
  1049. vi, vj := s[i].pkg.importPathShort, s[j].pkg.importPathShort
  1050. if len(vi) != len(vj) {
  1051. return len(vi) < len(vj)
  1052. }
  1053. return vi < vj
  1054. }
  1055. func (s byDistanceOrImportPathShortLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  1056. func distance(basepath, targetpath string) int {
  1057. p, err := filepath.Rel(basepath, targetpath)
  1058. if err != nil {
  1059. return -1
  1060. }
  1061. if p == "." {
  1062. return 0
  1063. }
  1064. return strings.Count(p, string(filepath.Separator)) + 1
  1065. }
  1066. func (r *gopathResolver) scan(ctx context.Context, callback *scanCallback) error {
  1067. add := func(root gopathwalk.Root, dir string) {
  1068. // We assume cached directories have not changed. We can skip them and their
  1069. // children.
  1070. if _, ok := r.cache.Load(dir); ok {
  1071. return
  1072. }
  1073. importpath := filepath.ToSlash(dir[len(root.Path)+len("/"):])
  1074. info := directoryPackageInfo{
  1075. status: directoryScanned,
  1076. dir: dir,
  1077. rootType: root.Type,
  1078. nonCanonicalImportPath: VendorlessPath(importpath),
  1079. }
  1080. r.cache.Store(dir, info)
  1081. }
  1082. processDir := func(info directoryPackageInfo) {
  1083. // Skip this directory if we were not able to get the package information successfully.
  1084. if scanned, err := info.reachedStatus(directoryScanned); !scanned || err != nil {
  1085. return
  1086. }
  1087. p := &pkg{
  1088. importPathShort: info.nonCanonicalImportPath,
  1089. dir: info.dir,
  1090. relevance: MaxRelevance - 1,
  1091. }
  1092. if info.rootType == gopathwalk.RootGOROOT {
  1093. p.relevance = MaxRelevance
  1094. }
  1095. if !callback.dirFound(p) {
  1096. return
  1097. }
  1098. var err error
  1099. p.packageName, err = r.cache.CachePackageName(info)
  1100. if err != nil {
  1101. return
  1102. }
  1103. if !callback.packageNameLoaded(p) {
  1104. return
  1105. }
  1106. if _, exports, err := r.loadExports(ctx, p, false); err == nil {
  1107. callback.exportsLoaded(p, exports)
  1108. }
  1109. }
  1110. stop := r.cache.ScanAndListen(ctx, processDir)
  1111. defer stop()
  1112. // The callback is not necessarily safe to use in the goroutine below. Process roots eagerly.
  1113. roots := filterRoots(gopathwalk.SrcDirsRoots(r.env.buildContext()), callback.rootFound)
  1114. // We can't cancel walks, because we need them to finish to have a usable
  1115. // cache. Instead, run them in a separate goroutine and detach.
  1116. scanDone := make(chan struct{})
  1117. go func() {
  1118. select {
  1119. case <-ctx.Done():
  1120. return
  1121. case <-r.scanSema:
  1122. }
  1123. defer func() { r.scanSema <- struct{}{} }()
  1124. gopathwalk.Walk(roots, add, gopathwalk.Options{Logf: r.env.Logf, ModulesEnabled: false})
  1125. close(scanDone)
  1126. }()
  1127. select {
  1128. case <-ctx.Done():
  1129. case <-scanDone:
  1130. }
  1131. return nil
  1132. }
  1133. func (r *gopathResolver) scoreImportPath(ctx context.Context, path string) int {
  1134. if _, ok := stdlib[path]; ok {
  1135. return MaxRelevance
  1136. }
  1137. return MaxRelevance - 1
  1138. }
  1139. func filterRoots(roots []gopathwalk.Root, include func(gopathwalk.Root) bool) []gopathwalk.Root {
  1140. var result []gopathwalk.Root
  1141. for _, root := range roots {
  1142. if !include(root) {
  1143. continue
  1144. }
  1145. result = append(result, root)
  1146. }
  1147. return result
  1148. }
  1149. func (r *gopathResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []string, error) {
  1150. if info, ok := r.cache.Load(pkg.dir); ok && !includeTest {
  1151. return r.cache.CacheExports(ctx, r.env, info)
  1152. }
  1153. return loadExportsFromFiles(ctx, r.env, pkg.dir, includeTest)
  1154. }
  1155. // VendorlessPath returns the devendorized version of the import path ipath.
  1156. // For example, VendorlessPath("foo/bar/vendor/a/b") returns "a/b".
  1157. func VendorlessPath(ipath string) string {
  1158. // Devendorize for use in import statement.
  1159. if i := strings.LastIndex(ipath, "/vendor/"); i >= 0 {
  1160. return ipath[i+len("/vendor/"):]
  1161. }
  1162. if strings.HasPrefix(ipath, "vendor/") {
  1163. return ipath[len("vendor/"):]
  1164. }
  1165. return ipath
  1166. }
  1167. func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, includeTest bool) (string, []string, error) {
  1168. var exports []string
  1169. // Look for non-test, buildable .go files which could provide exports.
  1170. all, err := ioutil.ReadDir(dir)
  1171. if err != nil {
  1172. return "", nil, err
  1173. }
  1174. var files []os.FileInfo
  1175. for _, fi := range all {
  1176. name := fi.Name()
  1177. if !strings.HasSuffix(name, ".go") || (!includeTest && strings.HasSuffix(name, "_test.go")) {
  1178. continue
  1179. }
  1180. match, err := env.buildContext().MatchFile(dir, fi.Name())
  1181. if err != nil || !match {
  1182. continue
  1183. }
  1184. files = append(files, fi)
  1185. }
  1186. if len(files) == 0 {
  1187. return "", nil, fmt.Errorf("dir %v contains no buildable, non-test .go files", dir)
  1188. }
  1189. var pkgName string
  1190. fset := token.NewFileSet()
  1191. for _, fi := range files {
  1192. select {
  1193. case <-ctx.Done():
  1194. return "", nil, ctx.Err()
  1195. default:
  1196. }
  1197. fullFile := filepath.Join(dir, fi.Name())
  1198. f, err := parser.ParseFile(fset, fullFile, nil, 0)
  1199. if err != nil {
  1200. return "", nil, fmt.Errorf("parsing %s: %v", fullFile, err)
  1201. }
  1202. if f.Name.Name == "documentation" {
  1203. // Special case from go/build.ImportDir, not
  1204. // handled by MatchFile above.
  1205. continue
  1206. }
  1207. if includeTest && strings.HasSuffix(f.Name.Name, "_test") {
  1208. // x_test package. We want internal test files only.
  1209. continue
  1210. }
  1211. pkgName = f.Name.Name
  1212. for name := range f.Scope.Objects {
  1213. if ast.IsExported(name) {
  1214. exports = append(exports, name)
  1215. }
  1216. }
  1217. }
  1218. if env.Logf != nil {
  1219. sortedExports := append([]string(nil), exports...)
  1220. sort.Strings(sortedExports)
  1221. env.Logf("loaded exports in dir %v (package %v): %v", dir, pkgName, strings.Join(sortedExports, ", "))
  1222. }
  1223. return pkgName, exports, nil
  1224. }
  1225. // findImport searches for a package with the given symbols.
  1226. // If no package is found, findImport returns ("", false, nil)
  1227. func findImport(ctx context.Context, pass *pass, candidates []pkgDistance, pkgName string, symbols map[string]bool, filename string) (*pkg, error) {
  1228. // Sort the candidates by their import package length,
  1229. // assuming that shorter package names are better than long
  1230. // ones. Note that this sorts by the de-vendored name, so
  1231. // there's no "penalty" for vendoring.
  1232. sort.Sort(byDistanceOrImportPathShortLength(candidates))
  1233. if pass.env.Logf != nil {
  1234. for i, c := range candidates {
  1235. pass.env.Logf("%s candidate %d/%d: %v in %v", pkgName, i+1, len(candidates), c.pkg.importPathShort, c.pkg.dir)
  1236. }
  1237. }
  1238. // Collect exports for packages with matching names.
  1239. rescv := make([]chan *pkg, len(candidates))
  1240. for i := range candidates {
  1241. rescv[i] = make(chan *pkg, 1)
  1242. }
  1243. const maxConcurrentPackageImport = 4
  1244. loadExportsSem := make(chan struct{}, maxConcurrentPackageImport)
  1245. ctx, cancel := context.WithCancel(ctx)
  1246. var wg sync.WaitGroup
  1247. defer func() {
  1248. cancel()
  1249. wg.Wait()
  1250. }()
  1251. wg.Add(1)
  1252. go func() {
  1253. defer wg.Done()
  1254. for i, c := range candidates {
  1255. select {
  1256. case loadExportsSem <- struct{}{}:
  1257. case <-ctx.Done():
  1258. return
  1259. }
  1260. wg.Add(1)
  1261. go func(c pkgDistance, resc chan<- *pkg) {
  1262. defer func() {
  1263. <-loadExportsSem
  1264. wg.Done()
  1265. }()
  1266. if pass.env.Logf != nil {
  1267. pass.env.Logf("loading exports in dir %s (seeking package %s)", c.pkg.dir, pkgName)
  1268. }
  1269. // If we're an x_test, load the package under test's test variant.
  1270. includeTest := strings.HasSuffix(pass.f.Name.Name, "_test") && c.pkg.dir == pass.srcDir
  1271. _, exports, err := pass.env.GetResolver().loadExports(ctx, c.pkg, includeTest)
  1272. if err != nil {
  1273. if pass.env.Logf != nil {
  1274. pass.env.Logf("loading exports in dir %s (seeking package %s): %v", c.pkg.dir, pkgName, err)
  1275. }
  1276. resc <- nil
  1277. return
  1278. }
  1279. exportsMap := make(map[string]bool, len(exports))
  1280. for _, sym := range exports {
  1281. exportsMap[sym] = true
  1282. }
  1283. // If it doesn't have the right
  1284. // symbols, send nil to mean no match.
  1285. for symbol := range symbols {
  1286. if !exportsMap[symbol] {
  1287. resc <- nil
  1288. return
  1289. }
  1290. }
  1291. resc <- c.pkg
  1292. }(c, rescv[i])
  1293. }
  1294. }()
  1295. for _, resc := range rescv {
  1296. pkg := <-resc
  1297. if pkg == nil {
  1298. continue
  1299. }
  1300. return pkg, nil
  1301. }
  1302. return nil, nil
  1303. }
  1304. // pkgIsCandidate reports whether pkg is a candidate for satisfying the
  1305. // finding which package pkgIdent in the file named by filename is trying
  1306. // to refer to.
  1307. //
  1308. // This check is purely lexical and is meant to be as fast as possible
  1309. // because it's run over all $GOPATH directories to filter out poor
  1310. // candidates in order to limit the CPU and I/O later parsing the
  1311. // exports in candidate packages.
  1312. //
  1313. // filename is the file being formatted.
  1314. // pkgIdent is the package being searched for, like "client" (if
  1315. // searching for "client.New")
  1316. func pkgIsCandidate(filename string, refs references, pkg *pkg) bool {
  1317. // Check "internal" and "vendor" visibility:
  1318. if !canUse(filename, pkg.dir) {
  1319. return false
  1320. }
  1321. // Speed optimization to minimize disk I/O:
  1322. // the last two components on disk must contain the
  1323. // package name somewhere.
  1324. //
  1325. // This permits mismatch naming like directory
  1326. // "go-foo" being package "foo", or "pkg.v3" being "pkg",
  1327. // or directory "google.golang.org/api/cloudbilling/v1"
  1328. // being package "cloudbilling", but doesn't
  1329. // permit a directory "foo" to be package
  1330. // "bar", which is strongly discouraged
  1331. // anyway. There's no reason goimports needs
  1332. // to be slow just to accommodate that.
  1333. for pkgIdent := range refs {
  1334. lastTwo := lastTwoComponents(pkg.importPathShort)
  1335. if strings.Contains(lastTwo, pkgIdent) {
  1336. return true
  1337. }
  1338. if hasHyphenOrUpperASCII(lastTwo) && !hasHyphenOrUpperASCII(pkgIdent) {
  1339. lastTwo = lowerASCIIAndRemoveHyphen(lastTwo)
  1340. if strings.Contains(lastTwo, pkgIdent) {
  1341. return true
  1342. }
  1343. }
  1344. }
  1345. return false
  1346. }
  1347. func hasHyphenOrUpperASCII(s string) bool {
  1348. for i := 0; i < len(s); i++ {
  1349. b := s[i]
  1350. if b == '-' || ('A' <= b && b <= 'Z') {
  1351. return true
  1352. }
  1353. }
  1354. return false
  1355. }
  1356. func lowerASCIIAndRemoveHyphen(s string) (ret string) {
  1357. buf := make([]byte, 0, len(s))
  1358. for i := 0; i < len(s); i++ {
  1359. b := s[i]
  1360. switch {
  1361. case b == '-':
  1362. continue
  1363. case 'A' <= b && b <= 'Z':
  1364. buf = append(buf, b+('a'-'A'))
  1365. default:
  1366. buf = append(buf, b)
  1367. }
  1368. }
  1369. return string(buf)
  1370. }
  1371. // canUse reports whether the package in dir is usable from filename,
  1372. // respecting the Go "internal" and "vendor" visibility rules.
  1373. func canUse(filename, dir string) bool {
  1374. // Fast path check, before any allocations. If it doesn't contain vendor
  1375. // or internal, it's not tricky:
  1376. // Note that this can false-negative on directories like "notinternal",
  1377. // but we check it correctly below. This is just a fast path.
  1378. if !strings.Contains(dir, "vendor") && !strings.Contains(dir, "internal") {
  1379. return true
  1380. }
  1381. dirSlash := filepath.ToSlash(dir)
  1382. if !strings.Contains(dirSlash, "/vendor/") && !strings.Contains(dirSlash, "/internal/") && !strings.HasSuffix(dirSlash, "/internal") {
  1383. return true
  1384. }
  1385. // Vendor or internal directory only visible from children of parent.
  1386. // That means the path from the current directory to the target directory
  1387. // can contain ../vendor or ../internal but not ../foo/vendor or ../foo/internal
  1388. // or bar/vendor or bar/internal.
  1389. // After stripping all the leading ../, the only okay place to see vendor or internal
  1390. // is at the very beginning of the path.
  1391. absfile, err := filepath.Abs(filename)
  1392. if err != nil {
  1393. return false
  1394. }
  1395. absdir, err := filepath.Abs(dir)
  1396. if err != nil {
  1397. return false
  1398. }
  1399. rel, err := filepath.Rel(absfile, absdir)
  1400. if err != nil {
  1401. return false
  1402. }
  1403. relSlash := filepath.ToSlash(rel)
  1404. if i := strings.LastIndex(relSlash, "../"); i >= 0 {
  1405. relSlash = relSlash[i+len("../"):]
  1406. }
  1407. return !strings.Contains(relSlash, "/vendor/") && !strings.Contains(relSlash, "/internal/") && !strings.HasSuffix(relSlash, "/internal")
  1408. }
  1409. // lastTwoComponents returns at most the last two path components
  1410. // of v, using either / or \ as the path separator.
  1411. func lastTwoComponents(v string) string {
  1412. nslash := 0
  1413. for i := len(v) - 1; i >= 0; i-- {
  1414. if v[i] == '/' || v[i] == '\\' {
  1415. nslash++
  1416. if nslash == 2 {
  1417. return v[i:]
  1418. }
  1419. }
  1420. }
  1421. return v
  1422. }
  1423. type visitFn func(node ast.Node) ast.Visitor
  1424. func (fn visitFn) Visit(node ast.Node) ast.Visitor {
  1425. return fn(node)
  1426. }
  1427. func copyExports(pkg []string) map[string]bool {
  1428. m := make(map[string]bool, len(pkg))
  1429. for _, v := range pkg {
  1430. m[v] = true
  1431. }
  1432. return m
  1433. }