Auto capitalize enums name in Ruby (#10454) (#10763)

This closes #1965.
pull/10772/head
tison 2 years ago committed by GitHub
parent 5d90ef2432
commit fa5a9e1035
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      ruby/compatibility_tests/v3.0.0/tests/basic.rb
  2. 9
      ruby/ext/google/protobuf_c/message.c
  3. 23
      ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java
  4. 1
      ruby/tests/basic_test.proto
  5. 1
      ruby/tests/basic_test_proto2.proto
  6. 19
      ruby/tests/common_tests.rb
  7. 2
      ruby/tests/generated_code.proto
  8. 2
      ruby/tests/generated_code_proto2.proto
  9. 1
      ruby/tests/repeated_field_test.rb

@ -667,8 +667,8 @@ module BasicTest
assert m["z"] == :C
m["z"] = 2
assert m["z"] == :B
m["z"] = 4
assert m["z"] == 4
m["z"] = 5
assert m["z"] == 5
assert_raise RangeError do
m["z"] = :Z
end

@ -1290,15 +1290,20 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
int n = upb_EnumDef_ValueCount(e);
for (int i = 0; i < n; i++) {
const upb_EnumValueDef* ev = upb_EnumDef_Value(e, i);
const char* name = upb_EnumValueDef_Name(ev);
char* name = strdup(upb_EnumValueDef_Name(ev));
int32_t value = upb_EnumValueDef_Number(ev);
if (name[0] < 'A' || name[0] > 'Z') {
rb_warn(
if (name[0] >= 'a' && name[0] <= 'z') {
name[0] -= 32; // auto capitalize
} else {
rb_warn(
"Enum value '%s' does not start with an uppercase letter "
"as is required for Ruby constants.",
name);
}
}
rb_define_const(mod, name, INT2NUM(value));
free(name);
}
rb_define_singleton_method(mod, "lookup", enum_lookup, 1);

@ -162,9 +162,10 @@ public class RubyEnumDescriptor extends RubyObject {
boolean defaultValueRequiredButNotFound =
descriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3;
for (EnumValueDescriptor value : descriptor.getValues()) {
String name = value.getName();
// Make sure its a valid constant name before trying to create it
if (Character.isUpperCase(name.codePointAt(0))) {
String name = fixEnumConstantName(value.getName());
// Make sure it's a valid constant name before trying to create it
int ch = name.codePointAt(0);
if (Character.isUpperCase(ch)) {
enumModule.defineConstant(name, runtime.newFixnum(value.getNumber()));
} else {
runtime
@ -189,6 +190,22 @@ public class RubyEnumDescriptor extends RubyObject {
return enumModule;
}
private static String fixEnumConstantName(String name) {
if (name != null && name.length() > 0) {
int ch = name.codePointAt(0);
if (ch >= 'a' && ch <= 'z') {
// Protobuf enums can start with lowercase letters, while Ruby's constant should
// always start with uppercase letters. We tolerate this case by capitalizing
// the first character if possible.
return new StringBuilder()
.appendCodePoint(Character.toUpperCase(ch))
.append(name.substring(1))
.toString();
}
}
return name;
}
private EnumDescriptor descriptor;
private EnumDescriptorProto.Builder builder;
private IRubyObject name;

@ -73,6 +73,7 @@ enum TestEnum {
A = 1;
B = 2;
C = 3;
v0 = 4;
}
message TestEmbeddedMessageParent {

@ -69,6 +69,7 @@ enum TestEnum {
A = 1;
B = 2;
C = 3;
v0 = 4;
}
enum TestNonZeroEnum {

@ -331,14 +331,16 @@ module CommonTests
l.push :A
l.push :B
l.push :C
assert l.count == 3
l.push :v0
assert l.count == 4
assert_raise RangeError do
l.push :D
end
assert l[0] == :A
assert l[3] == :v0
l.push 4
assert l[3] == 4
l.push 5
assert l[4] == 5
end
def test_rptfield_initialize
@ -542,8 +544,8 @@ module CommonTests
assert m["z"] == :C
m["z"] = 2
assert m["z"] == :B
m["z"] = 4
assert m["z"] == 4
m["z"] = 5
assert m["z"] == 5
assert_raise RangeError do
m["z"] = :Z
end
@ -712,14 +714,17 @@ module CommonTests
assert proto_module::TestEnum::A == 1
assert proto_module::TestEnum::B == 2
assert proto_module::TestEnum::C == 3
assert proto_module::TestEnum::V0 == 4
assert proto_module::TestEnum::lookup(1) == :A
assert proto_module::TestEnum::lookup(2) == :B
assert proto_module::TestEnum::lookup(3) == :C
assert proto_module::TestEnum::lookup(4) == :v0
assert proto_module::TestEnum::resolve(:A) == 1
assert proto_module::TestEnum::resolve(:B) == 2
assert proto_module::TestEnum::resolve(:C) == 3
assert proto_module::TestEnum::resolve(:v0) == 4
end
def test_enum_const_get_helpers
@ -788,7 +793,7 @@ module CommonTests
assert_raise(NoMethodError) { m.a }
assert_raise(NoMethodError) { m.a_const_const }
end
def test_repeated_push
m = proto_module::TestMessage.new
@ -1762,7 +1767,7 @@ module CommonTests
assert_raise(FrozenErrorType) { m.repeated_msg = proto_module::TestMessage2.new }
assert_raise(FrozenErrorType) { m.repeated_enum = :A }
end
def test_eq
m1 = proto_module::TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
m2 = proto_module::TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])

@ -67,6 +67,8 @@ enum TestEnum {
A = 1;
B = 2;
C = 3;
v0 = 4;
}
message testLowercaseNested {

@ -68,6 +68,8 @@ enum TestEnum {
A = 1;
B = 2;
C = 3;
v0 = 4;
}
message TestUnknown {

@ -697,6 +697,7 @@ class RepeatedFieldTest < Test::Unit::TestCase
value :A, 1
value :B, 2
value :C, 3
value :v0, 4
end
end

Loading…
Cancel
Save