github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/confusing-results.go (about)

     1  package rule
     2  
     3  import (
     4  	"go/ast"
     5  
     6  	"github.com/mgechev/revive/lint"
     7  )
     8  
     9  // ConfusingResultsRule lints given function declarations
    10  type ConfusingResultsRule struct{}
    11  
    12  // Apply applies the rule to given file.
    13  func (r *ConfusingResultsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
    14  	var failures []lint.Failure
    15  
    16  	fileAst := file.AST
    17  	walker := lintConfusingResults{
    18  		onFailure: func(failure lint.Failure) {
    19  			failures = append(failures, failure)
    20  		},
    21  	}
    22  
    23  	ast.Walk(walker, fileAst)
    24  
    25  	return failures
    26  }
    27  
    28  // Name returns the rule name.
    29  func (r *ConfusingResultsRule) Name() string {
    30  	return "confusing-results"
    31  }
    32  
    33  type lintConfusingResults struct {
    34  	onFailure func(lint.Failure)
    35  }
    36  
    37  func (w lintConfusingResults) Visit(n ast.Node) ast.Visitor {
    38  	fn, ok := n.(*ast.FuncDecl)
    39  	if !ok || fn.Type.Results == nil || len(fn.Type.Results.List) < 2 {
    40  		return w
    41  	}
    42  	lastType := ""
    43  	for _, result := range fn.Type.Results.List {
    44  		if len(result.Names) > 0 {
    45  			return w
    46  		}
    47  
    48  		t, ok := result.Type.(*ast.Ident)
    49  		if !ok {
    50  			return w
    51  		}
    52  
    53  		if t.Name == lastType {
    54  			w.onFailure(lint.Failure{
    55  				Node:       n,
    56  				Confidence: 1,
    57  				Category:   "naming",
    58  				Failure:    "unnamed results of the same type may be confusing, consider using named results",
    59  			})
    60  			break
    61  		}
    62  		lastType = t.Name
    63  
    64  	}
    65  
    66  	return w
    67  }