github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/addon/rules/rpcNamesUpperCamelCaseRule.go (about)

     1  package rules
     2  
     3  import (
     4  	"github.com/yoheimuta/go-protoparser/v4/lexer"
     5  	"github.com/yoheimuta/go-protoparser/v4/parser"
     6  	"github.com/yoheimuta/protolint/linter/autodisable"
     7  	"github.com/yoheimuta/protolint/linter/fixer"
     8  	"github.com/yoheimuta/protolint/linter/rule"
     9  
    10  	"github.com/yoheimuta/protolint/linter/report"
    11  	"github.com/yoheimuta/protolint/linter/strs"
    12  	"github.com/yoheimuta/protolint/linter/visitor"
    13  )
    14  
    15  // RPCNamesUpperCamelCaseRule verifies that all rpc names are CamelCase (with an initial capital).
    16  // See https://developers.google.com/protocol-buffers/docs/style#services.
    17  type RPCNamesUpperCamelCaseRule struct {
    18  	RuleWithSeverity
    19  	fixMode         bool
    20  	autoDisableType autodisable.PlacementType
    21  }
    22  
    23  // NewRPCNamesUpperCamelCaseRule creates a new RPCNamesUpperCamelCaseRule.
    24  func NewRPCNamesUpperCamelCaseRule(
    25  	severity rule.Severity,
    26  	fixMode bool,
    27  	autoDisableType autodisable.PlacementType,
    28  ) RPCNamesUpperCamelCaseRule {
    29  	if autoDisableType != autodisable.Noop {
    30  		fixMode = false
    31  	}
    32  	return RPCNamesUpperCamelCaseRule{
    33  		RuleWithSeverity: RuleWithSeverity{severity: severity},
    34  		fixMode:          fixMode,
    35  		autoDisableType:  autoDisableType,
    36  	}
    37  }
    38  
    39  // ID returns the ID of this rule.
    40  func (r RPCNamesUpperCamelCaseRule) ID() string {
    41  	return "RPC_NAMES_UPPER_CAMEL_CASE"
    42  }
    43  
    44  // Purpose returns the purpose of this rule.
    45  func (r RPCNamesUpperCamelCaseRule) Purpose() string {
    46  	return "Verifies that all rpc names are CamelCase (with an initial capital)."
    47  }
    48  
    49  // IsOfficial decides whether or not this rule belongs to the official guide.
    50  func (r RPCNamesUpperCamelCaseRule) IsOfficial() bool {
    51  	return true
    52  }
    53  
    54  // Apply applies the rule to the proto.
    55  func (r RPCNamesUpperCamelCaseRule) Apply(proto *parser.Proto) ([]report.Failure, error) {
    56  	base, err := visitor.NewBaseFixableVisitor(r.ID(), r.fixMode, proto, string(r.Severity()))
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	v := &rpcNamesUpperCamelCaseVisitor{
    62  		BaseFixableVisitor: base,
    63  	}
    64  	return visitor.RunVisitorAutoDisable(v, proto, r.ID(), r.autoDisableType)
    65  }
    66  
    67  type rpcNamesUpperCamelCaseVisitor struct {
    68  	*visitor.BaseFixableVisitor
    69  }
    70  
    71  // VisitRPC checks the rpc.
    72  func (v *rpcNamesUpperCamelCaseVisitor) VisitRPC(rpc *parser.RPC) bool {
    73  	name := rpc.RPCName
    74  	if !strs.IsUpperCamelCase(name) {
    75  		expected := strs.ToUpperCamelCase(name)
    76  		v.AddFailuref(rpc.Meta.Pos, "RPC name %q must be UpperCamelCase like %q", name, expected)
    77  
    78  		err := v.Fixer.SearchAndReplace(rpc.Meta.Pos, func(lex *lexer.Lexer) fixer.TextEdit {
    79  			lex.NextKeyword()
    80  			lex.Next()
    81  			return fixer.TextEdit{
    82  				Pos:     lex.Pos.Offset,
    83  				End:     lex.Pos.Offset + len(lex.Text) - 1,
    84  				NewText: []byte(expected),
    85  			}
    86  		})
    87  		if err != nil {
    88  			panic(err)
    89  		}
    90  	}
    91  	return false
    92  }