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

     1  package rule
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  
     7  	"github.com/mgechev/revive/lint"
     8  )
     9  
    10  // ReceiverNamingRule lints given else constructs.
    11  type ReceiverNamingRule struct{}
    12  
    13  // Apply applies the rule to given file.
    14  func (r *ReceiverNamingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
    15  	var failures []lint.Failure
    16  
    17  	fileAst := file.AST
    18  	walker := lintReceiverName{
    19  		onFailure: func(failure lint.Failure) {
    20  			failures = append(failures, failure)
    21  		},
    22  		typeReceiver: map[string]string{},
    23  	}
    24  
    25  	ast.Walk(walker, fileAst)
    26  
    27  	return failures
    28  }
    29  
    30  // Name returns the rule name.
    31  func (r *ReceiverNamingRule) Name() string {
    32  	return "receiver-naming"
    33  }
    34  
    35  type lintReceiverName struct {
    36  	onFailure    func(lint.Failure)
    37  	typeReceiver map[string]string
    38  }
    39  
    40  func (w lintReceiverName) Visit(n ast.Node) ast.Visitor {
    41  	fn, ok := n.(*ast.FuncDecl)
    42  	if !ok || fn.Recv == nil || len(fn.Recv.List) == 0 {
    43  		return w
    44  	}
    45  	names := fn.Recv.List[0].Names
    46  	if len(names) < 1 {
    47  		return w
    48  	}
    49  	name := names[0].Name
    50  	const ref = styleGuideBase + "#receiver-names"
    51  	if name == "_" {
    52  		w.onFailure(lint.Failure{
    53  			Node:       n,
    54  			Confidence: 1,
    55  			Category:   "naming",
    56  			Failure:    "receiver name should not be an underscore, omit the name if it is unused",
    57  		})
    58  		return w
    59  	}
    60  	if name == "this" || name == "self" {
    61  		w.onFailure(lint.Failure{
    62  			Node:       n,
    63  			Confidence: 1,
    64  			Category:   "naming",
    65  			Failure:    `receiver name should be a reflection of its identity; don't use generic names such as "this" or "self"`,
    66  		})
    67  		return w
    68  	}
    69  	recv := receiverType(fn)
    70  	if prev, ok := w.typeReceiver[recv]; ok && prev != name {
    71  		w.onFailure(lint.Failure{
    72  			Node:       n,
    73  			Confidence: 1,
    74  			Category:   "naming",
    75  			Failure:    fmt.Sprintf("receiver name %s should be consistent with previous receiver name %s for %s", name, prev, recv),
    76  		})
    77  		return w
    78  	}
    79  	w.typeReceiver[recv] = name
    80  	return w
    81  }