Skip to content

Commit 2a6a7dc

Browse files
committed
feat proto-structs: camel case for enums
commit_hash:d873964ff730542de5223de0fc1675ea750700c2
1 parent 991e889 commit 2a6a7dc

File tree

8 files changed

+54
-23
lines changed

8 files changed

+54
-23
lines changed

libraries/proto-structs/codegen-tests/proto/enums/names.proto

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,11 @@ message NestedTrickEnum {
4141
BAR_VAR = 2;
4242
}
4343
}
44+
45+
enum WithoutPrefix {
46+
BarVar = 0;
47+
Bar_Foo = 1;
48+
Bar_foo1 = 2;
49+
Bar_FooQux = 3;
50+
Bar_FooQuX1 = 4;
51+
}

libraries/proto-structs/codegen-tests/src/enums/names_test.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,40 @@ USERVER_NAMESPACE_BEGIN
99
TEST(EnumNames, Unprefixed) {
1010
using Enum = enums::structs::Unprefixed;
1111
static_assert(std::is_enum_v<Enum>);
12-
static_assert(std::is_same_v<decltype(Enum::FOO_VAR), Enum>);
13-
static_assert(std::is_same_v<decltype(Enum::BAR_VAR), Enum>);
12+
static_assert(std::is_same_v<decltype(Enum::kFooVar), Enum>);
13+
static_assert(std::is_same_v<decltype(Enum::kBarVar), Enum>);
1414
}
1515

1616
TEST(EnumNames, AllowedCuts) {
1717
using Enum = enums::structs::AllowedCuts;
1818
static_assert(std::is_enum_v<Enum>);
19-
static_assert(std::is_same_v<decltype(Enum::FOO_VAR), Enum>);
20-
static_assert(std::is_same_v<decltype(Enum::DIGITS1), Enum>);
19+
static_assert(std::is_same_v<decltype(Enum::kFooVar), Enum>);
20+
static_assert(std::is_same_v<decltype(Enum::kDigits1), Enum>);
2121
}
2222

2323
TEST(EnumNames, DisallowedCuts) {
2424
using Enum = enums::structs::DisallowedCuts;
2525
static_assert(std::is_enum_v<Enum>);
26-
static_assert(std::is_same_v<decltype(Enum::DisallowedCuts_UNKNOWN), Enum>);
27-
static_assert(std::is_same_v<decltype(Enum::DISALLOWED_CUTS), Enum>);
28-
static_assert(std::is_same_v<decltype(Enum::DISALLOWED_CUTS1), Enum>);
29-
static_assert(std::is_same_v<decltype(Enum::DISALLOWED_CUTS_2), Enum>);
30-
static_assert(std::is_same_v<decltype(Enum::DisallowedCutsCamel), Enum>);
26+
static_assert(std::is_same_v<decltype(Enum::kDisallowedCutsUnknown), Enum>);
27+
static_assert(std::is_same_v<decltype(Enum::kDisallowedCuts), Enum>);
28+
static_assert(std::is_same_v<decltype(Enum::kDisallowedCuts1), Enum>);
29+
static_assert(std::is_same_v<decltype(Enum::kDisallowedCuts2), Enum>);
30+
static_assert(std::is_same_v<decltype(Enum::kDisallowedCutsCamel), Enum>);
3131
}
3232

3333
TEST(EnumNames, NestedTrick) {
3434
using Enum = enums::structs::NestedTrickEnum;
3535
static_assert(std::is_enum_v<Enum>);
36-
static_assert(std::is_same_v<decltype(Enum::FOO_VAR), Enum>);
36+
static_assert(std::is_same_v<decltype(Enum::kFooVar), Enum>);
37+
}
38+
39+
TEST(EnumNames, WithoutPrefix) {
40+
using Enum = enums::structs::WithoutPrefix;
41+
static_assert(std::is_same_v<decltype(Enum::kBarVar), Enum>);
42+
static_assert(std::is_same_v<decltype(Enum::kBarFoo), Enum>);
43+
static_assert(std::is_same_v<decltype(Enum::kBarFoo1), Enum>);
44+
static_assert(std::is_same_v<decltype(Enum::kBarFooQux), Enum>);
45+
static_assert(std::is_same_v<decltype(Enum::kBarFooQuX1), Enum>);
3746
}
3847

3948
USERVER_NAMESPACE_END

