diff --git a/rule/struct_tag.go b/rule/struct_tag.go index 3a0e4f2..a154c1c 100644 --- a/rule/struct_tag.go +++ b/rule/struct_tag.go @@ -106,6 +106,7 @@ const ( keyMapstructure = "mapstructure" keyProtobuf = "protobuf" keyRequired = "required" + keyTOML = "toml" keyURL = "url" keyValidate = "validate" keyXML = "xml" @@ -212,6 +213,11 @@ func (w lintStructTagRule) checkTaggedField(f *ast.Field) { if tag.Name != "true" && tag.Name != "false" { w.addFailure(f.Tag, "required should be 'true' or 'false'") } + case keyTOML: + msg, ok := w.checkTOMLTag(tag.Options) + if !ok { + w.addFailure(f.Tag, msg) + } case keyURL: msg, ok := w.checkURLTag(tag.Options) if !ok { @@ -435,6 +441,21 @@ func (w lintStructTagRule) checkValidateTag(options []string) (string, bool) { return "", true } +func (w lintStructTagRule) checkTOMLTag(options []string) (string, bool) { + for _, opt := range options { + switch opt { + case "omitempty": + default: + if w.isUserDefined(keyTOML, opt) { + continue + } + return fmt.Sprintf("unknown option '%s' in TOML tag", opt), false + } + } + + return "", true +} + func (w lintStructTagRule) checkValidateOptionsAlternatives(alternatives []string) (string, bool) { for _, alternative := range alternatives { alternative := strings.TrimSpace(alternative) diff --git a/test/struct_tag_test.go b/test/struct_tag_test.go index 3be021b..389f0a8 100644 --- a/test/struct_tag_test.go +++ b/test/struct_tag_test.go @@ -20,6 +20,7 @@ func TestStructTagWithUserOptions(t *testing.T) { "datastore,myDatastoreOption", "mapstructure,myMapstructureOption", "validate,displayName", + "toml,unknown", }, }) } diff --git a/testdata/struct_tag.go b/testdata/struct_tag.go index 045f4cd..330d631 100644 --- a/testdata/struct_tag.go +++ b/testdata/struct_tag.go @@ -158,3 +158,8 @@ type ValidateUser struct { BadComplex2 string `validate:"gt=0,dive,eq=1|eq=2,endkeys,required"` // MATCH /option 'endkeys' without a previous 'keys' option in validate tag/ BadComplex3 string `validate:"gt=0,dive,keys,eq=1|eq=2,endkeys,endkeys,required"` // MATCH /option 'endkeys' without a previous 'keys' option in validate tag/ } + +type TomlUser struct { + Username string `toml:"username,omitempty"` + Location string `toml:"location,unknown"` // MATCH /unknown option 'unknown' in TOML tag/ +} diff --git a/testdata/struct_tag_user_options.go b/testdata/struct_tag_user_options.go index c9997bb..66585e6 100644 --- a/testdata/struct_tag_user_options.go +++ b/testdata/struct_tag_user_options.go @@ -41,3 +41,8 @@ type ValidateUser struct { BadComplex2 string `validate:"gt=0,dive,eq=1|eq=2,endkeys,required"` // MATCH /option 'endkeys' without a previous 'keys' option in validate tag/ BadComplex3 string `validate:"gt=0,dive,keys,eq=1|eq=2,endkeys,endkeys,required"` // MATCH /option 'endkeys' without a previous 'keys' option in validate tag/ } + +type TomlUser struct { + Username string `toml:"username,omitempty"` + Location string `toml:"location,unknown"` +}