Move enum value name calculation

PiperOrigin-RevId: 596767666
pull/15325/head
Alyssa Haroldsen 1 year ago committed by Copybara-Service
parent fa67ce8d4d
commit e3d2551c8e
  1. 1
      src/google/protobuf/compiler/rust/BUILD.bazel
  2. 40
      src/google/protobuf/compiler/rust/enum.cc
  3. 54
      src/google/protobuf/compiler/rust/naming.cc
  4. 22
      src/google/protobuf/compiler/rust/naming.h

@ -152,6 +152,7 @@ cc_library(
"//src/google/protobuf",
"//src/google/protobuf/compiler:code_generator",
"//src/google/protobuf/compiler/cpp:names_internal",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/log:absl_log",
"@com_google_absl//absl/strings",
],

@ -17,12 +17,9 @@
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/absl_check.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/types/span.h"
#include "google/protobuf/compiler/rust/context.h"
#include "google/protobuf/compiler/rust/naming.h"
@ -52,17 +49,7 @@ std::vector<std::pair<absl::string_view, int32_t>> EnumValuesInput(
std::vector<RustEnumValue> EnumValues(
absl::string_view enum_name,
absl::Span<const std::pair<absl::string_view, int32_t>> values) {
// Enum values may have a prefix of the name of the enum stripped from the
// value names in the gencode. This prefix is flexible:
// - It can be the original enum name, the name as UpperCamel, or snake_case.
// - The stripped prefix may also end in an underscore.
// The set of prefixes that will be stripped.
std::initializer_list<std::string> prefixes = {
std::string(enum_name),
ScreamingSnakeToUpperCamelCase(enum_name),
CamelToSnakeCase(enum_name),
};
MultiCasePrefixStripper stripper(enum_name);
absl::flat_hash_set<std::string> seen_by_name;
absl::flat_hash_map<int32_t, RustEnumValue*> seen_by_number;
@ -74,32 +61,9 @@ std::vector<RustEnumValue> EnumValues(
seen_by_number.reserve(values.size());
for (const auto& name_and_number : values) {
absl::string_view base_value_name = name_and_number.first;
for (absl::string_view prefix : prefixes) {
if (absl::StartsWithIgnoreCase(base_value_name, prefix)) {
base_value_name.remove_prefix(prefix.size());
// Also strip a joining underscore, if present.
absl::ConsumePrefix(&base_value_name, "_");
// Only strip one prefix.
break;
}
}
if (base_value_name.empty()) {
// The enum value name has a similar name to the enum - don't strip.
base_value_name = name_and_number.first;
}
int32_t number = name_and_number.second;
std::string rust_value_name =
ScreamingSnakeToUpperCamelCase(base_value_name);
// Invalid identifiers are prefixed with `_`.
if (absl::ascii_isdigit(rust_value_name[0])) {
rust_value_name = absl::StrCat("_", rust_value_name);
}
EnumValueRsName(stripper, name_and_number.first);
if (seen_by_name.contains(rust_value_name)) {
// Don't add an alias with the same normalized name.

@ -10,13 +10,16 @@
#include <string>
#include <vector>
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/strings/substitute.h"
#include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/compiler/cpp/helpers.h"
@ -257,6 +260,29 @@ std::string EnumRsName(const EnumDescriptor& desc) {
return SnakeToUpperCamelCase(desc.name());
}
std::string EnumValueRsName(const EnumValueDescriptor& value) {
MultiCasePrefixStripper stripper(value.type()->name());
return EnumValueRsName(stripper, value.name());
}
std::string EnumValueRsName(const MultiCasePrefixStripper& stripper,
absl::string_view value_name) {
// Enum values may have a prefix of the name of the enum stripped from the
// value names in the gencode. This prefix is flexible:
// - It can be the original enum name, the name as UpperCamel, or snake_case.
// - The stripped prefix may also end in an underscore.
auto stripped = stripper.StripPrefix(value_name);
auto name = ScreamingSnakeToUpperCamelCase(stripped);
ABSL_CHECK(!name.empty());
// Invalid identifiers are prefixed with `_`.
if (absl::ascii_isdigit(name[0])) {
name = absl::StrCat("_", name);
}
return name;
}
std::string OneofViewEnumRsName(const OneofDescriptor& oneof) {
return SnakeToUpperCamelCase(oneof.name());
}
@ -318,6 +344,34 @@ std::string ScreamingSnakeToUpperCamelCase(absl::string_view input) {
return result;
}
MultiCasePrefixStripper::MultiCasePrefixStripper(absl::string_view prefix)
: prefixes_{
std::string(prefix),
ScreamingSnakeToUpperCamelCase(prefix),
CamelToSnakeCase(prefix),
} {}
absl::string_view MultiCasePrefixStripper::StripPrefix(
absl::string_view name) const {
absl::string_view start_name = name;
for (absl::string_view prefix : prefixes_) {
if (absl::StartsWithIgnoreCase(name, prefix)) {
name.remove_prefix(prefix.size());
// Also strip a joining underscore, if present.
absl::ConsumePrefix(&name, "_");
// Only strip one prefix.
break;
}
}
if (name.empty()) {
return start_name;
}
return name;
}
} // namespace rust
} // namespace compiler
} // namespace protobuf

@ -8,6 +8,7 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_RUST_NAMING_H__
#define GOOGLE_PROTOBUF_COMPILER_RUST_NAMING_H__
#include <array>
#include <string>
#include "absl/strings/string_view.h"
@ -39,6 +40,7 @@ std::string ThunkName(Context& ctx, const Descriptor& msg,
std::string RsTypePath(Context& ctx, const FieldDescriptor& field);
std::string EnumRsName(const EnumDescriptor& desc);
std::string EnumValueRsName(const EnumValueDescriptor& value);
std::string OneofViewEnumRsName(const OneofDescriptor& oneof);
std::string OneofMutEnumRsName(const OneofDescriptor& oneof);
@ -75,6 +77,26 @@ std::string SnakeToUpperCamelCase(absl::string_view input);
// Converts a SCREAMING_SNAKE_CASE string to an UpperCamelCase string.
std::string ScreamingSnakeToUpperCamelCase(absl::string_view input);
// Given a fixed prefix, this will repeatedly strip provided
// string_views if they start with the prefix, the prefix in UpperCamel, or
// the prefix in snake_case.
class MultiCasePrefixStripper final {
public:
explicit MultiCasePrefixStripper(absl::string_view prefix);
// Strip a prefix from the name in UpperCamel or snake_case, if present.
// If there is an underscore after the prefix, that will also be stripped.
// The stripping is case-insensitive.
absl::string_view StripPrefix(absl::string_view name) const;
private:
std::array<std::string, 3> prefixes_;
};
// More efficient overload if a stripper is already constructed.
std::string EnumValueRsName(const MultiCasePrefixStripper& stripper,
absl::string_view value_name);
} // namespace rust
} // namespace compiler
} // namespace protobuf

Loading…
Cancel
Save