gtigen

package
v0.0.9 Latest Latest
Warning

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

Go to latest
Published: Mar 20, 2024 License: BSD-3-Clause Imports: 17 Imported by: 0

Documentation

Overview

Package gtigen provides the generation of general purpose type information for Go types, methods, functions and variables

Index

Constants

This section is empty.

Variables

View Source
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.

View Source
var FuncTmpl = template.Must(template.New("Func").Parse(
	`
	var _ = gti.AddFunc(&gti.Func
		{{- printf "%#v" . -}}
	)
	`))

FuncTmpl is the template for gti.Func declarations. It takes a *gti.Func as its value.

View Source
var SetterMethodsTmpl = template.Must(template.New("SetterMethods").
	Funcs(template.FuncMap{
		"SetterFields": SetterFields,
		"ToCamel":      strcase.ToCamel,
		"SetterType":   SetterType,
		"DocToComment": DocToComment,
	}).Parse(
	`
	{{$typ := .}}
	{{range (SetterFields .)}}
	// Set{{ToCamel .Name}} sets the [{{$typ.LocalName}}.{{.Name}}] {{- if ne .Doc ""}}:{{end}}
	{{DocToComment .Doc}}
	func (t *{{$typ.LocalName}}) Set{{ToCamel .Name}}(v {{SetterType . $typ}}) *{{$typ.LocalName}} { t.{{.Name}} = v; return t }
	{{end}}
`))

SetterMethodsTmpl is the template for setter methods for a type. It takes a *Type as its value.

View Source
var TypeTmpl = template.Must(template.New("Type").
	Funcs(template.FuncMap{
		"GtiTypeOf": GtiTypeOf,
	}).Parse(
	`
	{{if .Config.TypeVar}} // {{.LocalName}}Type is the [gti.Type] for [{{.LocalName}}]
	var {{.LocalName}}Type {{else}} var _ {{end}} = gti.AddType(&gti.Type
		{{- $typ := GtiTypeOf . -}}
		{{- printf "%#v" $typ -}}
	)
	`))

TypeTmpl is the template for gti.Type declarations. It takes a *Type as its value.

Functions

func DocToComment

func DocToComment(doc string) string

DocToComment converts the given doc string to an appropriate comment string.

func FullName

func FullName(pkg *packages.Package, name string) string

FullName returns the fully qualified name of an identifier in the given package with the given name.

func Generate

func Generate(cfg *Config) error

Generate generates gti type info, 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 gtigen that does all of the steps; for more specific functionality, create a new Generator with NewGenerator and call methods on it.

func GeneratePkgs

func GeneratePkgs(cfg *Config, pkgs []*packages.Package) error

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 gtigen that does all of the steps; for more specific functionality, create a new Generator with NewGenerator and call methods on it.

func GtiTypeOf

func GtiTypeOf(typ *Type) *gti.Type

GtiTypeOf converts the given *Type to a *gti.Type

func LoadFromComment

func LoadFromComment(c *ast.CommentGroup, cfg *Config) (dirs []gti.Directive, hasAdd bool, hasSkip bool, err error)

LoadFromComment processes the given comment group, setting the values of the given config object based on any gti directives in the comment group, and returning all directives found, whether there was a gti:add directive, and any error. If the given documentation is nil, LoadFromComment still returns an empty but valid gti.Directives value, false, and no error.

func LoadFromComments

func LoadFromComments(cfg *Config, c ...*ast.CommentGroup) (dirs []gti.Directive, hasAdd bool, hasSkip bool, err error)

LoadFromComments is a helper function that combines the results of LoadFromComment for the given comment groups.

func LocalTypeNameQualifier

func LocalTypeNameQualifier(pkg *types.Package) types.Qualifier

LocalTypeNameQualifier returns a types.Qualifier similar to that returned by types.RelativeTo, but using the package name instead of the package path so that it can be used in code.

func PackageModes

func PackageModes(cfg *Config) packages.LoadMode

PackageModes returns the package load modes needed for gtigen, based on the given config information.

func ParsePackages

func ParsePackages(cfg *Config) ([]*packages.Package, error)

ParsePackages parses the package(s) located in the configuration source directory.

func SetterFields

func SetterFields(typ *Type) []gti.Field

SetterFields returns all of the fields and embedded fields of the given type that don't have a `set:"-"` struct tag.

func SetterType

func SetterType(f gti.Field, typ *Type) string

SetterType returns the setter type name for the given field in the context of the given type. It converts slices to variadic arguments.

Types

type Config

