github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/unused-param.go (about) 1 package rule 2 3 import ( 4 "fmt" 5 "go/ast" 6 7 "github.com/mgechev/revive/lint" 8 ) 9 10 // UnusedParamRule lints unused params in functions. 11 type UnusedParamRule struct{} 12 13 // Apply applies the rule to given file. 14 func (r *UnusedParamRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 15 var failures []lint.Failure 16 17 onFailure := func(failure lint.Failure) { 18 failures = append(failures, failure) 19 } 20 21 w := lintUnusedParamRule{onFailure: onFailure} 22 23 ast.Walk(w, file.AST) 24 25 return failures 26 } 27 28 // Name returns the rule name. 29 func (r *UnusedParamRule) Name() string { 30 return "unused-parameter" 31 } 32 33 type lintUnusedParamRule struct { 34 onFailure func(lint.Failure) 35 } 36 37 func (w lintUnusedParamRule) Visit(node ast.Node) ast.Visitor { 38 switch n := node.(type) { 39 case *ast.FuncDecl: 40 params := retrieveNamedParams(n.Type.Params) 41 if len(params) < 1 { 42 return nil // skip, func without parameters 43 } 44 45 if n.Body == nil { 46 return nil // skip, is a function prototype 47 } 48 49 // inspect the func body looking for references to parameters 50 fselect := func(n ast.Node) bool { 51 ident, isAnID := n.(*ast.Ident) 52 53 if !isAnID { 54 return false 55 } 56 57 _, isAParam := params[ident.Obj] 58 if isAParam { 59 params[ident.Obj] = false // mark as used 60 } 61 62 return false 63 } 64 _ = pick(n.Body, fselect, nil) 65 66 for _, p := range n.Type.Params.List { 67 for _, n := range p.Names { 68 if params[n.Obj] { 69 w.onFailure(lint.Failure{ 70 Confidence: 1, 71 Node: n, 72 Category: "bad practice", 73 Failure: fmt.Sprintf("parameter '%s' seems to be unused, consider removing or renaming it as _", n.Name), 74 }) 75 } 76 } 77 } 78 79 return nil // full method body already inspected 80 } 81 82 return w 83 } 84 85 func retrieveNamedParams(params *ast.FieldList) map[*ast.Object]bool { 86 result := map[*ast.Object]bool{} 87 if params.List == nil { 88 return result 89 } 90 91 for _, p := range params.List { 92 for _, n := range p.Names { 93 if n.Name == "_" { 94 continue 95 } 96 97 result[n.Obj] = true 98 } 99 } 100 101 return result 102 }