github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/flag-param.go (about) 1 package rule 2 3 import ( 4 "fmt" 5 "github.com/mgechev/revive/lint" 6 "go/ast" 7 ) 8 9 // FlagParamRule lints given else constructs. 10 type FlagParamRule struct{} 11 12 // Apply applies the rule to given file. 13 func (r *FlagParamRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 14 var failures []lint.Failure 15 16 onFailure := func(failure lint.Failure) { 17 failures = append(failures, failure) 18 } 19 20 w := lintFlagParamRule{onFailure: onFailure} 21 ast.Walk(w, file.AST) 22 return failures 23 } 24 25 // Name returns the rule name. 26 func (r *FlagParamRule) Name() string { 27 return "flag-parameter" 28 } 29 30 type lintFlagParamRule struct { 31 onFailure func(lint.Failure) 32 } 33 34 func (w lintFlagParamRule) Visit(node ast.Node) ast.Visitor { 35 fd, ok := node.(*ast.FuncDecl) 36 if !ok { 37 return w 38 } 39 40 if fd.Body == nil { 41 return nil // skip whole function declaration 42 } 43 44 for _, p := range fd.Type.Params.List { 45 t := p.Type 46 47 id, ok := t.(*ast.Ident) 48 if !ok { 49 continue 50 } 51 52 if id.Name != "bool" { 53 continue 54 } 55 56 cv := conditionVisitor{p.Names, fd, w} 57 ast.Walk(cv, fd.Body) 58 } 59 60 return w 61 } 62 63 type conditionVisitor struct { 64 ids []*ast.Ident 65 fd *ast.FuncDecl 66 linter lintFlagParamRule 67 } 68 69 func (w conditionVisitor) Visit(node ast.Node) ast.Visitor { 70 ifStmt, ok := node.(*ast.IfStmt) 71 if !ok { 72 return w 73 } 74 75 fselect := func(n ast.Node) bool { 76 ident, ok := n.(*ast.Ident) 77 if !ok { 78 return false 79 } 80 81 for _, id := range w.ids { 82 if ident.Name == id.Name { 83 return true 84 } 85 } 86 87 return false 88 } 89 90 uses := pick(ifStmt.Cond, fselect, nil) 91 92 if len(uses) < 1 { 93 return w 94 } 95 96 w.linter.onFailure(lint.Failure{ 97 Confidence: 1, 98 Node: w.fd.Type.Params, 99 Category: "bad practice", 100 Failure: fmt.Sprintf("parameter '%s' seems to be a control flag, avoid control coupling", uses[0]), 101 }) 102 103 return nil 104 }