Skip to content

Commit 3cf67c5

Browse files
authored
feature: add support of URL struct tags in struct-tag rule (#1239)
1 parent 8ece20b commit 3cf67c5

File tree

4 files changed

+49
-1
lines changed

4 files changed

+49
-1
lines changed

rule/struct_tag.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ const (
104104
keyJSON = "json"
105105
keyProtobuf = "protobuf"
106106
keyRequired = "required"
107+
keyURL = "url"
107108
keyXML = "xml"
108109
keyYAML = "yaml"
109110
)
@@ -198,6 +199,11 @@ func (w lintStructTagRule) checkTaggedField(f *ast.Field) {
198199
if tag.Name != "true" && tag.Name != "false" {
199200
w.addFailure(f.Tag, "required should be 'true' or 'false'")
200201
}
202+
case keyURL:
203+
msg, ok := w.checkURLTag(tag.Options)
204+
if !ok {
205+
w.addFailure(f.Tag, msg)
206+
}
201207
case keyXML:
202208
msg, ok := w.checkXMLTag(tag.Options)
203209
if !ok {
@@ -329,6 +335,29 @@ func (w lintStructTagRule) checkYAMLTag(options []string) (string, bool) {
329335
return "", true
330336
}
331337

338+
func (w lintStructTagRule) checkURLTag(options []string) (string, bool) {
339+
var delimiter = ""
340+
for _, opt := range options {
341+
switch opt {
342+
case "int", "omitempty", "numbered", "brackets":
343+
case "unix", "unixmilli", "unixnano": // TODO : check that the field is of type time.Time
344+
case "comma", "semicolon", "space":
345+
if delimiter == "" {
346+
delimiter = opt
347+
continue
348+
}
349+
return fmt.Sprintf("can not set both '%s' and '%s' as delimiters in URL tag", opt, delimiter), false
350+
default:
351+
if w.isUserDefined(keyURL, opt) {
352+
continue
353+
}
354+
return fmt.Sprintf("unknown option '%s' in URL tag", opt), false
355+
}
356+
}
357+
358+
return "", true
359+
}
360+
332361
func (lintStructTagRule) typeValueMatch(t ast.Expr, val string) bool {
333362
tID, ok := t.(*ast.Ident)
334363
if !ok {

test/struct_tag_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func TestStructTag(t *testing.T) {
1313

1414
func TestStructTagWithUserOptions(t *testing.T) {
1515
testRule(t, "struct_tag_user_options", &rule.StructTagRule{}, &lint.RuleConfig{
16-
Arguments: []any{"json,inline,outline", "bson,gnu"},
16+
Arguments: []any{"json,inline,outline", "bson,gnu", "url,myURLOption"},
1717
})
1818
}
1919

testdata/struct_tag.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,16 @@ type Simple struct {
123123
XXX_unrecognized []byte `json:"-"`
124124
XXX_sizecache int32 `json:"-"`
125125
}
126+
127+
type RequestQueryOption struct {
128+
Properties []string `url:"properties,comma,omitempty"`
129+
CustomProperties []string `url:"-"`
130+
Associations []string `url:"associations,brackets,omitempty"`
131+
Associations2 []string `url:"associations2,semicolon,omitempty"`
132+
Associations3 []string `url:"associations3,space,brackets,omitempty"`
133+
Associations4 []string `url:"associations4,numbered,omitempty"`
134+
Associations5 []string `url:"associations5,space,semicolon,omitempty"` // MATCH /can not set both 'semicolon' and 'space' as delimiters in URL tag/
135+
PaginateAssociations bool `url:"paginateAssociations,int,omitempty"`
136+
Archived bool `url:"archived,myURLOption"` // MATCH /unknown option 'myURLOption' in URL tag/
137+
IDProperty string `url:"idProperty,omitempty"`
138+
}

testdata/struct_tag_user_options.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,9 @@ type RangeAllocation struct {
1313
Range string `bson:"range,flow"` // MATCH /unknown option 'flow' in BSON tag/
1414
Data []byte `bson:"data,inline"`
1515
}
16+
17+
type RequestQueryOptions struct {
18+
Properties []string `url:"properties,commmma,omitempty"` // MATCH /unknown option 'commmma' in URL tag/
19+
CustomProperties []string `url:"-"`
20+
Archived bool `url:"archived,myURLOption"`
21+
}

0 commit comments

Comments
 (0)