1
0
mirror of https://github.com/mgechev/revive.git synced 2025-04-27 12:12:10 +02:00

fix #751 [rule.add-constant] add ignoreFuncs to exclude constants in … (#756)

* fix #751 [rule.add-constant] add ignoreFuncs to exclude constants in functions

* Update add-constant.go

* Update add-constant.go

* fix #751 [rule.add-constant] add ignoreFuncs to exclude constants in functions

* add details to regex-related errors

Co-authored-by: chavacava <salvadorcavadini+github@gmail.com>
This commit is contained in:
Buyanov Vladimir 2022-10-13 14:23:23 +03:00 committed by GitHub
parent 5cc9e27ddb
commit 3d83403fb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 126 additions and 14 deletions

View File

@ -85,12 +85,13 @@ _Configuration_:
* `allowStr`: (string) comma-separated list of allowed string literals * `allowStr`: (string) comma-separated list of allowed string literals
* `allowInts`: (string) comma-separated list of allowed integers * `allowInts`: (string) comma-separated list of allowed integers
* `allowFloats`: (string) comma-separated list of allowed floats * `allowFloats`: (string) comma-separated list of allowed floats
* `ignoreFuncs`: (string) comma-separated list of function names regexp patterns to exclude
Example: Example:
```toml ```toml
[rule.add-constant] [rule.add-constant]
arguments = [{maxLitCount = "3",allowStrs ="\"\"",allowInts="0,1,2",allowFloats="0.0,0.,1.0,1.,2.0,2."}] arguments = [{maxLitCount = "3",allowStrs ="\"\"",allowInts="0,1,2",allowFloats="0.0,0.,1.0,1.,2.0,2.","ignoreFuncs": "os.*,fmt.Println,make"}]
``` ```
## argument-limit ## argument-limit

View File

@ -3,6 +3,7 @@ package rule
import ( import (
"fmt" "fmt"
"go/ast" "go/ast"
"regexp"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -33,6 +34,7 @@ func (wl whiteList) add(kind, list string) {
// AddConstantRule lints unused params in functions. // AddConstantRule lints unused params in functions.
type AddConstantRule struct { type AddConstantRule struct {
whiteList whiteList whiteList whiteList
ignoreFunctions []*regexp.Regexp
strLitLimit int strLitLimit int
sync.Mutex sync.Mutex
} }
@ -47,7 +49,13 @@ func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lin
failures = append(failures, failure) failures = append(failures, failure)
} }
w := lintAddConstantRule{onFailure: onFailure, strLits: make(map[string]int), strLitLimit: r.strLitLimit, whiteLst: r.whiteList} w := lintAddConstantRule{
onFailure: onFailure,
strLits: make(map[string]int),
strLitLimit: r.strLitLimit,
whiteLst: r.whiteList,
ignoreFunctions: r.ignoreFunctions,
}
ast.Walk(w, file.AST) ast.Walk(w, file.AST)
@ -64,13 +72,54 @@ type lintAddConstantRule struct {
strLits map[string]int strLits map[string]int
strLitLimit int strLitLimit int
whiteLst whiteList whiteLst whiteList
ignoreFunctions []*regexp.Regexp
} }
func (w lintAddConstantRule) Visit(node ast.Node) ast.Visitor { func (w lintAddConstantRule) Visit(node ast.Node) ast.Visitor {
switch n := node.(type) { switch n := node.(type) {
case *ast.CallExpr:
w.checkFunc(n)
return nil
case *ast.GenDecl: case *ast.GenDecl:
return nil // skip declarations return nil // skip declarations
case *ast.BasicLit: case *ast.BasicLit:
w.checkLit(n)
}
return w
}
func (w lintAddConstantRule) checkFunc(expr *ast.CallExpr) {
fName := w.getFuncName(expr)
for _, arg := range expr.Args {
switch t := arg.(type) {
case *ast.CallExpr:
w.checkFunc(t)
case *ast.BasicLit:
if w.isIgnoredFunc(fName) {
continue
}
w.checkLit(t)
}
}
}
func (w lintAddConstantRule) getFuncName(expr *ast.CallExpr) string {
switch f := expr.Fun.(type) {
case *ast.SelectorExpr:
switch prefix := f.X.(type) {
case *ast.Ident:
return prefix.Name + "." + f.Sel.Name
}
case *ast.Ident:
return f.Name
}
return ""
}
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)
@ -79,7 +128,14 @@ func (w lintAddConstantRule) Visit(node ast.Node) ast.Visitor {
} }
} }
return w func (w lintAddConstantRule) isIgnoredFunc(fName string) bool {
for _, pattern := range w.ignoreFunctions {
if pattern.MatchString(fName) {
return true
}
}
return false
} }
func (w lintAddConstantRule) checkStrLit(n *ast.BasicLit) { func (w lintAddConstantRule) checkStrLit(n *ast.BasicLit) {
@ -158,6 +214,25 @@ func (r *AddConstantRule) configure(arguments lint.Arguments) {
panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v)) panic(fmt.Sprintf("Invalid argument to the add-constant rule, expecting string representation of an integer. Got '%v'", v))
} }
r.strLitLimit = limit r.strLitLimit = limit
case "ignoreFuncs":
excludes, ok := v.(string)
if !ok {
panic(fmt.Sprintf("Invalid argument to the ignoreFuncs parameter of add-constant rule, string expected. Got '%v' (%T)", v, v))
}
for _, exclude := range strings.Split(excludes, ",") {
exclude = strings.Trim(exclude, " ")
if exclude == "" {
panic("Invalid argument to the ignoreFuncs parameter of add-constant rule, expected regular expression must not be empty.")
}
exp, err := regexp.Compile(exclude)
if err != nil {
panic(fmt.Sprintf("Invalid argument to the ignoreFuncs parameter of add-constant rule: regexp %q does not compile: %v", exclude, err))
}
r.ignoreFunctions = append(r.ignoreFunctions, exp)
}
} }
} }
} }

