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