diff options
Diffstat (limited to 'src/google/protobuf/compiler/python/python_generator.cc')
-rw-r--r-- | src/google/protobuf/compiler/python/python_generator.cc | 382 |
1 files changed, 326 insertions, 56 deletions
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index fae83a3..15e05da 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ +// 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 @@ -28,6 +28,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +//#PY25 compatible generated code for GAE. +// Copyright 2007 Google Inc. All Rights Reserved. // Author: robinson@google.com (Will Robinson) // // This module outputs pure-Python protocol message classes that will @@ -45,6 +47,7 @@ #include <limits> #include <map> #include <utility> +#include <memory> #include <string> #include <vector> @@ -52,6 +55,7 @@ #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/stringprintf.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/io/zero_copy_stream.h> @@ -106,6 +110,12 @@ string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, const char kDescriptorKey[] = "DESCRIPTOR"; +// Does the file have top-level enums? +inline bool HasTopLevelEnums(const FileDescriptor *file) { + return file->enum_type_count() > 0; +} + + // Should we generate generic services for this file? inline bool HasGenericServices(const FileDescriptor *file) { return file->service_count() > 0 && @@ -120,13 +130,23 @@ void PrintTopBoilerplate( // TODO(robinson): Allow parameterization of Python version? printer->Print( "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "\n" - "from google.protobuf import descriptor\n" - "from google.protobuf import message\n" - "from google.protobuf import reflection\n"); + "# source: $filename$\n" + "\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))" //##PY25 + "\n", + "filename", file->name()); + if (HasTopLevelEnums(file)) { + printer->Print( + "from google.protobuf.internal import enum_type_wrapper\n"); + } + printer->Print( + "from google.protobuf import descriptor as _descriptor\n" + "from google.protobuf import message as _message\n" + "from google.protobuf import reflection as _reflection\n" + "from google.protobuf import symbol_database as " + "_symbol_database\n"); if (HasGenericServices(file)) { printer->Print( - "from google.protobuf import service\n" + "from google.protobuf import service as _service\n" "from google.protobuf import service_reflection\n"); } @@ -136,7 +156,8 @@ void PrintTopBoilerplate( "from google.protobuf import descriptor_pb2\n"); } printer->Print( - "# @@protoc_insertion_point(imports)\n"); + "# @@protoc_insertion_point(imports)\n\n" + "_sym_db = _symbol_database.Default()\n"); printer->Print("\n\n"); } @@ -202,12 +223,12 @@ string StringifyDefaultValue(const FieldDescriptor& field) { case FieldDescriptor::CPPTYPE_ENUM: return SimpleItoa(field.default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: - if (field.type() == FieldDescriptor::TYPE_STRING) { - return "unicode(\"" + CEscape(field.default_value_string()) + - "\", \"utf-8\")"; - } else { - return "\"" + CEscape(field.default_value_string()) + "\""; - } +//##!PY25 return "b\"" + CEscape(field.default_value_string()) + +//##!PY25 (field.type() != FieldDescriptor::TYPE_STRING ? "\"" : +//##!PY25 "\".decode('utf-8')"); + return "_b(\"" + CEscape(field.default_value_string()) + //##PY25 + (field.type() != FieldDescriptor::TYPE_STRING ? "\")" : //##PY25 + "\").decode('utf-8')"); //##PY25 case FieldDescriptor::CPPTYPE_MESSAGE: return "None"; } @@ -230,7 +251,7 @@ Generator::~Generator() { bool Generator::Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { // Completely serialize all Generate() calls on this instance. The @@ -252,26 +273,29 @@ bool Generator::Generate(const FileDescriptor* file, fdp.SerializeToString(&file_descriptor_serialized_); - scoped_ptr<io::ZeroCopyOutputStream> output(output_directory->Open(filename)); + scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); GOOGLE_CHECK(output.get()); io::Printer printer(output.get(), '$'); printer_ = &printer; PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto()); + PrintImports(); PrintFileDescriptor(); PrintTopLevelEnums(); PrintTopLevelExtensions(); PrintAllNestedEnumsInFile(); PrintMessageDescriptors(); - // We have to print the imports after the descriptors, so that mutually - // recursive protos in separate files can successfully reference each other. - PrintImports(); FixForeignFieldsInDescriptors(); PrintMessages(); // We have to fix up the extensions after the message classes themselves, // since they need to call static RegisterExtension() methods on these // classes. FixForeignFieldsInExtensions(); + // Descriptor options may have custom extensions. These custom options + // can only be successfully parsed after we register corresponding + // extensions. Therefore we parse all options again here to recognize + // custom options that may be unknown when we define the descriptors. + FixAllDescriptorOptions(); if (HasGenericServices(file)) { PrintServices(); } @@ -290,6 +314,13 @@ void Generator::PrintImports() const { module_name); } printer_->Print("\n"); + + // Print public imports. + for (int i = 0; i < file_->public_dependency_count(); ++i) { + string module_name = ModuleName(file_->public_dependency(i)->name()); + printer_->Print("from $module$ import *\n", "module", module_name); + } + printer_->Print("\n"); } // Prints the single file descriptor for this file. @@ -299,20 +330,31 @@ void Generator::PrintFileDescriptor() const { m["name"] = file_->name(); m["package"] = file_->package(); const char file_descriptor_template[] = - "$descriptor_name$ = descriptor.FileDescriptor(\n" + "$descriptor_name$ = _descriptor.FileDescriptor(\n" " name='$name$',\n" " package='$package$',\n"; printer_->Print(m, file_descriptor_template); printer_->Indent(); printer_->Print( - "serialized_pb='$value$'", +//##!PY25 "serialized_pb=b'$value$'\n", + "serialized_pb=_b('$value$')\n", //##PY25 "value", strings::CHexEscape(file_descriptor_serialized_)); + if (file_->dependency_count() != 0) { + printer_->Print(",\ndependencies=["); + for (int i = 0; i < file_->dependency_count(); ++i) { + string module_name = ModuleName(file_->dependency(i)->name()); + printer_->Print("$module_name$.DESCRIPTOR,", "module_name", module_name); + } + printer_->Print("]"); + } // TODO(falk): Also print options and fix the message_type, enum_type, // service and extension later in the generation. printer_->Outdent(); printer_->Print(")\n"); + printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name", + kDescriptorKey); printer_->Print("\n"); } @@ -323,6 +365,11 @@ void Generator::PrintTopLevelEnums() const { for (int i = 0; i < file_->enum_type_count(); ++i) { const EnumDescriptor& enum_descriptor = *file_->enum_type(i); PrintEnum(enum_descriptor); + printer_->Print("$name$ = " + "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)", + "name", enum_descriptor.name(), + "descriptor_name", + ModuleLevelDescriptorName(enum_descriptor)); printer_->Print("\n"); for (int j = 0; j < enum_descriptor.value_count(); ++j) { @@ -352,12 +399,14 @@ void Generator::PrintAllNestedEnumsInFile() const { // enum_descriptor. void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { map<string, string> m; - m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor); + string module_level_descriptor_name = + ModuleLevelDescriptorName(enum_descriptor); + m["descriptor_name"] = module_level_descriptor_name; m["name"] = enum_descriptor.name(); m["full_name"] = enum_descriptor.full_name(); m["file"] = kDescriptorKey; const char enum_descriptor_template[] = - "$descriptor_name$ = descriptor.EnumDescriptor(\n" + "$descriptor_name$ = _descriptor.EnumDescriptor(\n" " name='$name$',\n" " full_name='$full_name$',\n" " filename=None,\n" @@ -377,11 +426,13 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { printer_->Print("containing_type=None,\n"); printer_->Print("options=$options_value$,\n", "options_value", - OptionsValue("EnumOptions", CEscape(options_string))); + OptionsValue("EnumOptions", options_string)); EnumDescriptorProto edp; PrintSerializedPbInterval(enum_descriptor, edp); printer_->Outdent(); printer_->Print(")\n"); + printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", + module_level_descriptor_name); printer_->Print("\n"); } @@ -438,7 +489,7 @@ void Generator::PrintServiceDescriptor( descriptor.options().SerializeToString(&options_string); printer_->Print( - "$service_name$ = descriptor.ServiceDescriptor(\n", + "$service_name$ = _descriptor.ServiceDescriptor(\n", "service_name", service_name); printer_->Indent(); map<string, string> m; @@ -461,7 +512,6 @@ void Generator::PrintServiceDescriptor( printer_->Print("methods=[\n"); for (int i = 0; i < descriptor.method_count(); ++i) { const MethodDescriptor* method = descriptor.method(i); - string options_string; method->options().SerializeToString(&options_string); m.clear(); @@ -472,7 +522,7 @@ void Generator::PrintServiceDescriptor( m["input_type"] = ModuleLevelDescriptorName(*(method->input_type())); m["output_type"] = ModuleLevelDescriptorName(*(method->output_type())); m["options_value"] = OptionsValue("MethodOptions", options_string); - printer_->Print("descriptor.MethodDescriptor(\n"); + printer_->Print("_descriptor.MethodDescriptor(\n"); printer_->Indent(); printer_->Print( m, @@ -493,27 +543,36 @@ void Generator::PrintServiceDescriptor( void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { // Print the service. - printer_->Print("class $class_name$(service.Service):\n", + printer_->Print("$class_name$ = service_reflection.GeneratedServiceType(" + "'$class_name$', (_service.Service,), dict(\n", "class_name", descriptor.name()); printer_->Indent(); printer_->Print( - "__metaclass__ = service_reflection.GeneratedServiceType\n" - "$descriptor_key$ = $descriptor_name$\n", + "$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); + printer_->Print( + "__module__ = '$module_name$'\n", + "module_name", ModuleName(file_->name())); + printer_->Print("))\n\n"); printer_->Outdent(); } void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { // Print the service stub. - printer_->Print("class $class_name$_Stub($class_name$):\n", + printer_->Print("$class_name$_Stub = " + "service_reflection.GeneratedServiceStubType(" + "'$class_name$_Stub', ($class_name$,), dict(\n", "class_name", descriptor.name()); printer_->Indent(); printer_->Print( - "__metaclass__ = service_reflection.GeneratedServiceStubType\n" - "$descriptor_key$ = $descriptor_name$\n", + "$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); + printer_->Print( + "__module__ = '$module_name$'\n", + "module_name", ModuleName(file_->name())); + printer_->Print("))\n\n"); printer_->Outdent(); } @@ -525,7 +584,7 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { PrintNestedDescriptors(message_descriptor); printer_->Print("\n"); - printer_->Print("$descriptor_name$ = descriptor.Descriptor(\n", + printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n", "descriptor_name", ModuleLevelDescriptorName(message_descriptor)); printer_->Indent(); @@ -583,7 +642,22 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { "end", SimpleItoa(range->end)); } printer_->Print("],\n"); - + printer_->Print("oneofs=[\n"); + printer_->Indent(); + for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) { + const OneofDescriptor* desc = message_descriptor.oneof_decl(i); + map<string, string> m; + m["name"] = desc->name(); + m["full_name"] = desc->full_name(); + m["index"] = SimpleItoa(desc->index()); + printer_->Print( + m, + "_descriptor.OneofDescriptor(\n" + " name='$name$', full_name='$full_name$',\n" + " index=$index$, containing_type=None, fields=[]),\n"); + } + printer_->Outdent(); + printer_->Print("],\n"); // Serialization of proto DescriptorProto edp; PrintSerializedPbInterval(message_descriptor, edp); @@ -606,7 +680,12 @@ void Generator::PrintNestedDescriptors( // Prints all messages in |file|. void Generator::PrintMessages() const { for (int i = 0; i < file_->message_type_count(); ++i) { - PrintMessage(*file_->message_type(i)); + vector<string> to_register; + PrintMessage(*file_->message_type(i), "", &to_register); + for (int j = 0; j < to_register.size(); ++j) { + printer_->Print("_sym_db.RegisterMessage($name$)\n", "name", + to_register[j]); + } printer_->Print("\n"); } } @@ -618,33 +697,40 @@ void Generator::PrintMessages() const { // reflection.py will use to construct the meat of the class itself. // // Mutually recursive with PrintNestedMessages(). -void Generator::PrintMessage( - const Descriptor& message_descriptor) const { - printer_->Print("class $name$(message.Message):\n", "name", - message_descriptor.name()); +// Collect nested message names to_register for the symbol_database. +void Generator::PrintMessage(const Descriptor& message_descriptor, + const string& prefix, + vector<string>* to_register) const { + string qualified_name(prefix + message_descriptor.name()); + to_register->push_back(qualified_name); + printer_->Print( + "$name$ = _reflection.GeneratedProtocolMessageType('$name$', " + "(_message.Message,), dict(\n", + "name", message_descriptor.name()); printer_->Indent(); - printer_->Print("__metaclass__ = reflection.GeneratedProtocolMessageType\n"); - PrintNestedMessages(message_descriptor); + + PrintNestedMessages(message_descriptor, qualified_name + ".", to_register); map<string, string> m; m["descriptor_key"] = kDescriptorKey; m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); - printer_->Print(m, "$descriptor_key$ = $descriptor_name$\n"); - - printer_->Print( - "\n" - "# @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", message_descriptor.full_name()); - + printer_->Print(m, "$descriptor_key$ = $descriptor_name$,\n"); + printer_->Print("__module__ = '$module_name$'\n", + "module_name", ModuleName(file_->name())); + printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", message_descriptor.full_name()); + printer_->Print("))\n"); printer_->Outdent(); } // Prints all nested messages within |containing_descriptor|. // Mutually recursive with PrintMessage(). -void Generator::PrintNestedMessages( - const Descriptor& containing_descriptor) const { +void Generator::PrintNestedMessages(const Descriptor& containing_descriptor, + const string& prefix, + vector<string>* to_register) const { for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { printer_->Print("\n"); - PrintMessage(*containing_descriptor.nested_type(i)); + PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register); + printer_->Print(",\n"); } } @@ -672,6 +758,57 @@ void Generator::FixForeignFieldsInDescriptor( const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i); FixContainingTypeInDescriptor(enum_descriptor, &descriptor); } + for (int i = 0; i < descriptor.oneof_decl_count(); ++i) { + map<string, string> m; + const OneofDescriptor* oneof = descriptor.oneof_decl(i); + m["descriptor_name"] = ModuleLevelDescriptorName(descriptor); + m["oneof_name"] = oneof->name(); + for (int j = 0; j < oneof->field_count(); ++j) { + m["field_name"] = oneof->field(j)->name(); + printer_->Print( + m, + "$descriptor_name$.oneofs_by_name['$oneof_name$'].fields.append(\n" + " $descriptor_name$.fields_by_name['$field_name$'])\n"); + printer_->Print( + m, + "$descriptor_name$.fields_by_name['$field_name$'].containing_oneof = " + "$descriptor_name$.oneofs_by_name['$oneof_name$']\n"); + } + } +} + +void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { + map<string, string> m; + m["descriptor_name"] = kDescriptorKey; + m["message_name"] = descriptor.name(); + m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor); + const char file_descriptor_template[] = + "$descriptor_name$.message_types_by_name['$message_name$'] = " + "$message_descriptor_name$\n"; + printer_->Print(m, file_descriptor_template); +} + +void Generator::AddEnumToFileDescriptor( + const EnumDescriptor& descriptor) const { + map<string, string> m; + m["descriptor_name"] = kDescriptorKey; + m["enum_name"] = descriptor.name(); + m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor); + const char file_descriptor_template[] = + "$descriptor_name$.enum_types_by_name['$enum_name$'] = " + "$enum_descriptor_name$\n"; + printer_->Print(m, file_descriptor_template); +} + +void Generator::AddExtensionToFileDescriptor( + const FieldDescriptor& descriptor) const { + map<string, string> m; + m["descriptor_name"] = kDescriptorKey; + m["field_name"] = descriptor.name(); + const char file_descriptor_template[] = + "$descriptor_name$.extensions_by_name['$field_name$'] = " + "$field_name$\n"; + printer_->Print(m, file_descriptor_template); } // Sets any necessary message_type and enum_type attributes @@ -738,7 +875,7 @@ void Generator::FixContainingTypeInDescriptor( const string parent_name = ModuleLevelDescriptorName( *containing_descriptor); printer_->Print( - "$nested_name$.containing_type = $parent_name$;\n", + "$nested_name$.containing_type = $parent_name$\n", "nested_name", nested_name, "parent_name", parent_name); } @@ -752,6 +889,15 @@ void Generator::FixForeignFieldsInDescriptors() const { for (int i = 0; i < file_->message_type_count(); ++i) { FixForeignFieldsInDescriptor(*file_->message_type(i), NULL); } + for (int i = 0; i < file_->message_type_count(); ++i) { + AddMessageToFileDescriptor(*file_->message_type(i)); + } + for (int i = 0; i < file_->enum_type_count(); ++i) { + AddEnumToFileDescriptor(*file_->enum_type(i)); + } + for (int i = 0; i < file_->extension_count(); ++i) { + AddExtensionToFileDescriptor(*file_->extension(i)); + } printer_->Print("\n"); } @@ -767,6 +913,7 @@ void Generator::FixForeignFieldsInExtensions() const { for (int i = 0; i < file_->message_type_count(); ++i) { FixForeignFieldsInNestedExtensions(*file_->message_type(i)); } + printer_->Print("\n"); } void Generator::FixForeignFieldsInExtension( @@ -817,20 +964,24 @@ void Generator::PrintEnumValueDescriptor( m["options"] = OptionsValue("EnumValueOptions", options_string); printer_->Print( m, - "descriptor.EnumValueDescriptor(\n" + "_descriptor.EnumValueDescriptor(\n" " name='$name$', index=$index$, number=$number$,\n" " options=$options$,\n" " type=None)"); } +// Returns a Python expression that calls descriptor._ParseOptions using +// the given descriptor class name and serialized options protobuf string. string Generator::OptionsValue( const string& class_name, const string& serialized_options) const { if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { return "None"; } else { string full_class_name = "descriptor_pb2." + class_name; - return "descriptor._ParseOptions(" + full_class_name + "(), '" - + CEscape(serialized_options)+ "')"; +//##!PY25 return "_descriptor._ParseOptions(" + full_class_name + "(), b'" +//##!PY25 + CEscape(serialized_options)+ "')"; + return "_descriptor._ParseOptions(" + full_class_name + "(), _b('" //##PY25 + + CEscape(serialized_options)+ "'))"; //##PY25 } } @@ -855,7 +1006,7 @@ void Generator::PrintFieldDescriptor( // these fields in correctly after all referenced descriptors have been // defined and/or imported (see FixForeignFieldsInDescriptors()). const char field_descriptor_decl[] = - "descriptor.FieldDescriptor(\n" + "_descriptor.FieldDescriptor(\n" " name='$name$', full_name='$full_name$', index=$index$,\n" " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n" " has_default_value=$has_default_value$, default_value=$default_value$,\n" @@ -986,6 +1137,125 @@ void Generator::PrintSerializedPbInterval( "serialized_end", SimpleItoa(offset + sp.size())); } +namespace { +void PrintDescriptorOptionsFixingCode(const string& descriptor, + const string& options, + io::Printer* printer) { + // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase + // in proto2 python runtime but it couldn't be used here because appengine + // uses a snapshot version of the library in which the new method is not + // yet present. After appengine has synced their runtime library, the code + // below should be cleaned up to use _SetOptions(). + printer->Print( + "$descriptor$.has_options = True\n" + "$descriptor$._options = $options$\n", + "descriptor", descriptor, "options", options); +} +} // namespace + +// Prints expressions that set the options field of all descriptors. +void Generator::FixAllDescriptorOptions() const { + // Prints an expression that sets the file descriptor's options. + string file_options = OptionsValue( + "FileOptions", file_->options().SerializeAsString()); + if (file_options != "None") { + PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_); + } + // Prints expressions that set the options for all top level enums. + for (int i = 0; i < file_->enum_type_count(); ++i) { + const EnumDescriptor& enum_descriptor = *file_->enum_type(i); + FixOptionsForEnum(enum_descriptor); + } + // Prints expressions that set the options for all top level extensions. + for (int i = 0; i < file_->extension_count(); ++i) { + const FieldDescriptor& field = *file_->extension(i); + FixOptionsForField(field); + } + // Prints expressions that set the options for all messages, nested enums, + // nested extensions and message fields. + for (int i = 0; i < file_->message_type_count(); ++i) { + FixOptionsForMessage(*file_->message_type(i)); + } +} + +// Prints expressions that set the options for an enum descriptor and its +// value descriptors. +void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { + string descriptor_name = ModuleLevelDescriptorName(enum_descriptor); + string enum_options = OptionsValue( + "EnumOptions", enum_descriptor.options().SerializeAsString()); + if (enum_options != "None") { + PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_); + } + for (int i = 0; i < enum_descriptor.value_count(); ++i) { + const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i); + string value_options = OptionsValue( + "EnumValueOptions", value_descriptor.options().SerializeAsString()); + if (value_options != "None") { + PrintDescriptorOptionsFixingCode( + StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), + value_descriptor.name().c_str()), + value_options, printer_); + } + } +} + +// Prints expressions that set the options for field descriptors (including +// extensions). +void Generator::FixOptionsForField( + const FieldDescriptor& field) const { + string field_options = OptionsValue( + "FieldOptions", field.options().SerializeAsString()); + if (field_options != "None") { + string field_name; + if (field.is_extension()) { + if (field.extension_scope() == NULL) { + // Top level extensions. + field_name = field.name(); + } else { + field_name = FieldReferencingExpression( + field.extension_scope(), field, "extensions_by_name"); + } + } else { + field_name = FieldReferencingExpression( + field.containing_type(), field, "fields_by_name"); + } + PrintDescriptorOptionsFixingCode(field_name, field_options, printer_); + } +} + +// Prints expressions that set the options for a message and all its inner +// types (nested messages, nested enums, extensions, fields). +void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { + // Nested messages. + for (int i = 0; i < descriptor.nested_type_count(); ++i) { + FixOptionsForMessage(*descriptor.nested_type(i)); + } + // Enums. + for (int i = 0; i < descriptor.enum_type_count(); ++i) { + FixOptionsForEnum(*descriptor.enum_type(i)); + } + // Fields. + for (int i = 0; i < descriptor.field_count(); ++i) { + const FieldDescriptor& field = *descriptor.field(i); + FixOptionsForField(field); + } + // Extensions. + for (int i = 0; i < descriptor.extension_count(); ++i) { + const FieldDescriptor& field = *descriptor.extension(i); + FixOptionsForField(field); + } + // Message option for this message. + string message_options = OptionsValue( + "MessageOptions", descriptor.options().SerializeAsString()); + if (message_options != "None") { + string descriptor_name = ModuleLevelDescriptorName(descriptor); + PrintDescriptorOptionsFixingCode(descriptor_name, + message_options, + printer_); + } +} + } // namespace python } // namespace compiler } // namespace protobuf |