github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/addon/rules/enumFieldNamesUpperSnakeCaseRule.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/report"
     9  	"github.com/yoheimuta/protolint/linter/rule"
    10  	"github.com/yoheimuta/protolint/linter/strs"
    11  	"github.com/yoheimuta/protolint/linter/visitor"
    12  )
    13  
    14  // EnumFieldNamesUpperSnakeCaseRule verifies that all enum field names are CAPITALS_WITH_UNDERSCORES.
    15  // See https://developers.google.com/protocol-buffers/docs/style#enums.
    16  type EnumFieldNamesUpperSnakeCaseRule struct {
    17  	RuleWithSeverity
    18  	fixMode         bool
    19  	autoDisableType autodisable.PlacementType
    20  }
    21  
    22  // NewEnumFieldNamesUpperSnakeCaseRule creates a new EnumFieldNamesUpperSnakeCaseRule.
    23  func NewEnumFieldNamesUpperSnakeCaseRule(
    24  	severity rule.Severity,
    25  	fixMode bool,
    26  	autoDisableType autodisable.PlacementType,
    27  ) EnumFieldNamesUpperSnakeCaseRule {
    28  	if autoDisableType != autodisable.Noop {
    29  		fixMode = false
    30  	}
    31  	return EnumFieldNamesUpperSnakeCaseRule{
    32  		RuleWithSeverity: RuleWithSeverity{severity: severity},
    33  		fixMode:          fixMode,
    34  		autoDisableType:  autoDisableType,
    35  	}
    36  }
    37  
    38  // ID returns the ID of this rule.
    39  func (r EnumFieldNamesUpperSnakeCaseRule) ID() string {
    40  	return "ENUM_FIELD_NAMES_UPPER_SNAKE_CASE"
    41  }
    42  
    43  // Purpose returns the purpose of this rule.
    44  func (r EnumFieldNamesUpperSnakeCaseRule) Purpose() string {
    45  	return "Verifies that all enum field names are CAPITALS_WITH_UNDERSCORES."
    46  }
    47  
    48  // IsOfficial decides whether or not this rule belongs to the official guide.
    49  func (r EnumFieldNamesUpperSnakeCaseRule) IsOfficial() bool {
    50  	return true
    51  }
    52  
    53  // Apply applies the rule to the proto.
    54  func (r EnumFieldNamesUpperSnakeCaseRule) Apply(proto *parser.Proto) ([]report.Failure, error) {
    55  	base, err := visitor.NewBaseFixableVisitor(r.ID(), r.fixMode, proto, string(r.Severity()))
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  
    60  	v := &enumFieldNamesUpperSnakeCaseVisitor{
    61  		BaseFixableVisitor: base,
    62  	}
    63  	return visitor.RunVisitorAutoDisable(v, proto, r.ID(), r.autoDisableType)
    64  }
    65  
    66  type enumFieldNamesUpperSnakeCaseVisitor struct {
    67  	*visitor.BaseFixableVisitor
    68  }
    69  
    70  // VisitEnumField checks the enum field.
    71  func (v *enumFieldNamesUpperSnakeCaseVisitor) VisitEnumField(field *parser.EnumField) bool {
    72  	name := field.Ident
    73  	if !strs.IsUpperSnakeCase(name) {
    74  		expected := strs.ToUpperSnakeCase(name)
    75  		v.AddFailuref(field.Meta.Pos, "EnumField name %q must be CAPITALS_WITH_UNDERSCORES like %q", name, expected)
    76  
    77  		err := v.Fixer.SearchAndReplace(field.Meta.Pos, func(lex *lexer.Lexer) fixer.TextEdit {
    78  			lex.Next()
    79  			return fixer.TextEdit{
    80  				Pos:     lex.Pos.Offset,
    81  				End:     lex.Pos.Offset + len(lex.Text) - 1,
    82  				NewText: []byte(expected),
    83  			}
    84  		})
    85  		if err != nil {
    86  			panic(err)
    87  		}
    88  	}
    89  	return false
    90  }