123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- package rule
-
- import (
- "fmt"
- "github.com/mgechev/revive/lint"
- "go/ast"
- )
-
- // FlagParamRule lints given else constructs.
- type FlagParamRule struct{}
-
- // Apply applies the rule to given file.
- func (r *FlagParamRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
- var failures []lint.Failure
-
- onFailure := func(failure lint.Failure) {
- failures = append(failures, failure)
- }
-
- w := lintFlagParamRule{onFailure: onFailure}
- ast.Walk(w, file.AST)
- return failures
- }
-
- // Name returns the rule name.
- func (r *FlagParamRule) Name() string {
- return "flag-parameter"
- }
-
- type lintFlagParamRule struct {
- onFailure func(lint.Failure)
- }
-
- func (w lintFlagParamRule) Visit(node ast.Node) ast.Visitor {
- fd, ok := node.(*ast.FuncDecl)
- if !ok {
- return w
- }
-
- if fd.Body == nil {
- return nil // skip whole function declaration
- }
-
- for _, p := range fd.Type.Params.List {
- t := p.Type
-
- id, ok := t.(*ast.Ident)
- if !ok {
- continue
- }
-
- if id.Name != "bool" {
- continue
- }
-
- cv := conditionVisitor{p.Names, fd, w}
- ast.Walk(cv, fd.Body)
- }
-
- return w
- }
-
- type conditionVisitor struct {
- ids []*ast.Ident
- fd *ast.FuncDecl
- linter lintFlagParamRule
- }
-
- func (w conditionVisitor) Visit(node ast.Node) ast.Visitor {
- ifStmt, ok := node.(*ast.IfStmt)
- if !ok {
- return w
- }
-
- fselect := func(n ast.Node) bool {
- ident, ok := n.(*ast.Ident)
- if !ok {
- return false
- }
-
- for _, id := range w.ids {
- if ident.Name == id.Name {
- return true
- }
- }
-
- return false
- }
-
- uses := pick(ifStmt.Cond, fselect, nil)
-
- if len(uses) < 1 {
- return w
- }
-
- w.linter.onFailure(lint.Failure{
- Confidence: 1,
- Node: w.fd.Type.Params,
- Category: "bad practice",
- Failure: fmt.Sprintf("parameter '%s' seems to be a control flag, avoid control coupling", uses[0]),
- })
-
- return nil
- }
|