github.com/azazeal/revive@v1.0.9/rule/modifies-param.go (about)

     1  package rule
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  
     7  	"github.com/azazeal/revive/lint"
     8  )
     9  
    10  // ModifiesParamRule lints given else constructs.
    11  type ModifiesParamRule struct{}
    12  
    13  // Apply applies the rule to given file.
    14  func (r *ModifiesParamRule) 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 := lintModifiesParamRule{onFailure: onFailure}
    22  	ast.Walk(w, file.AST)
    23  	return failures
    24  }
    25  
    26  // Name returns the rule name.
    27  func (r *ModifiesParamRule) Name() string {
    28  	return "modifies-parameter"
    29  }
    30  
    31  type lintModifiesParamRule struct {
    32  	params    map[string]bool
    33  	onFailure func(lint.Failure)
    34  }
    35  
    36  func retrieveParamNames(pl []*ast.Field) map[string]bool {
    37  	result := make(map[string]bool, len(pl))
    38  	for _, p := range pl {
    39  		for _, n := range p.Names {
    40  			if n.Name == "_" {
    41  				continue
    42  			}
    43  
    44  			result[n.Name] = true
    45  		}
    46  	}
    47  	return result
    48  }
    49  
    50  func (w lintModifiesParamRule) Visit(node ast.Node) ast.Visitor {
    51  	switch v := node.(type) {
    52  	case *ast.FuncDecl:
    53  		w.params = retrieveParamNames(v.Type.Params.List)
    54  	case *ast.IncDecStmt:
    55  		if id, ok := v.X.(*ast.Ident); ok {
    56  			checkParam(id, &w)
    57  		}
    58  	case *ast.AssignStmt:
    59  		lhs := v.Lhs
    60  		for _, e := range lhs {
    61  			id, ok := e.(*ast.Ident)
    62  			if ok {
    63  				checkParam(id, &w)
    64  			}
    65  		}
    66  	}
    67  
    68  	return w
    69  }
    70  
    71  func checkParam(id *ast.Ident, w *lintModifiesParamRule) {
    72  	if w.params[id.Name] {
    73  		w.onFailure(lint.Failure{
    74  			Confidence: 0.5, // confidence is low because of shadow variables
    75  			Node:       id,
    76  			Category:   "bad practice",
    77  			Failure:    fmt.Sprintf("parameter '%s' seems to be modified", id),
    78  		})
    79  	}
    80  }