Skip to content

Commit b290a67

Browse files
Fix rules (#101)
* casing fix * identifier issue * test fixes * Update rules/aep0004/resource_name_components_alternate.go Co-authored-by: Yusuke Tsutsumi <[email protected]> * pr suggestions --------- Co-authored-by: Yusuke Tsutsumi <[email protected]>
1 parent c2ec184 commit b290a67

File tree

9 files changed

+39
-125
lines changed

9 files changed

+39
-125
lines changed

rules/aep0004/resource_name_components_alternate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
"github.com/jhump/protoreflect/desc"
2626
)
2727

28-
var identifierRegexp = regexp.MustCompile("^{[a-z][_a-z0-9]*[a-z0-9]}$")
28+
var identifierRegexp = regexp.MustCompile("^{[a-z][-a-z0-9]*[a-z0-9]}$")
2929

3030
var resourceNameComponentsAlternate = &lint.MessageRule{
3131
Name: lint.NewRuleName(4, "resource-name-components-alternate"),

rules/aep0004/resource_name_components_alternate_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func TestResourceNameComponentsAlternate(t *testing.T) {
2727
problems testutils.Problems
2828
}{
2929
{"Valid", "author/{author}/books/{book}", testutils.Problems{}},
30+
{"Valid", "publishers/{publisher}/books/{book}/editions/{book-edition}", testutils.Problems{}},
3031
{"ValidSingleton", "user/{user}/config", testutils.Problems{}},
3132
{"InvalidDoubleCollection", "author/books/{book}", testutils.Problems{{Message: "must alternate"}}},
3233
{"InvalidDoubleIdentifier", "books/{author}/{book}", testutils.Problems{{Message: "must alternate"}}},

rules/aep0004/resource_plural.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ var resourcePlural = &lint.MessageRule{
3131
r := utils.GetResource(m)
3232
l := locations.MessageResource(m)
3333
p := r.GetPlural()
34-
pLower := utils.ToLowerCamelCase(p)
34+
pLower := utils.ToKebabCase(p)
3535
if p == "" {
3636
return []lint.Problem{{
3737
Message: "Resources should declare plural.",

rules/aep0004/resource_plural_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func TestResourcePlural(t *testing.T) {
2727
}{
2828
{
2929
"Valid",
30-
`plural: "bookShelves"`,
30+
`plural: "book-shelves"`,
3131
nil,
3232
},
3333
{

rules/aep0004/resource_singular.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ var resourceSingular = &lint.MessageRule{
3232
l := locations.MessageResource(m)
3333
s := r.GetSingular()
3434
_, typeName, ok := utils.SplitResourceTypeName(r.GetType())
35-
lowerTypeName := utils.ToLowerCamelCase(typeName)
35+
lowerTypeName := utils.ToKebabCase(typeName)
3636
if s == "" {
3737
return []lint.Problem{{
3838
Message: fmt.Sprintf("Resources should declare singular: %q", lowerTypeName),

rules/aep0004/resource_type_name.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ var resourceTypeName = &lint.MessageRule{
3232
LintMessage: func(m *desc.MessageDescriptor) []lint.Problem {
3333
resource := utils.GetResource(m)
3434
_, typeName, ok := utils.SplitResourceTypeName(resource.GetType())
35-
upperTypeName := utils.ToUpperCamelCase(typeName)
35+
kebabCase := utils.ToKebabCase(typeName)
3636
if !ok {
3737
return []lint.Problem{{
3838
Message: "Resource type names must be of the form {Service Name}/{Type}.",
3939
Descriptor: m,
4040
Location: locations.MessageResource(m),
4141
}}
4242
}
43-
if upperTypeName != typeName {
43+
if kebabCase != typeName {
4444
return []lint.Problem{{
45-
Message: fmt.Sprintf("Type must be UpperCamelCase with alphanumeric characters: %q", upperTypeName),
45+
Message: fmt.Sprintf("Type must be kebob-case with alphanumeric characters: %q", kebabCase),
4646
Descriptor: m,
4747
Location: locations.MessageResource(m),
4848
}}

rules/aep0004/resource_type_name_test.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,16 @@ func TestResourceTypeName(t *testing.T) {
2626
TypeName string
2727
problems testutils.Problems
2828
}{
29-
{"Valid", "library.googleapis.com/Book", testutils.Problems{}},
29+
{"Valid", "library.googleapis.com/book", testutils.Problems{}},
3030
{"InvalidTooMany", "library.googleapis.com/shelf/Book", testutils.Problems{{Message: "{Service Name}/{Type}"}}},
3131
{"InvalidNotEnough", "library.googleapis.com~Book", testutils.Problems{{Message: "{Service Name}/{Type}"}}},
32-
{"InvalidWithUnicode", "library.googleapis.com/BoØkLibre", testutils.Problems{{Message: `Type must be UpperCamelCase`}}},
33-
{"InvalidLowerCamelCase", "library.googleapis.com/bookLoan", testutils.Problems{{Message: `Type must be UpperCamelCase with alphanumeric characters: "BookLoan"`}}},
34-
{"InvalidTypeNotAlphaNumeric", "library.googleapis.com/Book.:3", testutils.Problems{{Message: `Type must be UpperCamelCase with alphanumeric characters: "Book3"`}}},
35-
{"InvalidTypeContainsEmoji", "library.googleapis.com/Book♥️", testutils.Problems{{Message: `Type must be UpperCamelCase with alphanumeric characters: "Book"`}}},
36-
{"InvalidTypeContainsDashes", "library.googleapis.com/Book-Shelf️", testutils.Problems{{Message: `Type must be UpperCamelCase with alphanumeric characters: "BookShelf"`}}},
37-
{"InvalidTypeContainsUnderscore", "library.googleapis.com/Book_Shelf️", testutils.Problems{{Message: `Type must be UpperCamelCase with alphanumeric characters: "BookShelf"`}}},
32+
{"InvalidWithUnicode", "library.googleapis.com/BoØkLibre", testutils.Problems{{Message: `Type must be kebob-case`}}},
33+
{"InvalidLowerCamelCase", "library.googleapis.com/bookLoan", testutils.Problems{{Message: `Type must be kebob-case with alphanumeric characters: "book-loan"`}}},
34+
{"ValidLowerCamelCase", "library.googleapis.com/book-loan", testutils.Problems{}},
35+
{"InvalidTypeNotAlphaNumeric", "library.googleapis.com/Book.:3", testutils.Problems{{Message: `Type must be kebob-case with alphanumeric characters: "book-:3"`}}},
36+
{"InvalidTypeContainsEmoji", "library.googleapis.com/Book♥️", testutils.Problems{{Message: `Type must be kebob-case with alphanumeric characters: "book♥️"`}}},
37+
{"InvalidTypeContainsDashes", "library.googleapis.com/Book-Shelf️", testutils.Problems{{Message: `Type must be kebob-case with alphanumeric characters: "book--she`}}},
38+
{"InvalidTypeContainsUnderscore", "library.googleapis.com/Book_Shelf️", testutils.Problems{{Message: `Type must be kebob-case with alphanumeric characters: "book--she`}}},
3839
} {
3940
t.Run(test.name, func(t *testing.T) {
4041
f := testutils.ParseProto3Tmpl(t, `

rules/internal/utils/casing.go

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,54 +14,27 @@
1414

1515
package utils
1616

17-
// ToUpperCamelCase returns the UpperCamelCase of a string, including removing
18-
// delimiters (_,-,., ) and using them to denote a new word.
19-
func ToUpperCamelCase(s string) string {
20-
return toCamelCase(s, true, false)
21-
}
22-
23-
// ToLowerCamelCase returns the lowerCamelCase of a string, including removing
24-
// delimiters (_,-,., ) and using them to denote a new word.
25-
func ToLowerCamelCase(s string) string {
26-
return toCamelCase(s, false, true)
27-
}
28-
29-
func toCamelCase(s string, makeNextUpper bool, makeNextLower bool) string {
17+
// ToKebabCase returns the kebob-case of a word (book-edition).
18+
func ToKebabCase(s string) string {
3019
asLower := make([]rune, 0, len(s))
31-
for _, r := range s {
32-
if isLower(r) {
33-
if makeNextUpper {
34-
r = r & '_' // make uppercase
35-
}
36-
asLower = append(asLower, r)
37-
} else if isUpper(r) {
38-
if makeNextLower {
39-
r = r | ' ' // make lowercase
20+
for i, r := range s {
21+
if isUpper(r) {
22+
r = r | ' ' // make lowercase
23+
24+
// Only insert hypen after first word.
25+
if i != 0 {
26+
asLower = append(asLower, '-')
4027
}
4128
asLower = append(asLower, r)
42-
} else if isNumber(r) {
29+
} else if r == '-' || r == '_' || r == ' ' || r == '.' {
30+
asLower = append(asLower, '-')
31+
} else {
4332
asLower = append(asLower, r)
4433
}
45-
makeNextUpper = false
46-
makeNextLower = false
47-
48-
if r == '-' || r == '_' || r == ' ' || r == '.' {
49-
// handle snake case scenarios, which generally indicates
50-
// a delimited word.
51-
makeNextUpper = true
52-
}
5334
}
5435
return string(asLower)
5536
}
5637

5738
func isUpper(r rune) bool {
5839
return ('A' <= r && r <= 'Z')
5940
}
60-
61-
func isNumber(r rune) bool {
62-
return ('0' <= r && r <= '9')
63-
}
64-
65-
func isLower(r rune) bool {
66-
return ('a' <= r && r <= 'z')
67-
}

rules/internal/utils/casing_test.go

Lines changed: 11 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -16,67 +16,6 @@ package utils
1616

1717
import "testing"
1818

19-
func TestToLowerCamelCase(t *testing.T) {
20-
for _, test := range []struct {
21-
name string
22-
input string
23-
want string
24-
}{
25-
{
26-
name: "OneWord",
27-
input: "Foo",
28-
want: "foo",
29-
},
30-
{
31-
name: "OneWordNoop",
32-
input: "foo",
33-
want: "foo",
34-
},
35-
{
36-
name: "TwoWords",
37-
input: "bookShelf",
38-
want: "bookShelf",
39-
},
40-
{
41-
name: "WithDash",
42-
input: "book-shelf",
43-
want: "bookShelf",
44-
},
45-
{
46-
name: "WithNumbers",
47-
input: "universe42love",
48-
want: "universe42love",
49-
},
50-
{
51-
name: "WithUnderscore",
52-
input: "book_shelf",
53-
want: "bookShelf",
54-
},
55-
{
56-
name: "WithUnderscore",
57-
input: "book_shelf",
58-
want: "bookShelf",
59-
},
60-
{
61-
name: "WithSpaces",
62-
input: "book shelf",
63-
want: "bookShelf",
64-
},
65-
{
66-
name: "WithPeriods",
67-
input: "book.shelf",
68-
want: "bookShelf",
69-
},
70-
} {
71-
t.Run(test.name, func(t *testing.T) {
72-
got := ToLowerCamelCase(test.input)
73-
if got != test.want {
74-
t.Errorf("ToLowerCamelCase(%q) = %q, got %q", test.input, test.want, got)
75-
}
76-
})
77-
}
78-
}
79-
8019
func TestToUpperCamelCase(t *testing.T) {
8120
for _, test := range []struct {
8221
name string
@@ -86,53 +25,53 @@ func TestToUpperCamelCase(t *testing.T) {
8625
{
8726
name: "OneWord",
8827
input: "foo",
89-
want: "Foo",
28+
want: "foo",
9029
},
9130
{
9231
name: "OneWordNoop",
9332
input: "Foo",
94-
want: "Foo",
33+
want: "foo",
9534
},
9635
{
9736
name: "TwoWords",
9837
input: "bookShelf",
99-
want: "BookShelf",
38+
want: "book-shelf",
10039
},
10140
{
10241
name: "WithDash",
10342
input: "book-shelf",
104-
want: "BookShelf",
43+
want: "book-shelf",
10544
},
10645
{
10746
name: "WithNumbers",
10847
input: "universe42love",
109-
want: "Universe42love",
48+
want: "universe42love",
11049
},
11150
{
11251
name: "WithUnderscore",
11352
input: "Book_shelf",
114-
want: "BookShelf",
53+
want: "book-shelf",
11554
},
11655
{
11756
name: "WithUnderscore",
11857
input: "Book_shelf",
119-
want: "BookShelf",
58+
want: "book-shelf",
12059
},
12160
{
12261
name: "WithSpaces",
12362
input: "Book shelf",
124-
want: "BookShelf",
63+
want: "book-shelf",
12564
},
12665
{
12766
name: "WithPeriods",
12867
input: "book.shelf",
129-
want: "BookShelf",
68+
want: "book-shelf",
13069
},
13170
} {
13271
t.Run(test.name, func(t *testing.T) {
133-
got := ToUpperCamelCase(test.input)
72+
got := ToKebabCase(test.input)
13473
if got != test.want {
135-
t.Errorf("ToLowerCamelCase(%q) = %q, got %q", test.input, test.want, got)
74+
t.Errorf("ToKebabCase(%q) = %q, got %q", test.input, test.want, got)
13675
}
13776
})
13877
}

0 commit comments

Comments
 (0)