xref: /aosp_15_r20/external/bazelbuild-rules_go/go/tools/gopackagesdriver/packageregistry.go (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
1*9bb1b549SSpandan Das// Copyright 2021 The Bazel Authors. All rights reserved.
2*9bb1b549SSpandan Das//
3*9bb1b549SSpandan Das// Licensed under the Apache License, Version 2.0 (the "License");
4*9bb1b549SSpandan Das// you may not use this file except in compliance with the License.
5*9bb1b549SSpandan Das// You may obtain a copy of the License at
6*9bb1b549SSpandan Das//
7*9bb1b549SSpandan Das//    http://www.apache.org/licenses/LICENSE-2.0
8*9bb1b549SSpandan Das//
9*9bb1b549SSpandan Das// Unless required by applicable law or agreed to in writing, software
10*9bb1b549SSpandan Das// distributed under the License is distributed on an "AS IS" BASIS,
11*9bb1b549SSpandan Das// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9bb1b549SSpandan Das// See the License for the specific language governing permissions and
13*9bb1b549SSpandan Das// limitations under the License.
14*9bb1b549SSpandan Das
15*9bb1b549SSpandan Daspackage main
16*9bb1b549SSpandan Das
17*9bb1b549SSpandan Dasimport (
18*9bb1b549SSpandan Das	"fmt"
19*9bb1b549SSpandan Das	"strings"
20*9bb1b549SSpandan Das)
21*9bb1b549SSpandan Das
22*9bb1b549SSpandan Dastype PackageRegistry struct {
23*9bb1b549SSpandan Das	packagesByID map[string]*FlatPackage
24*9bb1b549SSpandan Das	stdlib       map[string]string
25*9bb1b549SSpandan Das}
26*9bb1b549SSpandan Das
27*9bb1b549SSpandan Dasfunc NewPackageRegistry(pkgs ...*FlatPackage) *PackageRegistry {
28*9bb1b549SSpandan Das	pr := &PackageRegistry{
29*9bb1b549SSpandan Das		packagesByID: map[string]*FlatPackage{},
30*9bb1b549SSpandan Das		stdlib:       map[string]string{},
31*9bb1b549SSpandan Das	}
32*9bb1b549SSpandan Das	pr.Add(pkgs...)
33*9bb1b549SSpandan Das	return pr
34*9bb1b549SSpandan Das}
35*9bb1b549SSpandan Das
36*9bb1b549SSpandan Dasfunc (pr *PackageRegistry) Add(pkgs ...*FlatPackage) *PackageRegistry {
37*9bb1b549SSpandan Das	for _, pkg := range pkgs {
38*9bb1b549SSpandan Das		pr.packagesByID[pkg.ID] = pkg
39*9bb1b549SSpandan Das
40*9bb1b549SSpandan Das		if pkg.IsStdlib() {
41*9bb1b549SSpandan Das			pr.stdlib[pkg.PkgPath] = pkg.ID
42*9bb1b549SSpandan Das		}
43*9bb1b549SSpandan Das	}
44*9bb1b549SSpandan Das	return pr
45*9bb1b549SSpandan Das}
46*9bb1b549SSpandan Das
47*9bb1b549SSpandan Dasfunc (pr *PackageRegistry) ResolvePaths(prf PathResolverFunc) error {
48*9bb1b549SSpandan Das	for _, pkg := range pr.packagesByID {
49*9bb1b549SSpandan Das		pkg.ResolvePaths(prf)
50*9bb1b549SSpandan Das		pkg.FilterFilesForBuildTags()
51*9bb1b549SSpandan Das	}
52*9bb1b549SSpandan Das	return nil
53*9bb1b549SSpandan Das}
54*9bb1b549SSpandan Das
55*9bb1b549SSpandan Das// ResolveImports adds stdlib imports to packages. This is required because
56*9bb1b549SSpandan Das// stdlib packages are not part of the JSON file exports as bazel is unaware of
57*9bb1b549SSpandan Das// them.
58*9bb1b549SSpandan Dasfunc (pr *PackageRegistry) ResolveImports() error {
59*9bb1b549SSpandan Das	resolve := func(importPath string) string {
60*9bb1b549SSpandan Das		if pkgID, ok := pr.stdlib[importPath]; ok {
61*9bb1b549SSpandan Das			return pkgID
62*9bb1b549SSpandan Das		}
63*9bb1b549SSpandan Das
64*9bb1b549SSpandan Das		return ""
65*9bb1b549SSpandan Das	}
66*9bb1b549SSpandan Das
67*9bb1b549SSpandan Das	for _, pkg := range pr.packagesByID {
68*9bb1b549SSpandan Das		if err := pkg.ResolveImports(resolve); err != nil {
69*9bb1b549SSpandan Das			return err
70*9bb1b549SSpandan Das		}
71*9bb1b549SSpandan Das	}
72*9bb1b549SSpandan Das
73*9bb1b549SSpandan Das	return nil
74*9bb1b549SSpandan Das}
75*9bb1b549SSpandan Das
76*9bb1b549SSpandan Dasfunc (pr *PackageRegistry) walk(acc map[string]*FlatPackage, root string) {
77*9bb1b549SSpandan Das	pkg := pr.packagesByID[root]
78*9bb1b549SSpandan Das
79*9bb1b549SSpandan Das	acc[pkg.ID] = pkg
80*9bb1b549SSpandan Das	for _, pkgID := range pkg.Imports {
81*9bb1b549SSpandan Das		if _, ok := acc[pkgID]; !ok {
82*9bb1b549SSpandan Das			pr.walk(acc, pkgID)
83*9bb1b549SSpandan Das		}
84*9bb1b549SSpandan Das	}
85*9bb1b549SSpandan Das}
86*9bb1b549SSpandan Das
87*9bb1b549SSpandan Dasfunc (pr *PackageRegistry) Match(labels []string) ([]string, []*FlatPackage) {
88*9bb1b549SSpandan Das	roots := map[string]struct{}{}
89*9bb1b549SSpandan Das
90*9bb1b549SSpandan Das	for _, label := range labels {
91*9bb1b549SSpandan Das		if !strings.HasPrefix(label, "@") {
92*9bb1b549SSpandan Das			label = fmt.Sprintf("@%s", label)
93*9bb1b549SSpandan Das		}
94*9bb1b549SSpandan Das
95*9bb1b549SSpandan Das		roots[label] = struct{}{}
96*9bb1b549SSpandan Das	}
97*9bb1b549SSpandan Das
98*9bb1b549SSpandan Das	walkedPackages := map[string]*FlatPackage{}
99*9bb1b549SSpandan Das	retRoots := make([]string, 0, len(roots))
100*9bb1b549SSpandan Das	for rootPkg := range roots {
101*9bb1b549SSpandan Das		retRoots = append(retRoots, rootPkg)
102*9bb1b549SSpandan Das		pr.walk(walkedPackages, rootPkg)
103*9bb1b549SSpandan Das	}
104*9bb1b549SSpandan Das
105*9bb1b549SSpandan Das	retPkgs := make([]*FlatPackage, 0, len(walkedPackages))
106*9bb1b549SSpandan Das	for _, pkg := range walkedPackages {
107*9bb1b549SSpandan Das		retPkgs = append(retPkgs, pkg)
108*9bb1b549SSpandan Das	}
109*9bb1b549SSpandan Das
110*9bb1b549SSpandan Das	return retRoots, retPkgs
111*9bb1b549SSpandan Das}
112