github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/addon/rules/enumFieldNamesZeroValueEndWithRule.go (about) 1 package rules 2 3 import ( 4 "strings" 5 6 "github.com/yoheimuta/go-protoparser/v4/lexer" 7 "github.com/yoheimuta/protolint/linter/autodisable" 8 "github.com/yoheimuta/protolint/linter/fixer" 9 "github.com/yoheimuta/protolint/linter/rule" 10 11 "github.com/yoheimuta/go-protoparser/v4/parser" 12 13 "github.com/yoheimuta/protolint/linter/report" 14 "github.com/yoheimuta/protolint/linter/visitor" 15 ) 16 17 const ( 18 defaultSuffix = "UNSPECIFIED" 19 ) 20 21 // EnumFieldNamesZeroValueEndWithRule verifies that the zero value enum should have the suffix (e.g. "UNSPECIFIED", "INVALID"). 22 // See https://developers.google.com/protocol-buffers/docs/style#enums. 23 type EnumFieldNamesZeroValueEndWithRule struct { 24 RuleWithSeverity 25 suffix string 26 fixMode bool 27 autoDisableType autodisable.PlacementType 28 } 29 30 // NewEnumFieldNamesZeroValueEndWithRule creates a new EnumFieldNamesZeroValueEndWithRule. 31 func NewEnumFieldNamesZeroValueEndWithRule( 32 severity rule.Severity, 33 suffix string, 34 fixMode bool, 35 autoDisableType autodisable.PlacementType, 36 ) EnumFieldNamesZeroValueEndWithRule { 37 if len(suffix) == 0 { 38 suffix = defaultSuffix 39 } 40 if autoDisableType != autodisable.Noop { 41 fixMode = false 42 } 43 return EnumFieldNamesZeroValueEndWithRule{ 44 RuleWithSeverity: RuleWithSeverity{severity: severity}, 45 suffix: suffix, 46 fixMode: fixMode, 47 autoDisableType: autoDisableType, 48 } 49 } 50 51 // ID returns the ID of this rule. 52 func (r EnumFieldNamesZeroValueEndWithRule) ID() string { 53 return "ENUM_FIELD_NAMES_ZERO_VALUE_END_WITH" 54 } 55 56 // Purpose returns the purpose of this rule. 57 func (r EnumFieldNamesZeroValueEndWithRule) Purpose() string { 58 return `Verifies that the zero value enum should have the suffix (e.g. "UNSPECIFIED", "INVALID").` 59 } 60 61 // IsOfficial decides whether or not this rule belongs to the official guide. 62 func (r EnumFieldNamesZeroValueEndWithRule) IsOfficial() bool { 63 return true 64 } 65 66 // Apply applies the rule to the proto. 67 func (r EnumFieldNamesZeroValueEndWithRule) Apply(proto *parser.Proto) ([]report.Failure, error) { 68 base, err := visitor.NewBaseFixableVisitor(r.ID(), r.fixMode, proto, string(r.Severity())) 69 if err != nil { 70 return nil, err 71 } 72 73 v := &enumFieldNamesZeroValueEndWithVisitor{ 74 BaseFixableVisitor: base, 75 suffix: r.suffix, 76 } 77 return visitor.RunVisitorAutoDisable(v, proto, r.ID(), r.autoDisableType) 78 } 79 80 type enumFieldNamesZeroValueEndWithVisitor struct { 81 *visitor.BaseFixableVisitor 82 suffix string 83 } 84 85 // VisitEnumField checks the enum field. 86 func (v *enumFieldNamesZeroValueEndWithVisitor) VisitEnumField(field *parser.EnumField) bool { 87 if field.Number == "0" && !strings.HasSuffix(field.Ident, v.suffix) { 88 v.AddFailuref(field.Meta.Pos, "EnumField name %q with zero value should have the suffix %q", field.Ident, v.suffix) 89 90 expected := field.Ident + "_" + v.suffix 91 err := v.Fixer.SearchAndReplace(field.Meta.Pos, func(lex *lexer.Lexer) fixer.TextEdit { 92 lex.Next() 93 return fixer.TextEdit{ 94 Pos: lex.Pos.Offset, 95 End: lex.Pos.Offset + len(lex.Text) - 1, 96 NewText: []byte(expected), 97 } 98 }) 99 if err != nil { 100 panic(err) 101 } 102 } 103 return false 104 }