genhelpers

package
v0.96.0 Latest Latest
Warning

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

Go to latest
Published: Sep 19, 2024 License: MIT Imports: 17 Imported by: 0

README

generator commons

Because we generate a bunch of code in the project, and we tend to copy-paste similar setup for the generators, templates, etc., we decided to introduce common generator creation utils that can be reused by variety of generators.

Description

The main building blocks of this package are:

  • generator.go defining Generator[T ObjectNameProvider, M GenerationModel] struct allowing to create new generators
  • mappers.go defining mappers that can be reused in the generated objects
  • struct_details_extractor.go allowing to parse any struct to retrieve its information (for the later generation purposes)
  • template_commons.go containing template helper functions and the easy way to use them without providing their name everytime
  • util.go with a variety of util functions

How it works

Defining and running a new generator

Before proceeding with the following steps check objectassert/gen package for reference.

To create a new generator:

  1. Create gen package in the destination package with:
    • main/main.go file
    • templates directory
    • model.go containing the model definition and conversion
    • templates.go containing the templates definitions and helper functions
  2. Create generate.go file on the same level as the gen package above with the following content only (in addition to the package name) //go:generate go run ./gen/main/main.go $SF_TF_GENERATOR_ARGS.
  3. In the gen/main/main.go create and run a new generator. This means:
    • providing an input definition for the source objects
    • method to enrich source object definitions with the necessary content
    • method to translate enriched objects to the models used inside the templates
    • method with the generated files naming strategy
    • list of all the needed templates
    • (optionally) additional debug output you want to run for each of the objects
    • (optionally) a filter to limit the generation to only specific objects
  4. Add two entries to our Makefile:
    • first for a cleanup, e.g. rm -f ./pkg/acceptance/bettertestspoc/assert/objectparametersassert/*_gen.go
    • second for a generation itself, e.g. go generate ./pkg/acceptance/bettertestspoc/assert/objectparametersassert/generate.go
  5. By default, generator support the following command line flags (invokable with e.g. make generate-show-output-schemas SF_TF_GENERATOR_ARGS='--dry-run --verbose')
    • --dry-run allowing to print the generated content to the command line instead of saving it to files
    • --verbose allowing to see the all the additional debug logs

Next steps

Known limitations
  • Currently, only 3 generators reuse the same flow; we need to include more to have more observations
Improvements

Functional improvements:

Implementation improvements:

  • add acceptance test for a testStruct (the one from struct_details_extractor_test.go) for the whole generation flow
  • add description to all publicly available structs and functions (multiple TODOs left)
  • introduce a more meaningful function for the GenerationModel interface (TODO left in the generator.go)
  • tackle the temporary hacky solution to allow easy passing multiple args from the make command (TODO left in the generator.go)
  • extract a common filter by name filter (TODO left in the pkg/schemas/gen/main)
  • describe and test all the template helpers (TODOs left in templates_commons.go)
  • test writing to file (TODO left in util.go)
  • use commons in the SDK generator

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	Identity           = func(field string) string { return field }
	ToString           = func(field string) string { return fmt.Sprintf("%s.String()", field) }
	FullyQualifiedName = func(field string) string { return fmt.Sprintf("%s.FullyQualifiedName()", field) }
	Name               = func(field string) string { return fmt.Sprintf("%s.Name()", field) }
	CastToString       = func(field string) string { return fmt.Sprintf("string(%s)", field) }
	CastToInt          = func(field string) string { return fmt.Sprintf("int(%s)", field) }
)

Functions

func AdditionalStandardImports

func AdditionalStandardImports(fields []Field) []string

TODO: test

func BuildTemplateFuncMap

func BuildTemplateFuncMap(funcs ...any) template.FuncMap

func CamelToWords

func CamelToWords(camel string) string

func ColumnOutput

func ColumnOutput(columnWidth int, columns ...string) string

ColumnOutput is a helper to align a tabular output with the given columnWidth, e.g. (for 20 spaces column width): Name string string State sdk.WarehouseState string

func FirstLetter

func FirstLetter(in string) string

func FirstLetterLowercase

func FirstLetterLowercase(in string) string

func IsLastItem

func IsLastItem(itemIdx int, collectionLength int) bool

func RunMapper

func RunMapper(mapper Mapper, in ...string) string

func SnakeCase

func SnakeCase(name string) string

func SnakeCaseToCamel

func SnakeCaseToCamel(snake string) string

func ToSnakeCase

func ToSnakeCase(str string) string

ToSnakeCase allows converting a CamelCase text to camel_case one (needed for schema attribute names). Examples: - CamelCase -> camel_case - ACamelCase -> a_camel_case - URLParser -> url_parser - Camel1Case -> camel1_case - camelCase -> camel_case - camelURL -> camel_url - camelURLSomething -> camel_url_something

func TypeWithoutPointer

func TypeWithoutPointer(t string) string

func WriteCodeToFile

func WriteCodeToFile(buffer *bytes.Buffer, fileName string) error

WriteCodeToFile formats and saves content from the given buffer into file relative to the current working directory. TODO [SNOW-1501905]: test

Types

type Field

type Field struct {
	Name           string
	ConcreteType   string
	UnderlyingType string
}

func (*Field) ConcreteTypeNoPointer added in v0.95.0

func (f *Field) ConcreteTypeNoPointer() string

func (*Field) GetImportedType

func (f *Field) GetImportedType() (string, bool)

func (*Field) IsPointer

func (f *Field) IsPointer() bool

func (*Field) IsSlice

func (f *Field) IsSlice() bool

type GenerationModel

type GenerationModel interface {
	SomeFunc()
}

TODO [SNOW-1501905]: describe TODO [SNOW-1501905]: better func

type Generator

type Generator[T ObjectNameProvider, M GenerationModel] struct {
	// contains filtered or unexported fields
}

func NewGenerator

func NewGenerator[T ObjectNameProvider, M GenerationModel](objectsProvider func() []T, modelProvider func(T) M, filenameProvider func(T, M) string, templates []*template.Template) *Generator[T, M]

func (*Generator[T, _]) Run

func (g *Generator[T, _]) Run() error

func (*Generator[_, _]) RunAndHandleOsReturn

func (g *Generator[_, _]) RunAndHandleOsReturn()

func (*Generator[T, M]) WithAdditionalObjectsDebugLogs

func (g *Generator[T, M]) WithAdditionalObjectsDebugLogs(objectLogsProvider func([]T)) *Generator[T, M]

func (*Generator[T, M]) WithObjectFilter

func (g *Generator[T, M]) WithObjectFilter(objectFilter func(T) bool) *Generator[T, M]

type Mapper

type Mapper func(string) string

type ObjectNameProvider

type ObjectNameProvider interface {
	ObjectName() string
}

TODO [SNOW-1501905]: describe

type ResourceSchemaDetails

type ResourceSchemaDetails struct {
	Name       string
	Attributes []SchemaAttribute
}

func ExtractResourceSchemaDetails

func ExtractResourceSchemaDetails(name string, schema map[string]*schema.Schema) ResourceSchemaDetails

TODO: test

func (ResourceSchemaDetails) ObjectName

func (s ResourceSchemaDetails) ObjectName() string

type SchemaAttribute

type SchemaAttribute struct {
	Name          string
	AttributeType schema.ValueType
	Required      bool
}

type SdkObjectDetails

type SdkObjectDetails struct {
	IdType     string
	ObjectType sdk.ObjectType
	StructDetails
}

type StructDetails

type StructDetails struct {
	Name   string
	Fields []Field
}

func ExtractStructDetails

func ExtractStructDetails(s any) StructDetails

func (StructDetails) ObjectName

func (s StructDetails) ObjectName() string

Jump to

Keyboard shortcuts

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