Fix struct tag with spaces as values (#36)

This commit is contained in:
sunboyy 2023-04-19 19:42:08 +07:00 committed by GitHub
parent bdb63c8129
commit 021de6214c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 38 additions and 86 deletions

View file

@ -3,6 +3,7 @@ package code
import (
"fmt"
"go/ast"
"reflect"
"strconv"
"strings"
)
@ -60,7 +61,7 @@ func extractStructType(name string, structType *ast.StructType) Struct {
}
strField.Type = getType(field.Type)
if field.Tag != nil {
strField.Tags = extractStructTag(field.Tag.Value)
strField.Tag = extractStructTag(field.Tag.Value)
}
str.Fields = append(str.Fields, strField)
@ -103,26 +104,8 @@ func extractInterfaceType(name string, interfaceType *ast.InterfaceType) Interfa
return intf
}
func extractStructTag(tagValue string) map[string][]string {
tagTokens := strings.Fields(tagValue[1 : len(tagValue)-1])
tags := make(map[string][]string)
for _, tagToken := range tagTokens {
colonIndex := strings.Index(tagToken, ":")
if colonIndex == -1 {
continue
}
tagKey := tagToken[:colonIndex]
tagValue, err := strconv.Unquote(tagToken[colonIndex+1:])
if err != nil {
fmt.Printf("cannot unquote struct tag %s : %s\n", tagToken[colonIndex+1:], err)
continue
}
tagValues := strings.Split(tagValue, ",")
tags[tagKey] = tagValues
}
return tags
func extractStructTag(tagValue string) reflect.StructTag {
return reflect.StructTag(tagValue[1 : len(tagValue)-1])
}
func extractFunction(name string, comments []string, funcType *ast.FuncType) Method {

View file

@ -61,6 +61,7 @@ import (
type UserModel struct {
ID primitive.ObjectID ` + "`bson:\"_id,omitempty\" json:\"id\"`" + `
Username string ` + "`bson:\"username\" json:\"username\"`" + `
Password string ` + "`bson:\"password\" json:\"-\" note:\"This should be hidden.\"`" + `
}`,
ExpectedOutput: code.File{
PackageName: "user",
@ -71,18 +72,17 @@ type UserModel struct {
code.StructField{
Name: "ID",
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
Tags: map[string][]string{
"bson": {"_id", "omitempty"},
"json": {"id"},
},
Tag: `bson:"_id,omitempty" json:"id"`,
},
code.StructField{
Name: "Username",
Type: code.TypeString,
Tags: map[string][]string{
"bson": {"username"},
"json": {"username"},
},
Tag: `bson:"username" json:"username"`,
},
code.StructField{
Name: "Password",
Type: code.TypeString,
Tag: `bson:"password" json:"-" note:"This should be hidden."`,
},
},
},
@ -268,18 +268,12 @@ type UserRepository interface {
code.StructField{
Name: "ID",
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
Tags: map[string][]string{
"bson": {"_id", "omitempty"},
"json": {"id"},
},
Tag: `bson:"_id,omitempty" json:"id"`,
},
code.StructField{
Name: "Username",
Type: code.TypeString,
Tags: map[string][]string{
"bson": {"username"},
"json": {"username"},
},
Tag: `bson:"username" json:"username"`,
},
},
},

View file

@ -2,6 +2,7 @@ package code
import (
"fmt"
"reflect"
)
// File is a container of all required components for code generation in the file
@ -46,7 +47,7 @@ func (fields StructFields) ByName(name string) (StructField, bool) {
type StructField struct {
Name string
Type Type
Tags map[string][]string
Tag reflect.StructTag
}
// InterfaceType is a definition of the interface

View file

@ -62,10 +62,7 @@ func TestBuilderBuild(t *testing.T) {
PackageAlias: "primitive",
Name: "ObjectID",
},
Tags: map[string][]string{
"bson": {"id"},
"json": {"id", "omitempty"},
},
Tag: `bson:"id" json:"id,omitempty"`,
},
{
Name: "Username",

View file

@ -3,7 +3,6 @@ package codegen
import (
"bytes"
"fmt"
"sort"
"strings"
"text/template"
@ -39,25 +38,10 @@ func (sb StructBuilder) GenFields() string {
var fieldLines []string
for _, field := range sb.Fields {
fieldLine := fmt.Sprintf("\t%s %s", field.Name, field.Type.Code())
if len(field.Tags) > 0 {
fieldLine += fmt.Sprintf(" `%s`", sb.generateStructTag(field.Tags))
if len(field.Tag) > 0 {
fieldLine += fmt.Sprintf(" `%s`", string(field.Tag))
}
fieldLines = append(fieldLines, fieldLine)
}
return strings.Join(fieldLines, "\n")
}
func (sb StructBuilder) generateStructTag(tags map[string][]string) string {
var tagKeys []string
for key := range tags {
tagKeys = append(tagKeys, key)
}
sort.Strings(tagKeys)
var tagGroups []string
for _, key := range tagKeys {
tagValue := strings.Join(tags[key], ",")
tagGroups = append(tagGroups, fmt.Sprintf("%s:\"%s\"", key, tagValue))
}
return strings.Join(tagGroups, " ")
}

View file

@ -28,25 +28,17 @@ func TestStructBuilderBuild(t *testing.T) {
PackageAlias: "primitive",
Name: "ObjectID",
},
Tags: map[string][]string{
"json": {"id", "omitempty"},
"bson": {"id", "omitempty"},
},
Tag: `bson:"id,omitempty" json:"id,omitempty"`,
},
{
Name: "Username",
Type: code.TypeString,
Tags: map[string][]string{
"json": {"username"},
"bson": {"username"},
},
Tag: `bson:"username" json:"username"`,
},
{
Name: "Age",
Type: code.TypeInt,
Tags: map[string][]string{
"bson": {"age"},
},
Tag: `bson:"age"`,
},
{
Name: "orderCount",

View file

@ -14,17 +14,17 @@ var (
idField = code.StructField{
Name: "ID",
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
Tags: map[string][]string{"bson": {"_id", "omitempty"}},
Tag: `bson:"_id,omitempty"`,
}
genderField = code.StructField{
Name: "Gender",
Type: code.SimpleType("Gender"),
Tags: map[string][]string{"bson": {"gender"}},
Tag: `bson:"gender"`,
}
ageField = code.StructField{
Name: "Age",
Type: code.TypeInt,
Tags: map[string][]string{"bson": {"age"}},
Tag: `bson:"age"`,
}
)
@ -36,7 +36,7 @@ func TestGenerateMongoRepository(t *testing.T) {
code.StructField{
Name: "Username",
Type: code.TypeString,
Tags: map[string][]string{"bson": {"username"}},
Tag: `bson:"username"`,
},
genderField,
ageField,

View file

@ -63,12 +63,13 @@ func (g baseMethodGenerator) bsonFieldReference(fieldReference spec.FieldReferen
}
func (g baseMethodGenerator) bsonTagFromField(field code.StructField) (string, error) {
bsonTag, ok := field.Tags["bson"]
bsonTag, ok := field.Tag.Lookup("bson")
if !ok {
return "", NewBsonTagNotFoundError(field.Name)
}
return bsonTag[0], nil
documentKey := strings.Split(bsonTag, ",")[0]
return documentKey, nil
}
func (g baseMethodGenerator) convertQuerySpec(query spec.QuerySpec) (querySpec, error) {

View file

@ -15,37 +15,37 @@ var (
idField = code.StructField{
Name: "ID",
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
Tags: map[string][]string{"bson": {"_id", "omitempty"}},
Tag: `bson:"_id,omitempty"`,
}
genderField = code.StructField{
Name: "Gender",
Type: code.SimpleType("Gender"),
Tags: map[string][]string{"bson": {"gender"}},
Tag: `bson:"gender"`,
}
ageField = code.StructField{
Name: "Age",
Type: code.TypeInt,
Tags: map[string][]string{"bson": {"age"}},
Tag: `bson:"age"`,
}
nameField = code.StructField{
Name: "Name",
Type: code.SimpleType("NameModel"),
Tags: map[string][]string{"bson": {"name"}},
Tag: `bson:"name"`,
}
referrerField = code.StructField{
Name: "Referrer",
Type: code.PointerType{ContainedType: code.SimpleType("UserModel")},
Tags: map[string][]string{"bson": {"referrer"}},
Tag: `bson:"referrer"`,
}
consentHistoryField = code.StructField{
Name: "ConsentHistory",
Type: code.ArrayType{ContainedType: code.SimpleType("ConsentHistory")},
Tags: map[string][]string{"bson": {"consent_history"}},
Tag: `bson:"consent_history"`,
}
enabledField = code.StructField{
Name: "Enabled",
Type: code.TypeBool,
Tags: map[string][]string{"bson": {"enabled"}},
Tag: `bson:"enabled"`,
}
accessTokenField = code.StructField{
Name: "AccessToken",
@ -55,7 +55,7 @@ var (
firstNameField = code.StructField{
Name: "First",
Type: code.TypeString,
Tags: map[string][]string{"bson": {"first"}},
Tag: `bson:"first"`,
}
)
@ -66,7 +66,7 @@ var userModel = code.Struct{
code.StructField{
Name: "Username",
Type: code.TypeString,
Tags: map[string][]string{"bson": {"username"}},
Tag: `bson:"username"`,
},
genderField,
ageField,