diff options
Diffstat (limited to 'src/google/protobuf/compiler')
15 files changed, 575 insertions, 303 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 42525687..02f360bb 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -791,7 +791,7 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { // AssignDescriptors(). All later times, waits for the first call to // complete and then returns. printer->Print( - "void protobuf_AssignDescriptors() {\n" + "static void protobuf_AssignDescriptors() {\n" // Make sure the file has found its way into the pool. If a descriptor // is requested *during* static init then AddDescriptors() may not have // been called yet, so we call it manually. Note that it's fine if @@ -812,7 +812,7 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { printer->Print( "}\n" "\n" - "void protobuf_AssignDescriptorsOnce() {\n" + "static void protobuf_AssignDescriptorsOnce() {\n" " static ::google::protobuf::internal::once_flag once;\n" " ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors);\n" "}\n" @@ -850,7 +850,7 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { // Now generate the AddDescriptors() function. printer->Print( - "void AddDescriptorsImpl() {\n" + "static void AddDescriptorsImpl() {\n" " InitDefaults();\n"); printer->Indent(); diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 8c2336af..778fc406 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -2280,7 +2280,7 @@ GenerateArenaDestructorCode(io::Printer* printer) { "classname", classname_); } else { printer->Print( - "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n" + "void $classname$::RegisterArenaDtor(::google::protobuf::Arena*) {\n" "}\n", "classname", classname_); } diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 5bca1ffa..04b61074 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -169,7 +169,7 @@ std::string UnderscoresToCamelCase(const std::string& input, } } // Add a trailing "_" if the name should be altered. - if (input[input.size() - 1] == '#') { + if (input.size() > 0 && input[input.size() - 1] == '#') { result += '_'; } return result; diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index 0686ea0f..ef64d88b 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -305,11 +305,15 @@ GenerateBuildingCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_ = $name$_;\n" " $set_has_field_bit_to_local$;\n" + "} else {\n" + " result.$name$_ = $default_number$;\n" "}\n"); + } else { + printer->Print(variables_, + "result.$name$_ = $name$_;\n"); } - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); } void ImmutableEnumFieldGenerator:: diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc index abf8e55c..6544bea0 100644 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc +++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc @@ -233,12 +233,9 @@ void ImmutableLazyMessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_.set($name$_);\n" " $set_has_field_bit_to_local$;\n" "}\n"); - - printer->Print(variables_, - "result.$name$_.set(\n" - " $name$_);\n"); } void ImmutableLazyMessageFieldGenerator:: diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index baa7f872..bda4fcc0 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -255,7 +255,7 @@ GenerateBuilderMembers(io::Printer* printer) const { bool support_field_presence = SupportFieldPresence(descriptor_->file()); printer->Print(variables_, - "private $type$ $name$_ = null;\n"); + "private $type$ $name$_;\n"); printer->Print(variables_, // If this builder is non-null, it is used and the other fields are @@ -444,15 +444,20 @@ void ImmutableMessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); + "if ($get_has_field_bit_from_local$) {\n"); + printer->Indent(); + PrintNestedBuilderCondition(printer, + "result.$name$_ = $name$_;\n", + "result.$name$_ = $name$Builder_.build();\n"); + printer->Outdent(); + printer->Print(variables_, + " $set_has_field_bit_to_local$;\n" + "}\n"); + } else { + PrintNestedBuilderCondition(printer, + "result.$name$_ = $name$_;\n", + "result.$name$_ = $name$Builder_.build();\n"); } - - PrintNestedBuilderCondition(printer, - "result.$name$_ = $name$_;\n", - - "result.$name$_ = $name$Builder_.build();\n"); } void ImmutableMessageFieldGenerator:: diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index 71ee0992..e6ce69c7 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -264,7 +264,9 @@ GenerateFieldBuilderInitializationCode(io::Printer* printer) const { void ImmutablePrimitiveFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); + if (!IsDefaultValueJavaDefault(descriptor_)) { + printer->Print(variables_, "$name$_ = $default$;\n"); + } } void ImmutablePrimitiveFieldGenerator:: @@ -294,11 +296,21 @@ GenerateBuildingCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); + " result.$name$_ = $name$_;\n" + " $set_has_field_bit_to_local$;\n"); + if (IsDefaultValueJavaDefault(descriptor_)) { + printer->Print(variables_, + "}\n"); + } else { + printer->Print(variables_, + "} else {\n" + " result.$name$_ = $default$;\n" + "}\n"); + } + } else { + printer->Print(variables_, + "result.$name$_ = $name$_;\n"); } - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); } void ImmutablePrimitiveFieldGenerator:: diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index 2b6e9381..b08febc0 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -405,11 +405,15 @@ GenerateBuildingCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_ = $name$_;\n" " $set_has_field_bit_to_local$;\n" + "} else {\n" + " result.$name$_ = $default$;\n" "}\n"); + } else { + printer->Print(variables_, + "result.$name$_ = $name$_;\n"); } - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); } void ImmutableStringFieldGenerator:: diff --git a/src/google/protobuf/compiler/js/embed.cc b/src/google/protobuf/compiler/js/embed.cc deleted file mode 100644 index f0f946e5..00000000 --- a/src/google/protobuf/compiler/js/embed.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <cassert> -#include <cstdlib> -#include <fstream> -#include <iostream> -#include <string> - -static bool AsciiIsPrint(unsigned char c) { - return c >= 32 && c < 127; -} - -static char ToDecimalDigit(int num) { - assert(num < 10); - return '0' + num; -} - -static std::string CEscape(const std::string& str) { - std::string dest; - - for (size_t i = 0; i < str.size(); ++i) { - unsigned char ch = str[i]; - switch (ch) { - case '\n': dest += "\\n"; break; - case '\r': dest += "\\r"; break; - case '\t': dest += "\\t"; break; - case '\"': dest += "\\\""; break; - case '\\': dest += "\\\\"; break; - default: - if (AsciiIsPrint(ch)) { - dest += ch; - } else { - dest += "\\"; - dest += ToDecimalDigit(ch / 64); - dest += ToDecimalDigit((ch % 64) / 8); - dest += ToDecimalDigit(ch % 8); - } - break; - } - } - - return dest; -} - -static void AddFile(const char* name, std::basic_ostream<char>* out) { - std::ifstream in(name); - - if (!in.is_open()) { - std::cerr << "Couldn't open input file: " << name << "\n"; - std::exit(EXIT_FAILURE); - } - - // Make canonical name only include the final element. - for (const char *p = name; *p; p++) { - if (*p == '/') { - name = p + 1; - } - } - - *out << "{\"" << CEscape(name) << "\",\n"; - - for (std::string line; std::getline(in, line); ) { - *out << " \"" << CEscape(line) << "\\n\"\n"; - } - - *out << "},\n"; -} - -int main(int argc, char *argv[]) { - std::cout << "#include " - "\"google/protobuf/compiler/js/well_known_types_embed.h\"\n"; - std::cout << "struct FileToc well_known_types_js[] = {\n"; - - for (int i = 1; i < argc; i++) { - AddFile(argv[i], &std::cout); - } - - std::cout << " {NULL, NULL} // Terminate the list.\n"; - std::cout << "};\n"; - - return EXIT_SUCCESS; -} diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc index d8282e40..7109ed5b 100755 --- a/src/google/protobuf/compiler/js/js_generator.cc +++ b/src/google/protobuf/compiler/js/js_generator.cc @@ -3477,7 +3477,8 @@ void Generator::GenerateFile(const GeneratorOptions& options, GenerateExtension(options, printer, *it); } - if (options.import_style == GeneratorOptions::kImportCommonJs) { + // if provided is empty, do not export anything + if (options.import_style == GeneratorOptions::kImportCommonJs && !provided.empty()) { printer->Print("goog.object.extend(exports, $package$);\n", "package", GetFilePath(options, file)); } diff --git a/src/google/protobuf/compiler/js/well_known_types_embed.cc b/src/google/protobuf/compiler/js/well_known_types_embed.cc new file mode 100644 index 00000000..e5ee5510 --- /dev/null +++ b/src/google/protobuf/compiler/js/well_known_types_embed.cc @@ -0,0 +1,225 @@ +#include <google/protobuf/compiler/js/well_known_types_embed.h> + +struct FileToc well_known_types_js[] = { + {"any.js", + "/* This code will be inserted into generated code for\n" + " * google/protobuf/any.proto. */\n" + "\n" + "/**\n" + " * Returns the type name contained in this instance, if any.\n" + " * @return {string|undefined}\n" + " */\n" + "proto.google.protobuf.Any.prototype.getTypeName = function() {\n" + " return this.getTypeUrl().split('/').pop();\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Packs the given message instance into this Any.\n" + " * @param {!Uint8Array} serialized The serialized data to pack.\n" + " * @param {string} name The type name of this message object.\n" + " * @param {string=} opt_typeUrlPrefix the type URL prefix.\n" + " */\n" + "proto.google.protobuf.Any.prototype.pack = function(serialized, name,\n" + " opt_typeUrlPrefix) " + "{\n" + " if (!opt_typeUrlPrefix) {\n" + " opt_typeUrlPrefix = 'type.googleapis.com/';\n" + " }\n" + "\n" + " if (opt_typeUrlPrefix.substr(-1) != '/') {\n" + " this.setTypeUrl(opt_typeUrlPrefix + '/' + name);\n" + " } else {\n" + " this.setTypeUrl(opt_typeUrlPrefix + name);\n" + " }\n" + "\n" + " this.setValue(serialized);\n" + "};\n" + "\n" + "\n" + "/**\n" + " * @template T\n" + " * Unpacks this Any into the given message object.\n" + " * @param {function(Uint8Array):T} deserialize Function that will " + "deserialize\n" + " * the binary data properly.\n" + " * @param {string} name The expected type name of this message object.\n" + " * @return {?T} If the name matched the expected name, returns the " + "deserialized\n" + " * object, otherwise returns null.\n" + " */\n" + "proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) " + "{\n" + " if (this.getTypeName() == name) {\n" + " return deserialize(this.getValue_asU8());\n" + " } else {\n" + " return null;\n" + " }\n" + "};\n"}, + {"timestamp.js", + "/* This code will be inserted into generated code for\n" + " * google/protobuf/timestamp.proto. */\n" + "\n" + "/**\n" + " * Returns a JavaScript 'Date' object corresponding to this Timestamp.\n" + " * @return {!Date}\n" + " */\n" + "proto.google.protobuf.Timestamp.prototype.toDate = function() {\n" + " var seconds = this.getSeconds();\n" + " var nanos = this.getNanos();\n" + "\n" + " return new Date((seconds * 1000) + (nanos / 1000000));\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Sets the value of this Timestamp object to be the given Date.\n" + " * @param {!Date} value The value to set.\n" + " */\n" + "proto.google.protobuf.Timestamp.prototype.fromDate = function(value) {\n" + " this.setSeconds(Math.floor(value.getTime() / 1000));\n" + " this.setNanos(value.getMilliseconds() * 1000000);\n" + "};\n"}, + {"struct.js", + "/* This code will be inserted into generated code for\n" + " * google/protobuf/struct.proto. */\n" + "\n" + "/**\n" + " * Typedef representing plain JavaScript values that can go into a\n" + " * Struct.\n" + " * @typedef {null|number|string|boolean|Array|Object}\n" + " */\n" + "proto.google.protobuf.JavaScriptValue;\n" + "\n" + "\n" + "/**\n" + " * Converts this Value object to a plain JavaScript value.\n" + " * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript\n" + " * value representing this Struct.\n" + " */\n" + "proto.google.protobuf.Value.prototype.toJavaScript = function() {\n" + " var kindCase = proto.google.protobuf.Value.KindCase;\n" + " switch (this.getKindCase()) {\n" + " case kindCase.NULL_VALUE:\n" + " return null;\n" + " case kindCase.NUMBER_VALUE:\n" + " return this.getNumberValue();\n" + " case kindCase.STRING_VALUE:\n" + " return this.getStringValue();\n" + " case kindCase.BOOL_VALUE:\n" + " return this.getBoolValue();\n" + " case kindCase.STRUCT_VALUE:\n" + " return this.getStructValue().toJavaScript();\n" + " case kindCase.LIST_VALUE:\n" + " return this.getListValue().toJavaScript();\n" + " default:\n" + " throw new Error('Unexpected struct type');\n" + " }\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Converts this JavaScript value to a new Value proto.\n" + " * @param {!proto.google.protobuf.JavaScriptValue} value The value to\n" + " * convert.\n" + " * @return {!proto.google.protobuf.Value} The newly constructed value.\n" + " */\n" + "proto.google.protobuf.Value.fromJavaScript = function(value) {\n" + " var ret = new proto.google.protobuf.Value();\n" + " switch (goog.typeOf(value)) {\n" + " case 'string':\n" + " ret.setStringValue(/** @type {string} */ (value));\n" + " break;\n" + " case 'number':\n" + " ret.setNumberValue(/** @type {number} */ (value));\n" + " break;\n" + " case 'boolean':\n" + " ret.setBoolValue(/** @type {boolean} */ (value));\n" + " break;\n" + " case 'null':\n" + " ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE);\n" + " break;\n" + " case 'array':\n" + " ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript(\n" + " /** @type{!Array} */ (value)));\n" + " break;\n" + " case 'object':\n" + " ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript(\n" + " /** @type{!Object} */ (value)));\n" + " break;\n" + " default:\n" + " throw new Error('Unexpected struct type.');\n" + " }\n" + "\n" + " return ret;\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Converts this ListValue object to a plain JavaScript array.\n" + " * @return {!Array} a plain JavaScript array representing this List.\n" + " */\n" + "proto.google.protobuf.ListValue.prototype.toJavaScript = function() {\n" + " var ret = [];\n" + " var values = this.getValuesList();\n" + "\n" + " for (var i = 0; i < values.length; i++) {\n" + " ret[i] = values[i].toJavaScript();\n" + " }\n" + "\n" + " return ret;\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Constructs a ListValue protobuf from this plain JavaScript array.\n" + " * @param {!Array} array a plain JavaScript array\n" + " * @return {proto.google.protobuf.ListValue} a new ListValue object\n" + " */\n" + "proto.google.protobuf.ListValue.fromJavaScript = function(array) {\n" + " var ret = new proto.google.protobuf.ListValue();\n" + "\n" + " for (var i = 0; i < array.length; i++) {\n" + " " + "ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i]));\n" + " }\n" + "\n" + " return ret;\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Converts this Struct object to a plain JavaScript object.\n" + " * @return {!Object<string, !proto.google.protobuf.JavaScriptValue>} a " + "plain\n" + " * JavaScript object representing this Struct.\n" + " */\n" + "proto.google.protobuf.Struct.prototype.toJavaScript = function() {\n" + " var ret = {};\n" + "\n" + " this.getFieldsMap().forEach(function(value, key) {\n" + " ret[key] = value.toJavaScript();\n" + " });\n" + "\n" + " return ret;\n" + "};\n" + "\n" + "\n" + "/**\n" + " * Constructs a Struct protobuf from this plain JavaScript object.\n" + " * @param {!Object} obj a plain JavaScript object\n" + " * @return {proto.google.protobuf.Struct} a new Struct object\n" + " */\n" + "proto.google.protobuf.Struct.fromJavaScript = function(obj) {\n" + " var ret = new proto.google.protobuf.Struct();\n" + " var map = ret.getFieldsMap();\n" + "\n" + " for (var property in obj) {\n" + " var val = obj[property];\n" + " map.set(property, proto.google.protobuf.Value.fromJavaScript(val));\n" + " }\n" + "\n" + " return ret;\n" + "};\n"}, + {NULL, NULL} // Terminate the list. +}; diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc index 4e237fc7..a58e1754 100644 --- a/src/google/protobuf/compiler/php/php_generator.cc +++ b/src/google/protobuf/compiler/php/php_generator.cc @@ -83,7 +83,7 @@ std::string PhpName(const std::string& full_name, bool is_descriptor); std::string DefaultForField(FieldDescriptor* field); std::string IntToString(int32 value); std::string FilenameToClassname(const string& filename); -std::string GeneratedMetadataFileName(const std::string& proto_file, +std::string GeneratedMetadataFileName(const FileDescriptor* file, bool is_descriptor); std::string LabelForField(FieldDescriptor* field); std::string TypeName(FieldDescriptor* field); @@ -94,6 +94,9 @@ void Indent(io::Printer* printer); void Outdent(io::Printer* printer); void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message, int is_descriptor); +void GenerateMessageConstructorDocComment(io::Printer* printer, + const Descriptor* message, + int is_descriptor); void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field, int is_descriptor, int function_type); void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_, @@ -105,31 +108,40 @@ void GenerateServiceDocComment(io::Printer* printer, void GenerateServiceMethodDocComment(io::Printer* printer, const MethodDescriptor* method); -std::string RenameEmpty(const std::string& name) { - if (name == "Empty") { - return "GPBEmpty"; - } else { - return name; + +std::string ReservedNamePrefix(const string& classname, + const FileDescriptor* file) { + bool is_reserved = false; + + string lower = classname; + transform(lower.begin(), lower.end(), lower.begin(), ::tolower); + + for (int i = 0; i < kReservedNamesSize; i++) { + if (lower == kReservedNames[i]) { + is_reserved = true; + break; + } } -} -std::string MessageFullName(const Descriptor* message, bool is_descriptor) { - if (is_descriptor) { - return StringReplace(message->full_name(), - "google.protobuf", - "google.protobuf.internal", false); - } else { - return message->full_name(); + if (is_reserved) { + if (file->package() == "google.protobuf") { + return "GPB"; + } else { + return "PB"; + } } + + return ""; } -std::string EnumFullName(const EnumDescriptor* envm, bool is_descriptor) { +template <typename DescriptorType> +std::string DescriptorFullName(const DescriptorType* desc, bool is_descriptor) { if (is_descriptor) { - return StringReplace(envm->full_name(), + return StringReplace(desc->full_name(), "google.protobuf", "google.protobuf.internal", false); } else { - return envm->full_name(); + return desc->full_name(); } } @@ -141,22 +153,55 @@ std::string ClassNamePrefix(const string& classname, return prefix; } - bool is_reserved = false; + return ReservedNamePrefix(classname, desc->file()); +} + +template <typename DescriptorType> +std::string GeneratedClassNameImpl(const DescriptorType* desc) { + std::string classname = ClassNamePrefix(desc->name(), desc) + desc->name(); + const Descriptor* containing = desc->containing_type(); + while (containing != NULL) { + classname = ClassNamePrefix(containing->name(), desc) + containing->name() + + '\\' + classname; + containing = containing->containing_type(); + } + return classname; +} + +std::string GeneratedClassNameImpl(const ServiceDescriptor* desc) { + std::string classname = desc->name(); + return ClassNamePrefix(classname, desc) + classname; +} + +std::string GeneratedClassName(const Descriptor* desc) { + return GeneratedClassNameImpl(desc); +} + +std::string GeneratedClassName(const EnumDescriptor* desc) { + return GeneratedClassNameImpl(desc); +} + +std::string GeneratedClassName(const ServiceDescriptor* desc) { + return GeneratedClassNameImpl(desc); +} +template <typename DescriptorType> +std::string LegacyGeneratedClassName(const DescriptorType* desc) { + std::string classname = desc->name(); + const Descriptor* containing = desc->containing_type(); + while (containing != NULL) { + classname = containing->name() + '_' + classname; + containing = containing->containing_type(); + } + return ClassNamePrefix(classname, desc) + classname; +} + +std::string ClassNamePrefix(const string& classname) { string lower = classname; transform(lower.begin(), lower.end(), lower.begin(), ::tolower); for (int i = 0; i < kReservedNamesSize; i++) { if (lower == kReservedNames[i]) { - is_reserved = true; - break; - } - } - - if (is_reserved) { - if (desc->file()->package() == "google.protobuf") { - return "GPB"; - } else { return "PB"; } } @@ -192,34 +237,39 @@ std::string ConstantNamePrefix(const string& classname) { } template <typename DescriptorType> -std::string NamespacedName(const string& classname, - const DescriptorType* desc, bool is_descriptor) { +std::string RootPhpNamespace(const DescriptorType* desc, bool is_descriptor) { if (desc->file()->options().has_php_namespace()) { const string& php_namespace = desc->file()->options().php_namespace(); if (php_namespace != "") { - return php_namespace + '\\' + classname; - } else { - return classname; + return php_namespace; } + return ""; } - if (desc->file()->package() == "") { - return classname; - } else { - return PhpName(desc->file()->package(), is_descriptor) + '\\' + - classname; + if (desc->file()->package() != "") { + return PhpName(desc->file()->package(), is_descriptor); } + return ""; } template <typename DescriptorType> std::string FullClassName(const DescriptorType* desc, bool is_descriptor) { - string classname = GeneratedClassName(desc); - return NamespacedName(classname, desc, is_descriptor); + string classname = GeneratedClassNameImpl(desc); + string php_namespace = RootPhpNamespace(desc, is_descriptor); + if (php_namespace != "") { + return php_namespace + "\\" + classname; + } + return classname; } -std::string FullClassName(const ServiceDescriptor* desc, bool is_descriptor) { - string classname = GeneratedClassName(desc); - return NamespacedName(classname, desc, is_descriptor); +template <typename DescriptorType> +std::string LegacyFullClassName(const DescriptorType* desc, bool is_descriptor) { + string classname = LegacyGeneratedClassName(desc); + string php_namespace = RootPhpNamespace(desc, is_descriptor); + if (php_namespace != "") { + return php_namespace + "\\" + classname; + } + return classname; } std::string PhpName(const std::string& full_name, bool is_descriptor) { @@ -227,20 +277,23 @@ std::string PhpName(const std::string& full_name, bool is_descriptor) { return kDescriptorPackageName; } + std::string segment; std::string result; bool cap_next_letter = true; for (int i = 0; i < full_name.size(); i++) { if ('a' <= full_name[i] && full_name[i] <= 'z' && cap_next_letter) { - result += full_name[i] + ('A' - 'a'); + segment += full_name[i] + ('A' - 'a'); cap_next_letter = false; } else if (full_name[i] == '.') { - result += '\\'; + result += ClassNamePrefix(segment) + segment + '\\'; + segment = ""; cap_next_letter = true; } else { - result += full_name[i]; + segment += full_name[i]; cap_next_letter = false; } } + result += ClassNamePrefix(segment) + segment; return result; } @@ -268,11 +321,13 @@ std::string DefaultForField(const FieldDescriptor* field) { } } -std::string GeneratedMetadataFileName(const std::string& proto_file, +std::string GeneratedMetadataFileName(const FileDescriptor* file, bool is_descriptor) { + const string& proto_file = file->name(); int start_index = 0; int first_index = proto_file.find_first_of("/", start_index); - std::string result = "GPBMetadata/"; + std::string result = ""; + std::string segment = ""; if (proto_file == kEmptyFile) { return kEmptyMetadataFile; @@ -290,24 +345,44 @@ std::string GeneratedMetadataFileName(const std::string& proto_file, file_no_suffix = proto_file.substr(0, lastindex); } - while (first_index != string::npos) { - result += UnderscoresToCamelCase( - file_no_suffix.substr(start_index, first_index - start_index), true); - result += "/"; - start_index = first_index + 1; - first_index = file_no_suffix.find_first_of("/", start_index); + if (file->options().has_php_metadata_namespace()) { + const string& php_metadata_namespace = + file->options().php_metadata_namespace(); + if (php_metadata_namespace != "" && php_metadata_namespace != "\\") { + result += php_metadata_namespace; + std::replace(result.begin(), result.end(), '\\', '/'); + if (result.at(result.size() - 1) != '/') { + result += "/"; + } + } + } else { + result += "GPBMetadata/"; + while (first_index != string::npos) { + segment = UnderscoresToCamelCase( + file_no_suffix.substr(start_index, first_index - start_index), true); + result += ReservedNamePrefix(segment, file) + segment + "/"; + start_index = first_index + 1; + first_index = file_no_suffix.find_first_of("/", start_index); + } } // Append file name. - result += RenameEmpty(UnderscoresToCamelCase( - file_no_suffix.substr(start_index, first_index - start_index), true)); + int file_name_start = file_no_suffix.find_last_of("/"); + if (file_name_start == string::npos) { + file_name_start = 0; + } else { + file_name_start += 1; + } + segment = UnderscoresToCamelCase( + file_no_suffix.substr(file_name_start, first_index - file_name_start), true); - return result += ".php"; + return result + ReservedNamePrefix(segment, file) + segment + ".php"; } -std::string GeneratedMessageFileName(const Descriptor* message, +template <typename DescriptorType> +std::string GeneratedClassFileName(const DescriptorType* desc, bool is_descriptor) { - std::string result = FullClassName(message, is_descriptor); + std::string result = FullClassName(desc, is_descriptor); for (int i = 0; i < result.size(); i++) { if (result[i] == '\\') { result[i] = '/'; @@ -316,9 +391,11 @@ std::string GeneratedMessageFileName(const Descriptor* message, return result + ".php"; } -std::string GeneratedEnumFileName(const EnumDescriptor* en, - bool is_descriptor) { - std::string result = FullClassName(en, is_descriptor); +template <typename DescriptorType> +std::string LegacyGeneratedClassFileName(const DescriptorType* desc, + bool is_descriptor) { + std::string result = LegacyFullClassName(desc, is_descriptor); + for (int i = 0; i < result.size(); i++) { if (result[i] == '\\') { result[i] = '/'; @@ -461,10 +538,10 @@ std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor) std::string EnumOrMessageSuffix( const FieldDescriptor* field, bool is_descriptor) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - return ", '" + MessageFullName(field->message_type(), is_descriptor) + "'"; + return ", '" + DescriptorFullName(field->message_type(), is_descriptor) + "'"; } if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { - return ", '" + EnumFullName(field->enum_type(), is_descriptor) + "'"; + return ", '" + DescriptorFullName(field->enum_type(), is_descriptor) + "'"; } return ""; } @@ -651,11 +728,11 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor, } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { printer->Print( "GPBUtil::checkMessage($var, \\^class_name^::class);\n", - "class_name", FullClassName(field->message_type(), is_descriptor)); + "class_name", LegacyFullClassName(field->message_type(), is_descriptor)); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer->Print( "GPBUtil::checkEnum($var, \\^class_name^::class);\n", - "class_name", FullClassName(field->enum_type(), is_descriptor)); + "class_name", LegacyFullClassName(field->enum_type(), is_descriptor)); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { printer->Print( "GPBUtil::checkString($var, ^utf8^);\n", @@ -711,7 +788,7 @@ void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) { printer->Print( "$pool->addEnum('^name^', " "\\Google\\Protobuf\\Internal\\^class_name^::class)\n", - "name", EnumFullName(en, true), + "name", DescriptorFullName(en, true), "class_name", en->name()); Indent(printer); @@ -743,13 +820,13 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message, if (message->options().map_entry()) { return; } - string class_name = name_prefix.empty()? - message->name() : name_prefix + "_" + message->name(); + string class_name = (name_prefix.empty() ? "" : name_prefix + "\\") + + ReservedNamePrefix(message->name(), message->file()) + message->name(); printer->Print( "$pool->addMessage('^message^', " "\\Google\\Protobuf\\Internal\\^class_name^::class)\n", - "message", MessageFullName(message, true), + "message", DescriptorFullName(message, true), "class_name", class_name); Indent(printer); @@ -851,7 +928,7 @@ void GenerateAddFileToPool(const FileDescriptor* file, bool is_descriptor, continue; } std::string dependency_filename = - GeneratedMetadataFileName(name, is_descriptor); + GeneratedMetadataFileName(file->dependency(i), is_descriptor); printer->Print( "\\^name^::initOnce();\n", "name", FilenameToClassname(dependency_filename)); @@ -945,7 +1022,7 @@ std::string FilenameToClassname(const string& filename) { void GenerateMetadataFile(const FileDescriptor* file, bool is_descriptor, GeneratorContext* generator_context) { - std::string filename = GeneratedMetadataFileName(file->name(), is_descriptor); + std::string filename = GeneratedMetadataFileName(file, is_descriptor); std::unique_ptr<io::ZeroCopyOutputStream> output( generator_context->Open(filename)); io::Printer printer(output.get(), '^'); @@ -955,12 +1032,12 @@ void GenerateMetadataFile(const FileDescriptor* file, std::string fullname = FilenameToClassname(filename); int lastindex = fullname.find_last_of("\\"); - printer.Print( - "namespace ^name^;\n\n", - "name", fullname.substr(0, lastindex)); - if (lastindex != string::npos) { printer.Print( + "namespace ^name^;\n\n", + "name", fullname.substr(0, lastindex)); + + printer.Print( "class ^name^\n" "{\n", "name", fullname.substr(lastindex + 1)); @@ -978,9 +1055,47 @@ void GenerateMetadataFile(const FileDescriptor* file, printer.Print("}\n\n"); } +template <typename DescriptorType> +void LegacyGenerateClassFile(const FileDescriptor* file, const DescriptorType* desc, + bool is_descriptor, + GeneratorContext* generator_context) { + + std::string filename = LegacyGeneratedClassFileName(desc, is_descriptor); + std::unique_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(filename)); + io::Printer printer(output.get(), '^'); + + GenerateHead(file, &printer); + + std::string php_namespace = RootPhpNamespace(desc, is_descriptor); + if (php_namespace != "") { + printer.Print( + "namespace ^name^;\n\n", + "name", php_namespace); + } + std::string newname = FullClassName(desc, is_descriptor); + printer.Print("if (false) {\n"); + Indent(&printer); + printer.Print("/**\n"); + printer.Print(" * This class is deprecated. Use ^new^ instead.\n", + "new", newname); + printer.Print(" * @deprecated\n"); + printer.Print(" */\n"); + printer.Print("class ^old^ {}\n", + "old", LegacyGeneratedClassName(desc)); + Outdent(&printer); + printer.Print("}\n"); + printer.Print("class_exists(^new^::class);\n", + "new", GeneratedClassNameImpl(desc)); + printer.Print("@trigger_error('^old^ is deprecated and will be removed in " + "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n", + "old", LegacyFullClassName(desc, is_descriptor), + "fullname", newname); +} + void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, bool is_descriptor, GeneratorContext* generator_context) { - std::string filename = GeneratedEnumFileName(en, is_descriptor); + std::string filename = GeneratedClassFileName(en, is_descriptor); std::unique_ptr<io::ZeroCopyOutputStream> output( generator_context->Open(filename)); io::Printer printer(output.get(), '^'); @@ -990,32 +1105,22 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, std::string fullname = FilenameToClassname(filename); int lastindex = fullname.find_last_of("\\"); - if (file->options().has_php_namespace()) { - const string& php_namespace = file->options().php_namespace(); - if (!php_namespace.empty()) { - printer.Print( - "namespace ^name^;\n\n", - "name", php_namespace); - } - } else if (!file->package().empty()) { + if (lastindex != string::npos) { printer.Print( "namespace ^name^;\n\n", "name", fullname.substr(0, lastindex)); } - GenerateEnumDocComment(&printer, en, is_descriptor); - if (lastindex != string::npos) { - printer.Print( - "class ^name^\n" - "{\n", - "name", fullname.substr(lastindex + 1)); - } else { - printer.Print( - "class ^name^\n" - "{\n", - "name", fullname); + fullname = fullname.substr(lastindex + 1); } + + GenerateEnumDocComment(&printer, en, is_descriptor); + + printer.Print( + "class ^name^\n" + "{\n", + "name", fullname); Indent(&printer); for (int i = 0; i < en->value_count(); i++) { @@ -1028,6 +1133,17 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, Outdent(&printer); printer.Print("}\n\n"); + + // write legacy file for backwards compatiblity with nested messages and enums + if (en->containing_type() != NULL) { + printer.Print( + "// Adding a class alias for backwards compatibility with the previous class name.\n"); + printer.Print( + "class_alias(^new^::class, \\^old^::class);\n\n", + "new", fullname, + "old", LegacyFullClassName(en, is_descriptor)); + LegacyGenerateClassFile(file, en, is_descriptor, generator_context); + } } void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, @@ -1039,7 +1155,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, return; } - std::string filename = GeneratedMessageFileName(message, is_descriptor); + std::string filename = GeneratedClassFileName(message, is_descriptor); std::unique_ptr<io::ZeroCopyOutputStream> output( generator_context->Open(filename)); io::Printer printer(output.get(), '^'); @@ -1049,14 +1165,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, std::string fullname = FilenameToClassname(filename); int lastindex = fullname.find_last_of("\\"); - if (file->options().has_php_namespace()) { - const string& php_namespace = file->options().php_namespace(); - if (!php_namespace.empty()) { - printer.Print( - "namespace ^name^;\n\n", - "name", php_namespace); - } - } else if (!file->package().empty()) { + if (lastindex != string::npos) { printer.Print( "namespace ^name^;\n\n", "name", fullname.substr(0, lastindex)); @@ -1066,16 +1175,13 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, GenerateMessageDocComment(&printer, message, is_descriptor); if (lastindex != string::npos) { - printer.Print( - "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n" - "{\n", - "name", fullname.substr(lastindex + 1)); - } else { - printer.Print( - "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n" - "{\n", - "name", fullname); + fullname = fullname.substr(lastindex + 1); } + + printer.Print( + "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n" + "{\n", + "name", fullname); Indent(&printer); // Field and oneof definitions. @@ -1089,16 +1195,17 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, } printer.Print("\n"); + GenerateMessageConstructorDocComment(&printer, message, is_descriptor); printer.Print( - "public function __construct() {\n"); + "public function __construct($data = NULL) {\n"); Indent(&printer); std::string metadata_filename = - GeneratedMetadataFileName(file->name(), is_descriptor); + GeneratedMetadataFileName(file, is_descriptor); std::string metadata_fullname = FilenameToClassname(metadata_filename); printer.Print( "\\^fullname^::initOnce();\n" - "parent::__construct();\n", + "parent::__construct($data);\n", "fullname", metadata_fullname); Outdent(&printer); @@ -1126,6 +1233,17 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, Outdent(&printer); printer.Print("}\n\n"); + // write legacy file for backwards compatiblity with nested messages and enums + if (message->containing_type() != NULL) { + printer.Print( + "// Adding a class alias for backwards compatibility with the previous class name.\n"); + printer.Print( + "class_alias(^new^::class, \\^old^::class);\n\n", + "new", fullname, + "old", LegacyFullClassName(message, is_descriptor)); + LegacyGenerateClassFile(file, message, is_descriptor, generator_context); + } + // Nested messages and enums. for (int i = 0; i < message->nested_type_count(); i++) { GenerateMessageFile(file, message->nested_type(i), is_descriptor, @@ -1150,14 +1268,9 @@ void GenerateServiceFile(const FileDescriptor* file, std::string fullname = FilenameToClassname(filename); int lastindex = fullname.find_last_of("\\"); - if (file->options().has_php_namespace()) { - const string& php_namespace = file->options().php_namespace(); - if (!php_namespace.empty()) { - printer.Print( - "namespace ^name^;\n\n", - "name", php_namespace); - } - } else if (!file->package().empty()) { + if (!file->options().php_namespace().empty() || + (!file->options().has_php_namespace() && !file->package().empty()) || + lastindex != string::npos) { printer.Print( "namespace ^name^;\n\n", "name", fullname.substr(0, lastindex)); @@ -1251,7 +1364,8 @@ static string EscapePhpdoc(const string& input) { } static void GenerateDocCommentBodyForLocation( - io::Printer* printer, const SourceLocation& location) { + io::Printer* printer, const SourceLocation& location, bool trailingNewline, + int indentCount) { string comments = location.leading_comments.empty() ? location.trailing_comments : location.leading_comments; if (!comments.empty()) { @@ -1272,14 +1386,16 @@ static void GenerateDocCommentBodyForLocation( // Most lines should start with a space. Watch out for lines that start // with a /, since putting that right after the leading asterisk will // close the comment. - if (!lines[i].empty() && lines[i][0] == '/') { + if (indentCount == 0 && !lines[i].empty() && lines[i][0] == '/') { printer->Print(" * ^line^\n", "line", lines[i]); } else { - printer->Print(" *^line^\n", "line", lines[i]); + std::string indent = std::string(indentCount, ' '); + printer->Print(" *^ind^^line^\n", "ind", indent, "line", lines[i]); } } - printer->Print( - " *\n"); + if (trailingNewline) { + printer->Print(" *\n"); + } } } @@ -1288,7 +1404,7 @@ static void GenerateDocCommentBody( io::Printer* printer, const DescriptorType* descriptor) { SourceLocation location; if (descriptor->GetSourceLocation(&location)) { - GenerateDocCommentBodyForLocation(printer, location); + GenerateDocCommentBodyForLocation(printer, location, true, 0); } } @@ -1310,10 +1426,41 @@ void GenerateMessageDocComment(io::Printer* printer, printer->Print( " * Generated from protobuf message <code>^messagename^</code>\n" " */\n", - "fullname", EscapePhpdoc(PhpName(message->full_name(), is_descriptor)), + "fullname", EscapePhpdoc(FullClassName(message, is_descriptor)), "messagename", EscapePhpdoc(message->full_name())); } +void GenerateMessageConstructorDocComment(io::Printer* printer, + const Descriptor* message, + int is_descriptor) { + // In theory we should have slightly different comments for setters, getters, + // etc., but in practice everyone already knows the difference between these + // so it's redundant information. + + // We start the comment with the main body based on the comments from the + // .proto file (if present). We then end with the field declaration, e.g.: + // optional string foo = 5; + // If the field is a group, the debug string might end with {. + printer->Print("/**\n"); + printer->Print(" * Constructor.\n"); + printer->Print(" *\n"); + printer->Print(" * @param array $data {\n"); + printer->Print(" * Optional. Data for populating the Message object.\n"); + printer->Print(" *\n"); + for (int i = 0; i < message->field_count(); i++) { + const FieldDescriptor* field = message->field(i); + printer->Print(" * @type ^php_type^ $^var^\n", + "php_type", PhpSetterTypeName(field, is_descriptor), + "var", field->name()); + SourceLocation location; + if (field->GetSourceLocation(&location)) { + GenerateDocCommentBodyForLocation(printer, location, false, 10); + } + } + printer->Print(" * }\n"); + printer->Print(" */\n"); +} + void GenerateServiceDocComment(io::Printer* printer, const ServiceDescriptor* service) { printer->Print("/**\n"); @@ -1355,9 +1502,9 @@ void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_, printer->Print("/**\n"); GenerateDocCommentBody(printer, enum_); printer->Print( - " * Protobuf enum <code>^fullname^</code>\n" + " * Protobuf type <code>^fullname^</code>\n" " */\n", - "fullname", EscapePhpdoc(PhpName(enum_->full_name(), is_descriptor))); + "fullname", EscapePhpdoc(enum_->full_name())); } void GenerateEnumValueDocComment(io::Printer* printer, @@ -1410,31 +1557,6 @@ bool Generator::Generate(const FileDescriptor* file, const string& parameter, return true; } -std::string GeneratedClassName(const Descriptor* desc) { - std::string classname = desc->name(); - const Descriptor* containing = desc->containing_type(); - while (containing != NULL) { - classname = containing->name() + '_' + classname; - containing = containing->containing_type(); - } - return ClassNamePrefix(classname, desc) + classname; -} - -std::string GeneratedClassName(const EnumDescriptor* desc) { - std::string classname = desc->name(); - const Descriptor* containing = desc->containing_type(); - while (containing != NULL) { - classname = containing->name() + '_' + classname; - containing = containing->containing_type(); - } - return ClassNamePrefix(classname, desc) + classname; -} - -std::string GeneratedClassName(const ServiceDescriptor* desc) { - std::string classname = desc->name(); - return ClassNamePrefix(classname, desc) + classname; -} - } // namespace php } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/php/php_generator.h b/src/google/protobuf/compiler/php/php_generator.h index 54a95ef5..b851d9b4 100644 --- a/src/google/protobuf/compiler/php/php_generator.h +++ b/src/google/protobuf/compiler/php/php_generator.h @@ -48,7 +48,6 @@ class LIBPROTOC_EXPORT Generator const string& parameter, GeneratorContext* generator_context, string* error) const; - }; // To skip reserved keywords in php, some generated classname are prefixed. diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index ef52def3..20aa82c7 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -183,14 +183,14 @@ static ::google::protobuf::Message const * const file_default_instances[] = { reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_CodeGeneratorResponse_default_instance_), }; -void protobuf_AssignDescriptors() { +static void protobuf_AssignDescriptors() { AddDescriptors(); AssignDescriptors( "google/protobuf/compiler/plugin.proto", schemas, file_default_instances, TableStruct::offsets, file_level_metadata, NULL, NULL); } -void protobuf_AssignDescriptorsOnce() { +static void protobuf_AssignDescriptorsOnce() { static ::google::protobuf::internal::once_flag once; ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors); } @@ -201,7 +201,7 @@ void protobuf_RegisterTypes(const ::std::string&) { ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 4); } -void AddDescriptorsImpl() { +static void AddDescriptorsImpl() { InitDefaults(); static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { "\n%google/protobuf/compiler/plugin.proto\022" diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index 02aa61d1..bd737c02 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -337,9 +337,20 @@ void GenerateEnumAssignment( } int GeneratePackageModules( - std::string package_name, + const FileDescriptor* file, google::protobuf::io::Printer* printer) { int levels = 0; + bool need_change_to_module; + std::string package_name; + + if (file->options().has_ruby_package()) { + package_name = file->options().ruby_package(); + need_change_to_module = false; + } else { + package_name = file->package(); + need_change_to_module = true; + } + while (!package_name.empty()) { size_t dot_index = package_name.find("."); string component; @@ -350,7 +361,9 @@ int GeneratePackageModules( component = package_name.substr(0, dot_index); package_name = package_name.substr(dot_index + 1); } - component = PackageToModule(component); + if (need_change_to_module) { + component = PackageToModule(component); + } printer->Print( "module $name$\n", "name", component); @@ -462,7 +475,7 @@ bool GenerateFile(const FileDescriptor* file, io::Printer* printer, printer->Print( "end\n\n"); - int levels = GeneratePackageModules(file->package(), printer); + int levels = GeneratePackageModules(file, printer); for (int i = 0; i < file->message_type_count(); i++) { GenerateMessageAssignment("", file->message_type(i), printer); } |