Skip to content

Commit

Permalink
fix (#2628)
Browse files Browse the repository at this point in the history
  • Loading branch information
gitxiongpan committed May 5, 2023
1 parent 5a81c3e commit 4016b2b
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 4 deletions.
66 changes: 63 additions & 3 deletions plugin/modelgen/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,17 +450,71 @@ func GoTagFieldHook(td *ast.Definition, fd *ast.FieldDefinition, f *Field) (*Fie
return f, nil
}

// splitTagsBySpace split tags by space, except when space is inside quotes
func splitTagsBySpace(tagsString string) []string {
var tags []string
var currentTag string
inQuotes := false

for _, c := range tagsString {
if c == '"' {
inQuotes = !inQuotes
}
if c == ' ' && !inQuotes {
tags = append(tags, currentTag)
currentTag = ""
} else {
currentTag += string(c)
}
}
tags = append(tags, currentTag)

return tags
}

// containsInvalidSpace checks if the tagsString contains invalid space
func containsInvalidSpace(valuesString string) bool {
// get rid of quotes
valuesString = strings.ReplaceAll(valuesString, "\"", "")
if strings.Contains(valuesString, ",") {
// split by comma,
values := strings.Split(valuesString, ",")
for _, value := range values {
if strings.TrimSpace(value) != value {
return true
}
}
return false
}
if strings.Contains(valuesString, ";") {
// split by semicolon, which is common in gorm
values := strings.Split(valuesString, ";")
for _, value := range values {
if strings.TrimSpace(value) != value {
return true
}
}
return false
}
// single value
if strings.TrimSpace(valuesString) != valuesString {
return true
}
return false
}

func removeDuplicateTags(t string) string {
processed := make(map[string]bool)
tt := strings.Split(t, " ")
tt := splitTagsBySpace(t)
returnTags := ""

// iterate backwards through tags so appended goTag directives are prioritized
for i := len(tt) - 1; i >= 0; i-- {
ti := tt[i]
// check if ti contains ":", and not contains any empty space. if not, tag is in wrong format
if !strings.Contains(ti, ":") || strings.Contains(ti, " ") {
panic(fmt.Errorf("wrong format of tags: %s. goTag directive should be in format: @goTag(key: \"something\", value:\"value1,value2,etc\"), no empty space is allowed", t))
// correct example: json:"name"
if !strings.Contains(ti, ":") {
panic(fmt.Errorf("wrong format of tags: %s. goTag directive should be in format: @goTag(key: \"something\", value:\"value\"), ", t))
}

kv := strings.Split(ti, ":")
Expand All @@ -472,6 +526,12 @@ func removeDuplicateTags(t string) string {
if len(returnTags) > 0 {
returnTags = " " + returnTags
}

isContained := containsInvalidSpace(kv[1])
if isContained {
panic(fmt.Errorf("tag value should not contain any leading or trailing spaces: %s", kv[1]))
}

returnTags = kv[0] + ":" + kv[1] + returnTags
}

Expand Down
116 changes: 115 additions & 1 deletion plugin/modelgen/models_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,13 +428,37 @@ func TestRemoveDuplicate(t *testing.T) {
want: "something:\"name2\" json:\"name3\"",
},
{
name: "Test value with empty space",
name: "Test tag value with leading empty space",
args: args{
t: "json:\"name, name2\"",
},
want: "json:\"name, name2\"",
wantPanic: true,
},
{
name: "Test tag value with trailing empty space",
args: args{
t: "json:\"name,name2 \"",
},
want: "json:\"name,name2 \"",
wantPanic: true,
},
{
name: "Test tag value with space in between",
args: args{
t: "gorm:\"unique;not null\"",
},
want: "gorm:\"unique;not null\"",
wantPanic: false,
},
{
name: "Test mix use of gorm and json tags",
args: args{
t: "gorm:\"unique;not null\" json:\"name,name2\"",
},
want: "gorm:\"unique;not null\" json:\"name,name2\"",
wantPanic: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -448,3 +472,93 @@ func TestRemoveDuplicate(t *testing.T) {
})
}
}

func Test_containsInvalidSpace(t *testing.T) {
type args struct {
valuesString string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "Test tag value with leading empty space",
args: args{
valuesString: "name, name2",
},
want: true,
},
{
name: "Test tag value with trailing empty space",
args: args{
valuesString: "name ,name2",
},
want: true,
},
{
name: "Test tag value with valid empty space in words",
args: args{
valuesString: "accept this,name2",
},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, containsInvalidSpace(tt.args.valuesString), "containsInvalidSpace(%v)", tt.args.valuesString)
})
}
}

func Test_splitTagsBySpace(t *testing.T) {
type args struct {
tagsString string
}
tests := []struct {
name string
args args
want []string
}{
{
name: "multiple tags, single value",
args: args{
tagsString: "json:\"name\" something:\"name2\" json:\"name3\"",
},
want: []string{"json:\"name\"", "something:\"name2\"", "json:\"name3\""},
},
{
name: "multiple tag, multiple values",
args: args{
tagsString: "json:\"name\" something:\"name2\" json:\"name3,name4\"",
},
want: []string{"json:\"name\"", "something:\"name2\"", "json:\"name3,name4\""},
},
{
name: "single tag, single value",
args: args{
tagsString: "json:\"name\"",
},
want: []string{"json:\"name\""},
},
{
name: "single tag, multiple values",
args: args{
tagsString: "json:\"name,name2\"",
},
want: []string{"json:\"name,name2\""},
},
{
name: "space in value",
args: args{
tagsString: "gorm:\"not nul,name2\"",
},
want: []string{"gorm:\"not nul,name2\""},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, splitTagsBySpace(tt.args.tagsString), "splitTagsBySpace(%v)", tt.args.tagsString)
})
}
}

0 comments on commit 4016b2b

Please sign in to comment.