// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package importgraph computes the forward and reverse import
// dependency graphs for all packages in a Go workspace.
package importgraph

import (
	"go/build"
	"sync"

	"llvm.org/llgo/third_party/go.tools/go/buildutil"
)

// A Graph is an import dependency graph, either forward or reverse.
//
// The graph maps each node (a package import path) to the set of its
// successors in the graph.  For a forward graph, this is the set of
// imported packages (prerequisites); for a reverse graph, it is the set
// of importing packages (clients).
//
type Graph map[string]map[string]bool

func (g Graph) addEdge(from, to string) {
	edges := g[from]
	if edges == nil {
		edges = make(map[string]bool)
		g[from] = edges
	}
	edges[to] = true
}

// Search returns all the nodes of the graph reachable from
// any of the specified roots, by following edges forwards.
// Relationally, this is the reflexive transitive closure.
func (g Graph) Search(roots ...string) map[string]bool {
	seen := make(map[string]bool)
	var visit func(x string)
	visit = func(x string) {
		if !seen[x] {
			seen[x] = true
			for y := range g[x] {
				visit(y)
			}
		}
	}
	for _, root := range roots {
		visit(root)
	}
	return seen
}

// Builds scans the specified Go workspace and builds the forward and
// reverse import dependency graphs for all its packages.
// It also returns a mapping from import paths to errors for packages
// that could not be loaded.
func Build(ctxt *build.Context) (forward, reverse Graph, errors map[string]error) {
	// The (sole) graph builder goroutine receives a stream of import
	// edges from the package loading goroutine.
	forward = make(Graph)
	reverse = make(Graph)
	edgec := make(chan [2]string)
	go func() {
		for edge := range edgec {
			if edge[1] == "C" {
				continue // "C" is fake
			}
			forward.addEdge(edge[0], edge[1])
			reverse.addEdge(edge[1], edge[0])
		}
	}()

	// The (sole) error goroutine receives a stream of ReadDir and
	// Import errors.
	type pathError struct {
		path string
		err  error
	}
	errorc := make(chan pathError)
	go func() {
		for e := range errorc {
			if errors == nil {
				errors = make(map[string]error)
			}
			errors[e.path] = e.err
		}
	}()

	var wg sync.WaitGroup
	buildutil.ForEachPackage(ctxt, func(path string, err error) {
		if err != nil {
			errorc <- pathError{path, err}
			return
		}
		wg.Add(1)
		// The import goroutines load the metadata for each package.
		go func(path string) {
			defer wg.Done()
			bp, err := ctxt.Import(path, "", 0)
			if _, ok := err.(*build.NoGoError); ok {
				return // empty directory is not an error
			}
			if err != nil {
				errorc <- pathError{path, err}
				return
			}
			for _, imp := range bp.Imports {
				edgec <- [2]string{path, imp}
			}
			for _, imp := range bp.TestImports {
				edgec <- [2]string{path, imp}
			}
			for _, imp := range bp.XTestImports {
				edgec <- [2]string{path, imp}
			}
		}(path)
	})
	wg.Wait()

	close(edgec)
	close(errorc)

	return forward, reverse, errors
}
