blob: f6909878a8a145efdc08b4c1111ac77fad0c5503 [file] [log] [blame]
// Copyright 2025 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 stdlib
// This file provides the API for the import graph of the standard library.
//
// Be aware that the compiler-generated code for every package
// implicitly depends on package "runtime" and a handful of others
// (see runtimePkgs in GOROOT/src/cmd/internal/objabi/pkgspecial.go).
import (
"encoding/binary"
"iter"
"slices"
"strings"
)
// Imports returns the sequence of packages directly imported by the
// named standard packages, in name order.
// The imports of an unknown package are the empty set.
//
// The graph is built into the application and may differ from the
// graph in the Go source tree being analyzed by the application.
func Imports(pkgs ...string) iter.Seq[string] {
return func(yield func(string) bool) {
for _, pkg := range pkgs {
if i, ok := find(pkg); ok {
var depIndex uint64
for data := []byte(deps[i].deps); len(data) > 0; {
delta, n := binary.Uvarint(data)
depIndex += delta
if !yield(deps[depIndex].name) {
return
}
data = data[n:]
}
}
}
}
}
// Dependencies returns the set of all dependencies of the named
// standard packages, including the initial package,
// in a deterministic topological order.
// The dependencies of an unknown package are the empty set.
//
// The graph is built into the application and may differ from the
// graph in the Go source tree being analyzed by the application.
func Dependencies(pkgs ...string) iter.Seq[string] {
return func(yield func(string) bool) {
for _, pkg := range pkgs {
if i, ok := find(pkg); ok {
var seen [1 + len(deps)/8]byte // bit set of seen packages
var visit func(i int) bool
visit = func(i int) bool {
bit := byte(1) << (i % 8)
if seen[i/8]&bit == 0 {
seen[i/8] |= bit
var depIndex uint64
for data := []byte(deps[i].deps); len(data) > 0; {
delta, n := binary.Uvarint(data)
depIndex += delta
if !visit(int(depIndex)) {
return false
}
data = data[n:]
}
if !yield(deps[i].name) {
return false
}
}
return true
}
if !visit(i) {
return
}
}
}
}
}
// find returns the index of pkg in the deps table.
func find(pkg string) (int, bool) {
return slices.BinarySearchFunc(deps[:], pkg, func(p pkginfo, n string) int {
return strings.Compare(p.name, n)
})
}