Skip to content

Commit

Permalink
Merge pull request #203 from yoheimuta/enumNamesUpperCamelCase-fixer
Browse files Browse the repository at this point in the history
feat: Support a fixer for EnumNamesUpperCamelCase
  • Loading branch information
yoheimuta authored Jan 15, 2022
2 parents d270cf8 + 4192680 commit 1656b45
Show file tree
Hide file tree
Showing 13 changed files with 290 additions and 53 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ Some rules support a feature that automatically fixed the problems.
- IMPORTS_SORTED
- INDENT
- QUOTE_CONSISTENT
- ENUM_NAMES_UPPER_CAMEL_CASE

| Official | ID | Purpose |
|----------|-----------------------------------|--------------------------------------------------------------------------|
Expand Down
23 changes: 23 additions & 0 deletions _testdata/rules/enumNamesUpperCamelCase/invalid.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
syntax = "proto3";

enum enum {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 2 [(custom_option) = "hello world"];
}

enum Enum_allowing_alias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 2 [(custom_option) = "hello world"];
}

enum enumAllowing {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 2 [(custom_option) = "hello world"];
}

23 changes: 23 additions & 0 deletions _testdata/rules/enumNamesUpperCamelCase/upperCamelCase.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
syntax = "proto3";

enum Enum {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 2 [(custom_option) = "hello world"];
}

enum EnumAllowingAlias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 2 [(custom_option) = "hello world"];
}

enum EnumAllowing {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 2 [(custom_option) = "hello world"];
}

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ require (
github.com/golang/protobuf v1.5.2
github.com/hashicorp/go-hclog v1.0.0
github.com/hashicorp/go-plugin v1.4.3
github.com/yoheimuta/go-protoparser/v4 v4.4.0
github.com/yoheimuta/go-protoparser/v4 v4.5.0
google.golang.org/grpc v1.42.0
gopkg.in/yaml.v2 v2.4.0
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yoheimuta/go-protoparser/v4 v4.4.0 h1:aFvfPXEOAuxguLQAlRaSo9hyI1E8VuF+iZVAyP8hc0s=
github.com/yoheimuta/go-protoparser/v4 v4.4.0/go.mod h1:AHNNnSWnb0UoL4QgHPiOAg2BniQceFscPI5X/BZNHl8=
github.com/yoheimuta/go-protoparser/v4 v4.5.0 h1:Qna+FG1vYTtgPTNsPlwLu74aDhUiW7/UwXvAeu5EFvY=
github.com/yoheimuta/go-protoparser/v4 v4.5.0/go.mod h1:AHNNnSWnb0UoL4QgHPiOAg2BniQceFscPI5X/BZNHl8=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
Expand Down
42 changes: 35 additions & 7 deletions internal/addon/rules/enumNamesUpperCamelCaseRule.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package rules

import (
"github.com/yoheimuta/go-protoparser/v4/lexer"
"github.com/yoheimuta/go-protoparser/v4/parser"
"github.com/yoheimuta/protolint/linter/fixer"

"github.com/yoheimuta/protolint/linter/report"
"github.com/yoheimuta/protolint/linter/strs"
Expand All @@ -10,11 +12,17 @@ import (

// EnumNamesUpperCamelCaseRule verifies that all enum names are CamelCase (with an initial capital).
// See https://developers.google.com/protocol-buffers/docs/style#enums.
type EnumNamesUpperCamelCaseRule struct{}
type EnumNamesUpperCamelCaseRule struct {
fixMode bool
}

// NewEnumNamesUpperCamelCaseRule creates a new EnumNamesUpperCamelCaseRule.
func NewEnumNamesUpperCamelCaseRule() EnumNamesUpperCamelCaseRule {
return EnumNamesUpperCamelCaseRule{}
func NewEnumNamesUpperCamelCaseRule(
fixMode bool,
) EnumNamesUpperCamelCaseRule {
return EnumNamesUpperCamelCaseRule{
fixMode: fixMode,
}
}

// ID returns the ID of this rule.
Expand All @@ -34,20 +42,40 @@ func (r EnumNamesUpperCamelCaseRule) IsOfficial() bool {

// Apply applies the rule to the proto.
func (r EnumNamesUpperCamelCaseRule) Apply(proto *parser.Proto) ([]report.Failure, error) {
base, err := visitor.NewBaseFixableVisitor(r.ID(), r.fixMode, proto)
if err != nil {
return nil, err
}

v := &enumNamesUpperCamelCaseVisitor{
BaseAddVisitor: visitor.NewBaseAddVisitor(r.ID()),
BaseFixableVisitor: base,
}
return visitor.RunVisitor(v, proto, r.ID())
}

type enumNamesUpperCamelCaseVisitor struct {
*visitor.BaseAddVisitor
*visitor.BaseFixableVisitor
}

// VisitEnum checks the enum.
func (v *enumNamesUpperCamelCaseVisitor) VisitEnum(enum *parser.Enum) bool {
if !strs.IsUpperCamelCase(enum.EnumName) {
v.AddFailuref(enum.Meta.Pos, "Enum name %q must be UpperCamelCase", enum.EnumName)
name := enum.EnumName
if !strs.IsUpperCamelCase(name) {
expected := strs.ToUpperCamelCase(name)
v.AddFailuref(enum.Meta.Pos, "Enum name %q must be UpperCamelCase like %q", name, expected)

err := v.Fixer.SearchAndReplace(enum.Meta.Pos, func(lex *lexer.Lexer) fixer.TextEdit {
lex.NextKeyword()
lex.Next()
return fixer.TextEdit{
Pos: lex.Pos.Offset,
End: lex.Pos.Offset + len(lex.Text) - 1,
NewText: []byte(expected),
}
})
if err != nil {
panic(err)
}
}
return false
}
33 changes: 30 additions & 3 deletions internal/addon/rules/enumNamesUpperCamelCaseRule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func TestEnumNamesUpperCamelCaseRule_Apply(t *testing.T) {
Column: 10,
},
"ENUM_NAMES_UPPER_CAMEL_CASE",
`Enum name "enumName" must be UpperCamelCase`,
`Enum name "enumName" must be UpperCamelCase like "EnumName"`,
),
report.Failuref(
meta.Position{
Expand All @@ -87,7 +87,7 @@ func TestEnumNamesUpperCamelCaseRule_Apply(t *testing.T) {
Column: 20,
},
"ENUM_NAMES_UPPER_CAMEL_CASE",
`Enum name "Enum_name" must be UpperCamelCase`,
`Enum name "Enum_name" must be UpperCamelCase like "EnumName"`,
),
},
},
Expand All @@ -96,7 +96,7 @@ func TestEnumNamesUpperCamelCaseRule_Apply(t *testing.T) {
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
rule := rules.NewEnumNamesUpperCamelCaseRule()
rule := rules.NewEnumNamesUpperCamelCaseRule(false)

got, err := rule.Apply(test.inputProto)
if err != nil {
Expand All @@ -109,3 +109,30 @@ func TestEnumNamesUpperCamelCaseRule_Apply(t *testing.T) {
})
}
}

func TestEnumNamesUpperCamelCaseRule_Apply_fix(t *testing.T) {
tests := []struct {
name string
inputFilename string
wantFilename string
}{
{
name: "no fix for a correct proto",
inputFilename: "upperCamelCase.proto",
wantFilename: "upperCamelCase.proto",
},
{
name: "fix for an incorrect proto",
inputFilename: "invalid.proto",
wantFilename: "upperCamelCase.proto",
},
}

for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
r := rules.NewEnumNamesUpperCamelCaseRule(true)
testApplyFix(t, r, test.inputFilename, test.wantFilename)
})
}
}
91 changes: 52 additions & 39 deletions internal/addon/rules/quoteConsistentRule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"reflect"
"testing"

