1
0
mirror of https://github.com/mgechev/revive.git synced 2025-04-13 11:30:36 +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
* `allowInts`: (string) comma-separated list of allowed integers
* `allowFloats`: (string) comma-separated list of allowed floats
* `ignoreFuncs`: (string) comma-separated list of function names regexp patterns to exclude
Example:
```toml
[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

View File

@ -3,6 +3,7 @@ package rule
import (
"fmt"
"go/ast"
"regexp"
"strconv"
"strings"
"sync"
@ -32,8 +33,9 @@ func (wl whiteList) add(kind, list string) {
// AddConstantRule lints unused params in functions.
type AddConstantRule struct {
whiteList whiteList
strLitLimit int
whiteList whiteList
ignoreFunctions []*regexp.Regexp
strLitLimit int
sync.Mutex
}
@ -47,7 +49,13 @@ func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lin
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)
@ -60,28 +68,76 @@ func (*AddConstantRule) Name() string {
}
type lintAddConstantRule struct {
onFailure func(lint.Failure)
strLits map[string]int
strLitLimit int
whiteLst whiteList
onFailure func(lint.Failure)
strLits map[string]int
strLitLimit int
whiteLst whiteList
ignoreFunctions []*regexp.Regexp
}
func (w lintAddConstantRule) Visit(node ast.Node) ast.Visitor {
switch n := node.(type) {
case *ast.CallExpr:
w.checkFunc(n)
return nil
case *ast.GenDecl:
return nil // skip declarations
case *ast.BasicLit:
switch kind := n.Kind.String(); kind {
case kindFLOAT, kindINT:
w.checkNumLit(kind, n)
case kindSTRING:
w.checkStrLit(n)
}
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 {
case kindFLOAT, kindINT:
w.checkNumLit(kind, n)
case kindSTRING:
w.checkStrLit(n)
}
}
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) {
if w.whiteLst[kindSTRING][n.Value] {
return
@ -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))
}
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": "\"\"",
"allowInts": "0,1,2",
"allowFloats": "0.0,1.0",
"ignoreFuncs": "os\\.(CreateFile|WriteFile|Chmod|FindProcess),.Println,ignoredFunc",
}}
testRule(t, "add-constant", &rule.AddConstantRule{}, &lint.RuleConfig{

View File

@ -1,5 +1,10 @@
package fixtures
import (
"fmt"
"os"
)
func foo(a, b, c, d int) {
a = 1.0 // ignore
b = "ignore"
@ -13,4 +18,34 @@ func foo(a, b, c, d int) {
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
}