var importToGroup … func importGroup(localPrefix, importPath string) int { … } type ImportFixType … const AddImport … const DeleteImport … const SetImportName … type ImportFix … // parseOtherFiles parses all the Go files in srcDir except filename, including // test files if filename looks like a test. // // It returns an error only if ctx is cancelled. Files with parse errors are // ignored. func parseOtherFiles(ctx context.Context, fset *token.FileSet, srcDir, filename string) ([]*ast.File, error) { … } // addGlobals puts the names of package vars into the provided map. func addGlobals(f *ast.File, globals map[string]bool) { … } // collectReferences builds a map of selector expressions, from // left hand side (X) to a set of right hand sides (Sel). func collectReferences(f *ast.File) References { … } // collectImports returns all the imports in f. // Unnamed imports (., _) and "C" are ignored. func collectImports(f *ast.File) []*ImportInfo { … } // findMissingImport searches pass's candidates for an import that provides // pkg, containing all of syms. func (p *pass) findMissingImport(pkg string, syms map[string]bool) *ImportInfo { … } type pass … // loadPackageNames saves the package names for everything referenced by imports. func (p *pass) loadPackageNames(ctx context.Context, imports []*ImportInfo) error { … } // if there is a trailing major version, remove it func withoutVersion(nm string) string { … } // importIdentifier returns the identifier that imp will introduce. It will // guess if the package name has not been loaded, e.g. because the source // is not available. func (p *pass) importIdentifier(imp *ImportInfo) string { … } // load reads in everything necessary to run a pass, and reports whether the // file already has all the imports it needs. It fills in p.missingRefs with the // file's missing symbols, if any, or removes unused imports if not. func (p *pass) load(ctx context.Context) ([]*ImportFix, bool) { … } // fix attempts to satisfy missing imports using p.candidates. If it finds // everything, or if p.lastTry is true, it updates fixes to add the imports it found, // delete anything unused, and update import names, and returns true. func (p *pass) fix() ([]*ImportFix, bool) { … } func sortFixes(fixes []*ImportFix) { … } // importSpecName gets the import name of imp in the import spec. // // When the import identifier matches the assumed import name, the import name does // not appear in the import spec. func (p *pass) importSpecName(imp *ImportInfo) string { … } // apply will perform the fixes on f in order. func apply(fset *token.FileSet, f *ast.File, fixes []*ImportFix) { … } // assumeSiblingImportsValid assumes that siblings' use of packages is valid, // adding the exports they use. func (p *pass) assumeSiblingImportsValid() { … } // addCandidate adds a candidate import to p, and merges in the information // in pkg. func (p *pass) addCandidate(imp *ImportInfo, pkg *PackageInfo) { … } var fixImports … func fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) error { … } // getFixes gets the import fixes that need to be made to f in order to fix the imports. // It does not modify the ast. func getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) ([]*ImportFix, error) { … } func getFixesWithSource(ctx context.Context, fset *token.FileSet, f *ast.File, filename string, goroot string, logf func(string, ...any), source Source) ([]*ImportFix, error) { … } const MaxRelevance … // getCandidatePkgs works with the passed callback to find all acceptable packages. // It deduplicates by import path, and uses a cached stdlib rather than reading // from disk. func getCandidatePkgs(ctx context.Context, wrappedCallback *scanCallback, filename, filePkg string, env *ProcessEnv) error { … } func ScoreImportPaths(ctx context.Context, env *ProcessEnv, paths []string) (map[string]float64, error) { … } func PrimeCache(ctx context.Context, resolver Resolver) error { … } func candidateImportName(pkg *pkg) string { … } // GetAllCandidates calls wrapped for each package whose name starts with // searchPrefix, and can be imported from filename with the package name filePkg. // // Beware that the wrapped function may be called multiple times concurrently. // TODO(adonovan): encapsulate the concurrency. func GetAllCandidates(ctx context.Context, wrapped func(ImportFix), searchPrefix, filename, filePkg string, env *ProcessEnv) error { … } // GetImportPaths calls wrapped for each package whose import path starts with // searchPrefix, and can be imported from filename with the package name filePkg. func GetImportPaths(ctx context.Context, wrapped func(ImportFix), searchPrefix, filename, filePkg string, env *ProcessEnv) error { … } type PackageExport … // GetPackageExports returns all known packages with name pkg and their exports. func GetPackageExports(ctx context.Context, wrapped func(PackageExport), searchPkg, filename, filePkg string, env *ProcessEnv) error { … } var requiredGoEnvVars … type ProcessEnv … func (e *ProcessEnv) goEnv() (map[string]string, error) { … } func (e *ProcessEnv) matchFile(dir, name string) (bool, error) { … } // CopyConfig copies the env's configuration into a new env. func (e *ProcessEnv) CopyConfig() *ProcessEnv { … } func (e *ProcessEnv) init() error { … } func (e *ProcessEnv) env() []string { … } func (e *ProcessEnv) GetResolver() (Resolver, error) { … } // logf logs if e.Logf is non-nil. func (e *ProcessEnv) logf(format string, args ...any) { … } // buildContext returns the build.Context to use for matching files. // // TODO(rfindley): support dynamic GOOS, GOARCH here, when doing cross-platform // development. func (e *ProcessEnv) buildContext() (*build.Context, error) { … } func (e *ProcessEnv) invokeGo(ctx context.Context, verb string, args ...string) (*bytes.Buffer, error) { … } func addStdlibCandidates(pass *pass, refs References) error { … } type Resolver … type scanCallback … func addExternalCandidates(ctx context.Context, pass *pass, refs References, filename string) error { … } // notIdentifier reports whether ch is an invalid identifier character. func notIdentifier(ch rune) bool { … } // ImportPathToAssumedName returns the assumed package name of an import path. // It does this using only string parsing of the import path. // It picks the last element of the path that does not look like a major // version, and then picks the valid identifier off the start of that element. // It is used to determine if a local rename should be added to an import for // clarity. // This function could be moved to a standard package and exported if we want // for use in other tools. func ImportPathToAssumedName(importPath string) string { … } type gopathResolver … func newGopathResolver(env *ProcessEnv) *gopathResolver { … } func (r *gopathResolver) ClearForNewScan() Resolver { … } func (r *gopathResolver) loadPackageNames(importPaths []string, srcDir string) (map[string]string, error) { … } // importPathToName finds out the actual package name, as declared in its .go files. func importPathToName(bctx *build.Context, importPath, srcDir string) string { … } // packageDirToName is a faster version of build.Import if // the only thing desired is the package name. Given a directory, // packageDirToName then only parses one file in the package, // trusting that the files in the directory are consistent. func packageDirToName(dir string) (packageName string, err error) { … } type pkg … type pkgDistance … type byDistanceOrImportPathShortLength … func (s byDistanceOrImportPathShortLength) Len() int { … } func (s byDistanceOrImportPathShortLength) Less(i, j int) bool { … } func (s byDistanceOrImportPathShortLength) Swap(i, j int) { … } func distance(basepath, targetpath string) int { … } func (r *gopathResolver) scan(ctx context.Context, callback *scanCallback) error { … } func (r *gopathResolver) scoreImportPath(ctx context.Context, path string) float64 { … } func filterRoots(roots []gopathwalk.Root, include func(gopathwalk.Root) bool) []gopathwalk.Root { … } func (r *gopathResolver) loadExports(ctx context.Context, pkg *pkg, includeTest bool) (string, []stdlib.Symbol, error) { … } // VendorlessPath returns the devendorized version of the import path ipath. // For example, VendorlessPath("foo/bar/vendor/a/b") returns "a/b". func VendorlessPath(ipath string) string { … } func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, includeTest bool) (string, []stdlib.Symbol, error) { … } func sortSymbols(syms []stdlib.Symbol) { … } type symbolSearcher … // search searches the provided candidates for a package containing all // exported symbols. // // If successful, returns the resulting package. func (s *symbolSearcher) search(ctx context.Context, candidates []pkgDistance, pkgName string, symbols map[string]bool) (*pkg, error) { … } func (s *symbolSearcher) searchOne(ctx context.Context, c pkgDistance, symbols map[string]bool) (*pkg, error) { … } // pkgIsCandidate reports whether pkg is a candidate for satisfying the // finding which package pkgIdent in the file named by filename is trying // to refer to. // // This check is purely lexical and is meant to be as fast as possible // because it's run over all $GOPATH directories to filter out poor // candidates in order to limit the CPU and I/O later parsing the // exports in candidate packages. // // filename is the file being formatted. // pkgIdent is the package being searched for, like "client" (if // searching for "client.New") func pkgIsCandidate(filename string, refs References, pkg *pkg) bool { … } // canUse reports whether the package in dir is usable from filename, // respecting the Go "internal" and "vendor" visibility rules. func canUse(filename, dir string) bool { … } // matchesPath reports whether ident may match a potential package name // referred to by path, using heuristics to filter out unidiomatic package // names. // // Specifically, it checks whether either of the last two '/'- or '\'-delimited // path segments matches the identifier. The segment-matching heuristic must // allow for various conventions around segment naming, including go-foo, // foo-go, and foo.v3. To handle all of these, matching considers both (1) the // entire segment, ignoring '-' and '.', as well as (2) the last subsegment // separated by '-' or '.'. So the segment foo-go matches all of the following // identifiers: foo, go, and foogo. All matches are case insensitive (for ASCII // identifiers). // // See the docstring for [pkgIsCandidate] for an explanation of how this // heuristic filters potential candidate packages. func matchesPath(ident, path string) bool { … } type visitFn … func (fn visitFn) Visit(node ast.Node) ast.Visitor { … } func symbolNameSet(symbols []stdlib.Symbol) map[string]bool { … }