Documentation ¶
Overview ¶
Package enumgen provides functions for generating enum methods for enum types.
Index ¶
- Variables
- func Generate(cfg *Config) error
- func GeneratePkgs(cfg *Config, pkgs []*packages.Package) error
- func PackageModes() packages.LoadMode
- func ParsePackages(cfg *Config) ([]*packages.Package, error)
- type ByValue
- type Config
- type Generator
- func (g *Generator) AddValueAndScanMethod(typ *Type)
- func (g *Generator) BuildBasicMethods(values []Value, typ *Type)
- func (g *Generator) BuildBitFlagMethods(runs []Value, typ *Type)
- func (g *Generator) BuildGQLMethods(runs []Value, typ *Type)
- func (g *Generator) BuildString(values []Value, typ *Type)
- func (g *Generator) BuildTextMethods(runs []Value, typ *Type)
- func (g *Generator) ExecTmpl(t *template.Template, typ *Type)
- func (g *Generator) FindEnumTypes() error
- func (g *Generator) GenDecl(node ast.Node, file *ast.File, typ *Type) ([]Value, bool, error)
- func (g *Generator) Generate() (bool, error)
- func (g *Generator) InspectForType(n ast.Node) (bool, error)
- func (g *Generator) PrefixValueNames(values []Value, c *Config)
- func (g *Generator) PrintDescMap(values []Value, typ *Type)
- func (g *Generator) PrintHeader()
- func (g *Generator) PrintValueMap(values []Value, typ *Type)
- func (g *Generator) Printf(format string, args ...any)
- func (g *Generator) TransformValueNames(values []Value, c *Config) error
- func (g *Generator) TrimValueNames(values []Value, c *Config)
- func (g *Generator) Write() error
- type Type
- type Value
Constants ¶
This section is empty.
Variables ¶
var AllowedEnumTypes = map[string]bool{"int": true, "int64": true, "int32": true, "int16": true, "int8": true, "uint": true, "uint64": true, "uint32": true, "uint16": true, "uint8": true}
AllowedEnumTypes are the types that can be used for enums that are not bit flags (bit flags can only be int64s). It is stored as a map for quick and convenient access.
var DescMethodTmpl = template.Must(template.New("DescMethod").Parse(`// Desc returns the description of the {{.Name}} value.
func (i {{.Name}}) Desc() string {
{{- if eq .Extends ""}} return enums.Desc(i, _{{.Name}}DescMap)
{{- else}} return enums.DescExtended[{{.Name}}, {{.Extends}}](i, _{{.Name}}DescMap) {{end}} }
`))
var GQLMethodsTmpl = template.Must(template.New("GQLMethods").Parse(`
// MarshalGQL implements the [graphql.Marshaler] interface.
func (i {{.Name}}) MarshalGQL(w io.Writer) { w.Write([]byte(strconv.Quote(i.String()))) }
// UnmarshalGQL implements the [graphql.Unmarshaler] interface.
func (i *{{.Name}}) UnmarshalGQL(value any) error { return enums.Scan(i, value, "{{.Name}}") }
`))
var HasFlagMethodTmpl = template.Must(template.New("HasFlagMethod").Parse(
`// HasFlag returns whether these bit flags have the given bit flag set.
func (i {{.Name}}) HasFlag(f enums.BitFlag) bool { return enums.HasFlag((*int64)(&i), f) }
`))
var Int64MethodTmpl = template.Must(template.New("Int64Method").Parse(
`// Int64 returns the {{.Name}} value as an int64.
func (i {{.Name}}) Int64() int64 { return int64(i) }
`))
var IsValidMethodMapTmpl = template.Must(template.New("IsValidMethodMap").Parse(
`// IsValid returns whether the value is a valid option for type {{.Name}}.
func (i {{.Name}}) IsValid() bool { _, ok := _{{.Name}}Map[i]; return ok
{{- if ne .Extends ""}} || {{.Extends}}(i).IsValid() {{end}} }
`))
var NConstantTmpl = template.Must(template.New("StringNConstant").Parse(
`//{{.Name}}N is the highest valid value for type {{.Name}}, plus one.
const {{.Name}}N {{.Name}} = {{.MaxValueP1}}
`))
var ScanMethodTmpl = template.Must(template.New("ScanMethod").Parse(
`// Scan implements the [sql.Scanner] interface.
func (i *{{.Name}}) Scan(value any) error { return enums.Scan(i, value, "{{.Name}}") }
`))
var SetFlagMethodTmpl = template.Must(template.New("SetFlagMethod").Parse(
`// SetFlag sets the value of the given flags in these flags to the given value.
func (i *{{.Name}}) SetFlag(on bool, f ...enums.BitFlag) { enums.SetFlag((*int64)(i), on, f...) }
`))
var SetInt64MethodTmpl = template.Must(template.New("SetInt64Method").Parse(
`// SetInt64 sets the {{.Name}} value from an int64.
func (i *{{.Name}}) SetInt64(in int64) { *i = {{.Name}}(in) }
`))
var SetStringMethodBitFlagTmpl = template.Must(template.New("SetStringMethodBitFlag").Parse(
`// SetString sets the {{.Name}} value from its string representation,
// and returns an error if the string is invalid.
func (i *{{.Name}}) SetString(s string) error { *i = 0; return i.SetStringOr(s) }
`))
var SetStringMethodTmpl = template.Must(template.New("SetStringMethod").Parse(
`// SetString sets the {{.Name}} value from its string representation,
// and returns an error if the string is invalid.
func (i *{{.Name}}) SetString(s string) error {
{{- if eq .Extends ""}} return enums.SetString{{if .Config.AcceptLower}}Lower{{end}}(i, s, _{{.Name}}ValueMap, "{{.Name}}")
{{- else}} return enums.SetString{{if .Config.AcceptLower}}Lower{{end}}Extended(i, (*{{.Extends}})(i), s, _{{.Name}}ValueMap) {{end}} }
`))
var SetStringOrMethodBitFlagTmpl = template.Must(template.New("SetStringOrMethodBitFlag").Parse(
`// SetStringOr sets the {{.Name}} value from its string representation
// while preserving any bit flags already set, and returns an
// error if the string is invalid.
func (i *{{.Name}}) SetStringOr(s string) error {
{{- if eq .Extends ""}} return enums.SetStringOr{{if .Config.AcceptLower}}Lower{{end}}(i, s, _{{.Name}}ValueMap, "{{.Name}}")
{{- else}} return enums.SetStringOr{{if .Config.AcceptLower}}Lower{{end}}Extended(i, (*{{.Extends}})(i), s, _{{.Name}}ValueMap) {{end}} }
`))
var StringMethodBitFlagTmpl = template.Must(template.New("StringMethodBitFlag").Parse(
`// String returns the string representation of this {{.Name}} value.
func (i {{.Name}}) String() string {
{{- if eq .Extends ""}} return enums.BitFlagString(i, _{{.Name}}Values)
{{- else}} return enums.BitFlagStringExtended(i, _{{.Name}}Values, {{.Extends}}Values()) {{end}} }
`))
var StringMethodMapTmpl = template.Must(template.New("StringMethodMap").Parse(
`{{if .IsBitFlag}}
// BitIndexString returns the string representation of this {{.Name}} value
// if it is a bit index value (typically an enum constant), and
// not an actual bit flag value.
{{- else}}
// String returns the string representation of this {{.Name}} value.
{{- end}}
func (i {{.Name}}) {{if .IsBitFlag}} BitIndexString {{else}} String {{end}} () string { return enums.
{{- if eq .Extends ""}}String {{else -}} {{if .IsBitFlag -}} BitIndexStringExtended {{else -}} StringExtended {{- end}}[{{.Name}}, {{.Extends}}]{{- end}}(i, _{{.Name}}Map) }
`))
var TextMethodsTmpl = template.Must(template.New("TextMethods").Parse(
`
// MarshalText implements the [encoding.TextMarshaler] interface.
func (i {{.Name}}) MarshalText() ([]byte, error) { return []byte(i.String()), nil }
// UnmarshalText implements the [encoding.TextUnmarshaler] interface.
func (i *{{.Name}}) UnmarshalText(text []byte) error { return enums.UnmarshalText(i, text, "{{.Name}}") }
`))
var ValueMethodTmpl = template.Must(template.New("ValueMethod").Parse(
`// Value implements the [driver.Valuer] interface.
func (i {{.Name}}) Value() (driver.Value, error) { return i.String(), nil }
`))
var ValuesGlobalTmpl = template.Must(template.New("ValuesGlobal").Parse(
`// {{.Name}}Values returns all possible values for the type {{.Name}}.
func {{.Name}}Values() []{{.Name}} {
{{- if eq .Extends ""}} return _{{.Name}}Values
{{- else}} return enums.ValuesGlobalExtended(_{{.Name}}Values, {{.Extends}}Values())
{{- end}} }
`))
var ValuesMethodTmpl = template.Must(template.New("ValuesMethod").Parse(
`// Values returns all possible values for the type {{.Name}}.
func (i {{.Name}}) Values() []enums.Enum {
{{- if eq .Extends ""}} return enums.Values(_{{.Name}}Values)
{{- else}} return enums.ValuesExtended(_{{.Name}}Values, {{.Extends}}Values())
{{- end}} }
`))
Functions ¶
func Generate ¶
Generate generates enum methods, using the configuration information, loading the packages from the configuration source directory, and writing the result to the configuration output file.
It is a simple entry point to enumgen that does all of the steps; for more specific functionality, create a new Generator with NewGenerator and call methods on it.
func GeneratePkgs ¶
GeneratePkgs generates enum methods using the given configuration object and packages parsed from the configuration source directory, and writes the result to the config output file. It is a simple entry point to enumgen that does all of the steps; for more specific functionality, create a new Generator with NewGenerator and call methods on it.
func PackageModes ¶
PackageModes returns the package load modes needed for this generator
Types ¶
type ByValue ¶
type ByValue []Value
ByValue is a sorting method that sorts the constants into increasing order. We take care in the Less method to sort in signed or unsigned order, as appropriate.
type Config ¶
type Config struct { // the source directory to run enumgen on (can be set to multiple through paths like ./...) Dir string `default:"." posarg:"0" required:"-"` // the output file location relative to the package on which enumgen is being called Output string `default:"enumgen.go"` // if specified, the enum item transformation method (upper, lower, snake, SNAKE, kebab, KEBAB, // camel, lower-camel, title, sentence, first, first-upper, or first-lower) Transform string // if specified, a comma-separated list of prefixes to trim from each item TrimPrefix string // if specified, the prefix to add to each item AddPrefix string // whether to use line comment text as printed text when present LineComment bool // whether to accept lowercase versions of enum names in SetString AcceptLower bool // whether to generate a method returning whether a value is // a valid option for its enum type; this must also be set for // any base enum type being extended IsValid bool // whether to generate text marshaling methods Text bool `default:"true"` // whether to generate methods that implement the SQL Scanner and Valuer interfaces SQL bool // whether to generate GraphQL marshaling methods for gqlgen GQL bool // whether to allow enums to extend other enums; this should be on in almost all circumstances, // but can be turned off for specific enum types that extend non-enum types Extend bool `default:"true"` }
Config contains the configuration information used by enumgen
type Generator ¶
type Generator struct { Config *Config // The configuration information Buf bytes.Buffer // The accumulated output. Pkgs []*packages.Package // The packages we are scanning. Pkg *packages.Package // The packages we are currently on. Types []*Type // The enum types }
Generator holds the state of the generator. It is primarily used to buffer the output.
func NewGenerator ¶
NewGenerator returns a new generator with the given configuration information and parsed packages.
func (*Generator) AddValueAndScanMethod ¶
func (*Generator) BuildBasicMethods ¶
BuildBasicMethods builds methods common to all types, like Desc and SetString.
func (*Generator) BuildBitFlagMethods ¶
BuildBitFlagMethods builds methods specific to bit flag types.
func (*Generator) BuildGQLMethods ¶
func (*Generator) BuildString ¶
BuildString builds the string function using a map access approach.
func (*Generator) BuildTextMethods ¶
func (*Generator) ExecTmpl ¶
ExecTmpl executes the given template with the given type and writes the result to [Generator.Buf]. It fatally logs any error. All enumgen templates take a Type as their data.
func (*Generator) FindEnumTypes ¶
FindEnumTypes goes through all of the types in the package and finds all integer (signed or unsigned) types labeled with enums:enum or enums:bitflag. It stores the resulting types in [Generator.Types].
func (*Generator) GenDecl ¶
GenDecl processes one declaration clause. It returns whether the AST inspector should continue, and an error if there is one. It should only be called in ast.Inspect.
func (*Generator) Generate ¶
Generate produces the enum methods for the types stored in [Generator.Types] and stores them in [Generator.Buf]. It returns whether there were any enum types to generate methods for, and any error that occurred.
func (*Generator) InspectForType ¶
InspectForType looks at the given AST node and adds it to [Generator.Types] if it is marked with an appropriate comment directive. It returns whether the AST inspector should continue, and an error if there is one. It should only be called in ast.Inspect.
func (*Generator) PrefixValueNames ¶
PrefixValueNames adds the prefix specified in [Config.AddPrefix] to each name of the given values.
func (*Generator) PrintDescMap ¶
PrintDescMap prints the map of values to descriptions
func (*Generator) PrintHeader ¶
func (g *Generator) PrintHeader()
PrintHeader prints the header and package clause to the accumulated output
func (*Generator) PrintValueMap ¶
PrintValueMap prints the map between name and value
func (*Generator) Printf ¶
Printf prints the formatted string to the accumulated output in [Generator.Buf]
func (*Generator) TransformValueNames ¶
TransformValueNames transforms the names of the given values according to the transform method specified in [Config.Transform]
func (*Generator) TrimValueNames ¶
TrimValueNames removes the prefixes specified in [Config.TrimPrefix] from each name of the given values.
type Type ¶
type Type struct { Name string // The name of the type Type *ast.TypeSpec // The standard AST type value IsBitFlag bool // Whether the type is a bit flag type Extends string // The type that this type extends, if any ("" if it doesn't extend) MaxValueP1 int64 // the highest defined value for the type, plus one Config *Config // Configuration information set in the comment directive for the type; is initialized to generator config info first }
Type represents a parsed enum type.
type Value ¶
type Value struct { OriginalName string // The name of the constant before transformation Name string // The name of the constant after transformation (i.e. camel case => snake case) Desc string // The comment description of the constant // The Value is stored as a bit pattern alone. The boolean tells us // whether to interpret it as an int64 or a uint64; the only place // this matters is when sorting. // Much of the time the str field is all we need; it is printed // by Value.String. Value int64 Signed bool // Whether the constant is a signed type. Str string // The string representation given by the "go/constant" package. }
Value represents a declared constant.
func SortValues ¶
SortValues sorts the values and ensures there are no duplicates. The input slice is known to be non-empty.