visit.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. // Copyright 2018 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 packages
  5. import (
  6. "fmt"
  7. "os"
  8. "sort"
  9. )
  10. // Visit visits all the packages in the import graph whose roots are
  11. // pkgs, calling the optional pre function the first time each package
  12. // is encountered (preorder), and the optional post function after a
  13. // package's dependencies have been visited (postorder).
  14. // The boolean result of pre(pkg) determines whether
  15. // the imports of package pkg are visited.
  16. func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {
  17. seen := make(map[*Package]bool)
  18. var visit func(*Package)
  19. visit = func(pkg *Package) {
  20. if !seen[pkg] {
  21. seen[pkg] = true
  22. if pre == nil || pre(pkg) {
  23. paths := make([]string, 0, len(pkg.Imports))
  24. for path := range pkg.Imports {
  25. paths = append(paths, path)
  26. }
  27. sort.Strings(paths) // Imports is a map, this makes visit stable
  28. for _, path := range paths {
  29. visit(pkg.Imports[path])
  30. }
  31. }
  32. if post != nil {
  33. post(pkg)
  34. }
  35. }
  36. }
  37. for _, pkg := range pkgs {
  38. visit(pkg)
  39. }
  40. }
  41. // PrintErrors prints to os.Stderr the accumulated errors of all
  42. // packages in the import graph rooted at pkgs, dependencies first.
  43. // PrintErrors returns the number of errors printed.
  44. func PrintErrors(pkgs []*Package) int {
  45. var n int
  46. Visit(pkgs, nil, func(pkg *Package) {
  47. for _, err := range pkg.Errors {
  48. fmt.Fprintln(os.Stderr, err)
  49. n++
  50. }
  51. })
  52. return n
  53. }