Involved Source Files Package emit is plumb's final phase: it turns the resolved plans into the
gofmt-canonical generated file and the -v report. It chooses import aliases,
allocates local names, renders each injector via the plan's instances, and
aggregates cleanup and error handling. It produces text; it makes no wiring
decisions and reports no diagnostics (a malformed render is an invariant
violation and panics).name.goqual.gorender.goreport.go
Package-Level Type Names (total 4, in which 1 is exported)
/* sort exporteds by: | */
Result is the outcome of a successful generation. It is emit's output, handed
back through gen to the caller. Report is the human-readable discovery-and-inference report (the body of
the -v output). It is informational and not contractual. Source is the gofmt-canonical generated Go source.
func File(importPath, packageName string, pkgs []*discover.Package, plans []*solve.Plan, dest *solve.DestInfo) *Result
func go.pact.im/x/plumb/internal/gen.Generate(opts gen.Options, pkgs []*discover.Package) (*Result, error)
qualifier renders go/types types and symbols as Go source, deciding what is
unqualified (the destination package) and what is imported and qualified.
It runs in two modes. In recording mode (built with newRecording) it captures
every package a render would reference, so the import block and aliases can be
computed; the strings it returns in that mode are throwaway. In final mode
(built with newFinal) it returns the chosen qualifier for each package. // path → chosen qualifier (final mode)destPathstring // path → package (recording mode) aliasNames returns the chosen import qualifiers (final mode), so a caller can
reserve them as taken identifiers when allocating local names. objQual renders a package-level object reference (function, variable,
constant), qualified if it lives outside the destination. qualify is the go/types.Qualifier used with types.TypeString. recordedPackages returns the recorded packages sorted by import path. typeString renders t as Go source under this qualifier.
func newFinal(destPath string, alias map[string]string) *qualifier
func newRecording(destPath string) *qualifier
func newAllocator(dest *solve.DestInfo, q *qualifier, lifted map[string]bool) *allocator
func recordPlanPackages(pl *solve.Plan, q *qualifier, dest *solve.DestInfo, lifted map[string]bool)
func renderInstance(in *solve.Instance, q *qualifier, args []string) string
func renderPlan(pl *solve.Plan, q *qualifier, errorsAlias string, dest *solve.DestInfo, lifted map[string]bool) string
func writeTypeArgs(b *strings.Builder, q *qualifier, targs []types.Type)
Package-Level Functions (total 39, in which 1 is exported)
File turns the resolved plans into the gofmt-canonical generated file and the
-v report.
asReceiver parenthesizes a selector receiver when it is a value/pointer bridge.
The bridge renders *T → T as "*x" and T → *T as "&x"; used bare as a
receiver, "*x.M()" / "&x.M()" parse as "*(x.M())" / "&(x.M())", so they must
become "(*x).M()" / "(&x).M()". A plain local name is already a primary
expression and binds the selector correctly.
assignAliases assigns a deterministic qualifier to each imported package,
aliasing on collision with destination identifiers, lifted parameter names,
or another import.
baseName derives a readable local-variable base name from a type.
cleanupBaseName derives a cleanup local's base name from the provider function
that returns it, e.g. OpenConn's teardown becomes openConnCleanup. A cleanup
result only ever comes from a function or method provider, so its Fn is always
set. Naming after the provider (not the value the provider yields) keeps the
cleanup unambiguous even when a provider returns several values.
cleanupStmts renders each cleanup call in run order: a failable cleanup
captures its error in a "cleanupErr" local, a non-failable one is called bare.
It returns the statements and the captured error-local names, in run order.
The error locals live in this branch's scope alone, so they are allocated from
a fresh per-branch allocator and reset across branches.
coerceExpr renders the value/pointer bridge for an argument: &x passes a value
local where a pointer is wanted (every consumer takes the address of the same
local, so they share one instance), *x derefs a pointer where a value is
wanted. As a method receiver these prefixed forms are parenthesized by
asReceiver.
convNeedsParens reports whether a conversion to t must parenthesize the type so
that T(x) is not mis-parsed. T(x) goes wrong two ways: a leading operator (a
pointer *T reads as a dereference, a receive-only <-chan T as a receive), and a
rendered form ending in a result-less func (func()(x) reparses as func() (x),
its result list swallowing the argument). The latter is reachable through slice,
array, map-value, channel, and pointer tails. gofmt rescues neither: it leaves
*T(x) as a dereference and breaks func()-tailed conversions rather than fixing
them. (It does add parens around a top-level func *with* a result, e.g.
func() int(x) → (func() int)(x), so that one case needs no help here.) Every
other target (named/alias/interface/struct/basic types, and composites not
ending in a bare func) renders unambiguously.
endsInResultlessFunc reports whether t's rendered form ends in a result-less
func type, reached directly or through a slice/array/map-value/channel/pointer
element or a func's sole result. (A two-or-more result list renders in
parentheses, which closes the type, so it does not end in a bare func.) A named
or alias type renders as its name, so it is opaque and stops the recursion.
firstWordLen returns the byte length of the prefix lowerCamel lowercases,
which is the identifier's first word. A leading common initialism is the whole
word. Otherwise the word is the leading run of capitals, dropping its final
capital when a lowercase letter follows, since that capital starts the next word.
kindLabel is the provider-kind label for the report. KindSymbol recovers
var-vs-const from the referenced object's dynamic type, since the two share one
kind everywhere else.
leadingInitialism returns the longest common initialism that prefixes s at a
word boundary, or "". A word boundary means the initialism is all of s, or the
rune right after it is uppercase.
lowerCamel lowercases the first word of an identifier while preserving
camelCase: User → user, DB → db, DB2 → db2, HTTPServer → httpServer,
XMLHTTPRequest → xmlHTTPRequest. A leading common initialism is lowered as a
unit. Otherwise the leading run of capitals is lowered, except for its final
capital when a lowercase letter follows it, since that capital begins the next
word.
newFinal returns a qualifier that renders with the chosen per-package alias.
newRecording returns a qualifier that records every package referenced when
rendering, for computing the import block.
planNeedsErrors reports whether the plan's generated code emits errors.Join,
and so must import the errors package. It mirrors the two join sites exactly,
since claiming the import without an emitted Join (or vice versa) breaks the
generated build:
- renderAggregate joins on the success path when two or more cleanups are
failable (a single failable cleanup is returned directly);
- renderUnwind joins the build error with the failable cleanups acquired so
far when a fallible provider fails after at least one was acquired.
plural renders a count with its noun, pluralizing for any count but one:
"1 provider", "2 providers", "0 providers".
recordPlanPackages records, into the recording qualifier q, every package the
generated function will reference. It does so by rendering the plan under q and
discarding the text: the render is the single authoritative enumeration of
every qualified reference (signature, lifted constraints, and each instance's
producing expression), so recording through it means the import block cannot
drift from the emitted body: there is no second enumeration to keep in step.
The errors qualifier is irrelevant while recording (whether errors is imported
is decided separately by planNeedsErrors, and it is written as a literal alias,
never through q), so it is left empty.
renderAggregate renders the single aggregated cleanup returned on success.
renderInstance renders the value-producing expression for one instance: the
provider call or reference, given a qualifier and the already-coerced argument
expressions in input order. It is the single place provider kinds turn into Go
source: solve decides the wiring, emit renders it.
renderLiftedHeader renders a generic injector's type-parameter list
[T constraint, ...] from its lifted free parameters, collapsing an
empty-interface constraint to the bare "any"; qual renders a non-collapsing
constraint. An empty list renders nothing. Both the generated header (via
q.typeString) and the -v report (via its fallback qualifier) route through
here so the two spellings cannot drift.
renderPlan renders one set's injector function.
renderUnwind renders the teardown of already-acquired cleanups on a mid-build
error: newest first, with the build error joined in when cleanups are failable.
reservedIdents returns the identifiers a generated name must not collide with,
common to import-alias assignment and local-name allocation: the predeclared
universe, the destination package's own top-level names, and the lifted
type-parameter names. Keywords are not seeded here: go/token exposes no
enumerable keyword set, so they are rejected by the token.IsKeyword arm of each
collision predicate instead. Each caller augments the result with its own extra
category (set names for aliases, import aliases for locals).
Package-Level Variables (only one, which is unexported)
commonInitialisms are acronyms treated as one unit when lowering an
identifier's first word. This keeps the camelCase boundary after the whole
acronym (HTTPServer becomes httpServer) and stops a leading acronym from
merging with the next one (XMLHTTPRequest becomes xmlHTTPRequest).
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)