Skip to content

Commit 7f7f31a

Browse files
authored
feature: add support for properties tag in struct-tag rule (#1289)
1 parent d6ad7ce commit 7f7f31a

File tree

3 files changed

+60
-1
lines changed

3 files changed

+60
-1
lines changed

RULES_DESCRIPTIONS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ _Configuration_: N/A
924924
## struct-tag
925925

926926
_Description_: Struct tags are not checked at compile time.
927-
This rule spots errors in struct tags of the following types: asn1, bson, datastore, default, json, mapstructure, protobuf, required, toml, url, validate, xml, yaml.
927+
This rule spots errors in struct tags of the following types: asn1, bson, datastore, default, json, mapstructure, properties, protobuf, required, toml, url, validate, xml, yaml.
928928

929929
_Configuration_: (optional) list of user defined options.
930930

rule/struct_tag.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ const (
105105
keyDefault = "default"
106106
keyJSON = "json"
107107
keyMapstructure = "mapstructure"
108+
keyProperties = "properties"
108109
keyProtobuf = "protobuf"
109110
keyRequired = "required"
110111
keyTOML = "toml"
@@ -205,6 +206,11 @@ func (w lintStructTagRule) checkTaggedField(f *ast.Field) {
205206
if !ok {
206207
w.addFailure(f.Tag, msg)
207208
}
209+
case keyProperties:
210+
msg, ok := w.checkPropertiesTag(f.Type, tag.Options)
211+
if !ok {
212+
w.addFailure(f.Tag, msg)
213+
}
208214
case keyProtobuf:
209215
msg, ok := w.checkProtobufTag(tag)
210216
if !ok {
@@ -506,6 +512,43 @@ func (lintStructTagRule) typeValueMatch(t ast.Expr, val string) bool {
506512

507513
return typeMatches
508514
}
515+
func (w lintStructTagRule) checkPropertiesTag(t ast.Expr, options []string) (string, bool) {
516+
if len(options) == 0 {
517+
return "", true
518+
}
519+
520+
hasDefault := false
521+
for _, opt := range options {
522+
key, val, found := strings.Cut(opt, "=")
523+
switch key {
524+
case "default":
525+
if hasDefault {
526+
return "properties tag accepts only one default option", false
527+
}
528+
hasDefault = true
529+
530+
if !found {
531+
return "malformed default for properties tag", false
532+
}
533+
534+
if !w.typeValueMatch(t, val) {
535+
return "field type and default value type mismatch in properties tag", false
536+
}
537+
case "layout":
538+
if !found || strings.TrimSpace(val) == "" {
539+
return "malformed layout option for properties tag", false
540+
}
541+
542+
if gofmt(t) != "time.Time" {
543+
return "layout option is only applicable to fields of type time.Time in properties tag", false
544+
}
545+
default:
546+
return fmt.Sprintf("unknown option %q in properties tag", opt), false
547+
}
548+
}
549+
550+
return "", true
551+
}
509552

510553
func (w lintStructTagRule) checkProtobufTag(tag *structtag.Tag) (string, bool) {
511554
// check name

testdata/struct_tag.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,19 @@ type TomlUser struct {
163163
Username string `toml:"username,omitempty"`
164164
Location string `toml:"location,unknown"` // MATCH /unknown option 'unknown' in TOML tag/
165165
}
166+
167+
type PropertiesTags struct {
168+
Field int `properties:"-"`
169+
Field int `properties:"myName"`
170+
Field int `properties:"myName,default=15"`
171+
Field int `properties:"myName,default=sString"` // MATCH /field type and default value type mismatch in properties tag/
172+
Field int `properties:",default:15"` // MATCH /unknown option "default:15" in properties tag/
173+
Field int `properties:",default=15,default=2"` // MATCH /properties tag accepts only one default option/
174+
Field time.Time `properties:"date,layout=2006-01-02"`
175+
Field time.Time `properties:",layout=2006-01-02"`
176+
Field time.Time `properties:"date,layout"` // MATCH /malformed layout option for properties tag/
177+
Field time.Time `properties:"date,layout= "` // MATCH /malformed layout option for properties tag/
178+
Field string `properties:"date,layout=2006-01-02"` // MATCH /layout option is only applicable to fields of type time.Time in properties tag/
179+
Field []string `properties:",default=a;b;c"`
180+
Field map[string]string `properties:"myName,omitempty"` // MATCH /unknown option "omitempty" in properties tag/
181+
}

0 commit comments

Comments
 (0)