View File

@ -13,6 +13,7 @@ func TestAddConstant(t *testing.T) {
"allowStrs": "\"\"", "allowStrs": "\"\"",
"allowInts": "0,1,2", "allowInts": "0,1,2",
"allowFloats": "0.0,1.0", "allowFloats": "0.0,1.0",
"ignoreFuncs": "os\\.(CreateFile|WriteFile|Chmod|FindProcess),.Println,ignoredFunc",
}} }}
testRule(t, "add-constant", &rule.AddConstantRule{}, &lint.RuleConfig{ testRule(t, "add-constant", &rule.AddConstantRule{}, &lint.RuleConfig{

View File

@ -1,5 +1,10 @@
package fixtures package fixtures
import (
"fmt"
"os"
)
func foo(a, b, c, d int) { func foo(a, b, c, d int) {
a = 1.0 // ignore a = 1.0 // ignore
b = "ignore" b = "ignore"
@ -13,4 +18,34 @@ func foo(a, b, c, d int) {
println("lit") println("lit")
} }
} }
println(0666) // MATCH /avoid magic numbers like '0666', create a named constant for it/
os.Chmod("test", 0666) // ignore
os.FindProcess(102100) // ignore
fmt.Println("test", 12) // ignore
fmt.Printf("%d", 100) // MATCH /avoid magic numbers like '100', create a named constant for it/
ignoredFunc(1000) // ignore
println("The result of calling myFunc is: ", ignoredFunc(100)) // ignore
println("result is: ", ignoredFunc(notIgnoredFunc(ignoredFunc(100)))) // ignore
println("result of calling myFunc is: ", notIgnoredFunc(ignoredFunc(100))) // ignore
println("result myFunc is: ", notIgnoredFunc(100)) // MATCH /avoid magic numbers like '100', create a named constant for it/
println("The result is: ", ignoredFunc(notIgnoredFunc(100))) // MATCH /avoid magic numbers like '100', create a named constant for it/
}
func myPrintln(s string, num int) {
}
func not2ignoredFunc(num int) int {
return num
}
func ignoredFunc(num int) int {
return num
}
func notIgnoredFunc(num int) int {
return num
} }