diff options
author | Josh Haberman <jhaberman@gmail.com> | 2016-07-25 17:39:07 -0700 |
---|---|---|
committer | Josh Haberman <jhaberman@gmail.com> | 2016-07-25 17:39:07 -0700 |
commit | b3b07cd8513330ef6f50cadf218b92ea479488c5 (patch) | |
tree | e18d2b9922a198bb9007b62cde9214c579a82fab /src/google | |
parent | a17367f44a3b592993d2ac5c074ed58fb0ce784c (diff) | |
parent | ba52f2b6780fa5e6bee86cf7e8ee6f6ba617862c (diff) | |
download | protobuf-b3b07cd8513330ef6f50cadf218b92ea479488c5.tar.gz protobuf-b3b07cd8513330ef6f50cadf218b92ea479488c5.tar.bz2 protobuf-b3b07cd8513330ef6f50cadf218b92ea479488c5.zip |
Merge branch 'master' into 3.0.0-GA
We need to pick up some of the last-minute Ruby fixes.
Diffstat (limited to 'src/google')
-rw-r--r-- | src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb (renamed from src/google/protobuf/compiler/ruby/ruby_generated_code.rb) | 0 | ||||
-rw-r--r-- | src/google/protobuf/compiler/ruby/ruby_generator.cc | 60 | ||||
-rw-r--r-- | src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc | 4 |
3 files changed, 51 insertions, 13 deletions
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb index 49b23fbe..49b23fbe 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb +++ b/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index 92c76fb0..fbe3b4cb 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -48,7 +48,7 @@ namespace ruby { // Forward decls. std::string IntToString(int32 value); -std::string StripDotProto(const std::string& proto_file); +std::string GetRequireName(const std::string& proto_file); std::string LabelForField(google::protobuf::FieldDescriptor* field); std::string TypeName(google::protobuf::FieldDescriptor* field); void GenerateMessage(const google::protobuf::Descriptor* message, @@ -70,13 +70,13 @@ std::string IntToString(int32 value) { return os.str(); } -std::string StripDotProto(const std::string& proto_file) { +std::string GetRequireName(const std::string& proto_file) { int lastindex = proto_file.find_last_of("."); - return proto_file.substr(0, lastindex); + return proto_file.substr(0, lastindex) + "_pb"; } std::string GetOutputFilename(const std::string& proto_file) { - return StripDotProto(proto_file) + ".rb"; + return GetRequireName(proto_file) + ".rb"; } std::string LabelForField(const google::protobuf::FieldDescriptor* field) { @@ -237,15 +237,52 @@ void GenerateEnum(const google::protobuf::EnumDescriptor* en, "end\n"); } -// Module names, class names, and enum value names need to be Ruby constants, -// which must start with a capital letter. +// Locale-agnostic utility functions. +bool IsLower(char ch) { return ch >= 'a' && ch <= 'z'; } + +bool IsUpper(char ch) { return ch >= 'A' && ch <= 'Z'; } + +bool IsAlpha(char ch) { return IsLower(ch) || IsUpper(ch); } + +char ToUpper(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; } + + +// Package names in protobuf are snake_case by convention, but Ruby module +// names must be PascalCased. +// +// foo_bar_baz -> FooBarBaz +std::string PackageToModule(const std::string& name) { + bool next_upper = true; + std::string result; + result.reserve(name.size()); + + for (int i = 0; i < name.size(); i++) { + if (name[i] == '_') { + next_upper = true; + } else { + if (next_upper) { + result.push_back(ToUpper(name[i])); + } else { + result.push_back(name[i]); + } + next_upper = false; + } + } + + return result; +} + +// Class and enum names in protobuf should be PascalCased by convention, but +// since there is nothing enforcing this we need to ensure that they are valid +// Ruby constants. That mainly means making sure that the first character is +// an upper-case letter. std::string RubifyConstant(const std::string& name) { std::string ret = name; if (!ret.empty()) { - if (ret[0] >= 'a' && ret[0] <= 'z') { + if (IsLower(ret[0])) { // If it starts with a lowercase letter, capitalize it. - ret[0] = ret[0] - 'a' + 'A'; - } else if (ret[0] < 'A' || ret[0] > 'Z') { + ret[0] = ToUpper(ret[0]); + } else if (!IsAlpha(ret[0])) { // Otherwise (e.g. if it begins with an underscore), we need to come up // with some prefix that starts with a capital letter. We could be smarter // here, e.g. try to strip leading underscores, but this may cause other @@ -254,6 +291,7 @@ std::string RubifyConstant(const std::string& name) { ret = "PB_" + ret; } } + return ret; } @@ -314,7 +352,7 @@ int GeneratePackageModules( component = package_name.substr(0, dot_index); package_name = package_name.substr(dot_index + 1); } - component = RubifyConstant(component); + component = PackageToModule(component); printer->Print( "module $name$\n", "name", component); @@ -391,7 +429,7 @@ bool MaybeEmitDependency(const FileDescriptor* import, return true; } else { printer->Print( - "require '$name$'\n", "name", StripDotProto(import->name())); + "require '$name$'\n", "name", GetRequireName(import->name())); return true; } } diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index c0acb407..1aabe8aa 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -91,12 +91,12 @@ TEST(RubyGeneratorTest, GeneratorTest) { // Load the generated output and compare to the expected result. string output; GOOGLE_CHECK_OK(File::GetContents( - TestTempDir() + "/ruby_generated_code.rb", + TestTempDir() + "/ruby_generated_code_pb.rb", &output, true)); string expected_output; GOOGLE_CHECK_OK(File::GetContents( - ruby_tests + "/ruby_generated_code.rb", + ruby_tests + "/ruby_generated_code_pb.rb", &expected_output, true)); EXPECT_EQ(expected_output, output); |