load

package
v3.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package load wraps golang.org/x/tools/go/packages to load the main module and every transitively imported package in one type-checking session (so identity-based checks like types.Implements are valid across package boundaries), and to locate + parse the servo.Build(...) spec call.

Index

Constants

View Source
const BuildTag = "servoinject"

BuildTag is the build constraint that gates the spec file. Loading always activates it, so `servo generate` sees the spec file (read as syntax, never executed) and never the previously generated output for the same injector.

Variables

This section is empty.

Functions

func FileRequiresBuildTag

func FileRequiresBuildTag(file *ast.File, tag string) bool

FileRequiresBuildTag reports whether file carries a build constraint that can only be satisfied when tag is set. Exported so servo-vet can run the identical check without duplicating constraint-parsing logic.

func ImportClosure

func ImportClosure(start []*packages.Package) map[string]bool

ImportClosure returns the import paths transitively reachable from start (inclusive). internal/resolve uses this to scope structural interface search to "packages transitively imported from the roots" rather than every package the candidate scan covers.

func PackagePathOf

func PackagePathOf(t types.Type) (string, bool)

PackagePathOf returns the import path of the package declaring the named type underlying t (unwrapping one level of pointer), or false if t has no declaring package (e.g. a predeclared or anonymous type).

Types

type BindDecl

type BindDecl struct {
	Iface        graph.Key
	IfaceType    types.Type
	Concrete     graph.Key
	ConcreteType types.Type
	Pos          token.Position
}

type Config

type Config struct {
	// Dir is the working directory to load from; "" means the current
	// directory.
	Dir string
	// Pattern is the go/packages pattern to load; "" defaults to "./...".
	Pattern string
}

Config controls where and what to load.

type Loaded

type Loaded struct {
	Fset     *token.FileSet
	All      []*packages.Package // every loaded package, deduplicated — the candidate scan's universe
	ByPath   map[string]*packages.Package
	Roots    []*packages.Package // packages matching the input pattern
	ServoPkg *packages.Package
}

Loaded is every package reachable from Pattern, deduplicated and sharing one type-checking session.

func Load

func Load(cfg Config) (*Loaded, error)

func (*Loaded) NonInjectorErrors

func (l *Loaded) NonInjectorErrors(injectorPkgPaths ...string) error

NonInjectorErrors reports load/type errors in any package other than the given injector package paths. Errors within an injector package itself are deliberately not this function's concern: before the first `servo generate`, that package legitimately fails to compile (main.go references the not-yet-generated New/App), and that is not a reason to refuse to generate — it is the reason to. Variadic so a multi-injector module can exclude every known injector at once: otherwise checking injector B would trip on injector A's pre-generation "undefined: New".

type RootDecl

type RootDecl struct {
	Key  graph.Key
	Type types.Type
	Pos  token.Position
}

type ScopeDecl added in v3.1.0

type ScopeDecl struct {
	Impl      graph.Key
	ImplType  types.Type
	Iface     graph.Key
	IfaceType types.Type

	Linger    time.Duration
	LingerSet bool
	Max       int
	MaxSet    bool

	Pos token.Position
}

ScopeDecl is one servo.Scoped[T, I](...) declaration: the scoped type, the user-declared accessor interface the generated accessor satisfies, and the two policy knobs.

Linger and Max are recorded as "set or not" rather than folded into the defaults here, so a second declaration sharing the same key type can be checked for a *conflicting* value rather than for a merely-absent one.

func (ScopeDecl) EffectiveLinger added in v3.1.0

func (d ScopeDecl) EffectiveLinger() time.Duration

EffectiveLinger and EffectiveMax apply the package defaults for a declaration that omitted the option.

func (ScopeDecl) EffectiveMax added in v3.1.0

func (d ScopeDecl) EffectiveMax() int

type Spec

type Spec struct {
	InjectorPkg *packages.Package
	File        *ast.File
	Pos         token.Position
	Roots       []RootDecl
	Binds       []BindDecl
	Overrides   []BindDecl
	Scopes      []ScopeDecl
}

Spec is the resolved contents of the single servo.Build(...) call: the injector's declared roots and explicit bindings. Root/Bind/Override are read as syntax — nothing here executes them.

func FindSpec

func FindSpec(l *Loaded) (*Spec, error)

FindSpec narrows FindSpecs to exactly one — for commands that inherently operate on a single injector (explain/why/list/graph/doctor) and need the caller to disambiguate with --dir when the scanned scope contains more than one.

func FindSpecs

func FindSpecs(l *Loaded) ([]*Spec, error)

FindSpecs locates every servo.Build(...) call across the main module's packages and extracts each one's Root/Bind/Override arguments. Multiple specs in *different* packages is a normal multi-injector module — a monorepo with cmd/api, cmd/worker, cmd/migrator each wiring their own graph — and callers that can act on all of them (generate, check) should. Multiple specs in the *same* package is still an error: that package could only ever have one generated file, so two Build calls there are genuinely ambiguous, not a second injector.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL