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 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:
parent
5cc9e27ddb
commit
3d83403fb8
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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{
|
||||
|
35
testdata/add-constant.go
vendored
35
testdata/add-constant.go
vendored
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user