mirror of
https://github.com/mgechev/revive.git
synced 2025-07-13 01:00:17 +02:00
fix: add-constant struct tags in anonymous struct literals false positive (#954)
* fix: add-constant struct tags in anonymous struct literals false positive
This commit is contained in:
@ -49,12 +49,13 @@ func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lin
|
|||||||
failures = append(failures, failure)
|
failures = append(failures, failure)
|
||||||
}
|
}
|
||||||
|
|
||||||
w := lintAddConstantRule{
|
w := &lintAddConstantRule{
|
||||||
onFailure: onFailure,
|
onFailure: onFailure,
|
||||||
strLits: make(map[string]int),
|
strLits: make(map[string]int),
|
||||||
strLitLimit: r.strLitLimit,
|
strLitLimit: r.strLitLimit,
|
||||||
whiteLst: r.whiteList,
|
whiteLst: r.whiteList,
|
||||||
ignoreFunctions: r.ignoreFunctions,
|
ignoreFunctions: r.ignoreFunctions,
|
||||||
|
structTags: make(map[*ast.BasicLit]struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
ast.Walk(w, file.AST)
|
ast.Walk(w, file.AST)
|
||||||
@ -73,9 +74,14 @@ type lintAddConstantRule struct {
|
|||||||
strLitLimit int
|
strLitLimit int
|
||||||
whiteLst whiteList
|
whiteLst whiteList
|
||||||
ignoreFunctions []*regexp.Regexp
|
ignoreFunctions []*regexp.Regexp
|
||||||
|
structTags map[*ast.BasicLit]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintAddConstantRule) Visit(node ast.Node) ast.Visitor {
|
func (w *lintAddConstantRule) Visit(node ast.Node) ast.Visitor {
|
||||||
|
if node == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
switch n := node.(type) {
|
switch n := node.(type) {
|
||||||
case *ast.CallExpr:
|
case *ast.CallExpr:
|
||||||
w.checkFunc(n)
|
w.checkFunc(n)
|
||||||
@ -83,13 +89,23 @@ func (w lintAddConstantRule) Visit(node ast.Node) ast.Visitor {
|
|||||||
case *ast.GenDecl:
|
case *ast.GenDecl:
|
||||||
return nil // skip declarations
|
return nil // skip declarations
|
||||||
case *ast.BasicLit:
|
case *ast.BasicLit:
|
||||||
|
if !w.isStructTag(n) {
|
||||||
w.checkLit(n)
|
w.checkLit(n)
|
||||||
}
|
}
|
||||||
|
case *ast.StructType:
|
||||||
|
if n.Fields != nil {
|
||||||
|
for _, field := range n.Fields.List {
|
||||||
|
if field.Tag != nil {
|
||||||
|
w.structTags[field.Tag] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintAddConstantRule) checkFunc(expr *ast.CallExpr) {
|
func (w *lintAddConstantRule) checkFunc(expr *ast.CallExpr) {
|
||||||
fName := w.getFuncName(expr)
|
fName := w.getFuncName(expr)
|
||||||
|
|
||||||
for _, arg := range expr.Args {
|
for _, arg := range expr.Args {
|
||||||
@ -105,7 +121,7 @@ func (w lintAddConstantRule) checkFunc(expr *ast.CallExpr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lintAddConstantRule) getFuncName(expr *ast.CallExpr) string {
|
func (*lintAddConstantRule) getFuncName(expr *ast.CallExpr) string {
|
||||||
switch f := expr.Fun.(type) {
|
switch f := expr.Fun.(type) {
|
||||||
case *ast.SelectorExpr:
|
case *ast.SelectorExpr:
|
||||||
switch prefix := f.X.(type) {
|
switch prefix := f.X.(type) {
|
||||||
@ -119,7 +135,7 @@ func (lintAddConstantRule) getFuncName(expr *ast.CallExpr) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintAddConstantRule) checkLit(n *ast.BasicLit) {
|
func (w *lintAddConstantRule) checkLit(n *ast.BasicLit) {
|
||||||
switch kind := n.Kind.String(); kind {
|
switch kind := n.Kind.String(); kind {
|
||||||
case kindFLOAT, kindINT:
|
case kindFLOAT, kindINT:
|
||||||
w.checkNumLit(kind, n)
|
w.checkNumLit(kind, n)
|
||||||
@ -128,7 +144,7 @@ func (w lintAddConstantRule) checkLit(n *ast.BasicLit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintAddConstantRule) isIgnoredFunc(fName string) bool {
|
func (w *lintAddConstantRule) isIgnoredFunc(fName string) bool {
|
||||||
for _, pattern := range w.ignoreFunctions {
|
for _, pattern := range w.ignoreFunctions {
|
||||||
if pattern.MatchString(fName) {
|
if pattern.MatchString(fName) {
|
||||||
return true
|
return true
|
||||||
@ -138,7 +154,7 @@ func (w lintAddConstantRule) isIgnoredFunc(fName string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintAddConstantRule) checkStrLit(n *ast.BasicLit) {
|
func (w *lintAddConstantRule) checkStrLit(n *ast.BasicLit) {
|
||||||
if w.whiteLst[kindSTRING][n.Value] {
|
if w.whiteLst[kindSTRING][n.Value] {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -158,7 +174,7 @@ func (w lintAddConstantRule) checkStrLit(n *ast.BasicLit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w lintAddConstantRule) checkNumLit(kind string, n *ast.BasicLit) {
|
func (w *lintAddConstantRule) checkNumLit(kind string, n *ast.BasicLit) {
|
||||||
if w.whiteLst[kind][n.Value] {
|
if w.whiteLst[kind][n.Value] {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -171,6 +187,11 @@ func (w lintAddConstantRule) checkNumLit(kind string, n *ast.BasicLit) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *lintAddConstantRule) isStructTag(n *ast.BasicLit) bool {
|
||||||
|
_, ok := w.structTags[n]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
func (r *AddConstantRule) configure(arguments lint.Arguments) {
|
func (r *AddConstantRule) configure(arguments lint.Arguments) {
|
||||||
r.Lock()
|
r.Lock()
|
||||||
defer r.Unlock()
|
defer r.Unlock()
|
||||||
|
38
testdata/add-constant.go
vendored
38
testdata/add-constant.go
vendored
@ -5,7 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func foo(a, b, c, d int) {
|
func foo(a float32, b string, c any, d int) {
|
||||||
a = 1.0 // ignore
|
a = 1.0 // ignore
|
||||||
b = "ignore"
|
b = "ignore"
|
||||||
c = 2 // ignore
|
c = 2 // ignore
|
||||||
@ -51,3 +51,39 @@ func ignoredFunc(num int) int {
|
|||||||
func notIgnoredFunc(num int) int {
|
func notIgnoredFunc(num int) int {
|
||||||
return num
|
return num
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tagsInStructLiteralsShouldBeOK() {
|
||||||
|
a := struct {
|
||||||
|
X int `json:"x"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
b := struct {
|
||||||
|
X int `json:"x"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
c := struct {
|
||||||
|
X int `json:"x"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
d := struct {
|
||||||
|
X int `json:"x"`
|
||||||
|
Y int `json:"y"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
e := struct {
|
||||||
|
X int `json:"x"`
|
||||||
|
Y int `json:"y"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
var f struct {
|
||||||
|
X int `json:"x"`
|
||||||
|
Y int `json:"y"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var g struct {
|
||||||
|
X int `json:"x"`
|
||||||
|
Y int `json:"y"`
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, _, _, _, _, _ = a, b, c, d, e, f, g
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user