gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/golang.org/x/tools/go/packages/visit.go (about)

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