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