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

     1  package rule
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"strings"
     7  
     8  	"github.com/mgechev/revive/lint"
     9  )
    10  
    11  // GetReturnRule lints given else constructs.
    12  type GetReturnRule struct{}
    13  
    14  // Apply applies the rule to given file.
    15  func (r *GetReturnRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
    16  	var failures []lint.Failure
    17  
    18  	onFailure := func(failure lint.Failure) {
    19  		failures = append(failures, failure)
    20  	}
    21  
    22  	w := lintReturnRule{onFailure}
    23  	ast.Walk(w, file.AST)
    24  	return failures
    25  }
    26  
    27  // Name returns the rule name.
    28  func (r *GetReturnRule) Name() string {
    29  	return "get-return"
    30  }
    31  
    32  type lintReturnRule struct {
    33  	onFailure func(lint.Failure)
    34  }
    35  
    36  func isGetter(name string) bool {
    37  	if strings.HasPrefix(strings.ToUpper(name), "GET") {
    38  		if len(name) > 3 {
    39  			c := name[3]
    40  			return !(c >= 'a' && c <= 'z')
    41  		}
    42  	}
    43  
    44  	return false
    45  }
    46  
    47  func hasResults(rs *ast.FieldList) bool {
    48  	return rs != nil && len(rs.List) > 0
    49  }
    50  
    51  func (w lintReturnRule) Visit(node ast.Node) ast.Visitor {
    52  	fd, ok := node.(*ast.FuncDecl)
    53  	if !ok {
    54  		return w
    55  	}
    56  
    57  	if !isGetter(fd.Name.Name) {
    58  		return w
    59  	}
    60  	if !hasResults(fd.Type.Results) {
    61  		w.onFailure(lint.Failure{
    62  			Confidence: 0.8,
    63  			Node:       fd,
    64  			Category:   "logic",
    65  			Failure:    fmt.Sprintf("function '%s' seems to be a getter but it does not return any result", fd.Name.Name),
    66  		})
    67  	}
    68  
    69  	return w
    70  }