Skip to content

Commit

Permalink
feat: field tag (go-gorm#784)
Browse files Browse the repository at this point in the history
* feat: field tag

* feat: rm new field

* feat: test

* feat: sort tag

* feat: support comment tag and default tag for primary key

* feat: comment tag test
  • Loading branch information
qqxhb authored Apr 7, 2023
1 parent 9762b28 commit 6df282a
Show file tree
Hide file tree
Showing 18 changed files with 246 additions and 145 deletions.
6 changes: 0 additions & 6 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ type Config struct {

dataTypeMap map[string]func(columnType gorm.ColumnType) (dataType string)
fieldJSONTagNS func(columnName string) (tagContent string)
fieldNewTagNS func(columnName string) (tagContent string)

modelOpts []ModelOpt
}
Expand Down Expand Up @@ -104,11 +103,6 @@ func (cfg *Config) WithJSONTagNameStrategy(ns func(columnName string) (tagConten
cfg.fieldJSONTagNS = ns
}

// WithNewTagNameStrategy specify new tag naming strategy
func (cfg *Config) WithNewTagNameStrategy(ns func(columnName string) (tagContent string)) {
cfg.fieldNewTagNS = ns
}

// WithImportPkgPath specify import package path
func (cfg *Config) WithImportPkgPath(paths ...string) {
for i, path := range paths {
Expand Down
3 changes: 2 additions & 1 deletion examples/cmd/from_object/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"strings"

"gorm.io/gen/field"
"gorm.io/gen/helper"
)

Expand Down Expand Up @@ -57,7 +58,7 @@ func (f *DemoField) GORMTag() string { return f.gormTag }
func (f *DemoField) JSONTag() string { return f.jsonTag }

// Tag return new tag
func (f *DemoField) Tag() string { return f.tag }
func (f *DemoField) Tag() field.Tag { return field.NewTag() }

// Comment return comment
func (f *DemoField) Comment() string { return f.comment }
22 changes: 19 additions & 3 deletions field/association.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,9 @@ type RelateConfig struct {
RelateSlicePointer bool

JSONTag string
GORMTag string
NewTag string
OverwriteTag string
GORMTag GormTag
Tag Tag
OverwriteTag Tag
}

// RelateFieldPrefix return generated relation field's type
Expand All @@ -237,3 +237,19 @@ func (c *RelateConfig) RelateFieldPrefix(relationshipType RelationshipType) stri
return defaultRelationshipPrefix[relationshipType]
}
}
func (c *RelateConfig) GetTag(fieldName string) Tag {
if c == nil {
return NewTag()
}
if c.OverwriteTag != nil {
return c.OverwriteTag
}
if c.Tag == nil {
c.Tag = NewTag()
}
if c.JSONTag == "" {
c.JSONTag = ns.ColumnName("", fieldName)
}
c.Tag.Set(TagKeyJson, c.JSONTag)
return c.Tag
}
129 changes: 129 additions & 0 deletions field/tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package field

import (
"sort"
"strings"
)

const (
TagKeyGorm = "gorm"
TagKeyJson = "json"

//gorm tag
TagKeyGormColumn = "column"
TagKeyGormType = "type"
TagKeyGormPrimaryKey = "primaryKey"
TagKeyGormAutoIncrement = "autoIncrement"
TagKeyGormNotNull = "not null"
TagKeyGormUniqueIndex = "uniqueIndex"
TagKeyGormIndex = "index"
TagKeyGormDefault = "default"
TagKeyGormComment = "comment"
)

var (
tagKeyPriorities = map[string]int16{
TagKeyGorm: 100,
TagKeyJson: 99,

TagKeyGormColumn: 10,
TagKeyGormType: 9,
TagKeyGormPrimaryKey: 8,
TagKeyGormAutoIncrement: 7,
TagKeyGormNotNull: 6,
TagKeyGormUniqueIndex: 5,
TagKeyGormIndex: 4,
TagKeyGormDefault: 3,
TagKeyGormComment: 0,
}
)

type TagBuilder interface {
Build() string
}

type Tag map[string]string

func NewTag() Tag {
return Tag{}
}

func (tag Tag) Set(key, value string) {
tag[key] = value
}

func (tag Tag) Remove(key string) {
delete(tag, key)
}

func (tag Tag) Build() string {
if tag == nil || len(tag) == 0 {
return ""
}

tags := make([]string, 0, len(tag))
keys := tagKeySort(tag)
for _, k := range keys {
v := tag[k]
if k == "" || v == "" {
continue
}
tags = append(tags, k+":\""+v+"\"")
}
return strings.Join(tags, " ")
}

type GormTag Tag

func NewGormTag() GormTag {
return GormTag{}
}

func (tag GormTag) Set(key, value string) {
tag[key] = value
}

func (tag GormTag) Remove(key string) {
delete(tag, key)
}

func (tag GormTag) Build() string {
if tag == nil || len(tag) == 0 {
return ""
}
tags := make([]string, 0, len(tag))
keys := tagKeySort(Tag(tag))
for _, k := range keys {
v := tag[k]
if k == "" && v == "" {
continue
}
tv := make([]string, 0, 2)
if k != "" {
tv = append(tv, k)
}
if v != "" {
tv = append(tv, v)
}
tags = append(tags, strings.Join(tv, ":"))
}

return strings.Join(tags, ";")
}

func tagKeySort(tag Tag) []string {
keys := make([]string, 0, len(tag))
if len(tag) == 0 {
return keys
}
for k, _ := range tag {
keys = append(keys, k)
}
sort.Slice(keys, func(i, j int) bool {
if tagKeyPriorities[keys[i]] == tagKeyPriorities[keys[j]] {
return keys[i] <= keys[j]
}
return tagKeyPriorities[keys[i]] > tagKeyPriorities[keys[j]]
})
return keys
}
59 changes: 25 additions & 34 deletions field_options.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package gen

import (
"fmt"
"reflect"
"regexp"
"strings"
Expand All @@ -19,12 +18,12 @@ var ns = schema.NamingStrategy{}

var (
// FieldNew add new field (any type your want)
FieldNew = func(fieldName, fieldType, fieldTag string) model.CreateFieldOpt {
FieldNew = func(fieldName, fieldType string, fieldTag field.Tag) model.CreateFieldOpt {
return func(*model.Field) *model.Field {
return &model.Field{
Name: fieldName,
Type: fieldType,
OverwriteTag: fieldTag,
Name: fieldName,
Type: fieldType,
Tag: fieldTag,
}
}
}
Expand Down Expand Up @@ -112,10 +111,10 @@ var (
}
}
// FieldTag specify GORM tag and JSON tag
FieldTag = func(columnName string, gormTag, jsonTag string) model.ModifyFieldOpt {
FieldTag = func(columnName string, tagFunc func(tag field.Tag) field.Tag) model.ModifyFieldOpt {
return func(m *model.Field) *model.Field {
if m.ColumnName == columnName {
m.GORMTag, m.JSONTag = gormTag, jsonTag
m.Tag = tagFunc(m.Tag)
}
return m
}
Expand All @@ -124,7 +123,7 @@ var (
FieldJSONTag = func(columnName string, jsonTag string) model.ModifyFieldOpt {
return func(m *model.Field) *model.Field {
if m.ColumnName == columnName {
m.JSONTag = jsonTag
m.Tag.Set(field.TagKeyJson, jsonTag)
}
return m
}
Expand All @@ -133,25 +132,28 @@ var (
FieldJSONTagWithNS = func(schemaName func(columnName string) (tagContent string)) model.ModifyFieldOpt {
return func(m *model.Field) *model.Field {
if schemaName != nil {
m.JSONTag = schemaName(m.ColumnName)
m.Tag.Set(field.TagKeyJson, schemaName(m.ColumnName))

}
return m
}
}
// FieldGORMTag specify GORM tag
FieldGORMTag = func(columnName string, gormTag string) model.ModifyFieldOpt {
FieldGORMTag = func(columnName string, gormTag func(tag field.GormTag) field.GormTag) model.ModifyFieldOpt {
return func(m *model.Field) *model.Field {
if m.ColumnName == columnName {
m.GORMTag = gormTag
m.GORMTag = gormTag(m.GORMTag)
}
return m
}
}
// FieldNewTag add new tag
FieldNewTag = func(columnName string, newTag string) model.ModifyFieldOpt {
FieldNewTag = func(columnName string, newTag field.Tag) model.ModifyFieldOpt {
return func(m *model.Field) *model.Field {
if m.ColumnName == columnName {
m.NewTag += " " + newTag
for k, v := range newTag {
m.Tag.Set(k, v)
}
}
return m
}
Expand All @@ -162,7 +164,7 @@ var (
if schemaName == nil {
schemaName = func(name string) string { return name }
}
m.NewTag = fmt.Sprintf(`%s %s:"%s"`, m.NewTag, tagName, schemaName(m.ColumnName))
m.Tag.Set(tagName, schemaName(m.ColumnName))
return m
}
}
Expand Down Expand Up @@ -199,18 +201,13 @@ var (
if config == nil {
config = &field.RelateConfig{}
}
if config.JSONTag == "" {
config.JSONTag = ns.ColumnName("", fieldName)
}

return func(*model.Field) *model.Field {
return &model.Field{
Name: fieldName,
Type: config.RelateFieldPrefix(relationship) + table.StructInfo.Type,
JSONTag: config.JSONTag,
GORMTag: config.GORMTag,
NewTag: config.NewTag,
OverwriteTag: config.OverwriteTag,

Name: fieldName,
Type: config.RelateFieldPrefix(relationship) + table.StructInfo.Type,
Tag: config.GetTag(fieldName),
GORMTag: config.GORMTag,
Relation: field.NewRelationWithType(
relationship, fieldName, table.StructInfo.Package+"."+table.StructInfo.Type,
table.Relations()...),
Expand All @@ -228,19 +225,13 @@ var (
if config == nil {
config = &field.RelateConfig{}
}
if config.JSONTag == "" {
config.JSONTag = ns.ColumnName("", fieldName)
}

return func(*model.Field) *model.Field {
return &model.Field{
Name: fieldName,
Type: config.RelateFieldPrefix(relationship) + fieldType,
JSONTag: config.JSONTag,
GORMTag: config.GORMTag,
NewTag: config.NewTag,
OverwriteTag: config.OverwriteTag,

Name: fieldName,
Type: config.RelateFieldPrefix(relationship) + fieldType,
GORMTag: config.GORMTag,
Tag: config.GetTag(fieldName),
Relation: field.NewRelationWithModel(relationship, fieldName, fieldType, relModel),
}
}
Expand Down
1 change: 0 additions & 1 deletion generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ func (g *Generator) genModelConfig(tableName string, modelName string, modelOpts
FieldWithTypeTag: g.FieldWithTypeTag,

FieldJSONTagNS: g.fieldJSONTagNS,
FieldNewTagNS: g.fieldNewTagNS,
},
}
}
Expand Down
4 changes: 3 additions & 1 deletion helper/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package helper
import (
"errors"
"fmt"

"gorm.io/gen/field"
)

// Object an object interface
Expand Down Expand Up @@ -34,7 +36,7 @@ type Field interface {
// JSONTag return json tag
JSONTag() string
// Tag return field tag
Tag() string
Tag() field.Tag

// Comment return comment
Comment() string
Expand Down
27 changes: 18 additions & 9 deletions internal/generate/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,25 @@ func GetQueryStructMetaFromObject(obj helper.Object, conf *model.Config) (*Query
}

fields := make([]*model.Field, 0, 16)
for _, field := range obj.Fields() {
for _, fl := range obj.Fields() {
tag := fl.Tag()
if tag == nil {
tag = field.NewTag()
}
if gt := fl.GORMTag(); gt != "" {
tag.Set(field.TagKeyGorm, gt)
}
if jt := fl.GORMTag(); jt != "" {
tag.Set(field.TagKeyJson, jt)
}

fields = append(fields, &model.Field{
Name: field.Name(),
Type: field.Type(),
ColumnName: field.ColumnName(),
GORMTag: field.GORMTag(),
JSONTag: field.JSONTag(),
NewTag: field.Tag(),
ColumnComment: field.Comment(),
MultilineComment: strings.Contains(field.Comment(), "\n"),
Name: fl.Name(),
Type: fl.Type(),
ColumnName: fl.ColumnName(),
Tag: tag,
ColumnComment: fl.Comment(),
MultilineComment: strings.Contains(fl.Comment(), "\n"),
})
}

Expand Down
Loading

0 comments on commit 6df282a

Please sign in to comment.