github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/addon/rules/packageNameLowerCaseRule.go (about) 1 package rules 2 3 import ( 4 "strings" 5 6 "github.com/yoheimuta/go-protoparser/v4/lexer" 7 "github.com/yoheimuta/go-protoparser/v4/parser" 8 "github.com/yoheimuta/protolint/linter/fixer" 9 "github.com/yoheimuta/protolint/linter/rule" 10 11 "github.com/yoheimuta/protolint/linter/report" 12 "github.com/yoheimuta/protolint/linter/strs" 13 "github.com/yoheimuta/protolint/linter/visitor" 14 ) 15 16 // PackageNameLowerCaseRule verifies that the package name doesn't contain any uppercase letters. 17 // See https://developers.google.com/protocol-buffers/docs/style#packages. 18 type PackageNameLowerCaseRule struct { 19 RuleWithSeverity 20 fixMode bool 21 } 22 23 // NewPackageNameLowerCaseRule creates a new PackageNameLowerCaseRule. 24 func NewPackageNameLowerCaseRule( 25 severity rule.Severity, 26 fixMode bool, 27 ) PackageNameLowerCaseRule { 28 return PackageNameLowerCaseRule{ 29 RuleWithSeverity: RuleWithSeverity{severity: severity}, 30 fixMode: fixMode, 31 } 32 } 33 34 // ID returns the ID of this rule. 35 func (r PackageNameLowerCaseRule) ID() string { 36 return "PACKAGE_NAME_LOWER_CASE" 37 } 38 39 // Purpose returns the purpose of this rule. 40 func (r PackageNameLowerCaseRule) Purpose() string { 41 return "Verifies that the package name doesn't contain any uppercase letters." 42 } 43 44 // IsOfficial decides whether or not this rule belongs to the official guide. 45 func (r PackageNameLowerCaseRule) IsOfficial() bool { 46 return true 47 } 48 49 // Apply applies the rule to the proto. 50 func (r PackageNameLowerCaseRule) Apply(proto *parser.Proto) ([]report.Failure, error) { 51 base, err := visitor.NewBaseFixableVisitor(r.ID(), r.fixMode, proto, string(r.Severity())) 52 if err != nil { 53 return nil, err 54 } 55 56 v := &packageNameLowerCaseVisitor{ 57 BaseFixableVisitor: base, 58 } 59 return visitor.RunVisitor(v, proto, r.ID()) 60 } 61 62 type packageNameLowerCaseVisitor struct { 63 *visitor.BaseFixableVisitor 64 } 65 66 // VisitPackage checks the package. 67 func (v *packageNameLowerCaseVisitor) VisitPackage(p *parser.Package) bool { 68 name := p.Name 69 if !isPackageLowerCase(name) { 70 expected := strings.ToLower(name) 71 v.AddFailuref(p.Meta.Pos, "Package name %q must not contain any uppercase letter. Consider to change like %q.", name, expected) 72 73 err := v.Fixer.SearchAndReplace(p.Meta.Pos, func(lex *lexer.Lexer) fixer.TextEdit { 74 lex.NextKeyword() 75 ident, startPos, _ := lex.ReadFullIdent() 76 return fixer.TextEdit{ 77 Pos: startPos.Offset, 78 End: startPos.Offset + len(ident) - 1, 79 NewText: []byte(expected), 80 } 81 }) 82 if err != nil { 83 panic(err) 84 } 85 } 86 return false 87 } 88 89 func isPackageLowerCase(packageName string) bool { 90 return !strs.HasAnyUpperCase(packageName) 91 }