Fix struct tag with spaces as values (#36)
This commit is contained in:
parent
bdb63c8129
commit
021de6214c
9 changed files with 38 additions and 86 deletions
|
@ -3,6 +3,7 @@ package code
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -60,7 +61,7 @@ func extractStructType(name string, structType *ast.StructType) Struct {
|
||||||
}
|
}
|
||||||
strField.Type = getType(field.Type)
|
strField.Type = getType(field.Type)
|
||||||
if field.Tag != nil {
|
if field.Tag != nil {
|
||||||
strField.Tags = extractStructTag(field.Tag.Value)
|
strField.Tag = extractStructTag(field.Tag.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
str.Fields = append(str.Fields, strField)
|
str.Fields = append(str.Fields, strField)
|
||||||
|
@ -103,26 +104,8 @@ func extractInterfaceType(name string, interfaceType *ast.InterfaceType) Interfa
|
||||||
return intf
|
return intf
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractStructTag(tagValue string) map[string][]string {
|
func extractStructTag(tagValue string) reflect.StructTag {
|
||||||
tagTokens := strings.Fields(tagValue[1 : len(tagValue)-1])
|
return reflect.StructTag(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 extractFunction(name string, comments []string, funcType *ast.FuncType) Method {
|
func extractFunction(name string, comments []string, funcType *ast.FuncType) Method {
|
||||||
|
|
|
@ -61,6 +61,7 @@ import (
|
||||||
type UserModel struct {
|
type UserModel struct {
|
||||||
ID primitive.ObjectID ` + "`bson:\"_id,omitempty\" json:\"id\"`" + `
|
ID primitive.ObjectID ` + "`bson:\"_id,omitempty\" json:\"id\"`" + `
|
||||||
Username string ` + "`bson:\"username\" json:\"username\"`" + `
|
Username string ` + "`bson:\"username\" json:\"username\"`" + `
|
||||||
|
Password string ` + "`bson:\"password\" json:\"-\" note:\"This should be hidden.\"`" + `
|
||||||
}`,
|
}`,
|
||||||
ExpectedOutput: code.File{
|
ExpectedOutput: code.File{
|
||||||
PackageName: "user",
|
PackageName: "user",
|
||||||
|
@ -71,18 +72,17 @@ type UserModel struct {
|
||||||
code.StructField{
|
code.StructField{
|
||||||
Name: "ID",
|
Name: "ID",
|
||||||
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
||||||
Tags: map[string][]string{
|
Tag: `bson:"_id,omitempty" json:"id"`,
|
||||||
"bson": {"_id", "omitempty"},
|
|
||||||
"json": {"id"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
code.StructField{
|
code.StructField{
|
||||||
Name: "Username",
|
Name: "Username",
|
||||||
Type: code.TypeString,
|
Type: code.TypeString,
|
||||||
Tags: map[string][]string{
|
Tag: `bson:"username" json:"username"`,
|
||||||
"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{
|
code.StructField{
|
||||||
Name: "ID",
|
Name: "ID",
|
||||||
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
||||||
Tags: map[string][]string{
|
Tag: `bson:"_id,omitempty" json:"id"`,
|
||||||
"bson": {"_id", "omitempty"},
|
|
||||||
"json": {"id"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
code.StructField{
|
code.StructField{
|
||||||
Name: "Username",
|
Name: "Username",
|
||||||
Type: code.TypeString,
|
Type: code.TypeString,
|
||||||
Tags: map[string][]string{
|
Tag: `bson:"username" json:"username"`,
|
||||||
"bson": {"username"},
|
|
||||||
"json": {"username"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,6 +2,7 @@ package code
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// File is a container of all required components for code generation in the file
|
// 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 {
|
type StructField struct {
|
||||||
Name string
|
Name string
|
||||||
Type Type
|
Type Type
|
||||||
Tags map[string][]string
|
Tag reflect.StructTag
|
||||||
}
|
}
|
||||||
|
|
||||||
// InterfaceType is a definition of the interface
|
// InterfaceType is a definition of the interface
|
||||||
|
|
|
@ -62,10 +62,7 @@ func TestBuilderBuild(t *testing.T) {
|
||||||
PackageAlias: "primitive",
|
PackageAlias: "primitive",
|
||||||
Name: "ObjectID",
|
Name: "ObjectID",
|
||||||
},
|
},
|
||||||
Tags: map[string][]string{
|
Tag: `bson:"id" json:"id,omitempty"`,
|
||||||
"bson": {"id"},
|
|
||||||
"json": {"id", "omitempty"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Username",
|
Name: "Username",
|
||||||
|
|
|
@ -3,7 +3,6 @@ package codegen
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
@ -39,25 +38,10 @@ func (sb StructBuilder) GenFields() string {
|
||||||
var fieldLines []string
|
var fieldLines []string
|
||||||
for _, field := range sb.Fields {
|
for _, field := range sb.Fields {
|
||||||
fieldLine := fmt.Sprintf("\t%s %s", field.Name, field.Type.Code())
|
fieldLine := fmt.Sprintf("\t%s %s", field.Name, field.Type.Code())
|
||||||
if len(field.Tags) > 0 {
|
if len(field.Tag) > 0 {
|
||||||
fieldLine += fmt.Sprintf(" `%s`", sb.generateStructTag(field.Tags))
|
fieldLine += fmt.Sprintf(" `%s`", string(field.Tag))
|
||||||
}
|
}
|
||||||
fieldLines = append(fieldLines, fieldLine)
|
fieldLines = append(fieldLines, fieldLine)
|
||||||
}
|
}
|
||||||
return strings.Join(fieldLines, "\n")
|
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, " ")
|
|
||||||
}
|
|
||||||
|
|
|
@ -28,25 +28,17 @@ func TestStructBuilderBuild(t *testing.T) {
|
||||||
PackageAlias: "primitive",
|
PackageAlias: "primitive",
|
||||||
Name: "ObjectID",
|
Name: "ObjectID",
|
||||||
},
|
},
|
||||||
Tags: map[string][]string{
|
Tag: `bson:"id,omitempty" json:"id,omitempty"`,
|
||||||
"json": {"id", "omitempty"},
|
|
||||||
"bson": {"id", "omitempty"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Username",
|
Name: "Username",
|
||||||
Type: code.TypeString,
|
Type: code.TypeString,
|
||||||
Tags: map[string][]string{
|
Tag: `bson:"username" json:"username"`,
|
||||||
"json": {"username"},
|
|
||||||
"bson": {"username"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Age",
|
Name: "Age",
|
||||||
Type: code.TypeInt,
|
Type: code.TypeInt,
|
||||||
Tags: map[string][]string{
|
Tag: `bson:"age"`,
|
||||||
"bson": {"age"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "orderCount",
|
Name: "orderCount",
|
||||||
|
|
|
@ -14,17 +14,17 @@ var (
|
||||||
idField = code.StructField{
|
idField = code.StructField{
|
||||||
Name: "ID",
|
Name: "ID",
|
||||||
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
||||||
Tags: map[string][]string{"bson": {"_id", "omitempty"}},
|
Tag: `bson:"_id,omitempty"`,
|
||||||
}
|
}
|
||||||
genderField = code.StructField{
|
genderField = code.StructField{
|
||||||
Name: "Gender",
|
Name: "Gender",
|
||||||
Type: code.SimpleType("Gender"),
|
Type: code.SimpleType("Gender"),
|
||||||
Tags: map[string][]string{"bson": {"gender"}},
|
Tag: `bson:"gender"`,
|
||||||
}
|
}
|
||||||
ageField = code.StructField{
|
ageField = code.StructField{
|
||||||
Name: "Age",
|
Name: "Age",
|
||||||
Type: code.TypeInt,
|
Type: code.TypeInt,
|
||||||
Tags: map[string][]string{"bson": {"age"}},
|
Tag: `bson:"age"`,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ func TestGenerateMongoRepository(t *testing.T) {
|
||||||
code.StructField{
|
code.StructField{
|
||||||
Name: "Username",
|
Name: "Username",
|
||||||
Type: code.TypeString,
|
Type: code.TypeString,
|
||||||
Tags: map[string][]string{"bson": {"username"}},
|
Tag: `bson:"username"`,
|
||||||
},
|
},
|
||||||
genderField,
|
genderField,
|
||||||
ageField,
|
ageField,
|
||||||
|
|
|
@ -63,12 +63,13 @@ func (g baseMethodGenerator) bsonFieldReference(fieldReference spec.FieldReferen
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g baseMethodGenerator) bsonTagFromField(field code.StructField) (string, error) {
|
func (g baseMethodGenerator) bsonTagFromField(field code.StructField) (string, error) {
|
||||||
bsonTag, ok := field.Tags["bson"]
|
bsonTag, ok := field.Tag.Lookup("bson")
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", NewBsonTagNotFoundError(field.Name)
|
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) {
|
func (g baseMethodGenerator) convertQuerySpec(query spec.QuerySpec) (querySpec, error) {
|
||||||
|
|
|
@ -15,37 +15,37 @@ var (
|
||||||
idField = code.StructField{
|
idField = code.StructField{
|
||||||
Name: "ID",
|
Name: "ID",
|
||||||
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"},
|
||||||
Tags: map[string][]string{"bson": {"_id", "omitempty"}},
|
Tag: `bson:"_id,omitempty"`,
|
||||||
}
|
}
|
||||||
genderField = code.StructField{
|
genderField = code.StructField{
|
||||||
Name: "Gender",
|
Name: "Gender",
|
||||||
Type: code.SimpleType("Gender"),
|
Type: code.SimpleType("Gender"),
|
||||||
Tags: map[string][]string{"bson": {"gender"}},
|
Tag: `bson:"gender"`,
|
||||||
}
|
}
|
||||||
ageField = code.StructField{
|
ageField = code.StructField{
|
||||||
Name: "Age",
|
Name: "Age",
|
||||||
Type: code.TypeInt,
|
Type: code.TypeInt,
|
||||||
Tags: map[string][]string{"bson": {"age"}},
|
Tag: `bson:"age"`,
|
||||||
}
|
}
|
||||||
nameField = code.StructField{
|
nameField = code.StructField{
|
||||||
Name: "Name",
|
Name: "Name",
|
||||||
Type: code.SimpleType("NameModel"),
|
Type: code.SimpleType("NameModel"),
|
||||||
Tags: map[string][]string{"bson": {"name"}},
|
Tag: `bson:"name"`,
|
||||||
}
|
}
|
||||||
referrerField = code.StructField{
|
referrerField = code.StructField{
|
||||||
Name: "Referrer",
|
Name: "Referrer",
|
||||||
Type: code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
Type: code.PointerType{ContainedType: code.SimpleType("UserModel")},
|
||||||
Tags: map[string][]string{"bson": {"referrer"}},
|
Tag: `bson:"referrer"`,
|
||||||
}
|
}
|
||||||
consentHistoryField = code.StructField{
|
consentHistoryField = code.StructField{
|
||||||
Name: "ConsentHistory",
|
Name: "ConsentHistory",
|
||||||
Type: code.ArrayType{ContainedType: code.SimpleType("ConsentHistory")},
|
Type: code.ArrayType{ContainedType: code.SimpleType("ConsentHistory")},
|
||||||
Tags: map[string][]string{"bson": {"consent_history"}},
|
Tag: `bson:"consent_history"`,
|
||||||
}
|
}
|
||||||
enabledField = code.StructField{
|
enabledField = code.StructField{
|
||||||
Name: "Enabled",
|
Name: "Enabled",
|
||||||
Type: code.TypeBool,
|
Type: code.TypeBool,
|
||||||
Tags: map[string][]string{"bson": {"enabled"}},
|
Tag: `bson:"enabled"`,
|
||||||
}
|
}
|
||||||
accessTokenField = code.StructField{
|
accessTokenField = code.StructField{
|
||||||
Name: "AccessToken",
|
Name: "AccessToken",
|
||||||
|
@ -55,7 +55,7 @@ var (
|
||||||
firstNameField = code.StructField{
|
firstNameField = code.StructField{
|
||||||
Name: "First",
|
Name: "First",
|
||||||
Type: code.TypeString,
|
Type: code.TypeString,
|
||||||
Tags: map[string][]string{"bson": {"first"}},
|
Tag: `bson:"first"`,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ var userModel = code.Struct{
|
||||||
code.StructField{
|
code.StructField{
|
||||||
Name: "Username",
|
Name: "Username",
|
||||||
Type: code.TypeString,
|
Type: code.TypeString,
|
||||||
Tags: map[string][]string{"bson": {"username"}},
|
Tag: `bson:"username"`,
|
||||||
},
|
},
|
||||||
genderField,
|
genderField,
|
||||||
ageField,
|
ageField,
|
||||||
|
|
Loading…
Reference in a new issue