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