mirror of
https://github.com/mgechev/revive.git
synced 2025-11-25 22:12:38 +02:00
feature: struct-tag warns on (useless) options on ignored fields (#1487)
This commit is contained in:
@@ -180,6 +180,10 @@ func (w lintStructTagRule) checkTaggedField(checkCtx *checkContext, f *ast.Field
|
||||
w.addFailureWithTagKey(f.Tag, msg, tag.Key)
|
||||
}
|
||||
|
||||
if msg, ok := checkOptionsOnIgnoredField(tag); !ok {
|
||||
w.addFailureWithTagKey(f.Tag, msg, tag.Key)
|
||||
}
|
||||
|
||||
checker, ok := w.tagCheckers[tagKey(tag.Key)]
|
||||
if !ok {
|
||||
continue // we don't have a checker for the tag
|
||||
@@ -561,13 +565,6 @@ func checkYAMLTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (messa
|
||||
}
|
||||
|
||||
func checkSpannerTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (message string, succeeded bool) {
|
||||
if tag.Name == "-" {
|
||||
if len(tag.Options) > 0 {
|
||||
return fmt.Sprintf("useless option(s) %s for ignored field", strings.Join(tag.Options, ",")), false
|
||||
}
|
||||
return "", true
|
||||
}
|
||||
|
||||
for _, opt := range tag.Options {
|
||||
if !checkCtx.isUserDefined(keySpanner, opt) {
|
||||
return fmt.Sprintf(msgUnknownOption, opt), false
|
||||
@@ -577,6 +574,28 @@ func checkSpannerTag(checkCtx *checkContext, tag *structtag.Tag, _ ast.Expr) (me
|
||||
return "", true
|
||||
}
|
||||
|
||||
// checkOptionsOnIgnoredField checks if an ignored struct field (tag name "-") has any options specified.
|
||||
// It returns a message and false if there are useless options present, or an empty message and true if valid.
|
||||
func checkOptionsOnIgnoredField(tag *structtag.Tag) (message string, succeeded bool) {
|
||||
if tag.Name != "-" {
|
||||
return "", true
|
||||
}
|
||||
|
||||
switch len(tag.Options) {
|
||||
case 0:
|
||||
return "", true
|
||||
case 1:
|
||||
opt := strings.TrimSpace(tag.Options[0])
|
||||
if opt == "" {
|
||||
return "", true // accept "-," as options
|
||||
}
|
||||
|
||||
return fmt.Sprintf("useless option %s for ignored field", opt), false
|
||||
default:
|
||||
return fmt.Sprintf("useless options %s for ignored field", strings.Join(tag.Options, ",")), false
|
||||
}
|
||||
}
|
||||
|
||||
func checkValidateOptionsAlternatives(checkCtx *checkContext, alternatives []string) (message string, succeeded bool) {
|
||||
for _, alternative := range alternatives {
|
||||
alternative := strings.TrimSpace(alternative)
|
||||
|
||||
47
testdata/struct_tag_user_options.go
vendored
47
testdata/struct_tag_user_options.go
vendored
@@ -1,5 +1,7 @@
|
||||
package fixtures
|
||||
|
||||
import "time"
|
||||
|
||||
type RangeAllocation struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
@@ -49,6 +51,49 @@ type TomlUser struct {
|
||||
|
||||
type SpannerUserOptions struct {
|
||||
ID int `spanner:"user_id,mySpannerOption"`
|
||||
A int `spanner:"-,mySpannerOption"` // MATCH /useless option(s) mySpannerOption for ignored field in spanner tag/
|
||||
A int `spanner:"-,mySpannerOption"` // MATCH /useless option mySpannerOption for ignored field in spanner tag/
|
||||
Name string `spanner:"full_name,unknownOption"` // MATCH /unknown option "unknownOption" in spanner tag/
|
||||
}
|
||||
|
||||
type uselessOptions struct {
|
||||
A int `bson:"-,"`
|
||||
B int `bson:"-,omitempty"` // MATCH /useless option omitempty for ignored field in bson tag/
|
||||
C int `bson:"-,omitempty,omitempty"` // MATCH /useless options omitempty,omitempty for ignored field in bson tag/
|
||||
D int `datastore:"-,"`
|
||||
E int `datastore:"-,omitempty"` // MATCH /useless option omitempty for ignored field in datastore tag/
|
||||
F int `datastore:"-,omitempty,omitempty"` // MATCH /useless options omitempty,omitempty for ignored field in datastore tag/
|
||||
G int `json:"-,"`
|
||||
H int `json:"-,omitempty"` // MATCH /useless option omitempty for ignored field in json tag/
|
||||
I int `json:"-,omitempty,omitempty"` // MATCH /useless options omitempty,omitempty for ignored field in json tag/
|
||||
J int `mapstructure:"-,"`
|
||||
K int `mapstructure:"-,squash"` // MATCH /useless option squash for ignored field in mapstructure tag/
|
||||
L int `mapstructure:"-,omitempty,omitempty"` // MATCH /useless options omitempty,omitempty for ignored field in mapstructure tag/
|
||||
M int `properties:"-,"`
|
||||
N int `properties:"-,default=15"` // MATCH /useless option default=15 for ignored field in properties tag/
|
||||
O time.Time `properties:"-,layout=2006-01-02,default=2006-01-02"` // MATCH /useless options layout=2006-01-02,default=2006-01-02 for ignored field in properties tag/
|
||||
P int `spanner:"-,"`
|
||||
Q int `spanner:"-,mySpannerOption"` // MATCH /useless option mySpannerOption for ignored field in spanner tag/
|
||||
R int `spanner:"-,mySpannerOption,mySpannerOption"` // MATCH /useless options mySpannerOption,mySpannerOption for ignored field in spanner tag/
|
||||
S int `toml:"-,"`
|
||||
T int `toml:"-,omitempty"` // MATCH /useless option omitempty for ignored field in toml tag/
|
||||
U int `toml:"-,omitempty,omitempty"` // MATCH /useless options omitempty,omitempty for ignored field in toml tag/
|
||||
V int `url:"-,"`
|
||||
W int `url:"-,omitempty"` // MATCH /useless option omitempty for ignored field in url tag/
|
||||
X int `url:"-,omitempty,omitempty"` // MATCH /useless options omitempty,omitempty for ignored field in url tag/
|
||||
Y int `xml:"-,"`
|
||||
Z int `xml:"-,omitempty"` // MATCH /useless option omitempty for ignored field in xml tag/
|
||||
Aa int `xml:"-,omitempty,omitempty"` // MATCH /useless options omitempty,omitempty for ignored field in xml tag/
|
||||
Ba int `yaml:"-,"`
|
||||
Ca int `yaml:"-,omitempty"` // MATCH /useless option omitempty for ignored field in yaml tag/
|
||||
Da int `yaml:"-,omitempty,omitempty"` // MATCH /useless options omitempty,omitempty for ignored field in yaml tag/
|
||||
|
||||
// MATCH:59 /unknown option "" in bson tag/
|
||||
// MATCH:62 /unknown option "" in datastore tag/
|
||||
// MATCH:68 /unknown option "" in mapstructure tag/
|
||||
// MATCH:71 /unknown or malformed option "" in properties tag/
|
||||
// MATCH:74 /unknown option "" in spanner tag/
|
||||
// MATCH:77 /unknown option "" in toml tag/
|
||||
// MATCH:80 /unknown option "" in url tag/
|
||||
// MATCH:83 /unknown option "" in xml tag/
|
||||
// MATCH:86 /unknown option "" in yaml tag/
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user