MCPcopy
hub / github.com/golang/tools / TestBuildPackageGraph

Function TestBuildPackageGraph

gopls/internal/cache/typerefs/pkgrefs_test.go:66–198  ·  view source on GitHub ↗

TestBuildPackageGraph tests the BuildPackageGraph constructor, which uses the reference analysis of the Refs function to build a graph of relationships between packages. It simulates the operation of gopls at startup: packages are loaded via go/packages, and their syntax+metadata analyzed to determ

(t *testing.T)

Source from the content-addressed store, hash-verified

64// - verify toggles the verification w.r.t. the load graph (which may be
65// prohibitively expensive with large queries).
66func TestBuildPackageGraph(t *testing.T) {
67 if testing.Short() {
68 t.Skip("skipping with -short: loading the packages can take a long time with a cold cache")
69 }
70 testenv.NeedsGoBuild(t) // for go/packages
71
72 t0 := time.Now()
73 exports, meta, err := loadPackages(*query, *verify)
74 if err != nil {
75 t.Fatalf("loading failed: %v", err)
76 }
77 t.Logf("loaded %d packages in %v", len(exports), time.Since(t0))
78
79 ctx := context.Background()
80 var ids []PackageID
81 for id := range exports {
82 ids = append(ids, id)
83 }
84 slices.Sort(ids)
85
86 t0 = time.Now()
87 g, err := BuildPackageGraph(ctx, meta, ids, newParser().parse)
88 if err != nil {
89 t.Fatal(err)
90 }
91 t.Logf("building package graph took %v", time.Since(t0))
92
93 // Collect information about the edges between packages for later analysis.
94 //
95 // We compare the following package graphs:
96 // - the imports graph: edges are transitive imports
97 // - the reaches graph: edges are reachability relationships through syntax
98 // of imports (as defined in the package doc)
99 // - the loads graph: edges are packages loaded through the export data of
100 // imports
101 //
102 // By definition, loads < reaches < imports.
103 type edgeSet map[PackageID]map[PackageID]bool
104 var (
105 imports = make(edgeSet) // A imports B transitively
106 importedBy = make(edgeSet) // A is imported by B transitively
107 reaches = make(edgeSet) // A reaches B through top-level declaration syntax
108 reachedBy = make(edgeSet) // A is reached by B through top-level declaration syntax
109 loads = make(edgeSet) // A loads B through export data of its direct dependencies
110 loadedBy = make(edgeSet) // A is loaded by B through export data of B's direct dependencies
111 )
112 recordEdge := func(from, to PackageID, fwd, rev edgeSet) {
113 if fwd[from] == nil {
114 fwd[from] = make(map[PackageID]bool)
115 }
116 fwd[from][to] = true
117 if rev[to] == nil {
118 rev[to] = make(map[PackageID]bool)
119 }
120 rev[to][from] = true
121 }
122
123 exportedPackages := make(map[PackageID]*types.Package)

Callers

nothing calls this directly

Calls 15

NeedsGoBuildFunction · 0.92
appendFunction · 0.85
BuildPackageGraphFunction · 0.85
newParserFunction · 0.85
importFromExportDataFunction · 0.85
PackagePathTypeAlias · 0.85
ElemsMethod · 0.80
PackageIDMethod · 0.80
PathMethod · 0.80
VerboseMethod · 0.80
PrintlnMethod · 0.80
loadPackagesFunction · 0.70

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…