type Config struct {

	// the source directory to run gtigen 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 gtigen is being called
	Output string `default:"gtigen.go"`

	// whether to add types to gtigen by default
	AddTypes bool

	// whether to add methods to gtigen by default
	AddMethods bool

	// whether to add functions to gtigen by default
	AddFuncs bool

	// An ordered map of configs keyed by fully-qualified interface type names; if a type implements the interface, the config will be applied to it.
	// The configs are applied in sequential ascending order, which means that
	// the last config overrides the other ones, so the most specific
	// interfaces should typically be put last.
	// Note: the package gtigen is run on must explicitly reference this interface at some point for this to work; adding a simple
	// `var _ MyInterface = (*MyType)(nil)` statement to check for interface implementation is an easy way to accomplish that.
	// Note: gtigen will still succeed if it can not find one of the interfaces specified here in order to allow it to work generically across multiple directories; you can use the -v flag to get log warnings about this if you suspect that it is not finding interfaces when it should.
	InterfaceConfigs *ordmap.Map[string, *Config]

	// whether to generate an instance of the type(s)
	Instance bool

	// whether to generate a global type variable of the form 'TypeNameType'
	TypeVar bool

	// Whether to generate chaining `Set*` methods for each field of each type (eg: "SetText" for field "Text").
	// If this is set to true, then you can add `set:"-"` struct tags to individual fields
	// to prevent Set methods being generated for them.
	Setters bool

	// a slice of templates to execute on each type being added; the template data is of the type gtigen.Type
	Templates []*template.Template
}

Config contains the configuration information used by gtigen

type Fields

type Fields struct {
	Fields     []gti.Field
	LocalTypes map[string]string
	Tags       map[string]string
}

Fields extends []gti.Field to provide the local type names and struct tags for each field.

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.
	File       *ast.File                            // The file we are currently on.
	Cmap       ast.CommentMap                       // The comment map for the file we are currently on.
	Types      []*Type                              // The types
	Methods    ordmap.Map[string, []gti.Method]     // The methods, keyed by the the full package name of the type of the receiver
	Funcs      ordmap.Map[string, gti.Func]         // The functions
	Interfaces ordmap.Map[string, *types.Interface] // The cached interfaces, created from [Config.InterfaceConfigs]
}

Generator holds the state of the generator. It is primarily used to buffer the output.

func NewGenerator

func NewGenerator(config *Config, pkgs []*packages.Package) *Generator

NewGenerator returns a new generator with the given configuration information and parsed packages.

func (*Generator) ExecTmpl

func (g *Generator) ExecTmpl(t *template.Template, data any)

ExecTmpl executes the given template with the given data and writes the result to [Generator.Buf]. It fatally logs any error. All gtigen templates take a *Type or *gti.Func as their data.

func (*Generator) Find

func (g *Generator) Find() error

Find goes through all of the types, functions, variables, and constants in the package, finds those marked with gti:add, and adds them to [Generator.Types] and [Generator.Funcs]

func (*Generator) Generate

func (g *Generator) Generate() (bool, error)

Generate produces the code for the types stored in [Generator.Types] and stores them in [Generator.Buf]. It returns whether there were any types to generate methods for, and any error that occurred.

func (*Generator) GetEmbeddedFields

func (g *Generator) GetEmbeddedFields(efields *Fields, typ, startTyp types.Type)

GetEmbeddedFields recursively adds to the given set of embedded fields all of the embedded fields for the given type. It does not add the fields in the given starting type, as those fields aren't embedded.

func (*Generator) GetFields

func (g *Generator) GetFields(list *ast.FieldList, cfg *Config) (Fields, error)

GetFields creates and returns a new gti.Fields object from the given ast.FieldList, in the context of the given surrounding config. If the given field list is nil, GetFields still returns an empty but valid gti.Fields value and no error.

func (*Generator) GetInterfaces

func (g *Generator) GetInterfaces() error

GetInterfaces sets [Generator.Interfaces] based on [Generator.Config.InterfaceConfigs]. It should typically not be called by end-user code.

func (*Generator) Inspect

func (g *Generator) Inspect(n ast.Node) (bool, error)

Inspect 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) InspectFuncDecl

func (g *Generator) InspectFuncDecl(fd *ast.FuncDecl) (bool, error)

InspectFuncDecl is the implementation of Generator.Inspect for ast.FuncDecl nodes.

func (*Generator) InspectGenDecl

func (g *Generator) InspectGenDecl(gd *ast.GenDecl) (bool, error)

InspectGenDecl is the implementation of Generator.Inspect for ast.GenDecl nodes.

func (*Generator) LoadFromNodeComments

func (g *Generator) LoadFromNodeComments(cfg *Config, n ast.Node) (dirs []gti.Directive, hasAdd bool, hasSkip bool, err error)

LoadFromNodeComments is a helper function that calls LoadFromComments with the correctly filtered comment map comments of the given node.

func (*Generator) PrintHeader

func (g *Generator) PrintHeader()

PrintHeader prints the header and package clause to the accumulated output

func (*Generator) Printf

func (g *Generator) Printf(format string, args ...any)

Printf prints the formatted string to the accumulated output in [Generator.Buf]

func (*Generator) Write

func (g *Generator) Write() error

Write formats the data in the the Generator's buffer ([Generator.Buf]) and writes it to the file specified by [Generator.Config.Output].

type Type

type Type struct {
	gti.Type

	// LocalName is the name of the type in its package
	LocalName string

	// The standard AST type value
	AST *ast.TypeSpec

	// The name of the package the type is in
	Pkg string

	// The fields of the struct type; nil if not a struct
	Fields Fields

	// The embeds of the struct type; nil if not a struct
	Embeds Fields

	// The fields contained within the embeds of the struct type;
	// nil if not a struct, and used for generating setters only
	EmbeddedFields Fields

	// Configuration information set in the comment directive for the type;
	// is initialized to generator config info first
	Config *Config
}

Type represents a parsed type.

Jump to

Keyboard shortcuts

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