blob: 5e1de270cbc1813cbc163ce981b8fe2ec234198b [file] [log] [blame] [edit]
// Copyright 2024 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 loader loads Go packages.
package loader
import (
"context"
"fmt"
"go/ast"
"go/token"
"go/types"
"strings"
)
// Package represents a loaded Go package.
type Package struct {
Files []*File // Files in the package.
Fileset *token.FileSet // For translating between positions and locations in files.
TypeInfo *types.Info // Type information for the package (e.g. object identity, identifier uses/declarations, expression types).
TypePkg *types.Package // Describes the package (e.g. import objects, package scope).
}
func (p Package) String() string {
var paths []string
for _, f := range p.Files {
paths = append(paths, f.Path)
}
return fmt.Sprintf("Go Package %s with files:\n\t%s", p.TypePkg.Path(), strings.Join(paths, "\n\t"))
}
// File represents a single file in a loaded package.
type File struct {
// Parsed file.
AST *ast.File
Path string
// For go_test targets, this field indicates whether the file belongs to the
// test code itself (one or more _test.go files), or whether the file
// belongs to the package-under-test (via the go_test target’s library
// attribute).
//
// For other targets (go_binary or go_library), this field is always false.
LibraryUnderTest bool
// Source code from the file.
Code string
// True if the file was generated (go_embed_data, genrule, etc.).
Generated bool
}
// Target represents a package to be loaded. It is identified by the opaque ID
// field, which is interpreted by the loader (which, in turn, delegates to the
// gopackagesdriver).
type Target struct {
// ID is an opaque identifier for the package when using the packages loader.
ID string
// Testonly indicates that this package should be considered test code. This
// attribute needs to be passed in because go/packages does not have the
// concept of test only code, only Blaze does.
Testonly bool
LibrarySrcs map[string]bool
}
// LoadResult represents the result of loading an individual target. The Target
// field is always set. If something went wrong, Err is non-nil and Package is
// nil. Otherwise, Err is nil and Package is non-nil.
type LoadResult struct {
Target *Target
Package *Package
Err error
}
// Loader loads Go packages.
type Loader interface {
// LoadPackages loads a batch of Go packages.
//
// The method does not return a slice of results, but instead writes each
// result to the specified result channel as the result arrives. This allows
// for concurrency with loaders that support it, like the Compilations
// Bigtable loader (processing results while the load is still ongoing).
LoadPackages(context.Context, []*Target, chan LoadResult)
Close(context.Context) error
}
// LoadOne is a convenience function that loads precisely one target, saving the
// caller the mechanics of having to work with a batch of targets.
func LoadOne(ctx context.Context, l Loader, t *Target) (*Package, error) {
results := make(chan LoadResult, 1)
l.LoadPackages(context.Background(), []*Target{t}, results)
res := <-results
return res.Package, res.Err
}