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

     1  package rules
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/yoheimuta/go-protoparser/v4/parser"
     7  
     8  	"github.com/yoheimuta/protolint/internal/stringsutil"
     9  	"github.com/yoheimuta/protolint/linter/report"
    10  	"github.com/yoheimuta/protolint/linter/rule"
    11  	"github.com/yoheimuta/protolint/linter/strs"
    12  	"github.com/yoheimuta/protolint/linter/visitor"
    13  )
    14  
    15  // MessageNamesExcludePrepositionsRule verifies that all message names don't include prepositions (e.g. "With", "For").
    16  // It is assumed that the message names are CamelCase (with an initial capital).
    17  // See https://cloud.google.com/apis/design/naming_convention#message_names.
    18  type MessageNamesExcludePrepositionsRule struct {
    19  	RuleWithSeverity
    20  	prepositions []string
    21  	excludes     []string
    22  }
    23  
    24  // NewMessageNamesExcludePrepositionsRule creates a new MessageNamesExcludePrepositionsRule.
    25  func NewMessageNamesExcludePrepositionsRule(
    26  	severity rule.Severity,
    27  	prepositions []string,
    28  	excludes []string,
    29  ) MessageNamesExcludePrepositionsRule {
    30  	if len(prepositions) == 0 {
    31  		for _, p := range defaultPrepositions {
    32  			prepositions = append(prepositions, strings.Title(p))
    33  		}
    34  	}
    35  	return MessageNamesExcludePrepositionsRule{
    36  		RuleWithSeverity: RuleWithSeverity{severity: severity},
    37  		prepositions:     prepositions,
    38  		excludes:         excludes,
    39  	}
    40  }
    41  
    42  // ID returns the ID of this rule.
    43  func (r MessageNamesExcludePrepositionsRule) ID() string {
    44  	return "MESSAGE_NAMES_EXCLUDE_PREPOSITIONS"
    45  }
    46  
    47  // IsOfficial decides whether or not this rule belongs to the official guide.
    48  func (r MessageNamesExcludePrepositionsRule) IsOfficial() bool {
    49  	return false
    50  }
    51  
    52  // Purpose returns the purpose of this rule.
    53  func (r MessageNamesExcludePrepositionsRule) Purpose() string {
    54  	return `Verifies that all message names don't include prepositions (e.g. "With", "For").`
    55  }
    56  
    57  // Apply applies the rule to the proto.
    58  func (r MessageNamesExcludePrepositionsRule) Apply(proto *parser.Proto) ([]report.Failure, error) {
    59  	v := &messageNamesExcludePrepositionsVisitor{
    60  		BaseAddVisitor: visitor.NewBaseAddVisitor(r.ID(), string(r.Severity())),
    61  		prepositions:   r.prepositions,
    62  		excludes:       r.excludes,
    63  	}
    64  	return visitor.RunVisitor(v, proto, r.ID())
    65  }
    66  
    67  type messageNamesExcludePrepositionsVisitor struct {
    68  	*visitor.BaseAddVisitor
    69  	prepositions []string
    70  	excludes     []string
    71  }
    72  
    73  // VisitMessage checks the message.
    74  func (v *messageNamesExcludePrepositionsVisitor) VisitMessage(message *parser.Message) bool {
    75  	name := message.MessageName
    76  	for _, e := range v.excludes {
    77  		name = strings.Replace(name, e, "", -1)
    78  	}
    79  
    80  	parts := strs.SplitCamelCaseWord(name)
    81  	for _, p := range parts {
    82  		if stringsutil.ContainsStringInSlice(p, v.prepositions) {
    83  			v.AddFailuref(message.Meta.Pos, "Message name %q should not include a preposition %q", message.MessageName, p)
    84  		}
    85  	}
    86  	return true
    87  }