libraries/proto-structs/codegen-tests/src/simple_test.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ TEST(SingleFile, SimpleStruct) {
1919
message.is_condition = true;
2020
message.some_bytes = {"foo", "bar"};
2121
message.something.set_bar("bar_val");
22-
message.inner_enum = ss::SimpleStruct::InnerEnum2::FOO_VAL;
22+
message.inner_enum = ss::SimpleStruct::InnerEnum2::kFooVal;
2323

2424
ss::SimpleStruct::ProtobufMessage vanilla;
2525

@@ -57,12 +57,12 @@ TEST(SingleFile, NestedStruct) {
5757

5858
TEST(SingleFile, InnerEnum1) {
5959
static_assert(std::is_enum_v<ss::SimpleStruct::NestedStruct::NestedStruct2::InnerEnum1>);
60-
[[maybe_unused]] const auto inner_enum1 = ss::SimpleStruct::NestedStruct::NestedStruct2::InnerEnum1::BAR_VAL;
60+
[[maybe_unused]] const auto inner_enum1 = ss::SimpleStruct::NestedStruct::NestedStruct2::InnerEnum1::kBarVal;
6161
}
6262

6363
TEST(SingleFile, InnerEnum2) {
6464
static_assert(std::is_enum_v<ss::SimpleStruct::InnerEnum2>);
65-
[[maybe_unused]] const auto inner_enum2 = ss::SimpleStruct::InnerEnum2::FOO_VAL;
65+
[[maybe_unused]] const auto inner_enum2 = ss::SimpleStruct::InnerEnum2::kFooVal;
6666
}
6767

6868
TEST(SingleFile, SecondStruct) {

libraries/proto-structs/include/userver/proto-structs/impl/bundles/structs_hpp.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#pragma once
22

3-
#include <cstddef>
43
#include <cstdint>
54
#include <limits>
65
#include <optional>

scripts/proto_structs/descriptors/node_parsers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,16 @@ def parse_enum_value(value: descriptor.EnumValueDescriptor) -> gen_node.EnumValu
7272
enum_name = typing.cast(str, enum_descriptor.name)
7373

7474
return gen_node.EnumValue(
75-
short_name=names.escape_id(_cut_enum_value_name(enum_value_name, enum_name=enum_name)),
75+
short_name=names.escape_id(_format_enum_value_name(enum_value_name, enum_name=enum_name)),
7676
number=typing.cast(int, value.number),
7777
)
7878

7979

80+
def _format_enum_value_name(value_name: str, *, enum_name: str) -> str:
81+
name = _cut_enum_value_name(value_name, enum_name=enum_name)
82+
return f'k{names.to_pascal_case(name, to_lower=True)}'
83+
84+
8085
def _cut_enum_value_name(value_name: str, *, enum_name: str) -> str:
8186
if value_name.startswith(upper_enum_name := names.to_upper_case(enum_name)):
8287
# ENUM_NAME_VALUE_NAME -> VALUE_NAME

scripts/proto_structs/models/gen_node.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ def __init__(self, *, proto_relative_path: pathlib.Path, children: Sequence[Code
8080
def collect_includes(self) -> Iterable[includes.Include]:
8181
for child in self.children:
8282
yield from child.collect_includes()
83-
yield includes.Include(path='cstddef', kind=includes.IncludeKind.FOR_HPP)
84-
yield includes.Include(path='utility', kind=includes.IncludeKind.FOR_HPP)
8583

8684
def gen_path(self, *, ext: str) -> pathlib.Path:
8785
"""Path to the generated userver proto structs file."""
@@ -199,6 +197,7 @@ def own_includes(self) -> Iterable[includes.Include]:
199197
yield from [
200198
includes.Include(path=path, kind=includes.IncludeKind.FOR_CPP)
201199
for path in [
200+
'utility',
202201
'userver/proto-structs/io/impl/field_accessor.hpp',
203202
'userver/proto-structs/io/impl/read.hpp',
204203
'userver/proto-structs/io/impl/write.hpp',
@@ -239,6 +238,7 @@ def field_number_name(self) -> str:
239238
"""
240239
Converts a `snake_case` or `camelCase` identifier to `PascalCase`.
241240
Example: some_bytes_my_word -> kSomeBytesMyWordFieldNumber
241+
Example: IYandexUid -> kIYandexUidFieldNumber
242242
"""
243243
return f'k{names.to_pascal_case(self.short_name)}FieldNumber'
244244

scripts/proto_structs/models/includes_bundles.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from typing import Set
44

55
BUNDLE_HPP: Set[str] = {
6-
'cstddef',
76
'cstdint',
87
'limits',
98
'optional',

scripts/proto_structs/models/names.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,25 @@ def make_nested_type_name(containing_type_name: TypeName, short_name: str) -> Ty
225225
)
226226

227227

228-
def to_pascal_case(name: str) -> str:
228+
_SPLIT_PASCAL_PATTERN = re.compile(r'_|(?<=[a-z])(?=[A-Z])')
229+
230+
231+
def to_pascal_case(name: str, to_lower: bool = False) -> str:
229232
"""
230-
Converts a `snake_case` or `camelCase` identifier to `PascalCase`.
233+
Converts a `snake_case` or `UPPER_CASE` or `camelCase` identifier to `PascalCase`.
231234
Examples:
232-
some_bytes_my_word -> kSomeBytesMyWordFieldNumber
233-
by2tes_m1y -> kBy2TesM1YFieldNumber
234-
IYandexUid -> kIYandexUidFieldNumber
235+
some_bytes_my_word -> SomeBytesMyWord
236+
by2tes_m1y -> By2TesM1Y
237+
IYandexUid -> IYandexUid (if to_lower=False)
238+
FOO_BAR_BazQux -> FooBarBazQux
235239
"""
240+
# We should split name by '_' and uppers letters. 'FOO_BAR_BazQux' -> ["FOO", "BAR", "Baz", "Qux"]
241+
words = _SPLIT_PASCAL_PATTERN.split(name)
242+
name = '_'.join(words)
243+
244+
if to_lower:
245+
name = name.lower()
246+
236247
words = ''.join(word[0].upper() + word[1:] for word in name.split('_') if len(word) > 0)
237248

238249
result = ''

0 commit comments

Comments
 (0)