gent
-- import "github.com/metaleap/go-gent"
Package gent offers a Golang code-gen toolkit; philosophy being:
- "your package's type-defs. your pluggable custom code-gen logics (+ many
built-in ones), tuned via your struct-field tags. one
go generatecall."
The design idea is that your codegen programs remains your own main packages
written by you, but importing gent keeps them short and high-level: fast and
simple to write, iterate, maintain over time. Furthermore (unlike unwieldy
config-file-formats or 100s-of-cmd-args) this approach grants Turing-complete
control over fine-tuning the code-gen flow to only generate what's truly needed,
rather than "every possible func for every possible type-def", to minimize both
codegen and your compilation times.
Focus at the beginning is strictly on generating funcs and methods for a
package's existing type-defs, not generating type-defs such as structs.
For building the AST of the to-be-emitted Go source file:
-
gentrelies on mygithub.com/go-leap/dev/go/genpackage -
and so do the built-in code-gens under
github.com/metaleap/go-gent/gents/*, -
but your custom
gent.IGentimplementers are free to prefer other approaches (such astext/templateorgithub.com/dave/jenniferor hard-coded string-building or other) by having theirGenerateTopLevelDeclsimplementation return agithub.com/go-leap/dev/go/gen.SynRaw-typed byte-array.
Very WIP: more comprehensive readme / package docs to come.
Usage
var (
CodeGenCommentNotice Str = "DO NOT EDIT: code generated with `{progName}` using `github.com/metaleap/go-gent`"
CodeGenCommentProgName = filepath.Base(os.Args[0])
Defaults struct {
CtxOpt CtxOpts
}
OnBeforeLoad func(*Pkg)
)type Ctx
type Ctx struct {
// options pertaining to this `Ctx`
Opt CtxOpts
// strictly read-only
Pkg *Pkg
}Ctx is a codegen-time context during a Pkg.RunGents call and is passed to
IGent.GenerateTopLevelDecls.
func (*Ctx) DeclsGeneratedSoFar
func (this *Ctx) DeclsGeneratedSoFar(maybeGent IGent, maybeType *Type) (matches []udevgogen.Syns)DeclsGeneratedSoFar collects and returns all results of
IGent.GenerateTopLevelDecls performed so far by this Ctx, filtered
optionally by IGent and/or by Type.
func (*Ctx) Import
func (this *Ctx) Import(pkgImportPath string) (pkgImportName udevgogen.PkgName)Import returns the pkgImportName for the specified pkgImportPath. Eg.
Import("encoding/json") might return pkg__encoding_json and more
importantly, the import will be properly emitted (only if any of the import's
uses get emitted) at code-gen time. Import is a Ctx-local wrapper of the
github.com/go-leap/dev/go/gen.PkgImports.Ensure method.
type CtxOpts
type CtxOpts struct {
// For Defaults.CtxOpts, initialized from env-var
// `GOGENT_NOGOFMT` if `strconv.ParseBool`able.
NoGoFmt bool
// For Defaults.CtxOpts, initialized from env-var
// `GOGENT_EMITNOOPS` if `strconv.ParseBool`able.
EmitNoOpFuncBodies bool
// If set, can be used to prevent running of the given
// (or any) `IGent` on the given (or any) `*Type`.
// See also `IGent.Opt().MayRunForType`.
MayGentRunForType func(IGent, *Type) bool
}CtxOpts wraps Ctx options.
type Gents
type Gents []IGentGents is a slice if IGents.
func (Gents) EnableOrDisableAll
func (this Gents) EnableOrDisableAll(enabled bool)EnableOrDisableAll sets all IGent.Opt().Disabled fields to !enabled.
func (Gents) EnableOrDisableAllVariantsAndOptionals
func (this Gents) EnableOrDisableAllVariantsAndOptionals(enabled bool)EnableOrDisableAllVariantsAndOptionals calls the same-named method on all
IGents in this.
func (Gents) With
func (this Gents) With(gents ...Gents) (merged Gents)With merges all IGents in this with all those in gents into merged.
type IGent
type IGent interface {
// must never return `nil` (easiest impl is to embed `Opts`)
Opt() *Opts
// implemented as a no-op by `Opts`, to be
// overridden by implementations as desired
EnableOrDisableAllVariantsAndOptionals(bool)
// may read from but never mutate its args.
// expected to generate preferentially funcs / methods
// instead of top-level const / var / type decls
GenerateTopLevelDecls(*Ctx, *Type) udevgogen.Syns
}IGent is the interface implemented by individual code-gens.
type Opts
type Opts struct {
Disabled bool
EmitCommented bool
// not used by `go-gent`, but could be handy for callers
Name string
// tested right after `Disabled` and before the below checks.
// should typically be false for most `Gent`s as the design assumes
// generation of methods, but it's for the occasional need to generate
// non-method `func`s related to certain type-alias declarations
RunOnlyForTypeAliases bool
RunOnlyOnceWithoutAnyType bool
// if-and-only-if these are set, they're checked
// before `MayRunForType` (but after `Disabled`)
RunNeverForTypes, RunOnlyForTypes struct {
Named []string
Satisfying func(*Ctx, *Type) bool
}
// If set, can be used to prevent running of
// this `IGent` on the given (or any) `*Type`.
// See also `CtxOpts.MayGentRunForType`.
MayRunForType func(*Ctx, *Type) bool
}Opts related to a single IGent, and designed for embedding.
func (*Opts) EnableOrDisableAllVariantsAndOptionals
func (this *Opts) EnableOrDisableAllVariantsAndOptionals(bool)EnableOrDisableAllVariantsAndOptionals implements IGent but with a no-op, to
be overridden by Opts-embedders as desired.
To disable or enable an IGent itself, set Opts.Disabled.
func (*Opts) Opt
func (this *Opts) Opt() *OptsOpt implements IGent.Opt() for Opts embedders.
type Pkg
type Pkg struct {
Name string
ImportPath string
DirPath string
GoFileNames []string
Loaded struct {
Prog *loader.Program
Info *loader.PackageInfo
}
Types Types
CodeGen struct {
OutputFileName string
}
}func LoadPkg
func LoadPkg(pkgImportPathOrFileSystemPath string, outputFileName string, dontLoadButJustInitUsingPkgNameInstead string) (this *Pkg, err error)func MustLoadPkg
func MustLoadPkg(pkgImportPathOrFileSystemPath string, outputFileName string) *Pkgfunc (*Pkg) DirName
func (this *Pkg) DirName() stringfunc (*Pkg) RunGents
func (this *Pkg) RunGents(maybeCtxOpts *CtxOpts, gents Gents) (src []byte, stats *Stats, err error)RunGents instructs the given gents to generate code for this Pkg.
type Pkgs
type Pkgs map[string]*Pkgfunc LoadPkgs
func LoadPkgs(pkgPathsWithOutputFileNames map[string]string) (Pkgs, error)func MustLoadPkgs
func MustLoadPkgs(pkgPathsWithOutputFileNames map[string]string) Pkgsfunc (Pkgs) MustRunGentsAndGenerateOutputFiles
func (this Pkgs) MustRunGentsAndGenerateOutputFiles(maybeCtxOpts *CtxOpts, gents Gents) (timeTakenTotal time.Duration, statsPerPkg map[*Pkg]*Stats)MustRunGentsAndGenerateOutputFiles calls RunGents on the Pkgs in this.
func (Pkgs) RunGentsAndGenerateOutputFiles
func (this Pkgs) RunGentsAndGenerateOutputFiles(maybeCtxOpts *CtxOpts, gents Gents) (timeTakenTotal time.Duration, statsPerPkg map[*Pkg]*Stats, errs map[*Pkg]error)RunGentsAndGenerateOutputFiles calls RunGents on the Pkgs in this.
type Rename
type Rename func(*Ctx, *Type, string) stringtype Stats
type Stats struct {
DurationOf struct {
Constructing time.Duration
Emitting time.Duration
Formatting time.Duration
Everything time.Duration
}
}type Str
type Str stringfunc (Str) With
func (this Str) With(placeholderNamesAndValues ...string) stringtype Type
type Type struct {
Pkg *Pkg
Name string
Alias bool
// Expr is whatever underlying-type this type-decl represents, that is:
// of the original `type foo bar` or `type foo = bar` declaration,
// this `Type` is the `foo` identity and its `Expr` captures the `bar`.
Expr struct {
// original AST's type-decl's `Expr` (stripped of any&all `ParenExpr`s)
AstExpr ast.Expr
// a code-gen `TypeRef` to this `Type` decl's underlying-type
GenRef *udevgogen.TypeRef
}
// commonly useful code-gen values prepared for this `Type`
G struct {
// type-ref to this `Type`
T *udevgogen.TypeRef
// type-ref to pointer-to-`Type` (think 'ª for addr')
Tª *udevgogen.TypeRef
// type-ref to slice-of-`Type`
Ts *udevgogen.TypeRef
// type-ref to slice-of-pointers-to-`Type`
Tªs *udevgogen.TypeRef
// Name="this" and Type=.G.T
This udevgogen.NamedTyped
// Name="this" and Type=.G.Tª
Thisª udevgogen.NamedTyped
}
Enumish struct {
// expected to be builtin prim-type such as uint8, int64, int --- cases of additional indirections to be handled when they occur in practice
BaseType string
ConstNames []string
}
}func (*Type) IsArray
func (this *Type) IsArray() boolfunc (*Type) IsEnumish
func (this *Type) IsEnumish() boolfunc (*Type) IsSlice
func (this *Type) IsSlice() boolfunc (*Type) IsSliceOrArray
func (this *Type) IsSliceOrArray() booltype Types
type Types []*Typefunc (*Types) Add
func (this *Types) Add(t *Type)func (Types) Named
func (this Types) Named(name string) *Typetype Variant
type Variant struct {
Add bool
Name string
DocComment Str
}func (*Variant) NameWith
func (this *Variant) NameWith(placeholderNamesAndValues ...string) stringtype Variation
type Variation struct {
Disabled bool
DocComment Str
Name string
}func (*Variation) NameWith
func (this *Variation) NameWith(placeholderNamesAndValues ...string) string