Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip code generation for replaced enum types: skip-replaced-enum-types #1400

Merged
merged 1 commit into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 45 additions & 26 deletions boilingcore/boilingcore.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,36 +141,39 @@ func New(config *Config) (*State, error) {
// state given.
func (s *State) Run() error {
data := &templateData{
Tables: s.Tables,
Aliases: s.Config.Aliases,
DriverName: s.Config.DriverName,
PkgName: s.Config.PkgName,
AddGlobal: s.Config.AddGlobal,
AddPanic: s.Config.AddPanic,
AddSoftDeletes: s.Config.AddSoftDeletes,
AddEnumTypes: s.Config.AddEnumTypes,
EnumNullPrefix: s.Config.EnumNullPrefix,
NoContext: s.Config.NoContext,
NoHooks: s.Config.NoHooks,
NoAutoTimestamps: s.Config.NoAutoTimestamps,
NoRowsAffected: s.Config.NoRowsAffected,
NoDriverTemplates: s.Config.NoDriverTemplates,
NoBackReferencing: s.Config.NoBackReferencing,
AlwaysWrapErrors: s.Config.AlwaysWrapErrors,
StructTagCasing: s.Config.StructTagCasing,
StructTagCases: s.Config.StructTagCases,
TagIgnore: make(map[string]struct{}),
Tags: s.Config.Tags,
RelationTag: s.Config.RelationTag,
Dialect: s.Dialect,
Schema: s.Schema,
LQ: strmangle.QuoteCharacter(s.Dialect.LQ),
RQ: strmangle.QuoteCharacter(s.Dialect.RQ),
OutputDirDepth: s.Config.OutputDirDepth(),
Tables: s.Tables,
Aliases: s.Config.Aliases,
DriverName: s.Config.DriverName,
PkgName: s.Config.PkgName,
AddGlobal: s.Config.AddGlobal,
AddPanic: s.Config.AddPanic,
AddSoftDeletes: s.Config.AddSoftDeletes,
AddEnumTypes: s.Config.AddEnumTypes,
SkipReplacedEnumTypes: s.Config.SkipReplacedEnumTypes,
EnumNullPrefix: s.Config.EnumNullPrefix,
NoContext: s.Config.NoContext,
NoHooks: s.Config.NoHooks,
NoAutoTimestamps: s.Config.NoAutoTimestamps,
NoRowsAffected: s.Config.NoRowsAffected,
NoDriverTemplates: s.Config.NoDriverTemplates,
NoBackReferencing: s.Config.NoBackReferencing,
AlwaysWrapErrors: s.Config.AlwaysWrapErrors,
StructTagCasing: s.Config.StructTagCasing,
StructTagCases: s.Config.StructTagCases,
TagIgnore: make(map[string]struct{}),
Tags: s.Config.Tags,
RelationTag: s.Config.RelationTag,
Dialect: s.Dialect,
Schema: s.Schema,
LQ: strmangle.QuoteCharacter(s.Dialect.LQ),
RQ: strmangle.QuoteCharacter(s.Dialect.RQ),
OutputDirDepth: s.Config.OutputDirDepth(),

DBTypes: make(once),
StringFuncs: templateStringMappers,
AutoColumns: s.Config.AutoColumns,

DiscardedEnumTypes: s.Config.DiscardedEnumTypes,
}

for _, v := range s.Config.TagIgnore {
Expand Down Expand Up @@ -460,6 +463,17 @@ func (s *State) mergeEnumImports() {
// processTypeReplacements checks the config for type replacements
// and performs them.
func (s *State) processTypeReplacements() error {
var mandatoryEnumTypes []string
if s.Config.SkipReplacedEnumTypes {
mandatoryEnumTypes = make([]string, 0, 1)
// Replace types can be replaced themselves, so we must not disallow them in this case.
for _, r := range s.Config.TypeReplaces {
if !strmangle.ContainsAny(mandatoryEnumTypes, r.Replace.Type) {
mandatoryEnumTypes = append(mandatoryEnumTypes, r.Replace.Type)
}
}
}

for _, r := range s.Config.TypeReplaces {

for i := range s.Tables {
Expand All @@ -472,6 +486,11 @@ func (s *State) processTypeReplacements() error {
for j := range t.Columns {
c := t.Columns[j]
if matchColumn(c, r.Match) {
if s.Config.SkipReplacedEnumTypes &&
!strmangle.ContainsAny(s.Config.DiscardedEnumTypes, c.Type) &&
!strmangle.ContainsAny(mandatoryEnumTypes, c.Type) {
s.Config.DiscardedEnumTypes = append(s.Config.DiscardedEnumTypes, c.Type)
}
t.Columns[j] = columnMerge(c, r.Replace)

if len(r.Imports.Standard) != 0 || len(r.Imports.ThirdParty) != 0 {
Expand Down
9 changes: 9 additions & 0 deletions boilingcore/boilingcore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"testing"

"github.com/volatiletech/sqlboiler/v4/importers"
"github.com/volatiletech/strmangle"

"github.com/volatiletech/sqlboiler/v4/drivers"
"github.com/volatiletech/sqlboiler/v4/drivers/mocks"
Expand Down Expand Up @@ -226,6 +227,7 @@ func TestProcessTypeReplacements(t *testing.T) {
s := new(State)
s.Config = &Config{}
s.Config.Imports.BasedOnType = make(map[string]importers.Set)
s.Config.SkipReplacedEnumTypes = true
domainStr := "a_domain"
s.Tables = []drivers.Table{
{
Expand Down Expand Up @@ -348,4 +350,11 @@ func TestProcessTypeReplacements(t *testing.T) {
if i := s.Config.Imports.BasedOnType["excellent.NamedType"].ThirdParty[0]; i != `"rock.com/excellent-name"` {
t.Error("imports were not adjusted")
}

expectedDisallows := []string{
"int", "null.String", // Must NOT contain replaced "excellent.Type".
}
if disallowList := s.Config.DiscardedEnumTypes; len(strmangle.SetComplement(disallowList, expectedDisallows)) != 0 {
t.Error("expected disallows:", disallowList)
}
}
43 changes: 23 additions & 20 deletions boilingcore/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,27 @@ type Config struct {
DriverName string `toml:"driver_name,omitempty" json:"driver_name,omitempty"`
DriverConfig drivers.Config `toml:"driver_config,omitempty" json:"driver_config,omitempty"`

PkgName string `toml:"pkg_name,omitempty" json:"pkg_name,omitempty"`
OutFolder string `toml:"out_folder,omitempty" json:"out_folder,omitempty"`
TemplateDirs []string `toml:"template_dirs,omitempty" json:"template_dirs,omitempty"`
Tags []string `toml:"tags,omitempty" json:"tags,omitempty"`
Replacements []string `toml:"replacements,omitempty" json:"replacements,omitempty"`
Debug bool `toml:"debug,omitempty" json:"debug,omitempty"`
AddGlobal bool `toml:"add_global,omitempty" json:"add_global,omitempty"`
AddPanic bool `toml:"add_panic,omitempty" json:"add_panic,omitempty"`
AddSoftDeletes bool `toml:"add_soft_deletes,omitempty" json:"add_soft_deletes,omitempty"`
AddEnumTypes bool `toml:"add_enum_types,omitempty" json:"add_enum_types,omitempty"`
EnumNullPrefix string `toml:"enum_null_prefix,omitempty" json:"enum_null_prefix,omitempty"`
NoContext bool `toml:"no_context,omitempty" json:"no_context,omitempty"`
NoTests bool `toml:"no_tests,omitempty" json:"no_tests,omitempty"`
NoHooks bool `toml:"no_hooks,omitempty" json:"no_hooks,omitempty"`
NoAutoTimestamps bool `toml:"no_auto_timestamps,omitempty" json:"no_auto_timestamps,omitempty"`
NoRowsAffected bool `toml:"no_rows_affected,omitempty" json:"no_rows_affected,omitempty"`
NoDriverTemplates bool `toml:"no_driver_templates,omitempty" json:"no_driver_templates,omitempty"`
NoBackReferencing bool `toml:"no_back_reference,omitempty" json:"no_back_reference,omitempty"`
AlwaysWrapErrors bool `toml:"always_wrap_errors,omitempty" json:"always_wrap_errors,omitempty"`
Wipe bool `toml:"wipe,omitempty" json:"wipe,omitempty"`
PkgName string `toml:"pkg_name,omitempty" json:"pkg_name,omitempty"`
OutFolder string `toml:"out_folder,omitempty" json:"out_folder,omitempty"`
TemplateDirs []string `toml:"template_dirs,omitempty" json:"template_dirs,omitempty"`
Tags []string `toml:"tags,omitempty" json:"tags,omitempty"`
Replacements []string `toml:"replacements,omitempty" json:"replacements,omitempty"`
Debug bool `toml:"debug,omitempty" json:"debug,omitempty"`
AddGlobal bool `toml:"add_global,omitempty" json:"add_global,omitempty"`
AddPanic bool `toml:"add_panic,omitempty" json:"add_panic,omitempty"`
AddSoftDeletes bool `toml:"add_soft_deletes,omitempty" json:"add_soft_deletes,omitempty"`
AddEnumTypes bool `toml:"add_enum_types,omitempty" json:"add_enum_types,omitempty"`
SkipReplacedEnumTypes bool `toml:"skip_replaced_enum_types,omitempty" json:"skip_replaced_enum_types,omitempty"`
EnumNullPrefix string `toml:"enum_null_prefix,omitempty" json:"enum_null_prefix,omitempty"`
NoContext bool `toml:"no_context,omitempty" json:"no_context,omitempty"`
NoTests bool `toml:"no_tests,omitempty" json:"no_tests,omitempty"`
NoHooks bool `toml:"no_hooks,omitempty" json:"no_hooks,omitempty"`
NoAutoTimestamps bool `toml:"no_auto_timestamps,omitempty" json:"no_auto_timestamps,omitempty"`
NoRowsAffected bool `toml:"no_rows_affected,omitempty" json:"no_rows_affected,omitempty"`
NoDriverTemplates bool `toml:"no_driver_templates,omitempty" json:"no_driver_templates,omitempty"`
NoBackReferencing bool `toml:"no_back_reference,omitempty" json:"no_back_reference,omitempty"`
AlwaysWrapErrors bool `toml:"always_wrap_errors,omitempty" json:"always_wrap_errors,omitempty"`
Wipe bool `toml:"wipe,omitempty" json:"wipe,omitempty"`

StructTagCases StructTagCases `toml:"struct_tag_cases,omitempty" json:"struct_tag_cases,omitempty"`

Expand All @@ -61,6 +62,8 @@ type Config struct {

Imports importers.Collection `toml:"imports,omitempty" json:"imports,omitempty"`

DiscardedEnumTypes []string

DefaultTemplates fs.FS `toml:"-" json:"-"`
CustomTemplateFuncs template.FuncMap `toml:"-" json:"-"`

Expand Down
28 changes: 16 additions & 12 deletions boilingcore/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,19 @@ type templateData struct {
RQ string

// Control various generation features
AddGlobal bool
AddPanic bool
AddSoftDeletes bool
AddEnumTypes bool
EnumNullPrefix string
NoContext bool
NoHooks bool
NoAutoTimestamps bool
NoRowsAffected bool
NoDriverTemplates bool
NoBackReferencing bool
AlwaysWrapErrors bool
AddGlobal bool
AddPanic bool
AddSoftDeletes bool
AddEnumTypes bool
SkipReplacedEnumTypes bool
EnumNullPrefix string
NoContext bool
NoHooks bool
NoAutoTimestamps bool
NoRowsAffected bool
NoDriverTemplates bool
NoBackReferencing bool
AlwaysWrapErrors bool

// Tags control which tags are added to the struct
Tags []string
Expand Down Expand Up @@ -80,6 +81,9 @@ type templateData struct {

// AutoColumns set the name of the columns for auto timestamps and soft deletes
AutoColumns AutoColumns

// Enum types which will not be generated, because they were replaced.
DiscardedEnumTypes []string
}

func (t templateData) Quotes(s string) string {
Expand Down
41 changes: 22 additions & 19 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func main() {
rootCmd.PersistentFlags().BoolP("add-panic-variants", "", false, "Enable generation for panic variants")
rootCmd.PersistentFlags().BoolP("add-soft-deletes", "", false, "Enable soft deletion by updating deleted_at timestamp")
rootCmd.PersistentFlags().BoolP("add-enum-types", "", false, "Enable generation of types for enums")
rootCmd.PersistentFlags().BoolP("skip-replaced-enum-types", "", true, "Prevents the generation of unused enum types")
rootCmd.PersistentFlags().StringP("enum-null-prefix", "", "Null", "Name prefix of nullable enum types")
rootCmd.PersistentFlags().BoolP("version", "", false, "Print the version")
rootCmd.PersistentFlags().BoolP("wipe", "", false, "Delete the output folder (rm -rf) before generation to ensure sanity")
Expand Down Expand Up @@ -154,25 +155,26 @@ func preRun(cmd *cobra.Command, args []string) error {
}

cmdConfig = &boilingcore.Config{
DriverName: driverName,
OutFolder: viper.GetString("output"),
PkgName: viper.GetString("pkgname"),
Debug: viper.GetBool("debug"),
AddGlobal: viper.GetBool("add-global-variants"),
AddPanic: viper.GetBool("add-panic-variants"),
AddSoftDeletes: viper.GetBool("add-soft-deletes"),
AddEnumTypes: viper.GetBool("add-enum-types"),
EnumNullPrefix: viper.GetString("enum-null-prefix"),
NoContext: viper.GetBool("no-context"),
NoTests: viper.GetBool("no-tests"),
NoHooks: viper.GetBool("no-hooks"),
NoRowsAffected: viper.GetBool("no-rows-affected"),
NoAutoTimestamps: viper.GetBool("no-auto-timestamps"),
NoDriverTemplates: viper.GetBool("no-driver-templates"),
NoBackReferencing: viper.GetBool("no-back-referencing"),
AlwaysWrapErrors: viper.GetBool("always-wrap-errors"),
Wipe: viper.GetBool("wipe"),
StructTagCasing: strings.ToLower(viper.GetString("struct-tag-casing")), // camel | snake | title
DriverName: driverName,
OutFolder: viper.GetString("output"),
PkgName: viper.GetString("pkgname"),
Debug: viper.GetBool("debug"),
AddGlobal: viper.GetBool("add-global-variants"),
AddPanic: viper.GetBool("add-panic-variants"),
AddSoftDeletes: viper.GetBool("add-soft-deletes"),
SkipReplacedEnumTypes: viper.GetBool("skip-replaced-enum-types"),
AddEnumTypes: viper.GetBool("add-enum-types"),
EnumNullPrefix: viper.GetString("enum-null-prefix"),
NoContext: viper.GetBool("no-context"),
NoTests: viper.GetBool("no-tests"),
NoHooks: viper.GetBool("no-hooks"),
NoRowsAffected: viper.GetBool("no-rows-affected"),
NoAutoTimestamps: viper.GetBool("no-auto-timestamps"),
NoDriverTemplates: viper.GetBool("no-driver-templates"),
NoBackReferencing: viper.GetBool("no-back-referencing"),
AlwaysWrapErrors: viper.GetBool("always-wrap-errors"),
Wipe: viper.GetBool("wipe"),
StructTagCasing: strings.ToLower(viper.GetString("struct-tag-casing")), // camel | snake | title
StructTagCases: boilingcore.StructTagCases{
// make this compatible with the legacy struct-tag-casing config
Json: withDefaultCase(viper.GetString("struct-tag-cases.json"), viper.GetString("struct-tag-casing")),
Expand Down Expand Up @@ -227,6 +229,7 @@ func preRun(cmd *cobra.Command, args []string) error {
}

cmdConfig.Imports = configureImports()
cmdConfig.DiscardedEnumTypes = make([]string, 0, 1)

cmdState, err = boilingcore.New(cmdConfig)
return err
Expand Down
4 changes: 4 additions & 0 deletions templates/main/singleton/boil_types.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ It only titlecases the EnumValue portion if it's snake-cased.
*/}}
{{$once := onceNew}}
{{$onceNull := onceNew}}
{{$ignoredEnumTypes := .DiscardedEnumTypes -}}
{{- range $table := .Tables -}}
{{- range $col := $table.Columns | filterColumnsByEnum -}}
{{- $name := parseEnumName $col.DBType -}}
Expand All @@ -81,6 +82,9 @@ It only titlecases the EnumValue portion if it's snake-cased.
{{- else -}}
{{ $enumName = printf "%s%s" (titleCase $table.Name) (titleCase $col.Name)}}
{{- end -}}
{{if containsAny $ignoredEnumTypes $enumName -}}
{{continue}}
{{end -}}
{{/* First iteration for enum type $name (nullable or not) */}}
{{- $enumFirstIter := and
(not ($once.Has $name))
Expand Down
Loading