"github.com/yoheimuta/protolint/linter/rule"
"github.com/yoheimuta/protolint/linter/strs"

"github.com/yoheimuta/protolint/internal/linter/file"
"github.com/yoheimuta/protolint/internal/setting_test"

Expand Down Expand Up @@ -252,6 +255,53 @@ func TestQuoteConsistentRule_Apply(t *testing.T) {
}
}

func testApplyFix(
t *testing.T,
r rule.Rule,
inputFilename string,
wantFilename string,
) {
dataDir := strs.ToLowerCamelCase(r.ID())

input, err := newTestData(setting_test.TestDataPath("rules", dataDir, inputFilename))
if err != nil {
t.Errorf("got err %v", err)
return
}

want, err := newTestData(setting_test.TestDataPath("rules", dataDir, wantFilename))
if err != nil {
t.Errorf("got err %v", err)
return
}

proto, err := file.NewProtoFile(input.filePath, input.filePath).Parse(false)
if err != nil {
t.Errorf(err.Error())
return
}

_, err = r.Apply(proto)
if err != nil {
t.Errorf("got err %v, but want nil", err)
return
}

got, err := input.data()
if !reflect.DeepEqual(got, want.originData) {
t.Errorf(
"got %s(%v), but want %s(%v)",
string(got), got,
string(want.originData), want.originData,
)
}

err = input.restore()
if err != nil {
t.Errorf("got err %v", err)
}
}

func TestQuoteConsistentRule_Apply_fix(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -282,48 +332,11 @@ func TestQuoteConsistentRule_Apply_fix(t *testing.T) {
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
rule := rules.NewQuoteConsistentRule(
r := rules.NewQuoteConsistentRule(
test.inputQuote,
true,
)

input, err := newTestData(setting_test.TestDataPath("rules", "quoteConsistent", test.inputFilename))
if err != nil {
t.Errorf("got err %v", err)
return
}

want, err := newTestData(setting_test.TestDataPath("rules", "quoteConsistent", test.wantFilename))
if err != nil {
t.Errorf("got err %v", err)
return
}

proto, err := file.NewProtoFile(input.filePath, input.filePath).Parse(false)
if err != nil {
t.Errorf(err.Error())
return
}

_, err = rule.Apply(proto)
if err != nil {
t.Errorf("got err %v, but want nil", err)
return
}

got, err := input.data()
if !reflect.DeepEqual(got, want.originData) {
t.Errorf(
"got %s(%v), but want %s(%v)",
string(got), got,
string(want.originData), want.originData,
)
}

err = input.restore()
if err != nil {
t.Errorf("got err %v", err)
}
testApplyFix(t, r, test.inputFilename, test.wantFilename)
})
}
}
2 changes: 1 addition & 1 deletion internal/cmd/subcmds/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func newAllInternalRules(
enumFieldsHaveComment.ShouldFollowGolangStyle,
),

rules.NewEnumNamesUpperCamelCaseRule(),
rules.NewEnumNamesUpperCamelCaseRule(fixMode),
rules.NewEnumsHaveCommentRule(
enumsHaveComment.ShouldFollowGolangStyle,
),
Expand Down
Loading

0 comments on commit 1656b45

Please sign in to comment.